core/homeassistant/components/ipma/sensor.py

126 lines
3.7 KiB
Python

"""Support for IPMA sensors."""
from __future__ import annotations
import asyncio
from collections.abc import Callable, Coroutine
from dataclasses import asdict, dataclass
import logging
from typing import Any
from pyipma.api import IPMA_API
from pyipma.location import Location
from pyipma.rcm import RCM
from pyipma.uv import UV
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util import Throttle
from .const import DATA_API, DATA_LOCATION, DOMAIN, MIN_TIME_BETWEEN_UPDATES
from .entity import IPMADevice
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class IPMASensorEntityDescription(SensorEntityDescription):
"""Describes a IPMA sensor entity."""
value_fn: Callable[
[Location, IPMA_API], Coroutine[Location, IPMA_API, tuple[Any, dict[str, Any]]]
]
async def async_retrieve_rcm(
location: Location, api: IPMA_API
) -> tuple[int, dict[str, Any]] | tuple[None, dict[str, Any]]:
"""Retrieve RCM."""
fire_risk: RCM = await location.fire_risk(api)
if fire_risk:
return fire_risk.rcm, {}
return None, {}
async def async_retrieve_uvi(
location: Location, api: IPMA_API
) -> tuple[int, dict[str, Any]] | tuple[None, dict[str, Any]]:
"""Retrieve UV."""
uv_risk: UV = await location.uv_risk(api)
if uv_risk:
return round(uv_risk.iUv), {}
return None, {}
async def async_retrieve_warning(
location: Location, api: IPMA_API
) -> tuple[Any, dict[str, str]]:
"""Retrieve Warning."""
warnings = await location.warnings(api)
if len(warnings):
return warnings[0].awarenessLevelID, {
k: str(v) for k, v in asdict(warnings[0]).items()
}
return "green", {}
SENSOR_TYPES: tuple[IPMASensorEntityDescription, ...] = (
IPMASensorEntityDescription(
key="rcm",
translation_key="fire_risk",
value_fn=async_retrieve_rcm,
),
IPMASensorEntityDescription(
key="uvi",
translation_key="uv_index",
value_fn=async_retrieve_uvi,
),
IPMASensorEntityDescription(
key="alert",
translation_key="weather_alert",
value_fn=async_retrieve_warning,
),
)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up the IPMA sensor platform."""
api = hass.data[DOMAIN][entry.entry_id][DATA_API]
location = hass.data[DOMAIN][entry.entry_id][DATA_LOCATION]
entities = [IPMASensor(api, location, description) for description in SENSOR_TYPES]
async_add_entities(entities, True)
class IPMASensor(SensorEntity, IPMADevice):
"""Representation of an IPMA sensor."""
entity_description: IPMASensorEntityDescription
_attr_has_entity_name = True
def __init__(
self,
api: IPMA_API,
location: Location,
description: IPMASensorEntityDescription,
) -> None:
"""Initialize the IPMA Sensor."""
IPMADevice.__init__(self, api, location)
self.entity_description = description
self._attr_unique_id = f"{self._location.station_latitude}, {self._location.station_longitude}, {self.entity_description.key}"
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self) -> None:
"""Update sensors."""
async with asyncio.timeout(10):
state, attrs = await self.entity_description.value_fn(
self._location, self._api
)
self._attr_native_value = state
self._attr_extra_state_attributes = attrs