From 660e7fed57beb19d23f0ee5d9dfbfcd0dec25386 Mon Sep 17 00:00:00 2001 From: faanskit Date: Sat, 20 Jan 2024 15:14:33 +0100 Subject: [PATCH 1/4] Added support for RPI Data and CM10 Status --- pycheckwatt/__init__.py | 138 ++++++++++++++++++++++++++++++++++++++++ pyproject.toml | 2 +- setup.py | 2 +- 3 files changed, 140 insertions(+), 2 deletions(-) diff --git a/pycheckwatt/__init__.py b/pycheckwatt/__init__.py index 48b0230..ee31a6b 100644 --- a/pycheckwatt/__init__.py +++ b/pycheckwatt/__init__.py @@ -49,6 +49,8 @@ def __init__(self, username, password, application="pyCheckwatt") -> None: self.spot_prices = None self.energy_data = None self.header_identifier = application + self.rpi_data = None + self.meter_data = None async def __aenter__(self): """Asynchronous enter.""" @@ -679,6 +681,68 @@ async def get_energy_trading_company(self, input_id): except (ClientResponseError, ClientError) as error: return await self.handle_client_error(endpoint, headers, error) + async def get_rpi_data(self, rpi_serial=None): + """Fetch RPi Data from CheckWatt.""" + + try: + if rpi_serial is None: + rpi_serial = self.rpi_serial + + if rpi_serial is None: + _LOGGER.error("Invalid RpiSerial") + return False + + endpoint = f"/register/checkrpiv2?rpi={rpi_serial}" + # First fetch the revenue + async with self.session.get( + self.base_url + endpoint, + ) as response: + response.raise_for_status() + if response.status == 200: + self.rpi_data = await response.json() + return True + + _LOGGER.error( + "Obtaining data from URL %s failed with status code %d", + self.base_url + endpoint, + response.status, + ) + return False + + except (ClientResponseError, ClientError) as error: + return await self.handle_client_error(endpoint, "", error) + + async def get_meter_status(self, meter_id=None): + """Fetch RPi Data from CheckWatt.""" + + try: + if meter_id is None: + meter_id = self.meter_id + + if meter_id is None: + _LOGGER.error("Invalid MeterId") + return False + + endpoint = f"/asset/status?meterId={meter_id}" + # First fetch the revenue + async with self.session.get( + self.base_url + endpoint, + ) as response: + response.raise_for_status() + if response.status == 200: + self.meter_data = await response.json() + return True + + _LOGGER.error( + "Obtaining data from URL %s failed with status code %d", + self.base_url + endpoint, + response.status, + ) + return False + + except (ClientResponseError, ClientError) as error: + return await self.handle_client_error(endpoint, "", error) + @property def inverter_make_and_model(self): """Property for inverter make and model. Not used by HA integration..""" @@ -888,3 +952,77 @@ def battery_soc(self): _LOGGER.warning("Unable to retrieve Battery SoC") return None + + @property + def rpi_serial(self): + """Property for Rpi Serial.""" + if self.customer_details is not None: + meters = self.customer_details.get("Meter", []) + for meter in meters: + if "RpiSerial" in meter: + return meter["RpiSerial"].upper() + + _LOGGER.warning("Unable to find RPi Serial") + return None + + @property + def meter_id(self): + """Property for Meter Id.""" + if self.customer_details is not None: + meters = self.customer_details.get("Meter", []) + for meter in meters: + if "InstallationType" in meter and "Id" in meter: + if meter["InstallationType"] == "SoC": + return meter["Id"] + + _LOGGER.warning("Unable to find Meter Id") + return None + + @property + def meter_status(self): + """Property for Meter Status.""" + # First check if meter_data is available + if self.meter_data is not None: + if "Label" in self.meter_data: + return self.meter_data["Label"] + + # Then check if rpi_data is available + if self.rpi_data is not None: + meters = self.rpi_data.get("Meters", []) + for meter in meters: + if "InstallationType" in meter and "Status" in meter: + if meter["InstallationType"] == "SoC": + return meter["Status"] + + _LOGGER.warning("Unable to find Meter Status") + return None + + @property + def meter_status_date(self): + """Property for Meter Version.""" + if self.meter_data is not None: + if "Date" in self.meter_data: + return self.meter_data["Date"] + + _LOGGER.warning("Unable to find Meter Data") + return None + + @property + def meter_value_w(self): + """Property for Meter Version.""" + if self.meter_data is not None: + if "ValueW" in self.meter_data: + return self.meter_data["ValueW"] + + _LOGGER.warning("Unable to find Meter Data") + return None + + @property + def meter_version(self): + """Property for Meter Version.""" + if self.meter_data is not None: + if "Version" in self.meter_data: + return self.meter_data["Version"] + + _LOGGER.warning("Unable to find Meter Data") + return None diff --git a/pyproject.toml b/pyproject.toml index ffba5c3..1caef4a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "pycheckwatt" -version = "0.1.9" +version = "0.1.10" description = "Read data from CheckWatts EnergyInBalance WEB API" authors = ["Marcus Karlsson ", "Anders Yderborg ", "Daniel Nilsson "] license = "MIT License" diff --git a/setup.py b/setup.py index 08a5cf8..d9bd158 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ MIN_PY_VERSION = "3.10" PACKAGES = find_packages() -VERSION = "0.1.9" +VERSION = "0.1.10" setup( name="pycheckwatt", From beb3ecb249b9dae9f6589178e4098e7dcc3372dc Mon Sep 17 00:00:00 2001 From: faanskit Date: Sat, 20 Jan 2024 15:31:55 +0100 Subject: [PATCH 2/4] Added meter under test proerty --- pycheckwatt/__init__.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/pycheckwatt/__init__.py b/pycheckwatt/__init__.py index ee31a6b..1123b2b 100644 --- a/pycheckwatt/__init__.py +++ b/pycheckwatt/__init__.py @@ -1017,12 +1017,26 @@ def meter_value_w(self): _LOGGER.warning("Unable to find Meter Data") return None + @property + def meter_under_test(self): + """Property to check if meter is being tested.""" + if self.meter_data and "Version" in self.meter_data: + return self.meter_data["Version"].endswith(".83") + + _LOGGER.warning("Unable to find Meter Data") + return None + @property def meter_version(self): """Property for Meter Version.""" if self.meter_data is not None: if "Version" in self.meter_data: - return self.meter_data["Version"] + version_string = self.meter_data["Version"] + + # Use regular expression to extract Major.Minor.Patch + match = re.search(r"\d+\.\d+\.\d+", version_string) + if match: + return match.group() _LOGGER.warning("Unable to find Meter Data") return None From 4466c6bd4d865305dcafaf497b27514ea8f46e00 Mon Sep 17 00:00:00 2001 From: faanskit Date: Sat, 20 Jan 2024 15:37:58 +0100 Subject: [PATCH 3/4] Fixed comments --- pycheckwatt/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pycheckwatt/__init__.py b/pycheckwatt/__init__.py index 1123b2b..458e61b 100644 --- a/pycheckwatt/__init__.py +++ b/pycheckwatt/__init__.py @@ -999,7 +999,7 @@ def meter_status(self): @property def meter_status_date(self): - """Property for Meter Version.""" + """Property for Meter Status Date.""" if self.meter_data is not None: if "Date" in self.meter_data: return self.meter_data["Date"] @@ -1009,7 +1009,7 @@ def meter_status_date(self): @property def meter_value_w(self): - """Property for Meter Version.""" + """Property for Meter Value W.""" if self.meter_data is not None: if "ValueW" in self.meter_data: return self.meter_data["ValueW"] From c2d64e1417b4e849997ad0cf7588834cdcd8061f Mon Sep 17 00:00:00 2001 From: faanskit Date: Sun, 21 Jan 2024 07:06:55 +0100 Subject: [PATCH 4/4] Fixed review comments from @flopp999 --- pycheckwatt/__init__.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/pycheckwatt/__init__.py b/pycheckwatt/__init__.py index 458e61b..06e22a6 100644 --- a/pycheckwatt/__init__.py +++ b/pycheckwatt/__init__.py @@ -956,6 +956,12 @@ def battery_soc(self): @property def rpi_serial(self): """Property for Rpi Serial.""" + if self.rpi_data is not None: + meters = self.rpi_data.get("Meters", []) + for meter in meters: + if "RPi" in meter: + return meter["RPi"].upper() + if self.customer_details is not None: meters = self.customer_details.get("Meter", []) for meter in meters: @@ -968,6 +974,12 @@ def rpi_serial(self): @property def meter_id(self): """Property for Meter Id.""" + if self.rpi_data is not None: + meters = self.rpi_data.get("Meters", []) + for meter in meters: + if "Id" in meter: + return meter["Id"] + if self.customer_details is not None: meters = self.customer_details.get("Meter", []) for meter in meters: @@ -1004,7 +1016,7 @@ def meter_status_date(self): if "Date" in self.meter_data: return self.meter_data["Date"] - _LOGGER.warning("Unable to find Meter Data") + _LOGGER.warning("Unable to find Meter Data for Status Date") return None @property @@ -1014,7 +1026,7 @@ def meter_value_w(self): if "ValueW" in self.meter_data: return self.meter_data["ValueW"] - _LOGGER.warning("Unable to find Meter Data") + _LOGGER.warning("Unable to find Meter Data for Value W") return None @property @@ -1023,7 +1035,7 @@ def meter_under_test(self): if self.meter_data and "Version" in self.meter_data: return self.meter_data["Version"].endswith(".83") - _LOGGER.warning("Unable to find Meter Data") + _LOGGER.warning("Unable to find Meter Data for Meter Under Test") return None @property @@ -1038,5 +1050,5 @@ def meter_version(self): if match: return match.group() - _LOGGER.warning("Unable to find Meter Data") + _LOGGER.warning("Unable to find Meter Data for Meter Version") return None