1 """Implement device conditions for binary sensor."""
3 from __future__
import annotations
5 import voluptuous
as vol
18 config_validation
as cv,
19 entity_registry
as er,
24 from .
import DOMAIN, BinarySensorDeviceClass
28 DEVICE_CLASS_NONE =
"none"
30 CONF_IS_BAT_LOW =
"is_bat_low"
31 CONF_IS_NOT_BAT_LOW =
"is_not_bat_low"
32 CONF_IS_CHARGING =
"is_charging"
33 CONF_IS_NOT_CHARGING =
"is_not_charging"
35 CONF_IS_NO_CO =
"is_no_co"
36 CONF_IS_COLD =
"is_cold"
37 CONF_IS_NOT_COLD =
"is_not_cold"
38 CONF_IS_CONNECTED =
"is_connected"
39 CONF_IS_NOT_CONNECTED =
"is_not_connected"
40 CONF_IS_GAS =
"is_gas"
41 CONF_IS_NO_GAS =
"is_no_gas"
42 CONF_IS_HOT =
"is_hot"
43 CONF_IS_NOT_HOT =
"is_not_hot"
44 CONF_IS_LIGHT =
"is_light"
45 CONF_IS_NO_LIGHT =
"is_no_light"
46 CONF_IS_LOCKED =
"is_locked"
47 CONF_IS_NOT_LOCKED =
"is_not_locked"
48 CONF_IS_MOIST =
"is_moist"
49 CONF_IS_NOT_MOIST =
"is_not_moist"
50 CONF_IS_MOTION =
"is_motion"
51 CONF_IS_NO_MOTION =
"is_no_motion"
52 CONF_IS_MOVING =
"is_moving"
53 CONF_IS_NOT_MOVING =
"is_not_moving"
54 CONF_IS_OCCUPIED =
"is_occupied"
55 CONF_IS_NOT_OCCUPIED =
"is_not_occupied"
56 CONF_IS_PLUGGED_IN =
"is_plugged_in"
57 CONF_IS_NOT_PLUGGED_IN =
"is_not_plugged_in"
58 CONF_IS_POWERED =
"is_powered"
59 CONF_IS_NOT_POWERED =
"is_not_powered"
60 CONF_IS_PRESENT =
"is_present"
61 CONF_IS_NOT_PRESENT =
"is_not_present"
62 CONF_IS_PROBLEM =
"is_problem"
63 CONF_IS_NO_PROBLEM =
"is_no_problem"
64 CONF_IS_RUNNING =
"is_running"
65 CONF_IS_NOT_RUNNING =
"is_not_running"
66 CONF_IS_UNSAFE =
"is_unsafe"
67 CONF_IS_NOT_UNSAFE =
"is_not_unsafe"
68 CONF_IS_SMOKE =
"is_smoke"
69 CONF_IS_NO_SMOKE =
"is_no_smoke"
70 CONF_IS_SOUND =
"is_sound"
71 CONF_IS_NO_SOUND =
"is_no_sound"
72 CONF_IS_TAMPERED =
"is_tampered"
73 CONF_IS_NOT_TAMPERED =
"is_not_tampered"
74 CONF_IS_UPDATE =
"is_update"
75 CONF_IS_NO_UPDATE =
"is_no_update"
76 CONF_IS_VIBRATION =
"is_vibration"
77 CONF_IS_NO_VIBRATION =
"is_no_vibration"
78 CONF_IS_OPEN =
"is_open"
79 CONF_IS_NOT_OPEN =
"is_not_open"
112 CONF_IS_NOT_CHARGING,
114 CONF_IS_NOT_CONNECTED,
119 CONF_IS_NOT_OCCUPIED,
121 CONF_IS_NOT_PLUGGED_IN,
124 CONF_IS_NOT_TAMPERED,
135 CONF_IS_NO_VIBRATION,
139 ENTITY_CONDITIONS = {
140 BinarySensorDeviceClass.BATTERY: [
141 {CONF_TYPE: CONF_IS_BAT_LOW},
142 {CONF_TYPE: CONF_IS_NOT_BAT_LOW},
144 BinarySensorDeviceClass.BATTERY_CHARGING: [
145 {CONF_TYPE: CONF_IS_CHARGING},
146 {CONF_TYPE: CONF_IS_NOT_CHARGING},
148 BinarySensorDeviceClass.CO: [
149 {CONF_TYPE: CONF_IS_CO},
150 {CONF_TYPE: CONF_IS_NO_CO},
152 BinarySensorDeviceClass.COLD: [
153 {CONF_TYPE: CONF_IS_COLD},
154 {CONF_TYPE: CONF_IS_NOT_COLD},
156 BinarySensorDeviceClass.CONNECTIVITY: [
157 {CONF_TYPE: CONF_IS_CONNECTED},
158 {CONF_TYPE: CONF_IS_NOT_CONNECTED},
160 BinarySensorDeviceClass.DOOR: [
161 {CONF_TYPE: CONF_IS_OPEN},
162 {CONF_TYPE: CONF_IS_NOT_OPEN},
164 BinarySensorDeviceClass.GARAGE_DOOR: [
165 {CONF_TYPE: CONF_IS_OPEN},
166 {CONF_TYPE: CONF_IS_NOT_OPEN},
168 BinarySensorDeviceClass.GAS: [
169 {CONF_TYPE: CONF_IS_GAS},
170 {CONF_TYPE: CONF_IS_NO_GAS},
172 BinarySensorDeviceClass.HEAT: [
173 {CONF_TYPE: CONF_IS_HOT},
174 {CONF_TYPE: CONF_IS_NOT_HOT},
176 BinarySensorDeviceClass.LIGHT: [
177 {CONF_TYPE: CONF_IS_LIGHT},
178 {CONF_TYPE: CONF_IS_NO_LIGHT},
180 BinarySensorDeviceClass.LOCK: [
181 {CONF_TYPE: CONF_IS_LOCKED},
182 {CONF_TYPE: CONF_IS_NOT_LOCKED},
184 BinarySensorDeviceClass.MOISTURE: [
185 {CONF_TYPE: CONF_IS_MOIST},
186 {CONF_TYPE: CONF_IS_NOT_MOIST},
188 BinarySensorDeviceClass.MOTION: [
189 {CONF_TYPE: CONF_IS_MOTION},
190 {CONF_TYPE: CONF_IS_NO_MOTION},
192 BinarySensorDeviceClass.MOVING: [
193 {CONF_TYPE: CONF_IS_MOVING},
194 {CONF_TYPE: CONF_IS_NOT_MOVING},
196 BinarySensorDeviceClass.OCCUPANCY: [
197 {CONF_TYPE: CONF_IS_OCCUPIED},
198 {CONF_TYPE: CONF_IS_NOT_OCCUPIED},
200 BinarySensorDeviceClass.OPENING: [
201 {CONF_TYPE: CONF_IS_OPEN},
202 {CONF_TYPE: CONF_IS_NOT_OPEN},
204 BinarySensorDeviceClass.PLUG: [
205 {CONF_TYPE: CONF_IS_PLUGGED_IN},
206 {CONF_TYPE: CONF_IS_NOT_PLUGGED_IN},
208 BinarySensorDeviceClass.POWER: [
209 {CONF_TYPE: CONF_IS_POWERED},
210 {CONF_TYPE: CONF_IS_NOT_POWERED},
212 BinarySensorDeviceClass.PRESENCE: [
213 {CONF_TYPE: CONF_IS_PRESENT},
214 {CONF_TYPE: CONF_IS_NOT_PRESENT},
216 BinarySensorDeviceClass.PROBLEM: [
217 {CONF_TYPE: CONF_IS_PROBLEM},
218 {CONF_TYPE: CONF_IS_NO_PROBLEM},
220 BinarySensorDeviceClass.RUNNING: [
221 {CONF_TYPE: CONF_IS_RUNNING},
222 {CONF_TYPE: CONF_IS_NOT_RUNNING},
224 BinarySensorDeviceClass.SAFETY: [
225 {CONF_TYPE: CONF_IS_UNSAFE},
226 {CONF_TYPE: CONF_IS_NOT_UNSAFE},
228 BinarySensorDeviceClass.SMOKE: [
229 {CONF_TYPE: CONF_IS_SMOKE},
230 {CONF_TYPE: CONF_IS_NO_SMOKE},
232 BinarySensorDeviceClass.SOUND: [
233 {CONF_TYPE: CONF_IS_SOUND},
234 {CONF_TYPE: CONF_IS_NO_SOUND},
236 BinarySensorDeviceClass.TAMPER: [
237 {CONF_TYPE: CONF_IS_TAMPERED},
238 {CONF_TYPE: CONF_IS_NOT_TAMPERED},
240 BinarySensorDeviceClass.UPDATE: [
241 {CONF_TYPE: CONF_IS_UPDATE},
242 {CONF_TYPE: CONF_IS_NO_UPDATE},
244 BinarySensorDeviceClass.VIBRATION: [
245 {CONF_TYPE: CONF_IS_VIBRATION},
246 {CONF_TYPE: CONF_IS_NO_VIBRATION},
248 BinarySensorDeviceClass.WINDOW: [
249 {CONF_TYPE: CONF_IS_OPEN},
250 {CONF_TYPE: CONF_IS_NOT_OPEN},
253 {CONF_TYPE: CONF_IS_ON},
254 {CONF_TYPE: CONF_IS_OFF},
258 CONDITION_SCHEMA = cv.DEVICE_CONDITION_BASE_SCHEMA.extend(
260 vol.Required(CONF_ENTITY_ID): cv.entity_id_or_uuid,
261 vol.Required(CONF_TYPE): vol.In(IS_OFF + IS_ON),
262 vol.Optional(CONF_FOR): cv.positive_time_period_dict,
268 hass: HomeAssistant, device_id: str
269 ) -> list[dict[str, str]]:
270 """List device conditions."""
271 conditions: list[dict[str, str]] = []
272 entity_registry = er.async_get(hass)
275 for entry
in er.async_entries_for_device(entity_registry, device_id)
276 if entry.domain == DOMAIN
279 for entry
in entries:
282 templates = ENTITY_CONDITIONS.get(
283 device_class, ENTITY_CONDITIONS[DEVICE_CLASS_NONE]
289 "condition":
"device",
290 "device_id": device_id,
291 "entity_id": entry.id,
294 for template
in templates
302 hass: HomeAssistant, config: ConfigType
303 ) -> condition.ConditionCheckerType:
304 """Evaluate state based on configuration."""
305 condition_type = config[CONF_TYPE]
306 if condition_type
in IS_ON:
311 CONF_CONDITION:
"state",
312 CONF_ENTITY_ID: config[CONF_ENTITY_ID],
315 if CONF_FOR
in config:
316 state_config[CONF_FOR] = config[CONF_FOR]
317 state_config = cv.STATE_CONDITION_SCHEMA(state_config)
318 state_config = condition.state_validate_config(hass, state_config)
320 return condition.state_from_config(state_config)
324 hass: HomeAssistant, config: ConfigType
325 ) -> dict[str, vol.Schema]:
326 """List condition capabilities."""
328 "extra_fields": vol.Schema(
329 {vol.Optional(CONF_FOR): cv.positive_time_period_dict}
dict[str, vol.Schema] async_get_condition_capabilities(HomeAssistant hass, ConfigType config)
condition.ConditionCheckerType async_condition_from_config(HomeAssistant hass, ConfigType config)
list[dict[str, str]] async_get_conditions(HomeAssistant hass, str device_id)
str|None get_device_class(HomeAssistant hass, str entity_id)