"""Fully Kiosk Browser sensor.""" from __future__ import annotations from collections.abc import Callable from dataclasses import dataclass from typing import Any from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, SensorEntityDescription, SensorStateClass, ) from homeassistant.config_entries import ConfigEntry from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfInformation from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.typing import StateType from .const import DOMAIN from .coordinator import FullyKioskDataUpdateCoordinator from .entity import FullyKioskEntity def round_storage(value: int) -> float: """Convert storage values from bytes to megabytes.""" return round(value * 0.000001, 1) def truncate_url(value: StateType) -> tuple[StateType, dict[str, Any]]: """Truncate URL if longer than 256.""" url = str(value) truncated = len(url) > 256 extra_state_attributes = { "full_url": url, "truncated": truncated, } if truncated: return (url[0:255], extra_state_attributes) return (url, extra_state_attributes) @dataclass class FullySensorEntityDescription(SensorEntityDescription): """Fully Kiosk Browser sensor description.""" round_state_value: bool = False state_fn: Callable[[StateType], tuple[StateType, dict[str, Any]]] | None = None SENSORS: tuple[FullySensorEntityDescription, ...] = ( FullySensorEntityDescription( key="batteryLevel", device_class=SensorDeviceClass.BATTERY, native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, ), FullySensorEntityDescription( key="currentPage", translation_key="current_page", entity_category=EntityCategory.DIAGNOSTIC, state_fn=truncate_url, ), FullySensorEntityDescription( key="screenOrientation", translation_key="screen_orientation", entity_category=EntityCategory.DIAGNOSTIC, ), FullySensorEntityDescription( key="foregroundApp", translation_key="foreground_app", entity_category=EntityCategory.DIAGNOSTIC, ), FullySensorEntityDescription( key="internalStorageFreeSpace", translation_key="internal_storage_free_space", entity_category=EntityCategory.DIAGNOSTIC, native_unit_of_measurement=UnitOfInformation.MEGABYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, round_state_value=True, ), FullySensorEntityDescription( key="internalStorageTotalSpace", translation_key="internal_storage_total_space", entity_category=EntityCategory.DIAGNOSTIC, native_unit_of_measurement=UnitOfInformation.MEGABYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, round_state_value=True, ), FullySensorEntityDescription( key="ramFreeMemory", translation_key="ram_free_memory", entity_category=EntityCategory.DIAGNOSTIC, native_unit_of_measurement=UnitOfInformation.MEGABYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, round_state_value=True, ), FullySensorEntityDescription( key="ramTotalMemory", translation_key="ram_total_memory", entity_category=EntityCategory.DIAGNOSTIC, native_unit_of_measurement=UnitOfInformation.MEGABYTES, device_class=SensorDeviceClass.DATA_SIZE, state_class=SensorStateClass.MEASUREMENT, round_state_value=True, ), ) async def async_setup_entry( hass: HomeAssistant, config_entry: ConfigEntry, async_add_entities: AddEntitiesCallback, ) -> None: """Set up the Fully Kiosk Browser sensor.""" coordinator: FullyKioskDataUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ] async_add_entities( FullySensor(coordinator, description) for description in SENSORS if description.key in coordinator.data ) class FullySensor(FullyKioskEntity, SensorEntity): """Representation of a Fully Kiosk Browser sensor.""" entity_description: FullySensorEntityDescription def __init__( self, coordinator: FullyKioskDataUpdateCoordinator, sensor: FullySensorEntityDescription, ) -> None: """Initialize the sensor entity.""" self.entity_description = sensor self._attr_unique_id = f"{coordinator.data['deviceID']}-{sensor.key}" super().__init__(coordinator) @callback def _handle_coordinator_update(self) -> None: extra_state_attributes: dict[str, Any] = {} value = self.coordinator.data.get(self.entity_description.key) if value is not None: if self.entity_description.state_fn is not None: value, extra_state_attributes = self.entity_description.state_fn(value) if self.entity_description.round_state_value: value = round_storage(value) self._attr_native_value = value self._attr_extra_state_attributes = extra_state_attributes self.async_write_ha_state()