qolsys-controller 0.0.44__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 (81) 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 +1040 -20
  5. qolsys_controller/database/db.py +108 -29
  6. qolsys_controller/database/table.py +90 -60
  7. qolsys_controller/database/table_alarmedsensor.py +2 -2
  8. qolsys_controller/database/table_automation.py +0 -1
  9. qolsys_controller/database/table_country_locale.py +0 -1
  10. qolsys_controller/database/table_dashboard_msgs.py +1 -2
  11. qolsys_controller/database/table_dimmerlight.py +0 -1
  12. qolsys_controller/database/table_doorlock.py +0 -1
  13. qolsys_controller/database/table_eu_event.py +1 -2
  14. qolsys_controller/database/table_heat_map.py +0 -2
  15. qolsys_controller/database/table_history.py +4 -1
  16. qolsys_controller/database/table_iqremotesettings.py +0 -2
  17. qolsys_controller/database/table_iqrouter_network_config.py +0 -1
  18. qolsys_controller/database/table_iqrouter_user_device.py +0 -2
  19. qolsys_controller/database/table_master_slave.py +0 -1
  20. qolsys_controller/database/table_nest_device.py +0 -1
  21. qolsys_controller/database/table_output_rules.py +0 -1
  22. qolsys_controller/database/table_partition.py +0 -1
  23. qolsys_controller/database/table_pgm_outputs.py +0 -2
  24. qolsys_controller/database/table_powerg_device.py +0 -2
  25. qolsys_controller/database/table_qolsyssettings.py +0 -2
  26. qolsys_controller/database/table_scene.py +0 -2
  27. qolsys_controller/database/table_sensor.py +2 -2
  28. qolsys_controller/database/table_sensor_group.py +23 -0
  29. qolsys_controller/database/table_shades.py +0 -2
  30. qolsys_controller/database/table_smartsocket.py +12 -3
  31. qolsys_controller/database/table_state.py +0 -1
  32. qolsys_controller/database/table_tcc.py +0 -1
  33. qolsys_controller/database/table_thermostat.py +3 -1
  34. qolsys_controller/database/table_trouble_conditions.py +0 -2
  35. qolsys_controller/database/table_user.py +0 -2
  36. qolsys_controller/database/table_virtual_device.py +13 -3
  37. qolsys_controller/database/table_weather.py +0 -2
  38. qolsys_controller/database/table_zigbee_device.py +0 -1
  39. qolsys_controller/database/table_zwave_association_group.py +0 -1
  40. qolsys_controller/database/table_zwave_history.py +0 -1
  41. qolsys_controller/database/table_zwave_node.py +3 -1
  42. qolsys_controller/database/table_zwave_other.py +0 -1
  43. qolsys_controller/enum.py +42 -13
  44. qolsys_controller/enum_adc.py +28 -0
  45. qolsys_controller/enum_zwave.py +210 -36
  46. qolsys_controller/errors.py +14 -12
  47. qolsys_controller/mdns.py +7 -4
  48. qolsys_controller/mqtt_command.py +125 -0
  49. qolsys_controller/mqtt_command_queue.py +5 -4
  50. qolsys_controller/observable.py +2 -2
  51. qolsys_controller/panel.py +304 -156
  52. qolsys_controller/partition.py +149 -127
  53. qolsys_controller/pki.py +69 -97
  54. qolsys_controller/scene.py +30 -28
  55. qolsys_controller/settings.py +96 -50
  56. qolsys_controller/state.py +221 -34
  57. qolsys_controller/task_manager.py +11 -14
  58. qolsys_controller/users.py +25 -0
  59. qolsys_controller/utils_mqtt.py +8 -16
  60. qolsys_controller/weather.py +71 -0
  61. qolsys_controller/zone.py +243 -214
  62. qolsys_controller/zwave_device.py +234 -93
  63. qolsys_controller/zwave_dimmer.py +55 -49
  64. qolsys_controller/zwave_energy_clamp.py +15 -0
  65. qolsys_controller/zwave_garagedoor.py +3 -1
  66. qolsys_controller/zwave_generic.py +5 -3
  67. qolsys_controller/zwave_lock.py +51 -44
  68. qolsys_controller/zwave_outlet.py +3 -1
  69. qolsys_controller/zwave_service_meter.py +192 -0
  70. qolsys_controller/zwave_service_multilevelsensor.py +119 -0
  71. qolsys_controller/zwave_thermometer.py +21 -0
  72. qolsys_controller/zwave_thermostat.py +249 -143
  73. qolsys_controller-0.0.87.dist-info/METADATA +89 -0
  74. qolsys_controller-0.0.87.dist-info/RECORD +77 -0
  75. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/WHEEL +1 -1
  76. qolsys_controller/plugin.py +0 -34
  77. qolsys_controller/plugin_c4.py +0 -17
  78. qolsys_controller/plugin_remote.py +0 -1298
  79. qolsys_controller-0.0.44.dist-info/METADATA +0 -93
  80. qolsys_controller-0.0.44.dist-info/RECORD +0 -68
  81. {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/licenses/LICENSE +0 -0
@@ -1,147 +1,158 @@
1
+ import json
1
2
  import logging
2
3
 
4
+ from qolsys_controller.zwave_service_meter import QolsysZwaveServiceMeter
5
+ from qolsys_controller.zwave_service_multilevelsensor import QolsysZwaveMultilevelSensor, QolsysZwaveServiceMultilevelSensor
6
+
7
+ from .enum_zwave import ZwaveDeviceClass, ZWaveMultilevelSensorScale
3
8
  from .observable import QolsysObservable
4
9
 
5
10
  LOGGER = logging.getLogger(__name__)
6
11
 
7
12
 
8
13
  class QolsysZWaveDevice(QolsysObservable):
9
-
10
- def __init__(self, zwave_dict: dict) -> None:
14
+ def __init__(self, zwave_dict: dict[str, str]) -> None:
11
15
  super().__init__()
12
16
 
13
- self._id = zwave_dict.get("_id")
14
- self._node_id = zwave_dict.get("node_id", "")
15
- self._node_name = zwave_dict.get("node_name", "")
16
- self._node_type = zwave_dict.get("node_type", "")
17
- self._node_status = zwave_dict.get("node_status", "")
18
- self._partition_id = zwave_dict.get("partition_id", "")
19
- self._node_secure_cmd_cls = zwave_dict.get("node_secure_cmd_cls", "")
20
- self._node_battery_level = zwave_dict.get("node_battery_level", "")
21
- self._node_battery_level_value = zwave_dict.get("node_battery_level_value", "")
22
- self._is_node_listening_node = zwave_dict.get("is_node_listening_node", "")
23
- self._basic_report_value = zwave_dict.get("basic_report_value", "")
24
- self._switch_multilevel_report_value = zwave_dict.get("switch_multilevel_report_value", "")
25
- self._basic_device_type = zwave_dict.get("basic_device_type", "")
26
- self._generic_device_type = zwave_dict.get("generic_device_type", "")
27
- self._specific_device_type = zwave_dict.get("specific_device_type", "")
28
- self._num_secure_command_class = zwave_dict.get("num_secure_command_class", "")
29
- self._secure_command_class = zwave_dict.get("secure_command_class", "")
30
- self._manufacture_id = zwave_dict.get("manufacture_id", "")
31
- self._product_type = zwave_dict.get("product_type", "")
32
- self._device_protocol = zwave_dict.get("device_protocol", "")
33
- self._paired_status = zwave_dict.get("paired_status", "")
34
- self._is_device_sleeping = zwave_dict.get("is_device_sleeping", "")
35
- self._is_device_hidden = zwave_dict.get("is_device_hidden", "")
36
- self._last_updated_date = zwave_dict.get("last_updated_date", "")
37
- self._command_class_list = zwave_dict.get("command_class_list", "")
38
-
39
- @property
40
- def node_id(self) -> str:
41
- return self._node_id
42
-
43
- @property
44
- def paired_status(self) -> str:
45
- return self._paired_status
46
-
47
- @property
48
- def node_battery_level(self) -> str:
49
- return self._node_battery_level
17
+ self._id: str = zwave_dict.get("_id", "")
18
+ self._node_id: str = zwave_dict.get("node_id", "")
19
+ self._node_name: str = zwave_dict.get("node_name", "")
20
+ self._node_type: str = zwave_dict.get("node_type", "")
21
+ self._node_status: str = zwave_dict.get("node_status", "")
22
+ self._partition_id: str = zwave_dict.get("partition_id", "")
23
+ self._node_secure_cmd_cls: str = zwave_dict.get("node_secure_cmd_cls", "")
24
+ self._node_battery_level: str = zwave_dict.get("node_battery_level", "")
25
+ self._node_battery_level_value: str = zwave_dict.get("node_battery_level_value", "")
26
+ self._is_node_listening_node: str = zwave_dict.get("is_node_listening_node", "")
27
+ self._basic_report_value: str = zwave_dict.get("basic_report_value", "")
28
+ self._switch_multilevel_report_value: str = zwave_dict.get("switch_multilevel_report_value", "")
29
+ self._basic_device_type: str = zwave_dict.get("basic_device_type", "")
30
+ self._generic_device_type: str = zwave_dict.get("generic_device_type", "")
31
+ self._specific_device_type: str = zwave_dict.get("specific_device_type", "")
32
+ self._num_secure_command_class: str = zwave_dict.get("num_secure_command_class", "")
33
+ self._secure_command_class: str = zwave_dict.get("secure_command_class", "")
34
+ self._manufacture_id: str = zwave_dict.get("manufacture_id", "")
35
+ self._product_type: str = zwave_dict.get("product_type", "")
36
+ self._device_protocol: str = zwave_dict.get("device_protocol", "")
37
+ self._paired_status: str = zwave_dict.get("paired_status", "")
38
+ self._is_device_sleeping: str = zwave_dict.get("is_device_sleeping", "")
39
+ self._is_device_hidden: str = zwave_dict.get("is_device_hidden", "")
40
+ self._last_updated_date: str = zwave_dict.get("last_updated_date", "")
41
+ self._command_class_list: str = zwave_dict.get("command_class_list", "")
42
+ self._meter_capabilities: str = ""
43
+ self._multisensor_capabilities: str = ""
44
+ self._notification_capabilities = zwave_dict.get("notification_capabilities", "")
45
+ self._multi_channel_details = zwave_dict.get("multi_channel_details", "")
50
46
 
51
- @property
52
- def node_battery_level_value(self) -> str:
53
- return self._node_battery_level_value
47
+ # Set Meter and MutilevelSensor Services if available
48
+ self._meter_endpoints: list[QolsysZwaveServiceMeter] = []
49
+ self._multilevelsensor_endpoints: list[QolsysZwaveServiceMultilevelSensor] = []
50
+ self.meter_capabilities = zwave_dict.get("meter_capabilities", "")
51
+ self.multisensor_capabilities = zwave_dict.get("multisensor_capabilities", "")
54
52
 
55
- @property
56
- def node_status(self) -> str:
57
- return self._node_status
58
-
59
- @property
60
- def node_name(self) -> str:
61
- return self._node_name
62
-
63
- @property
64
- def node_type(self) -> str:
65
- return self._node_type
66
-
67
- @property
68
- def partition_id(self) -> str:
69
- return self._partition_id
70
-
71
- def update_base(self, data: dict) -> None: # noqa: C901, PLR0912, PLR0915
53
+ def update_raw(self, payload: bytes) -> None:
54
+ LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
72
55
 
56
+ def update_base(self, data: dict[str, str]) -> None: # noqa: C901, PLR0912, PLR0915
73
57
  # Check if we are updating same node_id
74
58
  node_id_update = data.get("node_id", "")
75
59
  if node_id_update != self._node_id:
76
60
  LOGGER.error(
77
- "Updating ZWave%s (%s) with ZWave%s (different node_id)", self.node_id, self.node_name, node_id_update,
61
+ "Updating ZWave%s (%s) with ZWave%s (different node_id)",
62
+ self.node_id,
63
+ self.node_name,
64
+ node_id_update,
78
65
  )
79
66
  return
80
67
 
81
68
  self.start_batch_update()
82
69
 
83
70
  if "paired_status" in data:
84
- self.paired_status = data.get("paired_status")
71
+ self.paired_status = data.get("paired_status", "")
85
72
  if "node_battery_level" in data:
86
- self.node_battery_level = data.get("node_battery_level")
73
+ self.node_battery_level = data.get("node_battery_level", "")
87
74
  if "node_battery_level_value" in data:
88
- self.node_battery_level_value = data.get("node_battery_level_value")
75
+ self.node_battery_level_value = data.get("node_battery_level_value", "")
89
76
  if "node_status" in data:
90
- self.node_status = data.get("node_status")
77
+ self.node_status = data.get("node_status", "")
91
78
  if "node_name" in data:
92
- self.node_name = data.get("node_name")
79
+ self.node_name = data.get("node_name", "")
93
80
  if "node_type" in data:
94
- self.node_type = data.get("node_type")
81
+ self.node_type = data.get("node_type", "")
95
82
  if "partition_id" in data:
96
- self.partition_id = data.get("partition_id")
83
+ self.partition_id = data.get("partition_id", "")
97
84
  if "node_secure_cmd_cls" in data:
98
- self._node_secure_cmd_cls = data.get("node_secure_cmd_cls")
85
+ self._node_secure_cmd_cls = data.get("node_secure_cmd_cls", "")
99
86
  if "is_node_listening_node" in data:
100
- self._is_node_listening_node = data.get("is_node_listening_node")
87
+ self._is_node_listening_node = data.get("is_node_listening_node", "")
101
88
  if "basic_report_value" in data:
102
- self._basic_report_value = data.get("basic_report_value")
89
+ self._basic_report_value = data.get("basic_report_value", "")
103
90
  if "switch_multilevel_report_value" in data:
104
- self._switch_multilevel_report_value = data.get("switch_multilevel_report_value")
91
+ self._switch_multilevel_report_value = data.get("switch_multilevel_report_value", "")
105
92
  if "basic_device_type" in data:
106
- self._basic_device_type = data.get("basic_device_type")
93
+ self._basic_device_type = data.get("basic_device_type", "")
107
94
  if "generic_device_type" in data:
108
- self._generic_device_type = data.get("generic_device_type")
95
+ self._generic_device_type = data.get("generic_device_type", "")
109
96
  if "specific_device_type" in data:
110
- self._specific_device_type = data.get("specific_device_type")
97
+ self._specific_device_type = data.get("specific_device_type", "")
111
98
  if "num_secure_command_class" in data:
112
- self._num_secure_command_class = data.get("num_secure_command_class")
99
+ self._num_secure_command_class = data.get("num_secure_command_class", "")
113
100
  if "secure_command_class" in data:
114
- self._secure_command_class = data.get("secure_command_class")
101
+ self._secure_command_class = data.get("secure_command_class", "")
115
102
  if "manufacture_id" in data:
116
- self._manufacture_id = data.get("manufacture_id")
103
+ self._manufacture_id = data.get("manufacture_id", "")
117
104
  if "product_type" in data:
118
- self._product_type = data.get("product_type")
105
+ self._product_type = data.get("product_type", "")
119
106
  if "device_protocol" in data:
120
- self._device_protocol = data.get("device_protocol")
107
+ self._device_protocol = data.get("device_protocol", "")
121
108
  if "paired_status" in data:
122
- self.paired_status = data.get("paired_status")
109
+ self.paired_status = data.get("paired_status", "")
123
110
  if "is_device_sleeping" in data:
124
- self._is_device_sleeping = data.get("is_device_sleeping")
111
+ self._is_device_sleeping = data.get("is_device_sleeping", "")
125
112
  if "is_device_hidden" in data:
126
- self._is_device_hidden = data.get("is_device_hidden")
113
+ self._is_device_hidden = data.get("is_device_hidden", "")
127
114
  if "last_updated_date" in data:
128
- self._last_updated_date = data.get("last_updated_date")
115
+ self._last_updated_date = data.get("last_updated_date", "")
129
116
  if "command_class_list" in data:
130
- self._last_updated_date = data.get("command_class_list")
117
+ self._last_updated_date = data.get("command_class_list", "")
118
+ if "multisensor_capabilities" in data:
119
+ self.multisensor_capabilities = data.get("multisensor_capabilities", "")
120
+ if "meter_capabilities" in data:
121
+ self.meter_capabilities = data.get("meter_capabilities", "")
122
+ if "notification_capabilities" in data:
123
+ self._notification_capabilities = data.get("notification_capabilities", "")
124
+ if "multi_channel_details" in data:
125
+ self._multi_channel_details = data.get("multi_channel_details", "")
131
126
 
132
127
  self.end_batch_update()
133
128
 
129
+ # -----------------------------
130
+ # properties + setters
131
+ # -----------------------------
132
+
133
+ @property
134
+ def node_id(self) -> str:
135
+ return self._node_id
136
+
134
137
  @node_id.setter
135
- def node_id(self, value: str) -> str:
138
+ def node_id(self, value: str) -> None:
136
139
  self._node_id = value
137
140
 
141
+ @property
142
+ def paired_status(self) -> str:
143
+ return self._paired_status
144
+
138
145
  @paired_status.setter
139
- def paired_status(self, value: str) -> str:
146
+ def paired_status(self, value: str) -> None:
140
147
  if self._paired_status != value:
141
148
  LOGGER.debug("ZWave%s (%s) - paired_status: %s", self.node_id, self.node_name, value)
142
149
  self._paired_status = value
143
150
  self.notify()
144
151
 
152
+ @property
153
+ def node_battery_level(self) -> str:
154
+ return self._node_battery_level
155
+
145
156
  @node_battery_level.setter
146
157
  def node_battery_level(self, value: str) -> None:
147
158
  if self._node_battery_level != value:
@@ -149,42 +160,168 @@ class QolsysZWaveDevice(QolsysObservable):
149
160
  self._node_battery_level = value
150
161
  self.notify()
151
162
 
163
+ @property
164
+ def meter_capabilities(self) -> str:
165
+ return self._meter_capabilities
166
+
167
+ @meter_capabilities.setter
168
+ def meter_capabilities(self, value: str) -> None:
169
+ if self._meter_capabilities != value:
170
+ self._meter_capabilities = value
171
+
172
+ # Update Meter Service
173
+ try:
174
+ meter_services = json.loads(value)
175
+ for endpoint, service in meter_services.items():
176
+ # Check if we already have this meter service
177
+ meter_endpoint = None
178
+ for meter in self._meter_endpoints:
179
+ if meter.endpoint == endpoint:
180
+ meter_endpoint = meter
181
+ meter_endpoint.update_iq2medi(service)
182
+ break
183
+
184
+ # Create new meter service if not found
185
+ if meter_endpoint is None:
186
+ LOGGER.debug("ZWave%s (%s) - Adding new meter endpoint: %s", self.node_id, self.node_name, endpoint)
187
+ meter_endpoint = QolsysZwaveServiceMeter(self, endpoint, service)
188
+ self._meter_endpoints.append(meter_endpoint)
189
+
190
+ except json.JSONDecodeError:
191
+ LOGGER.error("ZWave%s (%s) - Error parsing meter_capabilities:%s", self.node_id, self.node_name, value)
192
+ return
193
+
194
+ @property
195
+ def multisensor_capabilities(self) -> str:
196
+ return self._multisensor_capabilities
197
+
198
+ @multisensor_capabilities.setter
199
+ def multisensor_capabilities(self, value: str) -> None:
200
+ if self._multisensor_capabilities != value:
201
+ self._multisensor_capabilities = value
202
+
203
+ # Update Multilevel Sensor Service
204
+ try:
205
+ sensor_services = json.loads(value)
206
+ for endpoint, service in sensor_services.items():
207
+ # Check if we already have this meter service
208
+ sensor_endpoint = None
209
+ for sensor in self._multilevelsensor_endpoints:
210
+ if sensor.endpoint == endpoint:
211
+ sensor_endpoint = sensor
212
+ sensor_endpoint.update_iq2medi(service)
213
+ break
214
+
215
+ # Create new meter service if not found
216
+ if sensor_endpoint is None:
217
+ LOGGER.debug(
218
+ "ZWave%s (%s) - Adding new multilevelsensor endpoint: %s", self.node_id, self.node_name, endpoint
219
+ )
220
+ sensor_endpoint = QolsysZwaveServiceMultilevelSensor(self, endpoint, service)
221
+ self.multilevelsensor_endpoints.append(sensor_endpoint)
222
+
223
+ except json.JSONDecodeError:
224
+ LOGGER.error(
225
+ "ZWave%s (%s) - Error parsing multilevelsensor_capabilities:%s", self.node_id, self.node_name, value
226
+ )
227
+ return
228
+
229
+ @property
230
+ def node_battery_level_value(self) -> int | None:
231
+ try:
232
+ value = int(self._node_battery_level_value)
233
+ if value >= 0 and value <= 100:
234
+ return value
235
+ else:
236
+ return None
237
+
238
+ except ValueError:
239
+ return None
240
+
152
241
  @node_battery_level_value.setter
153
- def node_battery_level_value(self, value: str) -> str:
242
+ def node_battery_level_value(self, value: str) -> None:
154
243
  if self._node_battery_level_value != value:
155
244
  LOGGER.debug("ZWave%s (%s) - node_battery_level_value: %s", self.node_id, self.node_name, value)
156
245
  self._node_battery_level_value = value
157
246
  self.notify()
158
247
 
248
+ @property
249
+ def node_status(self) -> str:
250
+ return self._node_status
251
+
159
252
  @node_status.setter
160
- def node_status(self, value: str) -> str:
253
+ def node_status(self, value: str) -> None:
161
254
  if self._node_status != value:
162
255
  LOGGER.debug("ZWave%s (%s) - node_status: %s", self.node_id, self.node_name, value)
163
256
  self._node_status = value
164
257
  self.notify()
165
258
 
259
+ @property
260
+ def node_name(self) -> str:
261
+ return self._node_name
262
+
166
263
  @node_name.setter
167
- def node_name(self, value: str) -> str:
264
+ def node_name(self, value: str) -> None:
168
265
  if self._node_name != value:
169
266
  LOGGER.debug("ZWave%s (%s) - node_name: %s", self.node_id, self.node_name, value)
170
267
  self._node_name = value
171
268
  self.notify()
172
269
 
270
+ @property
271
+ def node_type(self) -> str:
272
+ return self._node_type
273
+
173
274
  @node_type.setter
174
- def node_type(self, value: str) -> str:
275
+ def node_type(self, value: str) -> None:
175
276
  if self._node_type != value:
176
277
  LOGGER.debug("ZWave%s (%s) - node_type: %s", self.node_id, self.node_name, value)
177
278
  self._node_type = value
178
279
  self.notify()
179
280
 
281
+ @property
282
+ def partition_id(self) -> str:
283
+ return self._partition_id
284
+
180
285
  @partition_id.setter
181
- def partition_id(self, value: str) -> str:
286
+ def partition_id(self, value: str) -> None:
182
287
  if self._partition_id != value:
183
288
  LOGGER.debug("ZWave%s (%s) - partition_id: %s", self._node_id, self._node_name, value)
184
289
  self._partition_id = value
185
290
  self.notify()
186
291
 
187
- def to_dict_base(self) -> dict:
292
+ @property
293
+ def meter_endpoints(self) -> list[QolsysZwaveServiceMeter]:
294
+ return self._meter_endpoints
295
+
296
+ @property
297
+ def multilevelsensor_endpoints(self) -> list[QolsysZwaveServiceMultilevelSensor]:
298
+ return self._multilevelsensor_endpoints
299
+
300
+ @property
301
+ def generic_device_type(self) -> ZwaveDeviceClass:
302
+ try:
303
+ return ZwaveDeviceClass(int(self._generic_device_type))
304
+ except ValueError:
305
+ return ZwaveDeviceClass.Unknown
306
+
307
+ def is_battery_enabled(self) -> bool:
308
+ return self.node_battery_level_value is not None
309
+
310
+ def is_service_meter_enabled(self) -> bool:
311
+ return self._meter_endpoints != []
312
+
313
+ def is_service_multilevelsensor_enabled(self) -> bool:
314
+ return self._multilevelsensor_endpoints != []
315
+
316
+ def multilevelsensor_value(self, scale: ZWaveMultilevelSensorScale) -> list[QolsysZwaveMultilevelSensor]:
317
+ result: list[QolsysZwaveMultilevelSensor] = []
318
+ for endpoint in self.multilevelsensor_endpoints:
319
+ sensor = endpoint.get_sensor(scale)
320
+ if sensor is not None:
321
+ result.append(sensor)
322
+ return result
323
+
324
+ def to_dict_base(self) -> dict[str, str]:
188
325
  return {
189
326
  "_id": self._id,
190
327
  "node_id": self.node_id,
@@ -193,7 +330,7 @@ class QolsysZWaveDevice(QolsysObservable):
193
330
  "node_status": self.node_status,
194
331
  "partition_id": self._partition_id,
195
332
  "node_battery_level": self.node_battery_level,
196
- "node_battery_level_value": self.node_battery_level_value,
333
+ "node_battery_level_value": self._node_battery_level_value,
197
334
  "paired_status": self.paired_status,
198
335
  "node_secure_cmd_cls": self._node_secure_cmd_cls,
199
336
  "is_node_listening_node": self._is_node_listening_node,
@@ -211,4 +348,8 @@ class QolsysZWaveDevice(QolsysObservable):
211
348
  "is_device_hidden": self._is_device_hidden,
212
349
  "last_updated_date": self._last_updated_date,
213
350
  "command_class_list": self._command_class_list,
351
+ "multisensor_capabilities": self.multisensor_capabilities,
352
+ "meter_capabilities": self.meter_capabilities,
353
+ "notification_capabilities": self._notification_capabilities,
354
+ "multi_channel_details": self._multi_channel_details,
214
355
  }
@@ -6,26 +6,31 @@ LOGGER = logging.getLogger(__name__)
6
6
 
7
7
 
8
8
  class QolsysDimmer(QolsysZWaveDevice):
9
+ def __init__(self, dimmer_dict: dict[str, str], zwave_dict: dict[str, str]) -> None:
10
+ super().__init__(zwave_dict)
9
11
 
10
- def __init__(self, dimmer_dict: dict, zwave_dict: dict) -> None:
12
+ self._dimmer_id: str = dimmer_dict.get("_id", "")
13
+ self._dimmer_version: str = dimmer_dict.get("version", "")
14
+ self._dimmer_opr: str = dimmer_dict.get("opr", "")
15
+ self._dimmer_partition_id: str = dimmer_dict.get("partition_id", "")
16
+ self._dimmer_name: str = dimmer_dict.get("dimmer_name", "")
17
+ self._dimmer_status: str = dimmer_dict.get("status", "")
18
+ self._dimmer_level: str = dimmer_dict.get("level", "")
19
+ self._dimmer_node_id: str = dimmer_dict.get("node_id", "")
20
+ self._dimmer_created_by: str = dimmer_dict.get("created_by", "")
21
+ self._dimmer_created_date: str = dimmer_dict.get("created_date", "")
22
+ self._dimmer_updated_by: str = dimmer_dict.get("updated_by", "")
23
+ self._dimmer_last_updated_date: str = dimmer_dict.get("last_updated_date", "")
24
+ self._dimmer_endpoint: str = dimmer_dict.get("endpoint", "")
25
+ self._dimmer_power_details: str = dimmer_dict.get("power_details", "")
26
+ self._dimmer_paired_status: str = dimmer_dict.get("paired_status", "")
11
27
 
12
- super().__init__(zwave_dict)
28
+ def is_on(self) -> bool:
29
+ return self.dimmer_status == "On"
13
30
 
14
- self._dimmer_id = dimmer_dict.get("_id")
15
- self._dimmer_version = dimmer_dict.get("version", "")
16
- self._dimmer_opr = dimmer_dict.get("opr", "")
17
- self._dimmer_partition_id = dimmer_dict.get("partition_id", "")
18
- self._dimmer_name = dimmer_dict.get("dimmer_name", "")
19
- self._dimmer_status = dimmer_dict.get("status", "")
20
- self._dimmer_level = dimmer_dict.get("level", "")
21
- self._dimmer_node_id = dimmer_dict.get("node_id", "")
22
- self._dimmer_created_by = dimmer_dict.get("created_by", "")
23
- self._dimmer_created_date = dimmer_dict.get("created_date", "")
24
- self._dimmer_updated_by = dimmer_dict.get("updated_by", "")
25
- self._dimmer_last_updated_date = dimmer_dict.get("last_updated_date", "")
26
- self._dimmer_endpoint = dimmer_dict.get("endpoint", "")
27
- self._dimmer_power_details = dimmer_dict.get("power_details", "")
28
- self._dimmer_paired_status = dimmer_dict.get("paired_status", "")
31
+ # -----------------------------
32
+ # properties + setters
33
+ # -----------------------------
29
34
 
30
35
  @property
31
36
  def dimmer_node_id(self) -> str:
@@ -35,10 +40,24 @@ class QolsysDimmer(QolsysZWaveDevice):
35
40
  def dimmer_status(self) -> str:
36
41
  return self._dimmer_status
37
42
 
43
+ @dimmer_status.setter
44
+ def dimmer_status(self, value: str) -> None:
45
+ if self._dimmer_status != value:
46
+ LOGGER.debug("Dimmer%s (%s) - status: %s", self.node_id, self.dimmer_name, value)
47
+ self._dimmer_status = value
48
+ self.notify()
49
+
38
50
  @property
39
51
  def dimmer_name(self) -> str:
40
52
  return self._dimmer_name
41
53
 
54
+ @dimmer_name.setter
55
+ def dimmer_name(self, value: str) -> None:
56
+ if self._dimmer_name != value:
57
+ LOGGER.debug("Dimmer%s (%s) - name: %s", self.node_id, self.dimmer_name, value)
58
+ self._dimmer_name = value
59
+ self.notify()
60
+
42
61
  @property
43
62
  def dimmer_level(self) -> str:
44
63
  return self._dimmer_level
@@ -50,63 +69,50 @@ class QolsysDimmer(QolsysZWaveDevice):
50
69
  self._dimmer_level = value
51
70
  self.notify()
52
71
 
53
- @dimmer_status.setter
54
- def dimmer_status(self, value: str) -> None:
55
- if self._dimmer_status != value:
56
- LOGGER.debug("Dimmer%s (%s) - status: %s", self.node_id, self.dimmer_name, value)
57
- self._dimmer_status = value
58
- self.notify()
59
-
60
- @dimmer_name.setter
61
- def dimmer_name(self, value: str) -> None:
62
- if self._dimmer_name != value:
63
- LOGGER.debug("Dimmer%s (%s) - name: %s", self.node_id, self.dimmer_name, value)
64
- self._dimmer_name = value
65
- self.notify()
66
-
67
- def is_on(self) -> bool:
68
- return self.dimmer_status == "On"
72
+ def update_raw(self, payload: bytes) -> None:
73
+ pass
69
74
 
70
- def update_dimmer(self, content_values: dict) -> None: # noqa: C901
75
+ def update_dimmer(self, content_values: dict[str, str]) -> None: # noqa: PLR0912
71
76
  # Check if we are updating same none_id
72
77
  node_id_update = content_values.get("node_id", "")
73
78
  if node_id_update != self._dimmer_node_id:
74
79
  LOGGER.error(
75
- "Updating Dimmer %s (%s) with dimmer %s (different id)", self._node_id, self.dimmer_name, node_id_update)
80
+ "Updating Dimmer %s (%s) with dimmer %s (different id)", self._node_id, self.dimmer_name, node_id_update
81
+ )
76
82
  return
77
83
 
78
84
  self.start_batch_update()
79
85
 
80
86
  if "status" in content_values:
81
- self.dimmer_status = content_values.get("status")
87
+ self.dimmer_status = content_values.get("status", "")
82
88
  if "level" in content_values:
83
- self.dimmer_level = content_values.get("level")
89
+ self.dimmer_level = content_values.get("level", "")
84
90
  if "dimmer_name" in content_values:
85
- self.dimmer_name = content_values.get("dimmer_name")
91
+ self.dimmer_name = content_values.get("dimmer_name", "")
86
92
  if "created_by" in content_values:
87
- self._dimmer_created_by = content_values.get("created_by")
93
+ self._dimmer_created_by = content_values.get("created_by", "")
88
94
  if "created_date" in content_values:
89
- self._dimmer_created_date = content_values.get("created_date")
95
+ self._dimmer_created_date = content_values.get("created_date", "")
90
96
  if "version" in content_values:
91
- self._dimmer_version = content_values.get("version")
97
+ self._dimmer_version = content_values.get("version", "")
92
98
  if "opr" in content_values:
93
- self._dimmer_opr = content_values.get("opr")
99
+ self._dimmer_opr = content_values.get("opr", "")
94
100
  if "partition_id" in content_values:
95
- self.partition_id = content_values.get("partition_id")
101
+ self.partition_id = content_values.get("partition_id", "")
96
102
  if "updated_by" in content_values:
97
- self._dimmer_updated_by = content_values.get("updated_by")
103
+ self._dimmer_updated_by = content_values.get("updated_by", "")
98
104
  if "last_updated_date" in content_values:
99
- self._last_updated_date = content_values.get("last_updated_date")
105
+ self._last_updated_date = content_values.get("last_updated_date", "")
100
106
  if "endpoint" in content_values:
101
- self._dimmer_endpoint = content_values.get("endpoint")
107
+ self._dimmer_endpoint = content_values.get("endpoint", "")
102
108
  if "power_details" in content_values:
103
- self._dimmer_power_details = content_values.get("power_details")
109
+ self._dimmer_power_details = content_values.get("power_details", "")
104
110
  if "paired_status" in content_values:
105
- self._dimmer_paired_status = content_values.get("paired_status")
111
+ self._dimmer_paired_status = content_values.get("paired_status", "")
106
112
 
107
113
  self.end_batch_update()
108
114
 
109
- def to_dict_dimmer(self) -> dict:
115
+ def to_dict_dimmer(self) -> dict[str, str]:
110
116
  return {
111
117
  "_id": self._dimmer_id,
112
118
  "version": self._dimmer_version,
@@ -0,0 +1,15 @@
1
+ import logging
2
+
3
+ from .zwave_device import QolsysZWaveDevice
4
+
5
+ LOGGER = logging.getLogger(__name__)
6
+
7
+
8
+ class QolsysEnergyClamp(QolsysZWaveDevice):
9
+ def __init__(self, zwave_dict: dict[str, str]) -> None:
10
+ super().__init__(zwave_dict)
11
+
12
+ # Energy clamp only enables meter seter in base zwave_device class
13
+
14
+ def update_raw(self, payload: bytes) -> None:
15
+ pass
@@ -6,6 +6,8 @@ LOGGER = logging.getLogger(__name__)
6
6
 
7
7
 
8
8
  class QolsysGarageDoor(QolsysZWaveDevice):
9
-
10
9
  def __init__(self) -> None:
11
10
  pass
11
+
12
+ def update_raw(self, payload: bytes) -> None:
13
+ LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
@@ -1,11 +1,13 @@
1
1
  import logging
2
2
 
3
- from qolsys_controller.zwave_device import QolsysZWaveDevice
3
+ from .zwave_device import QolsysZWaveDevice
4
4
 
5
5
  LOGGER = logging.getLogger(__name__)
6
6
 
7
7
 
8
8
  class QolsysGeneric(QolsysZWaveDevice):
9
-
10
- def __init__(self, zwave_dict: dict) -> None:
9
+ def __init__(self, zwave_dict: dict[str, str]) -> None:
11
10
  super().__init__(zwave_dict)
11
+
12
+ def update_raw(self, payload: bytes) -> None:
13
+ LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())