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/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
- DeviceData,
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 _all_device_data(self) -> None:
33
- """Helper-function for get_all_devices().
31
+ def _all_entity_data(self) -> None:
32
+ """Helper-function for get_all_gateway_entities().
34
33
 
35
- Collect data for each device and add to self.gw_data and self.gw_devices.
34
+ Collect data for each entity and add to self.gw_data and self.gw_entities.
36
35
  """
37
- self._update_gw_devices()
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 _update_gw_devices(self) -> None:
53
- """Helper-function for _all_device_data() and async_update().
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 device and add to self.gw_devices.
67
+ Collect data for each entity and add to self.gw_entities.
56
68
  """
57
69
  mac_list: list[str] = []
58
- for device_id, device in self.gw_devices.items():
59
- data = self._get_device_data(device_id)
60
- if device_id == self.gateway_id:
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(device_id, device, data)
74
+ self._add_or_update_notifications(entity_id, entity, data)
63
75
 
64
- device.update(data)
76
+ entity.update(data)
65
77
  is_battery_low = (
66
78
  mac_list
67
- and "low_battery" in device["binary_sensors"]
68
- and device["zigbee_mac_address"] in mac_list
69
- and device["dev_class"] in ("thermo_sensor", "thermostatic_radiator_valve", "zone_thermometer", "zone_thermostat")
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
- device["binary_sensors"]["low_battery"] = True
84
+ entity["binary_sensors"]["low_battery"] = True
73
85
 
74
- self._update_for_cooling(device)
86
+ self._update_for_cooling(entity)
75
87
 
76
- remove_empty_platform_dicts(device)
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, device_id: str, device: DeviceData, data: DeviceData
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
- device_id == self.gateway_id
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 device
110
- and "plugwise_notification" in device["binary_sensors"]
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, device: DeviceData) -> None:
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 device["dev_class"] == "thermostat"
133
+ and entity["dev_class"] == "thermostat"
122
134
  ):
123
- thermostat = device["thermostat"]
124
- sensors = device["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
- device["thermostat"] = temp_dict
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
- def _get_device_data(self, dev_id: str) -> DeviceData:
144
- """Helper-function for _all_device_data() and async_update().
167
+ # Thermostat data (presets, temperatures etc)
168
+ self._climate_data(loc_id, zone, data)
169
+
170
+ return data
145
171
 
146
- Provide device-data, based on Location ID (= dev_id), from APPLIANCES.
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
- device = self.gw_devices[dev_id]
149
- data = self._get_measurement_data(dev_id)
177
+ entity = self.gw_entities[entity_id]
178
+ data = self._get_measurement_data(entity_id)
150
179
 
151
- # Check availability of wired-connected devices
180
+ # Check availability of wired-connected entities
152
181
  # Smartmeter
153
182
  self._check_availability(
154
- device, "smartmeter", data, "P1 does not seem to be connected"
183
+ entity, "smartmeter", data, "P1 does not seem to be connected"
155
184
  )
156
- # OpenTherm device
157
- if device["name"] != "OnOff":
185
+ # OpenTherm entity
186
+ if entity["name"] != "OnOff":
158
187
  self._check_availability(
159
- device, "heater_central", data, "no OpenTherm communication"
188
+ entity, "heater_central", data, "no OpenTherm communication"
160
189
  )
161
190
 
162
191
  # Switching groups data
163
- self._device_data_switching_group(device, data)
192
+ self._entity_switching_group(entity, data)
164
193
  # Adam data
165
- self._device_data_adam(device, data)
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._device_data_climate(device, data)
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, device: DeviceData, dev_class: str, data: DeviceData, message: str
203
+ self, entity: GwEntityData, dev_class: str, data: GwEntityData, message: str
177
204
  ) -> None:
178
- """Helper-function for _get_device_data().
205
+ """Helper-function for _get_entity_data().
179
206
 
180
- Provide availability status for the wired-commected devices.
207
+ Provide availability status for the wired-connected devices.
181
208
  """
182
- if device["dev_class"] == dev_class:
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 _device_data_adam(self, device: DeviceData, data: DeviceData) -> None:
191
- """Helper-function for _get_device_data().
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
- device["dev_class"] == "heater_central"
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 device["dev_class"] == "gateway":
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 _device_data_climate(self, device: DeviceData, data: DeviceData) -> None:
222
- """Helper-function for _get_device_data().
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 device data.
250
+ Determine climate-control entity data.
225
251
  """
226
- loc_id = device["location"]
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.gw_devices[self.gateway_id]
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: DeviceData
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