@@ -75,7 +75,7 @@ def update_helper(
7575 device_id : str ,
7676 bsssw_type : str ,
7777 key : str ,
78- notifs : dict [str , str ],
78+ notifs : dict [str , dict [ str , str ] ],
7979) -> None :
8080 """Helper-function for async_update()."""
8181 for item in device_dict [bsssw_type ]: # type: ignore [literal-required]
@@ -323,17 +323,21 @@ def __init__(self) -> None:
323323 self ._home_location : str
324324 self ._is_thermostat = False
325325 self ._last_active : dict [str , str | None ] = {}
326+ self ._last_modified : dict [str , str ] = {}
326327 self ._locations : etree
327328 self ._loc_data : dict [str , ThermoLoc ] = {}
328329 self ._modules : etree
330+ self ._notifications : dict [str , dict [str , str ]] = {}
329331 self ._on_off_device = False
330332 self ._opentherm_device = False
331333 self ._outdoor_temp : float
332334 self ._schedule_old_states : dict [str , dict [str , str ]] = {}
333335 self ._sched_setpoints : list [float ] | None = None
334336 self ._smile_legacy = False
337+ self ._status : etree
335338 self ._stretch_v2 = False
336339 self ._stretch_v3 = False
340+ self ._system : etree
337341 self ._thermo_locs : dict [str , ThermoLoc ] = {}
338342 ###################################################################
339343 # '_elga_cooling_enabled' refers to the state of the Elga heatpump
@@ -375,9 +379,7 @@ def _locations_legacy(self) -> None:
375379 for appliance in self ._appliances .findall ("./appliance" ):
376380 appliances .add (appliance .attrib ["id" ])
377381
378- if self .smile_type == "thermostat" :
379- self ._loc_data [FAKE_LOC ] = {"name" : "Home" }
380- if self .smile_type == "stretch" :
382+ if self .smile_type in ("stretch" , "thermostat" ):
381383 self ._loc_data [FAKE_LOC ] = {"name" : "Home" }
382384
383385 def _locations_specials (self , loc : Munch , location : str ) -> Munch :
@@ -436,6 +438,7 @@ def _get_module_data(
436438 "hardware_version" : None ,
437439 "firmware_version" : None ,
438440 "zigbee_mac_address" : None ,
441+ "available" : None ,
439442 }
440443 if (appl_search := appliance .find (locator )) is not None :
441444 link_id = appl_search .attrib ["id" ]
@@ -453,6 +456,7 @@ def _get_module_data(
453456 # Adam
454457 if found := module .find ("./protocols/zig_bee_node" ):
455458 model_data ["zigbee_mac_address" ] = found .find ("mac_address" ).text
459+ model_data ["available" ] = found .find ("reachable" ).text == "true"
456460 # Stretches
457461 if found := module .find ("./protocols/network_router" ):
458462 model_data ["zigbee_mac_address" ] = found .find ("mac_address" ).text
@@ -801,10 +805,6 @@ def _presets(self, loc_id: str) -> dict[str, list[float]]:
801805 float (preset .get ("cooling_setpoint" )),
802806 ]
803807
804- # Adam does not show vacation preset anymore, issue #185
805- if self .smile_name == "Adam" :
806- presets .pop ("vacation" )
807-
808808 return presets
809809
810810 def _rule_ids_by_name (self , name : str , loc_id : str ) -> dict [str , str ]:
@@ -882,6 +882,24 @@ def _appliance_measurements(
882882
883883 return data
884884
885+ def _wireless_availablity (self , appliance : etree , data : DeviceData ) -> None :
886+ """Helper-function for _get_appliance_data().
887+ Collect the availablity-status for wireless connected devices.
888+ """
889+ if self .smile_name == "Adam" :
890+ # Collect for Plugs
891+ locator = "./logs/interval_log/electricity_interval_meter"
892+ mod_type = "electricity_interval_meter"
893+ module_data = self ._get_module_data (appliance , locator , mod_type )
894+ if module_data ["available" ] is None :
895+ # Collect for wireless thermostats
896+ locator = "./logs/point_log[type='thermostat']/thermostat"
897+ mod_type = "thermostat"
898+ module_data = self ._get_module_data (appliance , locator , mod_type )
899+
900+ if module_data ["available" ] is not None :
901+ data ["available" ] = module_data ["available" ]
902+
885903 def _get_appliance_data (self , d_id : str ) -> DeviceData :
886904 """Helper-function for smile.py: _get_device_data().
887905 Collect the appliance-data based on device id.
@@ -899,12 +917,22 @@ def _get_appliance_data(self, d_id: str) -> DeviceData:
899917 if (
900918 appliance := self ._appliances .find (f'./appliance[@id="{ d_id } "]' )
901919 ) is not None :
920+
902921 data = self ._appliance_measurements (appliance , data , measurements )
903922 data .update (self ._get_lock_state (appliance ))
904923 if (appl_type := appliance .find ("type" )) is not None :
905924 if appl_type .text in ACTUATOR_CLASSES :
906925 data .update (_get_actuator_functionalities (appliance ))
907926
927+ # Collect availability-status for wireless connected devices to Adam
928+ self ._wireless_availablity (appliance , data )
929+
930+ # Collect modified_date for devices without available-status
931+ if not self ._smile_legacy and (
932+ d_id != self .gateway_id or "available" not in data
933+ ):
934+ data ["modified" ] = appliance .find ("modified_date" ).text
935+
908936 # Remove c_heating_state from the output
909937 if "c_heating_state" in data :
910938 # Anna + Elga and Adam + OnOff heater/cooler don't use intended_cental_heating_state
@@ -1069,7 +1097,7 @@ def _heating_valves(self) -> int | None:
10691097
10701098 return None if loc_found == 0 else open_valve_count
10711099
1072- def _power_data_peak_value (self , loc : Munch ) -> Munch :
1100+ def _power_data_peak_value (self , direct_data : DeviceData , loc : Munch ) -> Munch :
10731101 """Helper-function for _power_data_from_location()."""
10741102 loc .found = True
10751103 no_tariffs = False
@@ -1129,7 +1157,7 @@ def _power_data_from_location(self, loc_id: str) -> DeviceData:
11291157 f'./{ loc .log_type } [type="{ loc .measurement } "]/period/'
11301158 f'measurement[@{ t_string } ="{ loc .peak_select } "]'
11311159 )
1132- loc = self ._power_data_peak_value (loc )
1160+ loc = self ._power_data_peak_value (direct_data , loc )
11331161 if not loc .found :
11341162 continue
11351163
0 commit comments