Skip to content

Commit 569686e

Browse files
authored
Merge pull request #802 from plugwise/module-deleted
Improve detection of orphaned/removed devices
2 parents 80a2e51 + 0279f99 commit 569686e

File tree

9 files changed

+1117
-16
lines changed

9 files changed

+1117
-16
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## v1.8.1
4+
5+
- Improve detection of orphaned/removed devices via [#802](https://github.com/plugwise/python-plugwise/pull/802)
6+
37
## v1.8.0
48

59
- Test/validate for Python 3.14
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
{
2+
"0466eae8520144c78afb29628384edeb": {
3+
"binary_sensors": {
4+
"plugwise_notification": false
5+
},
6+
"dev_class": "gateway",
7+
"firmware": "4.0.15",
8+
"hardware": "AME Smile 2.0 board",
9+
"location": "94c107dc6ac84ed98e9f68c0dd06bf71",
10+
"mac_address": "012345670001",
11+
"model": "Gateway",
12+
"model_id": "smile_thermo",
13+
"name": "Smile Anna",
14+
"notifications": {},
15+
"sensors": {
16+
"outdoor_temperature": 7.44
17+
},
18+
"vendor": "Plugwise"
19+
}
20+
}

plugwise/common.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,11 @@ def _appl_heater_central_info(
101101
module_data = self._get_module_data(xml_1, locator_1, xml_3)
102102
if not module_data["contents"]:
103103
module_data = self._get_module_data(xml_1, locator_2, xml_3)
104+
if not module_data["contents"]:
105+
self._heater_id = NONE
106+
return (
107+
Munch()
108+
) # no module-data present means the device has been removed
104109
appl.vendor_name = module_data["vendor_name"]
105110
appl.hardware = module_data["hardware_version"]
106111
appl.model_id = module_data["vendor_model"] if not legacy else None
@@ -117,6 +122,9 @@ def _appl_thermostat_info(
117122
locator = "./logs/point_log[type='thermostat']/thermostat"
118123
xml_2 = return_valid(xml_2, self._domain_objects)
119124
module_data = self._get_module_data(xml_1, locator, xml_2)
125+
if not module_data["contents"]:
126+
return Munch() # no module-data present means the device has been removed
127+
120128
appl.vendor_name = module_data["vendor_name"]
121129
appl.model = module_data["vendor_model"]
122130
if (

plugwise/helper.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,10 @@ def _get_p1_smartmeter_info(self) -> None:
170170
appl = Munch()
171171
locator = MODULE_LOCATOR
172172
module_data = self._get_module_data(self._home_location, locator)
173-
if not module_data["contents"]:
174-
LOGGER.error("No module data found for SmartMeter") # pragma: no cover
175-
return # pragma: no cover
173+
# No module-data present means the device has been removed
174+
if not module_data["contents"]: # pragma: no cover
175+
return
176+
176177
appl.available = None
177178
appl.entity_id = self._gateway_id
178179
appl.firmware = module_data["firmware_version"]
@@ -219,15 +220,16 @@ def _appliance_info_finder(self, appl: Munch, appliance: etree.Element) -> Munch
219220
return self._appl_thermostat_info(appl, appliance)
220221
case "heater_central":
221222
# Collect heater_central entity info
222-
self._appl_heater_central_info(
223-
appl, appliance, False
224-
) # False means non-legacy entity
223+
# 251016: the added guarding below also solves Core Issue #104433
224+
if not (
225+
appl := self._appl_heater_central_info(
226+
appl, appliance, False
227+
)
228+
): # False means non-legacy entity
229+
return Munch()
225230
self._dhw_allowed_modes = self._get_appl_actuator_modes(
226231
appliance, "domestic_hot_water_mode_control_functionality"
227232
)
228-
# Skip orphaned heater_central (Core Issue #104433)
229-
if appl.entity_id != self.heater_id:
230-
return Munch()
231233
return appl
232234
case _ as s if s.endswith("_plug"):
233235
# Collect info from plug-types (Plug, Aqara Smart Plug)

plugwise/legacy/helper.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -214,18 +214,19 @@ def _energy_entity_info_finder(self, appliance: etree, appl: Munch) -> Munch:
214214
module_data = self._get_module_data(
215215
appliance, locator, self._modules, legacy=True
216216
)
217-
appl.zigbee_mac = module_data["zigbee_mac_address"]
218-
# Filter appliance without zigbee_mac, it's an orphaned device
219-
if appl.zigbee_mac is None and self.smile.type != "power":
220-
return None
217+
if not module_data["contents"]:
218+
return (
219+
Munch()
220+
) # no module-data present means the device has been removed
221221

222+
appl.firmware = module_data["firmware_version"]
222223
appl.hardware = module_data["hardware_version"]
223224
appl.model = module_data["vendor_model"]
224-
appl.vendor_name = module_data["vendor_name"]
225225
if appl.hardware is not None:
226226
hw_version = appl.hardware.replace("-", "")
227227
appl.model = version_to_model(hw_version)
228-
appl.firmware = module_data["firmware_version"]
228+
appl.vendor_name = module_data["vendor_name"]
229+
appl.zigbee_mac = module_data["zigbee_mac_address"]
229230

230231
return appl
231232

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "plugwise"
7-
version = "1.8.0"
7+
version = "1.8.1"
88
license = "MIT"
99
description = "Plugwise Smile (Adam/Anna/P1) and Stretch module for Python 3."
1010
readme = "README.md"
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"devices": {
3+
"0466eae8520144c78afb29628384edeb": {
4+
"binary_sensors": {
5+
"plugwise_notification": false
6+
},
7+
"dev_class": "gateway",
8+
"firmware": "4.0.15",
9+
"hardware": "AME Smile 2.0 board",
10+
"location": "94c107dc6ac84ed98e9f68c0dd06bf71",
11+
"mac_address": "012345670001",
12+
"model": "Gateway",
13+
"model_id": "smile_thermo",
14+
"name": "Smile Anna",
15+
"notifications": {},
16+
"sensors": {
17+
"outdoor_temperature": 7.44
18+
},
19+
"vendor": "Plugwise"
20+
}
21+
}
22+
}

tests/test_anna.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,3 +546,24 @@ async def test_connect_anna_loria_driessens(self):
546546

547547
await api.close_connection()
548548
await self.disconnect(server, client)
549+
550+
@pytest.mark.asyncio
551+
async def test_connect_anna_v4_no_modules(self):
552+
"""Test an Anna v4 with removed Anna and OpenTherm device."""
553+
self.smile_setup = "anna_v4_no_modules"
554+
555+
testdata = await self.load_testdata(SMILE_TYPE, self.smile_setup)
556+
server, api, client = await self.connect_wrapper()
557+
assert api.smile.hostname == "smile000000"
558+
559+
self.validate_test_basics(
560+
_LOGGER,
561+
api,
562+
smile_version=None,
563+
)
564+
565+
await self.device_test(api, "2022-05-16 00:00:01", testdata)
566+
assert self.entity_items == 12
567+
568+
await api.close_connection()
569+
await self.disconnect(server, client)

0 commit comments

Comments
 (0)