Skip to content

Commit

Permalink
Refactoring to more generic code to support more heat pumps
Browse files Browse the repository at this point in the history
  • Loading branch information
klejejs committed Dec 30, 2021
1 parent 45976de commit bb921a0
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 28 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Thermia Online API
### A Python API for Thermia heat pumps using https://online.thermia.se
### A Python API for Thermia heat pumps using https://online.thermia.se

## Confirmed heat pumps that API supports:
* Thermia Diplomat / Diplomat Duo
* Thermia iTec (still to be confirmed)

## Available properties within ThermiaHeatPump class:
| Property | Description |
Expand Down
59 changes: 39 additions & 20 deletions ThermiaOnlineAPI/api/ThermiaAPI.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,6 @@

THERMIA_API_CONFIG_URL = "https://online.thermia.se/api/configuration"

REGISTER_VALUES = {
"temperature": 50,
"operation_mode": 51,
}

class ThermiaAPI():
def __init__(self, email, password):
self.__email = email
Expand Down Expand Up @@ -65,46 +60,59 @@ def get_device_status(self, device):

return request.json()

def get_temperature_status(self, device):
def get_temperature_status(self, device: ThermiaHeatPump):
self.__check_token_validity()

url = self.configuration['apiBaseUrl'] + "/api/v1/Registers/Installations/" + str(device['id']) + "/Groups/REG_GROUP_TEMPERATURES"
url = self.configuration['apiBaseUrl'] + "/api/v1/Registers/Installations/" + str(device.id) + "/Groups/REG_GROUP_TEMPERATURES"
request = requests.get(url, headers=DEFAULT_REQUEST_HEADERS)
status = request.status_code

if status != 200:
LOGGER.error("Error in getting device's operation mode. " + str(status))
LOGGER.error("Error in getting device's temperature status. " + str(status))
return None

data = [d for d in request.json() if d['registerIndex'] == REGISTER_VALUES['temperature']]
device_temperature_register_index = device.get_register_indexes()["temperature"]
if device_temperature_register_index is None:
LOGGER.error("Error in getting device's temperature status. No temperature register index.")
return None

data = [d for d in request.json() if d['registerIndex'] == device_temperature_register_index]

if len(data) == 0:
LOGGER.error("Error in getting device's temperature status. Could not find temperature by register.")
return None

data = data[0]

return {
"minValue": data[0]['minValue'],
"maxValue": data[0]['maxValue'],
"step": data[0]['step'],
"minValue": data['minValue'],
"maxValue": data['maxValue'],
"step": data['step'],
}

def get_operation_mode(self, device):
def get_operation_mode(self, device: ThermiaHeatPump):
self.__check_token_validity()

url = self.configuration['apiBaseUrl'] + "/api/v1/Registers/Installations/" + str(device['id']) + "/Groups/REG_GROUP_OPERATIONAL_OPERATION"
url = self.configuration['apiBaseUrl'] + "/api/v1/Registers/Installations/" + str(device.id) + "/Groups/REG_GROUP_OPERATIONAL_OPERATION"
request = requests.get(url, headers=DEFAULT_REQUEST_HEADERS)
status = request.status_code

if status != 200:
LOGGER.error("Error in getting device's operation mode. " + str(status))
return None

data = [d for d in request.json() if d['registerIndex'] == REGISTER_VALUES['operation_mode']]
data = [d for d in request.json() if d['registerName'] == "REG_OPERATIONMODE"]

if len(data) == 0:
LOGGER.error("Error in getting device's operation mode. Could not find operation mode by register name.")
return None

current_operation_mode = int(data[0].get("registerValue"))
operation_modes_data = data[0].get("valueNames")
data = data[0]

device.set_register_index_operation_mode(data['registerIndex'])

current_operation_mode = int(data.get("registerValue"))
operation_modes_data = data.get("valueNames")

if operation_modes_data is not None:
operation_modes = list(map(lambda values: values.get("name").split("REG_VALUE_OPERATION_MODE_")[1], operation_modes_data))
Expand All @@ -116,13 +124,24 @@ def get_operation_mode(self, device):
return None

def set_temperature(self, device: ThermiaHeatPump, temperature):
self.__set_register_value(device, REGISTER_VALUES["temperature"], temperature)
device_temperature_register_index = device.get_register_indexes()["temperature"]
if device_temperature_register_index is None:
LOGGER.error("Error setting device's temperature. No temperature register index.")
return

self.__set_register_value(device, device_temperature_register_index, temperature)

def set_operation_mode(self, device: ThermiaHeatPump, mode):
operation_mode_int = device.available_operation_modes.index(mode)
self.__set_register_value(device, REGISTER_VALUES["operation_mode"], operation_mode_int)

def __set_register_value(self, device: ThermiaHeatPump, register_index: REGISTER_VALUES, register_value: int):
device_operation_mode_register_index = device.get_register_indexes()["operation_mode"]
if device_operation_mode_register_index is None:
LOGGER.error("Error setting device's operation mode. No operation mode register index.")
return

self.__set_register_value(device, device_operation_mode_register_index, operation_mode_int)

def __set_register_value(self, device: ThermiaHeatPump, register_index: int, register_value: int):
self.__check_token_validity()

url = self.configuration['apiBaseUrl'] + "/api/v1/Registers/Installations/" + str(device.id) + "/Registers"
Expand Down
40 changes: 33 additions & 7 deletions ThermiaOnlineAPI/model/HeatPump.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@

LOGGER = logging.getLogger(__name__)

DEFAULT_REGISTER_INDEXES = {
"temperature": None,
"operation_mode": None,
}

class ThermiaHeatPump():
def __init__(self, device_data: json, api_interface: "ThermiaAPI"):
self.__device_data = device_data
Expand All @@ -16,14 +21,25 @@ def __init__(self, device_data: json, api_interface: "ThermiaAPI"):
self.__status = None
self.__temperature_state = None
self.__operation_mode_state = None

self.__register_indexes = DEFAULT_REGISTER_INDEXES

self.refetch_data()

def refetch_data(self):
self.__info = self.__api_interface.get_device_info(self.__device_data)
self.__status = self.__api_interface.get_device_status(self.__device_data)
self.__temperature_state = self.__api_interface.get_temperature_status(self.__device_data)
self.__operation_mode_state = self.__api_interface.get_operation_mode(self.__device_data)

self.__register_indexes["temperature"] = self.__status.get("heatingEffectRegisters", [None, None])[1]

self.__temperature_state = self.__api_interface.get_temperature_status(self)
self.__operation_mode_state = self.__api_interface.get_operation_mode(self)

def get_register_indexes(self):
return self.__register_indexes

def set_register_index_operation_mode(self, register_index: int):
self.__register_indexes["operation_mode"] = register_index

def set_temperature(self, temperature: int):
LOGGER.info("Setting temperature to " + str(temperature))
Expand Down Expand Up @@ -86,20 +102,30 @@ def heat_temperature(self):

@property
def heat_min_temperature_value(self):
return self.__temperature_state.get("minValue")
if self.__temperature_state is None:
return None
return self.__temperature_state.get("minValue", None)

@property
def heat_max_temperature_value(self):
return self.__temperature_state.get("maxValue")
if self.__temperature_state is None:
return None
return self.__temperature_state.get("maxValue", None)

@property
def heat_temperature_step(self):
return self.__temperature_state.get("step")
if self.__temperature_state is None:
return None
return self.__temperature_state.get("step", None)

@property
def operation_mode(self):
return self.__operation_mode_state["current"]
if self.__operation_mode_state is None:
return None
return self.__operation_mode_state.get("current", None)

@property
def available_operation_modes(self):
return self.__operation_mode_state["available"]
if self.__operation_mode_state is None:
return None
return self.__operation_mode_state.get("available", [])

0 comments on commit bb921a0

Please sign in to comment.