qolsys-controller 0.0.44__py3-none-any.whl → 0.0.87__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/adc_device.py +202 -0
- qolsys_controller/adc_service.py +139 -0
- qolsys_controller/adc_service_garagedoor.py +35 -0
- qolsys_controller/controller.py +1040 -20
- qolsys_controller/database/db.py +108 -29
- qolsys_controller/database/table.py +90 -60
- qolsys_controller/database/table_alarmedsensor.py +2 -2
- qolsys_controller/database/table_automation.py +0 -1
- qolsys_controller/database/table_country_locale.py +0 -1
- qolsys_controller/database/table_dashboard_msgs.py +1 -2
- qolsys_controller/database/table_dimmerlight.py +0 -1
- qolsys_controller/database/table_doorlock.py +0 -1
- qolsys_controller/database/table_eu_event.py +1 -2
- qolsys_controller/database/table_heat_map.py +0 -2
- qolsys_controller/database/table_history.py +4 -1
- qolsys_controller/database/table_iqremotesettings.py +0 -2
- qolsys_controller/database/table_iqrouter_network_config.py +0 -1
- qolsys_controller/database/table_iqrouter_user_device.py +0 -2
- qolsys_controller/database/table_master_slave.py +0 -1
- qolsys_controller/database/table_nest_device.py +0 -1
- qolsys_controller/database/table_output_rules.py +0 -1
- qolsys_controller/database/table_partition.py +0 -1
- qolsys_controller/database/table_pgm_outputs.py +0 -2
- qolsys_controller/database/table_powerg_device.py +0 -2
- qolsys_controller/database/table_qolsyssettings.py +0 -2
- qolsys_controller/database/table_scene.py +0 -2
- qolsys_controller/database/table_sensor.py +2 -2
- qolsys_controller/database/table_sensor_group.py +23 -0
- qolsys_controller/database/table_shades.py +0 -2
- qolsys_controller/database/table_smartsocket.py +12 -3
- qolsys_controller/database/table_state.py +0 -1
- qolsys_controller/database/table_tcc.py +0 -1
- qolsys_controller/database/table_thermostat.py +3 -1
- qolsys_controller/database/table_trouble_conditions.py +0 -2
- qolsys_controller/database/table_user.py +0 -2
- qolsys_controller/database/table_virtual_device.py +13 -3
- 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 +3 -1
- qolsys_controller/database/table_zwave_other.py +0 -1
- qolsys_controller/enum.py +42 -13
- qolsys_controller/enum_adc.py +28 -0
- qolsys_controller/enum_zwave.py +210 -36
- qolsys_controller/errors.py +14 -12
- qolsys_controller/mdns.py +7 -4
- qolsys_controller/mqtt_command.py +125 -0
- qolsys_controller/mqtt_command_queue.py +5 -4
- qolsys_controller/observable.py +2 -2
- qolsys_controller/panel.py +304 -156
- qolsys_controller/partition.py +149 -127
- qolsys_controller/pki.py +69 -97
- qolsys_controller/scene.py +30 -28
- qolsys_controller/settings.py +96 -50
- qolsys_controller/state.py +221 -34
- qolsys_controller/task_manager.py +11 -14
- qolsys_controller/users.py +25 -0
- qolsys_controller/utils_mqtt.py +8 -16
- qolsys_controller/weather.py +71 -0
- qolsys_controller/zone.py +243 -214
- qolsys_controller/zwave_device.py +234 -93
- qolsys_controller/zwave_dimmer.py +55 -49
- qolsys_controller/zwave_energy_clamp.py +15 -0
- qolsys_controller/zwave_garagedoor.py +3 -1
- qolsys_controller/zwave_generic.py +5 -3
- qolsys_controller/zwave_lock.py +51 -44
- qolsys_controller/zwave_outlet.py +3 -1
- qolsys_controller/zwave_service_meter.py +192 -0
- qolsys_controller/zwave_service_multilevelsensor.py +119 -0
- qolsys_controller/zwave_thermometer.py +21 -0
- qolsys_controller/zwave_thermostat.py +249 -143
- qolsys_controller-0.0.87.dist-info/METADATA +89 -0
- qolsys_controller-0.0.87.dist-info/RECORD +77 -0
- {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/WHEEL +1 -1
- qolsys_controller/plugin.py +0 -34
- qolsys_controller/plugin_c4.py +0 -17
- qolsys_controller/plugin_remote.py +0 -1298
- qolsys_controller-0.0.44.dist-info/METADATA +0 -93
- qolsys_controller-0.0.44.dist-info/RECORD +0 -68
- {qolsys_controller-0.0.44.dist-info → qolsys_controller-0.0.87.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,147 +1,158 @@
|
|
|
1
|
+
import json
|
|
1
2
|
import logging
|
|
2
3
|
|
|
4
|
+
from qolsys_controller.zwave_service_meter import QolsysZwaveServiceMeter
|
|
5
|
+
from qolsys_controller.zwave_service_multilevelsensor import QolsysZwaveMultilevelSensor, QolsysZwaveServiceMultilevelSensor
|
|
6
|
+
|
|
7
|
+
from .enum_zwave import ZwaveDeviceClass, ZWaveMultilevelSensorScale
|
|
3
8
|
from .observable import QolsysObservable
|
|
4
9
|
|
|
5
10
|
LOGGER = logging.getLogger(__name__)
|
|
6
11
|
|
|
7
12
|
|
|
8
13
|
class QolsysZWaveDevice(QolsysObservable):
|
|
9
|
-
|
|
10
|
-
def __init__(self, zwave_dict: dict) -> None:
|
|
14
|
+
def __init__(self, zwave_dict: dict[str, str]) -> None:
|
|
11
15
|
super().__init__()
|
|
12
16
|
|
|
13
|
-
self._id = zwave_dict.get("_id")
|
|
14
|
-
self._node_id = zwave_dict.get("node_id", "")
|
|
15
|
-
self._node_name = zwave_dict.get("node_name", "")
|
|
16
|
-
self._node_type = zwave_dict.get("node_type", "")
|
|
17
|
-
self._node_status = zwave_dict.get("node_status", "")
|
|
18
|
-
self._partition_id = zwave_dict.get("partition_id", "")
|
|
19
|
-
self._node_secure_cmd_cls = zwave_dict.get("node_secure_cmd_cls", "")
|
|
20
|
-
self._node_battery_level = zwave_dict.get("node_battery_level", "")
|
|
21
|
-
self._node_battery_level_value = zwave_dict.get("node_battery_level_value", "")
|
|
22
|
-
self._is_node_listening_node = zwave_dict.get("is_node_listening_node", "")
|
|
23
|
-
self._basic_report_value = zwave_dict.get("basic_report_value", "")
|
|
24
|
-
self._switch_multilevel_report_value = zwave_dict.get("switch_multilevel_report_value", "")
|
|
25
|
-
self._basic_device_type = zwave_dict.get("basic_device_type", "")
|
|
26
|
-
self._generic_device_type = zwave_dict.get("generic_device_type", "")
|
|
27
|
-
self._specific_device_type = zwave_dict.get("specific_device_type", "")
|
|
28
|
-
self._num_secure_command_class = zwave_dict.get("num_secure_command_class", "")
|
|
29
|
-
self._secure_command_class = zwave_dict.get("secure_command_class", "")
|
|
30
|
-
self._manufacture_id = zwave_dict.get("manufacture_id", "")
|
|
31
|
-
self._product_type = zwave_dict.get("product_type", "")
|
|
32
|
-
self._device_protocol = zwave_dict.get("device_protocol", "")
|
|
33
|
-
self._paired_status = zwave_dict.get("paired_status", "")
|
|
34
|
-
self._is_device_sleeping = zwave_dict.get("is_device_sleeping", "")
|
|
35
|
-
self._is_device_hidden = zwave_dict.get("is_device_hidden", "")
|
|
36
|
-
self._last_updated_date = zwave_dict.get("last_updated_date", "")
|
|
37
|
-
self._command_class_list = zwave_dict.get("command_class_list", "")
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def paired_status(self) -> str:
|
|
45
|
-
return self._paired_status
|
|
46
|
-
|
|
47
|
-
@property
|
|
48
|
-
def node_battery_level(self) -> str:
|
|
49
|
-
return self._node_battery_level
|
|
17
|
+
self._id: str = zwave_dict.get("_id", "")
|
|
18
|
+
self._node_id: str = zwave_dict.get("node_id", "")
|
|
19
|
+
self._node_name: str = zwave_dict.get("node_name", "")
|
|
20
|
+
self._node_type: str = zwave_dict.get("node_type", "")
|
|
21
|
+
self._node_status: str = zwave_dict.get("node_status", "")
|
|
22
|
+
self._partition_id: str = zwave_dict.get("partition_id", "")
|
|
23
|
+
self._node_secure_cmd_cls: str = zwave_dict.get("node_secure_cmd_cls", "")
|
|
24
|
+
self._node_battery_level: str = zwave_dict.get("node_battery_level", "")
|
|
25
|
+
self._node_battery_level_value: str = zwave_dict.get("node_battery_level_value", "")
|
|
26
|
+
self._is_node_listening_node: str = zwave_dict.get("is_node_listening_node", "")
|
|
27
|
+
self._basic_report_value: str = zwave_dict.get("basic_report_value", "")
|
|
28
|
+
self._switch_multilevel_report_value: str = zwave_dict.get("switch_multilevel_report_value", "")
|
|
29
|
+
self._basic_device_type: str = zwave_dict.get("basic_device_type", "")
|
|
30
|
+
self._generic_device_type: str = zwave_dict.get("generic_device_type", "")
|
|
31
|
+
self._specific_device_type: str = zwave_dict.get("specific_device_type", "")
|
|
32
|
+
self._num_secure_command_class: str = zwave_dict.get("num_secure_command_class", "")
|
|
33
|
+
self._secure_command_class: str = zwave_dict.get("secure_command_class", "")
|
|
34
|
+
self._manufacture_id: str = zwave_dict.get("manufacture_id", "")
|
|
35
|
+
self._product_type: str = zwave_dict.get("product_type", "")
|
|
36
|
+
self._device_protocol: str = zwave_dict.get("device_protocol", "")
|
|
37
|
+
self._paired_status: str = zwave_dict.get("paired_status", "")
|
|
38
|
+
self._is_device_sleeping: str = zwave_dict.get("is_device_sleeping", "")
|
|
39
|
+
self._is_device_hidden: str = zwave_dict.get("is_device_hidden", "")
|
|
40
|
+
self._last_updated_date: str = zwave_dict.get("last_updated_date", "")
|
|
41
|
+
self._command_class_list: str = zwave_dict.get("command_class_list", "")
|
|
42
|
+
self._meter_capabilities: str = ""
|
|
43
|
+
self._multisensor_capabilities: str = ""
|
|
44
|
+
self._notification_capabilities = zwave_dict.get("notification_capabilities", "")
|
|
45
|
+
self._multi_channel_details = zwave_dict.get("multi_channel_details", "")
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
47
|
+
# Set Meter and MutilevelSensor Services if available
|
|
48
|
+
self._meter_endpoints: list[QolsysZwaveServiceMeter] = []
|
|
49
|
+
self._multilevelsensor_endpoints: list[QolsysZwaveServiceMultilevelSensor] = []
|
|
50
|
+
self.meter_capabilities = zwave_dict.get("meter_capabilities", "")
|
|
51
|
+
self.multisensor_capabilities = zwave_dict.get("multisensor_capabilities", "")
|
|
54
52
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return self._node_status
|
|
58
|
-
|
|
59
|
-
@property
|
|
60
|
-
def node_name(self) -> str:
|
|
61
|
-
return self._node_name
|
|
62
|
-
|
|
63
|
-
@property
|
|
64
|
-
def node_type(self) -> str:
|
|
65
|
-
return self._node_type
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def partition_id(self) -> str:
|
|
69
|
-
return self._partition_id
|
|
70
|
-
|
|
71
|
-
def update_base(self, data: dict) -> None: # noqa: C901, PLR0912, PLR0915
|
|
53
|
+
def update_raw(self, payload: bytes) -> None:
|
|
54
|
+
LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
|
|
72
55
|
|
|
56
|
+
def update_base(self, data: dict[str, str]) -> None: # noqa: C901, PLR0912, PLR0915
|
|
73
57
|
# Check if we are updating same node_id
|
|
74
58
|
node_id_update = data.get("node_id", "")
|
|
75
59
|
if node_id_update != self._node_id:
|
|
76
60
|
LOGGER.error(
|
|
77
|
-
"Updating ZWave%s (%s) with ZWave%s (different node_id)",
|
|
61
|
+
"Updating ZWave%s (%s) with ZWave%s (different node_id)",
|
|
62
|
+
self.node_id,
|
|
63
|
+
self.node_name,
|
|
64
|
+
node_id_update,
|
|
78
65
|
)
|
|
79
66
|
return
|
|
80
67
|
|
|
81
68
|
self.start_batch_update()
|
|
82
69
|
|
|
83
70
|
if "paired_status" in data:
|
|
84
|
-
self.paired_status = data.get("paired_status")
|
|
71
|
+
self.paired_status = data.get("paired_status", "")
|
|
85
72
|
if "node_battery_level" in data:
|
|
86
|
-
self.node_battery_level = data.get("node_battery_level")
|
|
73
|
+
self.node_battery_level = data.get("node_battery_level", "")
|
|
87
74
|
if "node_battery_level_value" in data:
|
|
88
|
-
self.node_battery_level_value = data.get("node_battery_level_value")
|
|
75
|
+
self.node_battery_level_value = data.get("node_battery_level_value", "")
|
|
89
76
|
if "node_status" in data:
|
|
90
|
-
self.node_status = data.get("node_status")
|
|
77
|
+
self.node_status = data.get("node_status", "")
|
|
91
78
|
if "node_name" in data:
|
|
92
|
-
self.node_name = data.get("node_name")
|
|
79
|
+
self.node_name = data.get("node_name", "")
|
|
93
80
|
if "node_type" in data:
|
|
94
|
-
self.node_type = data.get("node_type")
|
|
81
|
+
self.node_type = data.get("node_type", "")
|
|
95
82
|
if "partition_id" in data:
|
|
96
|
-
self.partition_id = data.get("partition_id")
|
|
83
|
+
self.partition_id = data.get("partition_id", "")
|
|
97
84
|
if "node_secure_cmd_cls" in data:
|
|
98
|
-
self._node_secure_cmd_cls = data.get("node_secure_cmd_cls")
|
|
85
|
+
self._node_secure_cmd_cls = data.get("node_secure_cmd_cls", "")
|
|
99
86
|
if "is_node_listening_node" in data:
|
|
100
|
-
self._is_node_listening_node = data.get("is_node_listening_node")
|
|
87
|
+
self._is_node_listening_node = data.get("is_node_listening_node", "")
|
|
101
88
|
if "basic_report_value" in data:
|
|
102
|
-
self._basic_report_value = data.get("basic_report_value")
|
|
89
|
+
self._basic_report_value = data.get("basic_report_value", "")
|
|
103
90
|
if "switch_multilevel_report_value" in data:
|
|
104
|
-
self._switch_multilevel_report_value = data.get("switch_multilevel_report_value")
|
|
91
|
+
self._switch_multilevel_report_value = data.get("switch_multilevel_report_value", "")
|
|
105
92
|
if "basic_device_type" in data:
|
|
106
|
-
self._basic_device_type = data.get("basic_device_type")
|
|
93
|
+
self._basic_device_type = data.get("basic_device_type", "")
|
|
107
94
|
if "generic_device_type" in data:
|
|
108
|
-
self._generic_device_type = data.get("generic_device_type")
|
|
95
|
+
self._generic_device_type = data.get("generic_device_type", "")
|
|
109
96
|
if "specific_device_type" in data:
|
|
110
|
-
self._specific_device_type = data.get("specific_device_type")
|
|
97
|
+
self._specific_device_type = data.get("specific_device_type", "")
|
|
111
98
|
if "num_secure_command_class" in data:
|
|
112
|
-
self._num_secure_command_class = data.get("num_secure_command_class")
|
|
99
|
+
self._num_secure_command_class = data.get("num_secure_command_class", "")
|
|
113
100
|
if "secure_command_class" in data:
|
|
114
|
-
self._secure_command_class = data.get("secure_command_class")
|
|
101
|
+
self._secure_command_class = data.get("secure_command_class", "")
|
|
115
102
|
if "manufacture_id" in data:
|
|
116
|
-
self._manufacture_id = data.get("manufacture_id")
|
|
103
|
+
self._manufacture_id = data.get("manufacture_id", "")
|
|
117
104
|
if "product_type" in data:
|
|
118
|
-
self._product_type = data.get("product_type")
|
|
105
|
+
self._product_type = data.get("product_type", "")
|
|
119
106
|
if "device_protocol" in data:
|
|
120
|
-
self._device_protocol = data.get("device_protocol")
|
|
107
|
+
self._device_protocol = data.get("device_protocol", "")
|
|
121
108
|
if "paired_status" in data:
|
|
122
|
-
self.paired_status = data.get("paired_status")
|
|
109
|
+
self.paired_status = data.get("paired_status", "")
|
|
123
110
|
if "is_device_sleeping" in data:
|
|
124
|
-
self._is_device_sleeping = data.get("is_device_sleeping")
|
|
111
|
+
self._is_device_sleeping = data.get("is_device_sleeping", "")
|
|
125
112
|
if "is_device_hidden" in data:
|
|
126
|
-
self._is_device_hidden = data.get("is_device_hidden")
|
|
113
|
+
self._is_device_hidden = data.get("is_device_hidden", "")
|
|
127
114
|
if "last_updated_date" in data:
|
|
128
|
-
self._last_updated_date = data.get("last_updated_date")
|
|
115
|
+
self._last_updated_date = data.get("last_updated_date", "")
|
|
129
116
|
if "command_class_list" in data:
|
|
130
|
-
self._last_updated_date = data.get("command_class_list")
|
|
117
|
+
self._last_updated_date = data.get("command_class_list", "")
|
|
118
|
+
if "multisensor_capabilities" in data:
|
|
119
|
+
self.multisensor_capabilities = data.get("multisensor_capabilities", "")
|
|
120
|
+
if "meter_capabilities" in data:
|
|
121
|
+
self.meter_capabilities = data.get("meter_capabilities", "")
|
|
122
|
+
if "notification_capabilities" in data:
|
|
123
|
+
self._notification_capabilities = data.get("notification_capabilities", "")
|
|
124
|
+
if "multi_channel_details" in data:
|
|
125
|
+
self._multi_channel_details = data.get("multi_channel_details", "")
|
|
131
126
|
|
|
132
127
|
self.end_batch_update()
|
|
133
128
|
|
|
129
|
+
# -----------------------------
|
|
130
|
+
# properties + setters
|
|
131
|
+
# -----------------------------
|
|
132
|
+
|
|
133
|
+
@property
|
|
134
|
+
def node_id(self) -> str:
|
|
135
|
+
return self._node_id
|
|
136
|
+
|
|
134
137
|
@node_id.setter
|
|
135
|
-
def node_id(self, value: str) ->
|
|
138
|
+
def node_id(self, value: str) -> None:
|
|
136
139
|
self._node_id = value
|
|
137
140
|
|
|
141
|
+
@property
|
|
142
|
+
def paired_status(self) -> str:
|
|
143
|
+
return self._paired_status
|
|
144
|
+
|
|
138
145
|
@paired_status.setter
|
|
139
|
-
def paired_status(self, value: str) ->
|
|
146
|
+
def paired_status(self, value: str) -> None:
|
|
140
147
|
if self._paired_status != value:
|
|
141
148
|
LOGGER.debug("ZWave%s (%s) - paired_status: %s", self.node_id, self.node_name, value)
|
|
142
149
|
self._paired_status = value
|
|
143
150
|
self.notify()
|
|
144
151
|
|
|
152
|
+
@property
|
|
153
|
+
def node_battery_level(self) -> str:
|
|
154
|
+
return self._node_battery_level
|
|
155
|
+
|
|
145
156
|
@node_battery_level.setter
|
|
146
157
|
def node_battery_level(self, value: str) -> None:
|
|
147
158
|
if self._node_battery_level != value:
|
|
@@ -149,42 +160,168 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
149
160
|
self._node_battery_level = value
|
|
150
161
|
self.notify()
|
|
151
162
|
|
|
163
|
+
@property
|
|
164
|
+
def meter_capabilities(self) -> str:
|
|
165
|
+
return self._meter_capabilities
|
|
166
|
+
|
|
167
|
+
@meter_capabilities.setter
|
|
168
|
+
def meter_capabilities(self, value: str) -> None:
|
|
169
|
+
if self._meter_capabilities != value:
|
|
170
|
+
self._meter_capabilities = value
|
|
171
|
+
|
|
172
|
+
# Update Meter Service
|
|
173
|
+
try:
|
|
174
|
+
meter_services = json.loads(value)
|
|
175
|
+
for endpoint, service in meter_services.items():
|
|
176
|
+
# Check if we already have this meter service
|
|
177
|
+
meter_endpoint = None
|
|
178
|
+
for meter in self._meter_endpoints:
|
|
179
|
+
if meter.endpoint == endpoint:
|
|
180
|
+
meter_endpoint = meter
|
|
181
|
+
meter_endpoint.update_iq2medi(service)
|
|
182
|
+
break
|
|
183
|
+
|
|
184
|
+
# Create new meter service if not found
|
|
185
|
+
if meter_endpoint is None:
|
|
186
|
+
LOGGER.debug("ZWave%s (%s) - Adding new meter endpoint: %s", self.node_id, self.node_name, endpoint)
|
|
187
|
+
meter_endpoint = QolsysZwaveServiceMeter(self, endpoint, service)
|
|
188
|
+
self._meter_endpoints.append(meter_endpoint)
|
|
189
|
+
|
|
190
|
+
except json.JSONDecodeError:
|
|
191
|
+
LOGGER.error("ZWave%s (%s) - Error parsing meter_capabilities:%s", self.node_id, self.node_name, value)
|
|
192
|
+
return
|
|
193
|
+
|
|
194
|
+
@property
|
|
195
|
+
def multisensor_capabilities(self) -> str:
|
|
196
|
+
return self._multisensor_capabilities
|
|
197
|
+
|
|
198
|
+
@multisensor_capabilities.setter
|
|
199
|
+
def multisensor_capabilities(self, value: str) -> None:
|
|
200
|
+
if self._multisensor_capabilities != value:
|
|
201
|
+
self._multisensor_capabilities = value
|
|
202
|
+
|
|
203
|
+
# Update Multilevel Sensor Service
|
|
204
|
+
try:
|
|
205
|
+
sensor_services = json.loads(value)
|
|
206
|
+
for endpoint, service in sensor_services.items():
|
|
207
|
+
# Check if we already have this meter service
|
|
208
|
+
sensor_endpoint = None
|
|
209
|
+
for sensor in self._multilevelsensor_endpoints:
|
|
210
|
+
if sensor.endpoint == endpoint:
|
|
211
|
+
sensor_endpoint = sensor
|
|
212
|
+
sensor_endpoint.update_iq2medi(service)
|
|
213
|
+
break
|
|
214
|
+
|
|
215
|
+
# Create new meter service if not found
|
|
216
|
+
if sensor_endpoint is None:
|
|
217
|
+
LOGGER.debug(
|
|
218
|
+
"ZWave%s (%s) - Adding new multilevelsensor endpoint: %s", self.node_id, self.node_name, endpoint
|
|
219
|
+
)
|
|
220
|
+
sensor_endpoint = QolsysZwaveServiceMultilevelSensor(self, endpoint, service)
|
|
221
|
+
self.multilevelsensor_endpoints.append(sensor_endpoint)
|
|
222
|
+
|
|
223
|
+
except json.JSONDecodeError:
|
|
224
|
+
LOGGER.error(
|
|
225
|
+
"ZWave%s (%s) - Error parsing multilevelsensor_capabilities:%s", self.node_id, self.node_name, value
|
|
226
|
+
)
|
|
227
|
+
return
|
|
228
|
+
|
|
229
|
+
@property
|
|
230
|
+
def node_battery_level_value(self) -> int | None:
|
|
231
|
+
try:
|
|
232
|
+
value = int(self._node_battery_level_value)
|
|
233
|
+
if value >= 0 and value <= 100:
|
|
234
|
+
return value
|
|
235
|
+
else:
|
|
236
|
+
return None
|
|
237
|
+
|
|
238
|
+
except ValueError:
|
|
239
|
+
return None
|
|
240
|
+
|
|
152
241
|
@node_battery_level_value.setter
|
|
153
|
-
def node_battery_level_value(self, value: str) ->
|
|
242
|
+
def node_battery_level_value(self, value: str) -> None:
|
|
154
243
|
if self._node_battery_level_value != value:
|
|
155
244
|
LOGGER.debug("ZWave%s (%s) - node_battery_level_value: %s", self.node_id, self.node_name, value)
|
|
156
245
|
self._node_battery_level_value = value
|
|
157
246
|
self.notify()
|
|
158
247
|
|
|
248
|
+
@property
|
|
249
|
+
def node_status(self) -> str:
|
|
250
|
+
return self._node_status
|
|
251
|
+
|
|
159
252
|
@node_status.setter
|
|
160
|
-
def node_status(self, value: str) ->
|
|
253
|
+
def node_status(self, value: str) -> None:
|
|
161
254
|
if self._node_status != value:
|
|
162
255
|
LOGGER.debug("ZWave%s (%s) - node_status: %s", self.node_id, self.node_name, value)
|
|
163
256
|
self._node_status = value
|
|
164
257
|
self.notify()
|
|
165
258
|
|
|
259
|
+
@property
|
|
260
|
+
def node_name(self) -> str:
|
|
261
|
+
return self._node_name
|
|
262
|
+
|
|
166
263
|
@node_name.setter
|
|
167
|
-
def node_name(self, value: str) ->
|
|
264
|
+
def node_name(self, value: str) -> None:
|
|
168
265
|
if self._node_name != value:
|
|
169
266
|
LOGGER.debug("ZWave%s (%s) - node_name: %s", self.node_id, self.node_name, value)
|
|
170
267
|
self._node_name = value
|
|
171
268
|
self.notify()
|
|
172
269
|
|
|
270
|
+
@property
|
|
271
|
+
def node_type(self) -> str:
|
|
272
|
+
return self._node_type
|
|
273
|
+
|
|
173
274
|
@node_type.setter
|
|
174
|
-
def node_type(self, value: str) ->
|
|
275
|
+
def node_type(self, value: str) -> None:
|
|
175
276
|
if self._node_type != value:
|
|
176
277
|
LOGGER.debug("ZWave%s (%s) - node_type: %s", self.node_id, self.node_name, value)
|
|
177
278
|
self._node_type = value
|
|
178
279
|
self.notify()
|
|
179
280
|
|
|
281
|
+
@property
|
|
282
|
+
def partition_id(self) -> str:
|
|
283
|
+
return self._partition_id
|
|
284
|
+
|
|
180
285
|
@partition_id.setter
|
|
181
|
-
def partition_id(self, value: str) ->
|
|
286
|
+
def partition_id(self, value: str) -> None:
|
|
182
287
|
if self._partition_id != value:
|
|
183
288
|
LOGGER.debug("ZWave%s (%s) - partition_id: %s", self._node_id, self._node_name, value)
|
|
184
289
|
self._partition_id = value
|
|
185
290
|
self.notify()
|
|
186
291
|
|
|
187
|
-
|
|
292
|
+
@property
|
|
293
|
+
def meter_endpoints(self) -> list[QolsysZwaveServiceMeter]:
|
|
294
|
+
return self._meter_endpoints
|
|
295
|
+
|
|
296
|
+
@property
|
|
297
|
+
def multilevelsensor_endpoints(self) -> list[QolsysZwaveServiceMultilevelSensor]:
|
|
298
|
+
return self._multilevelsensor_endpoints
|
|
299
|
+
|
|
300
|
+
@property
|
|
301
|
+
def generic_device_type(self) -> ZwaveDeviceClass:
|
|
302
|
+
try:
|
|
303
|
+
return ZwaveDeviceClass(int(self._generic_device_type))
|
|
304
|
+
except ValueError:
|
|
305
|
+
return ZwaveDeviceClass.Unknown
|
|
306
|
+
|
|
307
|
+
def is_battery_enabled(self) -> bool:
|
|
308
|
+
return self.node_battery_level_value is not None
|
|
309
|
+
|
|
310
|
+
def is_service_meter_enabled(self) -> bool:
|
|
311
|
+
return self._meter_endpoints != []
|
|
312
|
+
|
|
313
|
+
def is_service_multilevelsensor_enabled(self) -> bool:
|
|
314
|
+
return self._multilevelsensor_endpoints != []
|
|
315
|
+
|
|
316
|
+
def multilevelsensor_value(self, scale: ZWaveMultilevelSensorScale) -> list[QolsysZwaveMultilevelSensor]:
|
|
317
|
+
result: list[QolsysZwaveMultilevelSensor] = []
|
|
318
|
+
for endpoint in self.multilevelsensor_endpoints:
|
|
319
|
+
sensor = endpoint.get_sensor(scale)
|
|
320
|
+
if sensor is not None:
|
|
321
|
+
result.append(sensor)
|
|
322
|
+
return result
|
|
323
|
+
|
|
324
|
+
def to_dict_base(self) -> dict[str, str]:
|
|
188
325
|
return {
|
|
189
326
|
"_id": self._id,
|
|
190
327
|
"node_id": self.node_id,
|
|
@@ -193,7 +330,7 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
193
330
|
"node_status": self.node_status,
|
|
194
331
|
"partition_id": self._partition_id,
|
|
195
332
|
"node_battery_level": self.node_battery_level,
|
|
196
|
-
"node_battery_level_value": self.
|
|
333
|
+
"node_battery_level_value": self._node_battery_level_value,
|
|
197
334
|
"paired_status": self.paired_status,
|
|
198
335
|
"node_secure_cmd_cls": self._node_secure_cmd_cls,
|
|
199
336
|
"is_node_listening_node": self._is_node_listening_node,
|
|
@@ -211,4 +348,8 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
211
348
|
"is_device_hidden": self._is_device_hidden,
|
|
212
349
|
"last_updated_date": self._last_updated_date,
|
|
213
350
|
"command_class_list": self._command_class_list,
|
|
351
|
+
"multisensor_capabilities": self.multisensor_capabilities,
|
|
352
|
+
"meter_capabilities": self.meter_capabilities,
|
|
353
|
+
"notification_capabilities": self._notification_capabilities,
|
|
354
|
+
"multi_channel_details": self._multi_channel_details,
|
|
214
355
|
}
|
|
@@ -6,26 +6,31 @@ LOGGER = logging.getLogger(__name__)
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class QolsysDimmer(QolsysZWaveDevice):
|
|
9
|
+
def __init__(self, dimmer_dict: dict[str, str], zwave_dict: dict[str, str]) -> None:
|
|
10
|
+
super().__init__(zwave_dict)
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
self._dimmer_id: str = dimmer_dict.get("_id", "")
|
|
13
|
+
self._dimmer_version: str = dimmer_dict.get("version", "")
|
|
14
|
+
self._dimmer_opr: str = dimmer_dict.get("opr", "")
|
|
15
|
+
self._dimmer_partition_id: str = dimmer_dict.get("partition_id", "")
|
|
16
|
+
self._dimmer_name: str = dimmer_dict.get("dimmer_name", "")
|
|
17
|
+
self._dimmer_status: str = dimmer_dict.get("status", "")
|
|
18
|
+
self._dimmer_level: str = dimmer_dict.get("level", "")
|
|
19
|
+
self._dimmer_node_id: str = dimmer_dict.get("node_id", "")
|
|
20
|
+
self._dimmer_created_by: str = dimmer_dict.get("created_by", "")
|
|
21
|
+
self._dimmer_created_date: str = dimmer_dict.get("created_date", "")
|
|
22
|
+
self._dimmer_updated_by: str = dimmer_dict.get("updated_by", "")
|
|
23
|
+
self._dimmer_last_updated_date: str = dimmer_dict.get("last_updated_date", "")
|
|
24
|
+
self._dimmer_endpoint: str = dimmer_dict.get("endpoint", "")
|
|
25
|
+
self._dimmer_power_details: str = dimmer_dict.get("power_details", "")
|
|
26
|
+
self._dimmer_paired_status: str = dimmer_dict.get("paired_status", "")
|
|
11
27
|
|
|
12
|
-
|
|
28
|
+
def is_on(self) -> bool:
|
|
29
|
+
return self.dimmer_status == "On"
|
|
13
30
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
self._dimmer_partition_id = dimmer_dict.get("partition_id", "")
|
|
18
|
-
self._dimmer_name = dimmer_dict.get("dimmer_name", "")
|
|
19
|
-
self._dimmer_status = dimmer_dict.get("status", "")
|
|
20
|
-
self._dimmer_level = dimmer_dict.get("level", "")
|
|
21
|
-
self._dimmer_node_id = dimmer_dict.get("node_id", "")
|
|
22
|
-
self._dimmer_created_by = dimmer_dict.get("created_by", "")
|
|
23
|
-
self._dimmer_created_date = dimmer_dict.get("created_date", "")
|
|
24
|
-
self._dimmer_updated_by = dimmer_dict.get("updated_by", "")
|
|
25
|
-
self._dimmer_last_updated_date = dimmer_dict.get("last_updated_date", "")
|
|
26
|
-
self._dimmer_endpoint = dimmer_dict.get("endpoint", "")
|
|
27
|
-
self._dimmer_power_details = dimmer_dict.get("power_details", "")
|
|
28
|
-
self._dimmer_paired_status = dimmer_dict.get("paired_status", "")
|
|
31
|
+
# -----------------------------
|
|
32
|
+
# properties + setters
|
|
33
|
+
# -----------------------------
|
|
29
34
|
|
|
30
35
|
@property
|
|
31
36
|
def dimmer_node_id(self) -> str:
|
|
@@ -35,10 +40,24 @@ class QolsysDimmer(QolsysZWaveDevice):
|
|
|
35
40
|
def dimmer_status(self) -> str:
|
|
36
41
|
return self._dimmer_status
|
|
37
42
|
|
|
43
|
+
@dimmer_status.setter
|
|
44
|
+
def dimmer_status(self, value: str) -> None:
|
|
45
|
+
if self._dimmer_status != value:
|
|
46
|
+
LOGGER.debug("Dimmer%s (%s) - status: %s", self.node_id, self.dimmer_name, value)
|
|
47
|
+
self._dimmer_status = value
|
|
48
|
+
self.notify()
|
|
49
|
+
|
|
38
50
|
@property
|
|
39
51
|
def dimmer_name(self) -> str:
|
|
40
52
|
return self._dimmer_name
|
|
41
53
|
|
|
54
|
+
@dimmer_name.setter
|
|
55
|
+
def dimmer_name(self, value: str) -> None:
|
|
56
|
+
if self._dimmer_name != value:
|
|
57
|
+
LOGGER.debug("Dimmer%s (%s) - name: %s", self.node_id, self.dimmer_name, value)
|
|
58
|
+
self._dimmer_name = value
|
|
59
|
+
self.notify()
|
|
60
|
+
|
|
42
61
|
@property
|
|
43
62
|
def dimmer_level(self) -> str:
|
|
44
63
|
return self._dimmer_level
|
|
@@ -50,63 +69,50 @@ class QolsysDimmer(QolsysZWaveDevice):
|
|
|
50
69
|
self._dimmer_level = value
|
|
51
70
|
self.notify()
|
|
52
71
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if self._dimmer_status != value:
|
|
56
|
-
LOGGER.debug("Dimmer%s (%s) - status: %s", self.node_id, self.dimmer_name, value)
|
|
57
|
-
self._dimmer_status = value
|
|
58
|
-
self.notify()
|
|
59
|
-
|
|
60
|
-
@dimmer_name.setter
|
|
61
|
-
def dimmer_name(self, value: str) -> None:
|
|
62
|
-
if self._dimmer_name != value:
|
|
63
|
-
LOGGER.debug("Dimmer%s (%s) - name: %s", self.node_id, self.dimmer_name, value)
|
|
64
|
-
self._dimmer_name = value
|
|
65
|
-
self.notify()
|
|
66
|
-
|
|
67
|
-
def is_on(self) -> bool:
|
|
68
|
-
return self.dimmer_status == "On"
|
|
72
|
+
def update_raw(self, payload: bytes) -> None:
|
|
73
|
+
pass
|
|
69
74
|
|
|
70
|
-
def update_dimmer(self, content_values: dict) -> None: # noqa:
|
|
75
|
+
def update_dimmer(self, content_values: dict[str, str]) -> None: # noqa: PLR0912
|
|
71
76
|
# Check if we are updating same none_id
|
|
72
77
|
node_id_update = content_values.get("node_id", "")
|
|
73
78
|
if node_id_update != self._dimmer_node_id:
|
|
74
79
|
LOGGER.error(
|
|
75
|
-
"Updating Dimmer %s (%s) with dimmer %s (different id)", self._node_id, self.dimmer_name, node_id_update
|
|
80
|
+
"Updating Dimmer %s (%s) with dimmer %s (different id)", self._node_id, self.dimmer_name, node_id_update
|
|
81
|
+
)
|
|
76
82
|
return
|
|
77
83
|
|
|
78
84
|
self.start_batch_update()
|
|
79
85
|
|
|
80
86
|
if "status" in content_values:
|
|
81
|
-
self.dimmer_status = content_values.get("status")
|
|
87
|
+
self.dimmer_status = content_values.get("status", "")
|
|
82
88
|
if "level" in content_values:
|
|
83
|
-
self.dimmer_level = content_values.get("level")
|
|
89
|
+
self.dimmer_level = content_values.get("level", "")
|
|
84
90
|
if "dimmer_name" in content_values:
|
|
85
|
-
self.dimmer_name = content_values.get("dimmer_name")
|
|
91
|
+
self.dimmer_name = content_values.get("dimmer_name", "")
|
|
86
92
|
if "created_by" in content_values:
|
|
87
|
-
self._dimmer_created_by = content_values.get("created_by")
|
|
93
|
+
self._dimmer_created_by = content_values.get("created_by", "")
|
|
88
94
|
if "created_date" in content_values:
|
|
89
|
-
self._dimmer_created_date = content_values.get("created_date")
|
|
95
|
+
self._dimmer_created_date = content_values.get("created_date", "")
|
|
90
96
|
if "version" in content_values:
|
|
91
|
-
self._dimmer_version = content_values.get("version")
|
|
97
|
+
self._dimmer_version = content_values.get("version", "")
|
|
92
98
|
if "opr" in content_values:
|
|
93
|
-
self._dimmer_opr = content_values.get("opr")
|
|
99
|
+
self._dimmer_opr = content_values.get("opr", "")
|
|
94
100
|
if "partition_id" in content_values:
|
|
95
|
-
self.partition_id = content_values.get("partition_id")
|
|
101
|
+
self.partition_id = content_values.get("partition_id", "")
|
|
96
102
|
if "updated_by" in content_values:
|
|
97
|
-
self._dimmer_updated_by = content_values.get("updated_by")
|
|
103
|
+
self._dimmer_updated_by = content_values.get("updated_by", "")
|
|
98
104
|
if "last_updated_date" in content_values:
|
|
99
|
-
self._last_updated_date = content_values.get("last_updated_date")
|
|
105
|
+
self._last_updated_date = content_values.get("last_updated_date", "")
|
|
100
106
|
if "endpoint" in content_values:
|
|
101
|
-
self._dimmer_endpoint = content_values.get("endpoint")
|
|
107
|
+
self._dimmer_endpoint = content_values.get("endpoint", "")
|
|
102
108
|
if "power_details" in content_values:
|
|
103
|
-
self._dimmer_power_details = content_values.get("power_details")
|
|
109
|
+
self._dimmer_power_details = content_values.get("power_details", "")
|
|
104
110
|
if "paired_status" in content_values:
|
|
105
|
-
self._dimmer_paired_status = content_values.get("paired_status")
|
|
111
|
+
self._dimmer_paired_status = content_values.get("paired_status", "")
|
|
106
112
|
|
|
107
113
|
self.end_batch_update()
|
|
108
114
|
|
|
109
|
-
def to_dict_dimmer(self) -> dict:
|
|
115
|
+
def to_dict_dimmer(self) -> dict[str, str]:
|
|
110
116
|
return {
|
|
111
117
|
"_id": self._dimmer_id,
|
|
112
118
|
"version": self._dimmer_version,
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
from .zwave_device import QolsysZWaveDevice
|
|
4
|
+
|
|
5
|
+
LOGGER = logging.getLogger(__name__)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class QolsysEnergyClamp(QolsysZWaveDevice):
|
|
9
|
+
def __init__(self, zwave_dict: dict[str, str]) -> None:
|
|
10
|
+
super().__init__(zwave_dict)
|
|
11
|
+
|
|
12
|
+
# Energy clamp only enables meter seter in base zwave_device class
|
|
13
|
+
|
|
14
|
+
def update_raw(self, payload: bytes) -> None:
|
|
15
|
+
pass
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from .zwave_device import QolsysZWaveDevice
|
|
4
4
|
|
|
5
5
|
LOGGER = logging.getLogger(__name__)
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
class QolsysGeneric(QolsysZWaveDevice):
|
|
9
|
-
|
|
10
|
-
def __init__(self, zwave_dict: dict) -> None:
|
|
9
|
+
def __init__(self, zwave_dict: dict[str, str]) -> None:
|
|
11
10
|
super().__init__(zwave_dict)
|
|
11
|
+
|
|
12
|
+
def update_raw(self, payload: bytes) -> None:
|
|
13
|
+
LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
|