custom_components/whatsapp_bridge_integration/sensor.py aktualisiert
0.2.0
This commit is contained in:
@@ -1,18 +1,62 @@
|
|||||||
|
import logging
|
||||||
|
import async_timeout
|
||||||
|
import aiohttp
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant.components.sensor import SensorEntity
|
from homeassistant.components.sensor import SensorEntity
|
||||||
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
from .const import DOMAIN
|
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):
|
async def async_setup_entry(hass, entry, async_add_entities):
|
||||||
"""Add sensors for WhatsApp accounts and a global broadcast sensor."""
|
"""Add sensors for WhatsApp accounts, live status, and a global broadcast sensor."""
|
||||||
entities = [WhatsAppAccountEntity(entry)]
|
|
||||||
|
|
||||||
# Wir prüfen, ob die Broadcast-Entität schon existiert
|
# Coordinator für den echten Live-Status vom Add-on einrichten
|
||||||
# Falls nicht, legen wir sie einmalig an
|
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"):
|
if not hass.data[DOMAIN].get("broadcast_registered"):
|
||||||
entities.append(WhatsAppBroadcastEntity())
|
entities.append(WhatsAppBroadcastEntity())
|
||||||
hass.data[DOMAIN]["broadcast_registered"] = True
|
hass.data[DOMAIN]["broadcast_registered"] = True
|
||||||
|
|
||||||
async_add_entities(entities, True)
|
async_add_entities(entities, True)
|
||||||
|
|
||||||
|
|
||||||
class WhatsAppAccountEntity(SensorEntity):
|
class WhatsAppAccountEntity(SensorEntity):
|
||||||
"""Individual Account (e.g., Rene, Work)."""
|
"""Individual Account (e.g., Rene, Work)."""
|
||||||
def __init__(self, entry):
|
def __init__(self, entry):
|
||||||
@@ -29,6 +73,14 @@ class WhatsAppAccountEntity(SensorEntity):
|
|||||||
def state(self):
|
def state(self):
|
||||||
return "Ready"
|
return "Ready"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_info(self) -> DeviceInfo:
|
||||||
|
"""Ordnet diesen Sensor dem Hauptgerät zu."""
|
||||||
|
return DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, "general_gateway")},
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class WhatsAppBroadcastEntity(SensorEntity):
|
class WhatsAppBroadcastEntity(SensorEntity):
|
||||||
"""Virtual 'All Accounts' Entity."""
|
"""Virtual 'All Accounts' Entity."""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -41,4 +93,70 @@ class WhatsAppBroadcastEntity(SensorEntity):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
return "Global"
|
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)
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user