Add missing device class triggers (#88316)
* Add constant tests for sensor device classes * Add missing strings * Adjust tests * Add missing conditions * Add missing trigger * Cleanuppull/88503/head
parent
69e42d0e4d
commit
488d78571e
|
@ -32,6 +32,7 @@ from . import ATTR_STATE_CLASS, DOMAIN, SensorDeviceClass
|
|||
DEVICE_CLASS_NONE = "none"
|
||||
|
||||
CONF_IS_APPARENT_POWER = "is_apparent_power"
|
||||
CONF_IS_AQI = "is_aqi"
|
||||
CONF_IS_ATMOSPHERIC_PRESSURE = "is_atmospheric_pressure"
|
||||
CONF_IS_BATTERY_LEVEL = "is_battery_level"
|
||||
CONF_IS_CO = "is_carbon_monoxide"
|
||||
|
@ -40,6 +41,7 @@ CONF_IS_CURRENT = "is_current"
|
|||
CONF_IS_DATA_RATE = "is_data_rate"
|
||||
CONF_IS_DATA_SIZE = "is_data_size"
|
||||
CONF_IS_DISTANCE = "is_distance"
|
||||
CONF_IS_DURATION = "is_duration"
|
||||
CONF_IS_ENERGY = "is_energy"
|
||||
CONF_IS_FREQUENCY = "is_frequency"
|
||||
CONF_IS_HUMIDITY = "is_humidity"
|
||||
|
@ -47,6 +49,7 @@ CONF_IS_GAS = "is_gas"
|
|||
CONF_IS_ILLUMINANCE = "is_illuminance"
|
||||
CONF_IS_IRRADIANCE = "is_irradiance"
|
||||
CONF_IS_MOISTURE = "is_moisture"
|
||||
CONF_IS_MONETARY = "is_monetary"
|
||||
CONF_IS_NITROGEN_DIOXIDE = "is_nitrogen_dioxide"
|
||||
CONF_IS_NITROGEN_MONOXIDE = "is_nitrogen_monoxide"
|
||||
CONF_IS_NITROUS_OXIDE = "is_nitrous_oxide"
|
||||
|
@ -75,6 +78,7 @@ CONF_IS_WIND_SPEED = "is_wind_speed"
|
|||
|
||||
ENTITY_CONDITIONS = {
|
||||
SensorDeviceClass.APPARENT_POWER: [{CONF_TYPE: CONF_IS_APPARENT_POWER}],
|
||||
SensorDeviceClass.AQI: [{CONF_TYPE: CONF_IS_AQI}],
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE: [{CONF_TYPE: CONF_IS_ATMOSPHERIC_PRESSURE}],
|
||||
SensorDeviceClass.BATTERY: [{CONF_TYPE: CONF_IS_BATTERY_LEVEL}],
|
||||
SensorDeviceClass.CO: [{CONF_TYPE: CONF_IS_CO}],
|
||||
|
@ -83,6 +87,7 @@ ENTITY_CONDITIONS = {
|
|||
SensorDeviceClass.DATA_RATE: [{CONF_TYPE: CONF_IS_DATA_RATE}],
|
||||
SensorDeviceClass.DATA_SIZE: [{CONF_TYPE: CONF_IS_DATA_SIZE}],
|
||||
SensorDeviceClass.DISTANCE: [{CONF_TYPE: CONF_IS_DISTANCE}],
|
||||
SensorDeviceClass.DURATION: [{CONF_TYPE: CONF_IS_DURATION}],
|
||||
SensorDeviceClass.ENERGY: [{CONF_TYPE: CONF_IS_ENERGY}],
|
||||
SensorDeviceClass.FREQUENCY: [{CONF_TYPE: CONF_IS_FREQUENCY}],
|
||||
SensorDeviceClass.GAS: [{CONF_TYPE: CONF_IS_GAS}],
|
||||
|
@ -90,6 +95,7 @@ ENTITY_CONDITIONS = {
|
|||
SensorDeviceClass.ILLUMINANCE: [{CONF_TYPE: CONF_IS_ILLUMINANCE}],
|
||||
SensorDeviceClass.IRRADIANCE: [{CONF_TYPE: CONF_IS_IRRADIANCE}],
|
||||
SensorDeviceClass.MOISTURE: [{CONF_TYPE: CONF_IS_MOISTURE}],
|
||||
SensorDeviceClass.MONETARY: [{CONF_TYPE: CONF_IS_MONETARY}],
|
||||
SensorDeviceClass.NITROGEN_DIOXIDE: [{CONF_TYPE: CONF_IS_NITROGEN_DIOXIDE}],
|
||||
SensorDeviceClass.NITROGEN_MONOXIDE: [{CONF_TYPE: CONF_IS_NITROGEN_MONOXIDE}],
|
||||
SensorDeviceClass.NITROUS_OXIDE: [{CONF_TYPE: CONF_IS_NITROUS_OXIDE}],
|
||||
|
@ -128,6 +134,7 @@ CONDITION_SCHEMA = vol.All(
|
|||
vol.Required(CONF_TYPE): vol.In(
|
||||
[
|
||||
CONF_IS_APPARENT_POWER,
|
||||
CONF_IS_AQI,
|
||||
CONF_IS_ATMOSPHERIC_PRESSURE,
|
||||
CONF_IS_BATTERY_LEVEL,
|
||||
CONF_IS_CO,
|
||||
|
@ -136,6 +143,7 @@ CONDITION_SCHEMA = vol.All(
|
|||
CONF_IS_DATA_RATE,
|
||||
CONF_IS_DATA_SIZE,
|
||||
CONF_IS_DISTANCE,
|
||||
CONF_IS_DURATION,
|
||||
CONF_IS_ENERGY,
|
||||
CONF_IS_FREQUENCY,
|
||||
CONF_IS_GAS,
|
||||
|
@ -143,6 +151,7 @@ CONDITION_SCHEMA = vol.All(
|
|||
CONF_IS_ILLUMINANCE,
|
||||
CONF_IS_IRRADIANCE,
|
||||
CONF_IS_MOISTURE,
|
||||
CONF_IS_MONETARY,
|
||||
CONF_IS_NITROGEN_DIOXIDE,
|
||||
CONF_IS_NITROGEN_MONOXIDE,
|
||||
CONF_IS_NITROUS_OXIDE,
|
||||
|
|
|
@ -31,6 +31,7 @@ from . import ATTR_STATE_CLASS, DOMAIN, SensorDeviceClass
|
|||
DEVICE_CLASS_NONE = "none"
|
||||
|
||||
CONF_APPARENT_POWER = "apparent_power"
|
||||
CONF_AQI = "aqi"
|
||||
CONF_ATMOSPHERIC_PRESSURE = "atmospheric_pressure"
|
||||
CONF_BATTERY_LEVEL = "battery_level"
|
||||
CONF_CO = "carbon_monoxide"
|
||||
|
@ -39,6 +40,7 @@ CONF_CURRENT = "current"
|
|||
CONF_DATA_RATE = "data_rate"
|
||||
CONF_DATA_SIZE = "data_size"
|
||||
CONF_DISTANCE = "distance"
|
||||
CONF_DURATION = "duration"
|
||||
CONF_ENERGY = "energy"
|
||||
CONF_FREQUENCY = "frequency"
|
||||
CONF_GAS = "gas"
|
||||
|
@ -46,6 +48,7 @@ CONF_HUMIDITY = "humidity"
|
|||
CONF_ILLUMINANCE = "illuminance"
|
||||
CONF_IRRADIANCE = "irradiance"
|
||||
CONF_MOISTURE = "moisture"
|
||||
CONF_MONETARY = "monetary"
|
||||
CONF_NITROGEN_DIOXIDE = "nitrogen_dioxide"
|
||||
CONF_NITROGEN_MONOXIDE = "nitrogen_monoxide"
|
||||
CONF_NITROUS_OXIDE = "nitrous_oxide"
|
||||
|
@ -74,6 +77,7 @@ CONF_WIND_SPEED = "wind_speed"
|
|||
|
||||
ENTITY_TRIGGERS = {
|
||||
SensorDeviceClass.APPARENT_POWER: [{CONF_TYPE: CONF_APPARENT_POWER}],
|
||||
SensorDeviceClass.AQI: [{CONF_TYPE: CONF_AQI}],
|
||||
SensorDeviceClass.ATMOSPHERIC_PRESSURE: [{CONF_TYPE: CONF_ATMOSPHERIC_PRESSURE}],
|
||||
SensorDeviceClass.BATTERY: [{CONF_TYPE: CONF_BATTERY_LEVEL}],
|
||||
SensorDeviceClass.CO: [{CONF_TYPE: CONF_CO}],
|
||||
|
@ -82,6 +86,7 @@ ENTITY_TRIGGERS = {
|
|||
SensorDeviceClass.DATA_RATE: [{CONF_TYPE: CONF_DATA_RATE}],
|
||||
SensorDeviceClass.DATA_SIZE: [{CONF_TYPE: CONF_DATA_SIZE}],
|
||||
SensorDeviceClass.DISTANCE: [{CONF_TYPE: CONF_DISTANCE}],
|
||||
SensorDeviceClass.DURATION: [{CONF_TYPE: CONF_DURATION}],
|
||||
SensorDeviceClass.ENERGY: [{CONF_TYPE: CONF_ENERGY}],
|
||||
SensorDeviceClass.FREQUENCY: [{CONF_TYPE: CONF_FREQUENCY}],
|
||||
SensorDeviceClass.GAS: [{CONF_TYPE: CONF_GAS}],
|
||||
|
@ -89,6 +94,7 @@ ENTITY_TRIGGERS = {
|
|||
SensorDeviceClass.ILLUMINANCE: [{CONF_TYPE: CONF_ILLUMINANCE}],
|
||||
SensorDeviceClass.IRRADIANCE: [{CONF_TYPE: CONF_IRRADIANCE}],
|
||||
SensorDeviceClass.MOISTURE: [{CONF_TYPE: CONF_MOISTURE}],
|
||||
SensorDeviceClass.MONETARY: [{CONF_TYPE: CONF_MONETARY}],
|
||||
SensorDeviceClass.NITROGEN_DIOXIDE: [{CONF_TYPE: CONF_NITROGEN_DIOXIDE}],
|
||||
SensorDeviceClass.NITROGEN_MONOXIDE: [{CONF_TYPE: CONF_NITROGEN_MONOXIDE}],
|
||||
SensorDeviceClass.NITROUS_OXIDE: [{CONF_TYPE: CONF_NITROUS_OXIDE}],
|
||||
|
@ -128,6 +134,7 @@ TRIGGER_SCHEMA = vol.All(
|
|||
vol.Required(CONF_TYPE): vol.In(
|
||||
[
|
||||
CONF_APPARENT_POWER,
|
||||
CONF_AQI,
|
||||
CONF_ATMOSPHERIC_PRESSURE,
|
||||
CONF_BATTERY_LEVEL,
|
||||
CONF_CO,
|
||||
|
@ -136,6 +143,7 @@ TRIGGER_SCHEMA = vol.All(
|
|||
CONF_DATA_RATE,
|
||||
CONF_DATA_SIZE,
|
||||
CONF_DISTANCE,
|
||||
CONF_DURATION,
|
||||
CONF_ENERGY,
|
||||
CONF_FREQUENCY,
|
||||
CONF_GAS,
|
||||
|
@ -143,6 +151,7 @@ TRIGGER_SCHEMA = vol.All(
|
|||
CONF_ILLUMINANCE,
|
||||
CONF_IRRADIANCE,
|
||||
CONF_MOISTURE,
|
||||
CONF_MONETARY,
|
||||
CONF_NITROGEN_DIOXIDE,
|
||||
CONF_NITROGEN_MONOXIDE,
|
||||
CONF_NITROUS_OXIDE,
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"device_automation": {
|
||||
"condition_type": {
|
||||
"is_apparent_power": "Current {entity_name} apparent power",
|
||||
"is_aqi": "Current {entity_name} air quality index",
|
||||
"is_atmospheric_pressure": "Current {entity_name} atmospheric pressure",
|
||||
"is_battery_level": "Current {entity_name} battery level",
|
||||
"is_carbon_monoxide": "Current {entity_name} carbon monoxide concentration level",
|
||||
|
@ -11,6 +12,7 @@
|
|||
"is_data_rate": "Current {entity_name} data rate",
|
||||
"is_data_size": "Current {entity_name} data size",
|
||||
"is_distance": "Current {entity_name} distance",
|
||||
"is_duration": "Current {entity_name} duration",
|
||||
"is_energy": "Current {entity_name} energy",
|
||||
"is_frequency": "Current {entity_name} frequency",
|
||||
"is_gas": "Current {entity_name} gas",
|
||||
|
@ -18,6 +20,7 @@
|
|||
"is_illuminance": "Current {entity_name} illuminance",
|
||||
"is_irradiance": "Current {entity_name} irradiance",
|
||||
"is_moisture": "Current {entity_name} moisture",
|
||||
"is_monetary": "Current {entity_name} money",
|
||||
"is_nitrogen_dioxide": "Current {entity_name} nitrogen dioxide concentration level",
|
||||
"is_nitrogen_monoxide": "Current {entity_name} nitrogen monoxide concentration level",
|
||||
"is_nitrous_oxide": "Current {entity_name} nitrous oxide concentration level",
|
||||
|
@ -27,6 +30,8 @@
|
|||
"is_pm25": "Current {entity_name} PM2.5 concentration level",
|
||||
"is_power": "Current {entity_name} power",
|
||||
"is_power_factor": "Current {entity_name} power factor",
|
||||
"is_precipitation": "Current {entity_name} precipitation",
|
||||
"is_precipitation_intensity": "Current {entity_name} precipitation intensity",
|
||||
"is_pressure": "Current {entity_name} pressure",
|
||||
"is_reactive_power": "Current {entity_name} reactive power",
|
||||
"is_signal_strength": "Current {entity_name} signal strength",
|
||||
|
@ -39,17 +44,21 @@
|
|||
"is_voltage": "Current {entity_name} voltage",
|
||||
"is_volume": "Current {entity_name} volume",
|
||||
"is_water": "Current {entity_name} water",
|
||||
"is_weight": "Current {entity_name} weight"
|
||||
"is_weight": "Current {entity_name} weight",
|
||||
"is_wind_speed": "Current {entity_name} wind speed"
|
||||
},
|
||||
"trigger_type": {
|
||||
"apparent_power": "{entity_name} apparent power changes",
|
||||
"aqi": "{entity_name} air quality index changes",
|
||||
"atmospheric_pressure": "{entity_name} atmospheric pressure changes",
|
||||
"battery_level": "{entity_name} battery level changes",
|
||||
"carbon_monoxide": "{entity_name} carbon monoxide concentration changes",
|
||||
"carbon_dioxide": "{entity_name} carbon dioxide concentration changes",
|
||||
"current": "{entity_name} current changes",
|
||||
"data_rate": "{entity_name} data rate changes",
|
||||
"data_size": "{entity_name} data size changes",
|
||||
"distance": "{entity_name} distance changes",
|
||||
"duration": "{entity_name} duration changes",
|
||||
"energy": "{entity_name} energy changes",
|
||||
"frequency": "{entity_name} frequency changes",
|
||||
"gas": "{entity_name} gas changes",
|
||||
|
@ -57,6 +66,7 @@
|
|||
"illuminance": "{entity_name} illuminance changes",
|
||||
"irradiance": "{entity_name} irradiance changes",
|
||||
"moisture": "{entity_name} moisture changes",
|
||||
"monetary": "{entity_name} money changes",
|
||||
"nitrogen_dioxide": "{entity_name} nitrogen dioxide concentration changes",
|
||||
"nitrogen_monoxide": "{entity_name} nitrogen monoxide concentration changes",
|
||||
"nitrous_oxide": "{entity_name} nitrous oxide concentration changes",
|
||||
|
@ -66,6 +76,8 @@
|
|||
"pm25": "{entity_name} PM2.5 concentration changes",
|
||||
"power": "{entity_name} power changes",
|
||||
"power_factor": "{entity_name} power factor changes",
|
||||
"precipitation": "{entity_name} precipitation changes",
|
||||
"precipitation_intensity": "{entity_name} precipitation intensity changes",
|
||||
"pressure": "{entity_name} pressure changes",
|
||||
"reactive_power": "{entity_name} reactive power changes",
|
||||
"signal_strength": "{entity_name} signal strength changes",
|
||||
|
@ -78,7 +90,8 @@
|
|||
"voltage": "{entity_name} voltage changes",
|
||||
"volume": "{entity_name} volume changes",
|
||||
"water": "{entity_name} water changes",
|
||||
"weight": "{entity_name} weight changes"
|
||||
"weight": "{entity_name} weight changes",
|
||||
"wind_speed": "{entity_name} wind speed changes"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
|
|
|
@ -8,13 +8,16 @@ from homeassistant.components.sensor import (
|
|||
DOMAIN,
|
||||
SensorDeviceClass,
|
||||
SensorStateClass,
|
||||
device_condition,
|
||||
)
|
||||
from homeassistant.components.sensor.const import NON_NUMERIC_DEVICE_CLASSES
|
||||
from homeassistant.components.sensor.device_condition import ENTITY_CONDITIONS
|
||||
from homeassistant.const import CONF_PLATFORM, PERCENTAGE, STATE_UNKNOWN, EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.entity_registry import RegistryEntryHider
|
||||
from homeassistant.setup import async_setup_component
|
||||
from homeassistant.util.json import load_json
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
|
@ -28,11 +31,47 @@ from tests.testing_config.custom_components.test.sensor import UNITS_OF_MEASUREM
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def calls(hass):
|
||||
def calls(hass: HomeAssistant) -> list[ServiceCall]:
|
||||
"""Track calls to a mock service."""
|
||||
return async_mock_service(hass, "test", "automation")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_class",
|
||||
[
|
||||
device_class
|
||||
for device_class in SensorDeviceClass
|
||||
if device_class not in NON_NUMERIC_DEVICE_CLASSES
|
||||
],
|
||||
)
|
||||
def test_matches_device_classes(device_class: SensorDeviceClass) -> None:
|
||||
"""Ensure device class constants are declared in device_condition module."""
|
||||
# Ensure it has corresponding CONF_IS_*** constant
|
||||
constant_name = {
|
||||
SensorDeviceClass.BATTERY: "CONF_IS_BATTERY_LEVEL",
|
||||
SensorDeviceClass.CO: "CONF_IS_CO",
|
||||
SensorDeviceClass.CO2: "CONF_IS_CO2",
|
||||
}.get(device_class, f"CONF_IS_{device_class.value.upper()}")
|
||||
assert hasattr(device_condition, constant_name), f"Missing constant {constant_name}"
|
||||
|
||||
# Ensure it has correct value
|
||||
constant_value = {
|
||||
SensorDeviceClass.BATTERY: "is_battery_level",
|
||||
}.get(device_class, f"is_{device_class.value}")
|
||||
assert getattr(device_condition, constant_name) == constant_value
|
||||
|
||||
# Ensure it is present in ENTITY_CONDITIONS
|
||||
assert device_class in ENTITY_CONDITIONS
|
||||
# Ensure it is present in CONDITION_SCHEMA
|
||||
schema_types = (
|
||||
device_condition.CONDITION_SCHEMA.validators[0].schema["type"].container
|
||||
)
|
||||
assert constant_value in schema_types
|
||||
# Ensure it is present in string.json
|
||||
strings = load_json("homeassistant/components/sensor/strings.json")
|
||||
assert constant_value in strings["device_automation"]["condition_type"]
|
||||
|
||||
|
||||
async def test_get_conditions(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
|
|
|
@ -10,14 +10,17 @@ from homeassistant.components.sensor import (
|
|||
DOMAIN,
|
||||
SensorDeviceClass,
|
||||
SensorStateClass,
|
||||
device_trigger,
|
||||
)
|
||||
from homeassistant.components.sensor.const import NON_NUMERIC_DEVICE_CLASSES
|
||||
from homeassistant.components.sensor.device_trigger import ENTITY_TRIGGERS
|
||||
from homeassistant.const import CONF_PLATFORM, PERCENTAGE, STATE_UNKNOWN, EntityCategory
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.core import HomeAssistant, ServiceCall
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
from homeassistant.helpers.entity_registry import RegistryEntryHider
|
||||
from homeassistant.setup import async_setup_component
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.json import load_json
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
|
@ -32,11 +35,45 @@ from tests.testing_config.custom_components.test.sensor import UNITS_OF_MEASUREM
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def calls(hass):
|
||||
def calls(hass: HomeAssistant) -> list[ServiceCall]:
|
||||
"""Track calls to a mock service."""
|
||||
return async_mock_service(hass, "test", "automation")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"device_class",
|
||||
[
|
||||
device_class
|
||||
for device_class in SensorDeviceClass
|
||||
if device_class not in NON_NUMERIC_DEVICE_CLASSES
|
||||
],
|
||||
)
|
||||
def test_matches_device_classes(device_class: SensorDeviceClass) -> None:
|
||||
"""Ensure device class constants are declared in device_trigger module."""
|
||||
# Ensure it has corresponding CONF_*** constant
|
||||
constant_name = {
|
||||
SensorDeviceClass.BATTERY: "CONF_BATTERY_LEVEL",
|
||||
SensorDeviceClass.CO: "CONF_CO",
|
||||
SensorDeviceClass.CO2: "CONF_CO2",
|
||||
}.get(device_class, f"CONF_{device_class.value.upper()}")
|
||||
assert hasattr(device_trigger, constant_name), f"Missing constant {constant_name}"
|
||||
|
||||
# Ensure it has correct value
|
||||
constant_value = {
|
||||
SensorDeviceClass.BATTERY: "battery_level",
|
||||
}.get(device_class, device_class.value)
|
||||
assert getattr(device_trigger, constant_name) == constant_value
|
||||
|
||||
# Ensure it is present in ENTITY_TRIGGERS
|
||||
assert device_class in ENTITY_TRIGGERS
|
||||
# Ensure it is present in TRIGGER_SCHEMA
|
||||
schema_types = device_trigger.TRIGGER_SCHEMA.validators[0].schema["type"].container
|
||||
assert constant_value in schema_types
|
||||
# Ensure it is present in string.json
|
||||
strings = load_json("homeassistant/components/sensor/strings.json")
|
||||
assert constant_value in strings["device_automation"]["trigger_type"]
|
||||
|
||||
|
||||
async def test_get_triggers(
|
||||
hass: HomeAssistant,
|
||||
device_registry: dr.DeviceRegistry,
|
||||
|
|
Loading…
Reference in New Issue