2022-03-19 07:42:22 +00:00
|
|
|
"""Sensor component that handles additional Tomorrowio data for your location."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
from abc import abstractmethod
|
|
|
|
from collections.abc import Callable
|
|
|
|
from dataclasses import dataclass
|
|
|
|
from typing import Any
|
|
|
|
|
|
|
|
from pytomorrowio.const import (
|
|
|
|
HealthConcernType,
|
|
|
|
PollenIndex,
|
|
|
|
PrecipitationType,
|
|
|
|
PrimaryPollutantType,
|
|
|
|
)
|
|
|
|
|
|
|
|
from homeassistant.components.sensor import (
|
|
|
|
SensorDeviceClass,
|
|
|
|
SensorEntity,
|
|
|
|
SensorEntityDescription,
|
|
|
|
)
|
|
|
|
from homeassistant.config_entries import ConfigEntry
|
|
|
|
from homeassistant.const import (
|
|
|
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
|
|
|
CONCENTRATION_PARTS_PER_MILLION,
|
2022-05-29 16:29:21 +00:00
|
|
|
CONF_API_KEY,
|
2022-03-19 07:42:22 +00:00
|
|
|
CONF_NAME,
|
|
|
|
PERCENTAGE,
|
2022-12-08 22:52:55 +00:00
|
|
|
UnitOfIrradiance,
|
2022-11-05 09:33:56 +00:00
|
|
|
UnitOfLength,
|
|
|
|
UnitOfPressure,
|
|
|
|
UnitOfSpeed,
|
|
|
|
UnitOfTemperature,
|
2022-03-19 07:42:22 +00:00
|
|
|
)
|
|
|
|
from homeassistant.core import HomeAssistant
|
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from homeassistant.util import slugify
|
2022-09-28 14:05:31 +00:00
|
|
|
from homeassistant.util.unit_conversion import DistanceConverter, SpeedConverter
|
2022-10-19 16:54:50 +00:00
|
|
|
from homeassistant.util.unit_system import US_CUSTOMARY_SYSTEM
|
2022-03-19 07:42:22 +00:00
|
|
|
|
|
|
|
from . import TomorrowioDataUpdateCoordinator, TomorrowioEntity
|
|
|
|
from .const import (
|
|
|
|
DOMAIN,
|
|
|
|
TMRW_ATTR_CARBON_MONOXIDE,
|
|
|
|
TMRW_ATTR_CHINA_AQI,
|
|
|
|
TMRW_ATTR_CHINA_HEALTH_CONCERN,
|
|
|
|
TMRW_ATTR_CHINA_PRIMARY_POLLUTANT,
|
|
|
|
TMRW_ATTR_CLOUD_BASE,
|
|
|
|
TMRW_ATTR_CLOUD_CEILING,
|
|
|
|
TMRW_ATTR_CLOUD_COVER,
|
|
|
|
TMRW_ATTR_DEW_POINT,
|
|
|
|
TMRW_ATTR_EPA_AQI,
|
|
|
|
TMRW_ATTR_EPA_HEALTH_CONCERN,
|
|
|
|
TMRW_ATTR_EPA_PRIMARY_POLLUTANT,
|
|
|
|
TMRW_ATTR_FEELS_LIKE,
|
|
|
|
TMRW_ATTR_FIRE_INDEX,
|
|
|
|
TMRW_ATTR_NITROGEN_DIOXIDE,
|
|
|
|
TMRW_ATTR_OZONE,
|
|
|
|
TMRW_ATTR_PARTICULATE_MATTER_10,
|
|
|
|
TMRW_ATTR_PARTICULATE_MATTER_25,
|
|
|
|
TMRW_ATTR_POLLEN_GRASS,
|
|
|
|
TMRW_ATTR_POLLEN_TREE,
|
|
|
|
TMRW_ATTR_POLLEN_WEED,
|
|
|
|
TMRW_ATTR_PRECIPITATION_TYPE,
|
|
|
|
TMRW_ATTR_PRESSURE_SURFACE_LEVEL,
|
|
|
|
TMRW_ATTR_SOLAR_GHI,
|
|
|
|
TMRW_ATTR_SULPHUR_DIOXIDE,
|
|
|
|
TMRW_ATTR_WIND_GUST,
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
class TomorrowioSensorEntityDescription(SensorEntityDescription):
|
|
|
|
"""Describes a Tomorrow.io sensor entity."""
|
|
|
|
|
|
|
|
unit_imperial: str | None = None
|
|
|
|
unit_metric: str | None = None
|
2022-04-05 06:52:36 +00:00
|
|
|
multiplication_factor: Callable[[float], float] | float | None = None
|
2022-04-14 16:58:16 +00:00
|
|
|
imperial_conversion: Callable[[float], float] | float | None = None
|
2022-03-19 07:42:22 +00:00
|
|
|
value_map: Any | None = None
|
|
|
|
|
2022-04-05 06:52:36 +00:00
|
|
|
def __post_init__(self) -> None:
|
|
|
|
"""Handle post init."""
|
|
|
|
if (self.unit_imperial is None and self.unit_metric is not None) or (
|
|
|
|
self.unit_imperial is not None and self.unit_metric is None
|
|
|
|
):
|
|
|
|
raise ValueError(
|
|
|
|
"Entity descriptions must include both imperial and metric units or "
|
|
|
|
"they must both be None"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# From https://cfpub.epa.gov/ncer_abstracts/index.cfm/fuseaction/display.files/fileID/14285
|
|
|
|
# x ug/m^3 = y ppb * molecular weight / 24.45
|
|
|
|
def convert_ppb_to_ugm3(molecular_weight: int | float) -> Callable[[float], float]:
|
|
|
|
"""Return function to convert ppb to ug/m^3."""
|
|
|
|
return lambda x: (x * molecular_weight) / 24.45
|
|
|
|
|
2022-03-19 07:42:22 +00:00
|
|
|
|
|
|
|
SENSOR_TYPES = (
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_FEELS_LIKE,
|
|
|
|
name="Feels Like",
|
2022-11-05 09:33:56 +00:00
|
|
|
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.TEMPERATURE,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_DEW_POINT,
|
|
|
|
name="Dew Point",
|
2022-11-05 09:33:56 +00:00
|
|
|
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.TEMPERATURE,
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as hPa
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_PRESSURE_SURFACE_LEVEL,
|
|
|
|
name="Pressure (Surface Level)",
|
2022-11-05 09:33:56 +00:00
|
|
|
native_unit_of_measurement=UnitOfPressure.HPA,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.PRESSURE,
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as W/m^2, convert to BTUs/(hr * ft^2) for imperial
|
2022-04-05 06:52:36 +00:00
|
|
|
# https://www.theunitconverter.com/watt-square-meter-to-btu-hour-square-foot-conversion/
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_SOLAR_GHI,
|
|
|
|
name="Global Horizontal Irradiance",
|
2022-12-08 22:52:55 +00:00
|
|
|
unit_imperial=UnitOfIrradiance.BTUS_PER_HOUR_SQUARE_FOOT,
|
|
|
|
unit_metric=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
|
2022-04-14 16:58:16 +00:00
|
|
|
imperial_conversion=(1 / 3.15459),
|
2022-12-08 22:52:55 +00:00
|
|
|
device_class=SensorDeviceClass.IRRADIANCE,
|
2022-03-19 07:42:22 +00:00
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as km, convert to miles for imperial
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CLOUD_BASE,
|
|
|
|
name="Cloud Base",
|
2022-11-05 09:33:56 +00:00
|
|
|
unit_imperial=UnitOfLength.MILES,
|
|
|
|
unit_metric=UnitOfLength.KILOMETERS,
|
2022-09-28 14:05:31 +00:00
|
|
|
imperial_conversion=lambda val: DistanceConverter.convert(
|
2022-11-05 09:33:56 +00:00
|
|
|
val,
|
|
|
|
UnitOfLength.KILOMETERS,
|
|
|
|
UnitOfLength.MILES,
|
2022-03-19 07:42:22 +00:00
|
|
|
),
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as km, convert to miles for imperial
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CLOUD_CEILING,
|
|
|
|
name="Cloud Ceiling",
|
2022-11-05 09:33:56 +00:00
|
|
|
unit_imperial=UnitOfLength.MILES,
|
|
|
|
unit_metric=UnitOfLength.KILOMETERS,
|
2022-09-28 14:05:31 +00:00
|
|
|
imperial_conversion=lambda val: DistanceConverter.convert(
|
2022-11-05 09:33:56 +00:00
|
|
|
val,
|
|
|
|
UnitOfLength.KILOMETERS,
|
|
|
|
UnitOfLength.MILES,
|
2022-03-19 07:42:22 +00:00
|
|
|
),
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CLOUD_COVER,
|
|
|
|
name="Cloud Cover",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=PERCENTAGE,
|
2022-03-19 07:42:22 +00:00
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as m/s, convert to mi/h for imperial
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_WIND_GUST,
|
|
|
|
name="Wind Gust",
|
2022-11-05 09:33:56 +00:00
|
|
|
unit_imperial=UnitOfSpeed.MILES_PER_HOUR,
|
|
|
|
unit_metric=UnitOfSpeed.METERS_PER_SECOND,
|
2022-09-28 14:05:31 +00:00
|
|
|
imperial_conversion=lambda val: SpeedConverter.convert(
|
2022-11-05 09:33:56 +00:00
|
|
|
val, UnitOfSpeed.METERS_PER_SECOND, UnitOfSpeed.MILES_PER_HOUR
|
2022-06-27 18:26:04 +00:00
|
|
|
),
|
2022-03-19 07:42:22 +00:00
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_PRECIPITATION_TYPE,
|
|
|
|
name="Precipitation Type",
|
|
|
|
value_map=PrecipitationType,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=["freezing_rain", "ice_pellets", "none", "rain", "snow"],
|
|
|
|
translation_key="precipitation_type",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:weather-snowy-rainy",
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as ppb, convert to µg/m^3
|
2022-04-05 06:52:36 +00:00
|
|
|
# Molecular weight of Ozone is 48
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_OZONE,
|
|
|
|
name="Ozone",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
|
|
|
multiplication_factor=convert_ppb_to_ugm3(48),
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.OZONE,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_PARTICULATE_MATTER_25,
|
|
|
|
name="Particulate Matter < 2.5 μm",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.PM25,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_PARTICULATE_MATTER_10,
|
|
|
|
name="Particulate Matter < 10 μm",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.PM10,
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as ppb, convert to µg/m^3
|
2022-04-05 06:52:36 +00:00
|
|
|
# Molecular weight of Nitrogen Dioxide is 46.01
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_NITROGEN_DIOXIDE,
|
|
|
|
name="Nitrogen Dioxide",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
|
|
|
multiplication_factor=convert_ppb_to_ugm3(46.01),
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as ppb, convert to ppm
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CARBON_MONOXIDE,
|
|
|
|
name="Carbon Monoxide",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
|
|
|
multiplication_factor=1 / 1000,
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.CO,
|
|
|
|
),
|
2022-06-27 18:26:04 +00:00
|
|
|
# Data comes in as ppb, convert to µg/m^3
|
2022-04-05 06:52:36 +00:00
|
|
|
# Molecular weight of Sulphur Dioxide is 64.07
|
2022-03-19 07:42:22 +00:00
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_SULPHUR_DIOXIDE,
|
|
|
|
name="Sulphur Dioxide",
|
2022-04-05 06:52:36 +00:00
|
|
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
|
|
|
multiplication_factor=convert_ppb_to_ugm3(64.07),
|
2022-03-19 07:42:22 +00:00
|
|
|
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_EPA_AQI,
|
|
|
|
name="US EPA Air Quality Index",
|
|
|
|
device_class=SensorDeviceClass.AQI,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_EPA_PRIMARY_POLLUTANT,
|
|
|
|
name="US EPA Primary Pollutant",
|
|
|
|
value_map=PrimaryPollutantType,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_EPA_HEALTH_CONCERN,
|
|
|
|
name="US EPA Health Concern",
|
|
|
|
value_map=HealthConcernType,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=[
|
|
|
|
"good",
|
|
|
|
"hazardous",
|
|
|
|
"moderate",
|
|
|
|
"unhealthy_for_sensitive_groups",
|
|
|
|
"unhealthy",
|
|
|
|
"very_unhealthy",
|
|
|
|
],
|
|
|
|
translation_key="health_concern",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:hospital",
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CHINA_AQI,
|
|
|
|
name="China MEP Air Quality Index",
|
|
|
|
device_class=SensorDeviceClass.AQI,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CHINA_PRIMARY_POLLUTANT,
|
|
|
|
name="China MEP Primary Pollutant",
|
|
|
|
value_map=PrimaryPollutantType,
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_CHINA_HEALTH_CONCERN,
|
|
|
|
name="China MEP Health Concern",
|
|
|
|
value_map=HealthConcernType,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=[
|
|
|
|
"good",
|
|
|
|
"hazardous",
|
|
|
|
"moderate",
|
|
|
|
"unhealthy_for_sensitive_groups",
|
|
|
|
"unhealthy",
|
|
|
|
"very_unhealthy",
|
|
|
|
],
|
|
|
|
translation_key="health_concern",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:hospital",
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_POLLEN_TREE,
|
|
|
|
name="Tree Pollen Index",
|
|
|
|
value_map=PollenIndex,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=["high", "low", "medium", "none", "very_high", "very_low"],
|
|
|
|
translation_key="pollen_index",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:flower-pollen",
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_POLLEN_WEED,
|
|
|
|
name="Weed Pollen Index",
|
|
|
|
value_map=PollenIndex,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=["high", "low", "medium", "none", "very_high", "very_low"],
|
|
|
|
translation_key="pollen_index",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:flower-pollen",
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
key=TMRW_ATTR_POLLEN_GRASS,
|
|
|
|
name="Grass Pollen Index",
|
|
|
|
value_map=PollenIndex,
|
2022-12-05 12:17:49 +00:00
|
|
|
device_class=SensorDeviceClass.ENUM,
|
|
|
|
options=["high", "low", "medium", "none", "very_high", "very_low"],
|
|
|
|
translation_key="pollen_index",
|
2022-03-19 07:42:22 +00:00
|
|
|
icon="mdi:flower-pollen",
|
|
|
|
),
|
|
|
|
TomorrowioSensorEntityDescription(
|
|
|
|
TMRW_ATTR_FIRE_INDEX,
|
|
|
|
name="Fire Index",
|
|
|
|
icon="mdi:fire",
|
|
|
|
),
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
|
|
|
"""Set up a config entry."""
|
2022-05-29 16:29:21 +00:00
|
|
|
coordinator = hass.data[DOMAIN][config_entry.data[CONF_API_KEY]]
|
2022-03-19 07:42:22 +00:00
|
|
|
entities = [
|
|
|
|
TomorrowioSensorEntity(hass, config_entry, coordinator, 4, description)
|
|
|
|
for description in SENSOR_TYPES
|
|
|
|
]
|
|
|
|
async_add_entities(entities)
|
|
|
|
|
|
|
|
|
2022-04-05 06:52:36 +00:00
|
|
|
def handle_conversion(
|
|
|
|
value: float | int, conversion: Callable[[float], float] | float
|
|
|
|
) -> float:
|
|
|
|
"""Handle conversion of a value based on conversion type."""
|
|
|
|
if callable(conversion):
|
|
|
|
return round(conversion(float(value)), 2)
|
|
|
|
|
|
|
|
return round(float(value) * conversion, 2)
|
|
|
|
|
|
|
|
|
2022-03-19 07:42:22 +00:00
|
|
|
class BaseTomorrowioSensorEntity(TomorrowioEntity, SensorEntity):
|
|
|
|
"""Base Tomorrow.io sensor entity."""
|
|
|
|
|
|
|
|
entity_description: TomorrowioSensorEntityDescription
|
|
|
|
_attr_entity_registry_enabled_default = False
|
|
|
|
|
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
coordinator: TomorrowioDataUpdateCoordinator,
|
|
|
|
api_version: int,
|
|
|
|
description: TomorrowioSensorEntityDescription,
|
|
|
|
) -> None:
|
|
|
|
"""Initialize Tomorrow.io Sensor Entity."""
|
|
|
|
super().__init__(config_entry, coordinator, api_version)
|
|
|
|
self.entity_description = description
|
|
|
|
self._attr_name = f"{self._config_entry.data[CONF_NAME]} - {description.name}"
|
|
|
|
self._attr_unique_id = (
|
|
|
|
f"{self._config_entry.unique_id}_{slugify(description.name)}"
|
|
|
|
)
|
2022-04-05 06:52:36 +00:00
|
|
|
if self.entity_description.native_unit_of_measurement is None:
|
2022-10-13 16:50:00 +00:00
|
|
|
self._attr_native_unit_of_measurement = description.unit_metric
|
2022-10-19 16:54:50 +00:00
|
|
|
if hass.config.units is US_CUSTOMARY_SYSTEM:
|
2022-10-13 16:50:00 +00:00
|
|
|
self._attr_native_unit_of_measurement = description.unit_imperial
|
2022-03-19 07:42:22 +00:00
|
|
|
|
|
|
|
@property
|
|
|
|
@abstractmethod
|
2022-04-05 06:52:36 +00:00
|
|
|
def _state(self) -> int | float | None:
|
2022-03-19 07:42:22 +00:00
|
|
|
"""Return the raw state."""
|
|
|
|
|
|
|
|
@property
|
|
|
|
def native_value(self) -> str | int | float | None:
|
|
|
|
"""Return the state."""
|
|
|
|
state = self._state
|
2022-04-05 06:52:36 +00:00
|
|
|
desc = self.entity_description
|
|
|
|
|
|
|
|
if state is None:
|
|
|
|
return state
|
|
|
|
|
|
|
|
if desc.value_map is not None:
|
|
|
|
return desc.value_map(state).name.lower()
|
|
|
|
|
|
|
|
if desc.multiplication_factor is not None:
|
|
|
|
state = handle_conversion(state, desc.multiplication_factor)
|
2022-03-19 07:42:22 +00:00
|
|
|
|
2022-04-14 16:58:16 +00:00
|
|
|
# If there is an imperial conversion needed and the instance is using imperial,
|
|
|
|
# apply the conversion logic.
|
2022-04-05 06:52:36 +00:00
|
|
|
if (
|
2022-04-14 16:58:16 +00:00
|
|
|
desc.imperial_conversion
|
2022-04-05 06:52:36 +00:00
|
|
|
and desc.unit_imperial is not None
|
|
|
|
and desc.unit_imperial != desc.unit_metric
|
2022-10-19 16:54:50 +00:00
|
|
|
and self.hass.config.units is US_CUSTOMARY_SYSTEM
|
2022-03-19 07:42:22 +00:00
|
|
|
):
|
2022-04-14 16:58:16 +00:00
|
|
|
return handle_conversion(state, desc.imperial_conversion)
|
2022-03-19 07:42:22 +00:00
|
|
|
|
|
|
|
return state
|
|
|
|
|
|
|
|
|
|
|
|
class TomorrowioSensorEntity(BaseTomorrowioSensorEntity):
|
|
|
|
"""Sensor entity that talks to Tomorrow.io v4 API to retrieve non-weather data."""
|
|
|
|
|
|
|
|
@property
|
2022-04-05 06:52:36 +00:00
|
|
|
def _state(self) -> int | float | None:
|
2022-03-19 07:42:22 +00:00
|
|
|
"""Return the raw state."""
|
2022-04-05 06:52:36 +00:00
|
|
|
val = self._get_current_property(self.entity_description.key)
|
|
|
|
assert not isinstance(val, str)
|
|
|
|
return val
|