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