Compare commits

...

3 Commits

Author SHA1 Message Date
abmantis b39e5c5d7d Update knx snapshots 2026-06-29 20:00:26 +01:00
abmantis 0679af1685 Improve unit system tests 2026-06-29 19:57:58 +01:00
abmantis 0498542340 Add radon device class to number and sensor 2026-06-29 19:33:04 +01:00
20 changed files with 125 additions and 2 deletions
+12
View File
@@ -34,6 +34,7 @@ from homeassistant.const import (
UnitOfPower,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfReactiveEnergy,
UnitOfReactivePower,
UnitOfSoundPressure,
@@ -67,6 +68,7 @@ from homeassistant.util.unit_conversion import (
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -378,6 +380,14 @@ class NumberDeviceClass(StrEnum):
- `inH₂O`
"""
RADON = "radon"
"""Radon.
Unit of measurement: UnitOfRadiationConcentration
- SI / metric: `Bq/m³`
- USCS / imperial: `pCi/L`
"""
REACTIVE_ENERGY = "reactive_energy"
"""Reactive energy.
@@ -592,6 +602,7 @@ DEVICE_CLASS_UNITS: dict[NumberDeviceClass, set[type[StrEnum] | str | None]] = {
NumberDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth),
NumberDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux),
NumberDeviceClass.PRESSURE: set(UnitOfPressure),
NumberDeviceClass.RADON: set(UnitOfRadiationConcentration),
NumberDeviceClass.REACTIVE_ENERGY: set(UnitOfReactiveEnergy),
NumberDeviceClass.REACTIVE_POWER: set(UnitOfReactivePower),
NumberDeviceClass.SIGNAL_STRENGTH: {
@@ -657,6 +668,7 @@ UNIT_CONVERTERS: dict[NumberDeviceClass, type[BaseUnitConverter]] = {
NumberDeviceClass.PRECIPITATION: DistanceConverter,
NumberDeviceClass.PRECIPITATION_INTENSITY: SpeedConverter,
NumberDeviceClass.PRESSURE: PressureConverter,
NumberDeviceClass.RADON: RadiationConcentrationConverter,
NumberDeviceClass.REACTIVE_ENERGY: ReactiveEnergyConverter,
NumberDeviceClass.REACTIVE_POWER: ReactivePowerConverter,
NumberDeviceClass.SULPHUR_DIOXIDE: SulphurDioxideConcentrationConverter,
@@ -114,6 +114,9 @@
"pressure": {
"default": "mdi:gauge"
},
"radon": {
"default": "mdi:radioactive"
},
"reactive_energy": {
"default": "mdi:lightning-bolt"
},
@@ -135,6 +135,9 @@
"pressure": {
"name": "[%key:component::sensor::entity_component::pressure::name%]"
},
"radon": {
"name": "[%key:component::sensor::entity_component::radon::name%]"
},
"reactive_energy": {
"name": "[%key:component::sensor::entity_component::reactive_energy::name%]"
},
@@ -64,6 +64,7 @@ from homeassistant.util.unit_conversion import (
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -219,6 +220,7 @@ _PRIMARY_UNIT_CONVERTERS: list[type[BaseUnitConverter]] = [
MassVolumeConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -37,6 +37,7 @@ from homeassistant.util.unit_conversion import (
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -101,6 +102,9 @@ UNIT_SCHEMA = vol.Schema(
vol.Optional("ozone"): vol.In(OzoneConcentrationConverter.VALID_UNITS),
vol.Optional("power"): vol.In(PowerConverter.VALID_UNITS),
vol.Optional("pressure"): vol.In(PressureConverter.VALID_UNITS),
vol.Optional("radiation_concentration"): vol.In(
RadiationConcentrationConverter.VALID_UNITS
),
vol.Optional("reactive_energy"): vol.In(ReactiveEnergyConverter.VALID_UNITS),
vol.Optional("reactive_power"): vol.In(ReactivePowerConverter.VALID_UNITS),
vol.Optional("speed"): vol.In(SpeedConverter.VALID_UNITS),
+14
View File
@@ -34,6 +34,7 @@ from homeassistant.const import (
UnitOfPower,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfReactiveEnergy,
UnitOfReactivePower,
UnitOfSoundPressure,
@@ -67,6 +68,7 @@ from homeassistant.util.unit_conversion import (
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -409,6 +411,14 @@ class SensorDeviceClass(StrEnum):
- `inH₂O`
"""
RADON = "radon"
"""Radon.
Unit of measurement: UnitOfRadiationConcentration
- SI / metric: `Bq/m³`
- USCS / imperial: `pCi/L`
"""
REACTIVE_ENERGY = "reactive_energy"
"""Reactive energy.
@@ -616,6 +626,7 @@ UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] =
SensorDeviceClass.PRECIPITATION: DistanceConverter,
SensorDeviceClass.PRECIPITATION_INTENSITY: SpeedConverter,
SensorDeviceClass.PRESSURE: PressureConverter,
SensorDeviceClass.RADON: RadiationConcentrationConverter,
SensorDeviceClass.REACTIVE_ENERGY: ReactiveEnergyConverter,
SensorDeviceClass.REACTIVE_POWER: ReactivePowerConverter,
SensorDeviceClass.SULPHUR_DIOXIDE: SulphurDioxideConcentrationConverter,
@@ -711,6 +722,7 @@ DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = {
SensorDeviceClass.PRECIPITATION: set(UnitOfPrecipitationDepth),
SensorDeviceClass.PRECIPITATION_INTENSITY: set(UnitOfVolumetricFlux),
SensorDeviceClass.PRESSURE: set(UnitOfPressure),
SensorDeviceClass.RADON: set(UnitOfRadiationConcentration),
SensorDeviceClass.REACTIVE_ENERGY: set(UnitOfReactiveEnergy),
SensorDeviceClass.REACTIVE_POWER: set(UnitOfReactivePower),
SensorDeviceClass.SIGNAL_STRENGTH: {
@@ -785,6 +797,7 @@ UNITS_PRECISION = {
0,
),
SensorDeviceClass.PRESSURE: (UnitOfPressure.PA, 0),
SensorDeviceClass.RADON: (UnitOfRadiationConcentration.PICOCURIES_PER_LITER, 1),
SensorDeviceClass.REACTIVE_POWER: (UnitOfReactivePower.VOLT_AMPERE_REACTIVE, 0),
SensorDeviceClass.SOUND_PRESSURE: (UnitOfSoundPressure.DECIBEL, 0),
SensorDeviceClass.SPEED: (UnitOfSpeed.MILLIMETERS_PER_SECOND, 0),
@@ -844,6 +857,7 @@ DEVICE_CLASS_STATE_CLASSES: dict[SensorDeviceClass, set[SensorStateClass]] = {
SensorDeviceClass.PRECIPITATION: set(SensorStateClass),
SensorDeviceClass.PRECIPITATION_INTENSITY: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.PRESSURE: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.RADON: {SensorStateClass.MEASUREMENT},
SensorDeviceClass.REACTIVE_ENERGY: {
SensorStateClass.TOTAL,
SensorStateClass.TOTAL_INCREASING,
@@ -69,6 +69,7 @@ CONF_IS_POWER_FACTOR = "is_power_factor"
CONF_IS_PRECIPITATION = "is_precipitation"
CONF_IS_PRECIPITATION_INTENSITY = "is_precipitation_intensity"
CONF_IS_PRESSURE = "is_pressure"
CONF_IS_RADON = "is_radon"
CONF_IS_SPEED = "is_speed"
CONF_IS_REACTIVE_ENERGY = "is_reactive_energy"
CONF_IS_REACTIVE_POWER = "is_reactive_power"
@@ -132,6 +133,7 @@ ENTITY_CONDITIONS = {
{CONF_TYPE: CONF_IS_PRECIPITATION_INTENSITY}
],
SensorDeviceClass.PRESSURE: [{CONF_TYPE: CONF_IS_PRESSURE}],
SensorDeviceClass.RADON: [{CONF_TYPE: CONF_IS_RADON}],
SensorDeviceClass.REACTIVE_ENERGY: [{CONF_TYPE: CONF_IS_REACTIVE_ENERGY}],
SensorDeviceClass.REACTIVE_POWER: [{CONF_TYPE: CONF_IS_REACTIVE_POWER}],
SensorDeviceClass.SIGNAL_STRENGTH: [{CONF_TYPE: CONF_IS_SIGNAL_STRENGTH}],
@@ -201,6 +203,7 @@ CONDITION_SCHEMA = vol.All(
CONF_IS_PRECIPITATION,
CONF_IS_PRECIPITATION_INTENSITY,
CONF_IS_PRESSURE,
CONF_IS_RADON,
CONF_IS_REACTIVE_ENERGY,
CONF_IS_REACTIVE_POWER,
CONF_IS_SIGNAL_STRENGTH,
@@ -70,6 +70,7 @@ CONF_POWER_FACTOR = "power_factor"
CONF_PRECIPITATION = "precipitation"
CONF_PRECIPITATION_INTENSITY = "precipitation_intensity"
CONF_PRESSURE = "pressure"
CONF_RADON = "radon"
CONF_REACTIVE_ENERGY = "reactive_energy"
CONF_REACTIVE_POWER = "reactive_power"
CONF_SIGNAL_STRENGTH = "signal_strength"
@@ -133,6 +134,7 @@ ENTITY_TRIGGERS = {
{CONF_TYPE: CONF_PRECIPITATION_INTENSITY}
],
SensorDeviceClass.PRESSURE: [{CONF_TYPE: CONF_PRESSURE}],
SensorDeviceClass.RADON: [{CONF_TYPE: CONF_RADON}],
SensorDeviceClass.REACTIVE_ENERGY: [{CONF_TYPE: CONF_REACTIVE_ENERGY}],
SensorDeviceClass.REACTIVE_POWER: [{CONF_TYPE: CONF_REACTIVE_POWER}],
SensorDeviceClass.SIGNAL_STRENGTH: [{CONF_TYPE: CONF_SIGNAL_STRENGTH}],
@@ -203,6 +205,7 @@ TRIGGER_SCHEMA = vol.All(
CONF_PRECIPITATION,
CONF_PRECIPITATION_INTENSITY,
CONF_PRESSURE,
CONF_RADON,
CONF_REACTIVE_ENERGY,
CONF_REACTIVE_POWER,
CONF_SIGNAL_STRENGTH,
@@ -136,6 +136,9 @@
"pressure": {
"default": "mdi:gauge"
},
"radon": {
"default": "mdi:radioactive"
},
"reactive_energy": {
"default": "mdi:lightning-bolt"
},
@@ -39,6 +39,7 @@
"is_precipitation": "Current {entity_name} precipitation",
"is_precipitation_intensity": "Current {entity_name} precipitation intensity",
"is_pressure": "Current {entity_name} pressure",
"is_radon": "Current {entity_name} radon concentration level",
"is_reactive_energy": "Current {entity_name} reactive energy",
"is_reactive_power": "Current {entity_name} reactive power",
"is_signal_strength": "Current {entity_name} signal strength",
@@ -102,6 +103,7 @@
"precipitation": "{entity_name} precipitation changes",
"precipitation_intensity": "{entity_name} precipitation intensity changes",
"pressure": "{entity_name} pressure changes",
"radon": "{entity_name} radon concentration changes",
"reactive_energy": "{entity_name} reactive energy changes",
"reactive_power": "{entity_name} reactive power changes",
"signal_strength": "{entity_name} signal strength changes",
@@ -270,6 +272,9 @@
"pressure": {
"name": "Pressure"
},
"radon": {
"name": "Radon"
},
"reactive_energy": {
"name": "Reactive energy"
},
+7
View File
@@ -823,6 +823,13 @@ class UnitOfBloodGlucoseConcentration(StrEnum):
MILLIMOLE_PER_LITER = "mmol/L"
class UnitOfRadiationConcentration(StrEnum):
"""Radiation concentration units."""
BECQUEREL_PER_CUBIC_METER = "Bq/m³"
PICOCURIES_PER_LITER = "pCi/L"
# Speed units
class UnitOfSpeed(StrEnum):
"""Speed units."""
+1
View File
@@ -39,6 +39,7 @@
"precipitation",
"precipitation_intensity",
"pressure",
"radon",
"reactive_energy",
"reactive_power",
"signal_strength",
+17
View File
@@ -23,6 +23,7 @@ from homeassistant.const import (
UnitOfMass,
UnitOfPower,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfRatio,
UnitOfReactiveEnergy,
UnitOfReactivePower,
@@ -105,6 +106,9 @@ _NITROGEN_MONOXIDE_MOLAR_MASS = 30.0061
_OZONE_MOLAR_MASS = 48.00
_SULPHUR_DIOXIDE_MOLAR_MASS = 64.066
# Radiation concentration conversion constant
_PICOCURIES_PER_LITER_TO_BECQUEREL_PER_CUBIC_METER = 37 # 1 pCi/L = 37 Bq/m³
class BaseUnitConverter:
"""Define the format of a conversion utility."""
@@ -612,6 +616,19 @@ class PressureConverter(BaseUnitConverter):
}
class RadiationConcentrationConverter(BaseUnitConverter):
"""Utility to convert radiation concentration values."""
UNIT_CLASS = "radiation_concentration"
_UNIT_CONVERSION: dict[str | None, float] = {
UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER: 1,
UnitOfRadiationConcentration.PICOCURIES_PER_LITER: (
1 / _PICOCURIES_PER_LITER_TO_BECQUEREL_PER_CUBIC_METER
),
}
VALID_UNITS = set(UnitOfRadiationConcentration)
class ReactiveEnergyConverter(BaseUnitConverter):
"""Utility to convert reactive energy values."""
+11
View File
@@ -21,6 +21,7 @@ from homeassistant.const import (
UnitOfMass,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolume,
@@ -295,6 +296,11 @@ METRIC_SYSTEM = UnitSystem(
("pressure", UnitOfPressure.PSI): UnitOfPressure.KPA,
("pressure", UnitOfPressure.INHG): UnitOfPressure.HPA,
("pressure", UnitOfPressure.INH2O): UnitOfPressure.KPA,
# Convert non-metric radon concentration
(
"radon",
UnitOfRadiationConcentration.PICOCURIES_PER_LITER,
): UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
# Convert non-metric speeds except knots to km/h
("speed", UnitOfSpeed.FEET_PER_SECOND): UnitOfSpeed.KILOMETERS_PER_HOUR,
("speed", UnitOfSpeed.INCHES_PER_SECOND): UnitOfSpeed.MILLIMETERS_PER_SECOND,
@@ -380,6 +386,11 @@ US_CUSTOMARY_SYSTEM = UnitSystem(
("pressure", UnitOfPressure.KPA): UnitOfPressure.PSI,
("pressure", UnitOfPressure.MMHG): UnitOfPressure.INHG,
("pressure", UnitOfPressure.INH2O): UnitOfPressure.PSI,
# Convert non-USCS radon concentration
(
"radon",
UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
): UnitOfRadiationConcentration.PICOCURIES_PER_LITER,
# Convert non-USCS speeds, except knots, to mph
("speed", UnitOfSpeed.METERS_PER_MINUTE): UnitOfSpeed.INCHES_PER_SECOND,
("speed", UnitOfSpeed.METERS_PER_SECOND): UnitOfSpeed.MILES_PER_HOUR,
@@ -1726,6 +1726,7 @@
'B/s',
'BTU/(h⋅ft²)',
'Beaufort',
'Bq/m³',
'CCF',
'EB',
'EiB',
@@ -1875,6 +1876,7 @@
'm³/s',
'nmi',
'oz',
'pCi/L',
'ppb',
'ppm',
'psi',
@@ -1947,6 +1949,7 @@
'precipitation',
'precipitation_intensity',
'pressure',
'radon',
'reactive_energy',
'reactive_power',
'signal_strength',
@@ -2071,6 +2074,7 @@
'B/s',
'BTU/(h⋅ft²)',
'Beaufort',
'Bq/m³',
'CCF',
'EB',
'EiB',
@@ -2220,6 +2224,7 @@
'm³/s',
'nmi',
'oz',
'pCi/L',
'ppb',
'ppm',
'psi',
@@ -2296,6 +2301,7 @@
'precipitation',
'precipitation_intensity',
'pressure',
'radon',
'reactive_energy',
'reactive_power',
'signal_strength',
+2
View File
@@ -31,6 +31,7 @@ from homeassistant.const import (
UnitOfPower,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfReactiveEnergy,
UnitOfReactivePower,
UnitOfSoundPressure,
@@ -90,6 +91,7 @@ UNITS_OF_MEASUREMENT = {
UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR
),
SensorDeviceClass.PRESSURE: UnitOfPressure.HPA,
SensorDeviceClass.RADON: UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
SensorDeviceClass.REACTIVE_ENERGY: UnitOfReactiveEnergy.VOLT_AMPERE_REACTIVE_HOUR,
SensorDeviceClass.REACTIVE_POWER: UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
SensorDeviceClass.SIGNAL_STRENGTH: SIGNAL_STRENGTH_DECIBELS,
@@ -121,7 +121,7 @@ async def test_get_conditions(
conditions = await async_get_device_automations(
hass, DeviceAutomationType.CONDITION, device_entry.id
)
assert len(conditions) == 57
assert len(conditions) == 58
assert conditions == unordered(expected_conditions)
@@ -122,7 +122,7 @@ async def test_get_triggers(
triggers = await async_get_device_automations(
hass, DeviceAutomationType.TRIGGER, device_entry.id
)
assert len(triggers) == 57
assert len(triggers) == 58
assert triggers == unordered(expected_triggers)
+22
View File
@@ -22,6 +22,7 @@ from homeassistant.const import (
UnitOfMass,
UnitOfPower,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfRatio,
UnitOfReactiveEnergy,
UnitOfReactivePower,
@@ -57,6 +58,7 @@ from homeassistant.util.unit_conversion import (
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -95,6 +97,7 @@ _ALL_CONVERTERS: dict[type[BaseUnitConverter], list[str | None]] = {
OzoneConcentrationConverter,
PowerConverter,
PressureConverter,
RadiationConcentrationConverter,
ReactiveEnergyConverter,
ReactivePowerConverter,
SpeedConverter,
@@ -181,6 +184,11 @@ _GET_UNIT_RATIO: dict[type[BaseUnitConverter], tuple[str | None, str | None, flo
),
PowerConverter: (UnitOfPower.WATT, UnitOfPower.KILO_WATT, 1000),
PressureConverter: (UnitOfPressure.HPA, UnitOfPressure.INHG, 33.86389),
RadiationConcentrationConverter: (
UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
UnitOfRadiationConcentration.PICOCURIES_PER_LITER,
37,
),
ReactiveEnergyConverter: (
UnitOfReactiveEnergy.VOLT_AMPERE_REACTIVE_HOUR,
UnitOfReactiveEnergy.KILO_VOLT_AMPERE_REACTIVE_HOUR,
@@ -874,6 +882,20 @@ _CONVERTED_VALUE: dict[
(30, UnitOfPressure.MMHG, 16.0572051431838, UnitOfPressure.INH2O),
(5, UnitOfPressure.BAR, 72.51887, UnitOfPressure.PSI),
],
RadiationConcentrationConverter: [
(
37,
UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
1,
UnitOfRadiationConcentration.PICOCURIES_PER_LITER,
),
(
1,
UnitOfRadiationConcentration.PICOCURIES_PER_LITER,
37,
UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,
),
],
ReactiveEnergyConverter: [
(
5,
+5
View File
@@ -17,6 +17,7 @@ from homeassistant.const import (
UnitOfMass,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRadiationConcentration,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolume,
@@ -609,6 +610,7 @@ UNCONVERTED_UNITS_METRIC_SYSTEM = {
UnitOfPressure.MILLIPASCAL,
UnitOfPressure.PA,
),
SensorDeviceClass.RADON: (UnitOfRadiationConcentration.BECQUEREL_PER_CUBIC_METER,),
SensorDeviceClass.SPEED: (
UnitOfSpeed.BEAUFORT,
UnitOfSpeed.KILOMETERS_PER_HOUR,
@@ -641,6 +643,7 @@ UNCONVERTED_UNITS_METRIC_SYSTEM = {
SensorDeviceClass.PRECIPITATION,
SensorDeviceClass.PRECIPITATION_INTENSITY,
SensorDeviceClass.PRESSURE,
SensorDeviceClass.RADON,
SensorDeviceClass.SPEED,
SensorDeviceClass.VOLUME,
SensorDeviceClass.WATER,
@@ -857,6 +860,7 @@ UNCONVERTED_UNITS_US_SYSTEM = {
UnitOfVolumetricFlux.INCHES_PER_HOUR,
),
SensorDeviceClass.PRESSURE: (UnitOfPressure.INHG, UnitOfPressure.PSI),
SensorDeviceClass.RADON: (UnitOfRadiationConcentration.PICOCURIES_PER_LITER,),
SensorDeviceClass.SPEED: (
UnitOfSpeed.BEAUFORT,
UnitOfSpeed.FEET_PER_SECOND,
@@ -891,6 +895,7 @@ UNCONVERTED_UNITS_US_SYSTEM = {
SensorDeviceClass.PRECIPITATION,
SensorDeviceClass.PRECIPITATION_INTENSITY,
SensorDeviceClass.PRESSURE,
SensorDeviceClass.RADON,
SensorDeviceClass.SPEED,
SensorDeviceClass.VOLUME,
SensorDeviceClass.WATER,