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
@@ -3,6 +3,12 @@ from __future__ import annotations
3
3
  import logging
4
4
  from typing import TYPE_CHECKING
5
5
 
6
+ from qolsys_controller.adc_service import QolsysAdcService
7
+ from qolsys_controller.adc_service_garagedoor import QolsysAdcGarageDoorService
8
+ from qolsys_controller.zwave_energy_clamp import QolsysEnergyClamp
9
+ from qolsys_controller.zwave_thermometer import QolsysThermometer
10
+
11
+ from .adc_device import QolsysAdcDevice
6
12
  from .observable import QolsysObservable
7
13
  from .weather import QolsysWeather
8
14
  from .zwave_device import QolsysZWaveDevice
@@ -28,11 +34,14 @@ class QolsysState(QolsysObservable):
28
34
  self._weather: QolsysWeather = QolsysWeather()
29
35
  self._partitions: list[QolsysPartition] = []
30
36
  self._zones: list[QolsysZone] = []
37
+ self._adc_devices: list[QolsysAdcDevice] = []
31
38
  self._zwave_devices: list[QolsysZWaveDevice] = []
32
39
  self._scenes: list[QolsysScene] = []
40
+
33
41
  self._state_partition_observer = QolsysObservable()
34
42
  self._state_zone_observer = QolsysObservable()
35
43
  self._state_zwave_observer = QolsysObservable()
44
+ self._state_adc_observer = QolsysObservable()
36
45
  self._state_scene_observer = QolsysObservable()
37
46
 
38
47
  @property
@@ -43,6 +52,10 @@ class QolsysState(QolsysObservable):
43
52
  def zwave_devices(self) -> list[QolsysZWaveDevice]:
44
53
  return self._zwave_devices
45
54
 
55
+ @property
56
+ def adc_devices(self) -> list[QolsysAdcDevice]:
57
+ return self._adc_devices
58
+
46
59
  @property
47
60
  def zones(self) -> list[QolsysZone]:
48
61
  return self._zones
@@ -79,9 +92,28 @@ class QolsysState(QolsysObservable):
79
92
  for device in self.zwave_devices:
80
93
  if isinstance(device, QolsysThermostat):
81
94
  thermostats.append(device)
82
-
83
95
  return thermostats
84
96
 
97
+ @property
98
+ def zwave_meters(self) -> list[QolsysEnergyClamp]:
99
+ meters = []
100
+ for device in self.zwave_devices:
101
+ if isinstance(device, QolsysEnergyClamp):
102
+ meters.append(device)
103
+ return meters
104
+
105
+ @property
106
+ def zwave_thermometers(self) -> list[QolsysThermometer]:
107
+ thermometer = []
108
+ for device in self.zwave_devices:
109
+ if isinstance(device, QolsysThermometer):
110
+ thermometer.append(device)
111
+ return thermometer
112
+
113
+ @property
114
+ def zwave_other_devices(self) -> list[dict[str, str]]:
115
+ return self._controller.panel.db.get_zwave_other_devices()
116
+
85
117
  @property
86
118
  def state_partition_observer(self) -> QolsysObservable:
87
119
  return self._state_partition_observer
@@ -98,6 +130,10 @@ class QolsysState(QolsysObservable):
98
130
  def state_scene_observer(self) -> QolsysObservable:
99
131
  return self._state_scene_observer
100
132
 
133
+ @property
134
+ def state_adc_observer(self) -> QolsysObservable:
135
+ return self._state_adc_observer
136
+
101
137
  def partition(self, partition_id: str) -> QolsysPartition | None:
102
138
  for partition in self.partitions:
103
139
  if partition.id == partition_id:
@@ -195,7 +231,12 @@ class QolsysState(QolsysObservable):
195
231
  for zwave_device in self.zwave_devices:
196
232
  if zwave_device.node_id == node_id:
197
233
  return zwave_device
234
+ return None
198
235
 
236
+ def zwave_thermostat(self, node_id: str) -> QolsysThermostat | None:
237
+ thermostat = self.zwave_device(node_id)
238
+ if isinstance(thermostat, QolsysThermostat):
239
+ return thermostat
199
240
  return None
200
241
 
201
242
  def zwave_add(self, new_zwave: QolsysZWaveDevice) -> None:
@@ -220,6 +261,61 @@ class QolsysState(QolsysObservable):
220
261
  self.zwave_devices.remove(zwave)
221
262
  self.state_zwave_observer.notify()
222
263
 
264
+ def adc_device(self, device_id: str) -> QolsysAdcDevice | None:
265
+ for adc_device in self.adc_devices:
266
+ if adc_device.device_id == device_id:
267
+ return adc_device
268
+ return None
269
+
270
+ def adc_add(self, new_adc: QolsysAdcDevice) -> None:
271
+ for adc_device in self.adc_devices:
272
+ if new_adc.device_id == adc_device.device_id:
273
+ LOGGER.debug("Adding ADC to State, ADC%s (%s) - Allready in ADC List", new_adc.device_id, new_adc.name)
274
+ return
275
+
276
+ self.adc_devices.append(new_adc)
277
+ self.adc_devices.sort(key=lambda x: x.device_id, reverse=False)
278
+ self.state_adc_observer.notify()
279
+
280
+ def adc_delete(self, device_id: str) -> None:
281
+ adc = self.adc_device(device_id)
282
+
283
+ if adc is None:
284
+ LOGGER.debug("Deleting ADC from State, ADC%s not found", device_id)
285
+ return
286
+
287
+ self.adc_devices.remove(adc)
288
+ self.state_adc_observer.notify()
289
+
290
+ def sync_adc_devices_data(self, db_adcs: list[QolsysAdcDevice]) -> None:
291
+ db_adc_list = []
292
+ for db_adc in db_adcs:
293
+ db_adc_list.append(db_adc.device_id)
294
+
295
+ state_adc_list = []
296
+ for state_adc in self.adc_devices:
297
+ state_adc_list.append(state_adc.device_id)
298
+
299
+ # Update existing ADC devices
300
+ for state_adc in self.adc_devices:
301
+ if state_adc.device_id in db_adc_list:
302
+ for db_adc in db_adcs:
303
+ if state_adc.device_id == db_adc.device_id:
304
+ LOGGER.debug("sync_data - update ADC%s", state_adc.device_id)
305
+ state_adc.update_adc_device(db_adc.to_dict_adc())
306
+
307
+ # Add new ADC devices
308
+ for db_adc in db_adcs:
309
+ if db_adc.device_id not in state_adc_list:
310
+ LOGGER.debug("sync_data - add ADC%s", db_adc.device_id)
311
+ self.adc_add(db_adc)
312
+
313
+ # Delete ADC device
314
+ for state_adc in self.adc_devices:
315
+ if state_adc.device_id not in db_adc_list:
316
+ LOGGER.debug("sync_data - delete ADC%s", state_adc.device_id)
317
+ self.adc_delete(state_adc.device_id)
318
+
223
319
  def sync_zwave_devices_data(self, db_zwaves: list[QolsysZWaveDevice]) -> None: # noqa: PLR0912
224
320
  db_zwave_list = []
225
321
  for db_zwave in db_zwaves:
@@ -254,6 +350,11 @@ class QolsysState(QolsysObservable):
254
350
  state_zwave.update_lock(db_zwave.to_dict_lock())
255
351
  break
256
352
 
353
+ # Update Energy Clamp
354
+ if isinstance(state_zwave, QolsysEnergyClamp) and isinstance(db_zwave, QolsysEnergyClamp):
355
+ state_zwave.update_base(db_zwave.to_dict_base())
356
+ break
357
+
257
358
  # Generic Z-Wave Device
258
359
  if isinstance(state_zwave, QolsysGeneric) and isinstance(db_zwave, QolsysGeneric):
259
360
  state_zwave.update_base(db_zwave.to_dict_base())
@@ -370,6 +471,29 @@ class QolsysState(QolsysObservable):
370
471
  def dump(self) -> None: # noqa: PLR0912, PLR0915
371
472
  LOGGER.debug("*** Device Information ***")
372
473
 
474
+ def dump_meter(self: QolsysState, device: QolsysZWaveDevice) -> None:
475
+ for endpoint in device.meter_endpoints:
476
+ for meter_sensor in endpoint.sensors:
477
+ LOGGER.debug(
478
+ " Meter%s Endpoint%s - %s - value: %.2f (%s)",
479
+ device.node_id,
480
+ endpoint.endpoint,
481
+ endpoint._meter_type.name,
482
+ meter_sensor.value,
483
+ meter_sensor.scale.name,
484
+ )
485
+
486
+ def dump_multilevelsensor(self: QolsysState, device: QolsysZWaveDevice) -> None:
487
+ for endpoint in device.multilevelsensor_endpoints:
488
+ for sensor in endpoint.sensors:
489
+ LOGGER.debug(
490
+ " Multilevelsensor%s Endpoint%s - value: %.2f (%s)",
491
+ device.node_id,
492
+ endpoint.endpoint,
493
+ sensor.value,
494
+ sensor.unit.name,
495
+ )
496
+
373
497
  for partition in self.partitions:
374
498
  pid = partition.id
375
499
  name = partition.name
@@ -410,6 +534,8 @@ class QolsysState(QolsysObservable):
410
534
  LOGGER.debug("Dimmer%s (%s) - node_status: %s", nid, name, zwave.node_status)
411
535
  LOGGER.debug("Dimmer%s (%s) - battery_level: %s", nid, name, zwave.node_battery_level)
412
536
  LOGGER.debug("Dimmer%s (%s) - battery_level_value: %s", nid, name, zwave.node_battery_level_value)
537
+ dump_meter(self, zwave)
538
+ dump_multilevelsensor(self, zwave)
413
539
  continue
414
540
 
415
541
  if isinstance(zwave, QolsysThermostat):
@@ -422,12 +548,32 @@ class QolsysState(QolsysObservable):
422
548
  LOGGER.debug("Thermostat%s (%s) - target_cool_temp: %s", zid, name, zwave.thermostat_target_cool_temp)
423
549
  LOGGER.debug("Thermostat%s (%s) - target_heat_temp: %s", zid, name, zwave.thermostat_target_heat_temp)
424
550
  LOGGER.debug("Thermostat%s (%s) - set_point_mode: %s", zid, name, zwave.thermostat_set_point_mode)
551
+ dump_meter(self, zwave)
552
+ dump_multilevelsensor(self, zwave)
425
553
  continue
426
554
 
427
555
  if isinstance(zwave, QolsysLock):
428
556
  zid = zwave.lock_node_id
429
557
  name = zwave.lock_name
430
558
  LOGGER.debug("Lock%s (%s) - lock_status: %s", zid, name, zwave.lock_status)
559
+ dump_meter(self, zwave)
560
+ dump_multilevelsensor(self, zwave)
561
+ continue
562
+
563
+ if isinstance(zwave, QolsysEnergyClamp):
564
+ nid = zwave.node_id
565
+ name = zwave.node_name
566
+ LOGGER.debug("EnergyClamp%s (%s)", nid, name)
567
+ dump_meter(self, zwave)
568
+ dump_multilevelsensor(self, zwave)
569
+ continue
570
+
571
+ if isinstance(zwave, QolsysThermometer):
572
+ nid = zwave.node_id
573
+ name = zwave.node_name
574
+ LOGGER.debug("Thermometer%s (%s)", nid, name)
575
+ dump_meter(self, zwave)
576
+ dump_multilevelsensor(self, zwave)
431
577
  continue
432
578
 
433
579
  if isinstance(zwave, QolsysGeneric):
@@ -437,8 +583,24 @@ class QolsysState(QolsysObservable):
437
583
  LOGGER.debug("Generic%s (%s) - status: %s", zid, name, zwave.node_status)
438
584
  LOGGER.debug("Generic%s (%s) - battery_level: %s", zid, name, zwave.node_battery_level)
439
585
  LOGGER.debug("Generic%s (%s) - battery_level_vale: %s", zid, name, zwave.node_battery_level_value)
586
+ dump_meter(self, zwave)
587
+ dump_multilevelsensor(self, zwave)
440
588
  continue
441
589
 
590
+ LOGGER.debug("Other Z-Wave devices information")
591
+ LOGGER.debug(self.zwave_other_devices)
592
+
593
+ for adc in self.adc_devices:
594
+ for service in adc.services:
595
+ if isinstance(service, QolsysAdcGarageDoorService):
596
+ LOGGER.debug(
597
+ "ADC%s GarageDoor%s (%s) - state: %s", adc.device_id, service.id, adc.name, service.func_state
598
+ )
599
+ continue
600
+
601
+ if isinstance(service, QolsysAdcService):
602
+ LOGGER.debug("ADC%s Service%s (%s) - state: %s", adc.device_id, service.id, adc.name, service.func_state)
603
+
442
604
  for scene in self.scenes:
443
605
  sid = scene.scene_id
444
606
  name = scene.name
@@ -20,10 +20,11 @@ class QolsysTaskManager:
20
20
  except asyncio.CancelledError:
21
21
  LOGGER.debug("Task Cancelled: %s", task.get_name())
22
22
 
23
- except Exception as e: # noqa: BLE001
24
- LOGGER.debug("[Callback] Task failed with: %s", e)
23
+ except Exception: # noqa: BLE001
24
+ LOGGER.exception("[Callback] Task failed: %s", task.get_name())
25
25
 
26
- self._tasks.discard(task)
26
+ finally:
27
+ self._tasks.discard(task)
27
28
 
28
29
  task.add_done_callback(_done_callback)
29
30
  return task
qolsys_controller/zone.py CHANGED
@@ -391,7 +391,8 @@ class QolsysZone(QolsysObservable):
391
391
  @property
392
392
  def powerg_temperature(self) -> float | None:
393
393
  try:
394
- return float(self._powerg_temperature)
394
+ temp = float(self._powerg_temperature)
395
+ return round(temp, 1)
395
396
  except ValueError:
396
397
  return None
397
398
 
@@ -1,6 +1,10 @@
1
+ import json
1
2
  import logging
2
3
 
3
- from .enum_zwave import ZwaveDeviceClass
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
4
8
  from .observable import QolsysObservable
5
9
 
6
10
  LOGGER = logging.getLogger(__name__)
@@ -35,6 +39,19 @@ class QolsysZWaveDevice(QolsysObservable):
35
39
  self._is_device_hidden: str = zwave_dict.get("is_device_hidden", "")
36
40
  self._last_updated_date: str = zwave_dict.get("last_updated_date", "")
37
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", "")
46
+
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", "")
52
+
53
+ def update_raw(self, payload: bytes) -> None:
54
+ LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
38
55
 
39
56
  def update_base(self, data: dict[str, str]) -> None: # noqa: C901, PLR0912, PLR0915
40
57
  # Check if we are updating same node_id
@@ -98,6 +115,14 @@ class QolsysZWaveDevice(QolsysObservable):
98
115
  self._last_updated_date = data.get("last_updated_date", "")
99
116
  if "command_class_list" in data:
100
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", "")
101
126
 
102
127
  self.end_batch_update()
103
128
 
@@ -136,8 +161,82 @@ class QolsysZWaveDevice(QolsysObservable):
136
161
  self.notify()
137
162
 
138
163
  @property
139
- def node_battery_level_value(self) -> str:
140
- return self._node_battery_level_value
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
141
240
 
142
241
  @node_battery_level_value.setter
143
242
  def node_battery_level_value(self, value: str) -> None:
@@ -190,6 +289,14 @@ class QolsysZWaveDevice(QolsysObservable):
190
289
  self._partition_id = value
191
290
  self.notify()
192
291
 
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
+
193
300
  @property
194
301
  def generic_device_type(self) -> ZwaveDeviceClass:
195
302
  try:
@@ -197,6 +304,23 @@ class QolsysZWaveDevice(QolsysObservable):
197
304
  except ValueError:
198
305
  return ZwaveDeviceClass.Unknown
199
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
+
200
324
  def to_dict_base(self) -> dict[str, str]:
201
325
  return {
202
326
  "_id": self._id,
@@ -206,7 +330,7 @@ class QolsysZWaveDevice(QolsysObservable):
206
330
  "node_status": self.node_status,
207
331
  "partition_id": self._partition_id,
208
332
  "node_battery_level": self.node_battery_level,
209
- "node_battery_level_value": self.node_battery_level_value,
333
+ "node_battery_level_value": self._node_battery_level_value,
210
334
  "paired_status": self.paired_status,
211
335
  "node_secure_cmd_cls": self._node_secure_cmd_cls,
212
336
  "is_node_listening_node": self._is_node_listening_node,
@@ -224,4 +348,8 @@ class QolsysZWaveDevice(QolsysObservable):
224
348
  "is_device_hidden": self._is_device_hidden,
225
349
  "last_updated_date": self._last_updated_date,
226
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,
227
355
  }
@@ -69,6 +69,9 @@ class QolsysDimmer(QolsysZWaveDevice):
69
69
  self._dimmer_level = value
70
70
  self.notify()
71
71
 
72
+ def update_raw(self, payload: bytes) -> None:
73
+ pass
74
+
72
75
  def update_dimmer(self, content_values: dict[str, str]) -> None: # noqa: PLR0912
73
76
  # Check if we are updating same none_id
74
77
  node_id_update = content_values.get("node_id", "")
@@ -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
@@ -8,3 +8,6 @@ LOGGER = logging.getLogger(__name__)
8
8
  class QolsysGarageDoor(QolsysZWaveDevice):
9
9
  def __init__(self) -> None:
10
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())
@@ -8,3 +8,6 @@ LOGGER = logging.getLogger(__name__)
8
8
  class QolsysGeneric(QolsysZWaveDevice):
9
9
  def __init__(self, zwave_dict: dict[str, str]) -> None:
10
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())
@@ -69,6 +69,9 @@ class QolsysLock(QolsysZWaveDevice):
69
69
  self._lock_paired_status = value
70
70
  self.notify()
71
71
 
72
+ def update_raw(self, payload: bytes) -> None:
73
+ pass
74
+
72
75
  def update_lock(self, data: dict[str, str]) -> None: # noqa: PLR0912
73
76
  # Check if we are updating same zoneid
74
77
  node_id_update = data.get("node_id", "")
@@ -118,6 +121,7 @@ class QolsysLock(QolsysZWaveDevice):
118
121
  "opr": self._lock_opr,
119
122
  "partition_id": self._lock_partition_id,
120
123
  "doorlock_name": self.lock_name,
124
+ "node_id": self.lock_node_id,
121
125
  "status": self.lock_status,
122
126
  "created_by": self._lock_created_by,
123
127
  "created_date": self._lock_created_date,
@@ -8,3 +8,6 @@ LOGGER = logging.getLogger(__name__)
8
8
  class QolsysOutlet(QolsysZWaveDevice):
9
9
  def __init__(self) -> None:
10
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())