Add dynamic unit of measurement support for Overkiz sensor (#80490)

* Add dynamic unit support

* Import all units

* Fix typing

* Add fallback to CORE_ELECTRIC_POWER_CONSUMPTION_STATE_MEASURED_VALUE_TYPE

* Fix rebase

* Give priority to the more accurate attribute

* Don’t use hardcoded seconds unit

* Don’t change SensorDescription

* Rework comment
pull/88970/head
Thibaut 2023-03-01 13:46:26 +01:00 committed by GitHub
parent 85f2693353
commit 0c66346fb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 89 additions and 3 deletions

View File

@ -5,9 +5,28 @@ from datetime import timedelta
import logging import logging
from typing import Final from typing import Final
from pyoverkiz.enums import OverkizCommandParam, UIClass, UIWidget from pyoverkiz.enums import MeasuredValueType, OverkizCommandParam, UIClass, UIWidget
from homeassistant.const import Platform from homeassistant.const import (
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX,
PERCENTAGE,
Platform,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfIrradiance,
UnitOfLength,
UnitOfPower,
UnitOfPressure,
UnitOfSpeed,
UnitOfTemperature,
UnitOfTime,
UnitOfVolume,
UnitOfVolumeFlowRate,
)
DOMAIN: Final = "overkiz" DOMAIN: Final = "overkiz"
LOGGER: logging.Logger = logging.getLogger(__package__) LOGGER: logging.Logger = logging.getLogger(__package__)
@ -98,3 +117,42 @@ OVERKIZ_STATE_TO_TRANSLATION: dict[str, str] = {
OverkizCommandParam.SFC: "sfc", OverkizCommandParam.SFC: "sfc",
OverkizCommandParam.UPS: "ups", OverkizCommandParam.UPS: "ups",
} }
OVERKIZ_UNIT_TO_HA: dict[str, str] = {
MeasuredValueType.ABSOLUTE_VALUE: "",
MeasuredValueType.ANGLE_IN_DEGREES: DEGREE,
MeasuredValueType.ANGULAR_SPEED_IN_DEGREES_PER_SECOND: f"{DEGREE}/{UnitOfTime.SECONDS}",
MeasuredValueType.ELECTRICAL_ENERGY_IN_KWH: UnitOfEnergy.KILO_WATT_HOUR,
MeasuredValueType.ELECTRICAL_ENERGY_IN_WH: UnitOfEnergy.WATT_HOUR,
MeasuredValueType.ELECTRICAL_POWER_IN_KW: UnitOfPower.KILO_WATT,
MeasuredValueType.ELECTRICAL_POWER_IN_W: UnitOfPower.WATT,
MeasuredValueType.ELECTRIC_CURRENT_IN_AMPERE: UnitOfElectricCurrent.AMPERE,
MeasuredValueType.ELECTRIC_CURRENT_IN_MILLI_AMPERE: UnitOfElectricCurrent.MILLIAMPERE,
MeasuredValueType.ENERGY_IN_CAL: "cal",
MeasuredValueType.ENERGY_IN_KCAL: "kcal",
MeasuredValueType.FLOW_IN_LITRE_PER_SECOND: f"{UnitOfVolume.LITERS}/{UnitOfTime.SECONDS}",
MeasuredValueType.FLOW_IN_METER_CUBE_PER_HOUR: UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR,
MeasuredValueType.FLOW_IN_METER_CUBE_PER_SECOND: f"{UnitOfVolume.CUBIC_METERS}/{UnitOfTime.SECONDS}",
MeasuredValueType.FOSSIL_ENERGY_IN_WH: UnitOfEnergy.WATT_HOUR,
MeasuredValueType.GRADIENT_IN_PERCENTAGE_PER_SECOND: f"{PERCENTAGE}/{UnitOfTime.SECONDS}",
MeasuredValueType.LENGTH_IN_METER: UnitOfLength.METERS,
MeasuredValueType.LINEAR_SPEED_IN_METER_PER_SECOND: UnitOfSpeed.METERS_PER_SECOND,
MeasuredValueType.LUMINANCE_IN_LUX: LIGHT_LUX,
MeasuredValueType.PARTS_PER_BILLION: CONCENTRATION_PARTS_PER_BILLION,
MeasuredValueType.PARTS_PER_MILLION: CONCENTRATION_PARTS_PER_MILLION,
MeasuredValueType.PARTS_PER_QUADRILLION: "ppq",
MeasuredValueType.PARTS_PER_TRILLION: "ppt",
MeasuredValueType.POWER_PER_SQUARE_METER: UnitOfIrradiance.WATTS_PER_SQUARE_METER,
MeasuredValueType.PRESSURE_IN_HPA: UnitOfPressure.HPA,
MeasuredValueType.PRESSURE_IN_MILLI_BAR: UnitOfPressure.MBAR,
MeasuredValueType.RELATIVE_VALUE_IN_PERCENTAGE: PERCENTAGE,
MeasuredValueType.TEMPERATURE_IN_CELCIUS: UnitOfTemperature.CELSIUS,
MeasuredValueType.TEMPERATURE_IN_KELVIN: UnitOfTemperature.KELVIN,
MeasuredValueType.TIME_IN_SECOND: UnitOfTime.SECONDS,
# MeasuredValueType.VECTOR_COORDINATE: "",
MeasuredValueType.VOLTAGE_IN_MILLI_VOLT: UnitOfElectricPotential.MILLIVOLT,
MeasuredValueType.VOLTAGE_IN_VOLT: UnitOfElectricPotential.VOLT,
MeasuredValueType.VOLUME_IN_CUBIC_METER: UnitOfVolume.CUBIC_METERS,
MeasuredValueType.VOLUME_IN_GALLON: UnitOfVolume.GALLONS,
MeasuredValueType.VOLUME_IN_LITER: UnitOfVolume.LITERS,
}

View File

@ -34,7 +34,12 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
from . import HomeAssistantOverkizData from . import HomeAssistantOverkizData
from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES, OVERKIZ_STATE_TO_TRANSLATION from .const import (
DOMAIN,
IGNORED_OVERKIZ_DEVICES,
OVERKIZ_STATE_TO_TRANSLATION,
OVERKIZ_UNIT_TO_HA,
)
from .coordinator import OverkizDataUpdateCoordinator from .coordinator import OverkizDataUpdateCoordinator
from .entity import OverkizDescriptiveEntity, OverkizEntity from .entity import OverkizDescriptiveEntity, OverkizEntity
@ -473,6 +478,29 @@ class OverkizStateSensor(OverkizDescriptiveEntity, SensorEntity):
return state.value return state.value
@property
def native_unit_of_measurement(self) -> str | None:
"""Return the unit of measurement."""
if (
not (default_unit := self.entity_description.native_unit_of_measurement)
or not (state := self.device.states.get(self.entity_description.key))
or not state.value
):
return default_unit
attrs = self.device.attributes
if (unit := attrs[f"{state.name}MeasuredValueType"]) and (
unit_value := unit.value_as_str
):
return OVERKIZ_UNIT_TO_HA.get(unit_value, default_unit)
if (unit := attrs[OverkizAttribute.CORE_MEASURED_VALUE_TYPE]) and (
unit_value := unit.value_as_str
):
return OVERKIZ_UNIT_TO_HA.get(unit_value, default_unit)
return default_unit
class OverkizHomeKitSetupCodeSensor(OverkizEntity, SensorEntity): class OverkizHomeKitSetupCodeSensor(OverkizEntity, SensorEntity):
"""Representation of an Overkiz HomeKit Setup Code.""" """Representation of an Overkiz HomeKit Setup Code."""