qolsys-controller 0.0.38__py3-none-any.whl → 0.0.62__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 (73) hide show
  1. qolsys_controller/controller.py +829 -20
  2. qolsys_controller/database/db.py +63 -25
  3. qolsys_controller/database/table.py +89 -60
  4. qolsys_controller/database/table_alarmedsensor.py +0 -2
  5. qolsys_controller/database/table_automation.py +0 -1
  6. qolsys_controller/database/table_country_locale.py +0 -1
  7. qolsys_controller/database/table_dashboard_msgs.py +1 -2
  8. qolsys_controller/database/table_dimmerlight.py +0 -1
  9. qolsys_controller/database/table_doorlock.py +1 -1
  10. qolsys_controller/database/table_eu_event.py +12 -4
  11. qolsys_controller/database/table_heat_map.py +0 -2
  12. qolsys_controller/database/table_history.py +4 -1
  13. qolsys_controller/database/table_iqremotesettings.py +0 -2
  14. qolsys_controller/database/table_iqrouter_network_config.py +0 -1
  15. qolsys_controller/database/table_iqrouter_user_device.py +0 -2
  16. qolsys_controller/database/table_master_slave.py +0 -1
  17. qolsys_controller/database/table_nest_device.py +0 -1
  18. qolsys_controller/database/table_output_rules.py +0 -1
  19. qolsys_controller/database/table_partition.py +0 -1
  20. qolsys_controller/database/table_pgm_outputs.py +0 -2
  21. qolsys_controller/database/table_powerg_device.py +25 -3
  22. qolsys_controller/database/table_qolsyssettings.py +0 -2
  23. qolsys_controller/database/table_scene.py +0 -2
  24. qolsys_controller/database/table_sensor.py +3 -2
  25. qolsys_controller/database/table_sensor_group.py +23 -0
  26. qolsys_controller/database/table_shades.py +0 -2
  27. qolsys_controller/database/table_smartsocket.py +0 -2
  28. qolsys_controller/database/table_state.py +0 -1
  29. qolsys_controller/database/table_tcc.py +0 -1
  30. qolsys_controller/database/table_thermostat.py +0 -1
  31. qolsys_controller/database/table_trouble_conditions.py +0 -2
  32. qolsys_controller/database/table_user.py +1 -2
  33. qolsys_controller/database/table_virtual_device.py +0 -2
  34. qolsys_controller/database/table_weather.py +0 -2
  35. qolsys_controller/database/table_zigbee_device.py +0 -1
  36. qolsys_controller/database/table_zwave_association_group.py +0 -1
  37. qolsys_controller/database/table_zwave_history.py +0 -1
  38. qolsys_controller/database/table_zwave_node.py +1 -1
  39. qolsys_controller/database/table_zwave_other.py +14 -2
  40. qolsys_controller/enum.py +44 -16
  41. qolsys_controller/enum_zwave.py +81 -36
  42. qolsys_controller/errors.py +9 -12
  43. qolsys_controller/mdns.py +7 -4
  44. qolsys_controller/mqtt_command.py +119 -0
  45. qolsys_controller/mqtt_command_queue.py +5 -4
  46. qolsys_controller/observable.py +2 -2
  47. qolsys_controller/panel.py +224 -143
  48. qolsys_controller/partition.py +129 -127
  49. qolsys_controller/pki.py +69 -97
  50. qolsys_controller/scene.py +30 -28
  51. qolsys_controller/settings.py +96 -50
  52. qolsys_controller/state.py +71 -33
  53. qolsys_controller/task_manager.py +8 -12
  54. qolsys_controller/users.py +25 -0
  55. qolsys_controller/utils_mqtt.py +8 -16
  56. qolsys_controller/weather.py +71 -0
  57. qolsys_controller/zone.py +307 -169
  58. qolsys_controller/zwave_device.py +108 -95
  59. qolsys_controller/zwave_dimmer.py +53 -50
  60. qolsys_controller/zwave_garagedoor.py +0 -1
  61. qolsys_controller/zwave_generic.py +2 -3
  62. qolsys_controller/zwave_lock.py +47 -44
  63. qolsys_controller/zwave_outlet.py +0 -1
  64. qolsys_controller/zwave_thermostat.py +112 -118
  65. qolsys_controller-0.0.62.dist-info/METADATA +89 -0
  66. qolsys_controller-0.0.62.dist-info/RECORD +69 -0
  67. {qolsys_controller-0.0.38.dist-info → qolsys_controller-0.0.62.dist-info}/WHEEL +1 -1
  68. qolsys_controller/plugin.py +0 -34
  69. qolsys_controller/plugin_c4.py +0 -17
  70. qolsys_controller/plugin_remote.py +0 -1298
  71. qolsys_controller-0.0.38.dist-info/METADATA +0 -93
  72. qolsys_controller-0.0.38.dist-info/RECORD +0 -68
  73. {qolsys_controller-0.0.38.dist-info → qolsys_controller-0.0.62.dist-info}/licenses/LICENSE +0 -0
qolsys_controller/zone.py CHANGED
@@ -1,71 +1,141 @@
1
1
  import asyncio
2
2
  import logging
3
3
 
4
- from qolsys_controller.settings import QolsysSettings
5
-
6
- from .enum import ZoneSensorGroup, ZoneSensorType, ZoneStatus
4
+ from .enum import DeviceCapability, ZoneSensorGroup, ZoneSensorType, ZoneStatus
7
5
  from .observable import QolsysObservable
6
+ from .settings import QolsysSettings
8
7
 
9
8
  LOGGER = logging.getLogger(__name__)
10
9
 
11
10
 
12
11
  class QolsysZone(QolsysObservable):
13
-
14
- def __init__(self, data: dict, settings: QolsysSettings) -> None:
12
+ def __init__(self, data: dict[str, str], settings: QolsysSettings) -> None:
15
13
  super().__init__()
16
14
 
17
15
  self._settings = settings
16
+ self._delay_task: asyncio.Task[None] | None = None
18
17
 
19
- self._delay_task:asyncio.Task = None
20
-
21
- self._zone_id = data.get("zoneid", "")
22
- self._sensorname = data.get("sensorname", "")
18
+ self._zone_id: str = data.get("zoneid", "")
19
+ self._sensorname: str = data.get("sensorname", "")
23
20
  self._sensorstatus: ZoneStatus = ZoneStatus(data.get("sensorstatus", ""))
24
21
  self._sensortype = ZoneSensorType(data.get("sensortype", ""))
25
- self._sensorgroup = data.get("sensorgroup", "")
26
- self._battery_status = data.get("battery_status", "")
27
- self._averagedBm = data.get("averagedBm", "")
28
- self._latestdBm = data.get("latestdBm", "")
29
- self._ac_status = data.get("ac_status", "")
30
-
31
- self._id = data.get("_id", "")
32
- self._zone_type = data.get("zone_type", "")
33
- self._sensor_id = data.get("sensorid", "")
34
- self._sensorstate = data.get("sensorstate", "")
35
- self._zone_physical_type = data.get("zone_physical_type", "")
36
- self._zone_alarm_type = data.get("zone_alarm_type", "")
37
- self._partition_id = data.get("partition_id", "")
38
- self._sensortts = data.get("sensortts", "")
39
- self._current_capability = data.get("current_capability", "")
40
- self._zone_rf_sensor = data.get("zone_rf_sensor", "")
41
- self._zone_supervised = data.get("zone_supervised", "")
42
- self._zone_reporting_enabled = data.get("zone_reporting_enabled", "")
43
- self._zone_two_way_voice_enabled = data.get("zone_two_way_voice_enabled", "")
44
- self._signal_source = data.get("signal_source", "")
45
- self._serial_number = data.get("serial_number", "")
46
- self._chimetype = data.get("chimetype", "")
47
- self._frame_count = data.get("frame_count", "")
48
- self._frame_type = data.get("frame_type", "")
49
- self._frame_id = data.get("frame_id", "")
50
- self._allowdisarming = data.get("allowdisarming", "")
51
- self._time = data.get("time", "")
52
- self._version = data.get("version", "")
53
- self._opr = data.get("opr", "")
54
- self._zone_equipement_code = data.get("zone_equipment_code", "")
55
- self._created_date = data.get("created_date", "")
56
- self._created_by = data.get("created_by", "")
57
- self._updated_by = data.get("updated_by", "")
58
- self._updated_date = data.get("updated_date", "")
59
- self._shortID = data.get("shortID", "")
60
- self._diag_24hr = data.get("diag_24hr", "")
61
- self._device_capability = data.get("device_capability", "")
62
- self._sub_type = data.get("sub_type", "")
63
- self._powerg_manufacture_id = data.get("powerg_manufacture_id", "")
64
- self._parent_node = data.get("parent_node", "")
65
- self._extras = data.get("extras", "")
66
-
67
- def update(self, data: dict) -> None: # noqa: C901, PLR0912, PLR0915
22
+ self._sensorgroup: str = data.get("sensorgroup", "")
23
+ self._battery_status: str = data.get("battery_status", "")
24
+ self._averagedBm: str = data.get("averagedBm", "")
25
+ self._latestdBm: str = data.get("latestdBm", "")
26
+ self._ac_status: str = data.get("ac_status", "")
27
+ self._shortID: str = data.get("shortID", "")
28
+ self._device_capability: str = data.get("device_capability", "")
29
+ self._current_capability: str = data.get("current_capability", "")
30
+
31
+ self._id: str = data.get("_id", "")
32
+ self._zone_type: str = data.get("zone_type", "")
33
+ self._sensor_id: str = data.get("sensorid", "")
34
+ self._sensorstate: str = data.get("sensorstate", "")
35
+ self._zone_physical_type: str = data.get("zone_physical_type", "")
36
+ self._zone_alarm_type: str = data.get("zone_alarm_type", "")
37
+ self._partition_id: str = data.get("partition_id", "")
38
+ self._sensortts: str = data.get("sensortts", "")
39
+ self._zone_rf_sensor: str = data.get("zone_rf_sensor", "")
40
+ self._zone_supervised: str = data.get("zone_supervised", "")
41
+ self._zone_reporting_enabled: str = data.get("zone_reporting_enabled", "")
42
+ self._zone_two_way_voice_enabled: str = data.get("zone_two_way_voice_enabled", "")
43
+ self._signal_source: str = data.get("signal_source", "")
44
+ self._serial_number: str = data.get("serial_number", "")
45
+ self._chimetype: str = data.get("chimetype", "")
46
+ self._frame_count: str = data.get("frame_count", "")
47
+ self._frame_type: str = data.get("frame_type", "")
48
+ self._frame_id: str = data.get("frame_id", "")
49
+ self._allowdisarming: str = data.get("allowdisarming", "")
50
+ self._time: str = data.get("time", "")
51
+ self._version: str = data.get("version", "")
52
+ self._opr: str = data.get("opr", "")
53
+ self._zone_equipement_code: str = data.get("zone_equipment_code", "")
54
+ self._created_date: str = data.get("created_date", "")
55
+ self._created_by: str = data.get("created_by", "")
56
+ self._updated_by: str = data.get("updated_by", "")
57
+ self._updated_date: str = data.get("updated_date", "")
58
+ self._diag_24hr: str = data.get("diag_24hr", "")
59
+ self._sub_type: str = data.get("sub_type", "")
60
+ self._powerg_manufacture_id: str = data.get("powerg_manufacture_id", "")
61
+ self._parent_node: str = data.get("parent_node", "")
62
+ self._extras: str = data.get("extras", "")
63
+
64
+ # EXTRA POWERG ATTRIBUTES
65
+ self._powerg_long_id: str = ""
66
+ self._powerg_status_data: str = ""
67
+ self._powerg_temperature: str = ""
68
+ self._powerg_light: str = ""
69
+ self._powerg_notification_period: str = ""
70
+ self._powerg_average_link_quality: str = ""
71
+ self._powerg_link_quality: str = ""
72
+ self._powerg_link_status: str = ""
73
+ self._powerg_battery_voltage: str = ""
74
+
75
+ def is_powerg_enabled(self) -> bool:
76
+ return self._current_capability == DeviceCapability.POWERG
77
+
78
+ def is_powerg_temperature_enabled(self) -> bool:
79
+ return self._powerg_temperature != ""
80
+
81
+ def is_powerg_light_enabled(self) -> bool:
82
+ return self._powerg_light != ""
83
+
84
+ def is_average_dbm_enabled(self) -> bool:
85
+ return self.averagedBm is not None
86
+
87
+ def is_latest_dbm_enabled(self) -> bool:
88
+ return self.latestdBm is not None
89
+
90
+ def is_battery_enabled(self) -> bool:
91
+ return self.battery_status != ""
92
+
93
+ def is_ac_enabled(self) -> bool:
94
+ return self.ac_status != ""
95
+
96
+ def update_powerg(self, data: dict[str, str]) -> None:
97
+ short_id_update = data.get("shortID", "")
98
+ if short_id_update != self.shortID:
99
+ LOGGER.error(
100
+ "Updating Zone%s PowerG Attribute (%s) with Zone%s (different shortID)",
101
+ self._zone_id,
102
+ self.sensorname,
103
+ short_id_update,
104
+ )
105
+ return
106
+
107
+ self.start_batch_update()
108
+
109
+ if "longID" in data:
110
+ self._powerg_long_id = data.get("longID", "")
111
+
112
+ if "status_data" in data:
113
+ self.powerg_status_data = data.get("status_data", "")
114
+
115
+ if "temperature" in data:
116
+ self.powerg_temperature = data.get("temperature", "")
117
+
118
+ if "light" in data:
119
+ self.powerg_light = data.get("light", "")
120
+
121
+ if "notification_period" in data:
122
+ self._powerg_notification_period = data.get("notification_period", "")
68
123
 
124
+ if "average_link_quality" in data:
125
+ self._powerg_average_link_quality = data.get("average_link_quality", "")
126
+
127
+ if "link_quality" in data:
128
+ self._powerg_link_quality = data.get("link_quality", "")
129
+
130
+ if "link_status" in data:
131
+ self._powerg_link_status = data.get("link_status", "")
132
+
133
+ if "battery_voltage" in data:
134
+ self._powerg_battery_voltage = data.get("battery_voltage", "")
135
+
136
+ self.end_batch_update()
137
+
138
+ def update(self, data: dict[str, str]) -> None: # noqa: C901, PLR0912, PLR0915
69
139
  zone_id_update = data.get("zoneid", "")
70
140
  if zone_id_update != self._zone_id:
71
141
  LOGGER.error("Updating Zone%s (%s) with Zone%s (different id)", self._zone_id, self.sensorname, zone_id_update)
@@ -73,90 +143,93 @@ class QolsysZone(QolsysObservable):
73
143
 
74
144
  self.start_batch_update()
75
145
 
76
- # Update sensor_name
77
146
  if "sensorname" in data:
78
- self.sensorname = data.get("sensorname")
147
+ self.sensorname = data.get("sensorname", "")
79
148
 
80
- # Update sensorsatus
81
149
  if "sensorstatus" in data:
82
- self.sensorstatus = ZoneStatus(data.get("sensorstatus"))
150
+ self.sensorstatus = ZoneStatus(data.get("sensorstatus", ""))
83
151
 
84
- # Update battery_status
85
152
  if "battery_status" in data:
86
- self.battery_status = data.get("battery_status")
153
+ self.battery_status = data.get("battery_status", "")
87
154
 
88
- # Update time
89
155
  if "time" in data:
90
- self.time = data.get("time")
156
+ self.time = data.get("time", "")
91
157
 
92
- # Update partition_id
93
158
  if "partition_id" in data:
94
- self._partition_id = data.get("partition_id")
159
+ self._partition_id = data.get("partition_id", "")
95
160
 
96
- # Update lastestdBm
97
161
  if "lastestdBm" in data:
98
- self.latestdBm = data.get("latestdBm")
162
+ self.latestdBm = data.get("latestdBm", "")
99
163
 
100
- # Update averagedBm
101
164
  if "averagedBm" in data:
102
- self.averagedBm = data.get("averagedBm")
165
+ self.averagedBm = data.get("averagedBm", "")
103
166
 
104
167
  if "sensorgroup" in data:
105
- self.sensorgroup = data.get("sensorgroup")
168
+ self.sensorgroup = data.get("sensorgroup", "")
106
169
 
107
170
  if "sensorstate" in data:
108
- self._sensorstate = data.get("sensorstate")
171
+ self._sensorstate = data.get("sensorstate", "")
109
172
 
110
173
  if "sensortype" in data:
111
- self.sensortype = ZoneSensorType(data.get("sensortype"))
174
+ self.sensortype = ZoneSensorType(data.get("sensortype", ""))
112
175
 
113
176
  if "zone_type" in data:
114
- self._zone_type = data.get("zone_type")
177
+ self._zone_type = data.get("zone_type", "")
115
178
 
116
179
  if "zone_physical_type" in data:
117
- self._zone_physical_type = data.get("zone_physical_type")
180
+ self._zone_physical_type = data.get("zone_physical_type", "")
118
181
 
119
182
  if "zone_alarm_type" in data:
120
- self._zone_alarm_type = data.get("zone_alarm_type")
183
+ self._zone_alarm_type = data.get("zone_alarm_type", "")
121
184
 
122
185
  if "sensorttss" in data:
123
- self._sensortts = data.get("sensortts")
186
+ self._sensortts = data.get("sensortts", "")
124
187
 
125
188
  if "current_capability" in data:
126
- self._current_capability = data.get("current_capability")
189
+ self._current_capability = data.get("current_capability", "")
127
190
 
128
191
  if "zone_rf_sensor" in data:
129
- self._zone_rf_sensor = data.get("zone_rf_sensor")
192
+ self._zone_rf_sensor = data.get("zone_rf_sensor", "")
130
193
 
131
194
  if "zone_supervised" in data:
132
- self._zone_supervised = data.get("zone_supervised")
195
+ self._zone_supervised = data.get("zone_supervised", "")
133
196
 
134
197
  if "zone_reporting_enabled" in data:
135
- self._zone_reporting_enabled = data.get("zone_reporting_enabled")
198
+ self._zone_reporting_enabled = data.get("zone_reporting_enabled", "")
136
199
 
137
200
  if "zone_two_way_voice_enabled" in data:
138
- self._zone_two_way_voice_enabled = data.get("zone_two_way_voice_enabled")
201
+ self._zone_two_way_voice_enabled = data.get("zone_two_way_voice_enabled", "")
139
202
 
140
203
  if "signal_source" in data:
141
- self._signal_source = data.get("signal_source")
204
+ self._signal_source = data.get("signal_source", "")
142
205
 
143
206
  if "serial_number" in data:
144
- self._serial_number = data.get("serial_number")
207
+ self._serial_number = data.get("serial_number", "")
145
208
 
146
209
  if "chimetype" in data:
147
- self._chimetype = data.get("chimetype")
210
+ self._chimetype = data.get("chimetype", "")
148
211
 
149
212
  if "frame_count" in data:
150
- self._frame_count = data.get("frame_count")
213
+ self._frame_count = data.get("frame_count", "")
151
214
 
152
215
  if "frame_type" in data:
153
- self._frame_type = data.get("frame_type")
216
+ self._frame_type = data.get("frame_type", "")
154
217
 
155
218
  if "allowdisarming" in data:
156
- self._allowdisarming = data.get("allowdisarming")
219
+ self._allowdisarming = data.get("allowdisarming", "")
157
220
 
158
221
  self.end_batch_update()
159
222
 
223
+ async def delay_zone(self, next_status: ZoneStatus) -> None:
224
+ await asyncio.sleep(self._settings.motion_sensor_delay_sec)
225
+ self._sensorstatus = next_status
226
+ LOGGER.debug("Zone%s (%s) - sensorstatus: %s", self._zone_id, self.sensorname, next_status)
227
+ self.notify()
228
+
229
+ # -----------------------------
230
+ # properties + setters
231
+ # -----------------------------
232
+
160
233
  @property
161
234
  def id(self) -> str:
162
235
  return self._id
@@ -165,18 +238,58 @@ class QolsysZone(QolsysObservable):
165
238
  def sensorname(self) -> str:
166
239
  return self._sensorname
167
240
 
241
+ @sensorname.setter
242
+ def sensorname(self, value: str) -> None:
243
+ if self.sensorname != value:
244
+ self._sensorname = value
245
+ self.notify()
246
+
168
247
  @property
169
248
  def sensorgroup(self) -> str:
170
249
  return self._sensorgroup
171
250
 
251
+ @sensorgroup.setter
252
+ def sensorgroup(self, new_value: str) -> None:
253
+ if self._sensorgroup != new_value:
254
+ # Report new values
255
+ try:
256
+ ZoneSensorGroup(new_value)
257
+ except ValueError:
258
+ LOGGER.exception("Unknown Sensor group: %s, please report", new_value)
259
+
260
+ self._sensorgroup = new_value
261
+ LOGGER.debug("Zone%s (%s) - sensorgroup: %s", self.zone_id, self.sensorname, new_value)
262
+ self.notify()
263
+
172
264
  @property
173
265
  def sensorstatus(self) -> ZoneStatus:
174
266
  return self._sensorstatus
175
267
 
268
+ @sensorstatus.setter
269
+ def sensorstatus(self, new_value: ZoneStatus) -> None:
270
+ if self._settings.motion_sensor_delay and self._sensortype in {ZoneSensorType.MOTION, ZoneSensorType.PANEL_MOTION}:
271
+ if new_value == ZoneStatus.IDLE:
272
+ return
273
+ if self._delay_task is not None:
274
+ self._delay_task.cancel()
275
+ self._delay_task = asyncio.create_task(self.delay_zone(ZoneStatus.IDLE))
276
+
277
+ if self._sensorstatus != new_value:
278
+ LOGGER.debug("Zone%s (%s) - sensorstatus: %s", self._zone_id, self.sensorname, new_value)
279
+ self._sensorstatus = new_value
280
+ self.notify()
281
+
176
282
  @property
177
283
  def battery_status(self) -> str:
178
284
  return self._battery_status
179
285
 
286
+ @battery_status.setter
287
+ def battery_status(self, value: str) -> None:
288
+ if self._battery_status != value:
289
+ LOGGER.debug("Zone%s (%s) - battery_status: %s", self.zone_id, self.sensorname, value)
290
+ self._battery_status = value
291
+ self.notify()
292
+
180
293
  @property
181
294
  def sensorstate(self) -> str:
182
295
  return self._sensorstate
@@ -185,6 +298,12 @@ class QolsysZone(QolsysObservable):
185
298
  def sensortype(self) -> ZoneSensorType:
186
299
  return self._sensortype
187
300
 
301
+ @sensortype.setter
302
+ def sensortype(self, value: ZoneSensorType) -> None:
303
+ if self._sensortype != value:
304
+ self._sensortype = value
305
+ self.notify()
306
+
188
307
  @property
189
308
  def zone_id(self) -> str:
190
309
  return self._zone_id
@@ -205,107 +324,137 @@ class QolsysZone(QolsysObservable):
205
324
  def partition_id(self) -> str:
206
325
  return self._partition_id
207
326
 
208
- @property
209
- def time(self) -> str:
210
- return self._time
327
+ @partition_id.setter
328
+ def partition_id(self, value: str) -> None:
329
+ if self.partition_id != value:
330
+ self.partition_id = value
331
+ self.notify()
211
332
 
212
333
  @property
213
- def latestdBm(self) -> str:
214
- return self._latestdBm
334
+ def shortID(self) -> str:
335
+ return self._shortID
215
336
 
216
337
  @property
217
- def averagedBm(self) -> str:
218
- return self._averagedBm
338
+ def time(self) -> str:
339
+ return self._time
219
340
 
220
- @averagedBm.setter
221
- def averagedBm(self, value: str) -> None:
222
- if self._averagedBm != value:
223
- self._averagedBm = value
341
+ @time.setter
342
+ def time(self, value: str) -> None:
343
+ if self._time != value:
344
+ self._time = value
345
+ self.notify()
224
346
 
225
- if value == "":
226
- self._averagedBm = 0
347
+ @property
348
+ def current_capability(self) -> str:
349
+ return self._current_capability
227
350
 
228
- self.notify()
351
+ @property
352
+ def latestdBm(self) -> int | None:
353
+ try:
354
+ n = int(self._latestdBm)
355
+ if n >= 0 and n < 999: # noqa: PLR2004
356
+ return n
357
+ except ValueError:
358
+ pass
359
+ return None
229
360
 
230
361
  @latestdBm.setter
231
362
  def latestdBm(self, value: str) -> None:
232
363
  if self._latestdBm != value:
233
364
  self.latestdBm = value
234
-
235
- if value == "":
236
- self._latestdBm = 0
237
-
238
365
  self.notify()
239
366
 
240
- @sensorstatus.setter
241
- def sensorstatus(self, new_value: ZoneStatus) -> None:
242
- if self._settings.motion_sensor_delay and self._sensortype in {ZoneSensorType.MOTION, ZoneSensorType.PANEL_MOTION}:
243
- if new_value == ZoneStatus.IDLE:
244
- return
245
- if self._delay_task is not None:
246
- self._delay_task.cancel()
247
- self._delay_task = asyncio.create_task(self.delay_zone(ZoneStatus.IDLE))
367
+ @property
368
+ def averagedBm(self) -> int | None:
369
+ try:
370
+ n = int(self._averagedBm)
371
+ if n >= 0 and n < 999: # noqa: PLR2004
372
+ return n
373
+ except ValueError:
374
+ pass
375
+ return None
248
376
 
249
- if self._sensorstatus != new_value:
250
- LOGGER.debug("Zone%s (%s) - sensorstatus: %s", self._zone_id, self.sensorname, new_value)
251
- self._sensorstatus = new_value
377
+ @averagedBm.setter
378
+ def averagedBm(self, value: str) -> None:
379
+ if self._averagedBm != value:
380
+ self._averagedBm = value
252
381
  self.notify()
253
382
 
254
- async def delay_zone(self,next_status: ZoneStatus) -> None:
255
- await asyncio.sleep(self._settings.motion_sensor_delay_sec)
256
- self._sensorstatus = next_status
257
- LOGGER.debug("Zone%s (%s) - sensorstatus: %s", self._zone_id, self.sensorname, next_status)
258
- self.notify()
259
-
260
- @battery_status.setter
261
- def battery_status(self, value: str) -> None:
262
- if self._battery_status != value:
263
- LOGGER.debug("Zone%s (%s) - battery_status: %s", self.zone_id, self.sensorname, value)
264
- self._battery_status = value
265
- self.notify()
383
+ @property
384
+ def device_capability(self) -> str:
385
+ return self._device_capability
266
386
 
267
- @sensorname.setter
268
- def sensorname(self, value: str) -> None:
269
- if self.sensorname != value:
270
- self._sensorname = value
271
- self.notify()
387
+ @property
388
+ def ac_status(self) -> str:
389
+ return self._ac_status
272
390
 
273
- @time.setter
274
- def time(self, value: str) -> None:
275
- if self._time != value:
276
- #LOGGER.debug("Zone%s (%s) - time: %s", self.zone_id, self.sensorname, value)
277
- self._time = value
391
+ @property
392
+ def powerg_temperature(self) -> float | None:
393
+ try:
394
+ return float(self._powerg_temperature)
395
+ except ValueError:
396
+ return None
397
+
398
+ @powerg_temperature.setter
399
+ def powerg_temperature(self, value: str) -> None:
400
+ if self._powerg_temperature != value:
401
+ LOGGER.debug("Zone%s (%s) - powerg_temperature: %s", self._zone_id, self.sensorname, value)
402
+ self._powerg_temperature = value
278
403
  self.notify()
279
404
 
280
- @sensortype.setter
281
- def sensortype(self, value: ZoneSensorType) -> None:
282
- if self._sensortype != value:
283
- self._sensortype = value
405
+ @property
406
+ def powerg_light(self) -> float | None:
407
+ try:
408
+ return float(self._powerg_light)
409
+ except ValueError:
410
+ return None
411
+
412
+ @powerg_light.setter
413
+ def powerg_light(self, value: str) -> None:
414
+ if self._powerg_light != value:
415
+ LOGGER.debug("Zone%s (%s) - powerg_light: %s", self._zone_id, self.sensorname, value)
416
+ self._powerg_light = value
284
417
  self.notify()
285
418
 
286
- @sensorgroup.setter
287
- def sensorgroup(self, new_value: str) -> None:
288
- if self._sensorgroup != new_value:
289
-
290
- # Report new values
291
- try:
292
- ZoneSensorGroup(new_value)
293
- except ValueError:
294
- LOGGER.exception("Unknown Sensor group: %s, please report", new_value)
295
-
296
- self._sensorgroup = new_value
297
- LOGGER.debug("Zone%s (%s) - sensorgroup: %s", self.zone_id, self.sensorname, new_value)
419
+ @property
420
+ def powerg_status_data(self) -> str:
421
+ return self._powerg_status_data
422
+
423
+ @powerg_status_data.setter
424
+ def powerg_status_data(self, value: str) -> None:
425
+ if self._powerg_status_data != value:
426
+ LOGGER.debug("Zone%s (%s) - powerg_status_data: %s", self._zone_id, self.sensorname, value)
427
+ self._powerg_status_data = value
298
428
  self.notify()
299
429
 
300
- @partition_id.setter
301
- def partition_id(self, value: str) -> None:
302
- if self.partition_id != value:
303
- self.partition_id = value
304
- self.notify()
430
+ def to_powerg_dict(self) -> dict[str, str]:
431
+ return {
432
+ "shortID": self.shortID,
433
+ "longID": self._powerg_long_id,
434
+ "status_data": self._powerg_status_data,
435
+ "temperature": self._powerg_temperature,
436
+ "light": self._powerg_light,
437
+ "notification_period": self._powerg_notification_period,
438
+ "average_link_quality": self._powerg_average_link_quality,
439
+ "link_quality": self._powerg_link_quality,
440
+ "link_status": self._powerg_link_status,
441
+ "battery_voltage": self._powerg_battery_voltage,
442
+ }
305
443
 
306
- def to_dict(self) -> dict:
444
+ def to_dict(self) -> dict[str, str]:
307
445
  return {
308
446
  "_id": self.id,
447
+ "ac_status": self.ac_status,
448
+ "allowdisarming": self._allowdisarming,
449
+ "averagedBm": self._averagedBm,
450
+ "battery_status": self.battery_status,
451
+ "chimetype": self._chimetype,
452
+ "created_by": self._created_by,
453
+ "created_date": self._created_date,
454
+ "current_capability": self._current_capability,
455
+ "device_capability": self._device_capability,
456
+ "diag_24hr": self._diag_24hr,
457
+ "extras": self._extras,
309
458
  "sensorid": self._sensor_id,
310
459
  "sensorname": self.sensorname,
311
460
  "sensorgroup": self.sensorgroup,
@@ -317,36 +466,25 @@ class QolsysZone(QolsysObservable):
317
466
  "zone_physical_type": self.zone_physical_type,
318
467
  "zone_alarm_type": self.zone_alarm_type,
319
468
  "partition_id": self.partition_id,
320
- "battery_status": self.battery_status,
321
469
  "sensortts": self._sensortts,
322
- "latestdBm": self.latestdBm,
323
- "averagedBm": self.averagedBm,
324
- "current_capability": self._current_capability,
470
+ "latestdBm": self._latestdBm,
325
471
  "zone_rf_sensor": self._zone_rf_sensor,
326
472
  "zone_supervised": self._zone_supervised,
327
473
  "zone_reporting_enabled": self._zone_reporting_enabled,
328
474
  "zone_two_way_voice_enabled": self._zone_two_way_voice_enabled,
329
475
  "signal_source": self._signal_source,
330
476
  "serial_number": self._serial_number,
331
- "chimetype": self._chimetype,
332
477
  "frame_count": self._frame_count,
333
478
  "frame_type": self._frame_type,
334
479
  "frame_id": self._frame_id,
335
- "allowdisarming": self._allowdisarming,
336
480
  "time": self.time,
337
481
  "version": self._version,
338
482
  "opr": self._opr,
339
483
  "zone_equipment_code": self._zone_equipement_code,
340
- "created_date": self._created_date,
341
- "created_by": self._created_by,
342
484
  "updated_by": self._updated_by,
343
485
  "updated_date": self._updated_date,
344
486
  "shortID": self._shortID,
345
- "diag_24hr": self._diag_24hr,
346
- "device_capability": self._device_capability,
347
487
  "sub_type": self._sub_type,
348
488
  "powerg_manufacture_id": self._powerg_manufacture_id,
349
489
  "parent_node": self._parent_node,
350
- "extras": self._extras,
351
- "ac_status": self._ac_status,
352
490
  }