plugwise 1.6.3__py3-none-any.whl → 1.7.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 CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  Plugwise backend module for Home Assistant Core.
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  from plugwise.constants import (
@@ -16,7 +17,8 @@ from plugwise.constants import (
16
17
  SMILES,
17
18
  STATUS,
18
19
  SYSTEM,
19
- PlugwiseData,
20
+ GwEntityData,
21
+ SmileProps,
20
22
  ThermoLoc,
21
23
  )
22
24
  from plugwise.exceptions import (
@@ -27,9 +29,9 @@ from plugwise.exceptions import (
27
29
  ResponseError,
28
30
  UnsupportedDeviceError,
29
31
  )
30
- from plugwise.helper import SmileComm
31
32
  from plugwise.legacy.smile import SmileLegacyAPI
32
33
  from plugwise.smile import SmileAPI
34
+ from plugwise.smilecomm import SmileComm
33
35
 
34
36
  import aiohttp
35
37
  from defusedxml import ElementTree as etree
@@ -37,9 +39,7 @@ from packaging.version import Version, parse
37
39
 
38
40
 
39
41
  class Smile(SmileComm):
40
- """The Plugwise SmileConnect class."""
41
-
42
- # pylint: disable=too-many-instance-attributes, too-many-public-methods
42
+ """The main Plugwise Smile API class."""
43
43
 
44
44
  def __init__(
45
45
  self,
@@ -50,20 +50,15 @@ class Smile(SmileComm):
50
50
  username: str = DEFAULT_USERNAME,
51
51
  ) -> None:
52
52
  """Set the constructor for this class."""
53
- self._host = host
54
- self._password = password
55
- self._port = port
56
53
  self._timeout = DEFAULT_LEGACY_TIMEOUT
57
- self._username = username
58
- self._websession = websession
59
54
  super().__init__(
60
- self._host,
61
- self._password,
62
- self._port,
55
+ host,
56
+ password,
57
+ port,
63
58
  self._timeout,
64
- self._username,
65
- self._websession,
66
- )
59
+ username,
60
+ websession,
61
+ )
67
62
 
68
63
  self._cooling_present = False
69
64
  self._elga = False
@@ -74,10 +69,9 @@ class Smile(SmileComm):
74
69
  self._opentherm_device = False
75
70
  self._schedule_old_states: dict[str, dict[str, str]] = {}
76
71
  self._smile_api: SmileAPI | SmileLegacyAPI
72
+ self._smile_props: SmileProps = {}
77
73
  self._stretch_v2 = False
78
74
  self._target_smile: str = NONE
79
- self.gateway_id: str = NONE
80
- self.smile_fw_version: Version | None = None
81
75
  self.smile_hostname: str = NONE
82
76
  self.smile_hw_version: str | None = None
83
77
  self.smile_legacy = False
@@ -89,8 +83,40 @@ class Smile(SmileComm):
89
83
  self.smile_version: Version | None = None
90
84
  self.smile_zigbee_mac_address: str | None = None
91
85
 
86
+ @property
87
+ def cooling_present(self) -> bool:
88
+ """Return the cooling capability."""
89
+ if "cooling_present" in self._smile_props:
90
+ return self._smile_props["cooling_present"]
91
+ return False
92
+
93
+ @property
94
+ def gateway_id(self) -> str:
95
+ """Return the gateway-id."""
96
+ return self._smile_props["gateway_id"]
97
+
98
+ @property
99
+ def heater_id(self) -> str:
100
+ """Return the heater-id."""
101
+ if "heater_id" in self._smile_props:
102
+ return self._smile_props["heater_id"]
103
+ return NONE
104
+
105
+ @property
106
+ def item_count(self) -> int:
107
+ """Return the item-count."""
108
+ return self._smile_props["item_count"]
109
+
110
+ @property
111
+ def reboot(self) -> bool:
112
+ """Return the reboot capability.
113
+
114
+ All non-legacy devices support gateway-rebooting.
115
+ """
116
+ return not self.smile_legacy
117
+
92
118
  async def connect(self) -> Version | None:
93
- """Connect to Plugwise device and determine its name, type and version."""
119
+ """Connect to the Plugwise Gateway and determine its name, type, version, and other data."""
94
120
  result = await self._request(DOMAIN_OBJECTS)
95
121
  # Work-around for Stretch fw 2.7.18
96
122
  if not (vendor_names := result.findall("./module/vendor_name")):
@@ -125,52 +151,46 @@ class Smile(SmileComm):
125
151
  # Determine smile specifics
126
152
  await self._smile_detect(result, dsmrmain)
127
153
 
128
- self._smile_api = SmileAPI(
129
- self._host,
130
- self._password,
131
- self._request,
132
- self._websession,
133
- self._cooling_present,
134
- self._elga,
135
- self._is_thermostat,
136
- self._last_active,
137
- self._loc_data,
138
- self._on_off_device,
139
- self._opentherm_device,
140
- self._schedule_old_states,
141
- self.gateway_id,
142
- self.smile_fw_version,
143
- self.smile_hostname,
144
- self.smile_hw_version,
145
- self.smile_mac_address,
146
- self.smile_model,
147
- self.smile_model_id,
148
- self.smile_name,
149
- self.smile_type,
150
- self.smile_version,
151
- self._port,
152
- self._username,
153
- ) if not self.smile_legacy else SmileLegacyAPI(
154
- self._host,
155
- self._password,
156
- self._request,
157
- self._websession,
158
- self._is_thermostat,
159
- self._loc_data,
160
- self._on_off_device,
161
- self._opentherm_device,
162
- self._stretch_v2,
163
- self._target_smile,
164
- self.smile_fw_version,
165
- self.smile_hostname,
166
- self.smile_hw_version,
167
- self.smile_mac_address,
168
- self.smile_model,
169
- self.smile_name,
170
- self.smile_type,
171
- self.smile_zigbee_mac_address,
172
- self._port,
173
- self._username,
154
+ self._smile_api = (
155
+ SmileAPI(
156
+ self._cooling_present,
157
+ self._elga,
158
+ self._is_thermostat,
159
+ self._last_active,
160
+ self._loc_data,
161
+ self._on_off_device,
162
+ self._opentherm_device,
163
+ self._request,
164
+ self._schedule_old_states,
165
+ self._smile_props,
166
+ self.smile_hostname,
167
+ self.smile_hw_version,
168
+ self.smile_mac_address,
169
+ self.smile_model,
170
+ self.smile_model_id,
171
+ self.smile_name,
172
+ self.smile_type,
173
+ self.smile_version,
174
+ )
175
+ if not self.smile_legacy
176
+ else SmileLegacyAPI(
177
+ self._is_thermostat,
178
+ self._loc_data,
179
+ self._on_off_device,
180
+ self._opentherm_device,
181
+ self._request,
182
+ self._smile_props,
183
+ self._stretch_v2,
184
+ self._target_smile,
185
+ self.smile_hostname,
186
+ self.smile_hw_version,
187
+ self.smile_mac_address,
188
+ self.smile_model,
189
+ self.smile_name,
190
+ self.smile_type,
191
+ self.smile_version,
192
+ self.smile_zigbee_mac_address,
193
+ )
174
194
  )
175
195
 
176
196
  # Update all endpoints on first connect
@@ -181,13 +201,13 @@ class Smile(SmileComm):
181
201
  async def _smile_detect(self, result: etree, dsmrmain: etree) -> None:
182
202
  """Helper-function for connect().
183
203
 
184
- Detect which type of Smile is connected.
204
+ Detect which type of Plugwise Gateway is being connected.
185
205
  """
186
206
  model: str = "Unknown"
187
207
  if (gateway := result.find("./gateway")) is not None:
188
208
  if (v_model := gateway.find("vendor_model")) is not None:
189
209
  model = v_model.text
190
- self.smile_fw_version = parse(gateway.find("firmware_version").text)
210
+ self.smile_version = parse(gateway.find("firmware_version").text)
191
211
  self.smile_hw_version = gateway.find("hardware_version").text
192
212
  self.smile_hostname = gateway.find("hostname").text
193
213
  self.smile_mac_address = gateway.find("mac_address").text
@@ -195,7 +215,7 @@ class Smile(SmileComm):
195
215
  else:
196
216
  model = await self._smile_detect_legacy(result, dsmrmain, model)
197
217
 
198
- if model == "Unknown" or self.smile_fw_version is None: # pragma: no cover
218
+ if model == "Unknown" or self.smile_version is None: # pragma: no cover
199
219
  # Corner case check
200
220
  LOGGER.error(
201
221
  "Unable to find model or version information, please create"
@@ -203,7 +223,7 @@ class Smile(SmileComm):
203
223
  )
204
224
  raise UnsupportedDeviceError
205
225
 
206
- version_major= str(self.smile_fw_version.major)
226
+ version_major = str(self.smile_version.major)
207
227
  self._target_smile = f"{model}_v{version_major}"
208
228
  LOGGER.debug("Plugwise identified as %s", self._target_smile)
209
229
  if self._target_smile not in SMILES:
@@ -227,7 +247,6 @@ class Smile(SmileComm):
227
247
  self.smile_model = "Gateway"
228
248
  self.smile_name = SMILES[self._target_smile].smile_name
229
249
  self.smile_type = SMILES[self._target_smile].smile_type
230
- self.smile_version = self.smile_fw_version
231
250
 
232
251
  if self.smile_type == "stretch":
233
252
  self._stretch_v2 = int(version_major) == 2
@@ -255,7 +274,10 @@ class Smile(SmileComm):
255
274
  async def _smile_detect_legacy(
256
275
  self, result: etree, dsmrmain: etree, model: str
257
276
  ) -> str:
258
- """Helper-function for _smile_detect()."""
277
+ """Helper-function for _smile_detect().
278
+
279
+ Detect which type of legacy Plugwise Gateway is being connected.
280
+ """
259
281
  return_model = model
260
282
  # Stretch: find the MAC of the zigbee master_controller (= Stick)
261
283
  if (network := result.find("./module/protocols/master_controller")) is not None:
@@ -273,7 +295,7 @@ class Smile(SmileComm):
273
295
  or network is not None
274
296
  ):
275
297
  system = await self._request(SYSTEM)
276
- self.smile_fw_version = parse(system.find("./gateway/firmware").text)
298
+ self.smile_version = parse(system.find("./gateway/firmware").text)
277
299
  return_model = system.find("./gateway/product").text
278
300
  self.smile_hostname = system.find("./gateway/hostname").text
279
301
  # If wlan0 contains data it's active, so eth0 should be checked last
@@ -284,7 +306,7 @@ class Smile(SmileComm):
284
306
  # P1 legacy:
285
307
  elif dsmrmain is not None:
286
308
  status = await self._request(STATUS)
287
- self.smile_fw_version = parse(status.find("./system/version").text)
309
+ self.smile_version = parse(status.find("./system/version").text)
288
310
  return_model = status.find("./system/product").text
289
311
  self.smile_hostname = status.find("./network/hostname").text
290
312
  self.smile_mac_address = status.find("./network/mac_address").text
@@ -299,28 +321,19 @@ class Smile(SmileComm):
299
321
  self.smile_legacy = True
300
322
  return return_model
301
323
 
302
- async def full_xml_update(self) -> None:
303
- """Helper-function used for testing."""
304
- await self._smile_api.full_xml_update()
305
-
306
- def get_all_gateway_entities(self) -> None:
307
- """Helper-function used for testing."""
308
- self._smile_api.get_all_gateway_entities()
309
-
310
- async def async_update(self) -> PlugwiseData:
311
- """Update the various entities and their states."""
312
- data = PlugwiseData(devices={}, gateway={})
324
+ async def async_update(self) -> dict[str, GwEntityData]:
325
+ """Update the Plughwise Gateway entities and their data and states."""
326
+ data: dict[str, GwEntityData] = {}
313
327
  try:
314
328
  data = await self._smile_api.async_update()
315
- self.gateway_id = data.gateway["gateway_id"]
316
329
  except (DataMissingError, KeyError) as err:
317
330
  raise PlugwiseError("No Plugwise data received") from err
318
331
 
319
332
  return data
320
333
 
321
- ########################################################################################################
322
- ### API Set and HA Service-related Functions ###
323
- ########################################################################################################
334
+ ########################################################################################################
335
+ ### API Set and HA Service-related Functions ###
336
+ ########################################################################################################
324
337
 
325
338
  async def set_select(
326
339
  self,
@@ -333,7 +346,9 @@ class Smile(SmileComm):
333
346
  try:
334
347
  await self._smile_api.set_select(key, loc_id, option, state)
335
348
  except ConnectionFailedError as exc:
336
- raise ConnectionFailedError(f"Failed to set select option '{option}': {str(exc)}") from exc
349
+ raise ConnectionFailedError(
350
+ f"Failed to set select option '{option}': {str(exc)}"
351
+ ) from exc
337
352
 
338
353
  async def set_schedule_state(
339
354
  self,
@@ -345,8 +360,9 @@ class Smile(SmileComm):
345
360
  try:
346
361
  await self._smile_api.set_schedule_state(loc_id, state, name)
347
362
  except ConnectionFailedError as exc: # pragma no cover
348
- raise ConnectionFailedError(f"Failed to set schedule state: {str(exc)}") from exc # pragma no cover
349
-
363
+ raise ConnectionFailedError(
364
+ f"Failed to set schedule state: {str(exc)}"
365
+ ) from exc # pragma no cover
350
366
 
351
367
  async def set_preset(self, loc_id: str, preset: str) -> None:
352
368
  """Set the given Preset on the relevant Thermostat."""
@@ -360,7 +376,9 @@ class Smile(SmileComm):
360
376
  try:
361
377
  await self._smile_api.set_temperature(loc_id, items)
362
378
  except ConnectionFailedError as exc:
363
- raise ConnectionFailedError(f"Failed to set temperature: {str(exc)}") from exc
379
+ raise ConnectionFailedError(
380
+ f"Failed to set temperature: {str(exc)}"
381
+ ) from exc
364
382
 
365
383
  async def set_number(
366
384
  self,
@@ -372,14 +390,18 @@ class Smile(SmileComm):
372
390
  try:
373
391
  await self._smile_api.set_number(dev_id, key, temperature)
374
392
  except ConnectionFailedError as exc:
375
- raise ConnectionFailedError(f"Failed to set number '{key}': {str(exc)}") from exc
393
+ raise ConnectionFailedError(
394
+ f"Failed to set number '{key}': {str(exc)}"
395
+ ) from exc
376
396
 
377
397
  async def set_temperature_offset(self, dev_id: str, offset: float) -> None:
378
398
  """Set the Temperature offset for thermostats that support this feature."""
379
399
  try: # pragma no cover
380
400
  await self._smile_api.set_offset(dev_id, offset) # pragma: no cover
381
401
  except ConnectionFailedError as exc: # pragma no cover
382
- raise ConnectionFailedError(f"Failed to set temperature offset: {str(exc)}") from exc # pragma no cover
402
+ raise ConnectionFailedError(
403
+ f"Failed to set temperature offset: {str(exc)}"
404
+ ) from exc # pragma no cover
383
405
 
384
406
  async def set_switch_state(
385
407
  self, appl_id: str, members: list[str] | None, model: str, state: str
@@ -388,39 +410,51 @@ class Smile(SmileComm):
388
410
  try:
389
411
  await self._smile_api.set_switch_state(appl_id, members, model, state)
390
412
  except ConnectionFailedError as exc:
391
- raise ConnectionFailedError(f"Failed to set switch state: {str(exc)}") from exc
413
+ raise ConnectionFailedError(
414
+ f"Failed to set switch state: {str(exc)}"
415
+ ) from exc
392
416
 
393
417
  async def set_gateway_mode(self, mode: str) -> None:
394
418
  """Set the gateway mode."""
395
419
  try: # pragma no cover
396
420
  await self._smile_api.set_gateway_mode(mode) # pragma: no cover
397
421
  except ConnectionFailedError as exc: # pragma no cover
398
- raise ConnectionFailedError(f"Failed to set gateway mode: {str(exc)}") from exc # pragma no cover
422
+ raise ConnectionFailedError(
423
+ f"Failed to set gateway mode: {str(exc)}"
424
+ ) from exc # pragma no cover
399
425
 
400
426
  async def set_regulation_mode(self, mode: str) -> None:
401
427
  """Set the heating regulation mode."""
402
428
  try: # pragma no cover
403
429
  await self._smile_api.set_regulation_mode(mode) # pragma: no cover
404
430
  except ConnectionFailedError as exc: # pragma no cover
405
- raise ConnectionFailedError(f"Failed to set regulation mode: {str(exc)}") from exc # pragma no cover
431
+ raise ConnectionFailedError(
432
+ f"Failed to set regulation mode: {str(exc)}"
433
+ ) from exc # pragma no cover
406
434
 
407
435
  async def set_dhw_mode(self, mode: str) -> None:
408
436
  """Set the domestic hot water heating regulation mode."""
409
437
  try: # pragma no cover
410
438
  await self._smile_api.set_dhw_mode(mode) # pragma: no cover
411
439
  except ConnectionFailedError as exc: # pragma no cover
412
- raise ConnectionFailedError(f"Failed to set dhw mode: {str(exc)}") from exc # pragma no cover
440
+ raise ConnectionFailedError(
441
+ f"Failed to set dhw mode: {str(exc)}"
442
+ ) from exc # pragma no cover
413
443
 
414
444
  async def delete_notification(self) -> None:
415
445
  """Delete the active Plugwise Notification."""
416
446
  try:
417
447
  await self._smile_api.delete_notification()
418
448
  except ConnectionFailedError as exc:
419
- raise ConnectionFailedError(f"Failed to delete notification: {str(exc)}") from exc
449
+ raise ConnectionFailedError(
450
+ f"Failed to delete notification: {str(exc)}"
451
+ ) from exc
420
452
 
421
453
  async def reboot_gateway(self) -> None:
422
454
  """Reboot the Plugwise Gateway."""
423
455
  try:
424
456
  await self._smile_api.reboot_gateway()
425
457
  except ConnectionFailedError as exc:
426
- raise ConnectionFailedError(f"Failed to reboot gateway: {str(exc)}") from exc
458
+ raise ConnectionFailedError(
459
+ f"Failed to reboot gateway: {str(exc)}"
460
+ ) from exc
plugwise/common.py CHANGED
@@ -2,25 +2,24 @@
2
2
 
3
3
  Plugwise Smile protocol helpers.
4
4
  """
5
+
5
6
  from __future__ import annotations
6
7
 
7
8
  from typing import cast
8
9
 
9
10
  from plugwise.constants import (
10
11
  ANNA,
12
+ NONE,
11
13
  SPECIAL_PLUG_TYPES,
12
14
  SWITCH_GROUP_TYPES,
13
15
  ApplianceType,
14
16
  GwEntityData,
15
17
  ModuleData,
16
- SensorType,
17
18
  )
18
19
  from plugwise.util import (
19
- check_alternative_location,
20
20
  check_heater_central,
21
21
  check_model,
22
22
  get_vendor_name,
23
- power_data_local_format,
24
23
  return_valid,
25
24
  )
26
25
 
@@ -28,19 +27,32 @@ from defusedxml import ElementTree as etree
28
27
  from munch import Munch
29
28
 
30
29
 
30
+ def get_zigbee_data(module: etree, module_data: ModuleData, legacy: bool) -> None:
31
+ """Helper-function for _get_module_data()."""
32
+ if legacy:
33
+ # Stretches
34
+ if (router := module.find("./protocols/network_router")) is not None:
35
+ module_data["zigbee_mac_address"] = router.find("mac_address").text
36
+ # Also look for the Circle+/Stealth M+
37
+ if (coord := module.find("./protocols/network_coordinator")) is not None:
38
+ module_data["zigbee_mac_address"] = coord.find("mac_address").text
39
+ # Adam
40
+ elif (zb_node := module.find("./protocols/zig_bee_node")) is not None:
41
+ module_data["zigbee_mac_address"] = zb_node.find("mac_address").text
42
+ module_data["reachable"] = zb_node.find("reachable").text == "true"
43
+
44
+
31
45
  class SmileCommon:
32
46
  """The SmileCommon class."""
33
47
 
34
48
  def __init__(self) -> None:
35
49
  """Init."""
36
- self._appliances: etree
50
+ self._cooling_present: bool
37
51
  self._count: int
38
52
  self._domain_objects: etree
39
- self._cooling_present: bool
40
- self._heater_id: str
53
+ self._heater_id: str = NONE
41
54
  self._on_off_device: bool
42
- self._opentherm_device: bool
43
- self.gw_entities: dict[str, GwEntityData]
55
+ self.gw_entities: dict[str, GwEntityData] = {}
44
56
  self.smile_name: str
45
57
  self.smile_type: str
46
58
 
@@ -83,21 +95,23 @@ class SmileCommon:
83
95
  appl.hardware = module_data["hardware_version"]
84
96
  appl.model_id = module_data["vendor_model"] if not legacy else None
85
97
  appl.model = (
86
- "Generic heater/cooler"
87
- if self._cooling_present
88
- else "Generic heater"
98
+ "Generic heater/cooler" if self._cooling_present else "Generic heater"
89
99
  )
90
100
 
91
101
  return appl
92
102
 
93
- def _appl_thermostat_info(self, appl: Munch, xml_1: etree, xml_2: etree = None) -> Munch:
103
+ def _appl_thermostat_info(
104
+ self, appl: Munch, xml_1: etree, xml_2: etree = None
105
+ ) -> Munch:
94
106
  """Helper-function for _appliance_info_finder()."""
95
107
  locator = "./logs/point_log[type='thermostat']/thermostat"
96
108
  xml_2 = return_valid(xml_2, self._domain_objects)
97
109
  module_data = self._get_module_data(xml_1, locator, xml_2)
98
110
  appl.vendor_name = module_data["vendor_name"]
99
111
  appl.model = module_data["vendor_model"]
100
- if appl.model != "ThermoTouch": # model_id for Anna not present as stand-alone device
112
+ if (
113
+ appl.model != "ThermoTouch"
114
+ ): # model_id for Anna not present as stand-alone device
101
115
  appl.model_id = appl.model
102
116
  appl.model = check_model(appl.model, appl.vendor_name)
103
117
 
@@ -108,97 +122,6 @@ class SmileCommon:
108
122
 
109
123
  return appl
110
124
 
111
- def _collect_power_values(self, data: GwEntityData, loc: Munch, tariff: str, legacy: bool = False) -> None:
112
- """Something."""
113
- for loc.peak_select in ("nl_peak", "nl_offpeak"):
114
- loc.locator = (
115
- f'./{loc.log_type}[type="{loc.measurement}"]/period/'
116
- f'measurement[@{tariff}="{loc.peak_select}"]'
117
- )
118
- if legacy:
119
- loc.locator = (
120
- f"./{loc.meas_list[0]}_{loc.log_type}/measurement"
121
- f'[@directionality="{loc.meas_list[1]}"][@{tariff}="{loc.peak_select}"]'
122
- )
123
-
124
- loc = self._power_data_peak_value(loc, legacy)
125
- if not loc.found:
126
- continue
127
-
128
- data = self._power_data_energy_diff(
129
- loc.measurement, loc.net_string, loc.f_val, data
130
- )
131
- key = cast(SensorType, loc.key_string)
132
- data["sensors"][key] = loc.f_val
133
-
134
- def _count_data_items(self, data: GwEntityData) -> None:
135
- """When present, count the binary_sensors, sensors and switches dict-items, don't count the dicts.
136
-
137
- Also, count the remaining single data items, the amount of dicts present have already been pre-subtracted in the previous step.
138
- """
139
- if "binary_sensors" in data:
140
- self._count += len(data["binary_sensors"]) - 1
141
- if "sensors" in data:
142
- self._count += len(data["sensors"]) - 1
143
- if "switches" in data:
144
- self._count += len(data["switches"]) - 1
145
- self._count += len(data)
146
-
147
- def _power_data_peak_value(self, loc: Munch, legacy: bool) -> Munch:
148
- """Helper-function for _power_data_from_location() and _power_data_from_modules()."""
149
- loc.found = True
150
- if loc.logs.find(loc.locator) is None:
151
- loc = check_alternative_location(loc, legacy)
152
- if not loc.found:
153
- return loc
154
-
155
- if (peak := loc.peak_select.split("_")[1]) == "offpeak":
156
- peak = "off_peak"
157
- log_found = loc.log_type.split("_")[0]
158
- loc.key_string = f"{loc.measurement}_{peak}_{log_found}"
159
- if "gas" in loc.measurement or loc.log_type == "point_meter":
160
- loc.key_string = f"{loc.measurement}_{log_found}"
161
- # Only for P1 Actual -------------------#
162
- if "phase" in loc.measurement:
163
- loc.key_string = f"{loc.measurement}"
164
- # --------------------------------------#
165
- loc.net_string = f"net_electricity_{log_found}"
166
- val = loc.logs.find(loc.locator).text
167
- loc.f_val = power_data_local_format(loc.attrs, loc.key_string, val)
168
-
169
- return loc
170
-
171
- def _power_data_energy_diff(
172
- self,
173
- measurement: str,
174
- net_string: SensorType,
175
- f_val: float | int,
176
- data: GwEntityData,
177
- ) -> GwEntityData:
178
- """Calculate differential energy."""
179
- if (
180
- "electricity" in measurement
181
- and "phase" not in measurement
182
- and "interval" not in net_string
183
- ):
184
- diff = 1
185
- if "produced" in measurement:
186
- diff = -1
187
- if net_string not in data["sensors"]:
188
- tmp_val: float | int = 0
189
- else:
190
- tmp_val = data["sensors"][net_string]
191
-
192
- if isinstance(f_val, int):
193
- tmp_val += f_val * diff
194
- else:
195
- tmp_val += float(f_val * diff)
196
- tmp_val = float(f"{round(tmp_val, 3):.3f}")
197
-
198
- data["sensors"][net_string] = tmp_val
199
-
200
- return data
201
-
202
125
  def _create_gw_entities(self, appl: Munch) -> None:
203
126
  """Helper-function for creating/updating gw_entities."""
204
127
  self.gw_entities[appl.entity_id] = {"dev_class": appl.pwclass}
@@ -220,9 +143,7 @@ class SmileCommon:
220
143
  self.gw_entities[appl.entity_id][appl_key] = value
221
144
  self._count += 1
222
145
 
223
- def _entity_switching_group(
224
- self, entity: GwEntityData, data: GwEntityData
225
- ) -> None:
146
+ def _entity_switching_group(self, entity: GwEntityData, data: GwEntityData) -> None:
226
147
  """Helper-function for _get_device_zone_data().
227
148
 
228
149
  Determine switching group device data.
@@ -268,7 +189,9 @@ class SmileCommon:
268
189
 
269
190
  return switch_groups
270
191
 
271
- def _get_lock_state(self, xml: etree, data: GwEntityData, stretch_v2: bool = False) -> None:
192
+ def _get_lock_state(
193
+ self, xml: etree, data: GwEntityData, stretch_v2: bool = False
194
+ ) -> None:
272
195
  """Helper-function for _get_measurement_data().
273
196
 
274
197
  Adam & Stretches: obtain the relay-switch lock state.
@@ -319,20 +242,6 @@ class SmileCommon:
319
242
  module_data["vendor_model"] = module.find("vendor_model").text
320
243
  module_data["hardware_version"] = module.find("hardware_version").text
321
244
  module_data["firmware_version"] = module.find("firmware_version").text
322
- self._get_zigbee_data(module, module_data, legacy)
245
+ get_zigbee_data(module, module_data, legacy)
323
246
 
324
247
  return module_data
325
-
326
- def _get_zigbee_data(self, module: etree, module_data: ModuleData, legacy: bool) -> None:
327
- """Helper-function for _get_module_data()."""
328
- if legacy:
329
- # Stretches
330
- if (router := module.find("./protocols/network_router")) is not None:
331
- module_data["zigbee_mac_address"] = router.find("mac_address").text
332
- # Also look for the Circle+/Stealth M+
333
- if (coord := module.find("./protocols/network_coordinator")) is not None:
334
- module_data["zigbee_mac_address"] = coord.find("mac_address").text
335
- # Adam
336
- elif (zb_node := module.find("./protocols/zig_bee_node")) is not None:
337
- module_data["zigbee_mac_address"] = zb_node.find("mac_address").text
338
- module_data["reachable"] = zb_node.find("reachable").text == "true"