44"""
55from __future__ import annotations
66
7+ import datetime as dt
8+
79import aiohttp
810from defusedxml import ElementTree as etree
911
3436 ZONE_THERMOSTATS ,
3537 ActuatorData ,
3638 DeviceData ,
39+ GatewayData ,
3740 PlugwiseData ,
3841)
3942from .exceptions import (
@@ -85,29 +88,46 @@ def update_for_cooling(self, device: DeviceData) -> DeviceData:
8588
8689 return device
8790
88- def _all_device_data (self ) -> None :
89- """Helper-function for get_all_devices ().
91+ def _update_gw_devices (self ) -> None :
92+ """Helper-function for _all_device_data() and async_update ().
9093
91- Collect data for each device and add to self.gw_data and self. gw_devices.
94+ Collect data for each device and add to self.gw_devices.
9295 """
9396 for device_id , device in self .gw_devices .items ():
9497 data = self ._get_device_data (device_id )
95- device .update (data )
96- # Add plugwise notification binary_sensor to the relevant gateway
97- if device_id == self .gateway_id and (
98- self ._is_thermostat
99- or (not self ._smile_legacy and self .smile_type == "power" )
98+ if (
99+ "binary_sensors" in device
100+ and "plugwise_notification" in device ["binary_sensors" ]
101+ ) or (
102+ device_id == self .gateway_id
103+ and (
104+ self ._is_thermostat
105+ or (self .smile_type == "power" and not self ._smile_legacy )
106+ )
100107 ):
101- device ["binary_sensors" ]["plugwise_notification" ] = False
108+ data ["binary_sensors" ]["plugwise_notification" ] = bool (
109+ self ._notifications
110+ )
111+ device .update (data )
102112
103113 # Update for cooling
104114 if device ["dev_class" ] in ZONE_THERMOSTATS :
105115 self .update_for_cooling (device )
106116
107117 remove_empty_platform_dicts (device )
108118
119+ def _all_device_data (self ) -> None :
120+ """Helper-function for get_all_devices().
121+
122+ Collect data for each device and add to self.gw_data and self.gw_devices.
123+ """
124+ self ._update_gw_devices ()
109125 self .gw_data .update (
110- {"smile_name" : self .smile_name , "gateway_id" : self .gateway_id }
126+ {
127+ "smile_name" : self .smile_name ,
128+ "gateway_id" : self .gateway_id ,
129+ "notifications" : self ._notifications ,
130+ }
111131 )
112132 if self ._is_thermostat :
113133 self .gw_data .update (
@@ -318,6 +338,7 @@ def __init__(
318338 SmileData .__init__ (self )
319339
320340 self .smile_hostname : str | None = None
341+ self ._previous_day_number : str = "0"
321342 self ._target_smile : str | None = None
322343
323344 async def connect (self ) -> bool :
@@ -473,15 +494,6 @@ async def _smile_detect(self, result: etree, dsmrmain: etree) -> None:
473494 if result .find (locator_2 ) is not None :
474495 self ._elga = True
475496
476- async def _full_update_device (self ) -> None :
477- """Perform a first fetch of all XML data, needed for initialization."""
478- await self ._update_domain_objects ()
479- self ._locations = await self ._request (LOCATIONS )
480- self ._modules = await self ._request (MODULES )
481- # P1 legacy has no appliances
482- if not (self .smile_type == "power" and self ._smile_legacy ):
483- self ._appliances = await self ._request (APPLIANCES )
484-
485497 async def _update_domain_objects (self ) -> None :
486498 """Helper-function for smile.py: full_update_device() and async_update().
487499
@@ -504,39 +516,48 @@ async def _update_domain_objects(self) -> None:
504516 f"{ self ._endpoint } { DOMAIN_OBJECTS } " ,
505517 )
506518
507- async def async_update (self ) -> PlugwiseData :
508- """Perform an incremental update for updating the various device states ."""
519+ async def _full_update_device (self ) -> None :
520+ """Perform a first fetch of all XML data, needed for initialization ."""
509521 await self ._update_domain_objects ()
510- match self ._target_smile :
511- case "smile_v2" :
512- self ._modules = await self ._request (MODULES )
513- case "smile_v3" | "smile_v4" :
514- self ._locations = await self ._request (LOCATIONS )
515- case "smile_open_therm_v2" | "smile_open_therm_v3" :
516- self ._appliances = await self ._request (APPLIANCES )
517- self ._modules = await self ._request (MODULES )
518- case self ._target_smile if self ._target_smile in REQUIRE_APPLIANCES :
519- self ._appliances = await self ._request (APPLIANCES )
520-
521- self .gw_data ["notifications" ] = self ._notifications
522-
523- for device_id , device in self .gw_devices .items ():
524- data = self ._get_device_data (device_id )
525- if (
526- "binary_sensors" in device
527- and "plugwise_notification" in device ["binary_sensors" ]
528- ):
529- data ["binary_sensors" ]["plugwise_notification" ] = bool (
530- self ._notifications
531- )
532- device .update (data )
533-
534- # Update for cooling
535- if device ["dev_class" ] in ZONE_THERMOSTATS :
536- self .update_for_cooling (device )
537-
538- remove_empty_platform_dicts (device )
522+ self ._locations = await self ._request (LOCATIONS )
523+ self ._modules = await self ._request (MODULES )
524+ # P1 legacy has no appliances
525+ if not (self .smile_type == "power" and self ._smile_legacy ):
526+ self ._appliances = await self ._request (APPLIANCES )
539527
528+ async def async_update (self ) -> PlugwiseData :
529+ """Perform an incremental update for updating the various device states."""
530+ # Perform a full update at day-change
531+ day_number = dt .datetime .now ().strftime ("%w" )
532+ if (
533+ day_number # pylint: disable=consider-using-assignment-expr
534+ != self ._previous_day_number
535+ ):
536+ LOGGER .debug (
537+ "Performing daily full-update, reload the Plugwise integration when a single entity becomes unavailable."
538+ )
539+ self .gw_data : GatewayData = {}
540+ self .gw_devices : dict [str , DeviceData ] = {}
541+ await self ._full_update_device ()
542+ self .get_all_devices ()
543+ # Otherwise perform an incremental update
544+ else :
545+ await self ._update_domain_objects ()
546+ match self ._target_smile :
547+ case "smile_v2" :
548+ self ._modules = await self ._request (MODULES )
549+ case "smile_v3" | "smile_v4" :
550+ self ._locations = await self ._request (LOCATIONS )
551+ case "smile_open_therm_v2" | "smile_open_therm_v3" :
552+ self ._appliances = await self ._request (APPLIANCES )
553+ self ._modules = await self ._request (MODULES )
554+ case self ._target_smile if self ._target_smile in REQUIRE_APPLIANCES :
555+ self ._appliances = await self ._request (APPLIANCES )
556+
557+ self ._update_gw_devices ()
558+ self .gw_data ["notifications" ] = self ._notifications
559+
560+ self ._previous_day_number = day_number
540561 return PlugwiseData (self .gw_data , self .gw_devices )
541562
542563 async def _set_schedule_state_legacy (
0 commit comments