Skip to content

Commit b18aa6b

Browse files
committed
Define smile-Munch
1 parent f6eb523 commit b18aa6b

File tree

6 files changed

+74
-115
lines changed

6 files changed

+74
-115
lines changed

plugwise/__init__.py

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636

3737
import aiohttp
3838
from defusedxml import ElementTree as etree
39+
from munch import Munch
3940
from packaging.version import Version, parse
4041

4142

@@ -72,16 +73,17 @@ def __init__(
7273
self._smile_api: SmileAPI | SmileLegacyAPI
7374
self._stretch_v2 = False
7475
self._target_smile: str = NONE
75-
self.smile_hostname: str = NONE
76-
self.smile_hw_version: str | None = None
77-
self.smile_legacy = False
78-
self.smile_mac_address: str | None = None
79-
self.smile_model: str = NONE
80-
self.smile_model_id: str | None = None
81-
self.smile_name: str = NONE
82-
self.smile_type: str = NONE
83-
self.smile_version: Version = Version("0.0.0")
84-
self.smile_zigbee_mac_address: str | None = None
76+
self.smile: Munch = Munch()
77+
self.smile.hostname: str = NONE
78+
self.smile.hw_version: str | None = None
79+
self.smile.legacy = False
80+
self.smile.mac_address: str | None = None
81+
self.smile.model: str = NONE
82+
self.smile.model_id: str | None = None
83+
self.smile.name: str = NONE
84+
self.smile.type: str = NONE
85+
self.smile.version: Version = Version("0.0.0")
86+
self.smile.zigbee_mac_address: str | None = None
8587

8688
@property
8789
def cooling_present(self) -> bool:
@@ -109,7 +111,7 @@ def reboot(self) -> bool:
109111
110112
All non-legacy devices support gateway-rebooting.
111113
"""
112-
return not self.smile_legacy
114+
return not self.smile.legacy
113115

114116
async def connect(self) -> Version:
115117
"""Connect to the Plugwise Gateway and determine its name, type, version, and other data."""
@@ -158,16 +160,9 @@ async def connect(self) -> Version:
158160
self._opentherm_device,
159161
self._request,
160162
self._schedule_old_states,
161-
self.smile_hostname,
162-
self.smile_hw_version,
163-
self.smile_mac_address,
164-
self.smile_model,
165-
self.smile_model_id,
166-
self.smile_name,
167-
self.smile_type,
168-
self.smile_version,
163+
self.smile,
169164
)
170-
if not self.smile_legacy
165+
if not self.smile.legacy
171166
else SmileLegacyAPI(
172167
self._is_thermostat,
173168
self._loc_data,
@@ -176,21 +171,14 @@ async def connect(self) -> Version:
176171
self._request,
177172
self._stretch_v2,
178173
self._target_smile,
179-
self.smile_hostname,
180-
self.smile_hw_version,
181-
self.smile_mac_address,
182-
self.smile_model,
183-
self.smile_name,
184-
self.smile_type,
185-
self.smile_version,
186-
self.smile_zigbee_mac_address,
174+
self.smile,
187175
)
188176
)
189177

190178
# Update all endpoints on first connect
191179
await self._smile_api.full_xml_update()
192180

193-
return self.smile_version
181+
return self.smile.version
194182

195183
async def _smile_detect(
196184
self, result: etree.Element, dsmrmain: etree.Element
@@ -203,23 +191,23 @@ async def _smile_detect(
203191
if (gateway := result.find("./gateway")) is not None:
204192
if (v_model := gateway.find("vendor_model")) is not None:
205193
model = v_model.text
206-
self.smile_version = parse(gateway.find("firmware_version").text)
207-
self.smile_hw_version = gateway.find("hardware_version").text
208-
self.smile_hostname = gateway.find("hostname").text
209-
self.smile_mac_address = gateway.find("mac_address").text
210-
self.smile_model_id = gateway.find("vendor_model").text
194+
self.smile.version = parse(gateway.find("firmware_version").text)
195+
self.smile.hw_version = gateway.find("hardware_version").text
196+
self.smile.hostname = gateway.find("hostname").text
197+
self.smile.mac_address = gateway.find("mac_address").text
198+
self.smile._model_id = gateway.find("vendor_model").text
211199
else:
212200
model = await self._smile_detect_legacy(result, dsmrmain, model)
213201

214-
if model == "Unknown" or self.smile_version is None: # pragma: no cover
202+
if model == "Unknown" or self.smile.version is None: # pragma: no cover
215203
# Corner case check
216204
LOGGER.error(
217205
"Unable to find model or version information, please create"
218206
" an issue on http://github.com/plugwise/python-plugwise"
219207
)
220208
raise UnsupportedDeviceError
221209

222-
version_major = str(self.smile_version.major)
210+
version_major = str(self.smile.version.major)
223211
self._target_smile = f"{model}_v{version_major}"
224212
LOGGER.debug("Plugwise identified as %s", self._target_smile)
225213
if self._target_smile not in SMILES:
@@ -230,7 +218,7 @@ async def _smile_detect(
230218
)
231219
raise UnsupportedDeviceError
232220

233-
if not self.smile_legacy:
221+
if not self.smile.legacy:
234222
self._timeout = DEFAULT_TIMEOUT
235223

236224
if self._target_smile in ("smile_open_therm_v2", "smile_thermo_v3"):
@@ -240,14 +228,14 @@ async def _smile_detect(
240228
) # pragma: no cover
241229
raise UnsupportedDeviceError # pragma: no cover
242230

243-
self.smile_model = "Gateway"
244-
self.smile_name = SMILES[self._target_smile].smile_name
245-
self.smile_type = SMILES[self._target_smile].smile_type
231+
self.smile.model = "Gateway"
232+
self.smile.name = SMILES[self._target_smile].smile_name
233+
self.smile.type = SMILES[self._target_smile].smile_type
246234

247-
if self.smile_type == "stretch":
235+
if self.smile.type == "stretch":
248236
self._stretch_v2 = int(version_major) == 2
249237

250-
if self.smile_type == "thermostat":
238+
if self.smile.type == "thermostat":
251239
self._is_thermostat = True
252240
# For Adam, Anna, determine the system capabilities:
253241
# Find the connected heating/cooling device (heater_central),
@@ -275,36 +263,36 @@ async def _smile_detect_legacy(
275263
return_model = model
276264
# Stretch: find the MAC of the zigbee master_controller (= Stick)
277265
if (network := result.find("./module/protocols/master_controller")) is not None:
278-
self.smile_zigbee_mac_address = network.find("mac_address").text
266+
self.smile.zigbee_mac_address = network.find("mac_address").text
279267
# Find the active MAC in case there is an orphaned Stick
280268
if zb_networks := result.findall("./network"):
281269
for zb_network in zb_networks:
282270
if zb_network.find("./nodes/network_router") is not None:
283271
network = zb_network.find("./master_controller")
284-
self.smile_zigbee_mac_address = network.find("mac_address").text
272+
self.smile.zigbee_mac_address = network.find("mac_address").text
285273

286274
# Legacy Anna or Stretch:
287275
if (
288276
result.find('./appliance[type="thermostat"]') is not None
289277
or network is not None
290278
):
291279
system = await self._request(SYSTEM)
292-
self.smile_version = parse(system.find("./gateway/firmware").text)
280+
self.smile.version = parse(system.find("./gateway/firmware").text)
293281
return_model = str(system.find("./gateway/product").text)
294-
self.smile_hostname = system.find("./gateway/hostname").text
282+
self.smile.hostname = system.find("./gateway/hostname").text
295283
# If wlan0 contains data it's active, eth0 should be checked last as is preferred
296284
for network in ("wlan0", "eth0"):
297285
locator = f"./{network}/mac"
298286
if (net_locator := system.find(locator)) is not None:
299-
self.smile_mac_address = net_locator.text
287+
self.smile.mac_address = net_locator.text
300288

301289
# P1 legacy:
302290
elif dsmrmain is not None:
303291
status = await self._request(STATUS)
304-
self.smile_version = parse(status.find("./system/version").text)
292+
self.smile.version = parse(status.find("./system/version").text)
305293
return_model = str(status.find("./system/product").text)
306-
self.smile_hostname = status.find("./network/hostname").text
307-
self.smile_mac_address = status.find("./network/mac_address").text
294+
self.smile.hostname = status.find("./network/hostname").text
295+
self.smile.mac_address = status.find("./network/mac_address").text
308296
else: # pragma: no cover
309297
# No cornercase, just end of the line
310298
LOGGER.error(
@@ -313,7 +301,7 @@ async def _smile_detect_legacy(
313301
)
314302
raise ResponseError
315303

316-
self.smile_legacy = True
304+
self.smile.legacy = True
317305
return return_model
318306

319307
async def async_update(self) -> dict[str, GwEntityData]:

plugwise/common.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,16 @@ def __init__(self) -> None:
5555
self._heater_id: str = NONE
5656
self._on_off_device: bool
5757
self.gw_entities: dict[str, GwEntityData] = {}
58-
self.smile_name: str
59-
self.smile_type: str
58+
self.smile: Munch
6059

6160
@property
6261
def heater_id(self) -> str:
6362
"""Return the heater-id."""
6463
return self._heater_id
6564

66-
def smile(self, name: str) -> bool:
65+
def check_name(self, name: str) -> bool:
6766
"""Helper-function checking the smile-name."""
68-
return self.smile_name == name
67+
return self.smile.name == name
6968

7069
def _appl_heater_central_info(
7170
self,
@@ -173,7 +172,7 @@ def _get_group_switches(self) -> dict[str, GwEntityData]:
173172
"""
174173
switch_groups: dict[str, GwEntityData] = {}
175174
# P1 and Anna don't have switchgroups
176-
if self.smile_type == "power" or self.smile(ANNA):
175+
if self.smile.type == "power" or self.check_name(ANNA):
177176
return switch_groups
178177

179178
for group in self._domain_objects.findall("./group"):

plugwise/helper.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,7 @@ def _appl_gateway_info(self, appl: Munch, appliance: etree.Element) -> Munch:
277277
appl.vendor_name = "Plugwise"
278278

279279
# Adam: collect the ZigBee MAC address of the Smile
280-
if self.smile(ADAM):
280+
if self.check_name(ADAM):
281281
if (
282282
found := self._domain_objects.find(".//protocols/zig_bee_coordinator")
283283
) is not None:
@@ -383,7 +383,7 @@ def _get_measurement_data(self, entity_id: str) -> GwEntityData:
383383
data.pop("c_heating_state")
384384
self._count -= 1
385385

386-
if self._is_thermostat and self.smile(ANNA):
386+
if self._is_thermostat and self.check_name(ANNA):
387387
self._update_anna_cooling(entity_id, data)
388388

389389
self._cleanup_data(data)
@@ -484,7 +484,7 @@ def _get_actuator_functionalities(
484484
item == "thermostat"
485485
and (
486486
entity["dev_class"] != "climate"
487-
if self.smile(ADAM)
487+
if self.check_name(ADAM)
488488
else entity["dev_class"] != "thermostat"
489489
)
490490
):
@@ -539,7 +539,7 @@ def _get_actuator_mode(
539539
540540
Collect the requested gateway mode.
541541
"""
542-
if not (self.smile(ADAM) and entity_id == self._gateway_id):
542+
if not (self.check_name(ADAM) and entity_id == self._gateway_id):
543543
return None
544544

545545
if (search := search_actuator_functionalities(appliance, key)) is not None:
@@ -605,10 +605,10 @@ def _process_on_off_device_c_heating_state(self, data: GwEntityData) -> None:
605605
606606
Solution for Core issue #81839.
607607
"""
608-
if self.smile(ANNA):
608+
if self.check_name(ANNA):
609609
data["binary_sensors"]["heating_state"] = data["c_heating_state"]
610610

611-
if self.smile(ADAM):
611+
if self.check_name(ADAM):
612612
# First count when not present, then create and init to False.
613613
# When present init to False
614614
if "heating_state" not in data["binary_sensors"]:

plugwise/legacy/helper.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,10 @@ def __init__(self) -> None:
7373
self._modules: etree.Element
7474
self._stretch_v2: bool
7575
self.gw_entities: dict[str, GwEntityData] = {}
76-
self.smile_mac_address: str | None
77-
self.smile_model: str
78-
self.smile_version: Version
79-
self.smile_zigbee_mac_address: str | None
76+
self.smile.mac_address: str | None
77+
self.smile.model: str
78+
self.smile.version: Version
79+
self.smile.zigbee_mac_address: str | None
8080

8181
@property
8282
def gateway_id(self) -> str:
@@ -95,7 +95,7 @@ def _all_appliances(self) -> None:
9595

9696
self._create_legacy_gateway()
9797
# For legacy P1 collect the connected SmartMeter info
98-
if self.smile_type == "power":
98+
if self.smile.type == "power":
9999
appl = Munch()
100100
self._p1_smartmeter_info_finder(appl)
101101
# Legacy P1 has no more devices
@@ -167,13 +167,13 @@ def _all_locations(self) -> None:
167167
loc.loc_id = location.attrib["id"]
168168
# Filter the valid single location for P1 legacy: services not empty
169169
locator = "./services"
170-
if self.smile_type == "power" and len(location.find(locator)) == 0:
170+
if self.smile.type == "power" and len(location.find(locator)) == 0:
171171
continue
172172

173173
if loc.name == "Home":
174174
self._home_loc_id = loc.loc_id
175175
# Replace location-name for P1 legacy, can contain privacy-related info
176-
if self.smile_type == "power":
176+
if self.smile.type == "power":
177177
loc.name = "Home"
178178
self._home_loc_id = loc.loc_id
179179

@@ -185,18 +185,18 @@ def _create_legacy_gateway(self) -> None:
185185
Use the home_location or FAKE_APPL as entity id.
186186
"""
187187
self._gateway_id = self._home_loc_id
188-
if self.smile_type == "power":
188+
if self.smile.type == "power":
189189
self._gateway_id = FAKE_APPL
190190

191191
self.gw_entities[self._gateway_id] = {"dev_class": "gateway"}
192192
self._count += 1
193193
for key, value in {
194-
"firmware": str(self.smile_version),
194+
"firmware": str(self.smile.version),
195195
"location": self._home_loc_id,
196-
"mac_address": self.smile_mac_address,
197-
"model": self.smile_model,
198-
"name": self.smile_name,
199-
"zigbee_mac_address": self.smile_zigbee_mac_address,
196+
"mac_address": self.smile.mac_address,
197+
"model": self.smile.model,
198+
"name": self.smile.name,
199+
"zigbee_mac_address": self.smile.zigbee_mac_address,
200200
"vendor": "Plugwise",
201201
}.items():
202202
if value is not None:
@@ -224,14 +224,14 @@ def _energy_entity_info_finder(self, appliance: etree, appl: Munch) -> Munch:
224224
225225
Collect energy entity info (Smartmeter, Circle, Stealth, etc.): firmware, model and vendor name.
226226
"""
227-
if self.smile_type in ("power", "stretch"):
227+
if self.smile.type in ("power", "stretch"):
228228
locator = "./services/electricity_point_meter"
229229
module_data = self._get_module_data(
230230
appliance, locator, self._modules, legacy=True
231231
)
232232
appl.zigbee_mac = module_data["zigbee_mac_address"]
233233
# Filter appliance without zigbee_mac, it's an orphaned device
234-
if appl.zigbee_mac is None and self.smile_type != "power":
234+
if appl.zigbee_mac is None and self.smile.type != "power":
235235
return None
236236

237237
appl.hardware = module_data["hardware_version"]
@@ -253,7 +253,7 @@ def _p1_smartmeter_info_finder(self, appl: Munch) -> None:
253253
appl.entity_id = loc_id
254254
appl.location = loc_id
255255
appl.mac = None
256-
appl.model = self.smile_model
256+
appl.model = self.smile.model
257257
appl.model_id = None
258258
appl.name = "P1"
259259
appl.pwclass = "smartmeter"
@@ -272,7 +272,7 @@ def _get_measurement_data(self, entity_id: str) -> GwEntityData:
272272
# Get P1 smartmeter data from MODULES
273273
entity = self.gw_entities[entity_id]
274274
# !! DON'T CHANGE below two if-lines, will break stuff !!
275-
if self.smile_type == "power":
275+
if self.smile.type == "power":
276276
if entity["dev_class"] == "smartmeter":
277277
data.update(self._power_data_from_modules())
278278

0 commit comments

Comments
 (0)