pyscript icon indicating copy to clipboard operation
pyscript copied to clipboard

Is it possible to access historical data through pyscript?

Open bob-tm opened this issue 3 years ago • 4 comments

Is it possible to access historical data through pyscript?

I would like to do some statistics on HA sensor values. How I can query previous values for 60 minutes?

bob-tm avatar Nov 26 '22 22:11 bob-tm

I create a ready to use solution We need to use native python code, so

  1. create new folder \config\pyscript\python
  2. create \pyscript\python\my_history.py and put this code
# Access Historical Data using Pyscript
# (c) Oleksiy Babenko
# 
class GetHistory:
	hass            = False
	entities        = []
	start_time_utc  = False
	end_time_utc    = False
	sgfcnt_only     = False
	result          = False
	
	
	def Execute(self):
		from homeassistant.components.recorder.history import get_significant_states
		
		self.result = get_significant_states(
			hass       = self.hass, 
			start_time = self.start_time_utc,
			end_time   = self.end_time_utc,
			entity_ids = self.entities, 
			filters    = None,
			include_start_time_state	= True, 
			significant_changes_only	= self.sgfcnt_only,
			minimal_response 			= True,
			no_attributes    			= True,
			compressed_state_format 	= True)
		
	async def GetData(self):
		from homeassistant.components.recorder import get_instance
		await get_instance(self.hass).async_add_executor_job(self.Execute)
		return self.result
		
	def __init__(self, hass, entities, start_time, end_time, significant_changes_only):
		from datetime import datetime,timezone
		
		self.hass            = hass
		self.entities        = entities
		self.start_time_utc  = start_time.astimezone(timezone.utc)
		self.end_time_utc    = end_time.astimezone(timezone.utc)		
		self.sgfcnt_only     = significant_changes_only
  1. Test code. Reload code is need for dev only.
@state_trigger("input_boolean.test=='on'")
def TestHistory():		
	import sys

	if "/config/pyscript/python" not in sys.path:
		sys.path.append("/config/pyscript/python")
	
	import my_history
	import imp
	imp.reload(my_history)
	
	from datetime import datetime

	
	start_time = datetime.fromisoformat('2022-12-04T16:00:00')
	end_time   = datetime.fromisoformat('2022-12-04T17:00:00')
	
	H = my_history.GetHistory(hass, ['sensor.lumi_lumi_weather_d55f5f07_temperature'], start_time, end_time, False)
	D = H.GetData()
	if D:
		log.info(D)
		
		x = datetime.fromtimestamp(D['sensor.lumi_lumi_weather_d55f5f07_temperature'][0]['lu'])
		
		log.info(x)


you can add similar code as part of Pyscript or as Example of usage

bob-tm avatar Dec 04 '22 16:12 bob-tm

@bob-tm Thanks for sharing, this is my approach which is very similar to yours :-)

from typing import Literal
from datetime import datetime, timezone

from homeassistant.components.recorder import get_instance
from homeassistant.components.recorder.statistics import statistics_during_period

async def _get_history(
    start_time: datetime,
    end_time: datetime | None,
    statistic_ids: list[str] | None,
    period: Literal["5minute", "day", "hour", "week", "month"],
    types: set[Literal["last_reset", "max", "mean", "min", "state", "sum"]]):

    start_time = start_time.astimezone(timezone.utc)
    end_time = end_time.astimezone(timezone.utc)

    return(await get_instance(hass).async_add_executor_job(statistics_during_period, hass, start_time, end_time, statistic_ids, period, None, types))

@state_trigger("sensor.nygardsvegen_6_forbruk")
def energy_get_data(var_name=None, value=None):
    start_time = datetime.today().replace(day=1)
    end_time = datetime.today()
 
    history = _get_history(start_time, end_time, [var_name], "hour", "state")

    for hour in history.get(var_name):
        log.debug(hour)

jkaberg avatar Dec 12 '22 08:12 jkaberg

@bob-tm could you please update or close the issue? Thank you

ALERTua avatar Sep 21 '23 10:09 ALERTua