2828 DEVICE_MEASUREMENTS ,
2929 ENERGY_KILO_WATT_HOUR ,
3030 ENERGY_WATT_HOUR ,
31+ FAKE_APPL ,
3132 FAKE_LOC ,
3233 HEATER_CENTRAL_MEASUREMENTS ,
3334 LIMITS ,
@@ -90,9 +91,7 @@ def update_helper(
9091
9192def check_model (name : str | None , vendor_name : str | None ) -> str | None :
9293 """Model checking before using version_to_model."""
93- if vendor_name in ["Plugwise" , "Plugwise B.V." ]:
94- if name == "ThermoTouch" :
95- return "Anna"
94+ if vendor_name == "Plugwise" :
9695 if (model := version_to_model (name )) != "Unknown" :
9796 return model
9897 return name
@@ -353,12 +352,13 @@ def __init__(self) -> None:
353352 self ._lortherm_cooling_active = False
354353 self ._lortherm_cooling_enabled = False
355354
356- self .gateway_id : str
355+ self .gateway_id : str | None = None
357356 self .gw_data : GatewayData = {}
358357 self .gw_devices : dict [str , DeviceData ] = {}
359358 self .smile_fw_version : str | None = None
360359 self .smile_hw_version : str | None = None
361360 self .smile_mac_address : str | None = None
361+ self .smile_model : str
362362 self .smile_name : str
363363 self .smile_type : str
364364 self .smile_version : tuple [str , VersionInfo ]
@@ -445,6 +445,8 @@ def _get_module_data(
445445 if module is not None : # pylint: disable=consider-using-assignment-expr
446446 model_data ["contents" ] = True
447447 model_data ["vendor_name" ] = module .find ("vendor_name" ).text
448+ if model_data ["vendor_name" ] == "Plugwise B.V." :
449+ model_data ["vendor_name" ] = "Plugwise"
448450 model_data ["vendor_model" ] = module .find ("vendor_model" ).text
449451 model_data ["hardware_version" ] = module .find ("hardware_version" ).text
450452 model_data ["firmware_version" ] = module .find ("firmware_version" ).text
@@ -464,18 +466,21 @@ def _energy_device_info_finder(self, appliance: etree, appl: Munch) -> Munch | N
464466 """Helper-function for _appliance_info_finder().
465467 Collect energy device info (Circle, Plug, Stealth): firmware, model and vendor name.
466468 """
467- if self .smile_type == " stretch" :
469+ if self .smile_type in ( "power" , " stretch") :
468470 locator = "./services/electricity_point_meter"
471+ if not self ._smile_legacy :
472+ locator = "./logs/point_log/electricity_point_meter"
469473 mod_type = "electricity_point_meter"
470474
471475 module_data = self ._get_module_data (appliance , locator , mod_type )
472476 # Filter appliance without zigbee_mac, it's an orphaned device
473477 appl .zigbee_mac = module_data ["zigbee_mac_address" ]
474- if appl .zigbee_mac is None :
478+ if appl .zigbee_mac is None and self . smile_type != "power" :
475479 return None
476480
477- appl .vendor_name = module_data ["vendor_name" ]
478481 appl .hardware = module_data ["hardware_version" ]
482+ appl .model = module_data ["vendor_model" ]
483+ appl .vendor_name = module_data ["vendor_name" ]
479484 if appl .hardware is not None :
480485 hw_version = appl .hardware .replace ("-" , "" )
481486 appl .model = version_to_model (hw_version )
@@ -506,10 +511,12 @@ def _appliance_info_finder(self, appliance: etree, appl: Munch) -> Munch:
506511 # Collect gateway device info
507512 if appl .pwclass == "gateway" :
508513 self .gateway_id = appliance .attrib ["id" ]
509- appl .fw = self .smile_fw_version
514+ appl .firmware = self .smile_fw_version
515+ appl .hardware = self .smile_hw_version
510516 appl .mac = self .smile_mac_address
511- appl .model = appl .name = self .smile_name
512- appl .vendor_name = "Plugwise B.V."
517+ appl .model = self .smile_model
518+ appl .name = self .smile_name
519+ appl .vendor_name = "Plugwise"
513520
514521 # Adam: look for the ZigBee MAC address of the Smile
515522 if self .smile_name == "Adam" and (
@@ -580,54 +587,74 @@ def _appliance_info_finder(self, appliance: etree, appl: Munch) -> Munch:
580587
581588 return appl
582589
583- def _all_appliances (self ) -> None :
584- """Collect all appliances with relevant info."""
585- self ._all_locations ()
590+ def _p1_smartmeter_info_finder (self , appl : Munch ) -> Munch :
591+ """Collect P1 DSMR Smartmeter info."""
592+ loc_id = next (iter (self ._loc_data .keys ()))
593+ appl .dev_id = self .gateway_id
594+ appl .location = loc_id
595+ if self ._smile_legacy :
596+ appl .dev_id = loc_id
597+ appl .mac = None
598+ appl .model = self .smile_model
599+ appl .name = "P1"
600+ appl .pwclass = "smartmeter"
601+ appl .zigbee_mac = None
602+ location = self ._locations .find (f'./location[@id="{ loc_id } "]' )
603+ appl = self ._energy_device_info_finder (location , appl )
604+
605+ self ._appl_data [appl .dev_id ] = {"dev_class" : appl .pwclass }
606+
607+ for key , value in {
608+ "firmware" : appl .firmware ,
609+ "hardware" : appl .hardware ,
610+ "location" : appl .location ,
611+ "mac_address" : appl .mac ,
612+ "model" : appl .model ,
613+ "name" : appl .name ,
614+ "zigbee_mac_address" : appl .zigbee_mac ,
615+ "vendor" : appl .vendor_name ,
616+ }.items ():
617+ if value is not None or key == "location" :
618+ self ._appl_data [appl .dev_id ].update ({key : value }) # type: ignore[misc]
586619
587- # Create a gateway for legacy Anna, P1 and Stretches
588- # and inject a home_location as device id for legacy so
589- # appl_data can use the location id as device id, where needed.
620+ return appl
621+
622+ def _create_legacy_gateway (self ) -> None :
623+ """Create the (missing) gateway devices for legacy Anna, P1 and Stretch.
624+
625+ Use the home_location or FAKE_APPL as device id.
626+ """
590627 if self ._smile_legacy :
591628 self .gateway_id = self ._home_location
592- self ._appl_data [self ._home_location ] = {
593- "dev_class" : "gateway" ,
629+ if self .smile_type == "power" :
630+ self .gateway_id = FAKE_APPL
631+
632+ self ._appl_data [self .gateway_id ] = {"dev_class" : "gateway" }
633+ for key , value in {
594634 "firmware" : self .smile_fw_version ,
595635 "location" : self ._home_location ,
596- }
597- if self .smile_mac_address is not None :
598- self ._appl_data [self ._home_location ].update (
599- {"mac_address" : self .smile_mac_address }
600- )
636+ "mac_address" : self .smile_mac_address ,
637+ "model" : self .smile_model ,
638+ "name" : self .smile_name ,
639+ "zigbee_mac_address" : self .smile_zigbee_mac_address ,
640+ "vendor" : "Plugwise" ,
641+ }.items ():
642+ if value is not None :
643+ self ._appl_data [self .gateway_id ].update ({key : value }) # type: ignore[misc]
601644
602645 if self .smile_type == "power" :
603- self ._appl_data [self ._home_location ].update (
604- {
605- "model" : "P1" ,
606- "name" : "P1" ,
607- "vendor" : "Plugwise B.V." ,
608- }
609- )
610- # legacy p1 has no more devices
611- return
646+ # For legacy P1 collect the connected SmartMeter info
647+ appl = Munch ()
648+ appl = self ._p1_smartmeter_info_finder (appl )
612649
613- if self .smile_type == "thermostat" :
614- self ._appl_data [self ._home_location ].update (
615- {
616- "model" : "Smile" ,
617- "name" : "Smile" ,
618- "vendor" : "Plugwise B.V." ,
619- }
620- )
650+ def _all_appliances (self ) -> None :
651+ """Collect all appliances with relevant info."""
652+ self ._all_locations ()
621653
622- if self .smile_type == "stretch" :
623- self ._appl_data [self ._home_location ].update (
624- {
625- "model" : "Stretch" ,
626- "name" : "Stretch" ,
627- "vendor" : "Plugwise B.V." ,
628- "zigbee_mac_address" : self .smile_zigbee_mac_address ,
629- }
630- )
654+ self ._create_legacy_gateway ()
655+ # Legacy P1 has no more devices
656+ if self ._smile_legacy and self .smile_type == "power" :
657+ return
631658
632659 for appliance in self ._appliances .findall ("./appliance" ):
633660 appl = Munch ()
@@ -661,9 +688,10 @@ def _all_appliances(self) -> None:
661688 if (appl := self ._appliance_info_finder (appliance , appl )) is None :
662689 continue
663690
664- if appl .pwclass == "gateway" :
665- appl .firmware = self .smile_fw_version
666- appl .hardware = self .smile_hw_version
691+ # P1: for gateway and smartmeter switch device_id - part 1
692+ # This is done to avoid breakage in HA Core
693+ if appl .pwclass == "gateway" and self .smile_type == "power" :
694+ appl .dev_id = appl .location
667695
668696 # Don't show orphaned non-legacy thermostat-types.
669697 if (
@@ -674,7 +702,6 @@ def _all_appliances(self) -> None:
674702 continue
675703
676704 self ._appl_data [appl .dev_id ] = {"dev_class" : appl .pwclass }
677-
678705 for key , value in {
679706 "firmware" : appl .firmware ,
680707 "hardware" : appl .hardware ,
@@ -688,6 +715,16 @@ def _all_appliances(self) -> None:
688715 if value is not None or key == "location" :
689716 self ._appl_data [appl .dev_id ].update ({key : value }) # type: ignore[misc]
690717
718+ # For non-legacy P1 collect the connected SmartMeter info
719+ if self .smile_type == "power" :
720+ appl = self ._p1_smartmeter_info_finder (appl )
721+ # P1: for gateway and smartmeter switch device_id - part 2
722+ for item in self ._appl_data :
723+ if item != self .gateway_id :
724+ self .gateway_id = item
725+ # Leave for-loop to avoid a 2nd switch
726+ break
727+
691728 def _match_locations (self ) -> dict [str , ThermoLoc ]:
692729 """Helper-function for _scan_thermostats().
693730 Match appliances with locations.
@@ -887,7 +924,7 @@ def _get_appliance_data(self, d_id: str) -> DeviceData:
887924 if d_id == self ._heater_id :
888925 if self ._adam_cooling_enabled :
889926 data ["adam_cooling_enabled" ] = self ._adam_cooling_enabled
890- if self .smile_name == "Smile" :
927+ if self .smile_name == "Smile Anna " :
891928 # Use elga_status_code or cooling_state to set the relevant *_cooling_enabled to True
892929 if not self ._anna_cooling_present :
893930 pass
@@ -990,7 +1027,7 @@ def _group_switches(self) -> dict[str, ApplianceData]:
9901027 """
9911028 switch_groups : dict [str , ApplianceData ] = {}
9921029 # P1 and Anna don't have switchgroups
993- if self .smile_type == "power" or self .smile_name == "Smile" :
1030+ if self .smile_type == "power" or self .smile_name == "Smile Anna " :
9941031 return switch_groups
9951032
9961033 for group in self ._domain_objects .findall ("./group" ):
@@ -1076,9 +1113,6 @@ def _power_data_from_location(self, loc_id: str) -> DeviceData:
10761113 direct_data : DeviceData = {}
10771114 loc = Munch ()
10781115
1079- if self .smile_type != "power" :
1080- return {}
1081-
10821116 search = self ._locations
10831117 log_list : list [str ] = ["point_log" , "cumulative_log" , "interval_log" ]
10841118 peak_list : list [str ] = ["nl_peak" , "nl_offpeak" ]
0 commit comments