Use EntityDescription - homekit_controller (#56945)
This commit is contained in:
parent
9d671eff27
commit
3976443292
2 changed files with 136 additions and 149 deletions
|
@ -4,22 +4,26 @@ Support for Homekit number ranges.
|
||||||
These are mostly used where a HomeKit accessory exposes additional non-standard
|
These are mostly used where a HomeKit accessory exposes additional non-standard
|
||||||
characteristics that don't map to a Home Assistant feature.
|
characteristics that don't map to a Home Assistant feature.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
||||||
|
|
||||||
from homeassistant.components.number import NumberEntity
|
from homeassistant.components.number import NumberEntity, NumberEntityDescription
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
|
|
||||||
from . import KNOWN_DEVICES, CharacteristicEntity
|
from . import KNOWN_DEVICES, CharacteristicEntity
|
||||||
|
|
||||||
NUMBER_ENTITIES = {
|
NUMBER_ENTITIES: dict[str, NumberEntityDescription] = {
|
||||||
CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: {
|
CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL: NumberEntityDescription(
|
||||||
"name": "Spray Quantity",
|
key=CharacteristicsTypes.Vendor.VOCOLINC_HUMIDIFIER_SPRAY_LEVEL,
|
||||||
"icon": "mdi:water",
|
name="Spray Quantity",
|
||||||
},
|
icon="mdi:water",
|
||||||
CharacteristicsTypes.Vendor.EVE_DEGREE_ELEVATION: {
|
),
|
||||||
"name": "Elevation",
|
CharacteristicsTypes.Vendor.EVE_DEGREE_ELEVATION: NumberEntityDescription(
|
||||||
"icon": "mdi:elevation-rise",
|
key=CharacteristicsTypes.Vendor.EVE_DEGREE_ELEVATION,
|
||||||
},
|
name="Elevation",
|
||||||
|
icon="mdi:elevation-rise",
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,11 +34,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_characteristic(char: Characteristic):
|
def async_add_characteristic(char: Characteristic):
|
||||||
kwargs = NUMBER_ENTITIES.get(char.type)
|
if not (description := NUMBER_ENTITIES.get(char.type)):
|
||||||
if not kwargs:
|
|
||||||
return False
|
return False
|
||||||
info = {"aid": char.service.accessory.aid, "iid": char.service.iid}
|
info = {"aid": char.service.accessory.aid, "iid": char.service.iid}
|
||||||
async_add_entities([HomeKitNumber(conn, info, char, **kwargs)], True)
|
async_add_entities([HomeKitNumber(conn, info, char, description)], True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
conn.add_char_factory(async_add_characteristic)
|
conn.add_char_factory(async_add_characteristic)
|
||||||
|
@ -48,32 +51,16 @@ class HomeKitNumber(CharacteristicEntity, NumberEntity):
|
||||||
conn,
|
conn,
|
||||||
info,
|
info,
|
||||||
char,
|
char,
|
||||||
device_class=None,
|
description: NumberEntityDescription,
|
||||||
icon=None,
|
|
||||||
name=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
):
|
||||||
"""Initialise a HomeKit number control."""
|
"""Initialise a HomeKit number control."""
|
||||||
self._device_class = device_class
|
self.entity_description = description
|
||||||
self._icon = icon
|
|
||||||
self._name = name
|
|
||||||
|
|
||||||
super().__init__(conn, info, char)
|
super().__init__(conn, info, char)
|
||||||
|
|
||||||
def get_characteristic_types(self):
|
def get_characteristic_types(self):
|
||||||
"""Define the homekit characteristics the entity is tracking."""
|
"""Define the homekit characteristics the entity is tracking."""
|
||||||
return [self._char.type]
|
return [self._char.type]
|
||||||
|
|
||||||
@property
|
|
||||||
def device_class(self):
|
|
||||||
"""Return type of sensor."""
|
|
||||||
return self._device_class
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Return the sensor icon."""
|
|
||||||
return self._icon
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def min_value(self) -> float:
|
def min_value(self) -> float:
|
||||||
"""Return the minimum value."""
|
"""Return the minimum value."""
|
||||||
|
|
|
@ -1,8 +1,17 @@
|
||||||
"""Support for Homekit sensors."""
|
"""Support for Homekit sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
from aiohomekit.model.characteristics import Characteristic, CharacteristicsTypes
|
||||||
from aiohomekit.model.services import ServicesTypes
|
from aiohomekit.model.services import ServicesTypes
|
||||||
|
|
||||||
from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT, SensorEntity
|
from homeassistant.components.sensor import (
|
||||||
|
STATE_CLASS_MEASUREMENT,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
CONCENTRATION_PARTS_PER_MILLION,
|
CONCENTRATION_PARTS_PER_MILLION,
|
||||||
|
@ -32,92 +41,112 @@ from . import KNOWN_DEVICES, CharacteristicEntity, HomeKitEntity
|
||||||
CO2_ICON = "mdi:molecule-co2"
|
CO2_ICON = "mdi:molecule-co2"
|
||||||
|
|
||||||
|
|
||||||
SIMPLE_SENSOR = {
|
@dataclass
|
||||||
CharacteristicsTypes.Vendor.EVE_ENERGY_WATT: {
|
class HomeKitSensorEntityDescription(SensorEntityDescription):
|
||||||
"name": "Real Time Energy",
|
"""Describes Homekit sensor."""
|
||||||
"device_class": DEVICE_CLASS_POWER,
|
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
probe: Callable[[Characteristic], bool] | None = None
|
||||||
"unit": POWER_WATT,
|
|
||||||
},
|
|
||||||
CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: {
|
SIMPLE_SENSOR: dict[str, HomeKitSensorEntityDescription] = {
|
||||||
"name": "Real Time Energy",
|
CharacteristicsTypes.Vendor.EVE_ENERGY_WATT: HomeKitSensorEntityDescription(
|
||||||
"device_class": DEVICE_CLASS_POWER,
|
key=CharacteristicsTypes.Vendor.EVE_ENERGY_WATT,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
name="Real Time Energy",
|
||||||
"unit": POWER_WATT,
|
device_class=DEVICE_CLASS_POWER,
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY_2: {
|
native_unit_of_measurement=POWER_WATT,
|
||||||
"name": "Real Time Energy",
|
),
|
||||||
"device_class": DEVICE_CLASS_POWER,
|
CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY: HomeKitSensorEntityDescription(
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
key=CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY,
|
||||||
"unit": POWER_WATT,
|
name="Real Time Energy",
|
||||||
},
|
device_class=DEVICE_CLASS_POWER,
|
||||||
CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE: {
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"name": "Air Pressure",
|
native_unit_of_measurement=POWER_WATT,
|
||||||
"device_class": DEVICE_CLASS_PRESSURE,
|
),
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY_2: HomeKitSensorEntityDescription(
|
||||||
"unit": PRESSURE_HPA,
|
key=CharacteristicsTypes.Vendor.KOOGEEK_REALTIME_ENERGY_2,
|
||||||
},
|
name="Real Time Energy",
|
||||||
CharacteristicsTypes.TEMPERATURE_CURRENT: {
|
device_class=DEVICE_CLASS_POWER,
|
||||||
"name": "Current Temperature",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"device_class": DEVICE_CLASS_TEMPERATURE,
|
native_unit_of_measurement=POWER_WATT,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
),
|
||||||
"unit": TEMP_CELSIUS,
|
CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE: HomeKitSensorEntityDescription(
|
||||||
|
key=CharacteristicsTypes.Vendor.EVE_DEGREE_AIR_PRESSURE,
|
||||||
|
name="Air Pressure",
|
||||||
|
device_class=DEVICE_CLASS_PRESSURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=PRESSURE_HPA,
|
||||||
|
),
|
||||||
|
CharacteristicsTypes.TEMPERATURE_CURRENT: HomeKitSensorEntityDescription(
|
||||||
|
key=CharacteristicsTypes.TEMPERATURE_CURRENT,
|
||||||
|
name="Current Temperature",
|
||||||
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
# This sensor is only for temperature characteristics that are not part
|
# This sensor is only for temperature characteristics that are not part
|
||||||
# of a temperature sensor service.
|
# of a temperature sensor service.
|
||||||
"probe": lambda char: char.service.type
|
probe=lambda char: char.service.type
|
||||||
!= ServicesTypes.get_uuid(ServicesTypes.TEMPERATURE_SENSOR),
|
!= ServicesTypes.get_uuid(ServicesTypes.TEMPERATURE_SENSOR),
|
||||||
},
|
),
|
||||||
CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: {
|
CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT: HomeKitSensorEntityDescription(
|
||||||
"name": "Current Humidity",
|
key=CharacteristicsTypes.RELATIVE_HUMIDITY_CURRENT,
|
||||||
"device_class": DEVICE_CLASS_HUMIDITY,
|
name="Current Humidity",
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
"unit": PERCENTAGE,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
# This sensor is only for humidity characteristics that are not part
|
# This sensor is only for humidity characteristics that are not part
|
||||||
# of a humidity sensor service.
|
# of a humidity sensor service.
|
||||||
"probe": lambda char: char.service.type
|
probe=lambda char: char.service.type
|
||||||
!= ServicesTypes.get_uuid(ServicesTypes.HUMIDITY_SENSOR),
|
!= ServicesTypes.get_uuid(ServicesTypes.HUMIDITY_SENSOR),
|
||||||
},
|
),
|
||||||
CharacteristicsTypes.AIR_QUALITY: {
|
CharacteristicsTypes.AIR_QUALITY: HomeKitSensorEntityDescription(
|
||||||
"name": "Air Quality",
|
key=CharacteristicsTypes.AIR_QUALITY,
|
||||||
"device_class": DEVICE_CLASS_AQI,
|
name="Air Quality",
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
device_class=DEVICE_CLASS_AQI,
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
CharacteristicsTypes.DENSITY_PM25: {
|
),
|
||||||
"name": "PM2.5 Density",
|
CharacteristicsTypes.DENSITY_PM25: HomeKitSensorEntityDescription(
|
||||||
"device_class": DEVICE_CLASS_PM25,
|
key=CharacteristicsTypes.DENSITY_PM25,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
name="PM2.5 Density",
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
device_class=DEVICE_CLASS_PM25,
|
||||||
},
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
CharacteristicsTypes.DENSITY_PM10: {
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"name": "PM10 Density",
|
),
|
||||||
"device_class": DEVICE_CLASS_PM10,
|
CharacteristicsTypes.DENSITY_PM10: HomeKitSensorEntityDescription(
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
key=CharacteristicsTypes.DENSITY_PM10,
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
name="PM10 Density",
|
||||||
},
|
device_class=DEVICE_CLASS_PM10,
|
||||||
CharacteristicsTypes.DENSITY_OZONE: {
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"name": "Ozone Density",
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"device_class": DEVICE_CLASS_OZONE,
|
),
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
CharacteristicsTypes.DENSITY_OZONE: HomeKitSensorEntityDescription(
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
key=CharacteristicsTypes.DENSITY_OZONE,
|
||||||
},
|
name="Ozone Density",
|
||||||
CharacteristicsTypes.DENSITY_NO2: {
|
device_class=DEVICE_CLASS_OZONE,
|
||||||
"name": "Nitrogen Dioxide Density",
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"device_class": DEVICE_CLASS_NITROGEN_DIOXIDE,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
),
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
CharacteristicsTypes.DENSITY_NO2: HomeKitSensorEntityDescription(
|
||||||
},
|
key=CharacteristicsTypes.DENSITY_NO2,
|
||||||
CharacteristicsTypes.DENSITY_SO2: {
|
name="Nitrogen Dioxide Density",
|
||||||
"name": "Sulphur Dioxide Density",
|
device_class=DEVICE_CLASS_NITROGEN_DIOXIDE,
|
||||||
"device_class": DEVICE_CLASS_SULPHUR_DIOXIDE,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
),
|
||||||
},
|
CharacteristicsTypes.DENSITY_SO2: HomeKitSensorEntityDescription(
|
||||||
CharacteristicsTypes.DENSITY_VOC: {
|
key=CharacteristicsTypes.DENSITY_SO2,
|
||||||
"name": "Volatile Organic Compound Density",
|
name="Sulphur Dioxide Density",
|
||||||
"device_class": DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
device_class=DEVICE_CLASS_SULPHUR_DIOXIDE,
|
||||||
"state_class": STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
"unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
},
|
),
|
||||||
|
CharacteristicsTypes.DENSITY_VOC: HomeKitSensorEntityDescription(
|
||||||
|
key=CharacteristicsTypes.DENSITY_VOC,
|
||||||
|
name="Volatile Organic Compound Density",
|
||||||
|
device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||||
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
# For legacy reasons, "built-in" characteristic types are in their short form
|
# For legacy reasons, "built-in" characteristic types are in their short form
|
||||||
|
@ -285,55 +314,27 @@ class SimpleSensor(CharacteristicEntity, SensorEntity):
|
||||||
be multiple entities per HomeKit service (this was not previously the case).
|
be multiple entities per HomeKit service (this was not previously the case).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
entity_description: HomeKitSensorEntityDescription
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
conn,
|
conn,
|
||||||
info,
|
info,
|
||||||
char,
|
char,
|
||||||
device_class=None,
|
description: HomeKitSensorEntityDescription,
|
||||||
state_class=None,
|
|
||||||
unit=None,
|
|
||||||
icon=None,
|
|
||||||
name=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
):
|
||||||
"""Initialise a secondary HomeKit characteristic sensor."""
|
"""Initialise a secondary HomeKit characteristic sensor."""
|
||||||
self._device_class = device_class
|
self.entity_description = description
|
||||||
self._state_class = state_class
|
|
||||||
self._unit = unit
|
|
||||||
self._icon = icon
|
|
||||||
self._name = name
|
|
||||||
|
|
||||||
super().__init__(conn, info, char)
|
super().__init__(conn, info, char)
|
||||||
|
|
||||||
def get_characteristic_types(self):
|
def get_characteristic_types(self):
|
||||||
"""Define the homekit characteristics the entity is tracking."""
|
"""Define the homekit characteristics the entity is tracking."""
|
||||||
return [self._char.type]
|
return [self._char.type]
|
||||||
|
|
||||||
@property
|
|
||||||
def device_class(self):
|
|
||||||
"""Return type of sensor."""
|
|
||||||
return self._device_class
|
|
||||||
|
|
||||||
@property
|
|
||||||
def state_class(self):
|
|
||||||
"""Return type of state."""
|
|
||||||
return self._state_class
|
|
||||||
|
|
||||||
@property
|
|
||||||
def native_unit_of_measurement(self):
|
|
||||||
"""Return units for the sensor."""
|
|
||||||
return self._unit
|
|
||||||
|
|
||||||
@property
|
|
||||||
def icon(self):
|
|
||||||
"""Return the sensor icon."""
|
|
||||||
return self._icon
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Return the name of the device if any."""
|
"""Return the name of the device if any."""
|
||||||
return f"{super().name} - {self._name}"
|
return f"{super().name} - {self.entity_description.name}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def native_value(self):
|
def native_value(self):
|
||||||
|
@ -368,13 +369,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_add_characteristic(char: Characteristic):
|
def async_add_characteristic(char: Characteristic):
|
||||||
kwargs = SIMPLE_SENSOR.get(char.type)
|
if not (description := SIMPLE_SENSOR.get(char.type)):
|
||||||
if not kwargs:
|
|
||||||
return False
|
return False
|
||||||
if "probe" in kwargs and not kwargs["probe"](char):
|
if description.probe and not description.probe(char):
|
||||||
return False
|
return False
|
||||||
info = {"aid": char.service.accessory.aid, "iid": char.service.iid}
|
info = {"aid": char.service.accessory.aid, "iid": char.service.iid}
|
||||||
async_add_entities([SimpleSensor(conn, info, char, **kwargs)], True)
|
async_add_entities([SimpleSensor(conn, info, char, description)], True)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue