import logging import async_timeout import aiohttp from datetime import timedelta from homeassistant.components.sensor import SensorEntity from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from .const import DOMAIN _LOGGER = logging.getLogger(__name__) # Polling-Intervall (15 Sekunden) SCAN_INTERVAL = timedelta(seconds=15) async def async_setup_entry(hass, entry, async_add_entities): """Add sensors for WhatsApp accounts, live status, and a global broadcast sensor.""" # Coordinator für den echten Live-Status vom Add-on einrichten async def _async_update_data(): url = "http://866fd2eb-whatsapp-bridge:3000/api/status" async with aiohttp.ClientSession() as session: try: async with async_timeout.timeout(5): async with session.get(url) as response: if response.status != 200: raise UpdateFailed(f"API meldet Fehler {response.status}") return await response.json() except Exception as err: raise UpdateFailed(f"Add-on nicht erreichbar: {err}") coordinator = DataUpdateCoordinator( hass, _LOGGER, name="whatsapp_bridge_status", update_method=_async_update_data, update_interval=SCAN_INTERVAL, ) # Ersten Abruf vor dem Erstellen der Entitäten erzwingen try: await coordinator.async_config_entry_first_refresh() except UpdateFailed: _LOGGER.warning("Erster Status-Abruf fehlgeschlagen. Add-on läuft eventuell noch an.") # Basis-Entitäten: Account-Sensor und der neue Live-Status-Sensor entities = [ WhatsAppAccountEntity(entry), WhatsAppStatusSensor(coordinator, entry) ] # Prüfen, ob die Broadcast-Entität schon existiert if not hass.data[DOMAIN].get("broadcast_registered"): entities.append(WhatsAppBroadcastEntity()) hass.data[DOMAIN]["broadcast_registered"] = True async_add_entities(entities, True) class WhatsAppAccountEntity(SensorEntity): """Individual Account (e.g., Rene, Work).""" def __init__(self, entry): self._entry = entry self._attr_name = f"WhatsApp {entry.title}" self._attr_unique_id = f"{entry.entry_id}_status" self._attr_icon = "mdi:whatsapp" self._attr_extra_state_attributes = { "phone_number": entry.data.get("phone_number"), "is_broadcast": False } @property def state(self): return "Ready" @property def device_info(self) -> DeviceInfo: """Ordnet diesen Sensor dem Hauptgerät zu.""" return DeviceInfo( identifiers={(DOMAIN, "general_gateway")}, ) class WhatsAppBroadcastEntity(SensorEntity): """Virtual 'All Accounts' Entity.""" def __init__(self): self._attr_name = "WhatsApp Broadcast (All)" self._attr_unique_id = "whatsapp_bridge_broadcast_all" self._attr_icon = "mdi:whatsapp-arrow-up" self._attr_extra_state_attributes = { "is_broadcast": True } @property def state(self): return "Global" @property def device_info(self) -> DeviceInfo: """Ordnet diesen Sensor dem Hauptgerät zu.""" return DeviceInfo( identifiers={(DOMAIN, "general_gateway")}, ) class WhatsAppStatusSensor(SensorEntity): """Echter Live-Status-Sensor, gekoppelt an die Add-on API.""" def __init__(self, coordinator, entry): self.coordinator = coordinator self._entry = entry self._attr_name = "WhatsApp Bridge Status" self._attr_unique_id = f"{entry.entry_id}_bridge_live_status" self._attr_icon = "mdi:whatsapp" @property def should_poll(self) -> bool: return False @property def available(self) -> bool: return self.coordinator.last_update_success @property def state(self): """Gibt den dynamischen Status aus der Add-on API zurück.""" data = self.coordinator.data if not data: return "OFFLINE" if data.get("isReady"): return "CONNECTED" elif data.get("hasQr"): return "WAITING_FOR_SCAN" elif data.get("isInitializing"): return "INITIALIZING" return "UNKNOWN" @property def extra_state_attributes(self): """Zusätzliche Attribute für erweitertes Debugging.""" data = self.coordinator.data if data: return { "client_state": data.get("clientState", "UNKNOWN"), "has_qr_code": data.get("hasQr", False) } return {} @property def device_info(self) -> DeviceInfo: """Ordnet diesen Sensor dem Hauptgerät zu.""" return DeviceInfo( identifiers={(DOMAIN, "general_gateway")}, ) async def async_added_to_hass(self): """Registrieren beim Live-Coordinator.""" self.async_on_remove( self.coordinator.async_add_listener(self.async_write_ha_state) )