qolsys-controller 0.0.38__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 +63 -25
- 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 +1 -1
- qolsys_controller/database/table_eu_event.py +12 -4
- 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 +25 -3
- qolsys_controller/database/table_qolsyssettings.py +0 -2
- qolsys_controller/database/table_scene.py +0 -2
- qolsys_controller/database/table_sensor.py +3 -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 +1 -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 +1 -1
- qolsys_controller/database/table_zwave_other.py +14 -2
- qolsys_controller/enum.py +44 -16
- 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 +224 -143
- 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 +71 -33
- 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 +307 -169
- 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.38.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.38.dist-info/METADATA +0 -93
- qolsys_controller-0.0.38.dist-info/RECORD +0 -68
- {qolsys_controller-0.0.38.dist-info → qolsys_controller-0.0.62.dist-info}/licenses/LICENSE +0 -0
qolsys_controller/scene.py
CHANGED
|
@@ -6,36 +6,46 @@ LOGGER = logging.getLogger(__name__)
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class QolsysScene(QolsysObservable):
|
|
9
|
-
|
|
10
|
-
def __init__(self, data: dict) -> None:
|
|
9
|
+
def __init__(self, data: dict[str, str]) -> None:
|
|
11
10
|
super().__init__()
|
|
12
11
|
|
|
13
|
-
self._scene_id = data.get("scene_id", "")
|
|
14
|
-
self._name = data.get("name", "")
|
|
15
|
-
self._icon = data.get("icon", "")
|
|
16
|
-
self._color = data.get("color", "")
|
|
17
|
-
|
|
18
|
-
def update(self, data: dict) -> None:
|
|
12
|
+
self._scene_id: str = data.get("scene_id", "")
|
|
13
|
+
self._name: str = data.get("name", "")
|
|
14
|
+
self._icon: str = data.get("icon", "")
|
|
15
|
+
self._color: str = data.get("color", "")
|
|
19
16
|
|
|
17
|
+
def update(self, data: dict[str, str]) -> None:
|
|
20
18
|
scene_id_update = data.get("scene_id", "")
|
|
21
19
|
if scene_id_update != self._scene_id:
|
|
22
|
-
LOGGER.error("Updating Scene%s (%s) with Scene%s (different id)", self._scene_id, self.
|
|
20
|
+
LOGGER.error("Updating Scene%s (%s) with Scene%s (different id)", self._scene_id, self.name, scene_id_update)
|
|
23
21
|
return
|
|
24
22
|
|
|
25
23
|
self.start_batch_update()
|
|
26
24
|
|
|
27
25
|
# Update name
|
|
28
26
|
if "name" in data:
|
|
29
|
-
self.sensorname = data.get("name")
|
|
27
|
+
self.sensorname = data.get("name", "")
|
|
30
28
|
|
|
31
29
|
if "color" in data:
|
|
32
|
-
self.color = data.get("color")
|
|
30
|
+
self.color = data.get("color", "")
|
|
33
31
|
|
|
34
32
|
if "icon" in data:
|
|
35
|
-
self.icon = data.get("icon")
|
|
33
|
+
self.icon = data.get("icon", "")
|
|
36
34
|
|
|
37
35
|
self.end_batch_update()
|
|
38
36
|
|
|
37
|
+
def to_dict(self) -> dict[str, str]:
|
|
38
|
+
return {
|
|
39
|
+
"scene_id": self.scene_id,
|
|
40
|
+
"name": self.name,
|
|
41
|
+
"color": self.color,
|
|
42
|
+
"icon": self.icon,
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
# -----------------------------
|
|
46
|
+
# properties + setters
|
|
47
|
+
# -----------------------------
|
|
48
|
+
|
|
39
49
|
@property
|
|
40
50
|
def scene_id(self) -> str:
|
|
41
51
|
return self._scene_id
|
|
@@ -44,36 +54,28 @@ class QolsysScene(QolsysObservable):
|
|
|
44
54
|
def name(self) -> str:
|
|
45
55
|
return self._name
|
|
46
56
|
|
|
47
|
-
@property
|
|
48
|
-
def icon(self) -> str:
|
|
49
|
-
return self._icon
|
|
50
|
-
|
|
51
|
-
@property
|
|
52
|
-
def color(self) -> str:
|
|
53
|
-
return self._color
|
|
54
|
-
|
|
55
57
|
@name.setter
|
|
56
58
|
def name(self, value: str) -> None:
|
|
57
59
|
if self._name != value:
|
|
58
60
|
self._name = value
|
|
59
61
|
self.notify()
|
|
60
62
|
|
|
63
|
+
@property
|
|
64
|
+
def icon(self) -> str:
|
|
65
|
+
return self._icon
|
|
66
|
+
|
|
61
67
|
@icon.setter
|
|
62
68
|
def icon(self, value: str) -> None:
|
|
63
69
|
if self._icon != value:
|
|
64
70
|
self._icon = value
|
|
65
71
|
self.notify()
|
|
66
72
|
|
|
73
|
+
@property
|
|
74
|
+
def color(self) -> str:
|
|
75
|
+
return self._color
|
|
76
|
+
|
|
67
77
|
@color.setter
|
|
68
78
|
def color(self, value: str) -> None:
|
|
69
79
|
if self._color != value:
|
|
70
80
|
self._color = value
|
|
71
81
|
self.notify()
|
|
72
|
-
|
|
73
|
-
def to_dict(self) -> dict:
|
|
74
|
-
return {
|
|
75
|
-
"scene_id": self.scene_id,
|
|
76
|
-
"name": self.name,
|
|
77
|
-
"color": self.color,
|
|
78
|
-
"icon": self.icon,
|
|
79
|
-
}
|
qolsys_controller/settings.py
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
2
4
|
from pathlib import Path
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
3
6
|
|
|
4
7
|
LOGGER = logging.getLogger(__name__)
|
|
5
8
|
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .controller import QolsysController
|
|
6
11
|
|
|
7
|
-
class QolsysSettings:
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
class QolsysSettings:
|
|
14
|
+
def __init__(self, controller: QolsysController) -> None:
|
|
15
|
+
self._controller = controller
|
|
10
16
|
|
|
11
17
|
# Plugin
|
|
12
|
-
self._plugin_ip = ""
|
|
13
|
-
self._random_mac = ""
|
|
14
|
-
self._panel_mac = ""
|
|
15
|
-
self._panel_ip = ""
|
|
18
|
+
self._plugin_ip: str = ""
|
|
19
|
+
self._random_mac: str = ""
|
|
20
|
+
self._panel_mac: str = ""
|
|
21
|
+
self._panel_ip: str = ""
|
|
16
22
|
|
|
17
23
|
# Path
|
|
18
24
|
self._config_directory: Path = Path()
|
|
@@ -22,16 +28,40 @@ class QolsysSettings:
|
|
|
22
28
|
|
|
23
29
|
# Pki
|
|
24
30
|
self._key_size: int = 2048
|
|
31
|
+
self._auto_discover_pki: bool = True
|
|
25
32
|
|
|
26
33
|
# MQTT
|
|
27
34
|
self._mqtt_timeout: int = 30
|
|
28
35
|
self._mqtt_ping: int = 600
|
|
29
|
-
self._mqtt_qos:int = 0
|
|
30
|
-
self._mqtt_remote_client_id = ""
|
|
36
|
+
self._mqtt_qos: int = 0
|
|
37
|
+
self._mqtt_remote_client_id: str = ""
|
|
38
|
+
self._log_mqtt_message: bool = False
|
|
31
39
|
|
|
32
40
|
# Operation
|
|
33
|
-
self._motion_sensor_delay:bool = True
|
|
34
|
-
self._motion_sensor_delay_sec:int = 310
|
|
41
|
+
self._motion_sensor_delay: bool = True
|
|
42
|
+
self._motion_sensor_delay_sec: int = 310
|
|
43
|
+
self._check_user_code_on_arm: bool = False
|
|
44
|
+
self._check_user_code_on_disarm: bool = True
|
|
45
|
+
|
|
46
|
+
def check_panel_ip(self) -> bool:
|
|
47
|
+
if self._panel_ip == "":
|
|
48
|
+
LOGGER.debug("Invalid Panel IP: %s", self._panel_ip)
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
LOGGER.debug("Found Panel IP: %s", self._panel_ip)
|
|
52
|
+
return True
|
|
53
|
+
|
|
54
|
+
def check_plugin_ip(self) -> bool:
|
|
55
|
+
if self._plugin_ip == "":
|
|
56
|
+
LOGGER.debug("Invalid Plugin IP: %s", self._plugin_ip)
|
|
57
|
+
return False
|
|
58
|
+
|
|
59
|
+
LOGGER.debug("Found Plugin IP: %s", self._plugin_ip)
|
|
60
|
+
return True
|
|
61
|
+
|
|
62
|
+
# -----------------------------
|
|
63
|
+
# properties + setters
|
|
64
|
+
# -----------------------------
|
|
35
65
|
|
|
36
66
|
@property
|
|
37
67
|
def random_mac(self) -> str:
|
|
@@ -45,6 +75,10 @@ class QolsysSettings:
|
|
|
45
75
|
def plugin_ip(self) -> str:
|
|
46
76
|
return self._plugin_ip
|
|
47
77
|
|
|
78
|
+
@plugin_ip.setter
|
|
79
|
+
def plugin_ip(self, plugin_ip: str) -> None:
|
|
80
|
+
self._plugin_ip = plugin_ip
|
|
81
|
+
|
|
48
82
|
@property
|
|
49
83
|
def panel_mac(self) -> str:
|
|
50
84
|
return self._panel_mac
|
|
@@ -57,36 +91,76 @@ class QolsysSettings:
|
|
|
57
91
|
def panel_ip(self) -> str:
|
|
58
92
|
return self._panel_ip
|
|
59
93
|
|
|
94
|
+
@panel_ip.setter
|
|
95
|
+
def panel_ip(self, panel_ip: str) -> None:
|
|
96
|
+
self._panel_ip = panel_ip
|
|
97
|
+
|
|
98
|
+
@property
|
|
99
|
+
def log_mqtt_mesages(self) -> bool:
|
|
100
|
+
return self._log_mqtt_messages
|
|
101
|
+
|
|
102
|
+
@log_mqtt_mesages.setter
|
|
103
|
+
def log_mqtt_mesages(self, log_mqtt_mesages: bool) -> None:
|
|
104
|
+
self._log_mqtt_messages = log_mqtt_mesages
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def check_user_code_on_disarm(self) -> bool:
|
|
108
|
+
return self._check_user_code_on_disarm
|
|
109
|
+
|
|
110
|
+
@check_user_code_on_disarm.setter
|
|
111
|
+
def check_user_code_on_disarm(self, check_user_code_on_disarm: bool) -> None:
|
|
112
|
+
self._check_user_code_on_disarm = check_user_code_on_disarm
|
|
113
|
+
|
|
114
|
+
@property
|
|
115
|
+
def check_user_code_on_arm(self) -> bool:
|
|
116
|
+
return self._check_user_code_on_arm
|
|
117
|
+
|
|
118
|
+
@check_user_code_on_arm.setter
|
|
119
|
+
def check_user_code_on_arm(self, check_user_code_on_arm: bool) -> None:
|
|
120
|
+
self._check_user_code_on_arm = check_user_code_on_arm
|
|
121
|
+
|
|
122
|
+
@property
|
|
123
|
+
def auto_discover_pki(self) -> bool:
|
|
124
|
+
return self._auto_discover_pki
|
|
125
|
+
|
|
126
|
+
@auto_discover_pki.setter
|
|
127
|
+
def auto_discover_pki(self, value: bool) -> None:
|
|
128
|
+
self._auto_discover_pki = value
|
|
129
|
+
|
|
60
130
|
@property
|
|
61
131
|
def mqtt_timeout(self) -> int:
|
|
62
132
|
return self._mqtt_timeout
|
|
63
133
|
|
|
134
|
+
@mqtt_timeout.setter
|
|
135
|
+
def mqtt_timeout(self, value: int) -> None:
|
|
136
|
+
self._mqtt_timeout = value
|
|
137
|
+
|
|
64
138
|
@property
|
|
65
139
|
def mqtt_ping(self) -> int:
|
|
66
140
|
return self._mqtt_ping
|
|
67
141
|
|
|
142
|
+
@mqtt_ping.setter
|
|
143
|
+
def mqtt_ping(self, value: int) -> None:
|
|
144
|
+
self._mqtt_ping = value
|
|
145
|
+
|
|
68
146
|
@property
|
|
69
147
|
def motion_sensor_delay(self) -> bool:
|
|
70
148
|
return self._motion_sensor_delay
|
|
71
149
|
|
|
72
|
-
@property
|
|
73
|
-
def motion_sensor_delay_sec(self) -> int:
|
|
74
|
-
return self._motion_sensor_delay_sec
|
|
75
|
-
|
|
76
150
|
@motion_sensor_delay.setter
|
|
77
151
|
def motion_sensor_delay(self, value: bool) -> None:
|
|
78
152
|
self._motion_sensor_delay = value
|
|
79
153
|
|
|
80
|
-
@
|
|
81
|
-
def
|
|
82
|
-
self.
|
|
154
|
+
@property
|
|
155
|
+
def motion_sensor_delay_sec(self) -> int:
|
|
156
|
+
return self._motion_sensor_delay_sec
|
|
83
157
|
|
|
84
|
-
@
|
|
85
|
-
def
|
|
86
|
-
self.
|
|
158
|
+
@motion_sensor_delay_sec.setter
|
|
159
|
+
def motion_sensor_delay_sec(self, value: int) -> None:
|
|
160
|
+
self._motion_sensor_delay_sec = value
|
|
87
161
|
|
|
88
162
|
@property
|
|
89
|
-
def config_directory(self) ->
|
|
163
|
+
def config_directory(self) -> Path:
|
|
90
164
|
return self._config_directory
|
|
91
165
|
|
|
92
166
|
@config_directory.setter
|
|
@@ -108,18 +182,6 @@ class QolsysSettings:
|
|
|
108
182
|
def key_size(self) -> int:
|
|
109
183
|
return self._key_size
|
|
110
184
|
|
|
111
|
-
@mqtt_timeout.setter
|
|
112
|
-
def mqtt_timeout(self, value: int) -> None:
|
|
113
|
-
self._mqtt_timeout = value
|
|
114
|
-
|
|
115
|
-
@mqtt_ping.setter
|
|
116
|
-
def mqtt_ping(self, value: int) -> None:
|
|
117
|
-
self._mqtt_ping = value
|
|
118
|
-
|
|
119
|
-
@mqtt_ping.setter
|
|
120
|
-
def mqtt_ping(self, ping:int) -> None:
|
|
121
|
-
self._mqtt_ping = ping
|
|
122
|
-
|
|
123
185
|
@property
|
|
124
186
|
def mqtt_qos(self) -> int:
|
|
125
187
|
return self._mqtt_qos
|
|
@@ -129,25 +191,9 @@ class QolsysSettings:
|
|
|
129
191
|
return self._mqtt_remote_client_id
|
|
130
192
|
|
|
131
193
|
@mqtt_remote_client_id.setter
|
|
132
|
-
def mqtt_remote_client_id(self,client_id:str) -> None:
|
|
194
|
+
def mqtt_remote_client_id(self, client_id: str) -> None:
|
|
133
195
|
self._mqtt_remote_client_id = client_id
|
|
134
196
|
|
|
135
|
-
def check_panel_ip(self) -> bool:
|
|
136
|
-
if self._panel_ip == "":
|
|
137
|
-
LOGGER.debug("Invalid Panel IP: %s", self._panel_ip)
|
|
138
|
-
return False
|
|
139
|
-
|
|
140
|
-
LOGGER.debug("Found Panel IP: %s", self._panel_ip)
|
|
141
|
-
return True
|
|
142
|
-
|
|
143
|
-
def check_plugin_ip(self) -> bool:
|
|
144
|
-
if self._plugin_ip == "":
|
|
145
|
-
LOGGER.debug("Invalid Plugin IP: %s", self._plugin_ip)
|
|
146
|
-
return False
|
|
147
|
-
|
|
148
|
-
LOGGER.debug("Found Plugin IP: %s", self._plugin_ip)
|
|
149
|
-
return True
|
|
150
|
-
|
|
151
197
|
def check_config_directory(self, create: bool = True) -> bool: # noqa: PLR0911
|
|
152
198
|
if not self.config_directory.is_dir():
|
|
153
199
|
if not create:
|
qolsys_controller/state.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import logging
|
|
4
|
+
from typing import TYPE_CHECKING
|
|
2
5
|
|
|
3
6
|
from .observable import QolsysObservable
|
|
4
|
-
from .
|
|
5
|
-
from .scene import QolsysScene
|
|
6
|
-
from .zone import QolsysZone
|
|
7
|
+
from .weather import QolsysWeather
|
|
7
8
|
from .zwave_device import QolsysZWaveDevice
|
|
8
9
|
from .zwave_dimmer import QolsysDimmer
|
|
9
10
|
from .zwave_generic import QolsysGeneric
|
|
@@ -12,17 +13,23 @@ from .zwave_thermostat import QolsysThermostat
|
|
|
12
13
|
|
|
13
14
|
LOGGER = logging.getLogger(__name__)
|
|
14
15
|
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from .controller import QolsysController
|
|
18
|
+
from .partition import QolsysPartition
|
|
19
|
+
from .scene import QolsysScene
|
|
20
|
+
from .zone import QolsysZone
|
|
21
|
+
from .zwave_device import QolsysZWaveDevice
|
|
15
22
|
|
|
16
|
-
class QolsysState(QolsysObservable):
|
|
17
23
|
|
|
18
|
-
|
|
24
|
+
class QolsysState(QolsysObservable):
|
|
25
|
+
def __init__(self, controller: QolsysController) -> None:
|
|
19
26
|
super().__init__()
|
|
20
|
-
|
|
21
|
-
self.
|
|
22
|
-
self.
|
|
23
|
-
self.
|
|
24
|
-
self.
|
|
25
|
-
|
|
27
|
+
self._controller: QolsysController = controller
|
|
28
|
+
self._weather: QolsysWeather = QolsysWeather()
|
|
29
|
+
self._partitions: list[QolsysPartition] = []
|
|
30
|
+
self._zones: list[QolsysZone] = []
|
|
31
|
+
self._zwave_devices: list[QolsysZWaveDevice] = []
|
|
32
|
+
self._scenes: list[QolsysScene] = []
|
|
26
33
|
self._state_partition_observer = QolsysObservable()
|
|
27
34
|
self._state_zone_observer = QolsysObservable()
|
|
28
35
|
self._state_zwave_observer = QolsysObservable()
|
|
@@ -44,6 +51,10 @@ class QolsysState(QolsysObservable):
|
|
|
44
51
|
def scenes(self) -> list[QolsysScene]:
|
|
45
52
|
return self._scenes
|
|
46
53
|
|
|
54
|
+
@property
|
|
55
|
+
def weather(self) -> QolsysWeather:
|
|
56
|
+
return self._weather
|
|
57
|
+
|
|
47
58
|
@property
|
|
48
59
|
def zwave_dimmers(self) -> list[QolsysDimmer]:
|
|
49
60
|
dimmers = []
|
|
@@ -87,7 +98,7 @@ class QolsysState(QolsysObservable):
|
|
|
87
98
|
def state_scene_observer(self) -> QolsysObservable:
|
|
88
99
|
return self._state_scene_observer
|
|
89
100
|
|
|
90
|
-
def partition(self, partition_id: str) -> QolsysPartition:
|
|
101
|
+
def partition(self, partition_id: str) -> QolsysPartition | None:
|
|
91
102
|
for partition in self.partitions:
|
|
92
103
|
if partition.id == partition_id:
|
|
93
104
|
return partition
|
|
@@ -97,8 +108,11 @@ class QolsysState(QolsysObservable):
|
|
|
97
108
|
def partition_add(self, new_partition: QolsysPartition) -> None:
|
|
98
109
|
for partition in self.partitions:
|
|
99
110
|
if new_partition.id == partition.id:
|
|
100
|
-
LOGGER.debug(
|
|
101
|
-
|
|
111
|
+
LOGGER.debug(
|
|
112
|
+
"Adding Partition to State, Partition%s (%s) - Allready in Partitions List",
|
|
113
|
+
new_partition.id,
|
|
114
|
+
partition.name,
|
|
115
|
+
)
|
|
102
116
|
return
|
|
103
117
|
|
|
104
118
|
self.partitions.append(new_partition)
|
|
@@ -115,7 +129,7 @@ class QolsysState(QolsysObservable):
|
|
|
115
129
|
self.partitions.remove(partition)
|
|
116
130
|
self.state_partition_observer.notify()
|
|
117
131
|
|
|
118
|
-
def scene(self, scene_id: str) -> QolsysScene:
|
|
132
|
+
def scene(self, scene_id: str) -> QolsysScene | None:
|
|
119
133
|
for scene in self.scenes:
|
|
120
134
|
if scene.scene_id == scene_id:
|
|
121
135
|
return scene
|
|
@@ -125,7 +139,7 @@ class QolsysState(QolsysObservable):
|
|
|
125
139
|
def scene_add(self, new_scene: QolsysScene) -> None:
|
|
126
140
|
for scene in self.scenes:
|
|
127
141
|
if new_scene.scene_id == scene.scene_id:
|
|
128
|
-
LOGGER.debug("Adding Scene to State, Scene%s (%s) - Allready in Scene List", new_scene.scene_id, scene.name
|
|
142
|
+
LOGGER.debug("Adding Scene to State, Scene%s (%s) - Allready in Scene List", new_scene.scene_id, scene.name)
|
|
129
143
|
return
|
|
130
144
|
|
|
131
145
|
self.scenes.append(new_scene)
|
|
@@ -143,16 +157,24 @@ class QolsysState(QolsysObservable):
|
|
|
143
157
|
self.scenes.remove(scene)
|
|
144
158
|
self.state_scene_observer.notify()
|
|
145
159
|
|
|
146
|
-
def zone(self, zone_id: str) -> QolsysZone:
|
|
160
|
+
def zone(self, zone_id: str) -> QolsysZone | None:
|
|
147
161
|
for zone in self.zones:
|
|
148
162
|
if zone.zone_id == zone_id:
|
|
149
163
|
return zone
|
|
150
164
|
return None
|
|
151
165
|
|
|
166
|
+
def zone_from_short_id(self, short_id: int) -> QolsysZone | None:
|
|
167
|
+
for zone in self.zones:
|
|
168
|
+
if zone.shortID == str(short_id):
|
|
169
|
+
return zone
|
|
170
|
+
return None
|
|
171
|
+
|
|
152
172
|
def zone_add(self, new_zone: QolsysZone) -> None:
|
|
153
173
|
for zone in self.zones:
|
|
154
174
|
if new_zone.zone_id == zone.zone_id:
|
|
155
|
-
LOGGER.debug(
|
|
175
|
+
LOGGER.debug(
|
|
176
|
+
"Adding Zone to State, zone%s (%s) - Allready in Zone List", new_zone.zone_id, new_zone.sensorname
|
|
177
|
+
)
|
|
156
178
|
return
|
|
157
179
|
|
|
158
180
|
self.zones.append(new_zone)
|
|
@@ -169,7 +191,7 @@ class QolsysState(QolsysObservable):
|
|
|
169
191
|
self.zones.remove(zone)
|
|
170
192
|
self.state_zone_observer.notify()
|
|
171
193
|
|
|
172
|
-
def zwave_device(self, node_id: str) -> QolsysZWaveDevice:
|
|
194
|
+
def zwave_device(self, node_id: str) -> QolsysZWaveDevice | None:
|
|
173
195
|
for zwave_device in self.zwave_devices:
|
|
174
196
|
if zwave_device.node_id == node_id:
|
|
175
197
|
return zwave_device
|
|
@@ -179,8 +201,9 @@ class QolsysState(QolsysObservable):
|
|
|
179
201
|
def zwave_add(self, new_zwave: QolsysZWaveDevice) -> None:
|
|
180
202
|
for zwave_device in self.zwave_devices:
|
|
181
203
|
if new_zwave.node_id == zwave_device.node_id:
|
|
182
|
-
LOGGER.debug(
|
|
183
|
-
|
|
204
|
+
LOGGER.debug(
|
|
205
|
+
"Adding ZWave to State, ZWave%s (%s) - Allready in ZWave List", new_zwave.node_id, zwave_device.node_name
|
|
206
|
+
)
|
|
184
207
|
return
|
|
185
208
|
|
|
186
209
|
self.zwave_devices.append(new_zwave)
|
|
@@ -198,7 +221,6 @@ class QolsysState(QolsysObservable):
|
|
|
198
221
|
self.state_zwave_observer.notify()
|
|
199
222
|
|
|
200
223
|
def sync_zwave_devices_data(self, db_zwaves: list[QolsysZWaveDevice]) -> None: # noqa: PLR0912
|
|
201
|
-
|
|
202
224
|
db_zwave_list = []
|
|
203
225
|
for db_zwave in db_zwaves:
|
|
204
226
|
db_zwave_list.append(db_zwave.node_id)
|
|
@@ -223,13 +245,13 @@ class QolsysState(QolsysObservable):
|
|
|
223
245
|
# Update Thermostat
|
|
224
246
|
if isinstance(state_zwave, QolsysThermostat) and isinstance(db_zwave, QolsysThermostat):
|
|
225
247
|
state_zwave.update_base(db_zwave.to_dict_base())
|
|
226
|
-
state_zwave.update_thermostat(db_zwave.to_dict_thermostat)
|
|
248
|
+
state_zwave.update_thermostat(db_zwave.to_dict_thermostat())
|
|
227
249
|
break
|
|
228
250
|
|
|
229
251
|
# Update Lock
|
|
230
252
|
if isinstance(state_zwave, QolsysLock) and isinstance(db_zwave, QolsysLock):
|
|
231
253
|
state_zwave.update_base(db_zwave.to_dict_base())
|
|
232
|
-
state_zwave.update_lock(db_zwave.to_dict_lock)
|
|
254
|
+
state_zwave.update_lock(db_zwave.to_dict_lock())
|
|
233
255
|
break
|
|
234
256
|
|
|
235
257
|
# Generic Z-Wave Device
|
|
@@ -237,10 +259,6 @@ class QolsysState(QolsysObservable):
|
|
|
237
259
|
state_zwave.update_base(db_zwave.to_dict_base())
|
|
238
260
|
break
|
|
239
261
|
|
|
240
|
-
# zwave node_id has changed of node_type, delete and add again
|
|
241
|
-
# self.zwave_delete(int(state_zwave.node_id))
|
|
242
|
-
# self.zwave_add(db_zwave)
|
|
243
|
-
|
|
244
262
|
# Add new zwave device
|
|
245
263
|
for db_zwave in db_zwaves:
|
|
246
264
|
if db_zwave.node_id not in state_zwave_list:
|
|
@@ -250,9 +268,13 @@ class QolsysState(QolsysObservable):
|
|
|
250
268
|
# Delete zwave device
|
|
251
269
|
for state_zwave in self.zwave_devices:
|
|
252
270
|
if state_zwave.node_id not in db_zwave_list:
|
|
253
|
-
LOGGER.debug("sync_data - delete ZWave%s", state_zwave.
|
|
271
|
+
LOGGER.debug("sync_data - delete ZWave%s", state_zwave.node_id)
|
|
254
272
|
self.zwave_delete(state_zwave.node_id)
|
|
255
273
|
|
|
274
|
+
def sync_weather_data(self, db_weather: QolsysWeather) -> None:
|
|
275
|
+
LOGGER.debug("sync_data - update Weather")
|
|
276
|
+
self._weather.update(db_weather.forecasts)
|
|
277
|
+
|
|
256
278
|
def sync_scenes_data(self, db_scenes: list[QolsysScene]) -> None:
|
|
257
279
|
db_scene_list = []
|
|
258
280
|
for db_scene in db_scenes:
|
|
@@ -299,6 +321,7 @@ class QolsysState(QolsysObservable):
|
|
|
299
321
|
if state_zone.zone_id == db_zone.zone_id:
|
|
300
322
|
LOGGER.debug("sync_data - update Zone%s", state_zone.zone_id)
|
|
301
323
|
state_zone.update(db_zone.to_dict())
|
|
324
|
+
state_zone.update_powerg(db_zone.to_powerg_dict())
|
|
302
325
|
|
|
303
326
|
# Delete zones
|
|
304
327
|
for state_zone in self.zones:
|
|
@@ -344,8 +367,8 @@ class QolsysState(QolsysObservable):
|
|
|
344
367
|
LOGGER.debug("sync_data - Add Partition%s", db_partition.id)
|
|
345
368
|
self.partition_add(db_partition)
|
|
346
369
|
|
|
347
|
-
def dump(self) -> None: # noqa: PLR0915
|
|
348
|
-
LOGGER.debug("*** Information ***")
|
|
370
|
+
def dump(self) -> None: # noqa: PLR0912, PLR0915
|
|
371
|
+
LOGGER.debug("*** Device Information ***")
|
|
349
372
|
|
|
350
373
|
for partition in self.partitions:
|
|
351
374
|
pid = partition.id
|
|
@@ -371,6 +394,12 @@ class QolsysState(QolsysObservable):
|
|
|
371
394
|
LOGGER.debug("Zone%s (%s) - latestdBm: %s", zid, name, zone.latestdBm)
|
|
372
395
|
LOGGER.debug("Zone%s (%s) - averagedBm: %s", zid, name, zone.averagedBm)
|
|
373
396
|
|
|
397
|
+
if zone.is_powerg_temperature_enabled():
|
|
398
|
+
LOGGER.debug("Zone%s (%s) - powerg_temperature: %s", zid, name, zone.powerg_temperature)
|
|
399
|
+
|
|
400
|
+
if zone.is_powerg_light_enabled():
|
|
401
|
+
LOGGER.debug("Zone%s (%s) - powerg_light: %s", zid, name, zone.powerg_light)
|
|
402
|
+
|
|
374
403
|
for zwave in self.zwave_devices:
|
|
375
404
|
if isinstance(zwave, QolsysDimmer):
|
|
376
405
|
nid = zwave.node_id
|
|
@@ -398,7 +427,7 @@ class QolsysState(QolsysObservable):
|
|
|
398
427
|
if isinstance(zwave, QolsysLock):
|
|
399
428
|
zid = zwave.lock_node_id
|
|
400
429
|
name = zwave.lock_name
|
|
401
|
-
LOGGER.debug("Lock%s (%s) -
|
|
430
|
+
LOGGER.debug("Lock%s (%s) - lock_status: %s", zid, name, zwave.lock_status)
|
|
402
431
|
continue
|
|
403
432
|
|
|
404
433
|
if isinstance(zwave, QolsysGeneric):
|
|
@@ -413,4 +442,13 @@ class QolsysState(QolsysObservable):
|
|
|
413
442
|
for scene in self.scenes:
|
|
414
443
|
sid = scene.scene_id
|
|
415
444
|
name = scene.name
|
|
416
|
-
LOGGER.debug("Scene%s (%s)",sid, name)
|
|
445
|
+
LOGGER.debug("Scene%s (%s)", sid, name)
|
|
446
|
+
|
|
447
|
+
for forecast in self.weather.forecasts:
|
|
448
|
+
LOGGER.debug(
|
|
449
|
+
"Weather - %s - High: %s, Low:%s, Condition: %s",
|
|
450
|
+
forecast.day_of_week[0:3],
|
|
451
|
+
forecast.high_temp,
|
|
452
|
+
forecast.low_temp,
|
|
453
|
+
forecast.condition,
|
|
454
|
+
)
|
|
@@ -7,32 +7,31 @@ LOGGER = logging.getLogger(__name__)
|
|
|
7
7
|
|
|
8
8
|
class QolsysTaskManager:
|
|
9
9
|
def __init__(self) -> None:
|
|
10
|
-
self._tasks = set()
|
|
10
|
+
self._tasks: set[asyncio.Task] = set() # type: ignore[type-arg]
|
|
11
11
|
|
|
12
|
-
def run(self, coro: Coroutine, label: str) -> asyncio.Task:
|
|
12
|
+
def run(self, coro: Coroutine, label: str) -> asyncio.Task: # type: ignore[type-arg]
|
|
13
13
|
task = asyncio.create_task(coro, name=label)
|
|
14
14
|
self._tasks.add(task)
|
|
15
15
|
|
|
16
|
-
def _done_callback(task: asyncio.Task) -> None:
|
|
17
|
-
|
|
16
|
+
def _done_callback(task: asyncio.Task) -> None: # type: ignore[type-arg]
|
|
18
17
|
try:
|
|
19
18
|
task.result()
|
|
20
19
|
|
|
21
20
|
except asyncio.CancelledError:
|
|
22
|
-
LOGGER.debug("Task Cancelled: %s",task.get_name())
|
|
21
|
+
LOGGER.debug("Task Cancelled: %s", task.get_name())
|
|
23
22
|
|
|
24
23
|
except Exception as e: # noqa: BLE001
|
|
25
|
-
LOGGER.debug("[Callback] Task failed with: %s",e)
|
|
24
|
+
LOGGER.debug("[Callback] Task failed with: %s", e)
|
|
26
25
|
|
|
27
26
|
self._tasks.discard(task)
|
|
28
27
|
|
|
29
28
|
task.add_done_callback(_done_callback)
|
|
30
29
|
return task
|
|
31
30
|
|
|
32
|
-
def get_task(self, label:str) -> asyncio.Task | None:
|
|
31
|
+
def get_task(self, label: str) -> asyncio.Task | None: # type: ignore[type-arg]
|
|
33
32
|
for task in self._tasks:
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
if task.get_name() == label:
|
|
34
|
+
return task
|
|
36
35
|
return None
|
|
37
36
|
|
|
38
37
|
def cancel(self, label: str) -> None:
|
|
@@ -49,9 +48,6 @@ class QolsysTaskManager:
|
|
|
49
48
|
if self._tasks:
|
|
50
49
|
await asyncio.gather(*self._tasks, return_exceptions=True)
|
|
51
50
|
|
|
52
|
-
def pending(self) -> None:
|
|
53
|
-
return {t for t in self._tasks if not t.done()}
|
|
54
|
-
|
|
55
51
|
def dump(self) -> None:
|
|
56
52
|
for task in self._tasks:
|
|
57
53
|
LOGGER.debug("Task: %s, Done: %s, Cancelled: %s", task.get_name(), task.done(), task.cancelled())
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
LOGGER = logging.getLogger(__name__)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class QolsysUser:
|
|
7
|
+
def __init__(self) -> None:
|
|
8
|
+
self._id: int = 0
|
|
9
|
+
self._user_code = ""
|
|
10
|
+
|
|
11
|
+
@property
|
|
12
|
+
def id(self) -> int:
|
|
13
|
+
return self._id
|
|
14
|
+
|
|
15
|
+
@id.setter
|
|
16
|
+
def id(self, value: int) -> None:
|
|
17
|
+
self._id = value
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def user_code(self) -> str:
|
|
21
|
+
return self._user_code
|
|
22
|
+
|
|
23
|
+
@user_code.setter
|
|
24
|
+
def user_code(self, value: str) -> None:
|
|
25
|
+
self._user_code = value
|
qolsys_controller/utils_mqtt.py
CHANGED
|
@@ -1,24 +1,16 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import random
|
|
3
|
-
import re
|
|
4
3
|
|
|
5
4
|
LOGGER = logging.getLogger(__name__)
|
|
6
5
|
|
|
7
6
|
|
|
8
|
-
def
|
|
9
|
-
def replace_escape(match):
|
|
10
|
-
hex_value = match.group(1)
|
|
11
|
-
decimal_value = int(hex_value, 16)
|
|
12
|
-
return f"\\u{decimal_value:04x}"
|
|
13
|
-
|
|
14
|
-
return re.sub(r"\\x([0-9a-fA-F]{2})", replace_escape, json_string)
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def generate_random_mac() -> str:
|
|
7
|
+
def generate_random_mac() -> str: # noqa: D103
|
|
18
8
|
mac = [
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
random.randint(0x00,
|
|
9
|
+
0xF2,
|
|
10
|
+
0x16,
|
|
11
|
+
0x3E,
|
|
12
|
+
random.randint(0x00, 0x7F),
|
|
13
|
+
random.randint(0x00, 0xFF),
|
|
14
|
+
random.randint(0x00, 0xFF),
|
|
23
15
|
]
|
|
24
|
-
return ":".join(map(lambda x: "%02x" % x, mac))
|
|
16
|
+
return ":".join(map(lambda x: "%02x" % x, mac)) # noqa: C417, UP031
|