88    BSBLAN ,
99    BSBLANAuthError ,
1010    BSBLANConnectionError ,
11+     HotWaterConfig ,
12+     HotWaterSchedule ,
1113    HotWaterState ,
1214    Sensor ,
1315    State ,
1921from  homeassistant .exceptions  import  ConfigEntryAuthFailed 
2022from  homeassistant .helpers .update_coordinator  import  DataUpdateCoordinator , UpdateFailed 
2123
22- from  .const  import  DOMAIN , LOGGER , SCAN_INTERVAL 
24+ from  .const  import  DOMAIN , LOGGER , SCAN_INTERVAL_FAST ,  SCAN_INTERVAL_SLOW 
2325
2426
2527@dataclass  
26- class  BSBLanCoordinatorData :
27-     """BSBLan data stored in the Home Assistant  data object .""" 
28+ class  BSBLanFastData :
29+     """BSBLan fast-polling  data.""" 
2830
2931    state : State 
3032    sensor : Sensor 
3133    dhw : HotWaterState 
3234
3335
34- class  BSBLanUpdateCoordinator (DataUpdateCoordinator [BSBLanCoordinatorData ]):
35-     """The BSB-Lan update coordinator.""" 
36+ @dataclass  
37+ class  BSBLanSlowData :
38+     """BSBLan slow-polling data.""" 
39+ 
40+     dhw_config : HotWaterConfig  |  None  =  None 
41+     dhw_schedule : HotWaterSchedule  |  None  =  None 
42+ 
43+ 
44+ class  BSBLanCoordinator [T ](DataUpdateCoordinator [T ]):
45+     """Base BSB-Lan coordinator.""" 
3646
3747    config_entry : ConfigEntry 
3848
@@ -41,44 +51,122 @@ def __init__(
4151        hass : HomeAssistant ,
4252        config_entry : ConfigEntry ,
4353        client : BSBLAN ,
54+         name : str ,
55+         update_interval : timedelta ,
4456    ) ->  None :
4557        """Initialize the BSB-Lan coordinator.""" 
4658        super ().__init__ (
4759            hass ,
4860            logger = LOGGER ,
4961            config_entry = config_entry ,
50-             name = f" { DOMAIN } _ { config_entry . data [ CONF_HOST ] } " 
51-             update_interval = self . _get_update_interval () ,
62+             name = name ,
63+             update_interval = update_interval ,
5264        )
5365        self .client  =  client 
5466
67+ 
68+ class  BSBLanFastCoordinator (BSBLanCoordinator [BSBLanFastData ]):
69+     """The BSB-Lan fast update coordinator for frequently changing data.""" 
70+ 
71+     def  __init__ (
72+         self ,
73+         hass : HomeAssistant ,
74+         config_entry : ConfigEntry ,
75+         client : BSBLAN ,
76+     ) ->  None :
77+         """Initialize the BSB-Lan fast coordinator.""" 
78+         super ().__init__ (
79+             hass ,
80+             config_entry ,
81+             client ,
82+             name = f"{ DOMAIN } { config_entry .data [CONF_HOST ]}  ,
83+             update_interval = self ._get_update_interval (),
84+         )
85+ 
5586    def  _get_update_interval (self ) ->  timedelta :
5687        """Get the update interval with a random offset. 
5788
58-         Use the default scan interval and add  a random number of seconds to avoid timeouts when 
89+         Add  a random number of seconds to avoid timeouts when 
5990        the BSB-Lan device is already/still busy retrieving data, 
6091        e.g. for MQTT or internal logging. 
6192        """ 
62-         return  SCAN_INTERVAL  +  timedelta (seconds = randint (1 , 8 ))
93+         return  SCAN_INTERVAL_FAST  +  timedelta (seconds = randint (1 , 8 ))
6394
64-     async  def  _async_update_data (self ) ->  BSBLanCoordinatorData :
65-         """Get state and sensor  data from BSB-Lan device.""" 
95+     async  def  _async_update_data (self ) ->  BSBLanFastData :
96+         """Fetch fast-changing  data from the  BSB-Lan device.""" 
6697        try :
67-             # initialize the client, this is cached and will only be called once 
68-             await  self .client .initialize ()
69- 
98+             # Client is already initialized in async_setup_entry 
99+             # Fetch fast-changing data (state, sensor, DHW state) 
70100            state  =  await  self .client .state ()
71101            sensor  =  await  self .client .sensor ()
72102            dhw  =  await  self .client .hot_water_state ()
103+ 
73104        except  BSBLANAuthError  as  err :
74105            raise  ConfigEntryAuthFailed (
75106                "Authentication failed for BSB-Lan device" 
76107            ) from  err 
77108        except  BSBLANConnectionError  as  err :
78-             host  =  self .config_entry .data [CONF_HOST ]  if   self . config_entry   else   "unknown" 
109+             host  =  self .config_entry .data [CONF_HOST ]
79110            raise  UpdateFailed (
80111                f"Error while establishing connection with BSB-Lan device at { host }  
81112            ) from  err 
82113
114+         # Update the interval with random jitter for next update 
83115        self .update_interval  =  self ._get_update_interval ()
84-         return  BSBLanCoordinatorData (state = state , sensor = sensor , dhw = dhw )
116+ 
117+         return  BSBLanFastData (
118+             state = state ,
119+             sensor = sensor ,
120+             dhw = dhw ,
121+         )
122+ 
123+ 
124+ class  BSBLanSlowCoordinator (BSBLanCoordinator [BSBLanSlowData ]):
125+     """The BSB-Lan slow update coordinator for infrequently changing data.""" 
126+ 
127+     def  __init__ (
128+         self ,
129+         hass : HomeAssistant ,
130+         config_entry : ConfigEntry ,
131+         client : BSBLAN ,
132+     ) ->  None :
133+         """Initialize the BSB-Lan slow coordinator.""" 
134+         super ().__init__ (
135+             hass ,
136+             config_entry ,
137+             client ,
138+             name = f"{ DOMAIN } { config_entry .data [CONF_HOST ]}  ,
139+             update_interval = SCAN_INTERVAL_SLOW ,
140+         )
141+ 
142+     async  def  _async_update_data (self ) ->  BSBLanSlowData :
143+         """Fetch slow-changing data from the BSB-Lan device.""" 
144+         try :
145+             # Client is already initialized in async_setup_entry 
146+             # Fetch slow-changing configuration data 
147+             dhw_config  =  await  self .client .hot_water_config ()
148+             dhw_schedule  =  await  self .client .hot_water_schedule ()
149+ 
150+         except  AttributeError :
151+             # Device does not support DHW functionality 
152+             LOGGER .debug (
153+                 "DHW (Domestic Hot Water) not available on device at %s" ,
154+                 self .config_entry .data [CONF_HOST ],
155+             )
156+             return  BSBLanSlowData ()
157+         except  (BSBLANConnectionError , BSBLANAuthError ) as  err :
158+             # If config update fails, keep existing data 
159+             LOGGER .debug (
160+                 "Failed to fetch DHW config from %s: %s" ,
161+                 self .config_entry .data [CONF_HOST ],
162+                 err ,
163+             )
164+             if  self .data :
165+                 return  self .data 
166+             # First fetch failed, return empty data 
167+             return  BSBLanSlowData ()
168+ 
169+         return  BSBLanSlowData (
170+             dhw_config = dhw_config ,
171+             dhw_schedule = dhw_schedule ,
172+         )
0 commit comments