qolsys-controller 0.0.62__py3-none-any.whl → 0.0.87__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of qolsys-controller might be problematic. Click here for more details.

Files changed (37) hide show
  1. qolsys_controller/adc_device.py +202 -0
  2. qolsys_controller/adc_service.py +139 -0
  3. qolsys_controller/adc_service_garagedoor.py +35 -0
  4. qolsys_controller/controller.py +245 -34
  5. qolsys_controller/database/db.py +60 -0
  6. qolsys_controller/database/table.py +1 -0
  7. qolsys_controller/database/table_alarmedsensor.py +2 -0
  8. qolsys_controller/database/table_history.py +2 -2
  9. qolsys_controller/database/table_smartsocket.py +12 -1
  10. qolsys_controller/database/table_thermostat.py +3 -0
  11. qolsys_controller/database/table_virtual_device.py +13 -1
  12. qolsys_controller/database/table_zwave_node.py +3 -0
  13. qolsys_controller/enum.py +5 -1
  14. qolsys_controller/enum_adc.py +28 -0
  15. qolsys_controller/enum_zwave.py +158 -29
  16. qolsys_controller/errors.py +5 -0
  17. qolsys_controller/mqtt_command.py +6 -0
  18. qolsys_controller/panel.py +109 -5
  19. qolsys_controller/partition.py +22 -2
  20. qolsys_controller/state.py +163 -1
  21. qolsys_controller/task_manager.py +4 -3
  22. qolsys_controller/zone.py +2 -1
  23. qolsys_controller/zwave_device.py +132 -4
  24. qolsys_controller/zwave_dimmer.py +3 -0
  25. qolsys_controller/zwave_energy_clamp.py +15 -0
  26. qolsys_controller/zwave_garagedoor.py +3 -0
  27. qolsys_controller/zwave_generic.py +3 -0
  28. qolsys_controller/zwave_lock.py +4 -0
  29. qolsys_controller/zwave_outlet.py +3 -0
  30. qolsys_controller/zwave_service_meter.py +192 -0
  31. qolsys_controller/zwave_service_multilevelsensor.py +119 -0
  32. qolsys_controller/zwave_thermometer.py +21 -0
  33. qolsys_controller/zwave_thermostat.py +150 -38
  34. {qolsys_controller-0.0.62.dist-info → qolsys_controller-0.0.87.dist-info}/METADATA +1 -1
  35. {qolsys_controller-0.0.62.dist-info → qolsys_controller-0.0.87.dist-info}/RECORD +37 -29
  36. {qolsys_controller-0.0.62.dist-info → qolsys_controller-0.0.87.dist-info}/WHEEL +0 -0
  37. {qolsys_controller-0.0.62.dist-info → qolsys_controller-0.0.87.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,192 @@
1
+ __all__ = ["QolsysZwaveMeterSensor"]
2
+
3
+ import json
4
+ import logging
5
+ from enum import IntEnum
6
+ from typing import TYPE_CHECKING, Any, Type
7
+
8
+ from qolsys_controller.enum_zwave import (
9
+ MeterRateType,
10
+ MeterType,
11
+ ZWaveElectricMeterScale,
12
+ ZWaveUnknownMeterScale,
13
+ )
14
+
15
+ if TYPE_CHECKING:
16
+ from .zwave_device import QolsysZWaveDevice
17
+
18
+ LOGGER = logging.getLogger(__name__)
19
+
20
+
21
+ def get_enum_by_name(enum: type[IntEnum], name: str) -> IntEnum | None:
22
+ for val in enum:
23
+ if val.name.upper() == name.upper():
24
+ return val
25
+ return None
26
+
27
+
28
+ class QolsysZwaveMeterSensor:
29
+ def __init__(self, parent_device: "QolsysZWaveDevice", parent_meter: "QolsysZwaveServiceMeter", scale: IntEnum) -> None:
30
+ self._parent_device: QolsysZWaveDevice = parent_device
31
+ self._parent_meter: QolsysZwaveServiceMeter = parent_meter
32
+ self._scale: IntEnum = scale
33
+ self._value: float | None = None
34
+ self._delta_time: int | None = None
35
+ self._previous_value: float | None = None
36
+
37
+ @property
38
+ def value(self) -> float | None:
39
+ return self._value
40
+
41
+ @value.setter
42
+ def value(self, new_value: float | None) -> None:
43
+ if self._value != new_value:
44
+ self._value = new_value
45
+ LOGGER.debug(
46
+ "ZWaveMeter%s-%s (%s) - %s - value: %s (%s)",
47
+ self._parent_device.node_id,
48
+ self._parent_meter.endpoint,
49
+ self._parent_device.node_name,
50
+ self._parent_meter._meter_type.name,
51
+ new_value,
52
+ self._scale.name,
53
+ )
54
+ self._parent_device.notify()
55
+
56
+ @property
57
+ def scale(self) -> IntEnum:
58
+ return self._scale
59
+
60
+
61
+ class QolsysZwaveServiceMeter:
62
+ def __init__(self, parent_device: "QolsysZWaveDevice", endpoint: str, meter_dict: dict[str, Any]) -> None:
63
+ self._parent_device: QolsysZWaveDevice = parent_device
64
+ self._endpoint: str = endpoint
65
+ self._meter_type: MeterType = MeterType.UNKNOWN
66
+ self._rate_type: MeterRateType = MeterRateType.UNSPECIFIED
67
+ self._scale_type: Type[IntEnum] = ZWaveUnknownMeterScale
68
+ self._supported_scale: list[IntEnum] = []
69
+ self._sensors: list[QolsysZwaveMeterSensor] = []
70
+ self._master_reset_flag: bool = False
71
+
72
+ # Set Meter_Type
73
+ type: str | int = meter_dict.get("meter_type", "")
74
+ if type == "ENERGY_METER" or type == MeterType.ELECTRIC_METER.value:
75
+ self._meter_type = MeterType.ELECTRIC_METER
76
+ self._scale_type = ZWaveElectricMeterScale
77
+ else:
78
+ LOGGER.warning("Zave Meter Service - Unknown Meter Type: %s", type)
79
+ return
80
+
81
+ # Set Rate Type
82
+ rate_type: int = meter_dict.get("meter_ratetype_supported", -1)
83
+ try:
84
+ self._rate_type = MeterRateType(rate_type)
85
+ except ValueError:
86
+ LOGGER.error("Zave Meter Service - Unknown MeterRateType, Setting to UNSPECIFIED")
87
+ self._rate_type = MeterRateType.UNSPECIFIED
88
+
89
+ # Set Master Reset Flag
90
+ self._master_reset_flag = bool(meter_dict.get("meter_master_reset_flag", False))
91
+
92
+ # Set Supported Scales
93
+ self.supported_scale = meter_dict.get("meter_scale_supported", "[]")
94
+
95
+ # Create Sensors for Supported Scales
96
+ for scale in self._supported_scale:
97
+ qolsys_meter_sensor = QolsysZwaveMeterSensor(self._parent_device, self, scale)
98
+ self.add_sensor(qolsys_meter_sensor)
99
+
100
+ # Update sensor values
101
+ self.update_iq2medi(meter_dict)
102
+
103
+ @property
104
+ def sensors(self) -> list[QolsysZwaveMeterSensor]:
105
+ return self._sensors
106
+
107
+ def add_sensor(self, new_sensor: QolsysZwaveMeterSensor) -> None:
108
+ for sensor in self._sensors:
109
+ if sensor._scale == new_sensor._scale:
110
+ LOGGER.error("Error Adding Sensor, scale allready present")
111
+ return
112
+ self._sensors.append(new_sensor)
113
+ self._parent_device.notify()
114
+
115
+ def get_sensor(self, scale: IntEnum) -> QolsysZwaveMeterSensor | None:
116
+ for sensor in self._sensors:
117
+ if sensor._scale == scale:
118
+ return sensor
119
+ return None
120
+
121
+ @property
122
+ def endpoint(self) -> str:
123
+ return self._endpoint
124
+
125
+ @property
126
+ def rate_type(self) -> MeterRateType:
127
+ return self._rate_type
128
+
129
+ @rate_type.setter
130
+ def rate_type(self, value: MeterRateType) -> None:
131
+ if self._rate_type != value:
132
+ self._rate_type = value
133
+ # LOGGER.debug("Zave Meter Service - rate_type: %s", value.name)
134
+ self._parent_device.notify()
135
+
136
+ @property
137
+ def supported_scale(self) -> list[IntEnum]:
138
+ return self._supported_scale
139
+
140
+ @supported_scale.setter
141
+ def supported_scale(self, value: str) -> None:
142
+ try:
143
+ scales = json.loads(value)
144
+ cleaned = [s.strip() for s in scales]
145
+
146
+ except json.JSONDecodeError:
147
+ self._supported_scale = []
148
+ LOGGER.error("Zave Meter Service - Error parsing meter_scale_supported, Setting to empty list")
149
+
150
+ for key in cleaned:
151
+ for scale in self._scale_type:
152
+ if key.lower() == scale.name.lower():
153
+ if scale not in self._supported_scale:
154
+ self._supported_scale.append(scale)
155
+
156
+ def update_iq2medi(self, data: dict[str, Any]) -> None:
157
+ # Update Z-Wave Meter Service
158
+
159
+ # Cannot change meter type once created
160
+ type: str | int = data.get("meter_type", "")
161
+ if type == "ENERGY_METER" or type == MeterType.ELECTRIC_METER:
162
+ if self._meter_type is not MeterType.ELECTRIC_METER:
163
+ LOGGER.error("Zave Meter Service - Cannot change Meter Type once created")
164
+ return
165
+
166
+ self._parent_device.start_batch_update()
167
+
168
+ # Upate Rate Type
169
+ if "meter_ratetype_supported" in data:
170
+ rate_type: int = data.get("meter_ratetype_supported", -1)
171
+ try:
172
+ self.rate_type = MeterRateType(rate_type)
173
+ except ValueError:
174
+ LOGGER.error("Zave Meter Service - Unknown MeterRateType, Setting to UNSPECIFIED")
175
+ self.rate_type = MeterRateType.UNSPECIFIED
176
+
177
+ # Update Master Reset Flag
178
+ if "meter_master_reset_flag" in data:
179
+ self._master_reset_flag = bool(data.get("meter_master_reset_flag", False))
180
+
181
+ # Update Meter Values
182
+ if "meter_scale_reading_values" in data:
183
+ scale_values: dict[str, Any] = data.get("meter_scale_reading_values", {})
184
+
185
+ for key, value in scale_values.items():
186
+ temp = get_enum_by_name(self._scale_type, key.strip())
187
+ if temp in self._supported_scale:
188
+ sensor = self.get_sensor(temp)
189
+ if sensor is not None:
190
+ sensor.value = float(value)
191
+
192
+ self._parent_device.end_batch_update()
@@ -0,0 +1,119 @@
1
+ __all__ = ["QolsysZwaveMultilevelSensor"]
2
+
3
+ import logging
4
+ from enum import IntEnum
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+ from qolsys_controller.enum_zwave import ZWaveMultilevelSensorScale
8
+
9
+ if TYPE_CHECKING:
10
+ from .zwave_device import QolsysZWaveDevice
11
+
12
+ LOGGER = logging.getLogger(__name__)
13
+
14
+
15
+ def get_enum_by_name(enum: type[IntEnum], name: str) -> IntEnum | None:
16
+ for val in enum:
17
+ if val.name.upper() == name.upper():
18
+ return val
19
+ return None
20
+
21
+
22
+ class QolsysZwaveMultilevelSensor:
23
+ def __init__(
24
+ self,
25
+ parent_device: "QolsysZWaveDevice",
26
+ parent_sensor: "QolsysZwaveServiceMultilevelSensor",
27
+ unit: ZWaveMultilevelSensorScale,
28
+ ) -> None:
29
+ self._parent_device: QolsysZWaveDevice = parent_device
30
+ self._parent_meter: QolsysZwaveServiceMultilevelSensor = parent_sensor
31
+ self._value: float | None = None
32
+ self._unit: ZWaveMultilevelSensorScale = unit
33
+
34
+ @property
35
+ def unit(self) -> ZWaveMultilevelSensorScale:
36
+ return self._unit
37
+
38
+ @property
39
+ def value(self) -> float | None:
40
+ return self._value
41
+
42
+ @value.setter
43
+ def value(self, new_value: float | None) -> None:
44
+ if self._value != new_value:
45
+ self._value = new_value
46
+ LOGGER.debug(
47
+ "ZWaveMultilevelSensor%s-%s (%s) - value: %s (%s)",
48
+ self._parent_device.node_id,
49
+ self._parent_meter.endpoint,
50
+ self._parent_device.node_name,
51
+ new_value,
52
+ self._unit.name,
53
+ )
54
+ self._parent_device.notify()
55
+
56
+
57
+ class QolsysZwaveServiceMultilevelSensor:
58
+ def __init__(self, parent_device: "QolsysZWaveDevice", endpoint: str, sensor_dict: dict[str, Any]) -> None:
59
+ self._parent_device: QolsysZWaveDevice = parent_device
60
+ self._endpoint: str = endpoint
61
+ self._sensors: list[QolsysZwaveMultilevelSensor] = []
62
+
63
+ # Update sensor values
64
+ self.update_iq2medi(sensor_dict)
65
+
66
+ @property
67
+ def sensors(self) -> list[QolsysZwaveMultilevelSensor]:
68
+ return self._sensors
69
+
70
+ def add_sensor(self, new_sensor: QolsysZwaveMultilevelSensor) -> None:
71
+ for sensor in self._sensors:
72
+ if sensor._unit == new_sensor._unit:
73
+ LOGGER.error("Error Adding Sensor, unit allready present")
74
+ return
75
+ self._sensors.append(new_sensor)
76
+ self._parent_device.notify()
77
+
78
+ def get_sensor(self, unit: ZWaveMultilevelSensorScale) -> QolsysZwaveMultilevelSensor | None:
79
+ for sensor in self._sensors:
80
+ if sensor.unit == unit:
81
+ return sensor
82
+ return None
83
+
84
+ @property
85
+ def endpoint(self) -> str:
86
+ return self._endpoint
87
+
88
+ def update_iq2medi(self, data: dict[str, Any]) -> None:
89
+ # Update Z-Wave Multilevelsensor Service
90
+
91
+ self._parent_device.start_batch_update()
92
+
93
+ # Update Sensors Values
94
+ for key, value in data.items():
95
+ if key == "AIR TEMPERATURE":
96
+ temperature: float | None = value.get("Fahrenheit (F)", None)
97
+ sensor = self.get_sensor(ZWaveMultilevelSensorScale.TEMPERATURE_FAHRENHEIT)
98
+ if sensor:
99
+ sensor.value = temperature
100
+ else:
101
+ sensor = QolsysZwaveMultilevelSensor(
102
+ self._parent_device, self, ZWaveMultilevelSensorScale.TEMPERATURE_FAHRENHEIT
103
+ )
104
+ self.add_sensor(sensor)
105
+ sensor.value = temperature
106
+
107
+ if key == "HUMIDITY":
108
+ humidity: float | None = value.get("Percentage value (%)", None)
109
+ sensor = self.get_sensor(ZWaveMultilevelSensorScale.RELATIVE_HUMIDITY)
110
+ if sensor:
111
+ sensor.value = humidity
112
+ else:
113
+ sensor = QolsysZwaveMultilevelSensor(
114
+ self._parent_device, self, ZWaveMultilevelSensorScale.RELATIVE_HUMIDITY
115
+ )
116
+ self.add_sensor(sensor)
117
+ sensor.value = humidity
118
+
119
+ self._parent_device.end_batch_update()
@@ -0,0 +1,21 @@
1
+ import logging
2
+
3
+ from .zwave_device import QolsysZWaveDevice
4
+
5
+ LOGGER = logging.getLogger(__name__)
6
+
7
+
8
+ class QolsysThermometer(QolsysZWaveDevice):
9
+ def __init__(self, zwave_dict: dict[str, str]) -> None:
10
+ super().__init__(zwave_dict)
11
+ self._temprature_value = ""
12
+ self._humidity_value = ""
13
+
14
+ def update_raw(self, payload: bytes) -> None:
15
+ LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
16
+
17
+ def to_dict_thermometer(self) -> dict[str, str]:
18
+ return {
19
+ "temperature_value": self._temprature_value,
20
+ "humidity_value": self._humidity_value,
21
+ }
@@ -1,6 +1,14 @@
1
1
  import logging
2
2
 
3
- from .enum_zwave import ThermostatFanMode, ThermostatMode
3
+ from .enum_zwave import (
4
+ BITMASK_SUPPORTED_THERMOSTAT_FAN_MODE,
5
+ BITMASK_SUPPORTED_THERMOSTAT_MODE,
6
+ BITMASK_SUPPORTED_THERMOSTAT_SETPOINT_MODE,
7
+ ThermostatFanMode,
8
+ ThermostatMode,
9
+ ThermostatSetpointMode,
10
+ ZWaveMultilevelSensorScale,
11
+ )
4
12
  from .zwave_device import QolsysZWaveDevice
5
13
 
6
14
  LOGGER = logging.getLogger(__name__)
@@ -41,6 +49,10 @@ class QolsysThermostat(QolsysZWaveDevice):
41
49
  self._thermostat_endpoint: str = thermostat_dict.get("endpoint", "")
42
50
  self._thermostat_paired_status: str = thermostat_dict.get("paired_status", "")
43
51
  self._thermostat_configuration_parameter: str = thermostat_dict.get("configuration_parameter", "")
52
+ self._thermostat_operating_state: str = thermostat_dict.get("operating_state", "")
53
+ self._thermostat_setpoint_capabilites = thermostat_dict.get("setpoint_capabilites", "")
54
+
55
+ self._thermostat_current_humidity: float | None = None
44
56
 
45
57
  # -----------------------------
46
58
  # properties + setters
@@ -61,6 +73,41 @@ class QolsysThermostat(QolsysZWaveDevice):
61
73
  self._thermostat_name = value
62
74
  self.notify()
63
75
 
76
+ @property
77
+ def thermostat_operating_state(self) -> str:
78
+ return self._thermostat_operating_state
79
+
80
+ @thermostat_operating_state.setter
81
+ def thermostat_operating_state(self, value: str) -> None:
82
+ if self._thermostat_operating_state != value:
83
+ LOGGER.debug("Thermostat%s (%s) - operating_state: %s", self.thermostat_node_id, self.thermostat_name, value)
84
+ self._thermostat_operating_state = value
85
+ self.notify()
86
+
87
+ @property
88
+ def thermostat_configuration_parameter(self) -> str:
89
+ return self._thermostat_configuration_parameter
90
+
91
+ @thermostat_configuration_parameter.setter
92
+ def thermostat_configuration_parameter(self, value: str) -> None:
93
+ if self._thermostat_configuration_parameter != value:
94
+ LOGGER.debug(
95
+ "Thermostat%s (%s) - configuration_parameter: %s", self.thermostat_node_id, self.thermostat_name, value
96
+ )
97
+ self._thermostat_configuration_parameter = value
98
+ self.notify()
99
+
100
+ @property
101
+ def thermostat_setpoint_capabilites(self) -> str:
102
+ return self._thermostat_setpoint_capabilites
103
+
104
+ @thermostat_setpoint_capabilites.setter
105
+ def thermostat_setpoint_capabilites(self, value: str) -> None:
106
+ if self._thermostat_setpoint_capabilites != value:
107
+ LOGGER.debug("Thermostat%s (%s) - setpoint_capabilites: %s", self.thermostat_node_id, self.thermostat_name, value)
108
+ self._thermostat_setpoint_capabilites = value
109
+ self.notify()
110
+
64
111
  @property
65
112
  def thermostat_device_temp_unit(self) -> str:
66
113
  return self._thermostat_device_temp_unit
@@ -118,37 +165,79 @@ class QolsysThermostat(QolsysZWaveDevice):
118
165
 
119
166
  @property
120
167
  def thermostat_mode(self) -> ThermostatMode | None:
121
- thermostat_mode = int(self._thermostat_mode)
122
- for mode in ThermostatMode:
123
- if thermostat_mode == mode:
124
- return mode
125
- return None
168
+ value = self._thermostat_mode.strip("[]").split(",")
169
+
170
+ if len(value) > 1:
171
+ LOGGER.error(
172
+ "Thermostat%s (%s) - thermostat_mode has multiple values: %s",
173
+ self.thermostat_node_id,
174
+ self.thermostat_name,
175
+ value,
176
+ )
177
+ return None
178
+
179
+ try:
180
+ int_value = int(value[0])
181
+ for mode in ThermostatMode:
182
+ if int_value == mode.value:
183
+ return mode
184
+ return None
185
+ except ValueError:
186
+ LOGGER.error(
187
+ "Thermostat%s (%s) - thermostat_mode value is not an integer: %s",
188
+ self.thermostat_node_id,
189
+ self.thermostat_name,
190
+ value,
191
+ )
192
+ return None
126
193
 
127
194
  @thermostat_mode.setter
128
195
  def thermostat_mode(self, value: str) -> None:
129
- if self._thermostat_mode != value:
130
- LOGGER.debug("Thermostat%s (%s) - mode: %s", self.thermostat_node_id, self.thermostat_name, value)
131
- self._thermostat_mode = value
196
+ new_value = value.strip("[]")
197
+ if self._thermostat_mode != new_value:
198
+ LOGGER.debug("Thermostat%s (%s) - mode: %s", self.thermostat_node_id, self.thermostat_name, new_value)
199
+ self._thermostat_mode = new_value
132
200
  self.notify()
133
201
 
134
202
  @property
135
203
  def thermostat_fan_mode(self) -> ThermostatFanMode | None:
136
- thermostat_fan_mode = int(self._thermostat_fan_mode)
137
- for mode in ThermostatFanMode:
138
- if thermostat_fan_mode == mode:
139
- return mode
140
- return None
204
+ value = self._thermostat_fan_mode.strip("[]").split(",")
205
+
206
+ if len(value) > 1:
207
+ LOGGER.error(
208
+ "Thermostat%s (%s) - thermostat_fan_mode has multiple values: %s",
209
+ self.thermostat_node_id,
210
+ self.thermostat_name,
211
+ value,
212
+ )
213
+ return None
214
+
215
+ try:
216
+ int_value = int(value[0])
217
+ for mode in ThermostatFanMode:
218
+ if int_value == mode.value:
219
+ return mode
220
+ return None
221
+ except ValueError:
222
+ LOGGER.error(
223
+ "Thermostat%s (%s) - thermostat_fan_mode value is not an integer: %s",
224
+ self.thermostat_node_id,
225
+ self.thermostat_name,
226
+ value,
227
+ )
228
+ return None
141
229
 
142
230
  @thermostat_fan_mode.setter
143
231
  def thermostat_fan_mode(self, value: str) -> None:
144
- if self._thermostat_fan_mode != value:
145
- LOGGER.debug("Thermostat%s (%s) - fan_mode: %s", self.thermostat_node_id, self.thermostat_name, value)
146
- self._thermostat_fan_mode = value
232
+ new_value = value.strip("[]")
233
+ if self._thermostat_fan_mode != new_value:
234
+ LOGGER.debug("Thermostat%s (%s) - fan_mode: %s", self.thermostat_node_id, self.thermostat_name, new_value)
235
+ self._thermostat_fan_mode = new_value
147
236
  self.notify()
148
237
 
149
238
  @property
150
239
  def thermostat_set_point_mode(self) -> str:
151
- return self._thermostat_set_point_mode
240
+ return self._thermostat_set_point_mode.strip("[]")
152
241
 
153
242
  @thermostat_set_point_mode.setter
154
243
  def thermostat_set_point_mode(self, value: str) -> None:
@@ -157,6 +246,22 @@ class QolsysThermostat(QolsysZWaveDevice):
157
246
  self._thermostat_set_point_mode = value
158
247
  self.notify()
159
248
 
249
+ @property
250
+ def thermostat_current_humidity(self) -> float | None:
251
+ sensor = self.multilevelsensor_value(ZWaveMultilevelSensorScale.RELATIVE_HUMIDITY)
252
+
253
+ if not sensor:
254
+ return None
255
+
256
+ if len(sensor) == 1:
257
+ return sensor[0].value
258
+
259
+ LOGGER.error("Multiple humidity sensor present")
260
+ return sensor[0].value
261
+
262
+ def update_raw(self, payload: bytes) -> None:
263
+ pass
264
+
160
265
  def update_thermostat(self, data: dict[str, str]) -> None: # noqa: C901, PLR0912, PLR0915
161
266
  # Check if we are updating same none_id
162
267
  node_id_update = data.get("node_id", "")
@@ -227,6 +332,10 @@ class QolsysThermostat(QolsysZWaveDevice):
227
332
  self._thermostat_endpoint = data.get("endpoint", "")
228
333
  if "configuration_parameter" in data:
229
334
  self._thermostat_configuration_parameter = data.get("configuration_parameter", "")
335
+ if "operating_state" in data:
336
+ self.thermostat_operating_state = data.get("operating_state", "")
337
+ if "setpoint_capabilites" in data:
338
+ self.thermostat_setpoint_capabilites = data.get("setpoint_capabilites", "")
230
339
 
231
340
  self.end_batch_update()
232
341
 
@@ -237,6 +346,7 @@ class QolsysThermostat(QolsysZWaveDevice):
237
346
  "opr": self._thermostat_opr,
238
347
  "partition_id": self._thermostat_partition_id,
239
348
  "thermostat_name": self.thermostat_name,
349
+ "node_id": self.thermostat_node_id,
240
350
  "device_temp_unit": self.thermostat_device_temp_unit,
241
351
  "current_temp": self.thermostat_current_temp,
242
352
  "target_cool_temp": self.thermostat_target_cool_temp,
@@ -260,41 +370,43 @@ class QolsysThermostat(QolsysZWaveDevice):
260
370
  "current_temp_updated_time": self._thermostat_current_temp_updated_time,
261
371
  "paired_status": self._thermostat_paired_status,
262
372
  "endpoint": self._thermostat_endpoint,
263
- "configuration_parameter": self._thermostat_configuration_parameter,
373
+ "configuration_parameter": self.thermostat_configuration_parameter,
374
+ "operating_state": self.thermostat_operating_state,
375
+ "setpoint_capabilites": self._thermostat_setpoint_capabilites,
264
376
  }
265
377
 
266
378
  def available_thermostat_mode(self) -> list[ThermostatMode]:
267
- int_list = [int(x) for x in self._thermostat_mode_bitmask.split(",")]
379
+ int_list = [int(x) for x in self._thermostat_mode_bitmask.strip("[]").split(",")]
268
380
  byte_array = bytes(int_list)
269
381
  bitmask = int.from_bytes(byte_array, byteorder="little")
270
382
 
271
- mode_array = []
272
- for mode in ThermostatMode:
273
- if mode.value & bitmask:
274
- mode_array.append(mode)
383
+ supported = []
384
+ for bit, mode in BITMASK_SUPPORTED_THERMOSTAT_MODE.items():
385
+ if bitmask & (1 << bit):
386
+ supported.append(mode)
275
387
 
276
- return mode_array
388
+ return supported
277
389
 
278
390
  def available_thermostat_fan_mode(self) -> list[ThermostatFanMode]:
279
- int_list = [int(x) for x in self._thermostat_fan_mode_bitmask.split(",")]
391
+ int_list = [int(x) for x in self._thermostat_fan_mode_bitmask.strip("[]").split(",")]
280
392
  byte_array = bytes(int_list)
281
393
  bitmask = int.from_bytes(byte_array, byteorder="little")
282
394
 
283
- fan_mode_array = []
284
- for mode in ThermostatFanMode:
285
- if mode.value & bitmask:
286
- fan_mode_array.append(mode)
395
+ supported = []
396
+ for bit, mode in BITMASK_SUPPORTED_THERMOSTAT_FAN_MODE.items():
397
+ if bitmask & (1 << bit):
398
+ supported.append(mode)
287
399
 
288
- return fan_mode_array
400
+ return supported
289
401
 
290
- def available_thermostat_set_point_mode(self) -> list[ThermostatMode]:
291
- int_list = [int(x) for x in self._thermostat_set_point_mode_bitmask.split(",")]
402
+ def available_thermostat_set_point_mode(self) -> list[ThermostatSetpointMode]:
403
+ int_list = [int(x) for x in self._thermostat_set_point_mode_bitmask.strip("[]").split(",")]
292
404
  byte_array = bytes(int_list)
293
405
  bitmask = int.from_bytes(byte_array, byteorder="little")
294
406
 
295
- set_point_mode_array = []
296
- for mode in ThermostatMode:
297
- if mode.value & bitmask:
298
- set_point_mode_array.append(mode)
407
+ supported = []
408
+ for bit, mode in BITMASK_SUPPORTED_THERMOSTAT_SETPOINT_MODE.items():
409
+ if bitmask & (1 << bit):
410
+ supported.append(mode)
299
411
 
300
- return set_point_mode_array
412
+ return supported
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qolsys-controller
3
- Version: 0.0.62
3
+ Version: 0.0.87
4
4
  Summary: A Python module that emulates a virtual IQ Remote device, enabling full local control of a Qolsys IQ Panel
5
5
  Project-URL: Homepage, https://github.com/EHylands/QolsysController
6
6
  Project-URL: Issues, https://github.com/EHylands/QolsysController/issues