plugwise 1.5.1a3__py3-none-any.whl → 1.6.0__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.
- plugwise/__init__.py +10 -10
- plugwise/common.py +68 -60
- plugwise/constants.py +47 -34
- plugwise/data.py +95 -67
- plugwise/helper.py +199 -168
- plugwise/legacy/data.py +23 -23
- plugwise/legacy/helper.py +57 -58
- plugwise/legacy/smile.py +18 -16
- plugwise/smile.py +24 -21
- plugwise/util.py +7 -9
- {plugwise-1.5.1a3.dist-info → plugwise-1.6.0.dist-info}/METADATA +1 -1
- plugwise-1.6.0.dist-info/RECORD +17 -0
- {plugwise-1.5.1a3.dist-info → plugwise-1.6.0.dist-info}/WHEEL +1 -1
- plugwise-1.5.1a3.dist-info/RECORD +0 -17
- {plugwise-1.5.1a3.dist-info → plugwise-1.6.0.dist-info}/LICENSE +0 -0
- {plugwise-1.5.1a3.dist-info → plugwise-1.6.0.dist-info}/top_level.txt +0 -0
plugwise/data.py
CHANGED
@@ -13,9 +13,8 @@ from plugwise.constants import (
|
|
13
13
|
MIN_SETPOINT,
|
14
14
|
NONE,
|
15
15
|
OFF,
|
16
|
-
ZONE_THERMOSTATS,
|
17
16
|
ActuatorData,
|
18
|
-
|
17
|
+
GwEntityData,
|
19
18
|
)
|
20
19
|
from plugwise.helper import SmileHelper
|
21
20
|
from plugwise.util import remove_empty_platform_dicts
|
@@ -29,12 +28,16 @@ class SmileData(SmileHelper):
|
|
29
28
|
SmileHelper.__init__(self)
|
30
29
|
|
31
30
|
|
32
|
-
def
|
33
|
-
"""Helper-function for
|
31
|
+
def _all_entity_data(self) -> None:
|
32
|
+
"""Helper-function for get_all_gateway_entities().
|
34
33
|
|
35
|
-
Collect data for each
|
34
|
+
Collect data for each entity and add to self.gw_data and self.gw_entities.
|
36
35
|
"""
|
37
|
-
self.
|
36
|
+
self._update_gw_entities()
|
37
|
+
if self.smile(ADAM):
|
38
|
+
self._update_zones()
|
39
|
+
self.gw_entities.update(self._zones)
|
40
|
+
|
38
41
|
self.gw_data.update(
|
39
42
|
{
|
40
43
|
"gateway_id": self.gateway_id,
|
@@ -49,31 +52,40 @@ class SmileData(SmileHelper):
|
|
49
52
|
{"heater_id": self._heater_id, "cooling_present": self._cooling_present}
|
50
53
|
)
|
51
54
|
|
52
|
-
def
|
53
|
-
"""Helper-function for
|
55
|
+
def _update_zones(self) -> None:
|
56
|
+
"""Helper-function for _all_entity_data() and async_update().
|
57
|
+
|
58
|
+
Collect data for each zone/location and add to self._zones.
|
59
|
+
"""
|
60
|
+
for location_id, zone in self._zones.items():
|
61
|
+
data = self._get_location_data(location_id)
|
62
|
+
zone.update(data)
|
63
|
+
|
64
|
+
def _update_gw_entities(self) -> None:
|
65
|
+
"""Helper-function for _all_entities_data() and async_update().
|
54
66
|
|
55
|
-
Collect data for each
|
67
|
+
Collect data for each entity and add to self.gw_entities.
|
56
68
|
"""
|
57
69
|
mac_list: list[str] = []
|
58
|
-
for
|
59
|
-
data = self.
|
60
|
-
if
|
70
|
+
for entity_id, entity in self.gw_entities.items():
|
71
|
+
data = self._get_entity_data(entity_id)
|
72
|
+
if entity_id == self.gateway_id:
|
61
73
|
mac_list = self._detect_low_batteries()
|
62
|
-
self._add_or_update_notifications(
|
74
|
+
self._add_or_update_notifications(entity_id, entity, data)
|
63
75
|
|
64
|
-
|
76
|
+
entity.update(data)
|
65
77
|
is_battery_low = (
|
66
78
|
mac_list
|
67
|
-
and "low_battery" in
|
68
|
-
and
|
69
|
-
and
|
79
|
+
and "low_battery" in entity["binary_sensors"]
|
80
|
+
and entity["zigbee_mac_address"] in mac_list
|
81
|
+
and entity["dev_class"] in ("thermo_sensor", "thermostatic_radiator_valve", "zone_thermometer", "zone_thermostat")
|
70
82
|
)
|
71
83
|
if is_battery_low:
|
72
|
-
|
84
|
+
entity["binary_sensors"]["low_battery"] = True
|
73
85
|
|
74
|
-
self._update_for_cooling(
|
86
|
+
self._update_for_cooling(entity)
|
75
87
|
|
76
|
-
remove_empty_platform_dicts(
|
88
|
+
remove_empty_platform_dicts(entity)
|
77
89
|
|
78
90
|
def _detect_low_batteries(self) -> list[str]:
|
79
91
|
"""Helper-function updating the low-battery binary_sensor status from a Battery-is-low message."""
|
@@ -97,31 +109,31 @@ class SmileData(SmileHelper):
|
|
97
109
|
return mac_address_list
|
98
110
|
|
99
111
|
def _add_or_update_notifications(
|
100
|
-
self,
|
112
|
+
self, entity_id: str, entity: GwEntityData, data: GwEntityData
|
101
113
|
) -> None:
|
102
114
|
"""Helper-function adding or updating the Plugwise notifications."""
|
103
115
|
if (
|
104
|
-
|
116
|
+
entity_id == self.gateway_id
|
105
117
|
and (
|
106
118
|
self._is_thermostat or self.smile_type == "power"
|
107
119
|
)
|
108
120
|
) or (
|
109
|
-
"binary_sensors" in
|
110
|
-
and "plugwise_notification" in
|
121
|
+
"binary_sensors" in entity
|
122
|
+
and "plugwise_notification" in entity["binary_sensors"]
|
111
123
|
):
|
112
124
|
data["binary_sensors"]["plugwise_notification"] = bool(self._notifications)
|
113
125
|
self._count += 1
|
114
126
|
|
115
|
-
def _update_for_cooling(self,
|
127
|
+
def _update_for_cooling(self, entity: GwEntityData) -> None:
|
116
128
|
"""Helper-function for adding/updating various cooling-related values."""
|
117
129
|
# For Anna and heating + cooling, replace setpoint with setpoint_high/_low
|
118
130
|
if (
|
119
131
|
self.smile(ANNA)
|
120
132
|
and self._cooling_present
|
121
|
-
and
|
133
|
+
and entity["dev_class"] == "thermostat"
|
122
134
|
):
|
123
|
-
thermostat =
|
124
|
-
sensors =
|
135
|
+
thermostat = entity["thermostat"]
|
136
|
+
sensors = entity["sensors"]
|
125
137
|
temp_dict: ActuatorData = {
|
126
138
|
"setpoint_low": thermostat["setpoint"],
|
127
139
|
"setpoint_high": MAX_SETPOINT,
|
@@ -133,53 +145,68 @@ class SmileData(SmileHelper):
|
|
133
145
|
}
|
134
146
|
thermostat.pop("setpoint")
|
135
147
|
temp_dict.update(thermostat)
|
136
|
-
|
148
|
+
entity["thermostat"] = temp_dict
|
137
149
|
if "setpoint" in sensors:
|
138
150
|
sensors.pop("setpoint")
|
139
151
|
sensors["setpoint_low"] = temp_dict["setpoint_low"]
|
140
152
|
sensors["setpoint_high"] = temp_dict["setpoint_high"]
|
141
|
-
self._count += 2
|
153
|
+
self._count += 2 # add 4, remove 2
|
154
|
+
|
155
|
+
|
156
|
+
def _get_location_data(self, loc_id: str) -> GwEntityData:
|
157
|
+
"""Helper-function for _all_entity_data() and async_update().
|
158
|
+
|
159
|
+
Provide entity-data, based on Location ID (= loc_id).
|
160
|
+
"""
|
161
|
+
zone = self._zones[loc_id]
|
162
|
+
data = self._get_zone_data(loc_id)
|
163
|
+
if ctrl_state := self._control_state(loc_id):
|
164
|
+
data["control_state"] = ctrl_state
|
165
|
+
self._count += 1
|
142
166
|
|
143
|
-
|
144
|
-
|
167
|
+
# Thermostat data (presets, temperatures etc)
|
168
|
+
self._climate_data(loc_id, zone, data)
|
169
|
+
|
170
|
+
return data
|
145
171
|
|
146
|
-
|
172
|
+
def _get_entity_data(self, entity_id: str) -> GwEntityData:
|
173
|
+
"""Helper-function for _update_gw_entities() and async_update().
|
174
|
+
|
175
|
+
Provide entity-data, based on appliance_id (= entity_id).
|
147
176
|
"""
|
148
|
-
|
149
|
-
data = self._get_measurement_data(
|
177
|
+
entity = self.gw_entities[entity_id]
|
178
|
+
data = self._get_measurement_data(entity_id)
|
150
179
|
|
151
|
-
# Check availability of wired-connected
|
180
|
+
# Check availability of wired-connected entities
|
152
181
|
# Smartmeter
|
153
182
|
self._check_availability(
|
154
|
-
|
183
|
+
entity, "smartmeter", data, "P1 does not seem to be connected"
|
155
184
|
)
|
156
|
-
# OpenTherm
|
157
|
-
if
|
185
|
+
# OpenTherm entity
|
186
|
+
if entity["name"] != "OnOff":
|
158
187
|
self._check_availability(
|
159
|
-
|
188
|
+
entity, "heater_central", data, "no OpenTherm communication"
|
160
189
|
)
|
161
190
|
|
162
191
|
# Switching groups data
|
163
|
-
self.
|
192
|
+
self._entity_switching_group(entity, data)
|
164
193
|
# Adam data
|
165
|
-
self.
|
166
|
-
# Skip obtaining data for (Adam) secondary thermostats
|
167
|
-
if device["dev_class"] not in ZONE_THERMOSTATS:
|
168
|
-
return data
|
194
|
+
self._get_adam_data(entity, data)
|
169
195
|
|
170
|
-
# Thermostat data (presets, temperatures etc)
|
171
|
-
self.
|
196
|
+
# Thermostat data for Anna (presets, temperatures etc)
|
197
|
+
if self.smile(ANNA) and entity["dev_class"] == "thermostat":
|
198
|
+
self._climate_data(entity_id, entity, data)
|
172
199
|
|
173
200
|
return data
|
174
201
|
|
175
202
|
def _check_availability(
|
176
|
-
self,
|
203
|
+
self, entity: GwEntityData, dev_class: str, data: GwEntityData, message: str
|
177
204
|
) -> None:
|
178
|
-
"""Helper-function for
|
205
|
+
"""Helper-function for _get_entity_data().
|
179
206
|
|
180
|
-
Provide availability status for the wired-
|
207
|
+
Provide availability status for the wired-connected devices.
|
181
208
|
"""
|
182
|
-
if
|
209
|
+
if entity["dev_class"] == dev_class:
|
183
210
|
data["available"] = True
|
184
211
|
self._count += 1
|
185
212
|
for item in self._notifications.values():
|
@@ -187,8 +214,8 @@ class SmileData(SmileHelper):
|
|
187
214
|
if message in msg:
|
188
215
|
data["available"] = False
|
189
216
|
|
190
|
-
def
|
191
|
-
"""Helper-function for
|
217
|
+
def _get_adam_data(self, entity: GwEntityData, data: GwEntityData) -> None:
|
218
|
+
"""Helper-function for _get_entity_data().
|
192
219
|
|
193
220
|
Determine Adam heating-status for on-off heating via valves,
|
194
221
|
available regulations_modes and thermostat control_states.
|
@@ -196,14 +223,14 @@ class SmileData(SmileHelper):
|
|
196
223
|
if self.smile(ADAM):
|
197
224
|
# Indicate heating_state based on valves being open in case of city-provided heating
|
198
225
|
if (
|
199
|
-
|
226
|
+
entity["dev_class"] == "heater_central"
|
200
227
|
and self._on_off_device
|
201
228
|
and isinstance(self._heating_valves(), int)
|
202
229
|
):
|
203
230
|
data["binary_sensors"]["heating_state"] = self._heating_valves() != 0
|
204
231
|
|
205
232
|
# Show the allowed regulation_modes and gateway_modes
|
206
|
-
if
|
233
|
+
if entity["dev_class"] == "gateway":
|
207
234
|
if self._reg_allowed_modes:
|
208
235
|
data["regulation_modes"] = self._reg_allowed_modes
|
209
236
|
self._count += 1
|
@@ -211,19 +238,20 @@ class SmileData(SmileHelper):
|
|
211
238
|
data["gateway_modes"] = self._gw_allowed_modes
|
212
239
|
self._count += 1
|
213
240
|
|
214
|
-
# Control_state, only available for Adam primary thermostats
|
215
|
-
if device["dev_class"] in ZONE_THERMOSTATS:
|
216
|
-
loc_id = device["location"]
|
217
|
-
if ctrl_state := self._control_state(loc_id):
|
218
|
-
data["control_state"] = ctrl_state
|
219
|
-
self._count += 1
|
220
241
|
|
221
|
-
def
|
222
|
-
|
242
|
+
def _climate_data(
|
243
|
+
self,
|
244
|
+
location_id: str,
|
245
|
+
entity: GwEntityData,
|
246
|
+
data: GwEntityData
|
247
|
+
) -> None:
|
248
|
+
"""Helper-function for _get_entity_data().
|
223
249
|
|
224
|
-
Determine climate-control
|
250
|
+
Determine climate-control entity data.
|
225
251
|
"""
|
226
|
-
loc_id =
|
252
|
+
loc_id = location_id
|
253
|
+
if entity.get("location") is not None:
|
254
|
+
loc_id = entity["location"]
|
227
255
|
|
228
256
|
# Presets
|
229
257
|
data["preset_modes"] = None
|
@@ -258,13 +286,13 @@ class SmileData(SmileHelper):
|
|
258
286
|
|
259
287
|
def check_reg_mode(self, mode: str) -> bool:
|
260
288
|
"""Helper-function for device_data_climate()."""
|
261
|
-
gateway = self.
|
289
|
+
gateway = self.gw_entities[self.gateway_id]
|
262
290
|
return (
|
263
291
|
"regulation_modes" in gateway and gateway["select_regulation_mode"] == mode
|
264
292
|
)
|
265
293
|
|
266
294
|
def _get_schedule_states_with_off(
|
267
|
-
self, location: str, schedules: list[str], selected: str, data:
|
295
|
+
self, location: str, schedules: list[str], selected: str, data: GwEntityData
|
268
296
|
) -> None:
|
269
297
|
"""Collect schedules with states for each thermostat.
|
270
298
|
|