From 12c194d991dba69d327644c2da92d5b16a6b7183 Mon Sep 17 00:00:00 2001 From: Christopher Kochan <5183896+crkochan@users.noreply.github.com> Date: Sun, 15 Aug 2021 08:49:08 -0700 Subject: [PATCH] Expose more SenseableBase properties. (#47) * Refactor get_trend(). In order to expose additional properties, refactored get_trend() to required more than two keys from self._trend_data. * 'key' is now a keyword argument get_trend() with a default of "consumption", no longer is set as a boolean inside the function. * Perform type check on data references by key, ensure type is dict (for consumption/production), float (for new to/from_grid and net_production properties), or int (for production_pct). * Updated and expanded base properties. In order to expose additional information to be used with the new Home Assistant Energy dashboard, the following changes were made. * Converted existing True/False paramters on self.get_trend() calls to explicit key names. * Added new properties exposing existing information already in self._trend_data for daily and above. - production_pct - net_production - from_grid - to_grid * Also chomped some whitespace, because why not. * Update setup.py * Add solar_powered property. Reports as a percentage value in trend data. * Remove uncessary roll ups in get_trend. Aggregate values are already present in self._trend_data. Use of roll ups here seem to be causing the numbers to skew high. Removing it makes them match the Sense app. * Set version. * Remove default from key param. * Fix zero number for usage counter. Recent refactor of get_trend() results in instances of zero for the scale usage sensors in Home Assistant. Commit pulls data for concumption from Sense when Home Assistant requests usage. * 0.9.1 release --- sense_energy/__init__.py | 2 +- sense_energy/sense_api.py | 132 ++++++++++++++++++++++++++++++-------- setup.py | 4 +- 3 files changed, 109 insertions(+), 29 deletions(-) diff --git a/sense_energy/__init__.py b/sense_energy/__init__.py index 175d64c..bed8278 100644 --- a/sense_energy/__init__.py +++ b/sense_energy/__init__.py @@ -8,4 +8,4 @@ from .plug_instance import PlugInstance from .sense_link import SenseLink -__version__ = "0.9.0" +__version__ = "0.9.1" diff --git a/sense_energy/sense_api.py b/sense_energy/sense_api.py index 071214c..8ca9d9e 100644 --- a/sense_energy/sense_api.py +++ b/sense_energy/sense_api.py @@ -25,10 +25,10 @@ def __init__(self, username=None, password=None, self.wss_timeout = wss_timeout self.rate_limit = RATE_LIMIT self.last_realtime_call = 0 - + self._realtime = {} self._devices = [] - self._trend_data = {} + self._trend_data = {} for scale in valid_scales: self._trend_data[scale] = {} if username and password: @@ -42,19 +42,18 @@ def set_auth_data(self, data): # create the auth header self.headers = {'Authorization': 'bearer {}'.format( self.sense_access_token)} - @property def devices(self): """Return devices.""" return self._devices - + def set_realtime(self, data): self._realtime = data self.last_realtime_call = time() - + def get_realtime(self): - return self._realtime + return self._realtime @property def active_power(self): @@ -67,53 +66,134 @@ def active_solar_power(self): @property def active_voltage(self): return self._realtime.get('voltage', []) - + @property def active_frequency(self): return self._realtime.get('hz', 0) - + @property def daily_usage(self): - return self.get_trend('DAY', False) + return self.get_trend('DAY', 'consumption') @property def daily_production(self): - return self.get_trend('DAY', True) - + return self.get_trend('DAY', 'production') + + @property + def daily_production_pct(self): + return self.get_trend('DAY', 'production_pct') + + @property + def daily_net_production(self): + return self.get_trend('DAY', 'net_production') + + @property + def daily_from_grid(self): + return self.get_trend('DAY', 'from_grid') + + @property + def daily_to_grid(self): + return self.get_trend('DAY', 'to_grid') + + @property + def daily_solar_powered(self): + return self.get_trend('DAY', 'solar_powered') + @property def weekly_usage(self): - return self.get_trend('WEEK', False) + return self.get_trend('WEEK', 'consumption') @property def weekly_production(self): - return self.get_trend('WEEK', True) - + return self.get_trend('WEEK', 'production') + + @property + def weekly_production_pct(self): + return self.get_trend('WEEK', 'production_pct') + + @property + def weekly_net_production(self): + return self.get_trend('WEEK', 'net_production') + + @property + def weekly_from_grid(self): + return self.get_trend('WEEK', 'from_grid') + + @property + def weekly_to_grid(self): + return self.get_trend('WEEK', 'to_grid') + + @property + def weekly_solar_powered(self): + return self.get_trend('WEEK', 'solar_powered') + @property def monthly_usage(self): - return self.get_trend('MONTH', False) + return self.get_trend('MONTH', 'consumption') @property def monthly_production(self): - return self.get_trend('MONTH', True) - + return self.get_trend('MONTH', 'production') + + @property + def monthly_production_pct(self): + return self.get_trend('MONTH', 'production_pct') + + @property + def monthly_net_production(self): + return self.get_trend('MONTH', 'net_production') + + @property + def monthly_from_grid(self): + return self.get_trend('MONTH', 'from_grid') + + @property + def monthly_to_grid(self): + return self.get_trend('MONTH', 'to_grid') + + @property + def monthly_solar_powered(self): + return self.get_trend('MONTH', 'solar_powered') + @property def yearly_usage(self): - return self.get_trend('YEAR', False) + return self.get_trend('YEAR', 'consumption') @property def yearly_production(self): - return self.get_trend('YEAR', True) + return self.get_trend('YEAR', 'production') + + @property + def yearly_production_pct(self): + return self.get_trend('YEAR', 'production_pct') + + @property + def yearly_net_production(self): + return self.get_trend('YEAR', 'net_production') + + @property + def yearly_from_grid(self): + return self.get_trend('YEAR', 'from_grid') + + @property + def yearly_to_grid(self): + return self.get_trend('YEAR', 'to_grid') + + @property + def yearly_solar_powered(self): + return self.get_trend('YEAR', 'solar_powered') @property def active_devices(self): return [d['name'] for d in self._realtime.get('devices', {})] - def get_trend(self, scale, is_production): - key = "production" if is_production else "consumption" + def get_trend(self, scale, key): + key = 'consumption' if key == 'usage' else key if key not in self._trend_data[scale]: return 0 - total = self._trend_data[scale][key].get('total', 0) - if scale == 'WEEK' or scale == 'MONTH': - return total + self.get_trend('DAY', is_production) - if scale == 'YEAR': - return total + self.get_trend('MONTH', is_production) + # Perform a check for a valid type + if not isinstance(self._trend_data[scale][key], (dict, float, int)): return 0 + if isinstance(self._trend_data[scale][key], dict): + total = self._trend_data[scale][key].get('total', 0) + else: + total = self._trend_data[scale][key] return total diff --git a/setup.py b/setup.py index 6172cd1..6c8ec22 100644 --- a/setup.py +++ b/setup.py @@ -12,14 +12,14 @@ 'websockets;python_version>="3.5"', 'aiohttp;python_version>="3.5"', ], - version = '0.9.0', + version = '0.9.1', description = 'API for the Sense Energy Monitor', long_description=long_description, long_description_content_type="text/markdown", author = 'scottbonline', author_email = 'scottbonline@gmail.com', url = 'https://github.com/scottbonline/sense', - download_url = 'https://github.com/scottbonline/sense/archive/0.9.0.tar.gz', + download_url = 'https://github.com/scottbonline/sense/archive/0.9.1.tar.gz', keywords = ['sense', 'energy', 'api', 'pytest'], classifiers = [ 'Programming Language :: Python :: 2',