1 """Provides device triggers for sensors."""
3 import voluptuous
as vol
6 DEVICE_TRIGGER_BASE_SCHEMA,
7 InvalidDeviceAutomationConfig,
8 async_get_entity_registry_entry_or_raise,
11 numeric_state
as numeric_state_trigger,
26 get_unit_of_measurement,
31 from .
import ATTR_STATE_CLASS, DOMAIN, SensorDeviceClass
33 DEVICE_CLASS_NONE =
"none"
35 CONF_APPARENT_POWER =
"apparent_power"
38 CONF_ATMOSPHERIC_PRESSURE =
"atmospheric_pressure"
39 CONF_BATTERY_LEVEL =
"battery_level"
40 CONF_BLOOD_GLUCOSE_CONCENTRATION =
"blood_glucose_concentration"
41 CONF_CO =
"carbon_monoxide"
42 CONF_CO2 =
"carbon_dioxide"
43 CONF_CONDUCTIVITY =
"conductivity"
44 CONF_CURRENT =
"current"
45 CONF_DATA_RATE =
"data_rate"
46 CONF_DATA_SIZE =
"data_size"
47 CONF_DISTANCE =
"distance"
48 CONF_DURATION =
"duration"
49 CONF_ENERGY =
"energy"
50 CONF_FREQUENCY =
"frequency"
52 CONF_HUMIDITY =
"humidity"
53 CONF_ILLUMINANCE =
"illuminance"
54 CONF_IRRADIANCE =
"irradiance"
55 CONF_MOISTURE =
"moisture"
56 CONF_MONETARY =
"monetary"
57 CONF_NITROGEN_DIOXIDE =
"nitrogen_dioxide"
58 CONF_NITROGEN_MONOXIDE =
"nitrogen_monoxide"
59 CONF_NITROUS_OXIDE =
"nitrous_oxide"
66 CONF_POWER_FACTOR =
"power_factor"
67 CONF_PRECIPITATION =
"precipitation"
68 CONF_PRECIPITATION_INTENSITY =
"precipitation_intensity"
69 CONF_PRESSURE =
"pressure"
70 CONF_REACTIVE_POWER =
"reactive_power"
71 CONF_SIGNAL_STRENGTH =
"signal_strength"
72 CONF_SOUND_PRESSURE =
"sound_pressure"
74 CONF_SULPHUR_DIOXIDE =
"sulphur_dioxide"
75 CONF_TEMPERATURE =
"temperature"
77 CONF_VOLATILE_ORGANIC_COMPOUNDS =
"volatile_organic_compounds"
78 CONF_VOLATILE_ORGANIC_COMPOUNDS_PARTS =
"volatile_organic_compounds_parts"
79 CONF_VOLTAGE =
"voltage"
80 CONF_VOLUME =
"volume"
81 CONF_VOLUME_FLOW_RATE =
"volume_flow_rate"
83 CONF_WEIGHT =
"weight"
84 CONF_WIND_SPEED =
"wind_speed"
87 SensorDeviceClass.APPARENT_POWER: [{CONF_TYPE: CONF_APPARENT_POWER}],
88 SensorDeviceClass.AQI: [{CONF_TYPE: CONF_AQI}],
89 SensorDeviceClass.AREA: [{CONF_TYPE: CONF_AREA}],
90 SensorDeviceClass.ATMOSPHERIC_PRESSURE: [{CONF_TYPE: CONF_ATMOSPHERIC_PRESSURE}],
91 SensorDeviceClass.BATTERY: [{CONF_TYPE: CONF_BATTERY_LEVEL}],
92 SensorDeviceClass.BLOOD_GLUCOSE_CONCENTRATION: [
93 {CONF_TYPE: CONF_BLOOD_GLUCOSE_CONCENTRATION}
95 SensorDeviceClass.CO: [{CONF_TYPE: CONF_CO}],
96 SensorDeviceClass.CO2: [{CONF_TYPE: CONF_CO2}],
97 SensorDeviceClass.CONDUCTIVITY: [{CONF_TYPE: CONF_CONDUCTIVITY}],
98 SensorDeviceClass.CURRENT: [{CONF_TYPE: CONF_CURRENT}],
99 SensorDeviceClass.DATA_RATE: [{CONF_TYPE: CONF_DATA_RATE}],
100 SensorDeviceClass.DATA_SIZE: [{CONF_TYPE: CONF_DATA_SIZE}],
101 SensorDeviceClass.DISTANCE: [{CONF_TYPE: CONF_DISTANCE}],
102 SensorDeviceClass.DURATION: [{CONF_TYPE: CONF_DURATION}],
103 SensorDeviceClass.ENERGY: [{CONF_TYPE: CONF_ENERGY}],
104 SensorDeviceClass.ENERGY_STORAGE: [{CONF_TYPE: CONF_ENERGY}],
105 SensorDeviceClass.FREQUENCY: [{CONF_TYPE: CONF_FREQUENCY}],
106 SensorDeviceClass.GAS: [{CONF_TYPE: CONF_GAS}],
107 SensorDeviceClass.HUMIDITY: [{CONF_TYPE: CONF_HUMIDITY}],
108 SensorDeviceClass.ILLUMINANCE: [{CONF_TYPE: CONF_ILLUMINANCE}],
109 SensorDeviceClass.IRRADIANCE: [{CONF_TYPE: CONF_IRRADIANCE}],
110 SensorDeviceClass.MOISTURE: [{CONF_TYPE: CONF_MOISTURE}],
111 SensorDeviceClass.MONETARY: [{CONF_TYPE: CONF_MONETARY}],
112 SensorDeviceClass.NITROGEN_DIOXIDE: [{CONF_TYPE: CONF_NITROGEN_DIOXIDE}],
113 SensorDeviceClass.NITROGEN_MONOXIDE: [{CONF_TYPE: CONF_NITROGEN_MONOXIDE}],
114 SensorDeviceClass.NITROUS_OXIDE: [{CONF_TYPE: CONF_NITROUS_OXIDE}],
115 SensorDeviceClass.OZONE: [{CONF_TYPE: CONF_OZONE}],
116 SensorDeviceClass.PH: [{CONF_TYPE: CONF_PH}],
117 SensorDeviceClass.PM1: [{CONF_TYPE: CONF_PM1}],
118 SensorDeviceClass.PM10: [{CONF_TYPE: CONF_PM10}],
119 SensorDeviceClass.PM25: [{CONF_TYPE: CONF_PM25}],
120 SensorDeviceClass.POWER: [{CONF_TYPE: CONF_POWER}],
121 SensorDeviceClass.POWER_FACTOR: [{CONF_TYPE: CONF_POWER_FACTOR}],
122 SensorDeviceClass.PRECIPITATION: [{CONF_TYPE: CONF_PRECIPITATION}],
123 SensorDeviceClass.PRECIPITATION_INTENSITY: [
124 {CONF_TYPE: CONF_PRECIPITATION_INTENSITY}
126 SensorDeviceClass.PRESSURE: [{CONF_TYPE: CONF_PRESSURE}],
127 SensorDeviceClass.REACTIVE_POWER: [{CONF_TYPE: CONF_REACTIVE_POWER}],
128 SensorDeviceClass.SIGNAL_STRENGTH: [{CONF_TYPE: CONF_SIGNAL_STRENGTH}],
129 SensorDeviceClass.SOUND_PRESSURE: [{CONF_TYPE: CONF_SOUND_PRESSURE}],
130 SensorDeviceClass.SPEED: [{CONF_TYPE: CONF_SPEED}],
131 SensorDeviceClass.SULPHUR_DIOXIDE: [{CONF_TYPE: CONF_SULPHUR_DIOXIDE}],
132 SensorDeviceClass.TEMPERATURE: [{CONF_TYPE: CONF_TEMPERATURE}],
133 SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: [
134 {CONF_TYPE: CONF_VOLATILE_ORGANIC_COMPOUNDS}
136 SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS: [
137 {CONF_TYPE: CONF_VOLATILE_ORGANIC_COMPOUNDS_PARTS}
139 SensorDeviceClass.VOLTAGE: [{CONF_TYPE: CONF_VOLTAGE}],
140 SensorDeviceClass.VOLUME: [{CONF_TYPE: CONF_VOLUME}],
141 SensorDeviceClass.VOLUME_STORAGE: [{CONF_TYPE: CONF_VOLUME}],
142 SensorDeviceClass.VOLUME_FLOW_RATE: [{CONF_TYPE: CONF_VOLUME_FLOW_RATE}],
143 SensorDeviceClass.WATER: [{CONF_TYPE: CONF_WATER}],
144 SensorDeviceClass.WEIGHT: [{CONF_TYPE: CONF_WEIGHT}],
145 SensorDeviceClass.WIND_SPEED: [{CONF_TYPE: CONF_WIND_SPEED}],
146 DEVICE_CLASS_NONE: [{CONF_TYPE: CONF_VALUE}],
150 TRIGGER_SCHEMA = vol.All(
151 DEVICE_TRIGGER_BASE_SCHEMA.extend(
153 vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
154 vol.Required(CONF_TYPE): vol.In(
159 CONF_ATMOSPHERIC_PRESSURE,
161 CONF_BLOOD_GLUCOSE_CONCENTRATION,
178 CONF_NITROGEN_DIOXIDE,
179 CONF_NITROGEN_MONOXIDE,
189 CONF_PRECIPITATION_INTENSITY,
192 CONF_SIGNAL_STRENGTH,
195 CONF_SULPHUR_DIOXIDE,
197 CONF_VOLATILE_ORGANIC_COMPOUNDS,
198 CONF_VOLATILE_ORGANIC_COMPOUNDS_PARTS,
201 CONF_VOLUME_FLOW_RATE,
208 vol.Optional(CONF_BELOW): vol.Any(vol.Coerce(float)),
209 vol.Optional(CONF_ABOVE): vol.Any(vol.Coerce(float)),
210 vol.Optional(CONF_FOR): cv.positive_time_period_dict,
213 cv.has_at_least_one_key(CONF_BELOW, CONF_ABOVE),
220 action: TriggerActionType,
221 trigger_info: TriggerInfo,
223 """Listen for state changes based on configuration."""
224 numeric_state_config = {
225 numeric_state_trigger.CONF_PLATFORM:
"numeric_state",
226 numeric_state_trigger.CONF_ENTITY_ID: config[CONF_ENTITY_ID],
228 if CONF_ABOVE
in config:
229 numeric_state_config[numeric_state_trigger.CONF_ABOVE] = config[CONF_ABOVE]
230 if CONF_BELOW
in config:
231 numeric_state_config[numeric_state_trigger.CONF_BELOW] = config[CONF_BELOW]
232 if CONF_FOR
in config:
233 numeric_state_config[CONF_FOR] = config[CONF_FOR]
235 numeric_state_config = await numeric_state_trigger.async_validate_trigger_config(
236 hass, numeric_state_config
238 return await numeric_state_trigger.async_attach_trigger(
239 hass, numeric_state_config, action, trigger_info, platform_type=
"device"
244 hass: HomeAssistant, device_id: str
245 ) -> list[dict[str, str]]:
246 """List device triggers."""
247 triggers: list[dict[str, str]] = []
248 entity_registry = er.async_get(hass)
252 for entry
in er.async_entries_for_device(entity_registry, device_id)
253 if entry.domain == DOMAIN
256 for entry
in entries:
258 state_class =
get_capability(hass, entry.entity_id, ATTR_STATE_CLASS)
261 if not unit_of_measurement
and not state_class:
264 templates = ENTITY_TRIGGERS.get(
265 device_class, ENTITY_TRIGGERS[DEVICE_CLASS_NONE]
271 "platform":
"device",
272 "device_id": device_id,
273 "entity_id": entry.id,
276 for automation
in templates
283 hass: HomeAssistant, config: ConfigType
284 ) -> dict[str, vol.Schema]:
285 """List trigger capabilities."""
290 except HomeAssistantError:
291 unit_of_measurement =
None
293 if not unit_of_measurement:
295 f
"No unit of measurement found for trigger entity {config[CONF_ENTITY_ID]}"
299 "extra_fields": vol.Schema(
302 CONF_ABOVE, description={
"suffix": unit_of_measurement}
303 ): vol.Coerce(float),
305 CONF_BELOW, description={
"suffix": unit_of_measurement}
306 ): vol.Coerce(float),
307 vol.Optional(CONF_FOR): cv.positive_time_period_dict,
er.RegistryEntry async_get_entity_registry_entry_or_raise(HomeAssistant hass, str entity_registry_id)
dict[str, vol.Schema] async_get_trigger_capabilities(HomeAssistant hass, ConfigType config)
CALLBACK_TYPE async_attach_trigger(HomeAssistant hass, ConfigType config, TriggerActionType action, TriggerInfo trigger_info)
list[dict[str, str]] async_get_triggers(HomeAssistant hass, str device_id)
str|None get_device_class(HomeAssistant hass, str entity_id)
Any|None get_capability(HomeAssistant hass, str entity_id, str capability)
str|None get_unit_of_measurement(HomeAssistant hass, str entity_id)