python
This commit is contained in:
914
custom_components/yandex_smart_home/property_float.py
Normal file
914
custom_components/yandex_smart_home/property_float.py
Normal file
@@ -0,0 +1,914 @@
|
||||
"""Implement the Yandex Smart Home float properties."""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from contextlib import suppress
|
||||
from functools import cached_property
|
||||
import logging
|
||||
from typing import Protocol, Self
|
||||
|
||||
from homeassistant.components import air_quality, climate, fan, humidifier, light, sensor, switch, water_heater
|
||||
from homeassistant.components.air_quality import ATTR_CO2, ATTR_PM_0_1, ATTR_PM_2_5, ATTR_PM_10
|
||||
from homeassistant.components.climate import ATTR_CURRENT_HUMIDITY, ATTR_CURRENT_TEMPERATURE, ATTR_HUMIDITY
|
||||
from homeassistant.components.sensor import SensorDeviceClass
|
||||
from homeassistant.const import (
|
||||
ATTR_BATTERY_LEVEL,
|
||||
ATTR_TEMPERATURE,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
ATTR_VOLTAGE,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
PERCENTAGE,
|
||||
STATE_UNAVAILABLE,
|
||||
STATE_UNKNOWN,
|
||||
UnitOfElectricCurrent,
|
||||
UnitOfElectricPotential,
|
||||
UnitOfEnergy,
|
||||
UnitOfPower,
|
||||
UnitOfVolume,
|
||||
)
|
||||
from homeassistant.util.unit_conversion import (
|
||||
BaseUnitConverter,
|
||||
ElectricCurrentConverter,
|
||||
ElectricPotentialConverter,
|
||||
EnergyConverter,
|
||||
PowerConverter,
|
||||
TemperatureConverter,
|
||||
VolumeConverter,
|
||||
)
|
||||
|
||||
from .const import (
|
||||
ATTR_CURRENT,
|
||||
ATTR_CURRENT_CONSUMPTION,
|
||||
ATTR_ILLUMINANCE,
|
||||
ATTR_LOAD_POWER,
|
||||
ATTR_POWER,
|
||||
ATTR_TVOC,
|
||||
ATTR_WATER_LEVEL,
|
||||
STATE_CHARGING,
|
||||
STATE_EMPTY,
|
||||
STATE_LOW,
|
||||
STATE_NONE,
|
||||
STATE_NONE_UI,
|
||||
XGW3DeviceClass,
|
||||
)
|
||||
from .helpers import APIError
|
||||
from .property import STATE_PROPERTIES_REGISTRY, Property, StateProperty
|
||||
from .schema import (
|
||||
AmperageFloatPropertyParameters,
|
||||
BatteryLevelFloatPropertyParameters,
|
||||
CO2LevelFloatPropertyParameters,
|
||||
ElectricityMeterFloatPropertyParameters,
|
||||
FloatPropertyDescription,
|
||||
FloatPropertyInstance,
|
||||
FloatPropertyParameters,
|
||||
FoodLevelFloatPropertyParameters,
|
||||
GasMeterFloatPropertyParameters,
|
||||
HeatMeterFloatPropertyParameters,
|
||||
HumidityFloatPropertyParameters,
|
||||
IlluminationFloatPropertyParameters,
|
||||
MeterFloatPropertyParameters,
|
||||
PM1DensityFloatPropertyParameters,
|
||||
PM10DensityFloatPropertyParameters,
|
||||
PM25DensityFloatPropertyParameters,
|
||||
PowerFloatPropertyParameters,
|
||||
PressureFloatPropertyParameters,
|
||||
PropertyType,
|
||||
ResponseCode,
|
||||
TemperatureFloatPropertyParameters,
|
||||
TVOCFloatPropertyParameters,
|
||||
VoltageFloatPropertyParameters,
|
||||
WaterLevelFloatPropertyParameters,
|
||||
WaterMeterFloatPropertyParameters,
|
||||
)
|
||||
from .unit_conversion import PressureConverter, TVOCConcentrationConverter, UnitOfPressure, UnitOfTemperature
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FloatProperty(Property, Protocol):
|
||||
"""Base class for float properties (sensors)."""
|
||||
|
||||
type: PropertyType = PropertyType.FLOAT
|
||||
instance: FloatPropertyInstance
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def parameters(self) -> FloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
...
|
||||
|
||||
def get_description(self) -> FloatPropertyDescription:
|
||||
"""Return a description for a device list request."""
|
||||
return FloatPropertyDescription(
|
||||
retrievable=self.retrievable, reportable=self.reportable, parameters=self.parameters
|
||||
)
|
||||
|
||||
def get_value(self) -> float | None:
|
||||
"""Return the current property value."""
|
||||
value = self._get_native_value()
|
||||
|
||||
if value is None:
|
||||
return None
|
||||
|
||||
if str(value).lower() in (STATE_UNAVAILABLE, STATE_UNKNOWN, STATE_NONE, STATE_NONE_UI, STATE_EMPTY):
|
||||
return None
|
||||
|
||||
try:
|
||||
float_value = float(value)
|
||||
except (ValueError, TypeError):
|
||||
raise APIError(ResponseCode.NOT_SUPPORTED_IN_CURRENT_MODE, f"Unsupported value '{value}' for {self}")
|
||||
|
||||
if self._native_unit_of_measurement and self.unit_of_measurement and self._unit_converter:
|
||||
if self._native_unit_of_measurement in self._unit_converter.VALID_UNITS:
|
||||
float_value = self._unit_converter.convert(
|
||||
float_value, self._native_unit_of_measurement, self.unit_of_measurement
|
||||
)
|
||||
else:
|
||||
_LOGGER.warning(
|
||||
f"Unsupported unit of measurement '{self._native_unit_of_measurement}' for {self}. "
|
||||
f"Valid units are: %s" % ", ".join(sorted(map(str, self._unit_converter.VALID_UNITS)))
|
||||
)
|
||||
|
||||
lower_limit, upper_limit = self.parameters.range
|
||||
if lower_limit is not None and float_value < lower_limit:
|
||||
return lower_limit
|
||||
if upper_limit is not None and float_value > upper_limit:
|
||||
return upper_limit
|
||||
|
||||
return round(float_value, 2)
|
||||
|
||||
def check_value_change(self, other: Self | None) -> bool:
|
||||
"""Test if the property value differs from other property."""
|
||||
if other is None:
|
||||
return True
|
||||
|
||||
value, other_value = self.get_value(), other.get_value()
|
||||
if value is None:
|
||||
return False
|
||||
|
||||
if other_value is None or value != other_value:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return None
|
||||
|
||||
@abstractmethod
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
...
|
||||
|
||||
@cached_property
|
||||
@abstractmethod
|
||||
def _native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit the native value is expressed in."""
|
||||
...
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> BaseUnitConverter | None:
|
||||
"""Return the unit converter."""
|
||||
return None # pragma: nocover
|
||||
|
||||
|
||||
class TemperatureProperty(FloatProperty, ABC):
|
||||
"""Base class for temperature properties."""
|
||||
|
||||
instance = FloatPropertyInstance.TEMPERATURE
|
||||
|
||||
@property
|
||||
def parameters(self) -> TemperatureFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return TemperatureFloatPropertyParameters(unit=self.unit_of_measurement.as_property_unit)
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> UnitOfTemperature:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
if self._native_unit_of_measurement:
|
||||
with suppress(ValueError):
|
||||
unit = UnitOfTemperature(self._native_unit_of_measurement)
|
||||
if unit.as_property_unit:
|
||||
return unit
|
||||
|
||||
return UnitOfTemperature.CELSIUS
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> TemperatureConverter:
|
||||
"""Return the unit converter."""
|
||||
return TemperatureConverter()
|
||||
|
||||
|
||||
class HumidityProperty(FloatProperty, ABC):
|
||||
"""Base class for humidity properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.HUMIDITY
|
||||
|
||||
@property
|
||||
def parameters(self) -> HumidityFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return HumidityFloatPropertyParameters()
|
||||
|
||||
|
||||
class PressureProperty(FloatProperty, ABC):
|
||||
"""Base class for pressure properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.PRESSURE
|
||||
|
||||
@property
|
||||
def parameters(self) -> PressureFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PressureFloatPropertyParameters(unit=self.unit_of_measurement.as_property_unit)
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> UnitOfPressure:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
if self._native_unit_of_measurement:
|
||||
with suppress(ValueError):
|
||||
unit = UnitOfPressure(self._native_unit_of_measurement)
|
||||
if unit.as_property_unit:
|
||||
return unit
|
||||
|
||||
return UnitOfPressure.MMHG
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> PressureConverter:
|
||||
"""Return the unit converter."""
|
||||
return PressureConverter()
|
||||
|
||||
|
||||
class IlluminationProperty(FloatProperty, ABC):
|
||||
"""Base class for illumination properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.ILLUMINATION
|
||||
|
||||
@property
|
||||
def parameters(self) -> IlluminationFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return IlluminationFloatPropertyParameters()
|
||||
|
||||
|
||||
class FoodLevelPercentageProperty(FloatProperty, Protocol):
|
||||
"""Base class for food level (%) properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.FOOD_LEVEL
|
||||
|
||||
@property
|
||||
def parameters(self) -> FoodLevelFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return FoodLevelFloatPropertyParameters()
|
||||
|
||||
|
||||
class WaterLevelPercentageProperty(FloatProperty, Protocol):
|
||||
"""Base class for water level (%) properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.WATER_LEVEL
|
||||
|
||||
@property
|
||||
def parameters(self) -> WaterLevelFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return WaterLevelFloatPropertyParameters()
|
||||
|
||||
|
||||
class CO2LevelProperty(FloatProperty, Protocol):
|
||||
"""Base class for CO2 level properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.CO2_LEVEL
|
||||
|
||||
@property
|
||||
def parameters(self) -> CO2LevelFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return CO2LevelFloatPropertyParameters()
|
||||
|
||||
|
||||
class MeterProperty(FloatProperty, Protocol):
|
||||
"""Base class for meter properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.METER
|
||||
|
||||
@property
|
||||
def parameters(self) -> MeterFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return MeterFloatPropertyParameters()
|
||||
|
||||
|
||||
class ElectricityMeterProperty(FloatProperty, Protocol):
|
||||
"""Base class for electricity meter properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.ELECTRICITY_METER
|
||||
|
||||
@property
|
||||
def parameters(self) -> ElectricityMeterFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return ElectricityMeterFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> UnitOfEnergy:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfEnergy.KILO_WATT_HOUR
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> EnergyConverter:
|
||||
"""Return the unit converter."""
|
||||
return EnergyConverter()
|
||||
|
||||
|
||||
class GasMeterProperty(FloatProperty, Protocol):
|
||||
"""Base class for gas meter properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.GAS_METER
|
||||
|
||||
@property
|
||||
def parameters(self) -> GasMeterFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return GasMeterFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> UnitOfVolume:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfVolume.CUBIC_METERS
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> VolumeConverter:
|
||||
"""Return the unit converter."""
|
||||
return VolumeConverter()
|
||||
|
||||
|
||||
class HeatMeterProperty(FloatProperty, Protocol):
|
||||
"""Base class for heat meter properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.HEAT_METER
|
||||
|
||||
@property
|
||||
def parameters(self) -> HeatMeterFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return HeatMeterFloatPropertyParameters()
|
||||
|
||||
|
||||
class WaterMeterProperty(FloatProperty, Protocol):
|
||||
"""Base class for water meter properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.WATER_METER
|
||||
|
||||
@property
|
||||
def parameters(self) -> WaterMeterFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return WaterMeterFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> UnitOfVolume:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfVolume.CUBIC_METERS
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> VolumeConverter:
|
||||
"""Return the unit converter."""
|
||||
return VolumeConverter()
|
||||
|
||||
|
||||
class PM1DensityProperty(FloatProperty, Protocol):
|
||||
"""Base class for PM1 density properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.PM1_DENSITY
|
||||
|
||||
@property
|
||||
def parameters(self) -> PM1DensityFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PM1DensityFloatPropertyParameters()
|
||||
|
||||
|
||||
class PM25DensityProperty(FloatProperty, Protocol):
|
||||
"""Base class for PM2.5 density properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.PM2_5_DENSITY
|
||||
|
||||
@property
|
||||
def parameters(self) -> PM25DensityFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PM25DensityFloatPropertyParameters()
|
||||
|
||||
|
||||
class PM10DensityProperty(FloatProperty, Protocol):
|
||||
"""Base class for PM10 density properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.PM10_DENSITY
|
||||
|
||||
@property
|
||||
def parameters(self) -> PM10DensityFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PM10DensityFloatPropertyParameters()
|
||||
|
||||
|
||||
class TVOCConcentrationProperty(FloatProperty, Protocol):
|
||||
"""Base class for TVOC concentration properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.TVOC
|
||||
|
||||
@property
|
||||
def parameters(self) -> TVOCFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return TVOCFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> TVOCConcentrationConverter:
|
||||
"""Return the unit converter."""
|
||||
return TVOCConcentrationConverter()
|
||||
|
||||
|
||||
class VoltageProperty(FloatProperty, Protocol):
|
||||
"""Base class for voltage properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.VOLTAGE
|
||||
|
||||
@property
|
||||
def parameters(self) -> VoltageFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return VoltageFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfElectricPotential.VOLT
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> ElectricPotentialConverter:
|
||||
"""Return the unit converter."""
|
||||
return ElectricPotentialConverter()
|
||||
|
||||
|
||||
class ElectricCurrentProperty(FloatProperty, Protocol):
|
||||
"""Base class for electric current properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.AMPERAGE
|
||||
|
||||
@property
|
||||
def parameters(self) -> AmperageFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return AmperageFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfElectricCurrent.AMPERE
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> ElectricCurrentConverter:
|
||||
"""Return the unit converter."""
|
||||
return ElectricCurrentConverter()
|
||||
|
||||
|
||||
class ElectricPowerProperty(FloatProperty, Protocol):
|
||||
"""Base class for electric power properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.POWER
|
||||
|
||||
@property
|
||||
def parameters(self) -> PowerFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PowerFloatPropertyParameters()
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Return the unit the property value is expressed in."""
|
||||
return UnitOfPower.WATT
|
||||
|
||||
@property
|
||||
def _unit_converter(self) -> PowerConverter:
|
||||
"""Return the unit converter."""
|
||||
return PowerConverter()
|
||||
|
||||
|
||||
class BatteryLevelPercentageProperty(FloatProperty, Protocol):
|
||||
"""Base class for battery level (%) properties."""
|
||||
|
||||
instance: FloatPropertyInstance = FloatPropertyInstance.BATTERY_LEVEL
|
||||
|
||||
@property
|
||||
def parameters(self) -> BatteryLevelFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return BatteryLevelFloatPropertyParameters()
|
||||
|
||||
|
||||
class StateFloatProperty(StateProperty, FloatProperty):
|
||||
"""Base class for a float property based on the state."""
|
||||
|
||||
@cached_property
|
||||
def _native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit the native value is expressed in."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class TemperatureSensor(StateFloatProperty, TemperatureProperty):
|
||||
"""Representaton of the state as a temperature sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
if self._state_device_class == SensorDeviceClass.TEMPERATURE:
|
||||
return True
|
||||
if self.state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) in UnitOfTemperature.__members__.values():
|
||||
return True
|
||||
case air_quality.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_TEMPERATURE) is not None
|
||||
case climate.DOMAIN | fan.DOMAIN | humidifier.DOMAIN | water_heater.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_CURRENT_TEMPERATURE) is not None
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
match self.state.domain:
|
||||
case air_quality.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_TEMPERATURE)
|
||||
case climate.DOMAIN | fan.DOMAIN | humidifier.DOMAIN | water_heater.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_CURRENT_TEMPERATURE)
|
||||
|
||||
return self.state.state
|
||||
|
||||
|
||||
class HumiditySensor(StateFloatProperty, HumidityProperty):
|
||||
"""Representaton of the state as a humidity sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class in (SensorDeviceClass.HUMIDITY, SensorDeviceClass.MOISTURE)
|
||||
case air_quality.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_HUMIDITY) is not None
|
||||
case climate.DOMAIN | fan.DOMAIN | humidifier.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_CURRENT_HUMIDITY) is not None
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
match self.state.domain:
|
||||
case air_quality.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_HUMIDITY)
|
||||
case climate.DOMAIN | fan.DOMAIN | humidifier.DOMAIN:
|
||||
return self.state.attributes.get(ATTR_CURRENT_HUMIDITY)
|
||||
|
||||
return self.state.state
|
||||
|
||||
|
||||
class PressureSensor(StateFloatProperty, PressureProperty):
|
||||
"""Representaton of the state as a pressure sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
return self.state.domain == sensor.DOMAIN and self._state_device_class in (
|
||||
SensorDeviceClass.PRESSURE,
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE,
|
||||
)
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.state
|
||||
|
||||
|
||||
class IlluminationSensor(StateFloatProperty, IlluminationProperty):
|
||||
"""Representaton of the state as a illumination sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
if self.state.domain == sensor.DOMAIN and self._state_device_class == SensorDeviceClass.ILLUMINANCE:
|
||||
return True
|
||||
|
||||
if self.state.domain in (sensor.DOMAIN, light.DOMAIN, fan.DOMAIN):
|
||||
return ATTR_ILLUMINANCE in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN and self._state_device_class == SensorDeviceClass.ILLUMINANCE:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_ILLUMINANCE)
|
||||
|
||||
|
||||
class WaterLevelPercentageSensor(StateFloatProperty, WaterLevelPercentageProperty):
|
||||
"""Representaton of the state as a water level sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
if self.state.domain in (fan.DOMAIN, humidifier.DOMAIN):
|
||||
return ATTR_WATER_LEVEL in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.attributes.get(ATTR_WATER_LEVEL)
|
||||
|
||||
|
||||
class CO2LevelSensor(StateFloatProperty, CO2LevelProperty):
|
||||
"""Representaton of the state as a CO2 level sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.CO2
|
||||
case air_quality.DOMAIN | fan.DOMAIN:
|
||||
return ATTR_CO2 in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_CO2)
|
||||
|
||||
|
||||
class ElectricityMeterSensor(StateFloatProperty, ElectricityMeterProperty):
|
||||
"""Representaton of the state as a electricity meter sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
return self.state.domain == sensor.DOMAIN and self._state_device_class == SensorDeviceClass.ENERGY
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.state
|
||||
|
||||
|
||||
class GasMeterSensor(StateFloatProperty, GasMeterProperty):
|
||||
"""Representaton of the state as a gas meter sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
return self.state.domain == sensor.DOMAIN and self._state_device_class == SensorDeviceClass.GAS
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.state
|
||||
|
||||
|
||||
class WaterMeterSensor(StateFloatProperty, WaterMeterProperty):
|
||||
"""Representaton of the state as a water meter sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
return self.state.domain == sensor.DOMAIN and self._state_device_class == SensorDeviceClass.WATER
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.state
|
||||
|
||||
|
||||
class PM1DensitySensor(StateFloatProperty, PM1DensityProperty):
|
||||
"""Representaton of the state as a PM1 density sensor."""
|
||||
|
||||
instance = FloatPropertyInstance.PM1_DENSITY
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.PM1
|
||||
case air_quality.DOMAIN:
|
||||
return ATTR_PM_0_1 in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
@property
|
||||
def parameters(self) -> PM1DensityFloatPropertyParameters:
|
||||
"""Return parameters for a devices list request."""
|
||||
return PM1DensityFloatPropertyParameters()
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_PM_0_1)
|
||||
|
||||
|
||||
class PM25DensitySensor(StateFloatProperty, PM25DensityProperty):
|
||||
"""Representaton of the state as a PM2.5 density sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.PM25
|
||||
case air_quality.DOMAIN:
|
||||
return ATTR_PM_2_5 in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_PM_2_5)
|
||||
|
||||
|
||||
class PM10DensitySensor(StateFloatProperty, PM10DensityProperty):
|
||||
"""Representaton of the state as a PM10 density sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.PM10
|
||||
case air_quality.DOMAIN:
|
||||
return ATTR_PM_10 in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_PM_10)
|
||||
|
||||
|
||||
class TVOCConcentrationSensor(StateFloatProperty, TVOCConcentrationProperty):
|
||||
"""Representaton of the state as a TVOC concentration sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class in (
|
||||
SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
|
||||
XGW3DeviceClass.TVOC,
|
||||
)
|
||||
case air_quality.DOMAIN:
|
||||
return ATTR_TVOC in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_TVOC)
|
||||
|
||||
|
||||
class VOCConcentrationSensor(StateFloatProperty, TVOCConcentrationProperty):
|
||||
"""Representaton of the state as a VOC concentration sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
return (
|
||||
self.state.domain == sensor.DOMAIN
|
||||
and self._state_device_class == SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS
|
||||
)
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
return self.state.state
|
||||
|
||||
@property
|
||||
def _native_unit_of_measurement(self) -> str | None:
|
||||
return None
|
||||
|
||||
|
||||
class VoltageSensor(StateFloatProperty, VoltageProperty):
|
||||
"""Representaton of the state as a voltage sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.VOLTAGE
|
||||
case switch.DOMAIN | light.DOMAIN:
|
||||
return ATTR_VOLTAGE in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_VOLTAGE)
|
||||
|
||||
|
||||
class ElectricCurrentSensor(StateFloatProperty, ElectricCurrentProperty):
|
||||
"""Representaton of the state as a electric current sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
match self.state.domain:
|
||||
case sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.CURRENT
|
||||
case switch.DOMAIN | light.DOMAIN:
|
||||
return ATTR_CURRENT in self.state.attributes
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self.state.state
|
||||
|
||||
return self.state.attributes.get(ATTR_CURRENT)
|
||||
|
||||
|
||||
class ElectricPowerSensor(StateFloatProperty, ElectricPowerProperty):
|
||||
"""Representaton of the state as a electric power sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
if self.state.domain == sensor.DOMAIN:
|
||||
return self._state_device_class == SensorDeviceClass.POWER
|
||||
|
||||
if self.state.domain == switch.DOMAIN:
|
||||
for attribute in (ATTR_POWER, ATTR_LOAD_POWER, ATTR_CURRENT_CONSUMPTION):
|
||||
if attribute in self.state.attributes:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
if self.state.domain == switch.DOMAIN:
|
||||
for attribute in (ATTR_POWER, ATTR_LOAD_POWER, ATTR_CURRENT_CONSUMPTION):
|
||||
if attribute in self.state.attributes:
|
||||
return self.state.attributes.get(attribute)
|
||||
|
||||
return self.state.state
|
||||
|
||||
|
||||
class BatteryLevelPercentageSensor(StateFloatProperty, BatteryLevelPercentageProperty):
|
||||
"""Representaton of the state as battery level sensor."""
|
||||
|
||||
@property
|
||||
def supported(self) -> bool:
|
||||
"""Test if the property is supported."""
|
||||
if (
|
||||
self._state_device_class == SensorDeviceClass.BATTERY
|
||||
and self.state.attributes.get(ATTR_UNIT_OF_MEASUREMENT) == PERCENTAGE
|
||||
):
|
||||
return True
|
||||
|
||||
return ATTR_BATTERY_LEVEL in self.state.attributes
|
||||
|
||||
def _get_native_value(self) -> float | str | None:
|
||||
"""Return the current property value without conversion."""
|
||||
value = None
|
||||
if self._state_device_class == SensorDeviceClass.BATTERY:
|
||||
value = self.state.state
|
||||
elif ATTR_BATTERY_LEVEL in self.state.attributes:
|
||||
value = self.state.attributes.get(ATTR_BATTERY_LEVEL)
|
||||
|
||||
if value in [STATE_LOW, STATE_CHARGING]:
|
||||
return 0
|
||||
|
||||
return value
|
||||
|
||||
|
||||
STATE_PROPERTIES_REGISTRY.register(TemperatureSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(HumiditySensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(PressureSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(IlluminationSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(WaterLevelPercentageSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(CO2LevelSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(ElectricityMeterSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(GasMeterSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(WaterMeterSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(PM1DensitySensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(PM25DensitySensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(PM10DensitySensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(TVOCConcentrationSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(VOCConcentrationSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(VoltageSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(ElectricCurrentSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(ElectricPowerSensor)
|
||||
STATE_PROPERTIES_REGISTRY.register(BatteryLevelPercentageSensor)
|
||||
Reference in New Issue
Block a user