qolsys-controller 0.0.76__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- qolsys_controller-0.3.2/.github/dependabot.yml +11 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/PKG-INFO +1 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/pyproject.toml +1 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/adc_service_garagedoor.py +1 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/controller.py +163 -35
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/db.py +8 -8
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_sensor.py +2 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_smartsocket.py +12 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_thermostat.py +1 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_user.py +1 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zwave_node.py +3 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/enum.py +38 -24
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/enum_zwave.py +87 -23
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/mqtt_command.py +8 -1
- qolsys_controller-0.3.2/qolsys_controller/observable_v2.py +14 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/panel.py +49 -20
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/state.py +146 -41
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zone.py +74 -12
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_device.py +156 -10
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_dimmer.py +7 -11
- qolsys_controller-0.3.2/qolsys_controller/zwave_energy_clamp.py +19 -0
- qolsys_controller-0.3.2/qolsys_controller/zwave_extenal_siren.py +86 -0
- qolsys_controller-0.3.2/qolsys_controller/zwave_garagedoor.py +20 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_generic.py +6 -2
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_lock.py +15 -12
- qolsys_controller-0.3.2/qolsys_controller/zwave_service_meter.py +192 -0
- qolsys_controller-0.3.2/qolsys_controller/zwave_service_multilevelsensor.py +128 -0
- qolsys_controller-0.3.2/qolsys_controller/zwave_smart_socket.py +20 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_thermometer.py +6 -2
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/zwave_thermostat.py +70 -22
- qolsys_controller-0.3.2/qolsys_controller/zwave_water_valve.py +83 -0
- qolsys_controller-0.3.2/requirements.txt +8 -0
- qolsys_controller-0.0.76/qolsys_controller/zwave_garagedoor.py +0 -13
- qolsys_controller-0.0.76/qolsys_controller/zwave_meter.py +0 -272
- qolsys_controller-0.0.76/qolsys_controller/zwave_outlet.py +0 -13
- qolsys_controller-0.0.76/requirements.txt +0 -8
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/.github/workflows/build.yml +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/.github/workflows/publish.yml +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/.gitignore +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/Info_mqtt.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/LICENSE +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/README.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/bin/qolsys.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/example.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/info_pairing.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/info_qolsys.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/mypy.ini +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/__init__.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/adc_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/adc_service.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_alarmedsensor.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_automation.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_country_locale.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_dashboard_msgs.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_dimmerlight.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_doorlock.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_eu_event.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_heat_map.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_history.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_iqremotesettings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_iqrouter_network_config.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_iqrouter_user_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_master_slave.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_nest_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_output_rules.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_partition.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_pgm_outputs.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_powerg_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_qolsyssettings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_scene.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_sensor_group.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_shades.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_state.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_tcc.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_trouble_conditions.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_virtual_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_weather.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zigbee_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zwave_association_group.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zwave_history.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zwave_other.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/enum_adc.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/errors.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/mdns.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/mqtt_command_queue.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/observable.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/partition.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/pki.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/scene.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/settings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/task_manager.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/users.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/utils_mqtt.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/weather.py +0 -0
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# To get started with Dependabot version updates, you'll need to specify which
|
|
2
|
+
# package ecosystems to update and where the package manifests are located.
|
|
3
|
+
# Please see the documentation for all configuration options:
|
|
4
|
+
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
5
|
+
|
|
6
|
+
version: 2
|
|
7
|
+
updates:
|
|
8
|
+
- package-ecosystem: "pip" # See documentation for possible values
|
|
9
|
+
directory: "/" # Location of package manifests
|
|
10
|
+
schedule:
|
|
11
|
+
interval: "weekly"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qolsys-controller
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A Python module that emulates a virtual IQ Remote device, enabling full local control of a Qolsys IQ Panel
|
|
5
5
|
Project-URL: Homepage, https://github.com/EHylands/QolsysController
|
|
6
6
|
Project-URL: Issues, https://github.com/EHylands/QolsysController/issues
|
|
@@ -18,9 +18,10 @@ from qolsys_controller.mqtt_command import (
|
|
|
18
18
|
MQTTCommand_Panel,
|
|
19
19
|
MQTTCommand_ZWave,
|
|
20
20
|
)
|
|
21
|
+
from qolsys_controller.zwave_thermostat import QolsysThermostat
|
|
21
22
|
|
|
22
23
|
from .enum import PartitionAlarmState, PartitionArmingType, PartitionSystemStatus
|
|
23
|
-
from .enum_zwave import ThermostatFanMode, ThermostatMode,
|
|
24
|
+
from .enum_zwave import ThermostatFanMode, ThermostatMode, ThermostatSetpointMode, ZwaveCommandClass
|
|
24
25
|
from .errors import QolsysMqttError, QolsysSslError, QolsysUserCodeError
|
|
25
26
|
from .mdns import QolsysMDNS
|
|
26
27
|
from .mqtt_command_queue import QolsysMqttCommandQueue
|
|
@@ -60,6 +61,7 @@ class QolsysController:
|
|
|
60
61
|
self._mqtt_task_listen_label: str = "mqtt_task_listen"
|
|
61
62
|
self._mqtt_task_connect_label: str = "mqtt_task_connect"
|
|
62
63
|
self._mqtt_task_ping_label: str = "mqtt_task_ping"
|
|
64
|
+
self._mqtt_task_zwave_meter_update_label: str = "mqtt_task_zwave_meter_update"
|
|
63
65
|
|
|
64
66
|
@property
|
|
65
67
|
def state(self) -> QolsysState:
|
|
@@ -151,32 +153,43 @@ class QolsysController:
|
|
|
151
153
|
self._task_manager.cancel(self._mqtt_task_listen_label)
|
|
152
154
|
self._task_manager.cancel(self._mqtt_task_ping_label)
|
|
153
155
|
self._task_manager.cancel(self._mqtt_task_config_label)
|
|
156
|
+
self._task_manager.cancel(self._mqtt_task_zwave_meter_update_label)
|
|
154
157
|
|
|
155
158
|
self.connected = False
|
|
156
159
|
self.connected_observer.notify()
|
|
157
160
|
|
|
158
161
|
async def mqtt_connect_task(self, reconnect: bool, run_forever: bool) -> None:
|
|
159
|
-
# Configure TLS
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
162
|
+
# Configure TLS context for MQTT connection
|
|
163
|
+
def create_tls_context(self: QolsysController) -> ssl.SSLContext:
|
|
164
|
+
ctx = ssl.create_default_context(
|
|
165
|
+
purpose=ssl.Purpose.SERVER_AUTH,
|
|
166
|
+
cafile=str(self._pki.qolsys_cer_file_path),
|
|
167
|
+
)
|
|
168
|
+
ctx.set_ciphers("DEFAULT:@SECLEVEL=0")
|
|
169
|
+
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
|
|
170
|
+
ctx.check_hostname = False
|
|
171
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
172
|
+
ctx.load_cert_chain(
|
|
173
|
+
certfile=str(self._pki.secure_file_path),
|
|
174
|
+
keyfile=str(self._pki.key_file_path),
|
|
175
|
+
)
|
|
176
|
+
return ctx
|
|
177
|
+
|
|
178
|
+
loop = asyncio.get_running_loop()
|
|
179
|
+
ctx = await loop.run_in_executor(None, create_tls_context, self)
|
|
168
180
|
|
|
169
181
|
LOGGER.debug("MQTT: Connecting ...")
|
|
170
182
|
|
|
171
183
|
self._task_manager.cancel(self._mqtt_task_listen_label)
|
|
172
184
|
self._task_manager.cancel(self._mqtt_task_ping_label)
|
|
185
|
+
self._task_manager.cancel(self._mqtt_task_zwave_meter_update_label)
|
|
173
186
|
|
|
174
187
|
while True:
|
|
175
188
|
try:
|
|
176
189
|
self.aiomqtt = aiomqtt.Client(
|
|
177
190
|
hostname=self.settings.panel_ip,
|
|
178
191
|
port=8883,
|
|
179
|
-
|
|
192
|
+
tls_context=ctx,
|
|
180
193
|
tls_insecure=True,
|
|
181
194
|
clean_session=True,
|
|
182
195
|
timeout=self.settings.mqtt_timeout,
|
|
@@ -213,11 +226,14 @@ class QolsysController:
|
|
|
213
226
|
|
|
214
227
|
response_database = await self.command_sync_database()
|
|
215
228
|
LOGGER.debug("MQTT: Updating State from syncdatabase")
|
|
216
|
-
self.panel.load_database(response_database.get("fulldbdata"))
|
|
229
|
+
await self.panel.load_database(response_database.get("fulldbdata"))
|
|
217
230
|
self.panel.dump()
|
|
218
231
|
self.state.dump()
|
|
219
232
|
|
|
220
233
|
self.connected = True
|
|
234
|
+
|
|
235
|
+
self._task_manager.run(self.mqtt_zwave_meter_update(), self._mqtt_task_zwave_meter_update_label)
|
|
236
|
+
|
|
221
237
|
self.connected_observer.notify()
|
|
222
238
|
|
|
223
239
|
if not run_forever:
|
|
@@ -258,6 +274,19 @@ class QolsysController:
|
|
|
258
274
|
|
|
259
275
|
await asyncio.sleep(self.settings.mqtt_ping)
|
|
260
276
|
|
|
277
|
+
async def mqtt_zwave_meter_update(self) -> None:
|
|
278
|
+
while True:
|
|
279
|
+
if self.aiomqtt is not None and self.connected:
|
|
280
|
+
LOGGER.debug("Updating Z-Wave Energy Clamps")
|
|
281
|
+
with contextlib.suppress(aiomqtt.MqttError):
|
|
282
|
+
for energy_clamp in self.state.zwave_meters:
|
|
283
|
+
for meter in energy_clamp.meter_endpoints:
|
|
284
|
+
zwave_command = MQTTCommand_ZWave(
|
|
285
|
+
self, energy_clamp.node_id, meter.endpoint, [ZwaveCommandClass.Meter, 0x01]
|
|
286
|
+
)
|
|
287
|
+
await zwave_command.send_command()
|
|
288
|
+
await asyncio.sleep(60)
|
|
289
|
+
|
|
261
290
|
async def mqtt_listen_task(self) -> None:
|
|
262
291
|
try:
|
|
263
292
|
async for message in self.aiomqtt.messages: # type: ignore[union-attr]
|
|
@@ -747,6 +776,70 @@ class QolsysController:
|
|
|
747
776
|
LOGGER.debug("MQTT: Receiving execute_scene command")
|
|
748
777
|
return response
|
|
749
778
|
|
|
779
|
+
async def command_panel_virtual_device_action(self, device_id: str, state: int) -> dict[str, Any] | None:
|
|
780
|
+
LOGGER.debug("MQTT: Sending virtual_device command")
|
|
781
|
+
|
|
782
|
+
garage_door = self.state.adc_device(device_id)
|
|
783
|
+
if not garage_door:
|
|
784
|
+
LOGGER.error("Invalid Virtual Garage Door Id: %s", device_id)
|
|
785
|
+
|
|
786
|
+
device_list = {
|
|
787
|
+
"virtualDeviceList": [
|
|
788
|
+
{
|
|
789
|
+
"virtualDeviceId": int(device_id),
|
|
790
|
+
"virtualDeviceFunctionList": [
|
|
791
|
+
{
|
|
792
|
+
"vdFuncId": 1,
|
|
793
|
+
"vdFuncState": state,
|
|
794
|
+
"vdFuncBackendTimestamp": int(time.time() * 1000),
|
|
795
|
+
"vdFuncType": 1,
|
|
796
|
+
}
|
|
797
|
+
],
|
|
798
|
+
}
|
|
799
|
+
]
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
virtual_command = {
|
|
803
|
+
"operation_name": "send_virtual_device_description",
|
|
804
|
+
"virtual_device_operation": 4,
|
|
805
|
+
"virtual_device_description": json.dumps(device_list),
|
|
806
|
+
"operation_source": 0,
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
virtual_command2 = {
|
|
810
|
+
"operation_name": "send_virtual_device_description",
|
|
811
|
+
"virtual_device_operation": 5,
|
|
812
|
+
"virtual_device_description": json.dumps(device_list),
|
|
813
|
+
"operation_source": 0,
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
ipc_request = [
|
|
817
|
+
{
|
|
818
|
+
"dataType": "string",
|
|
819
|
+
"dataValue": json.dumps(virtual_command),
|
|
820
|
+
}
|
|
821
|
+
]
|
|
822
|
+
|
|
823
|
+
ipc_request2 = [
|
|
824
|
+
{
|
|
825
|
+
"dataType": "string",
|
|
826
|
+
"dataValue": json.dumps(virtual_command2),
|
|
827
|
+
}
|
|
828
|
+
]
|
|
829
|
+
|
|
830
|
+
LOGGER.debug("virtual command: %s", virtual_command)
|
|
831
|
+
command = MQTTCommand_Panel(self)
|
|
832
|
+
command.append_ipc_request(ipc_request)
|
|
833
|
+
response = await command.send_command()
|
|
834
|
+
LOGGER.debug("MQTT: Receiving virtual_device command: %s", response)
|
|
835
|
+
|
|
836
|
+
LOGGER.debug("virtual command: %s", virtual_command2)
|
|
837
|
+
command2 = MQTTCommand_Panel(self)
|
|
838
|
+
command2.append_ipc_request(ipc_request2)
|
|
839
|
+
response2 = await command2.send_command()
|
|
840
|
+
LOGGER.debug("MQTT: Receiving virtual_device command: %s", response2)
|
|
841
|
+
return response
|
|
842
|
+
|
|
750
843
|
async def command_panel_trigger_police(self, partition_id: str, silent: bool) -> dict[str, Any] | None:
|
|
751
844
|
LOGGER.debug("MQTT: Sending panel_trigger_police command")
|
|
752
845
|
|
|
@@ -837,28 +930,28 @@ class QolsysController:
|
|
|
837
930
|
LOGGER.debug("MQTT: Receiving panel_trigger_fire command")
|
|
838
931
|
return response
|
|
839
932
|
|
|
840
|
-
async def command_zwave_switch_binary_set(self, node_id: str, status: bool) -> dict[str, Any] | None:
|
|
841
|
-
LOGGER.debug("MQTT: Sending
|
|
933
|
+
async def command_zwave_switch_binary_set(self, node_id: str, endpoint: str, status: bool) -> dict[str, Any] | None:
|
|
934
|
+
LOGGER.debug("MQTT: Sending set_zwave_switch_binar#y command - Node(%s) - Status(%s)", node_id, status)
|
|
842
935
|
zwave_node = self.state.zwave_device(node_id)
|
|
843
936
|
|
|
844
937
|
if not zwave_node:
|
|
845
938
|
LOGGER.error("switch_binary_set - Invalid node_id %s", node_id)
|
|
846
939
|
return None
|
|
847
940
|
|
|
848
|
-
if
|
|
849
|
-
LOGGER.error("
|
|
941
|
+
if ZwaveCommandClass.SwitchBinary not in zwave_node.command_class_list:
|
|
942
|
+
LOGGER.error("Z-Wave node does not support switch_binary_set")
|
|
850
943
|
return None
|
|
851
944
|
|
|
852
945
|
level = 0
|
|
853
946
|
if status:
|
|
854
947
|
level = 255
|
|
855
948
|
|
|
856
|
-
command = MQTTCommand_ZWave(self, node_id, [ZwaveCommandClass.SwitchBinary, 1, level])
|
|
949
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, [ZwaveCommandClass.SwitchBinary, 1, level])
|
|
857
950
|
response = await command.send_command()
|
|
858
951
|
LOGGER.debug("MQTT: Receiving set_zwave_switch_binary command")
|
|
859
952
|
return response
|
|
860
953
|
|
|
861
|
-
async def command_zwave_switch_multilevel_set(self, node_id: str, level: int) -> dict[str, Any] | None:
|
|
954
|
+
async def command_zwave_switch_multilevel_set(self, node_id: str, endpoint: str, level: int) -> dict[str, Any] | None:
|
|
862
955
|
LOGGER.debug("MQTT: Sending switch_multilevel_set command - Node(%s) - Level(%s)", node_id, level)
|
|
863
956
|
|
|
864
957
|
zwave_node = self.state.zwave_device(node_id)
|
|
@@ -866,16 +959,16 @@ class QolsysController:
|
|
|
866
959
|
LOGGER.error("switch_multilevel_set - Invalid node_id %s", node_id)
|
|
867
960
|
return None
|
|
868
961
|
|
|
869
|
-
if
|
|
870
|
-
LOGGER.error("
|
|
962
|
+
if ZwaveCommandClass.SwitchMultilevel not in zwave_node.command_class_list:
|
|
963
|
+
LOGGER.error("Z-Wave node does not support switch_multilevel_set")
|
|
871
964
|
return None
|
|
872
965
|
|
|
873
|
-
command = MQTTCommand_ZWave(self, node_id, [ZwaveCommandClass.SwitchMultilevel, 1, level])
|
|
966
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, [ZwaveCommandClass.SwitchMultilevel, 1, level])
|
|
874
967
|
response = await command.send_command()
|
|
875
968
|
LOGGER.debug("MQTT: Receiving set_zwave_multilevel_switch command")
|
|
876
969
|
return response
|
|
877
970
|
|
|
878
|
-
async def command_zwave_doorlock_set(self, node_id: str, locked: bool) -> dict[str, Any] | None:
|
|
971
|
+
async def command_zwave_doorlock_set(self, node_id: str, endpoint: str, locked: bool) -> dict[str, Any] | None:
|
|
879
972
|
LOGGER.debug("MQTT: Sending zwave_doorlock_set command - Node(%s) - Locked(%s)", node_id, locked)
|
|
880
973
|
|
|
881
974
|
zwave_node = self.state.zwave_device(node_id)
|
|
@@ -883,34 +976,68 @@ class QolsysController:
|
|
|
883
976
|
LOGGER.error("doorlock_set - Invalid node_id %s", node_id)
|
|
884
977
|
return None
|
|
885
978
|
|
|
979
|
+
if ZwaveCommandClass.DoorLock not in zwave_node.command_class_list:
|
|
980
|
+
LOGGER.error("Z-Wave node does not support zwave_doorlock_set")
|
|
981
|
+
return None
|
|
982
|
+
|
|
886
983
|
# 0 unlocked, 255 locked
|
|
887
984
|
lock_mode = 0
|
|
888
985
|
if locked:
|
|
889
986
|
lock_mode = 255
|
|
890
987
|
|
|
891
|
-
command = MQTTCommand_ZWave(self, node_id, [ZwaveCommandClass.DoorLock, 1, lock_mode])
|
|
988
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, [ZwaveCommandClass.DoorLock, 1, lock_mode])
|
|
892
989
|
response = await command.send_command()
|
|
893
990
|
LOGGER.debug("MQTT: Receiving zwave_doorlock_set command")
|
|
894
991
|
return response
|
|
895
992
|
|
|
896
993
|
async def command_zwave_thermostat_setpoint_set(
|
|
897
|
-
self, node_id: str, mode:
|
|
994
|
+
self, node_id: str, endpoint: str, mode: ThermostatSetpointMode, setpoint: int
|
|
898
995
|
) -> dict[str, Any] | None:
|
|
899
|
-
LOGGER.debug(
|
|
900
|
-
"MQTT: Sending zwave_thermostat_setpoint_set - Node(%s) - Mode(%s) - Setpoint(%s)", node_id, mode, setpoint
|
|
901
|
-
)
|
|
902
|
-
|
|
903
996
|
zwave_node = self.state.zwave_device(node_id)
|
|
904
997
|
if not zwave_node:
|
|
905
998
|
LOGGER.error("thermostat_setpoint_set - Invalid node_id %s", node_id)
|
|
906
999
|
return None
|
|
907
1000
|
|
|
908
|
-
|
|
1001
|
+
if not isinstance(zwave_node, QolsysThermostat):
|
|
1002
|
+
LOGGER.error("thermostat_setpoint_set - Z-Wave node is not a thermostat %s", node_id)
|
|
1003
|
+
return None
|
|
1004
|
+
|
|
1005
|
+
scale: int = 0
|
|
1006
|
+
if zwave_node.thermostat_device_temp_unit == "F":
|
|
1007
|
+
scale = 1
|
|
1008
|
+
|
|
1009
|
+
precision: int = 1
|
|
1010
|
+
size: int = 2
|
|
1011
|
+
pss = (precision << 5) | (scale << 3) | size
|
|
1012
|
+
temp_int = int(round(setpoint * (10**precision)))
|
|
1013
|
+
temp_bytes = temp_int.to_bytes(size, byteorder="big", signed=True)
|
|
1014
|
+
|
|
1015
|
+
setpointmode = ThermostatSetpointMode.HEATING
|
|
1016
|
+
if mode == ThermostatSetpointMode.COOLING:
|
|
1017
|
+
setpointmode = mode
|
|
1018
|
+
|
|
1019
|
+
zwave_bytes: list[int] = [
|
|
1020
|
+
0x43, # Thermostat Setpoint
|
|
1021
|
+
0x01, # SET
|
|
1022
|
+
setpointmode.value,
|
|
1023
|
+
pss,
|
|
1024
|
+
] + list(temp_bytes)
|
|
1025
|
+
|
|
1026
|
+
LOGGER.debug(
|
|
1027
|
+
"MQTT: Sending zwave_thermostat_setpoint_set - Node(%s) - Mode(%s) - Setpoint(%s): %s",
|
|
1028
|
+
node_id,
|
|
1029
|
+
mode.value,
|
|
1030
|
+
setpoint,
|
|
1031
|
+
zwave_bytes,
|
|
1032
|
+
)
|
|
1033
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, zwave_bytes)
|
|
909
1034
|
response = await command.send_command()
|
|
910
|
-
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command")
|
|
1035
|
+
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command:%s", response)
|
|
911
1036
|
return response
|
|
912
1037
|
|
|
913
|
-
async def command_zwave_thermostat_mode_set(
|
|
1038
|
+
async def command_zwave_thermostat_mode_set(
|
|
1039
|
+
self, node_id: str, endpoint: str, mode: ThermostatMode
|
|
1040
|
+
) -> dict[str, Any] | None:
|
|
914
1041
|
LOGGER.debug("MQTT: Sending zwave_thermostat_mode_set command - Node(%s) - Mode(%s)", node_id, mode)
|
|
915
1042
|
|
|
916
1043
|
thermostat = self.state.zwave_thermostat(node_id)
|
|
@@ -918,16 +1045,17 @@ class QolsysController:
|
|
|
918
1045
|
LOGGER.error("zwave_thermostat_mode_set - Invalid node_id %s", node_id)
|
|
919
1046
|
return None
|
|
920
1047
|
|
|
921
|
-
LOGGER.debug("thermostat_mode: %s", int(mode))
|
|
922
1048
|
if mode not in thermostat.available_thermostat_mode():
|
|
923
1049
|
LOGGER.error("thermostat_mode_set - Invalid mode %s", mode)
|
|
924
1050
|
|
|
925
|
-
command = MQTTCommand_ZWave(self, node_id, [ZwaveCommandClass.ThermostatMode, 1, int(mode)])
|
|
1051
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, [ZwaveCommandClass.ThermostatMode, 1, int(mode)])
|
|
926
1052
|
response = await command.send_command()
|
|
927
1053
|
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command")
|
|
928
1054
|
return response
|
|
929
1055
|
|
|
930
|
-
async def command_zwave_thermostat_fan_mode_set(
|
|
1056
|
+
async def command_zwave_thermostat_fan_mode_set(
|
|
1057
|
+
self, node_id: str, endpoint: str, fan_mode: ThermostatFanMode
|
|
1058
|
+
) -> dict[str, Any] | None:
|
|
931
1059
|
LOGGER.debug("MQTT: Sending zwave_thermostat_fan_mode_set command - Node(%s) - FanMode(%s)", node_id, fan_mode)
|
|
932
1060
|
|
|
933
1061
|
zwave_node = self.state.zwave_device(node_id)
|
|
@@ -935,7 +1063,7 @@ class QolsysController:
|
|
|
935
1063
|
LOGGER.error("thermostat_fan_mode_set - Invalid node_id %s", node_id)
|
|
936
1064
|
return None
|
|
937
1065
|
|
|
938
|
-
command = MQTTCommand_ZWave(self, node_id, [ZwaveCommandClass.ThermostatFanMode, 1, fan_mode])
|
|
1066
|
+
command = MQTTCommand_ZWave(self, node_id, endpoint, [ZwaveCommandClass.ThermostatFanMode, 1, fan_mode])
|
|
939
1067
|
response = await command.send_command()
|
|
940
1068
|
LOGGER.debug("MQTT: Receiving zwave_thermostat_fan_mode_set command")
|
|
941
1069
|
return response
|
|
@@ -216,7 +216,7 @@ class QolsysDB:
|
|
|
216
216
|
return partitions
|
|
217
217
|
|
|
218
218
|
def get_adc_devices(self) -> list[dict[str, str]]:
|
|
219
|
-
self.cursor.execute(f"SELECT * FROM {self.table_virtual_device.table} ORDER BY device_id")
|
|
219
|
+
self.cursor.execute(f"SELECT * FROM {self.table_virtual_device.table} ORDER BY CAST(device_id AS INTEGER)")
|
|
220
220
|
self.db.commit()
|
|
221
221
|
|
|
222
222
|
devices = []
|
|
@@ -228,7 +228,7 @@ class QolsysDB:
|
|
|
228
228
|
return devices
|
|
229
229
|
|
|
230
230
|
def get_zwave_devices(self) -> list[dict[str, str]]:
|
|
231
|
-
self.cursor.execute(f"SELECT * FROM {self.table_zwave_node.table} ORDER BY node_id")
|
|
231
|
+
self.cursor.execute(f"SELECT * FROM {self.table_zwave_node.table} ORDER BY CAST(node_id AS INTEGER)")
|
|
232
232
|
self.db.commit()
|
|
233
233
|
|
|
234
234
|
devices = []
|
|
@@ -240,7 +240,7 @@ class QolsysDB:
|
|
|
240
240
|
return devices
|
|
241
241
|
|
|
242
242
|
def get_zwave_other_devices(self) -> list[dict[str, str]]:
|
|
243
|
-
self.cursor.execute(f"SELECT * FROM {self.table_zwave_other.table} ORDER BY node_id")
|
|
243
|
+
self.cursor.execute(f"SELECT * FROM {self.table_zwave_other.table} ORDER BY CAST(node_id AS INTEGER)")
|
|
244
244
|
self.db.commit()
|
|
245
245
|
|
|
246
246
|
devices = []
|
|
@@ -252,7 +252,7 @@ class QolsysDB:
|
|
|
252
252
|
return devices
|
|
253
253
|
|
|
254
254
|
def get_locks(self) -> list[dict[str, str]]:
|
|
255
|
-
self.cursor.execute(f"SELECT * FROM {self.table_doorlock.table} ORDER BY node_id")
|
|
255
|
+
self.cursor.execute(f"SELECT * FROM {self.table_doorlock.table} ORDER BY CAST(node_id AS INTEGER)")
|
|
256
256
|
self.db.commit()
|
|
257
257
|
|
|
258
258
|
locks = []
|
|
@@ -264,7 +264,7 @@ class QolsysDB:
|
|
|
264
264
|
return locks
|
|
265
265
|
|
|
266
266
|
def get_thermostats(self) -> list[dict[str, str]]:
|
|
267
|
-
self.cursor.execute(f"SELECT * FROM {self.table_thermostat.table} ORDER BY node_id")
|
|
267
|
+
self.cursor.execute(f"SELECT * FROM {self.table_thermostat.table} ORDER BY CAST(node_id AS INTEGER)")
|
|
268
268
|
self.db.commit()
|
|
269
269
|
|
|
270
270
|
thermostats = []
|
|
@@ -276,7 +276,7 @@ class QolsysDB:
|
|
|
276
276
|
return thermostats
|
|
277
277
|
|
|
278
278
|
def get_dimmers(self) -> list[dict[str, str]]:
|
|
279
|
-
self.cursor.execute(f"SELECT * FROM {self.table_dimmer.table} ORDER BY node_id")
|
|
279
|
+
self.cursor.execute(f"SELECT * FROM {self.table_dimmer.table} ORDER BY CAST(node_id AS INTEGER)")
|
|
280
280
|
self.db.commit()
|
|
281
281
|
|
|
282
282
|
dimmers = []
|
|
@@ -288,7 +288,7 @@ class QolsysDB:
|
|
|
288
288
|
return dimmers
|
|
289
289
|
|
|
290
290
|
def get_zones(self) -> list[dict[str, str]]:
|
|
291
|
-
self.cursor.execute(f"SELECT * FROM {self.table_sensor.table} ORDER BY zoneid")
|
|
291
|
+
self.cursor.execute(f"SELECT * FROM {self.table_sensor.table} ORDER BY CAST(zoneid AS INTEGER)")
|
|
292
292
|
self.db.commit()
|
|
293
293
|
|
|
294
294
|
zones = []
|
|
@@ -390,7 +390,7 @@ class QolsysDB:
|
|
|
390
390
|
|
|
391
391
|
return None
|
|
392
392
|
|
|
393
|
-
def load_db(self, database:
|
|
393
|
+
def load_db(self, database: Any | None) -> None:
|
|
394
394
|
self.clear_db()
|
|
395
395
|
|
|
396
396
|
if not database:
|
{qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_smartsocket.py
RENAMED
|
@@ -12,10 +12,21 @@ class QolsysTableSmartSocket(QolsysTable):
|
|
|
12
12
|
self._uri = "content://com.qolsys.qolsysprovider.SmartSocketsContentProvider/smartsocket"
|
|
13
13
|
self._table = "smartsocket"
|
|
14
14
|
self._abort_on_error = False
|
|
15
|
-
self._implemented =
|
|
15
|
+
self._implemented = True
|
|
16
16
|
|
|
17
17
|
self._columns = [
|
|
18
18
|
"_id",
|
|
19
|
+
"created_by",
|
|
20
|
+
"created_date",
|
|
21
|
+
"last_updated_date",
|
|
22
|
+
"node_id",
|
|
23
|
+
"paired_status",
|
|
24
|
+
"power_usage",
|
|
25
|
+
"status",
|
|
26
|
+
"updated_by",
|
|
27
|
+
"socket_id",
|
|
28
|
+
"socket_name",
|
|
29
|
+
"current_usagevoltage_usage",
|
|
19
30
|
]
|
|
20
31
|
|
|
21
32
|
self._create_table()
|
{qolsys_controller-0.0.76 → qolsys_controller-0.3.2}/qolsys_controller/database/table_zwave_node.py
RENAMED
|
@@ -51,12 +51,12 @@ class QolsysTableZwaveNode(QolsysTable):
|
|
|
51
51
|
"node_battery_level_updated_time",
|
|
52
52
|
"basic_report_updated_time",
|
|
53
53
|
"switch_multilevel_report_updated_time",
|
|
54
|
-
"multi_channel_details",
|
|
55
54
|
"rediscover_status",
|
|
56
55
|
"last_rediscover_time",
|
|
57
56
|
"neighbour_info",
|
|
58
57
|
"last_node_test_time",
|
|
59
58
|
"notification_capabilities",
|
|
59
|
+
"multi_channel_details",
|
|
60
60
|
"endpoint",
|
|
61
61
|
"endpoint_details",
|
|
62
62
|
"device_wakeup_time",
|
|
@@ -80,6 +80,8 @@ class QolsysTableZwaveNode(QolsysTable):
|
|
|
80
80
|
"long_range_nodeid",
|
|
81
81
|
"hide_device_info",
|
|
82
82
|
"meter_capabilities",
|
|
83
|
+
"multisensor_capabilities",
|
|
84
|
+
"central_scene_supported",
|
|
83
85
|
]
|
|
84
86
|
|
|
85
87
|
self._create_table()
|
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
2
|
|
|
3
3
|
|
|
4
|
+
class QolsysEvent(StrEnum):
|
|
5
|
+
EVENT_PANEL_PARTITION_ADD = "EVENT_PANEL_PARTITION_ADD"
|
|
6
|
+
EVENT_PANEL_ZONE_ADD = "EVENT_PANEL_ZONE_ADD"
|
|
7
|
+
EVENT_PANEL_DOORBELL = "EVENT_PANEL_DOORBELL"
|
|
8
|
+
EVENT_PANEL_CHIME = "EVENT_PANEL_CHIME"
|
|
9
|
+
EVENT_ZWAVE_DEVICE_ADD = "EVENT_ZWAVE_MULTILEVELSENSOR_ADD"
|
|
10
|
+
EVENT_ZWAVE_MULTILEVELSENSOR_ADD = "EVENT_ZWAVE_MULTILEVELSENSOR_ADD"
|
|
11
|
+
EVENT_ZWAVE_METER_ADD = "EVENT_ZWAVE_METER_ADD"
|
|
12
|
+
|
|
13
|
+
|
|
4
14
|
class PartitionSystemStatus(StrEnum):
|
|
5
15
|
ARM_STAY = "ARM-STAY"
|
|
6
16
|
ARM_AWAY = "ARM-AWAY"
|
|
@@ -48,22 +58,24 @@ class PartitionAlarmType(StrEnum):
|
|
|
48
58
|
|
|
49
59
|
|
|
50
60
|
class ZoneStatus(StrEnum):
|
|
61
|
+
ACTIVE = "Active"
|
|
62
|
+
ACTIVATED = "Activated"
|
|
51
63
|
ALARMED = "Alarmed"
|
|
52
|
-
|
|
64
|
+
ARM_AWAY = "Arm-Away"
|
|
65
|
+
ARM_STAY = "Arm-Stay"
|
|
53
66
|
CLOSED = "Closed"
|
|
54
|
-
|
|
67
|
+
CONNECTED = "connected"
|
|
68
|
+
DISARM = "Disarm"
|
|
69
|
+
OPEN = "Open"
|
|
55
70
|
INACTIVE = "Inactive"
|
|
56
|
-
ACTIVATED = "Activated"
|
|
57
71
|
IDLE = "Idle"
|
|
58
72
|
NORMAL = "Normal"
|
|
59
73
|
UNREACHABLE = "Unreachable"
|
|
60
74
|
TAMPERED = "Tampered"
|
|
61
75
|
SYNCHRONIZING = "Synchronizing"
|
|
62
|
-
CONNECTED = "connected"
|
|
63
76
|
DISCONNECTED = "disconnected"
|
|
64
77
|
FAILURE = "Failure"
|
|
65
78
|
NOT_NETWORKED = "Not Networked"
|
|
66
|
-
DISARM = "Disarm"
|
|
67
79
|
|
|
68
80
|
|
|
69
81
|
class DeviceCapability(StrEnum):
|
|
@@ -71,37 +83,39 @@ class DeviceCapability(StrEnum):
|
|
|
71
83
|
WIFI = "WiFi"
|
|
72
84
|
POWERG = "POWERG"
|
|
73
85
|
ZWAVE = "Z-Wave"
|
|
86
|
+
S_LINE = "S-Line"
|
|
74
87
|
|
|
75
88
|
|
|
76
89
|
class ZoneSensorType(StrEnum):
|
|
77
|
-
|
|
90
|
+
AUXILIARY_PENDANT = "Auxiliary Pendant"
|
|
91
|
+
BLUETOOTH = "Bluetooth"
|
|
92
|
+
CO_DETECTOR = "CODetector"
|
|
78
93
|
DOORBELL = "Doorbell"
|
|
79
|
-
|
|
94
|
+
DOOR_WINDOW = "Door_Window"
|
|
95
|
+
DOOR_WINDOW_M = "Door_Window_M"
|
|
96
|
+
FREEZE = "Freeze"
|
|
80
97
|
GLASS_BREAK = "GlassBreak"
|
|
98
|
+
# HARDWIRE_TRANSLATOR = "" # TBD
|
|
99
|
+
HEAT = "Heat"
|
|
100
|
+
# HIGH_TEMPERATURE = "" # TBD
|
|
81
101
|
KEY_FOB = "KeyFob"
|
|
82
102
|
KEYPAD = "Keypad"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
MOTION = "Motion"
|
|
104
|
+
# OCCUPANCY = "" #TBD
|
|
105
|
+
PANEL_GLASS_BREAK = "Panel Glass Break"
|
|
106
|
+
PANEL_MOTION = "Panel Motion"
|
|
87
107
|
# WIRELESS_TRANSLATOR = "" #TBD
|
|
88
|
-
|
|
89
|
-
HEAT = "Heat"
|
|
90
|
-
WATER = "Water"
|
|
108
|
+
SIREN = "Siren"
|
|
91
109
|
SHOCK = "Shock"
|
|
92
|
-
|
|
93
|
-
TILT = "Tilt"
|
|
110
|
+
SMOKE_DETECTOR = "SmokeDetector"
|
|
94
111
|
SMOKE_M = "Smoke_M"
|
|
95
|
-
# DOOR_WINDOW_M = "" #TBD
|
|
96
|
-
# OCCUPANCY = "" #TBD
|
|
97
|
-
SIREN = "Siren"
|
|
98
|
-
# HIGH_TEMPERATURE = "" # TBD
|
|
99
|
-
PANEL_MOTION = "Panel Motion"
|
|
100
|
-
PANEL_GLASS_BREAK = "Panel Glass Break"
|
|
101
|
-
BLUETOOTH = "Bluetooth"
|
|
102
112
|
TAKEOVER_MODULE = "TakeoverModule"
|
|
103
|
-
TRANSLATOR = "Translator"
|
|
104
113
|
TAMPER = "Tamper Sensor"
|
|
114
|
+
TEMPERATURE = "Temperature"
|
|
115
|
+
TILT = "Tilt"
|
|
116
|
+
TRANSLATOR = "Translator"
|
|
117
|
+
UNKNOWN = "Unknown"
|
|
118
|
+
WATER = "Water"
|
|
105
119
|
|
|
106
120
|
|
|
107
121
|
class ZoneSensorGroup(StrEnum):
|