core/homeassistant/components/airvisual_pro/sensor.py

154 lines
5.2 KiB
Python

"""Support for AirVisual Pro sensors."""
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 (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import AirVisualProData, AirVisualProEntity
from .const import DOMAIN
@dataclass
class AirVisualProMeasurementKeyMixin:
"""Define an entity description mixin to include a measurement key."""
value_fn: Callable[[dict[str, Any], dict[str, Any], dict[str, Any]], float | int]
@dataclass
class AirVisualProMeasurementDescription(
SensorEntityDescription, AirVisualProMeasurementKeyMixin
):
"""Describe an AirVisual Pro sensor."""
SENSOR_DESCRIPTIONS = (
AirVisualProMeasurementDescription(
key="air_quality_index",
name="Air quality index",
device_class=SensorDeviceClass.AQI,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements[
async_get_aqi_locale(settings)
],
),
AirVisualProMeasurementDescription(
key="battery_level",
name="Battery",
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda settings, status, measurements: status["battery"],
),
AirVisualProMeasurementDescription(
key="carbon_dioxide",
name="C02",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["co2"],
),
AirVisualProMeasurementDescription(
key="humidity",
name="Humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
value_fn=lambda settings, status, measurements: measurements["humidity"],
),
AirVisualProMeasurementDescription(
key="particulate_matter_0_1",
name="PM 0.1",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm0_1"],
),
AirVisualProMeasurementDescription(
key="particulate_matter_1_0",
name="PM 1.0",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm1_0"],
),
AirVisualProMeasurementDescription(
key="particulate_matter_2_5",
name="PM 2.5",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["pm2_5"],
),
AirVisualProMeasurementDescription(
key="temperature",
name="Temperature",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["temperature_C"],
),
AirVisualProMeasurementDescription(
key="voc",
name="VOC",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements: measurements["voc"],
),
)
@callback
def async_get_aqi_locale(settings: dict[str, Any]) -> str:
"""Return the correct AQI locale based on settings data."""
if settings["is_aqi_usa"]:
return "aqi_us"
return "aqi_cn"
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up AirVisual sensors based on a config entry."""
data: AirVisualProData = hass.data[DOMAIN][entry.entry_id]
async_add_entities(
AirVisualProSensor(data.coordinator, description)
for description in SENSOR_DESCRIPTIONS
)
class AirVisualProSensor(AirVisualProEntity, SensorEntity):
"""Define an AirVisual Pro sensor."""
_attr_has_entity_name = True
entity_description: AirVisualProMeasurementDescription
@property
def native_value(self) -> float | int:
"""Return the sensor value."""
return self.entity_description.value_fn(
self.coordinator.data["settings"],
self.coordinator.data["status"],
self.coordinator.data["measurements"],
)