diff --git a/tests/test_discover.py b/tests/test_discover.py index 7455849e0..099c81e4c 100644 --- a/tests/test_discover.py +++ b/tests/test_discover.py @@ -30,7 +30,6 @@ QuirkBuilder, ZCLSensorMetadata, ) -from zigpy.quirks.v2.homeassistant import UnitOfTime import zigpy.types from zigpy.zcl import ClusterType import zigpy.zcl.clusters.closures @@ -317,7 +316,7 @@ async def test_quirks_v2_entity_discovery( min_value=1, max_value=100, step=1, - unit=UnitOfTime.SECONDS, + unit="s", multiplier=1, translation_key="off_wait_time", fallback_name="Off wait time", @@ -518,7 +517,7 @@ def _get_test_device( min_value=1, max_value=100, step=1, - unit=UnitOfTime.SECONDS, + unit="s", multiplier=1, translation_key="on_off_transition_time", fallback_name="On off transition time", @@ -529,7 +528,7 @@ def _get_test_device( min_value=1, max_value=100, step=1, - unit=UnitOfTime.SECONDS, + unit="s", multiplier=1, translation_key="on_off_transition_time", fallback_name="On off transition time", diff --git a/tests/test_sensor.py b/tests/test_sensor.py index 25bbb4a36..130244188 100644 --- a/tests/test_sensor.py +++ b/tests/test_sensor.py @@ -35,9 +35,8 @@ from zha.application.const import ZHA_CLUSTER_HANDLER_READS_PER_REQ from zha.application.gateway import Gateway from zha.application.platforms import PlatformEntity, sensor -from zha.application.platforms.sensor import DanfossSoftwareErrorCode, UnitOfMass +from zha.application.platforms.sensor import DanfossSoftwareErrorCode from zha.application.platforms.sensor.const import SensorDeviceClass -from zha.units import PERCENTAGE, UnitOfEnergy, UnitOfPressure, UnitOfVolume from zha.zigbee.device import Device EMAttrs = homeautomation.ElectricalMeasurement.AttributeDefs @@ -193,7 +192,7 @@ async def async_test_smart_energy_summation_delivered( await send_attributes_report( zha_gateway, cluster, {1025: 1, "current_summ_delivered": 12321, 1026: 100} ) - assert_state(entity, 12.321, UnitOfEnergy.KILO_WATT_HOUR) + assert_state(entity, 12.321, "kWh") assert entity.state["status"] == "NO_ALARMS" assert entity.state["device_type"] == "Electric Metering" assert entity.info_object.device_class == SensorDeviceClass.ENERGY @@ -207,7 +206,7 @@ async def async_test_smart_energy_summation_received( await send_attributes_report( zha_gateway, cluster, {1025: 1, "current_summ_received": 12321, 1026: 100} ) - assert_state(entity, 12.321, UnitOfEnergy.KILO_WATT_HOUR) + assert_state(entity, 12.321, "kWh") assert entity.state["status"] == "NO_ALARMS" assert entity.state["device_type"] == "Electric Metering" assert entity.info_object.device_class == SensorDeviceClass.ENERGY @@ -284,17 +283,17 @@ async def async_test_em_power_factor( # update divisor cached value await send_attributes_report(zha_gateway, cluster, {"ac_power_divisor": 1}) await send_attributes_report(zha_gateway, cluster, {0: 1, 0x0510: 100, 10: 1000}) - assert_state(entity, 100, PERCENTAGE) + assert_state(entity, 100, "%") await send_attributes_report(zha_gateway, cluster, {0: 1, 0x0510: 99, 10: 1000}) - assert_state(entity, 99, PERCENTAGE) + assert_state(entity, 99, "%") await send_attributes_report(zha_gateway, cluster, {"ac_power_divisor": 10}) await send_attributes_report(zha_gateway, cluster, {0: 1, 0x0510: 100, 10: 5000}) - assert_state(entity, 100, PERCENTAGE) + assert_state(entity, 100, "%") await send_attributes_report(zha_gateway, cluster, {0: 1, 0x0510: 99, 10: 5000}) - assert_state(entity, 99, PERCENTAGE) + assert_state(entity, 99, "%") async def async_test_em_rms_current( @@ -884,73 +883,73 @@ async def test_unsupported_attributes_sensor( 1, 12320, 1.23, - UnitOfVolume.CUBIC_METERS, + "m³", ), ( 1, 1232000, 123.2, - UnitOfVolume.CUBIC_METERS, + "m³", ), ( 3, 2340, 0.23, - UnitOfVolume.CUBIC_FEET, + "ft³", ), ( 3, 2360, 0.24, - UnitOfVolume.CUBIC_FEET, + "ft³", ), ( 8, 23660, 2.37, - UnitOfPressure.KPA, + "kPa", ), ( 0, 9366, 0.937, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 999, 0.1, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 10091, 1.009, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 10099, 1.01, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 100999, 10.1, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 100023, 10.002, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 0, 102456, 10.246, - UnitOfEnergy.KILO_WATT_HOUR, + "kWh", ), ( 5, @@ -962,7 +961,7 @@ async def test_unsupported_attributes_sensor( 7, 50124, 5.01, - UnitOfVolume.LITERS, + "L", ), ), ) @@ -1241,7 +1240,7 @@ def __init__(self, *args, **kwargs) -> None: OppleCluster.cluster_id, divisor=1, multiplier=1, - unit=UnitOfMass.GRAMS, + unit="g", translation_key="last_feeding_size", fallback_name="Last feeding size", ) diff --git a/tests/test_units.py b/tests/test_units.py deleted file mode 100644 index 45e7a77f4..000000000 --- a/tests/test_units.py +++ /dev/null @@ -1,30 +0,0 @@ -"""Tests for units.""" - -import enum - -import pytest -from zigpy.quirks.v2.homeassistant import UnitOfPower as QuirksUnitOfPower - -from zha.units import UnitOfPower, validate_unit - - -def test_unit_validation() -> None: - """Test unit validation.""" - - assert validate_unit(QuirksUnitOfPower.WATT) == UnitOfPower.WATT - - class FooUnit(enum.Enum): - """Foo unit.""" - - BAR = "bar" - - class UnitOfMass(enum.Enum): - """UnitOfMass.""" - - BAR = "bar" - - with pytest.raises(KeyError): - validate_unit(FooUnit.BAR) - - with pytest.raises(ValueError): - validate_unit(UnitOfMass.BAR) diff --git a/zha/application/platforms/climate/__init__.py b/zha/application/platforms/climate/__init__.py index c0ba9851b..6d2b2cbdd 100644 --- a/zha/application/platforms/climate/__init__.py +++ b/zha/application/platforms/climate/__init__.py @@ -39,7 +39,6 @@ ) from zha.application.registries import PLATFORM_ENTITIES from zha.decorators import periodic -from zha.units import UnitOfTemperature from zha.zigbee.cluster_handlers import ClusterAttributeUpdatedEvent from zha.zigbee.cluster_handlers.const import ( CLUSTER_HANDLER_ATTRIBUTE_UPDATED, @@ -81,7 +80,7 @@ class Thermostat(PlatformEntity): DEFAULT_MIN_TEMP = 7 _attr_precision = PRECISION_TENTHS - _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_temperature_unit = "°C" _attr_translation_key: str = "thermostat" _enable_turn_on_off_backwards_compatibility = False _attr_extra_state_attribute_names: set[str] = { diff --git a/zha/application/platforms/number/__init__.py b/zha/application/platforms/number/__init__.py index 4bb0468db..090dfe279 100644 --- a/zha/application/platforms/number/__init__.py +++ b/zha/application/platforms/number/__init__.py @@ -22,7 +22,6 @@ NumberMode, ) from zha.application.registries import PLATFORM_ENTITIES -from zha.units import UnitOfMass, UnitOfTemperature, UnitOfTime, validate_unit from zha.zigbee.cluster_handlers import ClusterAttributeUpdatedEvent from zha.zigbee.cluster_handlers.const import ( CLUSTER_HANDLER_ANALOG_OUTPUT, @@ -266,9 +265,7 @@ def _init_from_quirks_metadata(self, entity_metadata: NumberMetadata) -> None: _LOGGER, ) if entity_metadata.unit is not None: - self._attr_native_unit_of_measurement = validate_unit( - entity_metadata.unit - ).value + self._attr_native_unit_of_measurement = entity_metadata.unit @functools.cached_property def info_object(self) -> NumberConfigurationEntityInfo: @@ -814,7 +811,7 @@ class AqaraPetFeederPortionWeight(NumberConfigurationEntity): _attr_translation_key: str = "portion_weight" _attr_mode: NumberMode = NumberMode.BOX - _attr_native_unit_of_measurement: str = UnitOfMass.GRAMS + _attr_native_unit_of_measurement: str = "g" @CONFIG_DIAGNOSTIC_MATCH( @@ -832,7 +829,7 @@ class AqaraThermostatAwayTemp(NumberConfigurationEntity): _attr_translation_key: str = "away_preset_temperature" _attr_mode: NumberMode = NumberMode.SLIDER - _attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement: str = "°C" @CONFIG_DIAGNOSTIC_MATCH( @@ -851,7 +848,7 @@ class ThermostatLocalTempCalibration(NumberConfigurationEntity): _attr_translation_key: str = "local_temperature_calibration" _attr_mode: NumberMode = NumberMode.BOX - _attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement: str = "°C" @CONFIG_DIAGNOSTIC_MATCH( @@ -886,7 +883,7 @@ class SonoffPresenceSenorTimeout(NumberConfigurationEntity): class ZCLTemperatureEntity(NumberConfigurationEntity): """Common entity class for ZCL temperature input.""" - _attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement: str = "°C" _attr_mode: NumberMode = NumberMode.BOX _attr_native_step: float = 0.01 _attr_multiplier: float = 0.01 @@ -957,7 +954,7 @@ class DanfossExerciseTriggerTime(NumberConfigurationEntity): _attr_native_min_value: int = 0 _attr_native_max_value: int = 1439 _attr_mode: NumberMode = NumberMode.BOX - _attr_native_unit_of_measurement: str = UnitOfTime.MINUTES + _attr_native_unit_of_measurement: str = "min" @CONFIG_DIAGNOSTIC_MATCH( @@ -1000,7 +997,7 @@ class DanfossRegulationSetpointOffset(NumberConfigurationEntity): _attribute_name: str = "regulation_setpoint_offset" _attr_translation_key: str = "regulation_setpoint_offset" _attr_mode: NumberMode = NumberMode.BOX - _attr_native_unit_of_measurement: str = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement: str = "°C" _attr_native_min_value: float = -2.5 _attr_native_max_value: float = 2.5 _attr_native_step: float = 0.1 diff --git a/zha/application/platforms/sensor/__init__.py b/zha/application/platforms/sensor/__init__.py index f5341d98c..5387b1ca1 100644 --- a/zha/application/platforms/sensor/__init__.py +++ b/zha/application/platforms/sensor/__init__.py @@ -37,27 +37,6 @@ ) from zha.application.registries import PLATFORM_ENTITIES from zha.decorators import periodic -from zha.units import ( - CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, - CONCENTRATION_PARTS_PER_BILLION, - CONCENTRATION_PARTS_PER_MILLION, - LIGHT_LUX, - PERCENTAGE, - SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - UnitOfApparentPower, - UnitOfElectricCurrent, - UnitOfElectricPotential, - UnitOfEnergy, - UnitOfFrequency, - UnitOfMass, - UnitOfPower, - UnitOfPressure, - UnitOfTemperature, - UnitOfTime, - UnitOfVolume, - UnitOfVolumeFlowRate, - validate_unit, -) from zha.zigbee.cluster_handlers import ClusterAttributeUpdatedEvent from zha.zigbee.cluster_handlers.const import ( CLUSTER_HANDLER_ANALOG_INPUT, @@ -217,9 +196,7 @@ def _init_from_quirks_metadata(self, entity_metadata: ZCLSensorMetadata) -> None _LOGGER, ) if entity_metadata.unit is not None: - self._attr_native_unit_of_measurement = validate_unit( - entity_metadata.unit - ).value + self._attr_native_unit_of_measurement = entity_metadata.unit @functools.cached_property def info_object(self) -> SensorEntityInfo: @@ -539,7 +516,7 @@ class Battery(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.BATTERY _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_entity_category = EntityCategory.DIAGNOSTIC - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" _attr_extra_state_attribute_names: set[str] = { "battery_size", "battery_quantity", @@ -602,7 +579,7 @@ class ElectricalMeasurement(PollableSensor): _attribute_name = "active_power" _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT - _attr_native_unit_of_measurement: str = UnitOfPower.WATT + _attr_native_unit_of_measurement: str = "W" _div_mul_prefix: str | None = "ac_power" def __init__( @@ -670,7 +647,7 @@ class ElectricalMeasurementApparentPower(PolledElectricalMeasurement): _unique_id_suffix = "apparent_power" _use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor _attr_device_class: SensorDeviceClass = SensorDeviceClass.APPARENT_POWER - _attr_native_unit_of_measurement = UnitOfApparentPower.VOLT_AMPERE + _attr_native_unit_of_measurement = "VA" _div_mul_prefix = "ac_power" @@ -682,7 +659,7 @@ class ElectricalMeasurementRMSCurrent(PolledElectricalMeasurement): _unique_id_suffix = "rms_current" _use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor _attr_device_class: SensorDeviceClass = SensorDeviceClass.CURRENT - _attr_native_unit_of_measurement = UnitOfElectricCurrent.AMPERE + _attr_native_unit_of_measurement = "A" _div_mul_prefix = "ac_current" @@ -694,7 +671,7 @@ class ElectricalMeasurementRMSVoltage(PolledElectricalMeasurement): _unique_id_suffix = "rms_voltage" _use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor _attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLTAGE - _attr_native_unit_of_measurement = UnitOfElectricPotential.VOLT + _attr_native_unit_of_measurement = "V" _div_mul_prefix = "ac_voltage" @@ -707,7 +684,7 @@ class ElectricalMeasurementFrequency(PolledElectricalMeasurement): _use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor _attr_device_class: SensorDeviceClass = SensorDeviceClass.FREQUENCY _attr_translation_key: str = "ac_frequency" - _attr_native_unit_of_measurement = UnitOfFrequency.HERTZ + _attr_native_unit_of_measurement = "Hz" _div_mul_prefix = "ac_frequency" @@ -719,7 +696,7 @@ class ElectricalMeasurementPowerFactor(PolledElectricalMeasurement): _unique_id_suffix = "power_factor" _use_custom_polling = False # Poll indirectly by ElectricalMeasurementSensor _attr_device_class: SensorDeviceClass = SensorDeviceClass.POWER_FACTOR - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" _div_mul_prefix = None @@ -738,7 +715,7 @@ class Humidity(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.HUMIDITY _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _divisor = 100 - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_SOIL_MOISTURE) @@ -750,7 +727,7 @@ class SoilMoisture(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_translation_key: str = "soil_moisture" _divisor = 100 - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_LEAF_WETNESS) @@ -762,7 +739,7 @@ class LeafWetness(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_translation_key: str = "leaf_wetness" _divisor = 100 - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_ILLUMINANCE) @@ -772,7 +749,7 @@ class Illuminance(Sensor): _attribute_name = "measured_value" _attr_device_class: SensorDeviceClass = SensorDeviceClass.ILLUMINANCE _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT - _attr_native_unit_of_measurement = LIGHT_LUX + _attr_native_unit_of_measurement = "lx" def formatter(self, value: int) -> int | None: """Convert illumination data.""" @@ -813,49 +790,49 @@ class SmartEnergyMetering(PollableSensor): _ENTITY_DESCRIPTION_MAP = { 0x00: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfPower.WATT, + native_unit_of_measurement="W", device_class=SensorDeviceClass.POWER, ), 0x01: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR, + native_unit_of_measurement="m³/h", device_class=None, # volume flow rate is not supported yet ), 0x02: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_FEET_PER_MINUTE, + native_unit_of_measurement="ft³/min", device_class=None, # volume flow rate is not supported yet ), 0x03: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR, + native_unit_of_measurement="m³/h", device_class=None, # volume flow rate is not supported yet scale=100, ), 0x04: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=f"{UnitOfVolume.GALLONS}/{UnitOfTime.HOURS}", # US gallons per hour + native_unit_of_measurement=f"{"gal"}/{"h"}", # US gallons per hour device_class=None, # volume flow rate is not supported yet ), 0x05: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=f"IMP {UnitOfVolume.GALLONS}/{UnitOfTime.HOURS}", # IMP gallons per hour + native_unit_of_measurement=f"IMP {"gal"}/{"h"}", # IMP gallons per hour device_class=None, # needs to be None as imperial gallons are not supported ), 0x06: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfPower.BTU_PER_HOUR, + native_unit_of_measurement="BTU/h", device_class=None, state_class=None, ), 0x07: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=f"l/{UnitOfTime.HOURS}", + native_unit_of_measurement=f"l/{"h"}", device_class=None, # volume flow rate is not supported yet ), 0x08: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfPressure.KPA, + native_unit_of_measurement="kPa", device_class=SensorDeviceClass.PRESSURE, ), # gauge 0x09: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=UnitOfPressure.KPA, + native_unit_of_measurement="kPa", device_class=SensorDeviceClass.PRESSURE, ), # absolute 0x0A: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=f"{UnitOfVolume.CUBIC_FEET}/{UnitOfTime.HOURS}", # cubic feet per hour + native_unit_of_measurement=f"{"ft³"}/{"h"}", # cubic feet per hour device_class=None, # volume flow rate is not supported yet scale=1000, ), @@ -863,7 +840,7 @@ class SmartEnergyMetering(PollableSensor): native_unit_of_measurement="unitless", device_class=None, state_class=None ), 0x0C: SmartEnergyMeteringEntityDescription( - native_unit_of_measurement=f"{UnitOfEnergy.MEGA_JOULE}/{UnitOfTime.SECONDS}", + native_unit_of_measurement=f"{"MJ"}/{"s"}", device_class=None, # needs to be None as MJ/s is not supported ), } @@ -930,49 +907,49 @@ class SmartEnergySummation(SmartEnergyMetering): _ENTITY_DESCRIPTION_MAP = { 0x00: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + native_unit_of_measurement="kWh", device_class=SensorDeviceClass.ENERGY, ), 0x01: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.CUBIC_METERS, + native_unit_of_measurement="m³", device_class=SensorDeviceClass.VOLUME, ), 0x02: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.CUBIC_FEET, + native_unit_of_measurement="ft³", device_class=SensorDeviceClass.VOLUME, ), 0x03: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.CUBIC_FEET, + native_unit_of_measurement="ft³", device_class=SensorDeviceClass.VOLUME, scale=100, ), 0x04: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.GALLONS, # US gallons + native_unit_of_measurement="gal", # US gallons device_class=SensorDeviceClass.VOLUME, ), 0x05: SmartEnergySummationEntityDescription( - native_unit_of_measurement=f"IMP {UnitOfVolume.GALLONS}", + native_unit_of_measurement=f"IMP {"gal"}", device_class=None, # needs to be None as imperial gallons are not supported ), 0x06: SmartEnergySummationEntityDescription( native_unit_of_measurement="BTU", device_class=None, state_class=None ), 0x07: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.LITERS, + native_unit_of_measurement="L", device_class=SensorDeviceClass.VOLUME, ), 0x08: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfPressure.KPA, + native_unit_of_measurement="kPa", device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, ), # gauge 0x09: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfPressure.KPA, + native_unit_of_measurement="kPa", device_class=SensorDeviceClass.PRESSURE, state_class=SensorStateClass.MEASUREMENT, ), # absolute 0x0A: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfVolume.CUBIC_FEET, + native_unit_of_measurement="ft³", device_class=SensorDeviceClass.VOLUME, scale=1000, ), @@ -980,7 +957,7 @@ class SmartEnergySummation(SmartEnergyMetering): native_unit_of_measurement="unitless", device_class=None, state_class=None ), 0x0C: SmartEnergySummationEntityDescription( - native_unit_of_measurement=UnitOfEnergy.MEGA_JOULE, + native_unit_of_measurement="MJ", device_class=SensorDeviceClass.ENERGY, ), } @@ -1130,7 +1107,7 @@ class Pressure(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.PRESSURE _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 - _attr_native_unit_of_measurement = UnitOfPressure.HPA + _attr_native_unit_of_measurement = "hPa" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_FLOW) @@ -1141,7 +1118,7 @@ class Flow(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.VOLUME_FLOW_RATE _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _divisor = 10 - _attr_native_unit_of_measurement = UnitOfVolumeFlowRate.CUBIC_METERS_PER_HOUR + _attr_native_unit_of_measurement = "m³/h" def formatter(self, value: int) -> datetime | int | float | str | None: """Handle unknown value state.""" @@ -1158,7 +1135,7 @@ class Temperature(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.TEMPERATURE _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _divisor = 100 - _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement = "°C" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_DEVICE_TEMPERATURE) @@ -1170,7 +1147,7 @@ class DeviceTemperature(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_translation_key: str = "device_temperature" _divisor = 100 - _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement = "°C" _attr_entity_category = EntityCategory.DIAGNOSTIC @@ -1182,7 +1159,7 @@ class InovelliInternalTemperature(Sensor): _attr_device_class: SensorDeviceClass = SensorDeviceClass.TEMPERATURE _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_translation_key: str = "internal_temp_monitor" - _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS + _attr_native_unit_of_measurement = "°C" _attr_entity_category = EntityCategory.DIAGNOSTIC @@ -1213,7 +1190,7 @@ class CarbonDioxideConcentration(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 _multiplier = 1e6 - _attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION + _attr_native_unit_of_measurement = "ppm" @MULTI_MATCH(cluster_handler_names="carbon_monoxide_concentration") @@ -1225,7 +1202,7 @@ class CarbonMonoxideConcentration(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 _multiplier = 1e6 - _attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION + _attr_native_unit_of_measurement = "ppm" @MULTI_MATCH(generic_ids="cluster_handler_0x042e", stop_on_match_group="voc_level") @@ -1238,7 +1215,7 @@ class VOCLevel(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 _multiplier = 1e6 - _attr_native_unit_of_measurement = CONCENTRATION_MICROGRAMS_PER_CUBIC_METER + _attr_native_unit_of_measurement = "µg/m³" @MULTI_MATCH( @@ -1256,7 +1233,7 @@ class PPBVOCLevel(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 _multiplier = 1 - _attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_BILLION + _attr_native_unit_of_measurement = "ppb" @MULTI_MATCH(cluster_handler_names="pm25") @@ -1268,7 +1245,7 @@ class PM25(Sensor): _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _decimals = 0 _multiplier = 1 - _attr_native_unit_of_measurement = CONCENTRATION_MICROGRAMS_PER_CUBIC_METER + _attr_native_unit_of_measurement = "µg/m³" @MULTI_MATCH(cluster_handler_names="formaldehyde_concentration") @@ -1280,7 +1257,7 @@ class FormaldehydeConcentration(Sensor): _attr_translation_key: str = "formaldehyde" _decimals = 0 _multiplier = 1e6 - _attr_native_unit_of_measurement = CONCENTRATION_PARTS_PER_MILLION + _attr_native_unit_of_measurement = "ppm" @MULTI_MATCH( @@ -1425,7 +1402,7 @@ class RSSISensor(Sensor): _unique_id_suffix = "rssi" _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_device_class: SensorDeviceClass | None = SensorDeviceClass.SIGNAL_STRENGTH - _attr_native_unit_of_measurement: str | None = SIGNAL_STRENGTH_DECIBELS_MILLIWATT + _attr_native_unit_of_measurement: str | None = "dBm" _attr_entity_category = EntityCategory.DIAGNOSTIC _attr_entity_registry_enabled_default = False _attr_translation_key: str = "rssi" @@ -1523,7 +1500,7 @@ class TimeLeft(Sensor): _unique_id_suffix = "time_left" _attr_device_class: SensorDeviceClass = SensorDeviceClass.DURATION _attr_translation_key: str = "timer_time_left" - _attr_native_unit_of_measurement = UnitOfTime.MINUTES + _attr_native_unit_of_measurement = "min" @MULTI_MATCH(cluster_handler_names="ikea_airpurifier") @@ -1534,7 +1511,7 @@ class IkeaDeviceRunTime(Sensor): _unique_id_suffix = "device_run_time" _attr_device_class: SensorDeviceClass = SensorDeviceClass.DURATION _attr_translation_key: str = "device_run_time" - _attr_native_unit_of_measurement = UnitOfTime.MINUTES + _attr_native_unit_of_measurement = "min" _attr_entity_category: EntityCategory = EntityCategory.DIAGNOSTIC @@ -1546,7 +1523,7 @@ class IkeaFilterRunTime(Sensor): _unique_id_suffix = "filter_run_time" _attr_device_class: SensorDeviceClass = SensorDeviceClass.DURATION _attr_translation_key: str = "filter_run_time" - _attr_native_unit_of_measurement = UnitOfTime.MINUTES + _attr_native_unit_of_measurement = "min" _attr_entity_category: EntityCategory = EntityCategory.DIAGNOSTIC @@ -1593,7 +1570,7 @@ class AqaraPetFeederWeightDispensed(Sensor): _attribute_name = "weight_dispensed" _unique_id_suffix = "weight_dispensed" _attr_translation_key: str = "weight_dispensed_today" - _attr_native_unit_of_measurement = UnitOfMass.GRAMS + _attr_native_unit_of_measurement = "g" _attr_state_class: SensorStateClass = SensorStateClass.TOTAL_INCREASING @@ -1636,7 +1613,7 @@ class PiHeatingDemand(Sensor): _unique_id_suffix = "pi_heating_demand" _attribute_name = "pi_heating_demand" _attr_translation_key: str = "pi_heating_demand" - _attr_native_unit_of_measurement = PERCENTAGE + _attr_native_unit_of_measurement = "%" _decimals = 0 _attr_state_class: SensorStateClass = SensorStateClass.MEASUREMENT _attr_entity_category = EntityCategory.DIAGNOSTIC diff --git a/zha/units.py b/zha/units.py deleted file mode 100644 index 47c4b8d6b..000000000 --- a/zha/units.py +++ /dev/null @@ -1,181 +0,0 @@ -"""Units of measure for Zigbee Home Automation.""" - -from enum import Enum, StrEnum -from typing import Final - - -class UnitOfTemperature(StrEnum): - """Temperature units.""" - - CELSIUS = "°C" - FAHRENHEIT = "°F" - KELVIN = "K" - - -class UnitOfMass(StrEnum): - """Mass units.""" - - GRAMS = "g" - KILOGRAMS = "kg" - MILLIGRAMS = "mg" - MICROGRAMS = "µg" - OUNCES = "oz" - POUNDS = "lb" - STONES = "st" - - -class UnitOfPressure(StrEnum): - """Pressure units.""" - - PA = "Pa" - HPA = "hPa" - KPA = "kPa" - BAR = "bar" - CBAR = "cbar" - MBAR = "mbar" - MMHG = "mmHg" - INHG = "inHg" - PSI = "psi" - - -class UnitOfPower(StrEnum): - """Power units.""" - - WATT = "W" - KILO_WATT = "kW" - BTU_PER_HOUR = "BTU/h" - - -class UnitOfApparentPower(StrEnum): - """Apparent power units.""" - - VOLT_AMPERE = "VA" - - -class UnitOfElectricCurrent(StrEnum): - """Electric current units.""" - - MILLIAMPERE = "mA" - AMPERE = "A" - - -# Electric_potential units -class UnitOfElectricPotential(StrEnum): - """Electric potential units.""" - - MILLIVOLT = "mV" - VOLT = "V" - - -class UnitOfFrequency(StrEnum): - """Frequency units.""" - - HERTZ = "Hz" - KILOHERTZ = "kHz" - MEGAHERTZ = "MHz" - GIGAHERTZ = "GHz" - - -class UnitOfVolumeFlowRate(StrEnum): - """Volume flow rate units.""" - - CUBIC_METERS_PER_HOUR = "m³/h" - CUBIC_FEET_PER_MINUTE = "ft³/min" - LITERS_PER_MINUTE = "L/min" - GALLONS_PER_MINUTE = "gal/min" - - -class UnitOfVolume(StrEnum): - """Volume units.""" - - CUBIC_FEET = "ft³" - CENTUM_CUBIC_FEET = "CCF" - CUBIC_METERS = "m³" - LITERS = "L" - MILLILITERS = "mL" - GALLONS = "gal" - """Assumed to be US gallons in conversion utilities. - - British/Imperial gallons are not yet supported""" - FLUID_OUNCES = "fl. oz." - """Assumed to be US fluid ounces in conversion utilities. - - British/Imperial fluid ounces are not yet supported""" - - -class UnitOfTime(StrEnum): - """Time units.""" - - MICROSECONDS = "μs" - MILLISECONDS = "ms" - SECONDS = "s" - MINUTES = "min" - HOURS = "h" - DAYS = "d" - WEEKS = "w" - MONTHS = "m" - YEARS = "y" - - -class UnitOfLength(StrEnum): - """Length units.""" - - MILLIMETERS = "mm" - CENTIMETERS = "cm" - METERS = "m" - KILOMETERS = "km" - INCHES = "in" - FEET = "ft" - YARDS = "yd" - MILES = "mi" - - -class UnitOfEnergy(StrEnum): - """Energy units.""" - - GIGA_JOULE = "GJ" - KILO_WATT_HOUR = "kWh" - MEGA_JOULE = "MJ" - MEGA_WATT_HOUR = "MWh" - WATT_HOUR = "Wh" - - -# Concentration units -CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: Final = "µg/m³" -CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER: Final = "mg/m³" -CONCENTRATION_MICROGRAMS_PER_CUBIC_FOOT: Final = "μg/ft³" -CONCENTRATION_PARTS_PER_CUBIC_METER: Final = "p/m³" -CONCENTRATION_PARTS_PER_MILLION: Final = "ppm" -CONCENTRATION_PARTS_PER_BILLION: Final = "ppb" - -# Signal_strength units -SIGNAL_STRENGTH_DECIBELS: Final = "dB" -SIGNAL_STRENGTH_DECIBELS_MILLIWATT: Final = "dBm" - -# Light units -LIGHT_LUX: Final = "lx" - -# Percentage units -PERCENTAGE: Final[str] = "%" - - -UNITS_OF_MEASURE = { - UnitOfApparentPower.__name__: UnitOfApparentPower, - UnitOfPower.__name__: UnitOfPower, - UnitOfEnergy.__name__: UnitOfEnergy, - UnitOfElectricCurrent.__name__: UnitOfElectricCurrent, - UnitOfElectricPotential.__name__: UnitOfElectricPotential, - UnitOfTemperature.__name__: UnitOfTemperature, - UnitOfTime.__name__: UnitOfTime, - UnitOfFrequency.__name__: UnitOfFrequency, - UnitOfPressure.__name__: UnitOfPressure, - UnitOfVolume.__name__: UnitOfVolume, - UnitOfVolumeFlowRate.__name__: UnitOfVolumeFlowRate, - UnitOfLength.__name__: UnitOfLength, - UnitOfMass.__name__: UnitOfMass, -} - - -def validate_unit(external_unit: Enum) -> Enum: - """Validate and return a unit of measure.""" - return UNITS_OF_MEASURE[type(external_unit).__name__](external_unit.value)