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
@@ -1,1298 +0,0 @@
1
- import asyncio
2
- import base64
3
- import contextlib
4
- import datetime
5
- import json
6
- import logging
7
- import random
8
- import ssl
9
- import uuid
10
-
11
- import aiofiles
12
- import aiomqtt
13
-
14
- from .enum import PartitionAlarmState, PartitionSystemStatus
15
- from .enum_zwave import ThermostatFanMode, ThermostatMode
16
- from .errors import QolsysMqttError, QolsysSslError
17
- from .mdns import QolsysMDNS
18
- from .mqtt_command_queue import QolsysMqttCommandQueue
19
- from .panel import QolsysPanel
20
- from .pki import QolsysPKI
21
- from .plugin import QolsysPlugin
22
- from .settings import QolsysSettings
23
- from .state import QolsysState
24
- from .task_manager import QolsysTaskManager
25
- from .utils_mqtt import generate_random_mac
26
-
27
- LOGGER = logging.getLogger(__name__)
28
-
29
-
30
- class QolsysPluginRemote(QolsysPlugin):
31
-
32
- def __init__(self, state: QolsysState, panel: QolsysPanel, settings: QolsysSettings) -> None:
33
- super().__init__(state, panel, settings)
34
-
35
- # PKI
36
- self._pki = QolsysPKI(settings=settings)
37
- self._auto_discover_pki = True
38
-
39
- # Plugin
40
- self.certificate_exchange_server = None
41
- self._check_user_code_on_arm = False
42
- self._check_user_code_on_disarm = True
43
- self._log_mqtt_messages = False
44
- self._task_manager = QolsysTaskManager()
45
- self._mqtt_command_queue = QolsysMqttCommandQueue()
46
-
47
- # MQTT Client
48
- self.aiomqtt = None
49
- self._mqtt_task_config_label = "mqtt_task_config"
50
- self._mqtt_task_listen_label = "mqtt_task_listen"
51
- self._mqtt_task_connect_label = "mqtt_task_connect"
52
- self._mqtt_task_ping_label = "mqtt_task_ping"
53
-
54
- @property
55
- def log_mqtt_mesages(self) -> bool:
56
- return self._log_mqtt_messages
57
-
58
- @log_mqtt_mesages.setter
59
- def log_mqtt_mesages(self, log_mqtt_mesages: bool) -> None:
60
- self._log_mqtt_messages = log_mqtt_mesages
61
-
62
- @property
63
- def check_user_code_on_disarm(self) -> bool:
64
- return self._check_user_code_on_disarm
65
-
66
- @check_user_code_on_disarm.setter
67
- def check_user_code_on_disarm(self, check_user_code_on_disarm: bool) -> None:
68
- self._check_user_code_on_disarm = check_user_code_on_disarm
69
-
70
- @property
71
- def check_user_code_on_arm(self) -> bool:
72
- return self._check_user_code_on_arm
73
-
74
- @check_user_code_on_arm.setter
75
- def check_user_code_on_arm(self, check_user_code_on_arm: bool) -> None:
76
- self._check_user_code_on_arm = check_user_code_on_arm
77
-
78
- @property
79
- def auto_discover_pki(self) -> bool:
80
- return self._auto_discover_pki
81
-
82
- @auto_discover_pki.setter
83
- def auto_discover_pki(self, value: bool) -> None:
84
- self._auto_discover_pki = value
85
-
86
- def is_paired(self) -> bool:
87
- # Check if plugin is paired:
88
- # 1- random_mac set
89
- # 2- KEY file present
90
- # 3- Signed certificate file present
91
- # 4- Qolsys certificate present
92
- # 5- Qolsys Panel IP present
93
- return (
94
- self._pki.id != "" and
95
- self._pki.check_key_file() and
96
- self._pki.check_cer_file() and
97
- self._pki.check_qolsys_cer_file() and
98
- self._pki.check_secure_file() and
99
- self.settings.check_panel_ip() and
100
- self.settings.check_plugin_ip()
101
- )
102
-
103
- async def config(self, start_pairing: bool) -> bool:
104
- return await self._task_manager.run(self.config_task(start_pairing), self._mqtt_task_config_label)
105
-
106
- async def config_task(self, start_pairing: bool) -> bool:
107
- LOGGER.debug("Configuring Plugin")
108
- super().config()
109
-
110
- # Check and created config_directory
111
- if not self.settings.check_config_directory(create=start_pairing):
112
- return False
113
-
114
- # Read user file for access code
115
- loop = asyncio.get_running_loop()
116
- if not loop.run_in_executor(None, self.panel.read_users_file):
117
- return False
118
-
119
- # Config PKI
120
- if self._auto_discover_pki:
121
- if self._pki.auto_discover_pki():
122
- self.settings.random_mac = self._pki.formatted_id()
123
- else:
124
- self._pki.set_id(self.settings.random_mac)
125
-
126
- # Set mqtt_remote_client_id
127
- self.settings.mqtt_remote_client_id = "qolsys-controller-" + self._pki.formatted_id()
128
- LOGGER.debug("Using MQTT remoteClientID: %s", self.settings.mqtt_remote_client_id)
129
-
130
- # Check if plugin is paired
131
- if self.is_paired():
132
- LOGGER.debug("Panel is Paired")
133
-
134
- else:
135
- LOGGER.debug("Panel not paired")
136
-
137
- if not start_pairing:
138
- LOGGER.debug("Aborting pairing.")
139
- return False
140
-
141
- if not await self.start_initial_pairing():
142
- LOGGER.debug("Error Pairing with Panel")
143
- return False
144
-
145
- LOGGER.debug("Starting Plugin Operation")
146
-
147
- # Everything is configured
148
- return True
149
-
150
- async def start_operation(self) -> None:
151
- await self._task_manager.run(self.mqtt_connect_task(reconnect=True, run_forever=True), self._mqtt_task_connect_label)
152
-
153
- async def stop_operation(self) -> None:
154
- LOGGER.debug("Stopping Plugin Operation")
155
-
156
- if self.certificate_exchange_server is not None:
157
- self.certificate_exchange_server.close()
158
-
159
- if self.aiomqtt is not None:
160
- await self.aiomqtt.__aexit__(None, None, None)
161
- self.aiomqtt = None
162
-
163
- self._task_manager.cancel(self._mqtt_task_connect_label)
164
- self._task_manager.cancel(self._mqtt_task_listen_label)
165
- self._task_manager.cancel(self._mqtt_task_ping_label)
166
- self._task_manager.cancel(self._mqtt_task_config_label)
167
-
168
- self.connected = False
169
- self.connected_observer.notify()
170
-
171
- async def mqtt_connect_task(self, reconnect: bool, run_forever: bool) -> None:
172
- # Configure TLS parameters for MQTT connection
173
- tls_params = aiomqtt.TLSParameters(
174
- ca_certs=self._pki.qolsys_cer_file_path,
175
- certfile=self._pki.secure_file_path,
176
- keyfile=self._pki.key_file_path,
177
- cert_reqs=ssl.CERT_REQUIRED,
178
- tls_version=ssl.PROTOCOL_TLSv1_2,
179
- ciphers="ALL:@SECLEVEL=0",
180
- )
181
-
182
- LOGGER.debug("MQTT: Connecting ...")
183
-
184
- self._task_manager.cancel(self._mqtt_task_listen_label)
185
- self._task_manager.cancel(self._mqtt_task_ping_label)
186
-
187
- while True:
188
- try:
189
- self.aiomqtt = aiomqtt.Client(
190
- hostname=self.settings.panel_ip,
191
- port=8883,
192
- tls_params=tls_params,
193
- tls_insecure=True,
194
- clean_session=True,
195
- timeout=self.settings.mqtt_timeout,
196
- identifier= self.settings.mqtt_remote_client_id,
197
- )
198
-
199
- await self.aiomqtt.__aenter__()
200
-
201
- LOGGER.info("MQTT: Client Connected")
202
-
203
- # Subscribe to panel internal databse updates
204
- await self.aiomqtt.subscribe("iq2meid")
205
-
206
- # Subscribte to MQTT commands response
207
- await self.aiomqtt.subscribe("response_" + self.settings.random_mac, qos=self.settings.mqtt_qos)
208
-
209
- # Subscribe to Z-Wave response
210
- await self.aiomqtt.subscribe("ZWAVE_RESPONSE", qos=self.settings.mqtt_qos)
211
-
212
- # Only log all traffic for debug purposes
213
- if self.log_mqtt_mesages:
214
- # Subscribe to MQTT commands send to panel by other devices
215
- await self.aiomqtt.subscribe("mastermeid", qos=self.settings.mqtt_qos)
216
-
217
- # Subscribe to all topics
218
- # await self.aiomqtt.subscribe("#", qos=self.settings.mqtt_qos)
219
-
220
- self._task_manager.run(self.mqtt_listen_task(), self._mqtt_task_listen_label)
221
- self._task_manager.run(self.mqtt_ping_task(), self._mqtt_task_ping_label)
222
-
223
- response_connect = await self.command_connect()
224
- self.panel.imei = response_connect.get("master_imei", "")
225
- self.panel.product_type = response_connect.get("primary_product_type", "")
226
-
227
- await self.command_pingevent()
228
- await self.command_pair_status_request()
229
-
230
- response_database = await self.command_sync_database()
231
- LOGGER.debug("MQTT: Updating State from syncdatabase")
232
- self.panel.load_database(response_database.get("fulldbdata"))
233
- self.panel.dump()
234
- self.state.dump()
235
-
236
- self.connected = True
237
- self.connected_observer.notify()
238
-
239
- if not run_forever:
240
- self.connected = False
241
- self.connected_observer.notify()
242
- self._task_manager.cancel(self._mqtt_task_listen_label)
243
- self._task_manager.cancel(self._mqtt_task_ping_label)
244
- await self.aiomqtt.__aexit__(None,None,None)
245
-
246
- break
247
-
248
- except aiomqtt.MqttError as err:
249
- # Receive pannel network error
250
- self.connected = False
251
- self.connected_observer.notify()
252
- self.aiomqtt = None
253
-
254
- if reconnect:
255
- LOGGER.debug("MQTT Error - %s: Connect - Reconnecting in %s seconds ...", err, self.settings.mqtt_timeout)
256
- await asyncio.sleep(self.settings.mqtt_timeout)
257
- else:
258
- raise QolsysMqttError from err
259
-
260
- except ssl.SSLError as err:
261
- # SSL error is and authentication error with invalid certificates en pki
262
- # We cannot recover from this error automaticly
263
- # Pannels need to be re-paired
264
- self.connected = False
265
- self.connected_observer.notify()
266
- self.aiomqtt = None
267
- raise QolsysSslError from err
268
-
269
- async def mqtt_ping_task(self) -> None:
270
- while True:
271
- if self.aiomqtt is not None and self.connected:
272
- with contextlib.suppress(aiomqtt.MqttError):
273
- await self.command_pingevent()
274
-
275
- await asyncio.sleep(self.settings.mqtt_ping)
276
-
277
- async def mqtt_listen_task(self) -> None:
278
- try:
279
- async for message in self.aiomqtt.messages:
280
-
281
- if self.log_mqtt_mesages:
282
- LOGGER.debug("MQTT TOPIC: %s\n%s", message.topic, message.payload.decode())
283
-
284
- # Panel response to MQTT Commands
285
- if message.topic.matches("response_" + self.settings.random_mac):
286
- data = message.payload.decode()
287
- # data = message.payload.decode().replace("\\\\", "\\")
288
- # data = fix_json_string(data)
289
- data = json.loads(data)
290
- await self._mqtt_command_queue.handle_response(data)
291
-
292
- # Panel updates to IQ2MEID database
293
- if message.topic.matches("iq2meid"):
294
- data = json.loads(message.payload.decode())
295
- self.panel.parse_iq2meid_message(data)
296
-
297
- # Panel Z-Wave response
298
- if message.topic.matches("ZWAVE_RESPONSE"):
299
- data = json.loads(message.payload.decode())
300
- zwave = data.get("ZWAVE_RESPONSE","")
301
- decoded_payload = base64.b64decode(zwave.get("ZWAVE_PAYLOAD","")).hex()
302
- LOGGER.debug("Z-Wave Response: Node(%s) - Status(%s) - Payload(%s)",zwave.get("NODE_ID",""),zwave.get("ZWAVE_COMMAND_STATUS",""),decoded_payload)
303
-
304
- except aiomqtt.MqttError as err:
305
- self.connected = False
306
- self.connected_observer.notify()
307
-
308
- LOGGER.debug("%s: Listen - Reconnecting in %s seconds ...", err, self.settings.mqtt_timeout)
309
- await asyncio.sleep(self.settings.mqtt_timeout)
310
- self._task_manager.run(self.mqtt_connect_task(reconnect=True, run_forever=True), self._mqtt_task_connect_label)
311
-
312
- async def start_initial_pairing(self) -> bool:
313
- # check if random_mac exist
314
- if self.settings.random_mac == "":
315
- LOGGER.debug("Creating random_mac")
316
- self.settings.random_mac = generate_random_mac()
317
- self._pki.create(self.settings.random_mac, key_size=self.settings.key_size)
318
-
319
- # Check if PKI is valid
320
- self._pki.set_id(self.settings.random_mac)
321
- LOGGER.debug("Checking PKI")
322
- if not (
323
- self._pki.check_key_file() and
324
- self._pki.check_cer_file() and
325
- self._pki.check_csr_file()
326
- ):
327
- LOGGER.error("PKI Error")
328
- return False
329
-
330
- LOGGER.debug("Starting Pairing Process")
331
-
332
- if not self.settings.check_plugin_ip():
333
- LOGGER.error("Plugin IP Address not configured")
334
- return False
335
-
336
- # If we dont allready have client signed certificate, start the pairing server
337
- if not self._pki.check_secure_file() or not self._pki.check_qolsys_cer_file() or not self.settings.check_panel_ip():
338
-
339
- # High Level Random Pairing Port
340
- pairing_port = random.randint(50000, 55000)
341
-
342
- # Start Pairing mDNS Brodcast
343
- LOGGER.debug("Starting mDNS Service Discovery: %s:%s", self.settings.plugin_ip, str(pairing_port))
344
- mdns_server = QolsysMDNS(self.settings.plugin_ip, pairing_port)
345
- await mdns_server.start_mdns()
346
-
347
- # Start Key Exchange Server
348
- LOGGER.debug("Starting Certificate Exchange Server")
349
- context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
350
- context.load_cert_chain(certfile=self._pki.cer_file_path, keyfile=self._pki.key_file_path)
351
- self.certificate_exchange_server = await asyncio.start_server(self.handle_key_exchange_client,
352
- self.settings.plugin_ip, pairing_port, ssl=context)
353
- LOGGER.debug("Certificate Exchange Server Waiting for Panel")
354
- LOGGER.debug("Press Pair Button in IQ Remote Config Page ...")
355
-
356
- async with self.certificate_exchange_server:
357
- try:
358
- await self.certificate_exchange_server.serve_forever()
359
-
360
- except asyncio.CancelledError:
361
- LOGGER.debug("Stoping Certificate Exchange Server")
362
- await self.certificate_exchange_server.wait_closed()
363
- LOGGER.debug("Stoping mDNS Service Discovery")
364
- await mdns_server.stop_mdns()
365
-
366
- LOGGER.debug("Sending MQTT Pairing Request to Panel")
367
-
368
- # We have client sgined certificate at this point
369
- # Connect to Panel MQTT to send pairing command
370
- await self._task_manager.run(self.mqtt_connect_task(reconnect=False, run_forever=False), self._mqtt_task_connect_label)
371
- LOGGER.debug("Plugin Pairing Completed ")
372
- return True
373
-
374
- async def handle_key_exchange_client(self, reader: asyncio.StreamReader, writer: asyncio.StreamWriter) -> None: # noqa: PLR0915
375
-
376
- received_panel_mac = False
377
- received_signed_client_certificate = False
378
- received_qolsys_cer = False
379
-
380
- try:
381
- continue_pairing = True
382
- while continue_pairing:
383
-
384
- # Plugin is receiving panel_mac from panel
385
- if (not received_panel_mac and not received_signed_client_certificate and not received_qolsys_cer):
386
-
387
- request = (await reader.read(2048))
388
- mac = request.decode()
389
-
390
- address, port = writer.get_extra_info("peername")
391
- LOGGER.debug("Panel Connected from: %s:%s", address, port)
392
- LOGGER.debug("Receiving from Panel: %s", mac)
393
-
394
- # Remove \x00 and \x01 from received string
395
- self.settings.panel_mac = "".join(char for char in mac if char.isprintable())
396
- self.settings.panel_ip = address
397
- received_panel_mac = True
398
-
399
- # Sending random_mac to panel
400
- message = b"\x00\x11" + self.settings.random_mac.encode()
401
- LOGGER.debug("Sending to Panel: %s", message.decode())
402
- writer.write(message)
403
- await writer.drain()
404
-
405
- # Sending CSR File to panel
406
- async with aiofiles.open(self._pki.csr_file_path, mode='rb') as f:
407
- content = await f.read()
408
- LOGGER.debug("Sending to Panel: [CSR File Content]")
409
- writer.write(content)
410
- writer.write(b"sent")
411
- await writer.drain()
412
-
413
- continue
414
-
415
- # Read signed certificate data
416
- if (received_panel_mac and not received_signed_client_certificate and not received_qolsys_cer):
417
- request = await reader.readuntil(b"sent")
418
- if request.endswith(b"sent"):
419
- request = request[:-4]
420
-
421
- LOGGER.debug("Saving [Signed Client Certificate]")
422
- async with aiofiles.open(self._pki.secure_file_path, mode="wb") as f:
423
- await f.write(request)
424
- received_signed_client_certificate = True
425
-
426
- # Read qolsys certificate data
427
- if (received_panel_mac and received_signed_client_certificate and not received_qolsys_cer):
428
- request = await reader.readuntil(b"sent")
429
- if request.endswith(b"sent"):
430
- request = request[:-4]
431
-
432
- LOGGER.debug("Saving [Qolsys Certificate]")
433
- async with aiofiles.open(self._pki.qolsys_cer_file_path, mode="wb") as f:
434
- await f.write(request)
435
- received_qolsys_cer = True
436
- continue_pairing = False
437
-
438
- continue
439
-
440
- except asyncio.CancelledError:
441
- LOGGER.exception("Key Exchange Server asyncio CancelledError")
442
-
443
- except Exception:
444
- LOGGER.exception("Key Exchange Server error")
445
-
446
- finally:
447
- writer.close()
448
- await writer.wait_closed()
449
- self.certificate_exchange_server.close()
450
-
451
- async def send_command(self, topic: str, json_payload: str, request_id: str) -> dict:
452
- if self.aiomqtt is None:
453
- LOGGER.error("MQTT Client not configured")
454
- raise QolsysMqttError
455
-
456
- await self.aiomqtt.publish(topic=topic, payload=json.dumps(json_payload), qos=self.settings.mqtt_qos)
457
- return await self._mqtt_command_queue.wait_for_response(request_id)
458
-
459
- async def command_connect(self) -> dict:
460
- LOGGER.debug("MQTT: Sending connect command")
461
-
462
- topic = "mastermeid"
463
- ipAddress = self.settings.plugin_ip
464
- eventName = "connect_v204"
465
- macAddress = self.settings.random_mac
466
- remoteClientID = self.settings.mqtt_remote_client_id
467
- softwareVersion = "4.4.1"
468
- producType = "tab07_rk68"
469
- bssid = ""
470
- lastUpdateChecksum = "2132501716"
471
- dealerIconsCheckSum = ""
472
- remote_feature_support_version = "1"
473
- current_battery_status = "Normal"
474
- remote_panel_battery_status = 3
475
- remote_panel_battery_health = 2
476
- remote_panel_battery_level = 100
477
- remote_panel_battery_present = True
478
- remote_panel_battery_percentage = 100
479
- remote_panel_battery_scale = 100
480
- remote_panel_battery_voltage = 4082
481
- remote_panel_battery_technology = ""
482
- remote_panel_plugged = 1
483
- remote_panel_battery_temperature = 430
484
- requestID = str(uuid.uuid4())
485
- responseTopic = "response_" + self.settings.random_mac
486
- remoteMacAddress = self.settings.random_mac
487
-
488
- dhcpInfo = {
489
- "ipaddress": "",
490
- "gateway": "",
491
- "netmask": "",
492
- "dns1": "",
493
- "dns2": "",
494
- "dhcpServer": "",
495
- "leaseDuration": "",
496
- }
497
-
498
- payload = {
499
- "eventName": eventName,
500
- "pairing_request": True,
501
- "ipAddress": ipAddress,
502
- "macAddress": macAddress,
503
- "remoteClientID": remoteClientID,
504
- "softwareVersion": softwareVersion,
505
- "productType": producType,
506
- "bssid": bssid,
507
- "dhcpInfo": json.dumps(dhcpInfo),
508
- "lastUpdateChecksum": lastUpdateChecksum,
509
- "dealerIconsCheckSum": dealerIconsCheckSum,
510
- "remote_feature_support_version": remote_feature_support_version,
511
- "current_battery_status": current_battery_status,
512
- "remote_panel_battery_status": remote_panel_battery_status,
513
- "remote_panel_battery_health": remote_panel_battery_health,
514
- "remote_panel_battery_level": remote_panel_battery_level,
515
- "remote_panel_battery_present": remote_panel_battery_present,
516
- "remote_panel_battery_percentage": remote_panel_battery_percentage,
517
- "remote_panel_battery_scale": remote_panel_battery_scale,
518
- "remote_panel_battery_voltage": remote_panel_battery_voltage,
519
- "remote_panel_battery_technology": remote_panel_battery_technology,
520
- "remote_panel_plugged": remote_panel_plugged,
521
- "remote_panel_battery_temperature": remote_panel_battery_temperature,
522
- "requestID": requestID,
523
- "responseTopic": responseTopic,
524
- "remoteMacAddess": remoteMacAddress,
525
- }
526
-
527
- response = await self.send_command(topic, payload, requestID)
528
- LOGGER.debug("MQTT: Receiving connect command")
529
- return response
530
-
531
- async def command_pingevent(self) -> None:
532
- LOGGER.debug("MQTT: Sending pingevent command")
533
-
534
- topic = "mastermeid"
535
- eventName = "pingevent"
536
- macAddress = self.settings.random_mac
537
- remote_panel_status = "Active"
538
- ipAddress = self.settings.plugin_ip
539
- current_battery_status = "Normal"
540
- remote_panel_battery_percentage = 100
541
- remote_panel_battery_temperature = 430
542
- remote_panel_battery_status = 3
543
- remote_panel_battery_scale = 100
544
- remote_panel_battery_voltage = 4102
545
- remote_panel_battery_present = True
546
- remote_panel_battery_technology = ""
547
- remote_panel_battery_level = 100
548
- remote_panel_battery_health = 2
549
- remote_panel_plugged = 1
550
- requestID = str(uuid.uuid4())
551
- remoteMacAddress = self.settings.random_mac
552
- responseTopic = "response_" + self.settings.random_mac
553
-
554
- payload = {
555
- "eventName": eventName,
556
- "macAddress": macAddress,
557
- "remote_panel_status": remote_panel_status,
558
- "ipAddress": ipAddress,
559
- "current_battery_status": current_battery_status,
560
- "remote_panel_battery_percentage": remote_panel_battery_percentage,
561
- "remote_panel_battery_temperature": remote_panel_battery_temperature,
562
- "remote_panel_battery_status": remote_panel_battery_status,
563
- "remote_panel_battery_scale": remote_panel_battery_scale,
564
- "remote_panel_battery_voltage": remote_panel_battery_voltage,
565
- "remote_panel_battery_present": remote_panel_battery_present,
566
- "remote_panel_battery_technology": remote_panel_battery_technology,
567
- "remote_panel_battery_level": remote_panel_battery_level,
568
- "remote_panel_battery_health": remote_panel_battery_health,
569
- "remote_panel_plugged": remote_panel_plugged,
570
- "requestID": requestID,
571
- "responseTopic": responseTopic,
572
- "remoteMacAddess": remoteMacAddress,
573
- }
574
-
575
- await self.send_command(topic, payload, requestID)
576
- LOGGER.debug("MQTT: Receiving pingevent command")
577
-
578
- async def command_timesync(self) -> None:
579
- LOGGER.debug("MQTT: Sending timeSync command")
580
-
581
- topic = "mastermeid"
582
- eventName = "timeSync"
583
- startTimestamp = datetime.datetime.now().timestamp()
584
- requestID = str(uuid.uuid4())
585
- responseTopic = "response_" + self.settings.random_mac
586
- remoteMacAddress = self.settings.random_mac
587
-
588
- payload = {
589
- "eventName": eventName,
590
- "startTimestamp": startTimestamp,
591
- "requestID": requestID,
592
- "responseTopic": responseTopic,
593
- "remoteMacAddess": remoteMacAddress,
594
- }
595
-
596
- await self.send_command(topic, payload, requestID)
597
- LOGGER.debug("MQTT: Receiving timeSync command")
598
-
599
- async def command_sync_database(self) -> dict:
600
- LOGGER.debug("MQTT: Sending syncdatabase command")
601
-
602
- topic = "mastermeid"
603
- eventName = "syncdatabase"
604
- requestID = str(uuid.uuid4())
605
- responseTopic = "response_" + self.settings.random_mac
606
- remoteMacAddress = self.settings.random_mac
607
-
608
- payload = {
609
- "eventName": eventName,
610
- "requestID": requestID,
611
- "responseTopic": responseTopic,
612
- "remoteMacAddess": remoteMacAddress,
613
- }
614
-
615
- response = await self.send_command(topic, payload, requestID)
616
- LOGGER.debug("MQTT: Receiving syncdatabase command")
617
- return response
618
-
619
- async def command_acstatus(self) -> None:
620
- LOGGER.debug("MQTT: Sending acStatus command")
621
-
622
- topic = "mastermeid"
623
- eventName = "acStatus"
624
- requestID = str(uuid.uuid4())
625
- responseTopic = "response_" + self.settings.random_mac
626
- remoteMacAddress = self.settings.random_mac
627
- acStatus = "Connected"
628
-
629
- payload = {"eventName": eventName,
630
- "acStatus": acStatus,
631
- "requestID": requestID,
632
- "responseTopic": responseTopic,
633
- "remoteMacAddess": remoteMacAddress}
634
-
635
- await self.send_command(topic, payload, requestID)
636
-
637
- async def command_dealer_logo(self) -> None:
638
- LOGGER.debug("MQTT: Sending dealerLogo command")
639
-
640
- topic = "mastermeid"
641
- eventName = "dealerLogo"
642
- requestID = str(uuid.uuid4())
643
- responseTopic = "response_" + self.settings.random_mac
644
- remoteMacAddress = self.settings.random_mac
645
-
646
- payload = {
647
- "eventName": eventName,
648
- "requestID": requestID,
649
- "responseTopic": responseTopic,
650
- "remoteMacAddess": remoteMacAddress,
651
- }
652
-
653
- await self.send_command(topic, payload, requestID)
654
-
655
- async def command_pair_status_request(self) -> None:
656
- LOGGER.debug("MQTT: Sending pair_status_request command")
657
-
658
- topic = "mastermeid"
659
- eventName = "pair_status_request"
660
- remoteMacAddress = self.settings.random_mac
661
- requestID = str(uuid.uuid4())
662
- responseTopic = "response_" + self.settings.random_mac
663
-
664
- payload = {
665
- "eventName": eventName,
666
- "requestID": requestID,
667
- "responseTopic": responseTopic,
668
- "remoteMacAddess": remoteMacAddress,
669
- }
670
-
671
- await self.send_command(topic, payload, requestID)
672
- LOGGER.debug("MQTT: Receiving pair_status_request command")
673
-
674
- async def command_disconnect(self) -> None:
675
- LOGGER.debug("MQTT: Sending disconnect command")
676
-
677
- topic = "mastermeid"
678
- eventName = "disconnect"
679
- remoteClientID = self.settings.mqtt_remote_client_id
680
- requestID = str(uuid.uuid4())
681
- remoteMacAddress = self.settings.random_mac
682
-
683
- payload = {
684
- "eventName": eventName,
685
- "remoteClientID": remoteClientID,
686
- "requestID": requestID,
687
- "remoteMacAddess": remoteMacAddress,
688
- }
689
-
690
- await self.send_command(topic, payload, requestID)
691
-
692
- async def command_pairing_request(self) -> dict:
693
- LOGGER.debug("MQTT: Sending pairing_request command")
694
-
695
- topic = "mastermeid"
696
- eventName = "connect_v204"
697
- pairing_request = True
698
- ipAddress = self.settings.plugin_ip
699
- macAddress = self.settings.random_mac
700
- remoteClientID = self.settings.mqtt_remote_client_id
701
- softwareVersion = "4.4.1"
702
- productType = "tab07_rk68"
703
- bssid = ""
704
- lastUpdateChecksum = "2132501716"
705
- dealerIconsCheckSum = ""
706
- remote_feature_support_version = "1"
707
- requestID = str(uuid.uuid4())
708
- responseTopic = "response_" + self.settings.random_mac
709
- remoteMacAddress = self.settings.random_mac
710
-
711
- dhcpInfo = {
712
- "ipaddress": "",
713
- "gateway": "",
714
- "netmask": "",
715
- "dns1": "",
716
- "dns2": "",
717
- "dhcpServer": "",
718
- "leaseDuration": "",
719
- }
720
-
721
- payload = {
722
- "eventName": eventName,
723
- "pairing_request": pairing_request,
724
- "ipAddress": ipAddress,
725
- "macAddress": macAddress,
726
- "remoteClientID": remoteClientID,
727
- "softwareVersion": softwareVersion,
728
- "producType": productType,
729
- "bssid": bssid,
730
- "dhcpInfo": json.dumps(dhcpInfo),
731
- "lastUpdateChecksum": lastUpdateChecksum,
732
- "dealerIconsCheckSum": dealerIconsCheckSum,
733
- "remote_feature_support_version": remote_feature_support_version,
734
- "requestID": requestID,
735
- "responseTopic": responseTopic,
736
- "remoteMacAddess": remoteMacAddress,
737
- }
738
-
739
- response = await self.send_command(topic, payload, requestID)
740
- LOGGER.debug("MQTT: Receiving pairing_request command")
741
- return response
742
-
743
- async def command_ui_delay(self, partition_id: str,silent_disarming:bool = False) -> None:
744
- LOGGER.debug("MQTT: Sending ui_delay command")
745
-
746
- # partition state needs to be sent for ui_delay to work
747
- partition = self.state.partition(partition_id)
748
-
749
- arming_command = {
750
- "operation_name": "ui_delay",
751
- "panel_status": partition.system_status,
752
- "userID": 0,
753
- "partitionID": partition_id, # STR EXPECTED
754
- "silentDisarming":silent_disarming,
755
- "operation_source": 1,
756
- "macAddress": self.settings.random_mac,
757
- }
758
-
759
- topic = "mastermeid"
760
- eventName = "ipcCall"
761
- ipcServiceName = "qinternalservice"
762
- ipcInterfaceName = "android.os.IQInternalService"
763
- ipcTransactionID = 7
764
- requestID = str(uuid.uuid4())
765
- remoteMacAddress = self.settings.random_mac
766
- responseTopic = "response_" + self.settings.random_mac
767
-
768
- payload = {
769
- "eventName": eventName,
770
- "ipcServiceName": ipcServiceName,
771
- "ipcInterfaceName": ipcInterfaceName,
772
- "ipcTransactionID": ipcTransactionID,
773
- "ipcRequest": [{
774
- "dataType": "string",
775
- "dataValue": json.dumps(arming_command),
776
- }],
777
- "requestID": requestID,
778
- "responseTopic": responseTopic,
779
- "remoteMacAddress": remoteMacAddress,
780
- }
781
-
782
- await self.send_command(topic, payload, requestID)
783
- LOGGER.debug("MQTT: Receiving ui_delay command")
784
-
785
- async def command_disarm(self, partition_id: str, user_code: str = "", silent_disarming: bool = False) -> bool:
786
- partition = self.state.partition(partition_id)
787
- if not partition:
788
- LOGGER.debug("MQTT: disarm command error - Unknow Partition")
789
- return False
790
-
791
- # Do local user code verification
792
- user_id = 1
793
- if self.check_user_code_on_disarm:
794
- user_id = self.panel.check_user(user_code)
795
- if user_id == -1:
796
- LOGGER.debug("MQTT: disarm command error - user_code error")
797
- return False
798
-
799
- async def get_mqtt_disarm_command(silent_disarming:bool) -> str:
800
- if partition.alarm_state == PartitionAlarmState.ALARM:
801
- return "disarm_from_emergency"
802
- if partition.system_status in {PartitionSystemStatus.ARM_AWAY_EXIT_DELAY,
803
- PartitionSystemStatus.ARM_STAY_EXIT_DELAY,
804
- PartitionSystemStatus.ARM_NIGHT_EXIT_DELAY}:
805
- return "disarm_from_openlearn_sensor"
806
- if partition.system_status in {PartitionSystemStatus.ARM_AWAY,
807
- PartitionSystemStatus.ARM_STAY,
808
- PartitionSystemStatus.ARM_NIGHT}:
809
- await self.command_ui_delay(partition_id,silent_disarming)
810
- return "disarm_the_panel_from_entry_delay"
811
-
812
- return "disarm_from_openlearn_sensor"
813
-
814
- mqtt_disarm_command = await get_mqtt_disarm_command(silent_disarming)
815
- LOGGER.debug("MQTT: Sending disarm command - check_user_code:%s", self.check_user_code_on_disarm)
816
-
817
- disarm_command = {
818
- "operation_name": mqtt_disarm_command,
819
- "userID": user_id,
820
- "partitionID": int(partition_id), # INT EXPECTED
821
- "operation_source": 1,
822
- "macAddress": self.settings.random_mac,
823
- }
824
-
825
- topic = "mastermeid"
826
- eventName = "ipcCall"
827
- ipcServiceName = "qinternalservice"
828
- ipcInterfaceName = "android.os.IQInternalService"
829
- ipcTransactionID = 7
830
- requestID = str(uuid.uuid4())
831
- remoteMacAddress = self.settings.random_mac
832
- responseTopic = "response_" + self.settings.random_mac
833
-
834
- payload = {"eventName": eventName,
835
- "ipcServiceName": ipcServiceName,
836
- "ipcInterfaceName": ipcInterfaceName,
837
- "ipcTransactionID": ipcTransactionID,
838
- "ipcRequest": [{
839
- "dataType": "string",
840
- "dataValue": json.dumps(disarm_command),
841
- }],
842
- "requestID": requestID,
843
- "responseTopic": responseTopic,
844
- "remoteMacAddress": remoteMacAddress}
845
-
846
- await self.send_command(topic, payload, requestID)
847
- LOGGER.debug("MQTT: Receiving disarm command")
848
-
849
- return True
850
-
851
- async def command_zwave_doorlock_set(self, node_id: int, locked:bool) -> None:
852
- LOGGER.debug("MQTT: Sending zwave_doorlock_set command: EXPERIMENTAL")
853
- LOGGER.debug("MQTT: Sending zwave_doorlock_set command - Node(%s) - Locked(%s)",node_id,locked)
854
-
855
- command = 98
856
-
857
- # 0 unlocked
858
- # 255 locked
859
- lock_mode = 0
860
- if locked:
861
- lock_mode = 255
862
-
863
- ipcRequest = [{
864
- "dataType": "int",
865
- "dataValue": node_id,
866
- },
867
- {
868
- "dataType": "int",
869
- "dataValue": 0,
870
- },
871
- {
872
- "dataType": "byteArray",
873
- "dataValue": [command,1,lock_mode],
874
- },
875
- {
876
- "dataType": "int",
877
- "dataValue": 0,
878
- },
879
- {
880
- "dataType": "int",
881
- "dataValue": 106,
882
- },
883
- {
884
- "dataType": "byteArray",
885
- "dataValue": [0],
886
- },
887
- ]
888
-
889
- topic = "mastermeid"
890
- eventName = "ipcCall"
891
- ipcServiceName = "qzwaveservice"
892
- ipcInterfaceName = "android.os.IQZwaveService"
893
- ipcTransactionID = 47
894
- requestID = str(uuid.uuid4())
895
- remoteMacAddress = self.settings.random_mac
896
- responseTopic = "response_" + self.settings.random_mac
897
-
898
- payload = {
899
- "eventName": eventName,
900
- "ipcServiceName": ipcServiceName,
901
- "ipcInterfaceName": ipcInterfaceName,
902
- "ipcTransactionID": ipcTransactionID,
903
- "ipcRequest": ipcRequest,
904
- "requestID": requestID,
905
- "responseTopic": responseTopic,
906
- "remoteMacAddress": remoteMacAddress,
907
- }
908
-
909
- await self.send_command(topic, payload, requestID)
910
- LOGGER.debug("MQTT: Receiving zwave_doorlock_set command")
911
-
912
- async def command_zwave_thermostat_setpoint_set(self, node_id: int, mode:ThermostatMode, setpoint:float) -> None:
913
- # Command 67
914
- LOGGER.debug("MQTT: Sending zwave_thermostat_setpoint_set command: EXPERIMENTAL")
915
- LOGGER.debug("MQTT: Sending zwave_thermostat_setpoint_set - Node(%s) - Mode(%s) - Setpoint(%s)",node_id,mode,setpoint)
916
- ipcRequest = [{
917
- "dataType": "int",
918
- "dataValue": node_id,
919
- },
920
- {
921
- "dataType": "int",
922
- "dataValue": 0,
923
- },
924
- {
925
- "dataType": "byteArray",
926
- "dataValue": [67,1,mode,setpoint],
927
- },
928
- {
929
- "dataType": "int",
930
- "dataValue": 0,
931
- },
932
- {
933
- "dataType": "int",
934
- "dataValue": 106,
935
- },
936
- {
937
- "dataType": "byteArray",
938
- "dataValue": [0],
939
- },
940
- ]
941
-
942
- topic = "mastermeid"
943
- eventName = "ipcCall"
944
- ipcServiceName = "qzwaveservice"
945
- ipcInterfaceName = "android.os.IQZwaveService"
946
- ipcTransactionID = 47
947
- requestID = str(uuid.uuid4())
948
- remoteMacAddress = self.settings.random_mac
949
- responseTopic = "response_" + self.settings.random_mac
950
-
951
- payload = {"eventName": eventName,
952
- "ipcServiceName": ipcServiceName,
953
- "ipcInterfaceName": ipcInterfaceName,
954
- "ipcTransactionID": ipcTransactionID,
955
- "ipcRequest": ipcRequest,
956
- "requestID": requestID,
957
- "responseTopic": responseTopic,
958
- "remoteMacAddress": remoteMacAddress}
959
-
960
- await self.send_command(topic, payload, requestID)
961
- LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command")
962
-
963
- async def command_zwave_thermostat_mode_set(self, node_id: int, mode:ThermostatMode) -> None:
964
- # Command 64
965
- LOGGER.debug("MQTT: Sending zwave_thermostat_mode_set command: EXPERIMENTAL")
966
- LOGGER.debug("MQTT: Sending zwave_thermostat_mode_set command - Node(%s) - Mode(%s)",node_id,mode)
967
- ipcRequest = [{
968
- "dataType": "int",
969
- "dataValue": node_id,
970
- },
971
- {
972
- "dataType": "int",
973
- "dataValue": 0,
974
- },
975
- {
976
- "dataType": "byteArray",
977
- "dataValue": [64,1,mode],
978
- },
979
- {
980
- "dataType": "int",
981
- "dataValue": 0,
982
- },
983
- {
984
- "dataType": "int",
985
- "dataValue": 106,
986
- },
987
- {
988
- "dataType": "byteArray",
989
- "dataValue": [0],
990
- },
991
- ]
992
-
993
- topic = "mastermeid"
994
- eventName = "ipcCall"
995
- ipcServiceName = "qzwaveservice"
996
- ipcInterfaceName = "android.os.IQZwaveService"
997
- ipcTransactionID = 47
998
- requestID = str(uuid.uuid4())
999
- remoteMacAddress = self.settings.random_mac
1000
- responseTopic = "response_" + self.settings.random_mac
1001
-
1002
- payload = {
1003
- "eventName": eventName,
1004
- "ipcServiceName": ipcServiceName,
1005
- "ipcInterfaceName": ipcInterfaceName,
1006
- "ipcTransactionID": ipcTransactionID,
1007
- "ipcRequest": ipcRequest,
1008
- "requestID": requestID,
1009
- "responseTopic": responseTopic,
1010
- "remoteMacAddress": remoteMacAddress,
1011
- }
1012
-
1013
- await self.send_command(topic, payload, requestID)
1014
- LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command")
1015
-
1016
- async def command_zwave_thermostat_fan_mode_set(self, node_id: int, fan_mode:ThermostatFanMode) -> None:
1017
- # Command 68
1018
- LOGGER.debug("MQTT: Sending zwave_thermostat_fan_mode_set command: EXPERIMENTAL")
1019
- LOGGER.debug("MQTT: Sending zwave_thermostat_fan_mode_set command - Node(%s) - FanMode(%s)",node_id,fan_mode)
1020
- ipcRequest = [{
1021
- "dataType": "int",
1022
- "dataValue": node_id,
1023
- },
1024
- {
1025
- "dataType": "int",
1026
- "dataValue": 0,
1027
- },
1028
- {
1029
- "dataType": "byteArray",
1030
- "dataValue": [68,1,fan_mode],
1031
- },
1032
- {
1033
- "dataType": "int",
1034
- "dataValue": 0,
1035
- },
1036
- {
1037
- "dataType": "int",
1038
- "dataValue": 106,
1039
- },
1040
- {
1041
- "dataType": "byteArray",
1042
- "dataValue": [0],
1043
- },
1044
- ]
1045
-
1046
- topic = "mastermeid"
1047
- eventName = "ipcCall"
1048
- ipcServiceName = "qzwaveservice"
1049
- ipcInterfaceName = "android.os.IQZwaveService"
1050
- ipcTransactionID = 47
1051
- requestID = str(uuid.uuid4())
1052
- remoteMacAddress = self.settings.random_mac
1053
- responseTopic = "response_" + self.settings.random_mac
1054
-
1055
- payload = {"eventName": eventName,
1056
- "ipcServiceName": ipcServiceName,
1057
- "ipcInterfaceName": ipcInterfaceName,
1058
- "ipcTransactionID": ipcTransactionID,
1059
- "ipcRequest": ipcRequest,
1060
- "requestID": requestID,
1061
- "responseTopic": responseTopic,
1062
- "remoteMacAddress": remoteMacAddress}
1063
-
1064
- await self.send_command(topic, payload, requestID)
1065
- LOGGER.debug("MQTT: Receiving zwave_thermostat_fan_mode_set command")
1066
-
1067
- async def command_zwave_switch_multi_level(self, node_id: int, level: int) -> None:
1068
- LOGGER.debug("MQTT: Sending zwave_switch_multi_level command - Node(%s) - Level(%s)",node_id,level)
1069
- ipcRequest = [{
1070
- "dataType": "int", # Node ID
1071
- "dataValue": node_id,
1072
- },
1073
- {
1074
- "dataType": "int", # ?
1075
- "dataValue": 0,
1076
- },
1077
- {
1078
- # [38,1,level] ZWAVE MULTILEVELSWITCH SET (level 255 to set to previous state)
1079
- "dataType": "byteArray",
1080
- "dataValue": [38,1,level],
1081
- },
1082
- {
1083
- "dataType": "int", # ?
1084
- "dataValue": 0,
1085
- },
1086
- {
1087
- "dataType": "int", # ?
1088
- "dataValue": 106,
1089
- },
1090
- {
1091
- "dataType": "byteArray",
1092
- "dataValue": [0],
1093
- },
1094
- ]
1095
-
1096
- topic = "mastermeid"
1097
- eventName = "ipcCall"
1098
- ipcServiceName = "qzwaveservice"
1099
- ipcInterfaceName = "android.os.IQZwaveService"
1100
- ipcTransactionID = 47
1101
- requestID = str(uuid.uuid4())
1102
- remoteMacAddress = self.settings.random_mac
1103
- responseTopic = "response_" + self.settings.random_mac
1104
-
1105
- payload = {"eventName": eventName,
1106
- "ipcServiceName": ipcServiceName,
1107
- "ipcInterfaceName": ipcInterfaceName,
1108
- "ipcTransactionID": ipcTransactionID,
1109
- "ipcRequest": ipcRequest,
1110
- "requestID": requestID,
1111
- "responseTopic": responseTopic,
1112
- "remoteMacAddress": remoteMacAddress}
1113
-
1114
- await self.send_command(topic, payload, requestID)
1115
- LOGGER.debug("MQTT: Receiving zwave_switch_multi_level command")
1116
-
1117
- async def command_zwave_switch_binary(self, node_id: int, status:bool) -> None:
1118
- LOGGER.debug("MQTT:Sending zwave_switch_binary command")
1119
-
1120
- level = 0
1121
- if status:
1122
- level = 99
1123
-
1124
- ipcRequest = [{
1125
- "dataType": "int",
1126
- "dataValue": node_id,
1127
- },
1128
- {
1129
- "dataType": "int",
1130
- "dataValue": 0,
1131
- },
1132
- {
1133
- "dataType": "byteArray",
1134
- "dataValue": [37,1,level],
1135
- },
1136
- {
1137
- "dataType": "int",
1138
- "dataValue": 0,
1139
- },
1140
- {
1141
- "dataType": "int",
1142
- "dataValue": 106,
1143
- },
1144
- {
1145
- "dataType": "byteArray",
1146
- "dataValue": [0],
1147
- },
1148
- ]
1149
-
1150
- topic = "mastermeid"
1151
- eventName = "ipcCall"
1152
- ipcServiceName = "qzwaveservice"
1153
- ipcInterfaceName = "android.os.IQZwaveService"
1154
- ipcTransactionID = 47
1155
- requestID = str(uuid.uuid4())
1156
- remoteMacAddress = self.settings.random_mac
1157
- responseTopic = "response_" + self.settings.random_mac
1158
-
1159
- payload = {"eventName": eventName,
1160
- "ipcServiceName": ipcServiceName,
1161
- "ipcInterfaceName": ipcInterfaceName,
1162
- "ipcTransactionID": ipcTransactionID,
1163
- "ipcRequest": ipcRequest,
1164
- "requestID": requestID,
1165
- "responseTopic": responseTopic,
1166
- "remoteMacAddress": remoteMacAddress}
1167
-
1168
- await self.send_command(topic, payload, requestID)
1169
- LOGGER.debug("MQTT:Receiving zwave_switch_binary command")
1170
-
1171
-
1172
- async def command_arm(self, partition_id: str, arming_type: str, user_code: str = "", exit_sounds: bool = False, # noqa: PLR0913
1173
- instant_arm: bool = False, entry_delay: bool = True) -> bool:
1174
-
1175
- LOGGER.debug("MQTT: Sending arm command: partition%s, arming_type:%s, exit_sounds:%s, instant_arm: %s, entry_delay:%s",
1176
- partition_id, arming_type,exit_sounds,instant_arm,entry_delay)
1177
-
1178
- user_id = 0
1179
-
1180
- partition = self.state.partition(partition_id)
1181
- if not partition:
1182
- LOGGER.debug("MQTT: arm command error - Unknow Partition")
1183
- return False
1184
-
1185
- if self.panel.SECURE_ARMING == "true" and self.check_user_code_on_arm:
1186
- # Do local user code verification to arm if secure arming is enabled
1187
- user_id = self.panel.check_user(user_code)
1188
- if user_id == -1:
1189
- LOGGER.debug("MQTT: arm command error - user_code error")
1190
- return False
1191
-
1192
- mqtt_arming_type = ""
1193
- match arming_type:
1194
- case "ARM-STAY":
1195
- mqtt_arming_type = "ui_armstay"
1196
-
1197
- case "ARM-AWAY":
1198
- mqtt_arming_type = "ui_armaway"
1199
-
1200
- case "ARM-NIGHT":
1201
- mqtt_arming_type = "ui_armnight"
1202
-
1203
- case _:
1204
- LOGGER.debug("MQTT: Sending arm command: Unknow arming_type:%s", arming_type)
1205
- return False
1206
-
1207
- exitSoundValue = "ON"
1208
- if not exit_sounds:
1209
- exitSoundValue = "OFF"
1210
-
1211
- entryDelay = "ON"
1212
- if not entry_delay:
1213
- entryDelay = "OFF"
1214
-
1215
- arming_command = {
1216
- "operation_name": mqtt_arming_type,
1217
- "bypass_zoneid_set": "[]",
1218
- "userID": user_id,
1219
- "partitionID": int(partition_id),
1220
- "exitSoundValue": exitSoundValue,
1221
- "entryDelayValue": entryDelay,
1222
- "multiplePartitionsSelected": False,
1223
- "instant_arming": instant_arm,
1224
- "final_exit_arming_selected": False,
1225
- "manually_selected_zones": "[]",
1226
- "operation_source": 1,
1227
- "macAddress": self.settings.random_mac,
1228
- }
1229
-
1230
- topic = "mastermeid"
1231
- eventName = "ipcCall"
1232
- ipcServiceName = "qinternalservice"
1233
- ipcInterfaceName = "android.os.IQInternalService"
1234
- ipcTransactionID = 7
1235
- requestID = str(uuid.uuid4())
1236
- remoteMacAddress = self.settings.random_mac
1237
- responseTopic = "response_" + self.settings.random_mac
1238
-
1239
- payload = {
1240
- "eventName": eventName,
1241
- "ipcServiceName": ipcServiceName,
1242
- "ipcInterfaceName": ipcInterfaceName,
1243
- "ipcTransactionID": ipcTransactionID,
1244
- "ipcRequest": [{
1245
- "dataType": "string",
1246
- "dataValue": json.dumps(arming_command),
1247
- }],
1248
- "requestID": requestID,
1249
- "responseTopic": responseTopic,
1250
- "remoteMacAddress": remoteMacAddress,
1251
- }
1252
-
1253
- await self.send_command(topic, payload, requestID)
1254
-
1255
- return True
1256
-
1257
- async def command_execute_scene(self,scene_id:str) -> bool:
1258
- LOGGER.debug("MQTT: Sending execute_scene command")
1259
-
1260
- scene = self.state.scene(scene_id)
1261
- if not scene:
1262
- LOGGER.debug("MQTT: command_execute_scene Erro - Unknow Scene: %s", scene_id)
1263
- return False
1264
-
1265
- scene_command = {
1266
- "operation_name": "execute_scene",
1267
- "scene_id": scene.scene_id,
1268
- "operation_source": 1,
1269
- "macAddress": self.settings.random_mac,
1270
- }
1271
-
1272
- topic = "mastermeid"
1273
- eventName = "ipcCall"
1274
- ipcServiceName = "qinternalservice"
1275
- ipcInterfaceName = "android.os.IQInternalService"
1276
- ipcTransactionID = 7
1277
- requestID = str(uuid.uuid4())
1278
- remoteMacAddress = self.settings.random_mac
1279
- responseTopic = "response_" + self.settings.random_mac
1280
-
1281
- payload = {
1282
- "eventName": eventName,
1283
- "ipcServiceName": ipcServiceName,
1284
- "ipcInterfaceName": ipcInterfaceName,
1285
- "ipcTransactionID": ipcTransactionID,
1286
- "ipcRequest": [{
1287
- "dataType": "string",
1288
- "dataValue": json.dumps(scene_command),
1289
- }],
1290
- "requestID": requestID,
1291
- "responseTopic": responseTopic,
1292
- "remoteMacAddress": remoteMacAddress,
1293
- }
1294
-
1295
- await self.send_command(topic, payload, requestID)
1296
- LOGGER.debug("MQTT: Receiving execute_scene command")
1297
-
1298
- return False