mirror of
https://github.com/home-assistant/core.git
synced 2025-07-09 14:27:07 +00:00
Add SensorEntityDescription class (#53357)
This commit is contained in:
parent
88cffc86bb
commit
ee452d415d
@ -5,12 +5,11 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT
|
from homeassistant.components.sensor import (
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_DEVICE_CLASS,
|
|
||||||
ATTR_ICON,
|
|
||||||
ATTR_NAME,
|
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
|
||||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
CONCENTRATION_PARTS_PER_BILLION,
|
CONCENTRATION_PARTS_PER_BILLION,
|
||||||
CONCENTRATION_PARTS_PER_CUBIC_METER,
|
CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
@ -18,13 +17,10 @@ from homeassistant.const import (
|
|||||||
DEVICE_CLASS_CO,
|
DEVICE_CLASS_CO,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .models import AmbeeSensor
|
|
||||||
|
|
||||||
DOMAIN: Final = "ambee"
|
DOMAIN: Final = "ambee"
|
||||||
LOGGER = logging.getLogger(__package__)
|
LOGGER = logging.getLogger(__package__)
|
||||||
SCAN_INTERVAL = timedelta(hours=1)
|
SCAN_INTERVAL = timedelta(hours=1)
|
||||||
|
|
||||||
ATTR_ENABLED_BY_DEFAULT: Final = "enabled_by_default"
|
|
||||||
ATTR_ENTRY_TYPE: Final = "entry_type"
|
ATTR_ENTRY_TYPE: Final = "entry_type"
|
||||||
ENTRY_TYPE_SERVICE: Final = "service"
|
ENTRY_TYPE_SERVICE: Final = "service"
|
||||||
|
|
||||||
@ -38,175 +34,202 @@ SERVICES: dict[str, str] = {
|
|||||||
SERVICE_POLLEN: "Pollen",
|
SERVICE_POLLEN: "Pollen",
|
||||||
}
|
}
|
||||||
|
|
||||||
SENSORS: dict[str, dict[str, AmbeeSensor]] = {
|
SENSORS: dict[str, list[SensorEntityDescription]] = {
|
||||||
SERVICE_AIR_QUALITY: {
|
SERVICE_AIR_QUALITY: [
|
||||||
"particulate_matter_2_5": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Particulate Matter < 2.5 μm",
|
key="particulate_matter_2_5",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
name="Particulate Matter < 2.5 μm",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"particulate_matter_10": {
|
),
|
||||||
ATTR_NAME: "Particulate Matter < 10 μm",
|
SensorEntityDescription(
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
key="particulate_matter_10",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
name="Particulate Matter < 10 μm",
|
||||||
},
|
unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"sulphur_dioxide": {
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_NAME: "Sulphur Dioxide (SO2)",
|
),
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_BILLION,
|
SensorEntityDescription(
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
key="sulphur_dioxide",
|
||||||
},
|
name="Sulphur Dioxide (SO2)",
|
||||||
"nitrogen_dioxide": {
|
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
|
||||||
ATTR_NAME: "Nitrogen Dioxide (NO2)",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_BILLION,
|
),
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
SensorEntityDescription(
|
||||||
},
|
key="nitrogen_dioxide",
|
||||||
"ozone": {
|
name="Nitrogen Dioxide (NO2)",
|
||||||
ATTR_NAME: "Ozone",
|
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_BILLION,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
),
|
||||||
},
|
SensorEntityDescription(
|
||||||
"carbon_monoxide": {
|
key="ozone",
|
||||||
ATTR_NAME: "Carbon Monoxide (CO)",
|
name="Ozone",
|
||||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_CO,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_MILLION,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
),
|
||||||
},
|
SensorEntityDescription(
|
||||||
"air_quality_index": {
|
key="carbon_monoxide",
|
||||||
ATTR_NAME: "Air Quality Index (AQI)",
|
name="Carbon Monoxide (CO)",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
device_class=DEVICE_CLASS_CO,
|
||||||
},
|
unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
SERVICE_POLLEN: {
|
),
|
||||||
"grass": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Grass Pollen",
|
key="air_quality_index",
|
||||||
ATTR_ICON: "mdi:grass",
|
name="Air Quality Index (AQI)",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
),
|
||||||
},
|
],
|
||||||
"tree": {
|
SERVICE_POLLEN: [
|
||||||
ATTR_NAME: "Tree Pollen",
|
SensorEntityDescription(
|
||||||
ATTR_ICON: "mdi:tree",
|
key="grass",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
name="Grass Pollen",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
icon="mdi:grass",
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"weed": {
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_NAME: "Weed Pollen",
|
),
|
||||||
ATTR_ICON: "mdi:sprout",
|
SensorEntityDescription(
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
key="tree",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
name="Tree Pollen",
|
||||||
},
|
icon="mdi:tree",
|
||||||
"grass_risk": {
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_NAME: "Grass Pollen Risk",
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_ICON: "mdi:grass",
|
),
|
||||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_AMBEE_RISK,
|
SensorEntityDescription(
|
||||||
},
|
key="weed",
|
||||||
"tree_risk": {
|
name="Weed Pollen",
|
||||||
ATTR_NAME: "Tree Pollen Risk",
|
icon="mdi:sprout",
|
||||||
ATTR_ICON: "mdi:tree",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_AMBEE_RISK,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
},
|
),
|
||||||
"weed_risk": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Weed Pollen Risk",
|
key="grass_risk",
|
||||||
ATTR_ICON: "mdi:sprout",
|
name="Grass Pollen Risk",
|
||||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_AMBEE_RISK,
|
icon="mdi:grass",
|
||||||
},
|
device_class=DEVICE_CLASS_AMBEE_RISK,
|
||||||
"grass_poaceae": {
|
),
|
||||||
ATTR_NAME: "Poaceae Grass Pollen",
|
SensorEntityDescription(
|
||||||
ATTR_ICON: "mdi:grass",
|
key="tree_risk",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
name="Tree Pollen Risk",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
icon="mdi:tree",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
device_class=DEVICE_CLASS_AMBEE_RISK,
|
||||||
},
|
),
|
||||||
"tree_alder": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Alder Tree Pollen",
|
key="weed_risk",
|
||||||
ATTR_ICON: "mdi:tree",
|
name="Weed Pollen Risk",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
icon="mdi:sprout",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
device_class=DEVICE_CLASS_AMBEE_RISK,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
),
|
||||||
},
|
SensorEntityDescription(
|
||||||
"tree_birch": {
|
key="grass_poaceae",
|
||||||
ATTR_NAME: "Birch Tree Pollen",
|
name="Poaceae Grass Pollen",
|
||||||
ATTR_ICON: "mdi:tree",
|
icon="mdi:grass",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
entity_registry_enabled_default=False,
|
||||||
},
|
),
|
||||||
"tree_cypress": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Cypress Tree Pollen",
|
key="tree_alder",
|
||||||
ATTR_ICON: "mdi:tree",
|
name="Alder Tree Pollen",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
icon="mdi:tree",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
},
|
entity_registry_enabled_default=False,
|
||||||
"tree_elm": {
|
),
|
||||||
ATTR_NAME: "Elm Tree Pollen",
|
SensorEntityDescription(
|
||||||
ATTR_ICON: "mdi:tree",
|
key="tree_birch",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
name="Birch Tree Pollen",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
icon="mdi:tree",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
},
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
"tree_hazel": {
|
entity_registry_enabled_default=False,
|
||||||
ATTR_NAME: "Hazel Tree Pollen",
|
),
|
||||||
ATTR_ICON: "mdi:tree",
|
SensorEntityDescription(
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
key="tree_cypress",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
name="Cypress Tree Pollen",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
icon="mdi:tree",
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"tree_oak": {
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_NAME: "Oak Tree Pollen",
|
entity_registry_enabled_default=False,
|
||||||
ATTR_ICON: "mdi:tree",
|
),
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
SensorEntityDescription(
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
key="tree_elm",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
name="Elm Tree Pollen",
|
||||||
},
|
icon="mdi:tree",
|
||||||
"tree_pine": {
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_NAME: "Pine Tree Pollen",
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_ICON: "mdi:tree",
|
entity_registry_enabled_default=False,
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
),
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
SensorEntityDescription(
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
key="tree_hazel",
|
||||||
},
|
name="Hazel Tree Pollen",
|
||||||
"tree_plane": {
|
icon="mdi:tree",
|
||||||
ATTR_NAME: "Plane Tree Pollen",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_ICON: "mdi:tree",
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
entity_registry_enabled_default=False,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
),
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
SensorEntityDescription(
|
||||||
},
|
key="tree_oak",
|
||||||
"tree_poplar": {
|
name="Oak Tree Pollen",
|
||||||
ATTR_NAME: "Poplar Tree Pollen",
|
icon="mdi:tree",
|
||||||
ATTR_ICON: "mdi:tree",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
entity_registry_enabled_default=False,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
),
|
||||||
},
|
SensorEntityDescription(
|
||||||
"weed_chenopod": {
|
key="tree_pine",
|
||||||
ATTR_NAME: "Chenopod Weed Pollen",
|
name="Pine Tree Pollen",
|
||||||
ATTR_ICON: "mdi:sprout",
|
icon="mdi:tree",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
entity_registry_enabled_default=False,
|
||||||
},
|
),
|
||||||
"weed_mugwort": {
|
SensorEntityDescription(
|
||||||
ATTR_NAME: "Mugwort Weed Pollen",
|
key="tree_plane",
|
||||||
ATTR_ICON: "mdi:sprout",
|
name="Plane Tree Pollen",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
icon="mdi:tree",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
},
|
entity_registry_enabled_default=False,
|
||||||
"weed_nettle": {
|
),
|
||||||
ATTR_NAME: "Nettle Weed Pollen",
|
SensorEntityDescription(
|
||||||
ATTR_ICON: "mdi:sprout",
|
key="tree_poplar",
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
name="Poplar Tree Pollen",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
icon="mdi:tree",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
},
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
"weed_ragweed": {
|
entity_registry_enabled_default=False,
|
||||||
ATTR_NAME: "Ragweed Weed Pollen",
|
),
|
||||||
ATTR_ICON: "mdi:sprout",
|
SensorEntityDescription(
|
||||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
key="weed_chenopod",
|
||||||
ATTR_UNIT_OF_MEASUREMENT: CONCENTRATION_PARTS_PER_CUBIC_METER,
|
name="Chenopod Weed Pollen",
|
||||||
ATTR_ENABLED_BY_DEFAULT: False,
|
icon="mdi:sprout",
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
},
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="weed_mugwort",
|
||||||
|
name="Mugwort Weed Pollen",
|
||||||
|
icon="mdi:sprout",
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="weed_nettle",
|
||||||
|
name="Nettle Weed Pollen",
|
||||||
|
icon="mdi:sprout",
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
),
|
||||||
|
SensorEntityDescription(
|
||||||
|
key="weed_ragweed",
|
||||||
|
name="Ragweed Weed Pollen",
|
||||||
|
icon="mdi:sprout",
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
),
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
"""Models helper class for the Ambee integration."""
|
|
||||||
from __future__ import annotations
|
|
||||||
|
|
||||||
from typing import TypedDict
|
|
||||||
|
|
||||||
|
|
||||||
class AmbeeSensor(TypedDict, total=False):
|
|
||||||
"""Represent an Ambee Sensor."""
|
|
||||||
|
|
||||||
device_class: str
|
|
||||||
enabled_by_default: bool
|
|
||||||
icon: str
|
|
||||||
name: str
|
|
||||||
state_class: str
|
|
||||||
unit_of_measurement: str
|
|
@ -2,19 +2,12 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
ATTR_STATE_CLASS,
|
|
||||||
DOMAIN as SENSOR_DOMAIN,
|
DOMAIN as SENSOR_DOMAIN,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import ATTR_IDENTIFIERS, ATTR_MANUFACTURER, ATTR_NAME
|
||||||
ATTR_DEVICE_CLASS,
|
|
||||||
ATTR_ICON,
|
|
||||||
ATTR_IDENTIFIERS,
|
|
||||||
ATTR_MANUFACTURER,
|
|
||||||
ATTR_NAME,
|
|
||||||
ATTR_UNIT_OF_MEASUREMENT,
|
|
||||||
)
|
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
@ -23,15 +16,7 @@ from homeassistant.helpers.update_coordinator import (
|
|||||||
DataUpdateCoordinator,
|
DataUpdateCoordinator,
|
||||||
)
|
)
|
||||||
|
|
||||||
from .const import (
|
from .const import ATTR_ENTRY_TYPE, DOMAIN, ENTRY_TYPE_SERVICE, SENSORS, SERVICES
|
||||||
ATTR_ENABLED_BY_DEFAULT,
|
|
||||||
ATTR_ENTRY_TYPE,
|
|
||||||
DOMAIN,
|
|
||||||
ENTRY_TYPE_SERVICE,
|
|
||||||
SENSORS,
|
|
||||||
SERVICES,
|
|
||||||
)
|
|
||||||
from .models import AmbeeSensor
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
@ -44,13 +29,12 @@ async def async_setup_entry(
|
|||||||
AmbeeSensorEntity(
|
AmbeeSensorEntity(
|
||||||
coordinator=hass.data[DOMAIN][entry.entry_id][service_key],
|
coordinator=hass.data[DOMAIN][entry.entry_id][service_key],
|
||||||
entry_id=entry.entry_id,
|
entry_id=entry.entry_id,
|
||||||
sensor_key=sensor_key,
|
description=description,
|
||||||
sensor=sensor,
|
|
||||||
service_key=service_key,
|
service_key=service_key,
|
||||||
service=SERVICES[service_key],
|
service=SERVICES[service_key],
|
||||||
)
|
)
|
||||||
for service_key, service_sensors in SENSORS.items()
|
for service_key, service_sensors in SENSORS.items()
|
||||||
for sensor_key, sensor in service_sensors.items()
|
for description in service_sensors
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -62,26 +46,17 @@ class AmbeeSensorEntity(CoordinatorEntity, SensorEntity):
|
|||||||
*,
|
*,
|
||||||
coordinator: DataUpdateCoordinator,
|
coordinator: DataUpdateCoordinator,
|
||||||
entry_id: str,
|
entry_id: str,
|
||||||
sensor_key: str,
|
description: SensorEntityDescription,
|
||||||
sensor: AmbeeSensor,
|
|
||||||
service_key: str,
|
service_key: str,
|
||||||
service: str,
|
service: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Ambee sensor."""
|
"""Initialize Ambee sensor."""
|
||||||
super().__init__(coordinator=coordinator)
|
super().__init__(coordinator=coordinator)
|
||||||
self._sensor_key = sensor_key
|
|
||||||
self._service_key = service_key
|
self._service_key = service_key
|
||||||
|
|
||||||
self.entity_id = f"{SENSOR_DOMAIN}.{service_key}_{sensor_key}"
|
self.entity_id = f"{SENSOR_DOMAIN}.{service_key}_{description.key}"
|
||||||
self._attr_device_class = sensor.get(ATTR_DEVICE_CLASS)
|
self.entity_description = description
|
||||||
self._attr_entity_registry_enabled_default = sensor.get(
|
self._attr_unique_id = f"{entry_id}_{service_key}_{description.key}"
|
||||||
ATTR_ENABLED_BY_DEFAULT, True
|
|
||||||
)
|
|
||||||
self._attr_icon = sensor.get(ATTR_ICON)
|
|
||||||
self._attr_name = sensor.get(ATTR_NAME)
|
|
||||||
self._attr_state_class = sensor.get(ATTR_STATE_CLASS)
|
|
||||||
self._attr_unique_id = f"{entry_id}_{service_key}_{sensor_key}"
|
|
||||||
self._attr_unit_of_measurement = sensor.get(ATTR_UNIT_OF_MEASUREMENT)
|
|
||||||
|
|
||||||
self._attr_device_info = {
|
self._attr_device_info = {
|
||||||
ATTR_IDENTIFIERS: {(DOMAIN, f"{entry_id}_{service_key}")},
|
ATTR_IDENTIFIERS: {(DOMAIN, f"{entry_id}_{service_key}")},
|
||||||
@ -93,7 +68,7 @@ class AmbeeSensorEntity(CoordinatorEntity, SensorEntity):
|
|||||||
@property
|
@property
|
||||||
def state(self) -> StateType:
|
def state(self) -> StateType:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
value = getattr(self.coordinator.data, self._sensor_key)
|
value = getattr(self.coordinator.data, self.entity_description.key)
|
||||||
if isinstance(value, str):
|
if isinstance(value, str):
|
||||||
return value.lower()
|
return value.lower()
|
||||||
return value # type: ignore[no-any-return]
|
return value # type: ignore[no-any-return]
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Final, cast, final
|
from typing import Any, Final, cast, final
|
||||||
@ -31,7 +32,7 @@ from homeassistant.helpers.config_validation import ( # noqa: F401
|
|||||||
PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA,
|
||||||
PLATFORM_SCHEMA_BASE,
|
PLATFORM_SCHEMA_BASE,
|
||||||
)
|
)
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
|
|
||||||
@ -95,21 +96,38 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
return await component.async_unload_entry(entry)
|
return await component.async_unload_entry(entry)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class SensorEntityDescription(EntityDescription):
|
||||||
|
"""An class that describes sensor entities."""
|
||||||
|
|
||||||
|
state_class: str | None = None
|
||||||
|
last_reset: datetime | None = None
|
||||||
|
|
||||||
|
|
||||||
class SensorEntity(Entity):
|
class SensorEntity(Entity):
|
||||||
"""Base class for sensor entities."""
|
"""Base class for sensor entities."""
|
||||||
|
|
||||||
_attr_state_class: str | None = None
|
entity_description: SensorEntityDescription
|
||||||
_attr_last_reset: datetime | None = None
|
_attr_state_class: str | None
|
||||||
|
_attr_last_reset: datetime | None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_class(self) -> str | None:
|
def state_class(self) -> str | None:
|
||||||
"""Return the state class of this entity, from STATE_CLASSES, if any."""
|
"""Return the state class of this entity, from STATE_CLASSES, if any."""
|
||||||
|
if hasattr(self, "_attr_state_class"):
|
||||||
return self._attr_state_class
|
return self._attr_state_class
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.state_class
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def last_reset(self) -> datetime | None:
|
def last_reset(self) -> datetime | None:
|
||||||
"""Return the time when the sensor was last reset, if any."""
|
"""Return the time when the sensor was last reset, if any."""
|
||||||
|
if hasattr(self, "_attr_last_reset"):
|
||||||
return self._attr_last_reset
|
return self._attr_last_reset
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.last_reset
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def capability_attributes(self) -> Mapping[str, Any] | None:
|
def capability_attributes(self) -> Mapping[str, Any] | None:
|
||||||
|
@ -112,6 +112,9 @@ class _TemplateAttribute:
|
|||||||
class TemplateEntity(Entity):
|
class TemplateEntity(Entity):
|
||||||
"""Entity that uses templates to calculate attributes."""
|
"""Entity that uses templates to calculate attributes."""
|
||||||
|
|
||||||
|
_attr_available = True
|
||||||
|
_attr_entity_picture = None
|
||||||
|
_attr_icon = None
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
@ -128,7 +131,6 @@ class TemplateEntity(Entity):
|
|||||||
self._attribute_templates = attribute_templates
|
self._attribute_templates = attribute_templates
|
||||||
self._attr_extra_state_attributes = {}
|
self._attr_extra_state_attributes = {}
|
||||||
self._availability_template = availability_template
|
self._availability_template = availability_template
|
||||||
self._attr_available = True
|
|
||||||
self._icon_template = icon_template
|
self._icon_template = icon_template
|
||||||
self._entity_picture_template = entity_picture_template
|
self._entity_picture_template = entity_picture_template
|
||||||
self._self_ref_update_count = 0
|
self._self_ref_update_count = 0
|
||||||
|
@ -4,6 +4,7 @@ from __future__ import annotations
|
|||||||
from abc import ABC
|
from abc import ABC
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections.abc import Awaitable, Iterable, Mapping, MutableMapping
|
from collections.abc import Awaitable, Iterable, Mapping, MutableMapping
|
||||||
|
from dataclasses import dataclass
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import functools as ft
|
import functools as ft
|
||||||
import logging
|
import logging
|
||||||
@ -178,6 +179,21 @@ class DeviceInfo(TypedDict, total=False):
|
|||||||
default_model: str
|
default_model: str
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class EntityDescription:
|
||||||
|
"""An class that describes Home Assistant entities."""
|
||||||
|
|
||||||
|
# This is the key identifier for this entity
|
||||||
|
key: str
|
||||||
|
|
||||||
|
device_class: str | None = None
|
||||||
|
entity_registry_enabled_default: bool = True
|
||||||
|
force_update: bool = False
|
||||||
|
icon: str | None = None
|
||||||
|
name: str | None = None
|
||||||
|
unit_of_measurement: str | None = None
|
||||||
|
|
||||||
|
|
||||||
class Entity(ABC):
|
class Entity(ABC):
|
||||||
"""An abstract class for Home Assistant entities."""
|
"""An abstract class for Home Assistant entities."""
|
||||||
|
|
||||||
@ -194,6 +210,9 @@ class Entity(ABC):
|
|||||||
# Owning platform instance. Will be set by EntityPlatform
|
# Owning platform instance. Will be set by EntityPlatform
|
||||||
platform: EntityPlatform | None = None
|
platform: EntityPlatform | None = None
|
||||||
|
|
||||||
|
# Entity description instance for this Entity
|
||||||
|
entity_description: EntityDescription
|
||||||
|
|
||||||
# If we reported if this entity was slow
|
# If we reported if this entity was slow
|
||||||
_slow_reported = False
|
_slow_reported = False
|
||||||
|
|
||||||
@ -223,19 +242,19 @@ class Entity(ABC):
|
|||||||
_attr_assumed_state: bool = False
|
_attr_assumed_state: bool = False
|
||||||
_attr_available: bool = True
|
_attr_available: bool = True
|
||||||
_attr_context_recent_time: timedelta = timedelta(seconds=5)
|
_attr_context_recent_time: timedelta = timedelta(seconds=5)
|
||||||
_attr_device_class: str | None = None
|
_attr_device_class: str | None
|
||||||
_attr_device_info: DeviceInfo | None = None
|
_attr_device_info: DeviceInfo | None = None
|
||||||
_attr_entity_picture: str | None = None
|
_attr_entity_picture: str | None = None
|
||||||
_attr_entity_registry_enabled_default: bool = True
|
_attr_entity_registry_enabled_default: bool
|
||||||
_attr_extra_state_attributes: MutableMapping[str, Any] | None = None
|
_attr_extra_state_attributes: MutableMapping[str, Any] | None = None
|
||||||
_attr_force_update: bool = False
|
_attr_force_update: bool
|
||||||
_attr_icon: str | None = None
|
_attr_icon: str | None
|
||||||
_attr_name: str | None = None
|
_attr_name: str | None
|
||||||
_attr_should_poll: bool = True
|
_attr_should_poll: bool = True
|
||||||
_attr_state: StateType = STATE_UNKNOWN
|
_attr_state: StateType = STATE_UNKNOWN
|
||||||
_attr_supported_features: int | None = None
|
_attr_supported_features: int | None = None
|
||||||
_attr_unique_id: str | None = None
|
_attr_unique_id: str | None = None
|
||||||
_attr_unit_of_measurement: str | None = None
|
_attr_unit_of_measurement: str | None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self) -> bool:
|
def should_poll(self) -> bool:
|
||||||
@ -253,7 +272,11 @@ class Entity(ABC):
|
|||||||
@property
|
@property
|
||||||
def name(self) -> str | None:
|
def name(self) -> str | None:
|
||||||
"""Return the name of the entity."""
|
"""Return the name of the entity."""
|
||||||
|
if hasattr(self, "_attr_name"):
|
||||||
return self._attr_name
|
return self._attr_name
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.name
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self) -> StateType:
|
def state(self) -> StateType:
|
||||||
@ -309,17 +332,29 @@ class Entity(ABC):
|
|||||||
@property
|
@property
|
||||||
def device_class(self) -> str | None:
|
def device_class(self) -> str | None:
|
||||||
"""Return the class of this device, from component DEVICE_CLASSES."""
|
"""Return the class of this device, from component DEVICE_CLASSES."""
|
||||||
|
if hasattr(self, "_attr_device_class"):
|
||||||
return self._attr_device_class
|
return self._attr_device_class
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.device_class
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self) -> str | None:
|
def unit_of_measurement(self) -> str | None:
|
||||||
"""Return the unit of measurement of this entity, if any."""
|
"""Return the unit of measurement of this entity, if any."""
|
||||||
|
if hasattr(self, "_attr_unit_of_measurement"):
|
||||||
return self._attr_unit_of_measurement
|
return self._attr_unit_of_measurement
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.unit_of_measurement
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self) -> str | None:
|
def icon(self) -> str | None:
|
||||||
"""Return the icon to use in the frontend, if any."""
|
"""Return the icon to use in the frontend, if any."""
|
||||||
|
if hasattr(self, "_attr_icon"):
|
||||||
return self._attr_icon
|
return self._attr_icon
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.icon
|
||||||
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entity_picture(self) -> str | None:
|
def entity_picture(self) -> str | None:
|
||||||
@ -343,7 +378,11 @@ class Entity(ABC):
|
|||||||
If True, a state change will be triggered anytime the state property is
|
If True, a state change will be triggered anytime the state property is
|
||||||
updated, not just when the value changes.
|
updated, not just when the value changes.
|
||||||
"""
|
"""
|
||||||
|
if hasattr(self, "_attr_force_update"):
|
||||||
return self._attr_force_update
|
return self._attr_force_update
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.force_update
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self) -> int | None:
|
def supported_features(self) -> int | None:
|
||||||
@ -358,7 +397,11 @@ class Entity(ABC):
|
|||||||
@property
|
@property
|
||||||
def entity_registry_enabled_default(self) -> bool:
|
def entity_registry_enabled_default(self) -> bool:
|
||||||
"""Return if the entity should be enabled when first added to the entity registry."""
|
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||||
|
if hasattr(self, "_attr_entity_registry_enabled_default"):
|
||||||
return self._attr_entity_registry_enabled_default
|
return self._attr_entity_registry_enabled_default
|
||||||
|
if hasattr(self, "entity_description"):
|
||||||
|
return self.entity_description.entity_registry_enabled_default
|
||||||
|
return True
|
||||||
|
|
||||||
# DO NOT OVERWRITE
|
# DO NOT OVERWRITE
|
||||||
# These properties and methods are either managed by Home Assistant or they
|
# These properties and methods are either managed by Home Assistant or they
|
||||||
|
Loading…
x
Reference in New Issue
Block a user