From d2b8d165d7a87df67d64097c16587d94e7503457 Mon Sep 17 00:00:00 2001 From: Willem-Jan van Rootselaar Date: Tue, 13 Jan 2026 16:07:33 +0100 Subject: [PATCH] Optimize BSB-Lan integration startup (#160784) --- homeassistant/components/bsblan/__init__.py | 19 +++++---- .../components/bsblan/coordinator.py | 39 +++++++++---------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/homeassistant/components/bsblan/__init__.py b/homeassistant/components/bsblan/__init__.py index eaa0c1eebb6..1abe376826b 100644 --- a/homeassistant/components/bsblan/__init__.py +++ b/homeassistant/components/bsblan/__init__.py @@ -1,5 +1,6 @@ """The BSB-Lan integration.""" +import asyncio import dataclasses from bsblan import ( @@ -77,12 +78,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: BSBLanConfigEntry) -> bo bsblan = BSBLAN(config, session) try: - # Initialize the client first - this sets up internal caches and validates the connection + # Initialize the client first - this sets up internal caches and validates + # the connection by fetching firmware version await bsblan.initialize() - # Fetch all required device metadata - device = await bsblan.device() - info = await bsblan.info() - static = await bsblan.static_values() + + # Fetch device metadata in parallel for faster startup + device, info, static = await asyncio.gather( + bsblan.device(), + bsblan.info(), + bsblan.static_values(), + ) except BSBLANConnectionError as err: raise ConfigEntryNotReady( translation_domain=DOMAIN, @@ -110,10 +115,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: BSBLanConfigEntry) -> bo fast_coordinator = BSBLanFastCoordinator(hass, entry, bsblan) slow_coordinator = BSBLanSlowCoordinator(hass, entry, bsblan) - # Perform first refresh of both coordinators + # Perform first refresh of fast coordinator (required for entities) await fast_coordinator.async_config_entry_first_refresh() - # Try to refresh slow coordinator, but don't fail if DHW is not available + # Refresh slow coordinator - don't fail if DHW is not available # This allows the integration to work even if the device doesn't support DHW await slow_coordinator.async_refresh() diff --git a/homeassistant/components/bsblan/coordinator.py b/homeassistant/components/bsblan/coordinator.py index 6b1ae70b338..b39376f6f02 100644 --- a/homeassistant/components/bsblan/coordinator.py +++ b/homeassistant/components/bsblan/coordinator.py @@ -2,7 +2,6 @@ from dataclasses import dataclass from datetime import timedelta -from random import randint from bsblan import ( BSBLAN, @@ -23,6 +22,17 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, Upda from .const import DOMAIN, LOGGER, SCAN_INTERVAL_FAST, SCAN_INTERVAL_SLOW +# Filter lists for optimized API calls - only fetch parameters we actually use +# This significantly reduces response time (~0.2s per parameter saved) +STATE_INCLUDE = ["current_temperature", "target_temperature", "hvac_mode"] +SENSOR_INCLUDE = ["current_temperature", "outside_temperature"] +DHW_STATE_INCLUDE = [ + "operating_mode", + "nominal_setpoint", + "dhw_actual_value_top_temperature", +] +DHW_CONFIG_INCLUDE = ["reduced_setpoint", "nominal_setpoint_max"] + @dataclass class BSBLanFastData: @@ -80,26 +90,18 @@ class BSBLanFastCoordinator(BSBLanCoordinator[BSBLanFastData]): config_entry, client, name=f"{DOMAIN}_fast_{config_entry.data[CONF_HOST]}", - update_interval=self._get_update_interval(), + update_interval=SCAN_INTERVAL_FAST, ) - def _get_update_interval(self) -> timedelta: - """Get the update interval with a random offset. - - Add a random number of seconds to avoid timeouts when - the BSB-Lan device is already/still busy retrieving data, - e.g. for MQTT or internal logging. - """ - return SCAN_INTERVAL_FAST + timedelta(seconds=randint(1, 8)) - async def _async_update_data(self) -> BSBLanFastData: """Fetch fast-changing data from the BSB-Lan device.""" try: # Client is already initialized in async_setup_entry - # Fetch fast-changing data (state, sensor, DHW state) - state = await self.client.state() - sensor = await self.client.sensor() - dhw = await self.client.hot_water_state() + # Use include filtering to only fetch parameters we actually use + # This reduces response time significantly (~0.2s per parameter) + state = await self.client.state(include=STATE_INCLUDE) + sensor = await self.client.sensor(include=SENSOR_INCLUDE) + dhw = await self.client.hot_water_state(include=DHW_STATE_INCLUDE) except BSBLANAuthError as err: raise ConfigEntryAuthFailed( @@ -111,9 +113,6 @@ class BSBLanFastCoordinator(BSBLanCoordinator[BSBLanFastData]): f"Error while establishing connection with BSB-Lan device at {host}" ) from err - # Update the interval with random jitter for next update - self.update_interval = self._get_update_interval() - return BSBLanFastData( state=state, sensor=sensor, @@ -143,8 +142,8 @@ class BSBLanSlowCoordinator(BSBLanCoordinator[BSBLanSlowData]): """Fetch slow-changing data from the BSB-Lan device.""" try: # Client is already initialized in async_setup_entry - # Fetch slow-changing configuration data - dhw_config = await self.client.hot_water_config() + # Use include filtering to only fetch parameters we actually use + dhw_config = await self.client.hot_water_config(include=DHW_CONFIG_INCLUDE) dhw_schedule = await self.client.hot_water_schedule() except AttributeError: