qolsys-controller 0.0.76__tar.gz → 0.0.81__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/PKG-INFO +1 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/pyproject.toml +1 -1
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/controller.py +91 -7
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_thermostat.py +1 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_zwave_node.py +2 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/enum.py +1 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/enum_zwave.py +22 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/mqtt_command.py +6 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/panel.py +9 -9
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/state.py +45 -21
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_device.py +79 -7
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_dimmer.py +1 -1
- qolsys_controller-0.0.81/qolsys_controller/zwave_energy_clamp.py +15 -0
- qolsys_controller-0.0.81/qolsys_controller/zwave_service_meter.py +192 -0
- qolsys_controller-0.0.81/qolsys_controller/zwave_service_multilevelsensor.py +119 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_thermostat.py +8 -14
- qolsys_controller-0.0.76/qolsys_controller/zwave_meter.py +0 -272
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/.github/workflows/build.yml +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/.github/workflows/publish.yml +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/.gitignore +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/Info_mqtt.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/LICENSE +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/README.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/bin/qolsys.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/example.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/info_pairing.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/info_qolsys.md +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/mypy.ini +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/__init__.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/adc_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/adc_service.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/adc_service_garagedoor.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/db.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_alarmedsensor.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_automation.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_country_locale.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_dashboard_msgs.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_dimmerlight.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_doorlock.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_eu_event.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_heat_map.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_history.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_iqremotesettings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_iqrouter_network_config.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_iqrouter_user_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_master_slave.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_nest_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_output_rules.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_partition.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_pgm_outputs.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_powerg_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_qolsyssettings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_scene.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_sensor.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_sensor_group.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_shades.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_smartsocket.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_state.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_tcc.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_trouble_conditions.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_user.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_virtual_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_weather.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_zigbee_device.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_zwave_association_group.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_zwave_history.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/database/table_zwave_other.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/enum_adc.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/errors.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/mdns.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/mqtt_command_queue.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/observable.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/partition.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/pki.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/scene.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/settings.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/task_manager.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/users.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/utils_mqtt.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/weather.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zone.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_garagedoor.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_generic.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_lock.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_outlet.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/qolsys_controller/zwave_thermometer.py +0 -0
- {qolsys_controller-0.0.76 → qolsys_controller-0.0.81}/requirements.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: qolsys-controller
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.81
|
|
4
4
|
Summary: A Python module that emulates a virtual IQ Remote device, enabling full local control of a Qolsys IQ Panel
|
|
5
5
|
Project-URL: Homepage, https://github.com/EHylands/QolsysController
|
|
6
6
|
Project-URL: Issues, https://github.com/EHylands/QolsysController/issues
|
|
@@ -18,6 +18,7 @@ from qolsys_controller.mqtt_command import (
|
|
|
18
18
|
MQTTCommand_Panel,
|
|
19
19
|
MQTTCommand_ZWave,
|
|
20
20
|
)
|
|
21
|
+
from qolsys_controller.zwave_thermostat import QolsysThermostat
|
|
21
22
|
|
|
22
23
|
from .enum import PartitionAlarmState, PartitionArmingType, PartitionSystemStatus
|
|
23
24
|
from .enum_zwave import ThermostatFanMode, ThermostatMode, ZwaveCommandClass, ZwaveDeviceClass
|
|
@@ -894,20 +895,103 @@ class QolsysController:
|
|
|
894
895
|
return response
|
|
895
896
|
|
|
896
897
|
async def command_zwave_thermostat_setpoint_set(
|
|
897
|
-
self, node_id: str, mode: ThermostatMode, setpoint:
|
|
898
|
+
self, node_id: str, mode: ThermostatMode, setpoint: int
|
|
898
899
|
) -> dict[str, Any] | None:
|
|
899
|
-
LOGGER.debug(
|
|
900
|
-
"MQTT: Sending zwave_thermostat_setpoint_set - Node(%s) - Mode(%s) - Setpoint(%s)", node_id, mode, setpoint
|
|
901
|
-
)
|
|
902
|
-
|
|
903
900
|
zwave_node = self.state.zwave_device(node_id)
|
|
904
901
|
if not zwave_node:
|
|
905
902
|
LOGGER.error("thermostat_setpoint_set - Invalid node_id %s", node_id)
|
|
906
903
|
return None
|
|
907
904
|
|
|
908
|
-
|
|
905
|
+
if not isinstance(zwave_node, QolsysThermostat):
|
|
906
|
+
LOGGER.error("thermostat_setpoint_set - Z-Wane node is not a thermostat %s", node_id)
|
|
907
|
+
return None
|
|
908
|
+
|
|
909
|
+
scale: int = 0
|
|
910
|
+
if zwave_node.thermostat_device_temp_unit == "F":
|
|
911
|
+
scale = 1
|
|
912
|
+
|
|
913
|
+
precision: int = 1
|
|
914
|
+
size: int = 2
|
|
915
|
+
pss = (precision << 5) | (scale << 3) | size
|
|
916
|
+
temp_int = int(round(setpoint * (10**precision)))
|
|
917
|
+
temp_bytes = temp_int.to_bytes(size, byteorder="big", signed=True)
|
|
918
|
+
|
|
919
|
+
zwave_bytes: list[int] = [
|
|
920
|
+
0x43, # Thermostat Setpoint
|
|
921
|
+
0x03, # SET
|
|
922
|
+
mode.value, # Heating
|
|
923
|
+
pss,
|
|
924
|
+
] + list(temp_bytes)
|
|
925
|
+
|
|
926
|
+
zwave_bytes2: list[int] = [
|
|
927
|
+
0x43, # Thermostat Setpoint
|
|
928
|
+
0x01, # SET
|
|
929
|
+
mode.value, # Heating
|
|
930
|
+
pss,
|
|
931
|
+
] + list(temp_bytes)
|
|
932
|
+
|
|
933
|
+
zwave_bytes3: list[int] = [
|
|
934
|
+
0x43, # Thermostat Setpoint
|
|
935
|
+
0x01, # SET
|
|
936
|
+
0x03, # Furnace
|
|
937
|
+
pss,
|
|
938
|
+
] + list(temp_bytes)
|
|
939
|
+
|
|
940
|
+
zwave_bytes4: list[int] = [
|
|
941
|
+
0x43, # Thermostat Setpoint
|
|
942
|
+
0x03, # SET
|
|
943
|
+
0x03, # Furnace
|
|
944
|
+
pss,
|
|
945
|
+
] + list(temp_bytes)
|
|
946
|
+
|
|
947
|
+
LOGGER.debug(
|
|
948
|
+
"MQTT: Sending zwave_thermostat_setpoint_set 0x03 - Node(%s) - Mode(%s) - Setpoint(%s): %s",
|
|
949
|
+
node_id,
|
|
950
|
+
mode,
|
|
951
|
+
setpoint,
|
|
952
|
+
zwave_bytes,
|
|
953
|
+
)
|
|
954
|
+
command = MQTTCommand_ZWave(self, node_id, zwave_bytes)
|
|
909
955
|
response = await command.send_command()
|
|
910
|
-
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command")
|
|
956
|
+
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command:%s", response)
|
|
957
|
+
|
|
958
|
+
await asyncio.sleep(3)
|
|
959
|
+
|
|
960
|
+
LOGGER.debug(
|
|
961
|
+
"MQTT: Sending zwave_thermostat_setpoint_set 0x01 - Node(%s) - Mode(%s) - Setpoint(%s): %s",
|
|
962
|
+
node_id,
|
|
963
|
+
mode,
|
|
964
|
+
setpoint,
|
|
965
|
+
zwave_bytes2,
|
|
966
|
+
)
|
|
967
|
+
command2 = MQTTCommand_ZWave(self, node_id, zwave_bytes2)
|
|
968
|
+
response2 = await command2.send_command()
|
|
969
|
+
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command:%s", response2)
|
|
970
|
+
|
|
971
|
+
await asyncio.sleep(3)
|
|
972
|
+
|
|
973
|
+
LOGGER.debug(
|
|
974
|
+
"MQTT: Sending zwave_thermostat_setpoint_set 0x01 - Node(%s) - Mode(0x03) - Setpoint(%s): %s",
|
|
975
|
+
node_id,
|
|
976
|
+
setpoint,
|
|
977
|
+
zwave_bytes3,
|
|
978
|
+
)
|
|
979
|
+
command2 = MQTTCommand_ZWave(self, node_id, zwave_bytes2)
|
|
980
|
+
response2 = await command2.send_command()
|
|
981
|
+
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command:%s", response2)
|
|
982
|
+
|
|
983
|
+
await asyncio.sleep(3)
|
|
984
|
+
|
|
985
|
+
LOGGER.debug(
|
|
986
|
+
"MQTT: Sending zwave_thermostat_setpoint_set 0x03 - Node(%s) - Mode(0x3) - Setpoint(%s): %s",
|
|
987
|
+
node_id,
|
|
988
|
+
setpoint,
|
|
989
|
+
zwave_bytes4,
|
|
990
|
+
)
|
|
991
|
+
command2 = MQTTCommand_ZWave(self, node_id, zwave_bytes2)
|
|
992
|
+
response2 = await command2.send_command()
|
|
993
|
+
LOGGER.debug("MQTT: Receiving zwave_thermostat_mode_set command:%s", response2)
|
|
994
|
+
|
|
911
995
|
return response
|
|
912
996
|
|
|
913
997
|
async def command_zwave_thermostat_mode_set(self, node_id: str, mode: ThermostatMode) -> dict[str, Any] | None:
|
|
@@ -18,6 +18,28 @@ class MeterRateType(IntEnum):
|
|
|
18
18
|
RESERVED = 0x03
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
class ZWaveMultilevelSensorScale(Enum):
|
|
22
|
+
TEMPERATURE_CELSIUS = "temperature_celsius"
|
|
23
|
+
TEMPERATURE_FAHRENHEIT = "temperature_fahrenheit"
|
|
24
|
+
RELATIVE_HUMIDITY = "relative_humidity"
|
|
25
|
+
WIND_DIRECTION = "wind_direction"
|
|
26
|
+
BAROMETRIC_PRESSURE = "barometric_pressure"
|
|
27
|
+
DEW_POINT = "dew_point"
|
|
28
|
+
RAIN_RATE = "rain_rate"
|
|
29
|
+
TIDE_LEVEL = "tide_level"
|
|
30
|
+
WEIGHT = "weight"
|
|
31
|
+
VOLTS = "volts"
|
|
32
|
+
AMPS = "amps"
|
|
33
|
+
WATTS = "watts"
|
|
34
|
+
DISTANCE = "distance"
|
|
35
|
+
ANGLE_POSITION = "angle_position"
|
|
36
|
+
ROTATION = "rotation"
|
|
37
|
+
WATER_TEMPERATURE_CELSIUS = "water_temperature_celsius"
|
|
38
|
+
WATER_TEMPERATURE_FAHRENHEIT = "water_temperature_fahrenheit"
|
|
39
|
+
LUMINOSITY_LUX = "luminosity_lux"
|
|
40
|
+
UNKNOWN = "unknown"
|
|
41
|
+
|
|
42
|
+
|
|
21
43
|
class ZWaveUnknownMeterScale(IntEnum):
|
|
22
44
|
UNKNOWN = 0
|
|
23
45
|
|
|
@@ -91,26 +91,32 @@ class MQTTCommand_ZWave(MQTTCommand_IpcCall):
|
|
|
91
91
|
|
|
92
92
|
ipc_request: list[dict[str, Any]] = [
|
|
93
93
|
{
|
|
94
|
+
# Node ID
|
|
94
95
|
"dataType": "int",
|
|
95
96
|
"dataValue": int(node_id),
|
|
96
97
|
},
|
|
97
98
|
{
|
|
99
|
+
# End Point
|
|
98
100
|
"dataType": "int",
|
|
99
101
|
"dataValue": 0,
|
|
100
102
|
},
|
|
101
103
|
{
|
|
104
|
+
# Z-Wave Payload
|
|
102
105
|
"dataType": "byteArray",
|
|
103
106
|
"dataValue": zwave_command,
|
|
104
107
|
},
|
|
105
108
|
{
|
|
109
|
+
# Transmit option ?
|
|
106
110
|
"dataType": "int",
|
|
107
111
|
"dataValue": 0,
|
|
108
112
|
},
|
|
109
113
|
{
|
|
114
|
+
# Priority
|
|
110
115
|
"dataType": "int",
|
|
111
116
|
"dataValue": 106,
|
|
112
117
|
},
|
|
113
118
|
{
|
|
119
|
+
# Callback ?
|
|
114
120
|
"dataType": "byteArray",
|
|
115
121
|
"dataValue": [0],
|
|
116
122
|
},
|
|
@@ -6,7 +6,7 @@ import logging
|
|
|
6
6
|
from typing import TYPE_CHECKING, Any
|
|
7
7
|
|
|
8
8
|
from qolsys_controller.adc_device import QolsysAdcDevice
|
|
9
|
-
from qolsys_controller.
|
|
9
|
+
from qolsys_controller.zwave_energy_clamp import QolsysEnergyClamp
|
|
10
10
|
from qolsys_controller.zwave_thermometer import QolsysThermometer
|
|
11
11
|
|
|
12
12
|
from .database.db import QolsysDB
|
|
@@ -427,12 +427,12 @@ class QolsysPanel(QolsysObservable):
|
|
|
427
427
|
def parse_zwave_message(self, data: dict[str, Any]) -> None:
|
|
428
428
|
zwave = data.get("ZWAVE_RESPONSE", "")
|
|
429
429
|
payload = base64.b64decode(zwave.get("ZWAVE_PAYLOAD", "")).hex()
|
|
430
|
-
LOGGER.debug(
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
)
|
|
430
|
+
# LOGGER.debug(
|
|
431
|
+
# "Z-Wave Response: Node(%s) - Status(%s) - Payload(%s)",
|
|
432
|
+
# zwave.get("NODE_ID", ""),
|
|
433
|
+
# zwave.get("ZWAVE_COMMAND_STATUS", ""),
|
|
434
|
+
# payload,
|
|
435
|
+
# )
|
|
436
436
|
|
|
437
437
|
node_id: str = str(zwave.get("NODE_ID", 0))
|
|
438
438
|
node = self._controller.state.zwave_device(node_id)
|
|
@@ -900,8 +900,8 @@ class QolsysPanel(QolsysObservable):
|
|
|
900
900
|
|
|
901
901
|
# Check if z-wave device is an Energy Clamp
|
|
902
902
|
if device.get("node_type", "") == "Energy Clamp":
|
|
903
|
-
|
|
904
|
-
qolsys_meter_device
|
|
903
|
+
LOGGER.debug(device)
|
|
904
|
+
qolsys_meter_device = QolsysEnergyClamp(device)
|
|
905
905
|
devices.append(qolsys_meter_device)
|
|
906
906
|
device_added = True
|
|
907
907
|
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
-
from enum import IntEnum
|
|
5
4
|
from typing import TYPE_CHECKING
|
|
6
5
|
|
|
7
6
|
from qolsys_controller.adc_service import QolsysAdcService
|
|
8
7
|
from qolsys_controller.adc_service_garagedoor import QolsysAdcGarageDoorService
|
|
9
|
-
from qolsys_controller.
|
|
8
|
+
from qolsys_controller.zwave_energy_clamp import QolsysEnergyClamp
|
|
10
9
|
from qolsys_controller.zwave_thermometer import QolsysThermometer
|
|
11
10
|
|
|
12
11
|
from .adc_device import QolsysAdcDevice
|
|
@@ -96,10 +95,10 @@ class QolsysState(QolsysObservable):
|
|
|
96
95
|
return thermostats
|
|
97
96
|
|
|
98
97
|
@property
|
|
99
|
-
def zwave_meters(self) -> list[
|
|
98
|
+
def zwave_meters(self) -> list[QolsysEnergyClamp]:
|
|
100
99
|
meters = []
|
|
101
100
|
for device in self.zwave_devices:
|
|
102
|
-
if isinstance(device,
|
|
101
|
+
if isinstance(device, QolsysEnergyClamp):
|
|
103
102
|
meters.append(device)
|
|
104
103
|
return meters
|
|
105
104
|
|
|
@@ -351,10 +350,9 @@ class QolsysState(QolsysObservable):
|
|
|
351
350
|
state_zwave.update_lock(db_zwave.to_dict_lock())
|
|
352
351
|
break
|
|
353
352
|
|
|
354
|
-
# Update
|
|
355
|
-
if isinstance(state_zwave,
|
|
356
|
-
|
|
357
|
-
# Keep old value instact
|
|
353
|
+
# Update Energy Clamp
|
|
354
|
+
if isinstance(state_zwave, QolsysEnergyClamp) and isinstance(db_zwave, QolsysEnergyClamp):
|
|
355
|
+
state_zwave.update_base(db_zwave.to_dict_base())
|
|
358
356
|
break
|
|
359
357
|
|
|
360
358
|
# Generic Z-Wave Device
|
|
@@ -473,6 +471,29 @@ class QolsysState(QolsysObservable):
|
|
|
473
471
|
def dump(self) -> None: # noqa: PLR0912, PLR0915
|
|
474
472
|
LOGGER.debug("*** Device Information ***")
|
|
475
473
|
|
|
474
|
+
def dump_meter(self: QolsysState, device: QolsysZWaveDevice) -> None:
|
|
475
|
+
for endpoint in device.meter_endpoints:
|
|
476
|
+
for meter_sensor in endpoint.sensors:
|
|
477
|
+
LOGGER.debug(
|
|
478
|
+
" Meter%s Endpoint%s - %s - value: %.2f (%s)",
|
|
479
|
+
device.node_id,
|
|
480
|
+
endpoint.endpoint,
|
|
481
|
+
endpoint._meter_type.name,
|
|
482
|
+
meter_sensor.value,
|
|
483
|
+
meter_sensor.scale.name,
|
|
484
|
+
)
|
|
485
|
+
|
|
486
|
+
def dump_multilevelsensor(self: QolsysState, device: QolsysZWaveDevice) -> None:
|
|
487
|
+
for endpoint in device.multilevelsensor_endpoints:
|
|
488
|
+
for sensor in endpoint.sensors:
|
|
489
|
+
LOGGER.debug(
|
|
490
|
+
" Multilevelsensor%s Endpoint%s - value: %.2f (%s)",
|
|
491
|
+
device.node_id,
|
|
492
|
+
endpoint.endpoint,
|
|
493
|
+
sensor.value,
|
|
494
|
+
sensor.unit.name,
|
|
495
|
+
)
|
|
496
|
+
|
|
476
497
|
for partition in self.partitions:
|
|
477
498
|
pid = partition.id
|
|
478
499
|
name = partition.name
|
|
@@ -513,6 +534,8 @@ class QolsysState(QolsysObservable):
|
|
|
513
534
|
LOGGER.debug("Dimmer%s (%s) - node_status: %s", nid, name, zwave.node_status)
|
|
514
535
|
LOGGER.debug("Dimmer%s (%s) - battery_level: %s", nid, name, zwave.node_battery_level)
|
|
515
536
|
LOGGER.debug("Dimmer%s (%s) - battery_level_value: %s", nid, name, zwave.node_battery_level_value)
|
|
537
|
+
dump_meter(self, zwave)
|
|
538
|
+
dump_multilevelsensor(self, zwave)
|
|
516
539
|
continue
|
|
517
540
|
|
|
518
541
|
if isinstance(zwave, QolsysThermostat):
|
|
@@ -525,34 +548,33 @@ class QolsysState(QolsysObservable):
|
|
|
525
548
|
LOGGER.debug("Thermostat%s (%s) - target_cool_temp: %s", zid, name, zwave.thermostat_target_cool_temp)
|
|
526
549
|
LOGGER.debug("Thermostat%s (%s) - target_heat_temp: %s", zid, name, zwave.thermostat_target_heat_temp)
|
|
527
550
|
LOGGER.debug("Thermostat%s (%s) - set_point_mode: %s", zid, name, zwave.thermostat_set_point_mode)
|
|
551
|
+
dump_meter(self, zwave)
|
|
552
|
+
dump_multilevelsensor(self, zwave)
|
|
528
553
|
continue
|
|
529
554
|
|
|
530
555
|
if isinstance(zwave, QolsysLock):
|
|
531
556
|
zid = zwave.lock_node_id
|
|
532
557
|
name = zwave.lock_name
|
|
533
558
|
LOGGER.debug("Lock%s (%s) - lock_status: %s", zid, name, zwave.lock_status)
|
|
559
|
+
dump_meter(self, zwave)
|
|
560
|
+
dump_multilevelsensor(self, zwave)
|
|
534
561
|
continue
|
|
535
562
|
|
|
536
|
-
if isinstance(zwave,
|
|
563
|
+
if isinstance(zwave, QolsysEnergyClamp):
|
|
537
564
|
nid = zwave.node_id
|
|
538
565
|
name = zwave.node_name
|
|
539
|
-
LOGGER.debug("
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
LOGGER.debug(
|
|
545
|
-
" Sensor%s (%s) - value: %s (%s)",
|
|
546
|
-
meter_sensor.meter_type,
|
|
547
|
-
meter_sensor.meter_type.name,
|
|
548
|
-
meter_sensor.value,
|
|
549
|
-
scale_type(meter_sensor.scale).name,
|
|
550
|
-
)
|
|
566
|
+
LOGGER.debug("EnergyClamp%s (%s)", nid, name)
|
|
567
|
+
dump_meter(self, zwave)
|
|
568
|
+
dump_multilevelsensor(self, zwave)
|
|
569
|
+
continue
|
|
551
570
|
|
|
552
571
|
if isinstance(zwave, QolsysThermometer):
|
|
553
572
|
nid = zwave.node_id
|
|
554
573
|
name = zwave.node_name
|
|
555
574
|
LOGGER.debug("Thermometer%s (%s)", nid, name)
|
|
575
|
+
dump_meter(self, zwave)
|
|
576
|
+
dump_multilevelsensor(self, zwave)
|
|
577
|
+
continue
|
|
556
578
|
|
|
557
579
|
if isinstance(zwave, QolsysGeneric):
|
|
558
580
|
zid = zwave.node_id
|
|
@@ -561,6 +583,8 @@ class QolsysState(QolsysObservable):
|
|
|
561
583
|
LOGGER.debug("Generic%s (%s) - status: %s", zid, name, zwave.node_status)
|
|
562
584
|
LOGGER.debug("Generic%s (%s) - battery_level: %s", zid, name, zwave.node_battery_level)
|
|
563
585
|
LOGGER.debug("Generic%s (%s) - battery_level_vale: %s", zid, name, zwave.node_battery_level_value)
|
|
586
|
+
dump_meter(self, zwave)
|
|
587
|
+
dump_multilevelsensor(self, zwave)
|
|
564
588
|
continue
|
|
565
589
|
|
|
566
590
|
LOGGER.debug("Other Z-Wave devices information")
|
|
@@ -1,5 +1,9 @@
|
|
|
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 QolsysZwaveServiceMultilevelSensor
|
|
6
|
+
|
|
3
7
|
from .enum_zwave import ZwaveDeviceClass
|
|
4
8
|
from .observable import QolsysObservable
|
|
5
9
|
|
|
@@ -35,8 +39,14 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
35
39
|
self._is_device_hidden: str = zwave_dict.get("is_device_hidden", "")
|
|
36
40
|
self._last_updated_date: str = zwave_dict.get("last_updated_date", "")
|
|
37
41
|
self._command_class_list: str = zwave_dict.get("command_class_list", "")
|
|
38
|
-
self.
|
|
39
|
-
self.
|
|
42
|
+
self._meter_capabilities: str = ""
|
|
43
|
+
self._multisensor_capabilities: str = ""
|
|
44
|
+
|
|
45
|
+
# Set Meter and MutilevelSensor Services if available
|
|
46
|
+
self._meter_endpoints: list[QolsysZwaveServiceMeter] = []
|
|
47
|
+
self._multilevelsensor_endpoints: list[QolsysZwaveServiceMultilevelSensor] = []
|
|
48
|
+
self.meter_capabilities = zwave_dict.get("meter_capabilities", "")
|
|
49
|
+
self.multisensor_capabilities = zwave_dict.get("multisensor_capabilities", "")
|
|
40
50
|
|
|
41
51
|
def update_raw(self, payload: bytes) -> None:
|
|
42
52
|
LOGGER.debug("Raw Update (node%s) - payload: %s", self.node_id, payload.hex())
|
|
@@ -106,7 +116,7 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
106
116
|
if "multisensor_capabilities" in data:
|
|
107
117
|
self.multisensor_capabilities = data.get("multisensor_capabilities", "")
|
|
108
118
|
if "meter_capabilities" in data:
|
|
109
|
-
self.
|
|
119
|
+
self.meter_capabilities = data.get("meter_capabilities", "")
|
|
110
120
|
|
|
111
121
|
self.end_batch_update()
|
|
112
122
|
|
|
@@ -151,9 +161,30 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
151
161
|
@meter_capabilities.setter
|
|
152
162
|
def meter_capabilities(self, value: str) -> None:
|
|
153
163
|
if self._meter_capabilities != value:
|
|
154
|
-
LOGGER.debug("ZWave%s (%s) - meter_capabilities: %s", self.node_id, self.node_name, value)
|
|
164
|
+
# LOGGER.debug("ZWave%s (%s) - meter_capabilities: %s", self.node_id, self.node_name, value)
|
|
155
165
|
self._meter_capabilities = value
|
|
156
|
-
|
|
166
|
+
|
|
167
|
+
# Update Meter Service
|
|
168
|
+
try:
|
|
169
|
+
meter_services = json.loads(value)
|
|
170
|
+
for endpoint, service in meter_services.items():
|
|
171
|
+
# Check if we already have this meter service
|
|
172
|
+
meter_endpoint = None
|
|
173
|
+
for meter in self._meter_endpoints:
|
|
174
|
+
if meter.endpoint == endpoint:
|
|
175
|
+
meter_endpoint = meter
|
|
176
|
+
meter_endpoint.update_iq2medi(service)
|
|
177
|
+
break
|
|
178
|
+
|
|
179
|
+
# Create new meter service if not found
|
|
180
|
+
if meter_endpoint is None:
|
|
181
|
+
LOGGER.debug("ZWave%s (%s) - Adding new meter endpoint: %s", self.node_id, self.node_name, endpoint)
|
|
182
|
+
meter_endpoint = QolsysZwaveServiceMeter(self, endpoint, service)
|
|
183
|
+
self._meter_endpoints.append(meter_endpoint)
|
|
184
|
+
|
|
185
|
+
except json.JSONDecodeError:
|
|
186
|
+
LOGGER.error("ZWave%s (%s) - Error parsing meter_capabilities:%s", self.node_id, self.node_name, value)
|
|
187
|
+
return
|
|
157
188
|
|
|
158
189
|
@property
|
|
159
190
|
def multisensor_capabilities(self) -> str:
|
|
@@ -162,9 +193,36 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
162
193
|
@multisensor_capabilities.setter
|
|
163
194
|
def multisensor_capabilities(self, value: str) -> None:
|
|
164
195
|
if self._multisensor_capabilities != value:
|
|
165
|
-
LOGGER.debug("ZWave%s (%s) - multisensor_capabilities: %s", self.node_id, self.node_name, value)
|
|
196
|
+
# LOGGER.debug("ZWave%s (%s) - multisensor_capabilities: %s", self.node_id, self.node_name, value)
|
|
166
197
|
self._multisensor_capabilities = value
|
|
167
|
-
|
|
198
|
+
|
|
199
|
+
# Update Multilevel Sensor Service
|
|
200
|
+
try:
|
|
201
|
+
sensor_services = json.loads(value)
|
|
202
|
+
for endpoint, service in sensor_services.items():
|
|
203
|
+
# Check if we already have this meter service
|
|
204
|
+
sensor_endpoint = None
|
|
205
|
+
for sensor in self._multilevelsensor_endpoints:
|
|
206
|
+
if sensor.endpoint == endpoint:
|
|
207
|
+
sensor_endpoint = sensor
|
|
208
|
+
sensor_endpoint.update_iq2medi(service)
|
|
209
|
+
break
|
|
210
|
+
|
|
211
|
+
# Create new meter service if not found
|
|
212
|
+
if sensor_endpoint is None:
|
|
213
|
+
LOGGER.debug(
|
|
214
|
+
"ZWave%s (%s) - Adding new multilevelsensor endpoint: %s", self.node_id, self.node_name, endpoint
|
|
215
|
+
)
|
|
216
|
+
LOGGER.debug("create sensor service")
|
|
217
|
+
sensor_endpoint = QolsysZwaveServiceMultilevelSensor(self, endpoint, service)
|
|
218
|
+
self.multilevelsensor_endpoints.append(sensor_endpoint)
|
|
219
|
+
LOGGER.debug(sensor_endpoint.sensors)
|
|
220
|
+
|
|
221
|
+
except json.JSONDecodeError:
|
|
222
|
+
LOGGER.error(
|
|
223
|
+
"ZWave%s (%s) - Error parsing multilevelsensor_capabilities:%s", self.node_id, self.node_name, value
|
|
224
|
+
)
|
|
225
|
+
return
|
|
168
226
|
|
|
169
227
|
@property
|
|
170
228
|
def node_battery_level_value(self) -> int | None:
|
|
@@ -229,6 +287,14 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
229
287
|
self._partition_id = value
|
|
230
288
|
self.notify()
|
|
231
289
|
|
|
290
|
+
@property
|
|
291
|
+
def meter_endpoints(self) -> list[QolsysZwaveServiceMeter]:
|
|
292
|
+
return self._meter_endpoints
|
|
293
|
+
|
|
294
|
+
@property
|
|
295
|
+
def multilevelsensor_endpoints(self) -> list[QolsysZwaveServiceMultilevelSensor]:
|
|
296
|
+
return self._multilevelsensor_endpoints
|
|
297
|
+
|
|
232
298
|
@property
|
|
233
299
|
def generic_device_type(self) -> ZwaveDeviceClass:
|
|
234
300
|
try:
|
|
@@ -239,6 +305,12 @@ class QolsysZWaveDevice(QolsysObservable):
|
|
|
239
305
|
def is_battery_enabled(self) -> bool:
|
|
240
306
|
return self.node_battery_level_value is not None
|
|
241
307
|
|
|
308
|
+
def is_service_meter_enabled(self) -> bool:
|
|
309
|
+
return self._meter_endpoints != []
|
|
310
|
+
|
|
311
|
+
def is_service_multilevelsensor_enabled(self) -> bool:
|
|
312
|
+
return self._multilevelsensor_endpoints != []
|
|
313
|
+
|
|
242
314
|
def to_dict_base(self) -> dict[str, str]:
|
|
243
315
|
return {
|
|
244
316
|
"_id": self._id,
|
|
@@ -70,7 +70,7 @@ class QolsysDimmer(QolsysZWaveDevice):
|
|
|
70
70
|
self.notify()
|
|
71
71
|
|
|
72
72
|
def update_raw(self, payload: bytes) -> None:
|
|
73
|
-
|
|
73
|
+
pass
|
|
74
74
|
|
|
75
75
|
def update_dimmer(self, content_values: dict[str, str]) -> None: # noqa: PLR0912
|
|
76
76
|
# Check if we are updating same none_id
|
|
@@ -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
|