Skip to content

Commit

Permalink
Merge pull request #12 from klejejs/feature/add-hot-water-boost-switch
Browse files Browse the repository at this point in the history
Add hot water boost switch
  • Loading branch information
klejejs authored Dec 27, 2022
2 parents 6a69a71 + 18cf57c commit 3ded7d4
Show file tree
Hide file tree
Showing 5 changed files with 155 additions and 49 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,10 +89,11 @@ To execute the example file, first run `pip install -r requirements.txt` to inst
| `operation_mode` | Current operation mode of the Heat Pump |
| `available_operation_modes` | List of available operation modes for the Heat Pump |
| `available_operation_mode_map` | Dictionary mapping operation mode names to their values |
| `is_operation_mode_read_only` | Boolean value indicating if the Heat Pump operation mode is read-only |
| --- | --- |
| Hot Water data | |
| `is_operation_mode_read_only` | Boolean value indicating if the Heat Pump operation mode is read-only |
| `is_hot_water_switch_available` | Boolean value indicating if the Heat Pump has a hot water switch |
| `hot_water_switch_state` | Int value indicating the Heat Pump hot water switch state (0 or 1) or None if not available |
| `hot_water_boost_switch_state` | Int value indicating the Heat Pump hot water boost switch state (0 or 1) or None if not available |
| --- | --- |
| Historical data | |
| `historical_data_registers` | List of available registers to use for historical data fetching |
Expand All @@ -111,6 +112,7 @@ To execute the example file, first run `pip install -r requirements.txt` to inst
| `set_temperature()` | Set the target temperature for the Heat Pump |
| `set_operation_mode()` | Set the operation mode for the Heat Pump |
| `set_hot_water_switch_state()` | Set the hot water switch state to 0 (off) or 1 (on) for the Heat Pump |
| `set_hot_water_boost_switch_state()` | Set the hot water boost switch state to 0 (off) or 1 (on) for the Heat Pump |
| --- | --- |
| Fetch historical data | |
| `get_historical_data_for_register()` | Fetch historical data by using register name from `historical_data_registers` together with start_time and end_time of the data in Python datatime format. Returns list of dictionaries which contains data in format `{ "time": datetime, "value": int }` |
Expand Down
93 changes: 72 additions & 21 deletions ThermiaOnlineAPI/api/ThermiaAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
REG_GROUP_OPERATIONAL_STATUS,
REG_GROUP_OPERATIONAL_TIME,
REG_GROUP_TEMPERATURES,
REG_HOT_WATER_STATUS,
REG__HOT_WATER_BOOST,
REG_OPERATIONMODE,
THERMIA_API_CONFIG_URLS_BY_API_TYPE,
THERMIA_AZURE_AUTH_URL,
THERMIA_AZURE_AUTH_CLIENT_ID_AND_SCOPE,
Expand Down Expand Up @@ -202,7 +205,7 @@ def get_group_operational_operation(self, device: ThermiaHeatPump):
device.id, REG_GROUP_OPERATIONAL_OPERATION
)

data = [d for d in register_data if d["registerName"] == "REG_OPERATIONMODE"]
data = [d for d in register_data if d["registerName"] == REG_OPERATIONMODE]

if len(data) != 1:
# Operation mode not supported
Expand Down Expand Up @@ -244,26 +247,66 @@ def get_group_operational_operation(self, device: ThermiaHeatPump):

return None

def get_group_hot_water(self, device: ThermiaHeatPump):
register_data = self.__get_register_group(device.id, REG_GROUP_HOT_WATER)
def __get_switch_register_index_and_value_from_group_by_register_name(
self, register_group: list, register_name: str
):
default_return_object = {
"registerIndex": None,
"registerValue": None,
}

data = [d for d in register_data if d["registerName"] == "REG_HOT_WATER_STATUS"]
switch_data_list = [
d for d in register_group if d["registerName"] == register_name
]

if len(data) == 0:
# Hot water switch not supported
return None
if len(switch_data_list) != 1:
# Switch not supported
return default_return_object

data = data[0]
switch_data: dict = switch_data_list[0]

device.set_register_index_hot_water_switch(data["registerIndex"])
register_value = switch_data.get("registerValue")

current_switch_state = int(data.get("registerValue"))
switch_states_data = data.get("valueNames")
if register_value is None:
return default_return_object

if switch_states_data is not None and len(switch_states_data) == 2:
return current_switch_state
# Validate that register is a switch
switch_states_data = switch_data.get("valueNames")

return None
if switch_states_data is None or len(switch_states_data) != 2:
return default_return_object

return {
"registerIndex": switch_data["registerIndex"],
"registerValue": int(register_value),
}

def get_group_hot_water(self, device: ThermiaHeatPump) -> dict[str, int | None]:
register_data: list = self.__get_register_group(device.id, REG_GROUP_HOT_WATER)

hot_water_switch_data = (
self.__get_switch_register_index_and_value_from_group_by_register_name(
register_data, REG_HOT_WATER_STATUS
)
)
hot_water_boost_switch_data = (
self.__get_switch_register_index_and_value_from_group_by_register_name(
register_data, REG__HOT_WATER_BOOST
)
)

device.set_register_index_hot_water_switch(
hot_water_switch_data["registerIndex"]
)

device.set_register_index_hot_water_boost_switch(
hot_water_boost_switch_data["registerIndex"]
)

return {
"hot_water_switch": hot_water_switch_data["registerValue"],
"hot_water_boost_switch": hot_water_boost_switch_data["registerValue"],
}

def set_temperature(self, device: ThermiaHeatPump, temperature):
device_temperature_register_index = device.get_register_indexes()["temperature"]
Expand Down Expand Up @@ -312,18 +355,26 @@ def set_operation_mode(self, device: ThermiaHeatPump, mode):
def set_hot_water_switch_state(
self, device: ThermiaHeatPump, state: int
): # 0 - off, 1 - on
device_hot_water_switch_state_register_index = device.get_register_indexes()[
"hot_water_switch"
]
if device_hot_water_switch_state_register_index is None:
register_index = device.get_register_indexes()["hot_water_switch"]
if register_index is None:
_LOGGER.error(
"Error setting device's hot water switch state. No hot water switch register index."
)
return

self.__set_register_value(
device, device_hot_water_switch_state_register_index, state
)
self.__set_register_value(device, register_index, state)

def set_hot_water_boost_switch_state(
self, device: ThermiaHeatPump, state: int
): # 0 - off, 1 - on
register_index = device.get_register_indexes()["hot_water_boost_switch"]
if register_index is None:
_LOGGER.error(
"Error setting device's hot water boost switch state. No hot water boost switch register index."
)
return

self.__set_register_value(device, register_index, state)

def get_register_group_json(self, device_id: str, register_group: str) -> list:
return self.__get_register_group(device_id, register_group)
Expand Down
20 changes: 20 additions & 0 deletions ThermiaOnlineAPI/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,26 @@
REG_COOL_SENSOR_SUPPLY = "REG_COOL_SENSOR_SUPPLY"
REG_ACTUAL_POOL_TEMP = "REG_ACTUAL_POOL_TEMP"

###############################################################################
# Operational operation registers
###############################################################################

REG_OPERATIONMODE = "REG_OPERATIONMODE"

###############################################################################
# Operational status registers
###############################################################################

REG_OPERATIONAL_STATUS_PRIO1 = "REG_OPERATIONAL_STATUS_PRIO1"
REG_INTEGRAL_LSD = "REG_INTEGRAL_LSD"

###############################################################################
# Hot water registers
###############################################################################

REG_HOT_WATER_STATUS = "REG_HOT_WATER_STATUS"
REG__HOT_WATER_BOOST = "REG__HOT_WATER_BOOST"

###############################################################################
# Operational time registers
###############################################################################
Expand Down
63 changes: 44 additions & 19 deletions ThermiaOnlineAPI/model/HeatPump.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
REG_DESIRED_SUPPLY_LINE,
REG_DESIRED_SUPPLY_LINE_TEMP,
REG_DESIRED_SYS_SUPPLY_LINE_TEMP,
REG_INTEGRAL_LSD,
REG_OPERATIONAL_STATUS_PRIO1,
REG_OPER_DATA_RETURN,
REG_OPER_DATA_SUPPLY_MA_SA,
REG_OPER_TIME_COMPRESSOR,
Expand All @@ -36,6 +38,7 @@
"temperature": None,
"operation_mode": None,
"hot_water_switch": None,
"hot_water_boost_switch": None,
}


Expand All @@ -55,7 +58,10 @@ def __init__(self, device_data: dict, api_interface: "ThermiaAPI"):
self.__group_operational_status = None
self.__group_operational_time = None
self.__group_operational_operation = None
self.__group_hot_water = None
self.__group_hot_water: dict[str, int | None] = {
"hot_water_switch": None,
"hot_water_boost_switch": None,
}

self.__alarms = None
self.__historical_data_registers_map = None
Expand Down Expand Up @@ -95,9 +101,12 @@ def get_register_indexes(self):
def set_register_index_operation_mode(self, register_index: int):
self.__register_indexes["operation_mode"] = register_index

def set_register_index_hot_water_switch(self, register_index: int):
def set_register_index_hot_water_switch(self, register_index: int | None):
self.__register_indexes["hot_water_switch"] = register_index

def set_register_index_hot_water_boost_switch(self, register_index: int | None):
self.__register_indexes["hot_water_boost_switch"] = register_index

def set_temperature(self, temperature: int):
if self.__status is None:
self._LOGGER.error("Status not available, cannot set temperature")
Expand All @@ -124,14 +133,29 @@ def set_operation_mode(self, mode: str):
def set_hot_water_switch_state(self, state: int):
self._LOGGER.info("Setting hot water switch to " + str(state))

if self.__group_hot_water is None:
if self.__group_hot_water["hot_water_switch"] is None:
self._LOGGER.error("Hot water switch not available")
return

self.__group_hot_water = state # update local state before refetching data
self.__group_hot_water[
"hot_water_switch"
] = state # update local state before refetching data
self.__api_interface.set_hot_water_switch_state(self, state)
self.update_data()

def set_hot_water_boost_switch_state(self, state: int):
self._LOGGER.info("Setting hot water boost switch to " + str(state))

if self.__group_hot_water["hot_water_boost_switch"] is None:
self._LOGGER.error("Hot water switch not available")
return

self.__group_hot_water[
"hot_water_boost_switch"
] = state # update local state before refetching data
self.__api_interface.set_hot_water_boost_switch_state(self, state)
self.update_data()

def get_all_available_register_groups(self):
installation_profile_id = get_dict_value_safe(
self.__info, "installationProfileId"
Expand Down Expand Up @@ -297,7 +321,7 @@ def __get_value_by_key_and_register_name_from_operational_status(
):
data_from_register = self.__get_register_from_operational_status(register_name)

if not data_from_register:
if data_from_register is None:
return None

register_values_list = data_from_register.get("valueNames", [])
Expand All @@ -314,11 +338,9 @@ def __get_value_by_key_and_register_name_from_operational_status(
return None

def __get_all_operational_statuses_from_operational_status(self) -> ChainMap | None:
data = self.__get_register_from_operational_status(
"REG_OPERATIONAL_STATUS_PRIO1"
)
data = self.__get_register_from_operational_status(REG_OPERATIONAL_STATUS_PRIO1)

if not data:
if data is None:
return None

register_values_list = data.get("valueNames", [])
Expand Down Expand Up @@ -480,18 +502,16 @@ def cooling_supply_line_temperature(self):

@property
def operational_status(self):
data = self.__get_register_from_operational_status(
"REG_OPERATIONAL_STATUS_PRIO1"
)
data = self.__get_register_from_operational_status(REG_OPERATIONAL_STATUS_PRIO1)

if not data:
if data is None:
return None

current_register_value = get_dict_value_safe(data, "registerValue")

data = self.__get_all_operational_statuses_from_operational_status()

if not data:
if data is None:
return None

current_operation_mode = [
Expand All @@ -507,7 +527,7 @@ def operational_status(self):
def available_operational_statuses(self):
data = self.__get_all_operational_statuses_from_operational_status()

if not data:
if data is None:
return None

return data.values()
Expand Down Expand Up @@ -584,7 +604,7 @@ def operational_status_heating_status(self):

@property
def operational_status_integral(self):
data = self.__get_register_from_operational_status("REG_INTEGRAL_LSD")
data = self.__get_register_from_operational_status(REG_INTEGRAL_LSD)
return get_dict_value_safe(data, "registerValue")

###########################################################################
Expand Down Expand Up @@ -651,16 +671,21 @@ def is_operation_mode_read_only(self):
return get_dict_value_safe(self.__group_operational_operation, "isReadOnly")

###########################################################################
# Hot water switch data
# Hot water data
###########################################################################

# TODO: DEPRECATED, remove in next major release
@property
def is_hot_water_switch_available(self):
return self.__group_hot_water is not None

@property
def hot_water_switch_state(self):
return self.__group_hot_water
def hot_water_switch_state(self) -> int | None:
return self.__group_hot_water["hot_water_switch"]

@property
def hot_water_boost_switch_state(self) -> int | None:
return self.__group_hot_water["hot_water_boost_switch"]

###########################################################################
# Alarm data
Expand Down
22 changes: 15 additions & 7 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
from ThermiaOnlineAPI import Thermia
from credentials import USERNAME, PASSWORD

CHANGE_HEAT_PUMP_DATA_DURING_TEST = False # Set to True if you want to change heat pump data during test
CHANGE_HEAT_PUMP_DATA_DURING_TEST = (
False # Set to True if you want to change heat pump data during test
)

if not USERNAME or not PASSWORD:
USERNAME = input("Enter username: ")
Expand Down Expand Up @@ -110,9 +112,8 @@
print("\n")

print("Hot Water data")
print("Is Hot Water Switch Available: " + str(heat_pump.is_hot_water_switch_available))
if heat_pump.is_hot_water_switch_available:
print("Hot Water Switch State: " + str(heat_pump.hot_water_switch_state))
print("Hot Water Switch State: " + str(heat_pump.hot_water_switch_state))
print("Hot Water Boost Switch State: " + str(heat_pump.hot_water_boost_switch_state))

print("\n")

Expand Down Expand Up @@ -147,15 +148,22 @@

if CHANGE_HEAT_PUMP_DATA_DURING_TEST:
heat_pump.set_temperature(19)

heat_pump.set_register_data_by_register_group_and_name(
"REG_GROUP_HEATING_CURVE", "REG_HEATING_HEAT_CURVE", 30
)

heat_pump.set_operation_mode("COMPRESSOR")
if heat_pump.is_hot_water_switch_available:

if heat_pump.hot_water_switch_state:
heat_pump.set_hot_water_switch_state(1)

if heat_pump.hot_water_boost_switch_state:
heat_pump.set_hot_water_boost_switch_state(1)

print("Heat Temperature: " + str(heat_pump.heat_temperature))
print("Operation Mode: " + str(heat_pump.operation_mode))
print("Available Operation Modes: " + str(heat_pump.available_operation_modes))
if heat_pump.is_hot_water_switch_available:
print("Hot Water Switch State: " + str(heat_pump.hot_water_switch_state))

print("Hot Water Switch State: " + str(heat_pump.hot_water_switch_state))
print("Hot Water Boost Switch State: " + str(heat_pump.hot_water_boost_switch_state))

0 comments on commit 3ded7d4

Please sign in to comment.