from __future__ import annotations from datetime import datetime, timezone import logging from time import perf_counter from app.clients.base import BaseHTTPClient from app.config import Settings from app.models.sources import HomeAssistantSnapshot logger = logging.getLogger(__name__) class HomeAssistantClient(BaseHTTPClient): def __init__(self, settings: Settings) -> None: super().__init__(settings, "home-assistant", settings.home_assistant_base_url) async def fetch_status(self) -> HomeAssistantSnapshot: snapshot = HomeAssistantSnapshot() if not self.base_url or not self.settings.home_assistant_token: logger.info("home assistant skipped: base URL or token missing") return snapshot headers = { "Authorization": f"Bearer {self.settings.home_assistant_token}", "Content-Type": "application/json", } started_at = perf_counter() api_info = await self._request_json("GET", "/api/", headers=headers) logger.info("home assistant raw /api/ response: %s", api_info) elapsed_ms = int((perf_counter() - started_at) * 1000) config = await self._request_json("GET", "/api/config", headers=headers) logger.info("home assistant raw /api/config response: %s", config) version = None if isinstance(config, dict): version = config.get("version") # Fetch entity states for widget counts lights_on = 0 lights_total = 0 climate_active = 0 doors_open = 0 alerts = 0 try: states = await self._request_json("GET", "/api/states", headers=headers) if isinstance(states, list): for entity in states: eid = entity.get("entity_id", "") state = entity.get("state", "") if eid.startswith("light."): lights_total += 1 if state == "on": lights_on += 1 elif eid.startswith("climate."): if state not in ("off", "unavailable", "unknown"): climate_active += 1 elif eid.startswith("binary_sensor.") and "door" in eid: if state == "on": doors_open += 1 elif eid.startswith("persistent_notification."): if state == "notifying": alerts += 1 except Exception as exc: logger.warning("home assistant fetch states failed: %s", exc) normalized = HomeAssistantSnapshot( status="online", version=str(version) if version else None, response_time_ms=elapsed_ms, last_checked=datetime.now(timezone.utc), lights_on=lights_on, lights_total=lights_total, climate_active=climate_active, doors_open=doors_open, alerts=alerts, ) logger.info("home assistant normalized snapshot: %s", normalized.model_dump()) return normalized