Use EntityDescription - homekit_controller ()

This commit is contained in:
Marc Mueller 2021-10-04 01:42:25 +02:00 committed by GitHub
parent 9d671eff27
commit 3976443292
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 136 additions and 149 deletions
homeassistant/components/homekit_controller

View file

@ -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."""

View file

@ -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