qolsys-controller 0.0.19__tar.gz → 0.0.56__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of qolsys-controller might be problematic. Click here for more details.
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/.github/workflows/publish.yml +1 -0
- qolsys_controller-0.0.56/PKG-INFO +89 -0
- qolsys_controller-0.0.56/README.md +73 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/example.py +18 -12
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/pyproject.toml +4 -2
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/controller.py +18 -7
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/db.py +31 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table.py +39 -16
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_dashboard_msgs.py +1 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_dimmerlight.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_doorlock.py +3 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_eu_event.py +11 -2
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_master_slave.py +1 -0
- qolsys_controller-0.0.56/qolsys_controller/database/table_powerg_device.py +47 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_qolsyssettings.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_sensor.py +4 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_user.py +1 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_weather.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zwave_node.py +2 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zwave_other.py +14 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/enum.py +23 -8
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/enum_zwave.py +0 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/mdns.py +7 -3
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/panel.py +120 -65
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/partition.py +15 -2
- qolsys_controller-0.0.56/qolsys_controller/plugin.py +24 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/plugin_c4.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/plugin_remote.py +242 -183
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/scene.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/settings.py +53 -19
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/state.py +55 -19
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/task_manager.py +18 -1
- qolsys_controller-0.0.56/qolsys_controller/weather.py +74 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zone.py +191 -38
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_device.py +1 -1
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_lock.py +2 -2
- qolsys_controller-0.0.56/requirements.txt +7 -0
- qolsys_controller-0.0.19/PKG-INFO +0 -92
- qolsys_controller-0.0.19/README.md +0 -76
- qolsys_controller-0.0.19/qolsys_controller/database/table_powerg_device.py +0 -23
- qolsys_controller-0.0.19/qolsys_controller/plugin.py +0 -34
- qolsys_controller-0.0.19/requirements.txt +0 -3
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/.github/workflows/build.yml +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/.gitignore +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/Info_mqtt.md +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/LICENSE +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/bin/qolsys.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/info_pairing.md +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/info_qolsys.md +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/__init__.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_alarmedsensor.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_automation.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_country_locale.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_heat_map.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_history.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_iqremotesettings.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_iqrouter_network_config.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_iqrouter_user_device.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_nest_device.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_output_rules.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_partition.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_pgm_outputs.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_scene.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_shades.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_smartsocket.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_state.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_tcc.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_thermostat.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_trouble_conditions.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_virtual_device.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zigbee_device.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zwave_association_group.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zwave_history.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/errors.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/mqtt_command_queue.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/observable.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/pki.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/utils_mqtt.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_dimmer.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_garagedoor.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_generic.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_outlet.py +0 -0
- {qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/zwave_thermostat.py +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: qolsys-controller
|
|
3
|
+
Version: 0.0.56
|
|
4
|
+
Summary: A Python module that emulates a virtual IQ Remote device, enabling full local control of a Qolsys IQ Panel
|
|
5
|
+
Project-URL: Homepage, https://github.com/EHylands/QolsysController
|
|
6
|
+
Project-URL: Issues, https://github.com/EHylands/QolsysController/issues
|
|
7
|
+
Project-URL: Repository, https://github.com/EHylands/QolsysController.git
|
|
8
|
+
Author: Eric Hylands
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
13
|
+
Classifier: Topic :: Home Automation
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
|
|
17
|
+
# Qolsys Controller - qolsys-controller
|
|
18
|
+
|
|
19
|
+
[](https://github.com/EHylands/QolsysController/actions/workflows/build.yml)
|
|
20
|
+
|
|
21
|
+
A Python module that emulates a virtual IQ Remote device, enabling full **local control** of a Qolsys IQ Panel over MQTT — no cloud access required.
|
|
22
|
+
|
|
23
|
+
## QolsysController
|
|
24
|
+
- ✅ Connects directly to the **Qolsys Panel's local MQTT server as an IQ Remote**
|
|
25
|
+
- 🔐 Pairs by only using **Installer Code** (same procedure as standard IQ Remote pairing)
|
|
26
|
+
- 🔢 Supports **4-digit user codes**
|
|
27
|
+
- ⚠️ Uses a **custom local usercode database** — panel's internal user code verification process is not yet supported
|
|
28
|
+
|
|
29
|
+
## ✨ Functionality Highlights
|
|
30
|
+
|
|
31
|
+
| Category | Feature | Status |
|
|
32
|
+
|------------------------|--------------------------------------|--------|
|
|
33
|
+
| **Panel** | Diagnostic Sensors | ✅ |
|
|
34
|
+
| | Panel Scenes | ✅ |
|
|
35
|
+
| | Weather Forecast | ✅ |
|
|
36
|
+
| | (Alarm.com Weather to Panel) | |
|
|
37
|
+
| **Partition** | Arming Status | ✅ |
|
|
38
|
+
| | Alarm State | ✅ |
|
|
39
|
+
| | Home Instant Arming | ✅ |
|
|
40
|
+
| | Home Silent Disarming (Firmware 4.6.1)| ✅ |
|
|
41
|
+
| | Set Exit Sounds | ✅ |
|
|
42
|
+
| | Set Entry Delay | ✅ |
|
|
43
|
+
| | Disarm Photos | 🛠️ |
|
|
44
|
+
| | TTS | 🛠️ |
|
|
45
|
+
| **Zones** | Sensor Status | ✅ |
|
|
46
|
+
| | Tamper State | ✅ |
|
|
47
|
+
| | Battery Level | ✅ |
|
|
48
|
+
| | Temperature (supported PowerG device)| ✅ |
|
|
49
|
+
| | Light (supported PowerG device) | ✅ |
|
|
50
|
+
| | Average dBm | ✅ |
|
|
51
|
+
| | Latest dBm | ✅ |
|
|
52
|
+
| **Z-Wave Devices** | Battery Level | ✅ |
|
|
53
|
+
| | Node Status | ✅ |
|
|
54
|
+
| | Control Generic Devices | TBD |
|
|
55
|
+
| **Z-Wave Dimmers** | Light Status and Level Control | ✅ |
|
|
56
|
+
| **Z-Wave Door Locks** | Lock, Unlock | ✅ |
|
|
57
|
+
| **Z-Wave Thermostats** | Read device status | ✅ |
|
|
58
|
+
| | Write device status | ✅ |
|
|
59
|
+
| **Z-Wave Garage Doors**| | 🛠️ |
|
|
60
|
+
| **Z-Wave Outlets** | | 🛠️ |
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## ⚠️ Certificate Warning
|
|
64
|
+
|
|
65
|
+
During pairing, the main panel issues **only one signed client certificate** per virtual IQ Remote. If any key files are lost or deleted, re-pairing may become impossible.
|
|
66
|
+
|
|
67
|
+
A new PKI, including a new private key, can be recreated under specific circumstances, though the precise conditions remain unknown at this time.
|
|
68
|
+
|
|
69
|
+
**Important:**
|
|
70
|
+
Immediately back up the following files from the `pki/` directory after initial pairing:
|
|
71
|
+
|
|
72
|
+
- `.key` (private key)
|
|
73
|
+
- `.cer` (certificate)
|
|
74
|
+
- `.csr` (certificate signing request)
|
|
75
|
+
- `.secure` (signed client certificate)
|
|
76
|
+
- `.qolsys` (Qolsys Panel public certificate)
|
|
77
|
+
|
|
78
|
+
Store these files securely.
|
|
79
|
+
|
|
80
|
+
## 📦 Installation
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
git clone https://github.com/EHylands/QolsysController.git
|
|
84
|
+
cd qolsys_controller
|
|
85
|
+
pip3.12 install -r requirements.txt
|
|
86
|
+
|
|
87
|
+
# Change panel_ip and plugin_in in main.py file
|
|
88
|
+
python3.12 example.py
|
|
89
|
+
```
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Qolsys Controller - qolsys-controller
|
|
2
|
+
|
|
3
|
+
[](https://github.com/EHylands/QolsysController/actions/workflows/build.yml)
|
|
4
|
+
|
|
5
|
+
A Python module that emulates a virtual IQ Remote device, enabling full **local control** of a Qolsys IQ Panel over MQTT — no cloud access required.
|
|
6
|
+
|
|
7
|
+
## QolsysController
|
|
8
|
+
- ✅ Connects directly to the **Qolsys Panel's local MQTT server as an IQ Remote**
|
|
9
|
+
- 🔐 Pairs by only using **Installer Code** (same procedure as standard IQ Remote pairing)
|
|
10
|
+
- 🔢 Supports **4-digit user codes**
|
|
11
|
+
- ⚠️ Uses a **custom local usercode database** — panel's internal user code verification process is not yet supported
|
|
12
|
+
|
|
13
|
+
## ✨ Functionality Highlights
|
|
14
|
+
|
|
15
|
+
| Category | Feature | Status |
|
|
16
|
+
|------------------------|--------------------------------------|--------|
|
|
17
|
+
| **Panel** | Diagnostic Sensors | ✅ |
|
|
18
|
+
| | Panel Scenes | ✅ |
|
|
19
|
+
| | Weather Forecast | ✅ |
|
|
20
|
+
| | (Alarm.com Weather to Panel) | |
|
|
21
|
+
| **Partition** | Arming Status | ✅ |
|
|
22
|
+
| | Alarm State | ✅ |
|
|
23
|
+
| | Home Instant Arming | ✅ |
|
|
24
|
+
| | Home Silent Disarming (Firmware 4.6.1)| ✅ |
|
|
25
|
+
| | Set Exit Sounds | ✅ |
|
|
26
|
+
| | Set Entry Delay | ✅ |
|
|
27
|
+
| | Disarm Photos | 🛠️ |
|
|
28
|
+
| | TTS | 🛠️ |
|
|
29
|
+
| **Zones** | Sensor Status | ✅ |
|
|
30
|
+
| | Tamper State | ✅ |
|
|
31
|
+
| | Battery Level | ✅ |
|
|
32
|
+
| | Temperature (supported PowerG device)| ✅ |
|
|
33
|
+
| | Light (supported PowerG device) | ✅ |
|
|
34
|
+
| | Average dBm | ✅ |
|
|
35
|
+
| | Latest dBm | ✅ |
|
|
36
|
+
| **Z-Wave Devices** | Battery Level | ✅ |
|
|
37
|
+
| | Node Status | ✅ |
|
|
38
|
+
| | Control Generic Devices | TBD |
|
|
39
|
+
| **Z-Wave Dimmers** | Light Status and Level Control | ✅ |
|
|
40
|
+
| **Z-Wave Door Locks** | Lock, Unlock | ✅ |
|
|
41
|
+
| **Z-Wave Thermostats** | Read device status | ✅ |
|
|
42
|
+
| | Write device status | ✅ |
|
|
43
|
+
| **Z-Wave Garage Doors**| | 🛠️ |
|
|
44
|
+
| **Z-Wave Outlets** | | 🛠️ |
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
## ⚠️ Certificate Warning
|
|
48
|
+
|
|
49
|
+
During pairing, the main panel issues **only one signed client certificate** per virtual IQ Remote. If any key files are lost or deleted, re-pairing may become impossible.
|
|
50
|
+
|
|
51
|
+
A new PKI, including a new private key, can be recreated under specific circumstances, though the precise conditions remain unknown at this time.
|
|
52
|
+
|
|
53
|
+
**Important:**
|
|
54
|
+
Immediately back up the following files from the `pki/` directory after initial pairing:
|
|
55
|
+
|
|
56
|
+
- `.key` (private key)
|
|
57
|
+
- `.cer` (certificate)
|
|
58
|
+
- `.csr` (certificate signing request)
|
|
59
|
+
- `.secure` (signed client certificate)
|
|
60
|
+
- `.qolsys` (Qolsys Panel public certificate)
|
|
61
|
+
|
|
62
|
+
Store these files securely.
|
|
63
|
+
|
|
64
|
+
## 📦 Installation
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git clone https://github.com/EHylands/QolsysController.git
|
|
68
|
+
cd qolsys_controller
|
|
69
|
+
pip3.12 install -r requirements.txt
|
|
70
|
+
|
|
71
|
+
# Change panel_ip and plugin_in in main.py file
|
|
72
|
+
python3.12 example.py
|
|
73
|
+
```
|
|
@@ -55,8 +55,7 @@ async def main() -> None: # noqa: D103
|
|
|
55
55
|
#await asyncio.sleep(5)
|
|
56
56
|
|
|
57
57
|
#await remote.plugin.stop_operation()
|
|
58
|
-
|
|
59
|
-
LOGGER.debug("Qolsys Panel - Stopped")
|
|
58
|
+
#LOGGER.debug("Qolsys Panel - Stopped")
|
|
60
59
|
|
|
61
60
|
# Change Z-Wave dimmer
|
|
62
61
|
# node_id: z-wane device id
|
|
@@ -65,17 +64,18 @@ async def main() -> None: # noqa: D103
|
|
|
65
64
|
# await remote.plugin.command_zwave_switch_multi_level(node_id=6,level=99)
|
|
66
65
|
|
|
67
66
|
# DISARM
|
|
68
|
-
#
|
|
69
|
-
#
|
|
67
|
+
#await asyncio.sleep(3)
|
|
68
|
+
#await remote.plugin.command_disarm(partition_id="0",
|
|
70
69
|
# user_code="1111")
|
|
71
70
|
|
|
72
71
|
# ARM_STAY
|
|
73
|
-
await asyncio.sleep(3)
|
|
74
|
-
await remote.plugin.command_arm(partition_id="0",
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
#await asyncio.sleep(3)
|
|
73
|
+
#await remote.plugin.command_arm(partition_id="0",
|
|
74
|
+
# arming_type="ARM-STAY",
|
|
75
|
+
# user_code="1111",
|
|
76
|
+
# exit_sounds=False,
|
|
77
|
+
# instant_arm=True,
|
|
78
|
+
# entry_delay=False)
|
|
79
79
|
|
|
80
80
|
|
|
81
81
|
# ARM_AWAY
|
|
@@ -87,9 +87,15 @@ async def main() -> None: # noqa: D103
|
|
|
87
87
|
# instant_arm=True)
|
|
88
88
|
|
|
89
89
|
# DISARM
|
|
90
|
-
await asyncio.sleep(5)
|
|
91
|
-
await remote.plugin.command_disarm(partition_id="0", user_code="1111", silent_disarming=True)
|
|
90
|
+
#await asyncio.sleep(5)
|
|
91
|
+
#await remote.plugin.command_disarm(partition_id="0", user_code="1111", silent_disarming=True)
|
|
92
92
|
|
|
93
|
+
#await asyncio.sleep(5)
|
|
94
|
+
#await remote.plugin.command_execute_scene(scene_id="3")
|
|
95
|
+
|
|
96
|
+
#await asyncio.sleep(5)
|
|
97
|
+
#await remote.plugin.command_zwave_switch_multi_level(6,80)
|
|
98
|
+
#await remote.plugin.command_zwave_doorlock_set(node_id="7",locked=True)
|
|
93
99
|
|
|
94
100
|
# Use an asyncio.Event to keep the program running efficiently
|
|
95
101
|
stop_event = asyncio.Event()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "qolsys-controller"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.56"
|
|
4
4
|
authors = [
|
|
5
5
|
{ name="Eric Hylands", email="" },
|
|
6
6
|
]
|
|
@@ -27,9 +27,11 @@ build-backend = "hatchling.build"
|
|
|
27
27
|
packages = ["qolsys_controller/"]
|
|
28
28
|
|
|
29
29
|
[tool.ruff]
|
|
30
|
-
line-length =
|
|
30
|
+
line-length = 100
|
|
31
31
|
|
|
32
32
|
[tool.ruff.lint]
|
|
33
33
|
select = ['ALL']
|
|
34
34
|
ignore = ["E501","S608","S311","S104","D100","D101", "D102","D107","ERA001", "FBT001","FBT002", "N802","N806","PERF401"]
|
|
35
35
|
|
|
36
|
+
[tool.ruff.lint.mccabe]
|
|
37
|
+
max-complexity = 25
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
|
|
2
4
|
import logging
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from qolsys_controller.plugin import QolsysPlugin
|
|
3
8
|
|
|
4
9
|
from .panel import QolsysPanel
|
|
5
10
|
from .plugin_c4 import QolsysPluginC4
|
|
@@ -9,21 +14,27 @@ from .state import QolsysState
|
|
|
9
14
|
|
|
10
15
|
LOGGER = logging.getLogger(__name__)
|
|
11
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from .plugin import QolsysPlugin
|
|
12
19
|
|
|
13
20
|
class QolsysController:
|
|
14
21
|
|
|
15
22
|
def __init__(self) -> None:
|
|
16
23
|
|
|
17
24
|
# QolsysController Information
|
|
18
|
-
self.
|
|
19
|
-
self._state = QolsysState()
|
|
20
|
-
self._settings = QolsysSettings()
|
|
21
|
-
self._panel = QolsysPanel(
|
|
25
|
+
self._plugin: QolsysPlugin | None = None
|
|
26
|
+
self._state = QolsysState(self)
|
|
27
|
+
self._settings = QolsysSettings(self)
|
|
28
|
+
self._panel = QolsysPanel(self)
|
|
22
29
|
|
|
23
30
|
@property
|
|
24
31
|
def state(self) -> QolsysState:
|
|
25
32
|
return self._state
|
|
26
33
|
|
|
34
|
+
@property
|
|
35
|
+
def plugin(self) -> QolsysPlugin:
|
|
36
|
+
return self._plugin
|
|
37
|
+
|
|
27
38
|
@property
|
|
28
39
|
def panel(self) -> QolsysPanel:
|
|
29
40
|
return self._panel
|
|
@@ -38,13 +49,13 @@ class QolsysController:
|
|
|
38
49
|
|
|
39
50
|
case "c4":
|
|
40
51
|
LOGGER.debug("C4 Plugin Selected")
|
|
41
|
-
self.
|
|
52
|
+
self._plugin = QolsysPluginC4(self)
|
|
42
53
|
return
|
|
43
54
|
|
|
44
55
|
case "remote":
|
|
45
56
|
LOGGER.debug("Remote Plugin Selected")
|
|
46
|
-
self.
|
|
57
|
+
self._plugin = QolsysPluginRemote(self)
|
|
47
58
|
return
|
|
48
59
|
|
|
49
60
|
case _:
|
|
50
|
-
LOGGER.
|
|
61
|
+
LOGGER.error("Unknow Plugin Selected")
|
|
@@ -237,6 +237,37 @@ class QolsysDB:
|
|
|
237
237
|
|
|
238
238
|
return zones
|
|
239
239
|
|
|
240
|
+
def get_weather(self) -> list[dict]:
|
|
241
|
+
self.cursor.execute(f"SELECT * FROM {self.table_weather.table} ORDER BY _id")
|
|
242
|
+
self.db.commit()
|
|
243
|
+
|
|
244
|
+
weather_list = []
|
|
245
|
+
columns = [description[0] for description in self.cursor.description]
|
|
246
|
+
for row in self.cursor.fetchall():
|
|
247
|
+
row_dict = dict(zip(columns, row, strict=True))
|
|
248
|
+
weather_list.append(row_dict)
|
|
249
|
+
|
|
250
|
+
return weather_list
|
|
251
|
+
|
|
252
|
+
def get_powerg(self, short_id: str) -> dict:
|
|
253
|
+
try:
|
|
254
|
+
self.cursor.execute(f"SELECT * FROM {self.table_powerg_device.table} WHERE shortID = ?",(short_id,))
|
|
255
|
+
self.db.commit()
|
|
256
|
+
|
|
257
|
+
row = self.cursor.fetchone()
|
|
258
|
+
|
|
259
|
+
if row is None:
|
|
260
|
+
LOGGER.debug("%s value not found", short_id)
|
|
261
|
+
return None
|
|
262
|
+
|
|
263
|
+
columns = [description[0] for description in self.cursor.description]
|
|
264
|
+
return dict(zip(columns, row, strict=True))
|
|
265
|
+
|
|
266
|
+
except sqlite3.Error:
|
|
267
|
+
LOGGER.exception("Error getting PowerG device info for shortID %s", short_id)
|
|
268
|
+
return None
|
|
269
|
+
|
|
270
|
+
|
|
240
271
|
def get_setting_panel(self, setting: str) -> str:
|
|
241
272
|
self.cursor.execute(f"""SELECT value FROM {self.table_qolsyssettings.table}
|
|
242
273
|
WHERE name = ? and partition_id = ? """, (setting, "0"))
|
|
@@ -68,6 +68,7 @@ class QolsysTable:
|
|
|
68
68
|
raise error from err
|
|
69
69
|
|
|
70
70
|
def insert(self, data: dict) -> None:
|
|
71
|
+
|
|
71
72
|
try:
|
|
72
73
|
if not self._implemented and data is not None:
|
|
73
74
|
LOGGER.warning("New Table format: %s", self.uri)
|
|
@@ -92,6 +93,7 @@ class QolsysTable:
|
|
|
92
93
|
|
|
93
94
|
col_str = ", ".join(full_data.keys())
|
|
94
95
|
placeholder_str = ", ".join([f":{key}" for key in full_data])
|
|
96
|
+
|
|
95
97
|
query = f"INSERT OR IGNORE INTO {self.table} ({col_str}) VALUES ({placeholder_str})"
|
|
96
98
|
self._cursor.execute(query, full_data)
|
|
97
99
|
self._db.commit()
|
|
@@ -106,25 +108,43 @@ class QolsysTable:
|
|
|
106
108
|
if self._abort_on_error:
|
|
107
109
|
raise error from err
|
|
108
110
|
|
|
109
|
-
def update(self, selection: str, selection_argument: str, content_value: str) -> None:
|
|
111
|
+
def update(self, selection: str | None, selection_argument: list | str | None, content_value: str | None) -> None:
|
|
110
112
|
# selection: 'zone_id=?, parition_id=?'
|
|
111
113
|
# Firmware 4.4.1: selection_argument: '[3,1]'
|
|
112
114
|
# Firmware 4.6.1: selection_argument: ['3','1']
|
|
113
115
|
# contentValues:{"partition_id":"0","sensorgroup":"safetymotion","sensorstatus":"Idle"}"
|
|
114
116
|
|
|
115
|
-
#
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
# Selection Argument
|
|
119
|
-
# Panel send selection_argument as list in Firmware 4.6.1
|
|
120
|
-
if(type(selection_argument) is not list):
|
|
121
|
-
#Firmware 4.4.1, seletion_argument is sent as a string
|
|
117
|
+
# Firmware 4.4.1: seletion_argument is sent as a string and needs to be converted to an array
|
|
118
|
+
if(type(selection_argument) is str):
|
|
122
119
|
selection_argument = selection_argument.strip("[]")
|
|
123
120
|
selection_argument = [item.strip() for item in selection_argument.split(",")]
|
|
124
121
|
|
|
125
122
|
try:
|
|
126
|
-
|
|
127
|
-
|
|
123
|
+
full_data = {}
|
|
124
|
+
new_columns = []
|
|
125
|
+
|
|
126
|
+
for key, value in content_value.items():
|
|
127
|
+
if key in self._columns:
|
|
128
|
+
full_data[key] = value
|
|
129
|
+
else:
|
|
130
|
+
new_columns.append(key)
|
|
131
|
+
|
|
132
|
+
db_value = ",".join([f"{key}='{value}'" for key, value in full_data.items()])
|
|
133
|
+
|
|
134
|
+
# Warn if new column found in iq2meid database
|
|
135
|
+
if new_columns:
|
|
136
|
+
LOGGER.warning("New column found in iq2meid database")
|
|
137
|
+
LOGGER.warning("Table: %s", self.table)
|
|
138
|
+
LOGGER.warning("New Columns: %s", new_columns)
|
|
139
|
+
LOGGER.warning("Please Report")
|
|
140
|
+
|
|
141
|
+
if selection:
|
|
142
|
+
query = f"UPDATE {self.table} SET {db_value} WHERE {selection}"
|
|
143
|
+
self._cursor.execute(query, selection_argument)
|
|
144
|
+
else:
|
|
145
|
+
query = f"UPDATE {self.table} SET {db_value}"
|
|
146
|
+
self._cursor.execute(query)
|
|
147
|
+
|
|
128
148
|
self._db.commit()
|
|
129
149
|
|
|
130
150
|
except sqlite3.Error as err:
|
|
@@ -140,20 +160,23 @@ class QolsysTable:
|
|
|
140
160
|
if self._abort_on_error:
|
|
141
161
|
raise error from err
|
|
142
162
|
|
|
143
|
-
def delete(self, selection: str, selection_argument: str) -> None:
|
|
163
|
+
def delete(self, selection: str | None, selection_argument: list | str | None) -> None:
|
|
144
164
|
# selection: 'zone_id=?, parition_id=?'
|
|
145
165
|
# Firmware 4.4.1: selection_argument: '[3,1]'
|
|
146
166
|
# Firmware 4.6.1: selection_argument: ['3','1']
|
|
147
167
|
|
|
148
|
-
#
|
|
149
|
-
if(type(selection_argument) is
|
|
150
|
-
#Firmware 4.4.1, seletion_argument is sent as a string
|
|
168
|
+
# Firmware 4.4.1: seletion_argument is sent as a string and needs to be converted to an array
|
|
169
|
+
if(type(selection_argument) is str):
|
|
151
170
|
selection_argument = selection_argument.strip("[]")
|
|
152
171
|
selection_argument = [item.strip() for item in selection_argument.split(",")]
|
|
153
172
|
|
|
154
173
|
try:
|
|
155
|
-
|
|
156
|
-
|
|
174
|
+
if selection:
|
|
175
|
+
query = f"DELETE FROM {self.table} WHERE {selection}"
|
|
176
|
+
self._cursor.execute(query, selection_argument)
|
|
177
|
+
else:
|
|
178
|
+
self.clear()
|
|
179
|
+
|
|
157
180
|
self._db.commit()
|
|
158
181
|
|
|
159
182
|
except sqlite3.Error as err:
|
|
@@ -12,7 +12,7 @@ class QolsysTableDimmerLight(QolsysTable):
|
|
|
12
12
|
super().__init__(db, cursor)
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.DimmerLightsContentProvider/dimmerlight"
|
|
14
14
|
self._table = "dimmerlight"
|
|
15
|
-
self._abort_on_error =
|
|
15
|
+
self._abort_on_error = False
|
|
16
16
|
self._implemented = True
|
|
17
17
|
|
|
18
18
|
self._columns = [
|
{qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_doorlock.py
RENAMED
|
@@ -12,11 +12,12 @@ class QolsysTableDoorLock(QolsysTable):
|
|
|
12
12
|
super().__init__(db, cursor)
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.DoorLocksContentProvider/doorlock"
|
|
14
14
|
self._table = "doorlock"
|
|
15
|
-
self._abort_on_error =
|
|
15
|
+
self._abort_on_error = False
|
|
16
16
|
self._implemented = True
|
|
17
17
|
|
|
18
18
|
self._columns = [
|
|
19
19
|
"_id",
|
|
20
|
+
"capabilities",
|
|
20
21
|
"version",
|
|
21
22
|
"opr",
|
|
22
23
|
"partition_id",
|
|
@@ -32,6 +33,7 @@ class QolsysTableDoorLock(QolsysTable):
|
|
|
32
33
|
"panel_arming",
|
|
33
34
|
"endpoint",
|
|
34
35
|
"paired_status",
|
|
36
|
+
"configuration",
|
|
35
37
|
]
|
|
36
38
|
|
|
37
39
|
self._create_table()
|
{qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_eu_event.py
RENAMED
|
@@ -13,12 +13,21 @@ class QolsysTableEuEvent(QolsysTable):
|
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.EUEventContentProvider/eu_event"
|
|
14
14
|
self._table = "eu_event"
|
|
15
15
|
self._abort_on_error = False
|
|
16
|
-
self._implemented =
|
|
16
|
+
self._implemented = True
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
self._columns = [
|
|
20
20
|
"_id",
|
|
21
|
+
"version",
|
|
22
|
+
"opr",
|
|
23
|
+
"partition_id",
|
|
24
|
+
"history_id",
|
|
25
|
+
"device_id",
|
|
26
|
+
"device",
|
|
27
|
+
"events",
|
|
28
|
+
"time",
|
|
29
|
+
"ack",
|
|
30
|
+
"type",
|
|
21
31
|
]
|
|
22
32
|
|
|
23
33
|
self._create_table()
|
|
24
|
-
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import logging # noqa: INP001
|
|
2
|
+
import sqlite3
|
|
3
|
+
|
|
4
|
+
from .table import QolsysTable
|
|
5
|
+
|
|
6
|
+
LOGGER = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class QolsysTablePowerGDevice(QolsysTable):
|
|
10
|
+
|
|
11
|
+
def __init__(self, db: sqlite3.Connection, cursor: sqlite3.Cursor) -> None:
|
|
12
|
+
super().__init__(db, cursor)
|
|
13
|
+
self._uri = "content://com.qolsys.qolsysprovider.PowerGDeviceContentProvider/powerg_device"
|
|
14
|
+
self._table = "powerg_device"
|
|
15
|
+
self._abort_on_error = False
|
|
16
|
+
self._implemented = True
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
self._columns = [
|
|
20
|
+
"_id",
|
|
21
|
+
"avg_link_quality",
|
|
22
|
+
"battery_voltage",
|
|
23
|
+
"capabilities",
|
|
24
|
+
"dealer_code",
|
|
25
|
+
"extras",
|
|
26
|
+
"firmware_version",
|
|
27
|
+
"led",
|
|
28
|
+
"light",
|
|
29
|
+
"link_quality",
|
|
30
|
+
"link_status",
|
|
31
|
+
"longID",
|
|
32
|
+
"manufacturing_id",
|
|
33
|
+
"notification_period",
|
|
34
|
+
"opr",
|
|
35
|
+
"parent_node",
|
|
36
|
+
"partition_id",
|
|
37
|
+
"radio_id",
|
|
38
|
+
"radio_version",
|
|
39
|
+
"shortID",
|
|
40
|
+
"status_data",
|
|
41
|
+
"supported_type",
|
|
42
|
+
"temperature",
|
|
43
|
+
"version",
|
|
44
|
+
"writeable_capabilities",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
self._create_table()
|
|
@@ -12,7 +12,7 @@ class QolsysTableQolsysSettings(QolsysTable):
|
|
|
12
12
|
super().__init__(db, cursor)
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.QolsysSettingsProvider/qolsyssettings"
|
|
14
14
|
self._table = "qolsyssettings"
|
|
15
|
-
self._abort_on_error =
|
|
15
|
+
self._abort_on_error = False
|
|
16
16
|
self._implemented = True
|
|
17
17
|
|
|
18
18
|
|
{qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_sensor.py
RENAMED
|
@@ -40,6 +40,9 @@ class QolsysTableSensor(QolsysTable):
|
|
|
40
40
|
"zone_supervised",
|
|
41
41
|
"zone_two_way_voice_enabled",
|
|
42
42
|
"zone_reporting_enabled",
|
|
43
|
+
"zone_feature1",
|
|
44
|
+
"zone_feature2",
|
|
45
|
+
"zone_feature3",
|
|
43
46
|
"battery_status",
|
|
44
47
|
"created_date",
|
|
45
48
|
"created_by",
|
|
@@ -59,6 +62,7 @@ class QolsysTableSensor(QolsysTable):
|
|
|
59
62
|
"latestdBm",
|
|
60
63
|
"averagedBm",
|
|
61
64
|
"serial_number",
|
|
65
|
+
"secondary_panel_mac_address",
|
|
62
66
|
"extras",
|
|
63
67
|
"allowspeaker",
|
|
64
68
|
]
|
{qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_weather.py
RENAMED
|
@@ -12,7 +12,7 @@ class QolsysTableWeather(QolsysTable):
|
|
|
12
12
|
super().__init__(db, cursor)
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.ForecastWeatherContentProvider/weather"
|
|
14
14
|
self._table = "weather"
|
|
15
|
-
self._abort_on_error =
|
|
15
|
+
self._abort_on_error = False
|
|
16
16
|
self._implemented = True
|
|
17
17
|
|
|
18
18
|
self._columns = [
|
{qolsys_controller-0.0.19 → qolsys_controller-0.0.56}/qolsys_controller/database/table_zwave_node.py
RENAMED
|
@@ -12,7 +12,7 @@ class QolsysTableZwaveNode(QolsysTable):
|
|
|
12
12
|
super().__init__(db, cursor)
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.ZwaveContentProvider/zwave_node"
|
|
14
14
|
self._table = "zwave_node"
|
|
15
|
-
self._abort_on_error =
|
|
15
|
+
self._abort_on_error = False
|
|
16
16
|
self._implemented = True
|
|
17
17
|
|
|
18
18
|
self._columns = [
|
|
@@ -57,6 +57,7 @@ class QolsysTableZwaveNode(QolsysTable):
|
|
|
57
57
|
"last_rediscover_time",
|
|
58
58
|
"neighbour_info",
|
|
59
59
|
"last_node_test_time",
|
|
60
|
+
"notification_capabilities",
|
|
60
61
|
"endpoint",
|
|
61
62
|
"endpoint_details",
|
|
62
63
|
"device_wakeup_time",
|
|
@@ -13,10 +13,23 @@ class QolsysTableZwaveOther(QolsysTable):
|
|
|
13
13
|
self._uri = "content://com.qolsys.qolsysprovider.ZwaveOtherDeviceContentProvider/zwave_other"
|
|
14
14
|
self._table = "zwave_other"
|
|
15
15
|
self._abort_on_error = False
|
|
16
|
-
self._implemented =
|
|
16
|
+
self._implemented = True
|
|
17
17
|
|
|
18
18
|
self._columns = [
|
|
19
19
|
"_id",
|
|
20
|
+
"created_date",
|
|
21
|
+
"device_name",
|
|
22
|
+
"device_params_1",
|
|
23
|
+
"device_params_2",
|
|
24
|
+
"endpoint",
|
|
25
|
+
"last_updated_date",
|
|
26
|
+
"node_id",
|
|
27
|
+
"node_type",
|
|
28
|
+
"opr",
|
|
29
|
+
"paired_status",
|
|
30
|
+
"partition_id",
|
|
31
|
+
"status",
|
|
32
|
+
"version",
|
|
20
33
|
]
|
|
21
34
|
|
|
22
35
|
self._create_table()
|