@@ -269,6 +269,10 @@ def _all_appliances(self) -> None:
269269 for appliance in self ._domain_objects .findall ("./appliance" ):
270270 appl = Munch ()
271271 appl .pwclass = appliance .find ("type" ).text
272+ # Don't collect data for the OpenThermGateway appliance
273+ if appl .pwclass == "open_therm_gateway" :
274+ continue
275+
272276 # Extend device_class name of Plugs (Plugwise and Aqara) - Pw-Beta Issue #739
273277 description = appliance .find ("description" ).text
274278 if description is not None and (
@@ -291,6 +295,10 @@ def _all_appliances(self) -> None:
291295 elif appl .pwclass not in THERMOSTAT_CLASSES :
292296 appl .location = self ._home_location
293297
298+ # Don't show orphaned thermostat-types
299+ if appl .pwclass in THERMOSTAT_CLASSES and appl .location is None :
300+ continue
301+
294302 appl .dev_id = appliance .attrib ["id" ]
295303 appl .name = appliance .find ("name" ).text
296304 appl .model = None
@@ -301,24 +309,15 @@ def _all_appliances(self) -> None:
301309 appl .zigbee_mac = None
302310 appl .vendor_name = None
303311
304- # Determine class for this appliance
305- # Skip on heater_central when no active device present
312+ # Collect appliance info, skip orphaned/removed devices
306313 if not (appl := self ._appliance_info_finder (appl , appliance )):
307314 continue
308315
309- # Skip orphaned heater_central (Core Issue #104433)
310- if appl .pwclass == "heater_central" and appl .dev_id != self ._heater_id :
311- continue
312-
313316 # P1: for gateway and smartmeter switch device_id - part 1
314317 # This is done to avoid breakage in HA Core
315318 if appl .pwclass == "gateway" and self .smile_type == "power" :
316319 appl .dev_id = appl .location
317320
318- # Don't show orphaned thermostat-types or the OpenTherm Gateway.
319- if appl .pwclass in THERMOSTAT_CLASSES and appl .location is None :
320- continue
321-
322321 self ._create_gw_devices (appl )
323322
324323 # For P1 collect the connected SmartMeter info
@@ -354,23 +353,32 @@ def _all_locations(self) -> None:
354353 self .loc_data [loc .loc_id ] = {"name" : loc .name }
355354
356355 def _p1_smartmeter_info_finder (self , appl : Munch ) -> None :
357- """Collect P1 DSMR Smartmeter info."""
356+ """Collect P1 DSMR SmartMeter info."""
358357 loc_id = next (iter (self .loc_data .keys ()))
358+ location = self ._domain_objects .find (f'./location[@id="{ loc_id } "]' )
359+ locator = "./logs/point_log/electricity_point_meter"
360+ mod_type = "electricity_point_meter"
361+ module_data = self ._get_module_data (location , locator , mod_type )
362+ if not module_data ["contents" ]:
363+ LOGGER .error ("No module data found for SmartMeter" ) # pragma: no cover
364+ return None # pragma: no cover
365+
359366 appl .dev_id = self .gateway_id
367+ appl .firmware = module_data ["firmware_version" ]
368+ appl .hardware = module_data ["hardware_version" ]
360369 appl .location = loc_id
361370 appl .mac = None
362- appl .model = None
363- appl .model_id = None
371+ appl .model = module_data [ "vendor_model" ]
372+ appl .model_id = None # don't use model_id for SmartMeter
364373 appl .name = "P1"
365374 appl .pwclass = "smartmeter"
375+ appl .vendor_name = module_data ["vendor_name" ]
366376 appl .zigbee_mac = None
367- location = self ._domain_objects .find (f'./location[@id="{ loc_id } "]' )
368- appl = self ._energy_device_info_finder (appl , location )
369377
370378 self ._create_gw_devices (appl )
371379
372380 def _appliance_info_finder (self , appl : Munch , appliance : etree ) -> Munch :
373- """Collect device info (Smile/Stretch, Thermostats, OpenTherm/On-Off): firmware, model and vendor name ."""
381+ """Collect info for all appliances found ."""
374382 match appl .pwclass :
375383 case "gateway" :
376384 # Collect gateway device info
@@ -382,45 +390,28 @@ def _appliance_info_finder(self, appl: Munch, appliance: etree) -> Munch:
382390 # Collect heater_central device info
383391 self ._appl_heater_central_info (appl , appliance , False ) # False means non-legacy device
384392 self ._appl_dhw_mode_info (appl , appliance )
393+ # Skip orphaned heater_central (Core Issue #104433)
394+ if appl .dev_id != self ._heater_id :
395+ return Munch ()
396+ return appl
397+ case _ as s if s .endswith ("_plug" ):
398+ # Collect info from plug-types (Plug, Aqara Smart Plug)
399+ locator = "./logs/interval_log/electricity_interval_meter"
400+ mod_type = "electricity_interval_meter"
401+ module_data = self ._get_module_data (appliance , locator , mod_type )
402+ # A plug without module-data is orphaned/ no present
403+ if not module_data ["contents" ]:
404+ return Munch ()
405+
406+ appl .firmware = module_data ["firmware_version" ]
407+ appl .hardware = module_data ["hardware_version" ]
408+ appl .model_id = module_data ["vendor_model" ]
409+ appl .vendor_name = module_data ["vendor_name" ]
410+ appl .model = check_model (appl .model_id , appl .vendor_name )
411+ appl .zigbee_mac = module_data ["zigbee_mac_address" ]
412+ return appl
413+ case _: # pragma: no cover
385414 return appl
386- case _:
387- # Collect info from power-related devices (Plug, Aqara Smart Plug)
388- return self ._energy_device_info_finder (appl , appliance )
389-
390- def _energy_device_info_finder (self , appl : Munch , appliance : etree ) -> Munch :
391- """Helper-function for _appliance_info_finder().
392-
393- Collect energy device info (Smartmeter): firmware, model and vendor name.
394- """
395- if self .smile_type == "power" :
396- locator = "./logs/point_log/electricity_point_meter"
397- mod_type = "electricity_point_meter"
398- module_data = self ._get_module_data (appliance , locator , mod_type )
399- appl .hardware = module_data ["hardware_version" ]
400- appl .model = module_data ["vendor_model" ] # don't use model_id for Smartmeter
401- appl .vendor_name = module_data ["vendor_name" ]
402- appl .firmware = module_data ["firmware_version" ]
403-
404- return appl
405-
406- if self .smile (ADAM ):
407- locator = "./logs/interval_log/electricity_interval_meter"
408- mod_type = "electricity_interval_meter"
409- module_data = self ._get_module_data (appliance , locator , mod_type )
410- # Filter appliance without zigbee_mac, it's an orphaned device
411- appl .zigbee_mac = module_data ["zigbee_mac_address" ]
412- if appl .zigbee_mac is None :
413- return None
414-
415- appl .vendor_name = module_data ["vendor_name" ]
416- appl .model_id = module_data ["vendor_model" ]
417- appl .model = check_model (appl .model_id , appl .vendor_name )
418- appl .hardware = module_data ["hardware_version" ]
419- appl .firmware = module_data ["firmware_version" ]
420-
421- return appl
422-
423- return appl # pragma: no cover
424415
425416 def _appl_gateway_info (self , appl : Munch , appliance : etree ) -> Munch :
426417 """Helper-function for _appliance_info_finder()."""
@@ -725,15 +716,18 @@ def _wireless_availability(self, appliance: etree, data: DeviceData) -> None:
725716 Collect the availability-status for wireless connected devices.
726717 """
727718 if self .smile (ADAM ):
728- # Collect for Plugs
719+ # Try collecting for a Plug
729720 locator = "./logs/interval_log/electricity_interval_meter"
730721 mod_type = "electricity_interval_meter"
731722 module_data = self ._get_module_data (appliance , locator , mod_type )
732- if module_data ["reachable" ] is None :
733- # Collect for wireless thermostats
723+ if not module_data ["contents" ] :
724+ # Try collecting for a wireless thermostat
734725 locator = "./logs/point_log[type='thermostat']/thermostat"
735726 mod_type = "thermostat"
736727 module_data = self ._get_module_data (appliance , locator , mod_type )
728+ if not module_data ["contents" ]:
729+ LOGGER .error ("No module data found for Plug or wireless thermostat" ) # pragma: no cover
730+ return None # pragma: no cover
737731
738732 if module_data ["reachable" ] is not None :
739733 data ["available" ] = module_data ["reachable" ]
0 commit comments