diff --git a/custom_components/bahmcloud_store/__init__.py b/custom_components/bahmcloud_store/__init__.py index 110ebf7..77c6c4e 100644 --- a/custom_components/bahmcloud_store/__init__.py +++ b/custom_components/bahmcloud_store/__init__.py @@ -6,48 +6,53 @@ from datetime import timedelta from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.components.panel_custom import async_register_panel -from homeassistant.helpers.event import async_track_time_interval, async_call_later from homeassistant.const import EVENT_HOMEASSISTANT_STARTED +from homeassistant.helpers.event import async_call_later, async_track_time_interval -from .core import BCSCore, BCSConfig, BCSError -from .config_flow import CONF_GITHUB_TOKEN +from .const import CONF_GITHUB_TOKEN, DEFAULT_STORE_URL, DOMAIN +from .core import BCSError, BCSConfig, BCSCore _LOGGER = logging.getLogger(__name__) -DOMAIN = "bahmcloud_store" - -# Fixed store index URL (not configurable by users) -DEFAULT_STORE_URL = "https://git.bahmcloud.de/bahmcloud/ha_store/raw/branch/main/store.yaml" - PLATFORMS: list[str] = ["update"] -DATA_ENTRY = f"{DOMAIN}_entry_runtime" - async def async_setup(hass: HomeAssistant, config: dict) -> bool: """Set up Bahmcloud Store. - YAML configuration is intentionally not supported. - Setup must happen via the UI (Config Flow). + We intentionally do NOT support YAML configuration. + This method is kept so we can log a helpful message if someone tries. """ if DOMAIN in (config or {}): _LOGGER.warning( - "BCS does not support configuration.yaml setup. " - "Please remove 'bahmcloud_store:' from configuration.yaml and set up the integration via Settings -> Devices & Services." + "BCS YAML configuration is no longer supported. " + "Please remove 'bahmcloud_store:' from configuration.yaml and set up the integration via the UI." ) return True async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: - """Set up Bahmcloud Store from a config entry.""" - token = (entry.options.get(CONF_GITHUB_TOKEN) or "").strip() or None + """Set up Bahmcloud Store from a config entry (UI setup).""" + # Only one instance. + hass.data.setdefault(DOMAIN, {}) - core = BCSCore(hass, BCSConfig(store_url=DEFAULT_STORE_URL, github_token=token)) - hass.data[DOMAIN] = core + github_token = (entry.options.get(CONF_GITHUB_TOKEN) or "").strip() or None + + core = BCSCore( + hass, + BCSConfig( + store_url=DEFAULT_STORE_URL, + github_token=github_token, + ), + ) + + hass.data[DOMAIN][entry.entry_id] = core + # Keep a convenient shortcut for platforms that previously used hass.data[DOMAIN] directly. + hass.data[DOMAIN]["_core"] = core await core.async_initialize() - # Register HTTP views + static assets + # HTTP views + panel (registered once per entry; we only allow one entry). from .views import ( StaticAssetsView, BCSApiView, @@ -78,7 +83,6 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: hass.http.register_view(BCSRestoreView(core)) hass.http.register_view(BCSRestartView(core)) - # Sidebar panel await async_register_panel( hass, frontend_url_path="bahmcloud-store", @@ -91,16 +95,13 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: config={}, ) - # Forward platform setup (Update entities) - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - async def _do_startup_refresh(_now=None) -> None: try: await core.full_refresh(source="startup") except BCSError as e: _LOGGER.error("Initial refresh failed: %s", e) - # Do not block HA startup: schedule refresh after HA started. + # Do not block startup; refresh after HA is up. def _on_ha_started(_event) -> None: async_call_later(hass, 30, _do_startup_refresh) @@ -115,30 +116,18 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: _LOGGER.exception("Unexpected error during periodic refresh: %s", e) interval_seconds = int(getattr(core, "refresh_seconds", 300) or 300) - unsub = async_track_time_interval(hass, periodic, timedelta(seconds=interval_seconds)) + async_track_time_interval(hass, periodic, timedelta(seconds=interval_seconds)) - # Store unload callbacks safely - runtimes = hass.data.setdefault(DATA_ENTRY, {}) - runtimes[entry.entry_id] = {"unsub_interval": unsub} + await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) return True async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Unload a config entry.""" - try: - runtimes = hass.data.get(DATA_ENTRY, {}) or {} - rt = runtimes.pop(entry.entry_id, {}) if isinstance(runtimes, dict) else {} - unsub = rt.get("unsub_interval") - if callable(unsub): - unsub() - except Exception: - pass - unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS) if unload_ok: - hass.data.pop(DOMAIN, None) + try: + hass.data.get(DOMAIN, {}).pop(entry.entry_id, None) + except Exception: + pass return unload_ok - - -async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: - await hass.config_entries.async_reload(entry.entry_id)