From bc32dc52b4e9971101f1516c85edf28aeea9a7bf Mon Sep 17 00:00:00 2001 From: Krisjanis Lejejs Date: Sun, 25 Dec 2022 19:28:25 +0200 Subject: [PATCH] Add additional operational status data --- README.md | 12 +++ ThermiaOnlineAPI/api/ThermiaAPI.py | 48 +-------- ThermiaOnlineAPI/const.py | 25 ----- ThermiaOnlineAPI/model/HeatPump.py | 164 +++++++++++++++++++++++++++-- 4 files changed, 167 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 10c5537..44187f7 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,18 @@ See [example.py](https://github.com/klejejs/python-thermia-online-api/blob/main/ | `operational_status` | Operational status of the Heat Pump | | `available_operational_statuses` | List of available operational statuses | | `available_operational_statuses_map` | Dictionary mapping operational status names to their values | +| `operational_status_auxiliary_heater_3kw` | Auxiliary heater status for 3kw (returns `None` if unavailable) | +| `operational_status_auxiliary_heater_6kw` | Auxiliary heater status for 6kw (returns `None` if unavailable) | +| `operational_status_auxiliary_heater_9kw` | Auxiliary heater status for 9kw (returns `None` if unavailable) | +| `operational_status_auxiliary_heater_12kw` | Auxiliary heater status for 12kw (returns `None` if unavailable) | +| `operational_status_auxiliary_heater_15kw` | Auxiliary heater status for 15kw (returns `None` if unavailable) | +| `operational_status_compressor_status` | Compressor status | +| `operational_status_brine_pump_status` | Brine pump status | +| `operational_status_radiator_pump_status` | Radiator pump status | +| `operational_status_cooling_status` | Cooling status | +| `operational_status_hot_water_status` | Hot water status | +| `operational_status_heating_status` | Heating status | +| `operational_status_integral` | Integral | | --- | --- | | Operational Times | | | `compressor_operational_time` | Compressor operational time in hours | diff --git a/ThermiaOnlineAPI/api/ThermiaAPI.py b/ThermiaOnlineAPI/api/ThermiaAPI.py index 48bdc12..95e5d6d 100644 --- a/ThermiaOnlineAPI/api/ThermiaAPI.py +++ b/ThermiaOnlineAPI/api/ThermiaAPI.py @@ -194,53 +194,7 @@ def get__group_temperatures(self, device_id: str): return self.__get_register_group(device_id, REG_GROUP_TEMPERATURES) def get__group_operational_status(self, device_id: str): - register_data = self.__get_register_group( - device_id, REG_GROUP_OPERATIONAL_STATUS - ) - - data = [ - d - for d in register_data - if d["registerName"] == "REG_OPERATIONAL_STATUS_PRIO1" - ] - - if len(data) != 1: - # Operation operational status not supported - return None - - data = data[0] - - current_operation_mode_value = int(data.get("registerValue")) - operation_modes_data = data.get("valueNames") - - if operation_modes_data is not None: - operation_modes_map = map( - lambda values: { - values.get("value"): values.get("name").split("REG_VALUE_STATUS_")[ - 1 - ], - }, - operation_modes_data, - ) - operation_modes_list = list(operation_modes_map) - operation_modes = ChainMap(*operation_modes_list) - - current_operation_mode = [ - name - for value, name in operation_modes.items() - if value == current_operation_mode_value - ] - if len(current_operation_mode) != 1: - # Something has gone wrong or operation mode not supported - return None - - return { - "current": current_operation_mode[0], - "available": operation_modes, - "isReadOnly": data["isReadOnly"], - } - - return None + return self.__get_register_group(device_id, REG_GROUP_OPERATIONAL_STATUS) def get__group_operational_time(self, device_id: str): return self.__get_register_group(device_id, REG_GROUP_OPERATIONAL_TIME) diff --git a/ThermiaOnlineAPI/const.py b/ThermiaOnlineAPI/const.py index a79c703..23809b6 100644 --- a/ThermiaOnlineAPI/const.py +++ b/ThermiaOnlineAPI/const.py @@ -65,23 +65,6 @@ REG_COOL_SENSOR_SUPPLY = "REG_COOL_SENSOR_SUPPLY" REG_ACTUAL_POOL_TEMP = "REG_ACTUAL_POOL_TEMP" -TEMPERATURE_REGISTERS = [ - REG_OUTDOOR_TEMPERATURE, - REG_INDOOR_TEMPERATURE, - REG_SUPPLY_LINE, - REG_HOT_WATER_TEMPERATURE, - REG_BRINE_OUT, - REG_BRINE_IN, - REG_DESIRED_INDOOR_TEMPERATURE, - REG_RETURN_LINE, - REG_DESIRED_SUPPLY_LINE, - REG_OPER_DATA_RETURN, - REG_DESIRED_SYS_SUPPLY_LINE_TEMP, - REG_COOL_SENSOR_TANK, - REG_COOL_SENSOR_SUPPLY, - REG_ACTUAL_POOL_TEMP, -] - ############################################################################### # Operational time registers ############################################################################### @@ -92,14 +75,6 @@ REG_OPER_TIME_COMPRESSOR = "REG_OPER_TIME_COMPRESSOR" REG_OPER_TIME_HOT_WATER = "REG_OPER_TIME_HOT_WATER" -OPERATIONAL_TIME_REGISTERS = [ - REG_OPER_TIME_IMM1, - REG_OPER_TIME_IMM2, - REG_OPER_TIME_IMM3, - REG_OPER_TIME_COMPRESSOR, - REG_OPER_TIME_HOT_WATER, -] - ############################################################################### # Other ############################################################################### diff --git a/ThermiaOnlineAPI/model/HeatPump.py b/ThermiaOnlineAPI/model/HeatPump.py index e4c71ee..2c2b620 100644 --- a/ThermiaOnlineAPI/model/HeatPump.py +++ b/ThermiaOnlineAPI/model/HeatPump.py @@ -1,3 +1,4 @@ +from collections import ChainMap from datetime import datetime import logging import sys @@ -6,7 +7,6 @@ from typing import TYPE_CHECKING, Dict from ThermiaOnlineAPI.const import ( - OPERATIONAL_TIME_REGISTERS, REG_BRINE_IN, REG_BRINE_OUT, REG_ACTUAL_POOL_TEMP, @@ -24,7 +24,6 @@ REG_OPER_TIME_IMM3, REG_RETURN_LINE, REG_SUPPLY_LINE, - TEMPERATURE_REGISTERS, DATETIME_FORMAT, ) @@ -281,6 +280,58 @@ def __set_historical_data_registers(self): self.__historical_data_registers_map = data_map + def __get_register_from_operational_status(self, register_name: str) -> dict | None: + data = [ + d + for d in self.__group_operational_status or [] + if d["registerName"] == register_name + ] + + if len(data) != 1: + return None + + return data[0] + + def __get_value_by_key_and_register_name_from_operational_status( + self, register_name: str, value_key: str + ): + data_from_register = self.__get_register_from_operational_status(register_name) + + if not data_from_register: + return None + + register_values_list = data_from_register.get("valueNames", []) + values_list: list = [d for d in register_values_list if d["name"] == value_key] + + if len(values_list) != 1: + return None + + value: dict = values_list[0] + + if value.get("visible"): + return value.get("value") + + return None + + def __get_all_operational_statuses_from_operational_status(self) -> ChainMap | None: + data = self.__get_register_from_operational_status( + "REG_OPERATIONAL_STATUS_PRIO1" + ) + + if not data: + return None + + register_values_list = data.get("valueNames", []) + + operation_modes_map = map( + lambda values: { + values.get("value"): values.get("name").split("REG_VALUE_STATUS_")[1], + }, + register_values_list, + ) + operation_modes_list = list(operation_modes_map) + return ChainMap(*operation_modes_list) + @property def name(self): return get_dict_value_safe(self.__info, "name") @@ -424,24 +475,117 @@ def cooling_supply_line_temperature(self): ) ########################################################################### - # Operational status data + # Operational status (REG_GROUP_OPERATIONAL_STATUS) ########################################################################### @property def operational_status(self): - return get_dict_value_safe(self.__group_operational_status, "current") + data = self.__get_register_from_operational_status( + "REG_OPERATIONAL_STATUS_PRIO1" + ) + + if not data: + return None + + current_register_value = get_dict_value_safe(data, "registerValue") + + data = self.__get_all_operational_statuses_from_operational_status() + + if not data: + return None + + current_operation_mode = [ + name for value, name in data.items() if value == current_register_value + ] + + if len(current_operation_mode) != 1: + return None + + return current_operation_mode[0] @property def available_operational_statuses(self): - return list( - get_dict_value_safe( - self.__group_operational_status, "available", {} - ).values() - ) + data = self.__get_all_operational_statuses_from_operational_status() + + if not data: + return None + + return data.values() @property def available_operational_statuses_map(self): - return get_dict_value_safe(self.__group_operational_status, "available", {}) + return self.__get_all_operational_statuses_from_operational_status() + + @property + def operational_status_auxiliary_heater_3kw(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_POWER_STATUS", "COMP_VALUE_STEP_3KW" + ) + + @property + def operational_status_auxiliary_heater_6kw(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_POWER_STATUS", "COMP_VALUE_STEP_6KW" + ) + + @property + def operational_status_auxiliary_heater_9kw(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_POWER_STATUS", "COMP_VALUE_STEP_9KW" + ) + + @property + def operational_status_auxiliary_heater_12kw(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_POWER_STATUS", "COMP_VALUE_STEP_12KW" + ) + + @property + def operational_status_auxiliary_heater_15kw(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_POWER_STATUS", "COMP_VALUE_STEP_15KW" + ) + + @property + def operational_status_compressor_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_COMPR" + ) + + @property + def operational_status_brine_pump_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_BRINEPUMP" + ) + + @property + def operational_status_radiator_pump_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_RADIATORPUMP" + ) + + @property + def operational_status_cooling_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_COOLING" + ) + + @property + def operational_status_hot_water_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_HOT_WATER" + ) + + @property + def operational_status_heating_status(self): + return self.__get_value_by_key_and_register_name_from_operational_status( + "COMP_STATUS", "COMP_VALUE_HEATING" + ) + + @property + def operational_status_integral(self): + data = self.__get_register_from_operational_status("REG_INTEGRAL_LSD") + return get_dict_value_safe(data, "registerValue") ########################################################################### # Operational time data