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.
- qolsys_controller/controller.py +829 -20
- qolsys_controller/database/db.py +48 -29
- qolsys_controller/database/table.py +89 -60
- qolsys_controller/database/table_alarmedsensor.py +0 -2
- qolsys_controller/database/table_automation.py +0 -1
- qolsys_controller/database/table_country_locale.py +0 -1
- qolsys_controller/database/table_dashboard_msgs.py +1 -2
- qolsys_controller/database/table_dimmerlight.py +0 -1
- qolsys_controller/database/table_doorlock.py +0 -1
- qolsys_controller/database/table_eu_event.py +1 -2
- qolsys_controller/database/table_heat_map.py +0 -2
- qolsys_controller/database/table_history.py +4 -1
- qolsys_controller/database/table_iqremotesettings.py +0 -2
- qolsys_controller/database/table_iqrouter_network_config.py +0 -1
- qolsys_controller/database/table_iqrouter_user_device.py +0 -2
- qolsys_controller/database/table_master_slave.py +0 -1
- qolsys_controller/database/table_nest_device.py +0 -1
- qolsys_controller/database/table_output_rules.py +0 -1
- qolsys_controller/database/table_partition.py +0 -1
- qolsys_controller/database/table_pgm_outputs.py +0 -2
- qolsys_controller/database/table_powerg_device.py +0 -2
- qolsys_controller/database/table_qolsyssettings.py +0 -2
- qolsys_controller/database/table_scene.py +0 -2
- qolsys_controller/database/table_sensor.py +2 -2
- qolsys_controller/database/table_sensor_group.py +23 -0
- qolsys_controller/database/table_shades.py +0 -2
- qolsys_controller/database/table_smartsocket.py +0 -2
- qolsys_controller/database/table_state.py +0 -1
- qolsys_controller/database/table_tcc.py +0 -1
- qolsys_controller/database/table_thermostat.py +0 -1
- qolsys_controller/database/table_trouble_conditions.py +0 -2
- qolsys_controller/database/table_user.py +0 -2
- qolsys_controller/database/table_virtual_device.py +0 -2
- qolsys_controller/database/table_weather.py +0 -2
- qolsys_controller/database/table_zigbee_device.py +0 -1
- qolsys_controller/database/table_zwave_association_group.py +0 -1
- qolsys_controller/database/table_zwave_history.py +0 -1
- qolsys_controller/database/table_zwave_node.py +0 -1
- qolsys_controller/database/table_zwave_other.py +0 -1
- qolsys_controller/enum.py +37 -12
- qolsys_controller/enum_zwave.py +81 -36
- qolsys_controller/errors.py +9 -12
- qolsys_controller/mdns.py +7 -4
- qolsys_controller/mqtt_command.py +119 -0
- qolsys_controller/mqtt_command_queue.py +5 -4
- qolsys_controller/observable.py +2 -2
- qolsys_controller/panel.py +195 -151
- qolsys_controller/partition.py +129 -127
- qolsys_controller/pki.py +69 -97
- qolsys_controller/scene.py +30 -28
- qolsys_controller/settings.py +96 -50
- qolsys_controller/state.py +59 -34
- qolsys_controller/task_manager.py +8 -12
- qolsys_controller/users.py +25 -0
- qolsys_controller/utils_mqtt.py +8 -16
- qolsys_controller/weather.py +71 -0
- qolsys_controller/zone.py +242 -214
- qolsys_controller/zwave_device.py +108 -95
- qolsys_controller/zwave_dimmer.py +53 -50
- qolsys_controller/zwave_garagedoor.py +0 -1
- qolsys_controller/zwave_generic.py +2 -3
- qolsys_controller/zwave_lock.py +47 -44
- qolsys_controller/zwave_outlet.py +0 -1
- qolsys_controller/zwave_thermostat.py +112 -118
- qolsys_controller-0.0.62.dist-info/METADATA +89 -0
- qolsys_controller-0.0.62.dist-info/RECORD +69 -0
- {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.62.dist-info}/WHEEL +1 -1
- qolsys_controller/plugin.py +0 -34
- qolsys_controller/plugin_c4.py +0 -17
- qolsys_controller/plugin_remote.py +0 -1298
- qolsys_controller-0.0.44.dist-info/METADATA +0 -93
- qolsys_controller-0.0.44.dist-info/RECORD +0 -68
- {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
|