qolsys-controller 0.0.82__tar.gz → 0.2.9__tar.gz

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 (93) hide show
  1. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/PKG-INFO +1 -1
  2. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/pyproject.toml +1 -1
  3. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/controller.py +73 -16
  4. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/db.py +7 -7
  5. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_sensor.py +2 -0
  6. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_smartsocket.py +12 -1
  7. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_user.py +1 -0
  8. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/enum.py +29 -16
  9. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/enum_zwave.py +16 -0
  10. qolsys_controller-0.2.9/qolsys_controller/observable_v2.py +14 -0
  11. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/panel.py +40 -9
  12. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/state.py +74 -19
  13. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zone.py +68 -7
  14. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_device.py +57 -3
  15. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_dimmer.py +6 -2
  16. qolsys_controller-0.2.9/qolsys_controller/zwave_energy_clamp.py +19 -0
  17. qolsys_controller-0.2.9/qolsys_controller/zwave_extenal_siren.py +20 -0
  18. qolsys_controller-0.2.9/qolsys_controller/zwave_garagedoor.py +20 -0
  19. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_generic.py +6 -2
  20. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_lock.py +6 -2
  21. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_service_meter.py +1 -1
  22. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_service_multilevelsensor.py +9 -0
  23. qolsys_controller-0.2.9/qolsys_controller/zwave_smart_socket.py +20 -0
  24. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_thermometer.py +6 -2
  25. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/zwave_thermostat.py +43 -5
  26. qolsys_controller-0.2.9/qolsys_controller/zwave_water_valve.py +20 -0
  27. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/requirements.txt +2 -2
  28. qolsys_controller-0.0.82/qolsys_controller/zwave_energy_clamp.py +0 -15
  29. qolsys_controller-0.0.82/qolsys_controller/zwave_garagedoor.py +0 -13
  30. qolsys_controller-0.0.82/qolsys_controller/zwave_outlet.py +0 -13
  31. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/.github/workflows/build.yml +0 -0
  32. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/.github/workflows/publish.yml +0 -0
  33. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/.gitignore +0 -0
  34. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/Info_mqtt.md +0 -0
  35. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/LICENSE +0 -0
  36. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/README.md +0 -0
  37. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/bin/qolsys.py +0 -0
  38. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/example.py +0 -0
  39. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/info_pairing.md +0 -0
  40. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/info_qolsys.md +0 -0
  41. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/mypy.ini +0 -0
  42. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/__init__.py +0 -0
  43. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/adc_device.py +0 -0
  44. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/adc_service.py +0 -0
  45. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/adc_service_garagedoor.py +0 -0
  46. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table.py +0 -0
  47. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_alarmedsensor.py +0 -0
  48. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_automation.py +0 -0
  49. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_country_locale.py +0 -0
  50. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_dashboard_msgs.py +0 -0
  51. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_dimmerlight.py +0 -0
  52. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_doorlock.py +0 -0
  53. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_eu_event.py +0 -0
  54. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_heat_map.py +0 -0
  55. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_history.py +0 -0
  56. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_iqremotesettings.py +0 -0
  57. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_iqrouter_network_config.py +0 -0
  58. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_iqrouter_user_device.py +0 -0
  59. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_master_slave.py +0 -0
  60. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_nest_device.py +0 -0
  61. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_output_rules.py +0 -0
  62. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_partition.py +0 -0
  63. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_pgm_outputs.py +0 -0
  64. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_powerg_device.py +0 -0
  65. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_qolsyssettings.py +0 -0
  66. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_scene.py +0 -0
  67. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_sensor_group.py +0 -0
  68. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_shades.py +0 -0
  69. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_state.py +0 -0
  70. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_tcc.py +0 -0
  71. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_thermostat.py +0 -0
  72. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_trouble_conditions.py +0 -0
  73. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_virtual_device.py +0 -0
  74. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_weather.py +0 -0
  75. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_zigbee_device.py +0 -0
  76. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_zwave_association_group.py +0 -0
  77. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_zwave_history.py +0 -0
  78. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_zwave_node.py +1 -1
  79. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/database/table_zwave_other.py +0 -0
  80. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/enum_adc.py +0 -0
  81. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/errors.py +0 -0
  82. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/mdns.py +0 -0
  83. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/mqtt_command.py +0 -0
  84. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/mqtt_command_queue.py +0 -0
  85. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/observable.py +0 -0
  86. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/partition.py +0 -0
  87. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/pki.py +0 -0
  88. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/scene.py +0 -0
  89. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/settings.py +0 -0
  90. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/task_manager.py +0 -0
  91. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/users.py +0 -0
  92. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/utils_mqtt.py +0 -0
  93. {qolsys_controller-0.0.82 → qolsys_controller-0.2.9}/qolsys_controller/weather.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: qolsys-controller
3
- Version: 0.0.82
3
+ Version: 0.2.9
4
4
  Summary: A Python module that emulates a virtual IQ Remote device, enabling full local control of a Qolsys IQ Panel
5
5
  Project-URL: Homepage, https://github.com/EHylands/QolsysController
6
6
  Project-URL: Issues, https://github.com/EHylands/QolsysController/issues
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "qolsys-controller"
3
- version = "0.0.82"
3
+ version = "0.2.9"
4
4
  authors = [
5
5
  { name="Eric Hylands", email="" },
6
6
  ]
@@ -157,15 +157,24 @@ class QolsysController:
157
157
  self.connected_observer.notify()
158
158
 
159
159
  async def mqtt_connect_task(self, reconnect: bool, run_forever: bool) -> None:
160
- # Configure TLS parameters for MQTT connection
161
- tls_params = aiomqtt.TLSParameters(
162
- ca_certs=str(self._pki.qolsys_cer_file_path),
163
- certfile=str(self._pki.secure_file_path),
164
- keyfile=str(self._pki.key_file_path),
165
- cert_reqs=ssl.CERT_REQUIRED,
166
- tls_version=ssl.PROTOCOL_TLSv1_2,
167
- ciphers="ALL:@SECLEVEL=0",
168
- )
160
+ # Configure TLS context for MQTT connection
161
+ def create_tls_context(self: QolsysController) -> ssl.SSLContext:
162
+ ctx = ssl.create_default_context(
163
+ purpose=ssl.Purpose.SERVER_AUTH,
164
+ cafile=str(self._pki.qolsys_cer_file_path),
165
+ )
166
+ ctx.set_ciphers("DEFAULT:@SECLEVEL=0")
167
+ ctx.minimum_version = ssl.TLSVersion.TLSv1_2
168
+ ctx.check_hostname = False
169
+ ctx.verify_mode = ssl.CERT_NONE
170
+ ctx.load_cert_chain(
171
+ certfile=str(self._pki.secure_file_path),
172
+ keyfile=str(self._pki.key_file_path),
173
+ )
174
+ return ctx
175
+
176
+ loop = asyncio.get_running_loop()
177
+ ctx = await loop.run_in_executor(None, create_tls_context, self)
169
178
 
170
179
  LOGGER.debug("MQTT: Connecting ...")
171
180
 
@@ -177,7 +186,7 @@ class QolsysController:
177
186
  self.aiomqtt = aiomqtt.Client(
178
187
  hostname=self.settings.panel_ip,
179
188
  port=8883,
180
- tls_params=tls_params,
189
+ tls_context=ctx,
181
190
  tls_insecure=True,
182
191
  clean_session=True,
183
192
  timeout=self.settings.mqtt_timeout,
@@ -748,6 +757,51 @@ class QolsysController:
748
757
  LOGGER.debug("MQTT: Receiving execute_scene command")
749
758
  return response
750
759
 
760
+ async def command_panel_virtual_device_action(self, device_id: str, state: int) -> dict[str, Any] | None:
761
+ LOGGER.debug("MQTT: Sending virtual_device command")
762
+
763
+ garage_door = self.state.adc_device(device_id)
764
+ if not garage_door:
765
+ LOGGER.error("Invalid Virtual Garage Door Id: %s", device_id)
766
+
767
+ device_list = {
768
+ "virtualDeviceList": [
769
+ {
770
+ "virtualDeviceId": device_id,
771
+ "virtualDeviceFunctionList": [
772
+ {
773
+ "vdFuncId": 1,
774
+ "vdFuncState": state,
775
+ "vdFuncBackendTimestamp": int(time.time() * 1000),
776
+ "vdFuncType": 1,
777
+ }
778
+ ],
779
+ }
780
+ ]
781
+ }
782
+
783
+ virtual_command = {
784
+ "operation_name": "send_virtual_device_description",
785
+ "virtual_device_operation": 4,
786
+ "virtual_device_description": json.dumps(device_list),
787
+ "operation_source": 0,
788
+ }
789
+
790
+ ipc_request = [
791
+ {
792
+ "dataType": "string",
793
+ "dataValue": json.dumps(virtual_command),
794
+ }
795
+ ]
796
+
797
+ LOGGER.debug("virtual command: %s", virtual_command)
798
+
799
+ command = MQTTCommand_Panel(self)
800
+ command.append_ipc_request(ipc_request)
801
+ response = await command.send_command()
802
+ LOGGER.debug("MQTT: Receiving virtual_device command: %s", response)
803
+ return response
804
+
751
805
  async def command_panel_trigger_police(self, partition_id: str, silent: bool) -> dict[str, Any] | None:
752
806
  LOGGER.debug("MQTT: Sending panel_trigger_police command")
753
807
 
@@ -839,7 +893,7 @@ class QolsysController:
839
893
  return response
840
894
 
841
895
  async def command_zwave_switch_binary_set(self, node_id: str, status: bool) -> dict[str, Any] | None:
842
- LOGGER.debug("MQTT: Sending set_zwave_switch_binary command - Node(%s) - Status(%s)", node_id, status)
896
+ LOGGER.debug("MQTT: Sending set_zwave_switch_binar#y command - Node(%s) - Status(%s)", node_id, status)
843
897
  zwave_node = self.state.zwave_device(node_id)
844
898
 
845
899
  if not zwave_node:
@@ -916,17 +970,21 @@ class QolsysController:
916
970
  temp_int = int(round(setpoint * (10**precision)))
917
971
  temp_bytes = temp_int.to_bytes(size, byteorder="big", signed=True)
918
972
 
973
+ setpointmode = ThermostatSetpointMode.HEATING
974
+ if mode == ThermostatSetpointMode.COOLING:
975
+ setpointmode = mode
976
+
919
977
  zwave_bytes: list[int] = [
920
- ZwaveCommandClass.ThermostatSetPoint.value,
921
- 0x03, # SET
922
- mode.value,
978
+ 0x43, # Thermostat Setpoint
979
+ 0x01, # SET
980
+ setpointmode.value,
923
981
  pss,
924
982
  ] + list(temp_bytes)
925
983
 
926
984
  LOGGER.debug(
927
985
  "MQTT: Sending zwave_thermostat_setpoint_set - Node(%s) - Mode(%s) - Setpoint(%s): %s",
928
986
  node_id,
929
- mode,
987
+ mode.value,
930
988
  setpoint,
931
989
  zwave_bytes,
932
990
  )
@@ -943,7 +1001,6 @@ class QolsysController:
943
1001
  LOGGER.error("zwave_thermostat_mode_set - Invalid node_id %s", node_id)
944
1002
  return None
945
1003
 
946
- LOGGER.debug("thermostat_mode: %s", int(mode))
947
1004
  if mode not in thermostat.available_thermostat_mode():
948
1005
  LOGGER.error("thermostat_mode_set - Invalid mode %s", mode)
949
1006
 
@@ -216,7 +216,7 @@ class QolsysDB:
216
216
  return partitions
217
217
 
218
218
  def get_adc_devices(self) -> list[dict[str, str]]:
219
- self.cursor.execute(f"SELECT * FROM {self.table_virtual_device.table} ORDER BY device_id")
219
+ self.cursor.execute(f"SELECT * FROM {self.table_virtual_device.table} ORDER BY CAST(device_id AS INTEGER)")
220
220
  self.db.commit()
221
221
 
222
222
  devices = []
@@ -228,7 +228,7 @@ class QolsysDB:
228
228
  return devices
229
229
 
230
230
  def get_zwave_devices(self) -> list[dict[str, str]]:
231
- self.cursor.execute(f"SELECT * FROM {self.table_zwave_node.table} ORDER BY node_id")
231
+ self.cursor.execute(f"SELECT * FROM {self.table_zwave_node.table} ORDER BY CAST(node_id AS INTEGER)")
232
232
  self.db.commit()
233
233
 
234
234
  devices = []
@@ -240,7 +240,7 @@ class QolsysDB:
240
240
  return devices
241
241
 
242
242
  def get_zwave_other_devices(self) -> list[dict[str, str]]:
243
- self.cursor.execute(f"SELECT * FROM {self.table_zwave_other.table} ORDER BY node_id")
243
+ self.cursor.execute(f"SELECT * FROM {self.table_zwave_other.table} ORDER BY CAST(node_id AS INTEGER)")
244
244
  self.db.commit()
245
245
 
246
246
  devices = []
@@ -252,7 +252,7 @@ class QolsysDB:
252
252
  return devices
253
253
 
254
254
  def get_locks(self) -> list[dict[str, str]]:
255
- self.cursor.execute(f"SELECT * FROM {self.table_doorlock.table} ORDER BY node_id")
255
+ self.cursor.execute(f"SELECT * FROM {self.table_doorlock.table} ORDER BY CAST(node_id AS INTEGER)")
256
256
  self.db.commit()
257
257
 
258
258
  locks = []
@@ -264,7 +264,7 @@ class QolsysDB:
264
264
  return locks
265
265
 
266
266
  def get_thermostats(self) -> list[dict[str, str]]:
267
- self.cursor.execute(f"SELECT * FROM {self.table_thermostat.table} ORDER BY node_id")
267
+ self.cursor.execute(f"SELECT * FROM {self.table_thermostat.table} ORDER BY CAST(node_id AS INTEGER)")
268
268
  self.db.commit()
269
269
 
270
270
  thermostats = []
@@ -276,7 +276,7 @@ class QolsysDB:
276
276
  return thermostats
277
277
 
278
278
  def get_dimmers(self) -> list[dict[str, str]]:
279
- self.cursor.execute(f"SELECT * FROM {self.table_dimmer.table} ORDER BY node_id")
279
+ self.cursor.execute(f"SELECT * FROM {self.table_dimmer.table} ORDER BY CAST(node_id AS INTEGER)")
280
280
  self.db.commit()
281
281
 
282
282
  dimmers = []
@@ -288,7 +288,7 @@ class QolsysDB:
288
288
  return dimmers
289
289
 
290
290
  def get_zones(self) -> list[dict[str, str]]:
291
- self.cursor.execute(f"SELECT * FROM {self.table_sensor.table} ORDER BY zoneid")
291
+ self.cursor.execute(f"SELECT * FROM {self.table_sensor.table} ORDER BY CAST(zoneid AS INTEGER)")
292
292
  self.db.commit()
293
293
 
294
294
  zones = []
@@ -65,6 +65,8 @@ class QolsysTableSensor(QolsysTable):
65
65
  "extras",
66
66
  "allowspeaker",
67
67
  "firmware_version",
68
+ "radio_version",
69
+ "radio_id",
68
70
  ]
69
71
 
70
72
  self._create_table()
@@ -12,10 +12,21 @@ class QolsysTableSmartSocket(QolsysTable):
12
12
  self._uri = "content://com.qolsys.qolsysprovider.SmartSocketsContentProvider/smartsocket"
13
13
  self._table = "smartsocket"
14
14
  self._abort_on_error = False
15
- self._implemented = False
15
+ self._implemented = True
16
16
 
17
17
  self._columns = [
18
18
  "_id",
19
+ "created_by",
20
+ "created_date",
21
+ "last_updated_date",
22
+ "node_id",
23
+ "paired_status",
24
+ "power_usage",
25
+ "status",
26
+ "updated_by",
27
+ "socket_id",
28
+ "socket_name",
29
+ "current_usagevoltage_usage",
19
30
  ]
20
31
 
21
32
  self._create_table()
@@ -39,6 +39,7 @@ class QolsysTableUser(QolsysTable):
39
39
  "tag_flag",
40
40
  "check_in_time",
41
41
  "user_feature1",
42
+ "user_feature2",
42
43
  ]
43
44
 
44
45
  self._create_table()
@@ -1,6 +1,16 @@
1
1
  from enum import StrEnum
2
2
 
3
3
 
4
+ class QolsysEvent(StrEnum):
5
+ EVENT_PANEL_PARTITION_ADD = "EVENT_PANEL_PARTITION_ADD"
6
+ EVENT_PANEL_ZONE_ADD = "EVENT_PANEL_ZONE_ADD"
7
+ EVENT_PANEL_DOORBELL = "EVENT_PANEL_DOORBELL"
8
+ EVENT_PANEL_CHIME = "EVENT_PANEL_CHIME"
9
+ EVENT_ZWAVE_DEVICE_ADD = "EVENT_ZWAVE_MULTILEVELSENSOR_ADD"
10
+ EVENT_ZWAVE_MULTILEVELSENSOR_ADD = "EVENT_ZWAVE_MULTILEVELSENSOR_ADD"
11
+ EVENT_ZWAVE_METER_ADD = "EVENT_ZWAVE_METER_ADD"
12
+
13
+
4
14
  class PartitionSystemStatus(StrEnum):
5
15
  ARM_STAY = "ARM-STAY"
6
16
  ARM_AWAY = "ARM-AWAY"
@@ -48,23 +58,24 @@ class PartitionAlarmType(StrEnum):
48
58
 
49
59
 
50
60
  class ZoneStatus(StrEnum):
61
+ ACTIVE = "Active"
62
+ ACTIVATED = "Activated"
51
63
  ALARMED = "Alarmed"
52
- OPEN = "Open"
64
+ ARM_AWAY = "Arm-Away"
65
+ ARM_STAY = "Arm-Stay"
53
66
  CLOSED = "Closed"
54
- ACTIVE = "Active"
67
+ CONNECTED = "connected"
68
+ DISARM = "Disarm"
69
+ OPEN = "Open"
55
70
  INACTIVE = "Inactive"
56
- ACTIVATED = "Activated"
57
71
  IDLE = "Idle"
58
72
  NORMAL = "Normal"
59
73
  UNREACHABLE = "Unreachable"
60
74
  TAMPERED = "Tampered"
61
75
  SYNCHRONIZING = "Synchronizing"
62
- CONNECTED = "connected"
63
76
  DISCONNECTED = "disconnected"
64
77
  FAILURE = "Failure"
65
78
  NOT_NETWORKED = "Not Networked"
66
- DISARM = "Disarm"
67
- ARM_AWAY = "Arm-Away"
68
79
 
69
80
 
70
81
  class DeviceCapability(StrEnum):
@@ -72,20 +83,20 @@ class DeviceCapability(StrEnum):
72
83
  WIFI = "WiFi"
73
84
  POWERG = "POWERG"
74
85
  ZWAVE = "Z-Wave"
86
+ S_LINE = "S-Line"
75
87
 
76
88
 
77
89
  class ZoneSensorType(StrEnum):
78
- DOOR_WINDOW = "Door_Window"
90
+ AUXILIARY_PENDANT = "Auxiliary Pendant"
91
+ BLUETOOTH = "Bluetooth"
92
+ CO_DETECTOR = "CODetector"
79
93
  DOORBELL = "Doorbell"
80
- MOTION = "Motion"
94
+ DOOR_WINDOW = "Door_Window"
81
95
  GLASS_BREAK = "GlassBreak"
96
+ MOTION = "Motion"
82
97
  KEY_FOB = "KeyFob"
83
98
  KEYPAD = "Keypad"
84
- AUXILIARY_PENDANT = "Auxiliary Pendant"
85
99
  SMOKE_DETECTOR = "SmokeDetector"
86
- CO_DETECTOR = "CODetector"
87
- # HARDWIRE_TRANSLATOR = "" # TBD
88
- # WIRELESS_TRANSLATOR = "" #TBD
89
100
  TEMPERATURE = "Temperature"
90
101
  HEAT = "Heat"
91
102
  WATER = "Water"
@@ -93,16 +104,18 @@ class ZoneSensorType(StrEnum):
93
104
  FREEZE = "Freeze"
94
105
  TILT = "Tilt"
95
106
  SMOKE_M = "Smoke_M"
96
- # DOOR_WINDOW_M = "" #TBD
97
- # OCCUPANCY = "" #TBD
98
107
  SIREN = "Siren"
99
- # HIGH_TEMPERATURE = "" # TBD
100
108
  PANEL_MOTION = "Panel Motion"
101
109
  PANEL_GLASS_BREAK = "Panel Glass Break"
102
- BLUETOOTH = "Bluetooth"
103
110
  TAKEOVER_MODULE = "TakeoverModule"
104
111
  TRANSLATOR = "Translator"
105
112
  TAMPER = "Tamper Sensor"
113
+ ZWAVE_SIREN = "Z-Wave Siren"
114
+ # HARDWIRE_TRANSLATOR = "" # TBD
115
+ # HIGH_TEMPERATURE = "" # TBD
116
+ # DOOR_WINDOW_M = "" #TBD
117
+ # WIRELESS_TRANSLATOR = "" #TBD
118
+ # OCCUPANCY = "" #TBD
106
119
 
107
120
 
108
121
  class ZoneSensorGroup(StrEnum):
@@ -160,14 +160,30 @@ BITMASK_SUPPORTED_THERMOSTAT_FAN_MODE = {
160
160
  class ZwaveCommandClass(IntEnum):
161
161
  SwitchBinary = 0x25
162
162
  SwitchMultilevel = 0x26
163
+ SceneActivation = 0x2B
164
+ SceneActuatorConf = 0x2C
163
165
  SensorMultiLevel = 0x31
164
166
  Meter = 0x32
165
167
  ThermostatMode = 0x40
166
168
  ThermostatSetPoint = 0x43
167
169
  ThermostatFanMode = 0x44
168
170
  ThermostatFanState = 0x45
171
+ DeviceResetLocally = 0x5A
172
+ AssociationGroupInformation = 0x59
173
+ ZWavePlusInfo = 0x5E
174
+ MultiChannel = 0x60
169
175
  DoorLock = 0x62
176
+ Supervision = 0x6C
177
+ Configuration = 0x70
170
178
  Alarm = 0x71
179
+ ManufacturerSpecific = 0x72
180
+ PowerLevel = 0x73
181
+ FirmwareUpdate = 0x7A
182
+ Association = 0x85
183
+ Version = 0x86
184
+ Indicator = 0x87
185
+ MultiChannelAssociation = 0x8E
186
+ SecurityS2 = 0x9F
171
187
 
172
188
 
173
189
  class ZwaveCommand(IntEnum):
@@ -0,0 +1,14 @@
1
+ from collections.abc import Callable
2
+ from typing import Any
3
+
4
+
5
+ class QolsysObservable_v2:
6
+ def __init__(self) -> None:
7
+ self._observers: dict[str, Any] = {}
8
+
9
+ def subscribe(self, event_name: str, callback: Callable[[], None]) -> None:
10
+ self._observers.setdefault(event_name, []).append(callback)
11
+
12
+ def publish(self, event_name: str, *args: Any, **kwargs: Any) -> None:
13
+ for callback in self._observers.get(event_name, []):
14
+ callback(*args, **kwargs)
@@ -7,13 +7,18 @@ from typing import TYPE_CHECKING, Any
7
7
 
8
8
  from qolsys_controller.adc_device import QolsysAdcDevice
9
9
  from qolsys_controller.zwave_energy_clamp import QolsysEnergyClamp
10
+ from qolsys_controller.zwave_extenal_siren import QolsysExternalSiren
11
+ from qolsys_controller.zwave_garagedoor import QolsysGarageDoor
12
+ from qolsys_controller.zwave_smart_socket import QolsysSmartSocket
10
13
  from qolsys_controller.zwave_thermometer import QolsysThermometer
14
+ from qolsys_controller.zwave_water_valve import QolsysWaterValve
11
15
 
12
16
  from .database.db import QolsysDB
13
17
  from .enum import (
14
18
  PartitionAlarmState,
15
19
  PartitionAlarmType,
16
20
  PartitionSystemStatus,
21
+ QolsysEvent,
17
22
  )
18
23
  from .observable import QolsysObservable
19
24
  from .partition import QolsysPartition
@@ -452,6 +457,14 @@ class QolsysPanel(QolsysObservable):
452
457
  case "primaryDisconnect":
453
458
  LOGGER.info("Main Panel Disconnect")
454
459
 
460
+ case "eventNameDoorBell":
461
+ LOGGER.debug("Doorbell Event: %s", json.dumps(data))
462
+ self._controller.state.state_observer.publish(QolsysEvent.EVENT_PANEL_DOORBELL, data)
463
+
464
+ case "chime":
465
+ LOGGER.debug("Chime Event: %s", json.dumps(data))
466
+ self._controller.state.state_observer.publish(QolsysEvent.EVENT_PANEL_CHIME, data)
467
+
455
468
  case "dbChanged":
456
469
  match dbOperation:
457
470
  case "update":
@@ -901,23 +914,29 @@ class QolsysPanel(QolsysObservable):
901
914
  # Check if z-wave device is an Energy Clamp
902
915
  if device.get("node_type", "") == "Energy Clamp":
903
916
  LOGGER.debug(device)
904
- qolsys_meter_device = QolsysEnergyClamp(device)
917
+ qolsys_meter_device = QolsysEnergyClamp(self._controller, device)
905
918
  devices.append(qolsys_meter_device)
906
919
  device_added = True
907
920
 
908
921
  # Check if z-wave device is a thermometer
909
922
  if device.get("node_type", "") == "Thermometer":
910
- qolsys_thermometer = QolsysThermometer(device)
923
+ qolsys_thermometer = QolsysThermometer(self._controller, device)
911
924
  devices.append(qolsys_thermometer)
912
925
  device_added = True
913
926
 
927
+ # Check if z-wave device is an external siren
928
+ if device.get("node_type", "") == "External Siren":
929
+ qolsys_siren = QolsysExternalSiren(self._controller, device)
930
+ devices.append(qolsys_siren)
931
+ device_added = True
932
+
914
933
  # Check if z-wave device is a Dimmer
915
934
  for d in dimmers_list:
916
935
  dimmer_node_id = d.get("node_id", "")
917
936
 
918
937
  # Found a Dimmer
919
938
  if zwave_node_id == dimmer_node_id:
920
- qolsys_dimmer = QolsysDimmer(d, device)
939
+ qolsys_dimmer = QolsysDimmer(self._controller, d, device)
921
940
  devices.append(qolsys_dimmer)
922
941
  device_added = True
923
942
  break
@@ -928,7 +947,7 @@ class QolsysPanel(QolsysObservable):
928
947
 
929
948
  # Found a Thermostat
930
949
  if zwave_node_id == thermostat_node_id:
931
- qolsys_thermostat = QolsysThermostat(thermostat, device)
950
+ qolsys_thermostat = QolsysThermostat(self._controller, thermostat, device)
932
951
  devices.append(qolsys_thermostat)
933
952
  device_added = True
934
953
  break
@@ -939,18 +958,32 @@ class QolsysPanel(QolsysObservable):
939
958
 
940
959
  # Found a Lock
941
960
  if zwave_node_id == lock_node_id:
942
- qolsys_lock = QolsysLock(lock, device)
961
+ qolsys_lock = QolsysLock(self._controller, lock, device)
943
962
  devices.append(qolsys_lock)
944
963
  device_added = True
945
964
  break
946
965
 
947
966
  # Found a Smart Outlet
967
+ if device.get("node_type", "") == "Smart Socket":
968
+ qolsys_socket = QolsysSmartSocket(self._controller, device)
969
+ devices.append(qolsys_socket)
970
+ device_added = True
948
971
 
949
972
  # Found Garage Door Openner
973
+ if device.get("node_type", "") == "Garage Door":
974
+ qolsys_garagedoor = QolsysGarageDoor(self._controller, device)
975
+ devices.append(qolsys_garagedoor)
976
+ device_added = True
977
+
978
+ # Found a Water Valve
979
+ if device.get("node_type", "") == "Water Valve":
980
+ qolsys_watervalve = QolsysWaterValve(self._controller, device)
981
+ devices.append(qolsys_watervalve)
982
+ device_added = True
950
983
 
951
984
  # No Specific z-wave device found, add a generic z-wave device
952
985
  if not device_added:
953
- qolsys_generic = QolsysGeneric(device)
986
+ qolsys_generic = QolsysGeneric(self._controller, device)
954
987
  devices.append(qolsys_generic)
955
988
 
956
989
  return devices
@@ -987,9 +1020,7 @@ class QolsysPanel(QolsysObservable):
987
1020
  new_zone = QolsysZone(zone_info, self._controller.settings)
988
1021
 
989
1022
  if new_zone.current_capability == "POWERG":
990
- LOGGER.debug("Loading PowerG device info for zone %s", new_zone.zone_id)
991
1023
  powerg_dict = self.db.get_powerg(short_id=new_zone.shortID)
992
- LOGGER.debug("PowerG device info: %s", powerg_dict)
993
1024
  if powerg_dict is not None:
994
1025
  new_zone.update_powerg(powerg_dict)
995
1026
 
@@ -1042,7 +1073,7 @@ class QolsysPanel(QolsysObservable):
1042
1073
  LOGGER.debug("Z-Wave Firmware Version: %s", self.ZWAVE_FIRM_WARE_VERSION)
1043
1074
  LOGGER.debug("Z-Wave Card Present: %s", self.ZWAVE_CARD)
1044
1075
  LOGGER.debug("Z-Wave Controller Enabled: %s", self.ZWAVE_CONTROLLER)
1045
- LOGGER.debug("Partitons Enabled: %s", self.PARTITIONS)
1076
+ LOGGER.debug("Partitions Enabled: %s", self.PARTITIONS)
1046
1077
  LOGGER.debug("Control4 Enabled: %s", self.CONTROL_4)
1047
1078
  LOGGER.debug("Six Digit User Code Enabled: %s", self.SIX_DIGIT_USER_CODE)
1048
1079
  LOGGER.debug("Secure Arming: %s", self.SECURE_ARMING)