"""Sensor platform for LED Screen Controller.""" from __future__ import annotations import logging from typing import Any from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import ( DOMAIN, TARGET_TYPE_HA_LIGHT, DATA_COORDINATOR, ) from .coordinator import LedGrabCoordinator _LOGGER = logging.getLogger(__name__) async def async_setup_entry( hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up LED Screen Controller sensors.""" data = hass.data[DOMAIN][entry.entry_id] coordinator: LedGrabCoordinator = data[DATA_COORDINATOR] entities: list[SensorEntity] = [] if coordinator.data and "targets" in coordinator.data: for target_id, target_data in coordinator.data["targets"].items(): entities.append(LedGrabFPSSensor(coordinator, target_id, entry.entry_id)) entities.append( LedGrabStatusSensor(coordinator, target_id, entry.entry_id) ) # Add mapped lights sensor for HA Light targets info = target_data["info"] if info.get("target_type") == TARGET_TYPE_HA_LIGHT: entities.append(HALightMappedLightsSensor(coordinator, target_id, entry.entry_id)) async_add_entities(entities) class LedGrabFPSSensor(CoordinatorEntity, SensorEntity): """FPS sensor for a LED Screen Controller target.""" _attr_has_entity_name = True _attr_state_class = SensorStateClass.MEASUREMENT _attr_native_unit_of_measurement = "FPS" _attr_icon = "mdi:speedometer" _attr_suggested_display_precision = 1 def __init__( self, coordinator: LedGrabCoordinator, target_id: str, entry_id: str, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) self._target_id = target_id self._entry_id = entry_id self._attr_unique_id = f"{target_id}_fps" self._attr_translation_key = "fps" @property def device_info(self) -> dict[str, Any]: """Return device information.""" return {"identifiers": {(DOMAIN, self._target_id)}} @property def native_value(self) -> float | None: """Return the FPS value.""" target_data = self._get_target_data() if not target_data or not target_data.get("state"): return None state = target_data["state"] if not state.get("processing"): return None return state.get("fps_actual") @property def extra_state_attributes(self) -> dict[str, Any]: """Return additional attributes.""" target_data = self._get_target_data() if not target_data or not target_data.get("state"): return {} return {"fps_target": target_data["state"].get("fps_target")} @property def available(self) -> bool: """Return if entity is available.""" return self._get_target_data() is not None def _get_target_data(self) -> dict[str, Any] | None: if not self.coordinator.data: return None return self.coordinator.data.get("targets", {}).get(self._target_id) class LedGrabStatusSensor(CoordinatorEntity, SensorEntity): """Status sensor for a LED Screen Controller target.""" _attr_has_entity_name = True _attr_icon = "mdi:information-outline" _attr_device_class = SensorDeviceClass.ENUM _attr_options = ["processing", "idle", "error", "unavailable"] def __init__( self, coordinator: LedGrabCoordinator, target_id: str, entry_id: str, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) self._target_id = target_id self._entry_id = entry_id self._attr_unique_id = f"{target_id}_status" self._attr_translation_key = "status" @property def device_info(self) -> dict[str, Any]: """Return device information.""" return {"identifiers": {(DOMAIN, self._target_id)}} @property def native_value(self) -> str: """Return the status.""" target_data = self._get_target_data() if not target_data: return "unavailable" state = target_data.get("state") if not state: return "unavailable" if state.get("processing"): errors = state.get("errors", []) if errors: return "error" return "processing" return "idle" @property def available(self) -> bool: """Return if entity is available.""" return self._get_target_data() is not None def _get_target_data(self) -> dict[str, Any] | None: if not self.coordinator.data: return None return self.coordinator.data.get("targets", {}).get(self._target_id) class HALightMappedLightsSensor(CoordinatorEntity, SensorEntity): """Sensor showing the number of mapped HA lights for an HA Light target.""" _attr_has_entity_name = True _attr_icon = "mdi:lightbulb-group" def __init__( self, coordinator: LedGrabCoordinator, target_id: str, entry_id: str, ) -> None: """Initialize the sensor.""" super().__init__(coordinator) self._target_id = target_id self._entry_id = entry_id self._attr_unique_id = f"{target_id}_mapped_lights" self._attr_translation_key = "mapped_lights" @property def device_info(self) -> dict[str, Any]: """Return device information.""" return {"identifiers": {(DOMAIN, self._target_id)}} @property def native_value(self) -> int | None: """Return the number of mapped lights.""" target_data = self._get_target_data() if not target_data: return None mappings = target_data.get("info", {}).get("light_mappings", []) return len(mappings) @property def extra_state_attributes(self) -> dict[str, Any]: """Return light mapping details as attributes.""" target_data = self._get_target_data() if not target_data: return {} mappings = target_data.get("info", {}).get("light_mappings", []) entity_ids = [m.get("entity_id", "") for m in mappings] return { "entity_ids": entity_ids, "mappings": [ { "entity_id": m.get("entity_id", ""), "led_start": m.get("led_start", 0), "led_end": m.get("led_end", -1), "brightness_scale": m.get("brightness_scale", 1.0), } for m in mappings ], } @property def available(self) -> bool: """Return if entity is available.""" return self._get_target_data() is not None def _get_target_data(self) -> dict[str, Any] | None: if not self.coordinator.data: return None return self.coordinator.data.get("targets", {}).get(self._target_id)