1 """Component providing Switches for UniFi Protect."""
3 from __future__
import annotations
5 from collections.abc
import Sequence
6 from dataclasses
import dataclass
7 from functools
import partial
10 from uiprotect.data
import (
13 ProtectAdoptableDeviceModel,
24 from .data
import ProtectData, ProtectDeviceType, UFPConfigEntry
29 ProtectEntityDescription,
32 ProtectSetableKeysMixin,
34 async_all_device_entities,
37 ATTR_PREV_MIC =
"prev_mic_level"
38 ATTR_PREV_RECORD =
"prev_record_mode"
41 @dataclass(frozen=True, kw_only=True)
43 ProtectSetableKeysMixin[T], SwitchEntityDescription
45 """Describes UniFi Protect Switch entity."""
49 await obj.set_video_mode(VideoMode.HIGH_FPS
if value
else VideoMode.DEFAULT)
52 CAMERA_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
57 entity_registry_enabled_default=
False,
58 entity_category=EntityCategory.CONFIG,
59 ufp_value=
"is_ssh_enabled",
60 ufp_set_method=
"set_ssh",
61 ufp_perm=PermRequired.WRITE,
65 name=
"Status light on",
67 entity_category=EntityCategory.CONFIG,
68 ufp_required_field=
"feature_flags.has_led_status",
69 ufp_value=
"led_settings.is_enabled",
70 ufp_set_method=
"set_status_light",
71 ufp_perm=PermRequired.WRITE,
76 icon=
"mdi:brightness-7",
77 entity_category=EntityCategory.CONFIG,
78 entity_registry_enabled_default=
False,
79 ufp_required_field=
"feature_flags.has_hdr",
81 ufp_set_method=
"set_hdr",
82 ufp_perm=PermRequired.WRITE,
84 ProtectSwitchEntityDescription[Camera](
87 icon=
"mdi:video-high-definition",
88 entity_category=EntityCategory.CONFIG,
89 ufp_required_field=
"feature_flags.has_highfps",
90 ufp_value=
"is_high_fps_enabled",
91 ufp_set_method_fn=_set_highfps,
92 ufp_perm=PermRequired.WRITE,
98 entity_category=EntityCategory.CONFIG,
99 ufp_required_field=
"has_speaker",
100 ufp_value=
"speaker_settings.are_system_sounds_enabled",
101 ufp_enabled=
"feature_flags.has_speaker",
102 ufp_set_method=
"set_system_sounds",
103 ufp_perm=PermRequired.WRITE,
107 name=
"Overlay: show name",
108 icon=
"mdi:fullscreen",
109 entity_category=EntityCategory.CONFIG,
110 ufp_value=
"osd_settings.is_name_enabled",
111 ufp_set_method=
"set_osd_name",
112 ufp_perm=PermRequired.WRITE,
116 name=
"Overlay: show date",
117 icon=
"mdi:fullscreen",
118 entity_category=EntityCategory.CONFIG,
119 ufp_value=
"osd_settings.is_date_enabled",
120 ufp_set_method=
"set_osd_date",
121 ufp_perm=PermRequired.WRITE,
125 name=
"Overlay: show logo",
126 icon=
"mdi:fullscreen",
127 entity_category=EntityCategory.CONFIG,
128 ufp_value=
"osd_settings.is_logo_enabled",
129 ufp_set_method=
"set_osd_logo",
130 ufp_perm=PermRequired.WRITE,
134 name=
"Overlay: show nerd mode",
135 icon=
"mdi:fullscreen",
136 entity_category=EntityCategory.CONFIG,
137 ufp_value=
"osd_settings.is_debug_enabled",
138 ufp_set_method=
"set_osd_bitrate",
139 ufp_perm=PermRequired.WRITE,
142 key=
"color_night_vision",
143 name=
"Color night vision",
144 icon=
"mdi:light-flood-down",
145 entity_category=EntityCategory.CONFIG,
146 ufp_required_field=
"has_color_night_vision",
147 ufp_value=
"isp_settings.is_color_night_vision_enabled",
148 ufp_set_method=
"set_color_night_vision",
149 ufp_perm=PermRequired.WRITE,
153 name=
"Detections: motion",
155 entity_category=EntityCategory.CONFIG,
156 ufp_value=
"recording_settings.enable_motion_detection",
157 ufp_enabled=
"is_recording_enabled",
158 ufp_set_method=
"set_motion_detection",
159 ufp_perm=PermRequired.WRITE,
163 name=
"Detections: person",
165 entity_category=EntityCategory.CONFIG,
166 ufp_required_field=
"can_detect_person",
167 ufp_value=
"is_person_detection_on",
168 ufp_enabled=
"is_recording_enabled",
169 ufp_set_method=
"set_person_detection",
170 ufp_perm=PermRequired.WRITE,
174 name=
"Detections: vehicle",
176 entity_category=EntityCategory.CONFIG,
177 ufp_required_field=
"can_detect_vehicle",
178 ufp_value=
"is_vehicle_detection_on",
179 ufp_enabled=
"is_recording_enabled",
180 ufp_set_method=
"set_vehicle_detection",
181 ufp_perm=PermRequired.WRITE,
185 name=
"Detections: animal",
187 entity_category=EntityCategory.CONFIG,
188 ufp_required_field=
"can_detect_animal",
189 ufp_value=
"is_animal_detection_on",
190 ufp_enabled=
"is_recording_enabled",
191 ufp_set_method=
"set_animal_detection",
192 ufp_perm=PermRequired.WRITE,
196 name=
"Detections: package",
197 icon=
"mdi:package-variant-closed",
198 entity_category=EntityCategory.CONFIG,
199 ufp_required_field=
"can_detect_package",
200 ufp_value=
"is_package_detection_on",
201 ufp_enabled=
"is_recording_enabled",
202 ufp_set_method=
"set_package_detection",
203 ufp_perm=PermRequired.WRITE,
206 key=
"smart_licenseplate",
207 name=
"Detections: license plate",
209 entity_category=EntityCategory.CONFIG,
210 ufp_required_field=
"can_detect_license_plate",
211 ufp_value=
"is_license_plate_detection_on",
212 ufp_enabled=
"is_recording_enabled",
213 ufp_set_method=
"set_license_plate_detection",
214 ufp_perm=PermRequired.WRITE,
218 name=
"Detections: smoke",
220 entity_category=EntityCategory.CONFIG,
221 ufp_required_field=
"can_detect_smoke",
222 ufp_value=
"is_smoke_detection_on",
223 ufp_enabled=
"is_recording_enabled",
224 ufp_set_method=
"set_smoke_detection",
225 ufp_perm=PermRequired.WRITE,
229 name=
"Detections: CO",
230 icon=
"mdi:molecule-co",
231 entity_category=EntityCategory.CONFIG,
232 ufp_required_field=
"can_detect_co",
233 ufp_value=
"is_co_detection_on",
234 ufp_enabled=
"is_recording_enabled",
235 ufp_set_method=
"set_cmonx_detection",
236 ufp_perm=PermRequired.WRITE,
240 name=
"Detections: siren",
241 icon=
"mdi:alarm-bell",
242 entity_category=EntityCategory.CONFIG,
243 ufp_required_field=
"can_detect_siren",
244 ufp_value=
"is_siren_detection_on",
245 ufp_enabled=
"is_recording_enabled",
246 ufp_set_method=
"set_siren_detection",
247 ufp_perm=PermRequired.WRITE,
250 key=
"smart_baby_cry",
251 name=
"Detections: baby cry",
253 entity_category=EntityCategory.CONFIG,
254 ufp_required_field=
"can_detect_baby_cry",
255 ufp_value=
"is_baby_cry_detection_on",
256 ufp_enabled=
"is_recording_enabled",
257 ufp_set_method=
"set_baby_cry_detection",
258 ufp_perm=PermRequired.WRITE,
262 name=
"Detections: speaking",
263 icon=
"mdi:account-voice",
264 entity_category=EntityCategory.CONFIG,
265 ufp_required_field=
"can_detect_speaking",
266 ufp_value=
"is_speaking_detection_on",
267 ufp_enabled=
"is_recording_enabled",
268 ufp_set_method=
"set_speaking_detection",
269 ufp_perm=PermRequired.WRITE,
273 name=
"Detections: barking",
275 entity_category=EntityCategory.CONFIG,
276 ufp_required_field=
"can_detect_bark",
277 ufp_value=
"is_bark_detection_on",
278 ufp_enabled=
"is_recording_enabled",
279 ufp_set_method=
"set_bark_detection",
280 ufp_perm=PermRequired.WRITE,
283 key=
"smart_car_alarm",
284 name=
"Detections: car alarm",
286 entity_category=EntityCategory.CONFIG,
287 ufp_required_field=
"can_detect_car_alarm",
288 ufp_value=
"is_car_alarm_detection_on",
289 ufp_enabled=
"is_recording_enabled",
290 ufp_set_method=
"set_car_alarm_detection",
291 ufp_perm=PermRequired.WRITE,
294 key=
"smart_car_horn",
295 name=
"Detections: car horn",
297 entity_category=EntityCategory.CONFIG,
298 ufp_required_field=
"can_detect_car_horn",
299 ufp_value=
"is_car_horn_detection_on",
300 ufp_enabled=
"is_recording_enabled",
301 ufp_set_method=
"set_car_horn_detection",
302 ufp_perm=PermRequired.WRITE,
305 key=
"smart_glass_break",
306 name=
"Detections: glass break",
307 icon=
"mdi:glass-fragile",
308 entity_category=EntityCategory.CONFIG,
309 ufp_required_field=
"can_detect_glass_break",
310 ufp_value=
"is_glass_break_detection_on",
311 ufp_enabled=
"is_recording_enabled",
312 ufp_set_method=
"set_glass_break_detection",
313 ufp_perm=PermRequired.WRITE,
317 name=
"Tracking: person",
319 entity_category=EntityCategory.CONFIG,
320 ufp_required_field=
"feature_flags.is_ptz",
321 ufp_value=
"is_person_tracking_enabled",
322 ufp_set_method=
"set_person_track",
323 ufp_perm=PermRequired.WRITE,
327 PRIVACY_MODE_SWITCH = ProtectSwitchEntityDescription[Camera](
330 icon=
"mdi:eye-settings",
331 entity_category=EntityCategory.CONFIG,
332 ufp_required_field=
"feature_flags.has_privacy_mask",
333 ufp_value=
"is_privacy_on",
334 ufp_perm=PermRequired.WRITE,
337 SENSE_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
340 name=
"Status light on",
342 entity_category=EntityCategory.CONFIG,
343 ufp_value=
"led_settings.is_enabled",
344 ufp_set_method=
"set_status_light",
345 ufp_perm=PermRequired.WRITE,
349 name=
"Motion detection",
351 entity_category=EntityCategory.CONFIG,
352 ufp_value=
"motion_settings.is_enabled",
353 ufp_set_method=
"set_motion_status",
354 ufp_perm=PermRequired.WRITE,
358 name=
"Temperature sensor",
359 icon=
"mdi:thermometer",
360 entity_category=EntityCategory.CONFIG,
361 ufp_value=
"temperature_settings.is_enabled",
362 ufp_set_method=
"set_temperature_status",
363 ufp_perm=PermRequired.WRITE,
367 name=
"Humidity sensor",
368 icon=
"mdi:water-percent",
369 entity_category=EntityCategory.CONFIG,
370 ufp_value=
"humidity_settings.is_enabled",
371 ufp_set_method=
"set_humidity_status",
372 ufp_perm=PermRequired.WRITE,
377 icon=
"mdi:brightness-5",
378 entity_category=EntityCategory.CONFIG,
379 ufp_value=
"light_settings.is_enabled",
380 ufp_set_method=
"set_light_status",
381 ufp_perm=PermRequired.WRITE,
385 name=
"Alarm sound detection",
386 entity_category=EntityCategory.CONFIG,
387 ufp_value=
"alarm_settings.is_enabled",
388 ufp_set_method=
"set_alarm_status",
389 ufp_perm=PermRequired.WRITE,
394 LIGHT_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
399 entity_registry_enabled_default=
False,
400 entity_category=EntityCategory.CONFIG,
401 ufp_value=
"is_ssh_enabled",
402 ufp_set_method=
"set_ssh",
403 ufp_perm=PermRequired.WRITE,
407 name=
"Status light on",
409 entity_category=EntityCategory.CONFIG,
410 ufp_value=
"light_device_settings.is_indicator_enabled",
411 ufp_set_method=
"set_status_light",
412 ufp_perm=PermRequired.WRITE,
416 DOORLOCK_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
419 name=
"Status light on",
421 entity_category=EntityCategory.CONFIG,
422 ufp_value=
"led_settings.is_enabled",
423 ufp_set_method=
"set_status_light",
424 ufp_perm=PermRequired.WRITE,
428 VIEWER_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
433 entity_registry_enabled_default=
False,
434 entity_category=EntityCategory.CONFIG,
435 ufp_value=
"is_ssh_enabled",
436 ufp_set_method=
"set_ssh",
437 ufp_perm=PermRequired.WRITE,
441 NVR_SWITCHES: tuple[ProtectSwitchEntityDescription, ...] = (
443 key=
"analytics_enabled",
444 name=
"Analytics enabled",
445 icon=
"mdi:google-analytics",
446 entity_category=EntityCategory.CONFIG,
447 ufp_value=
"is_analytics_enabled",
448 ufp_set_method=
"set_anonymous_analytics",
451 key=
"insights_enabled",
452 name=
"Insights enabled",
454 entity_category=EntityCategory.CONFIG,
455 ufp_value=
"is_insights_enabled",
456 ufp_set_method=
"set_insights",
460 _MODEL_DESCRIPTIONS: dict[ModelType, Sequence[ProtectEntityDescription]] = {
461 ModelType.CAMERA: CAMERA_SWITCHES,
462 ModelType.LIGHT: LIGHT_SWITCHES,
463 ModelType.SENSOR: SENSE_SWITCHES,
464 ModelType.DOORLOCK: DOORLOCK_SWITCHES,
465 ModelType.VIEWPORT: VIEWER_SWITCHES,
468 _PRIVACY_DESCRIPTIONS: dict[ModelType, Sequence[ProtectEntityDescription]] = {
469 ModelType.CAMERA: [PRIVACY_MODE_SWITCH]
474 """Base class for UniFi Protect Switch."""
476 entity_description: ProtectSwitchEntityDescription
479 """Turn the device on."""
483 """Turn the device off."""
488 """A UniFi Protect Switch."""
490 entity_description: ProtectSwitchEntityDescription
494 """A UniFi Protect NVR Switch."""
496 entity_description: ProtectSwitchEntityDescription
500 """A UniFi Protect Switch."""
503 entity_description: ProtectSwitchEntityDescription
509 description: ProtectSwitchEntityDescription,
511 """Initialize an UniFi Protect Switch."""
512 super().
__init__(data, device, description)
513 if device.is_privacy_on:
517 ATTR_PREV_RECORD, RecordingMode.ALWAYS
541 """Turn the device on."""
544 await self.
devicedevice.set_privacy(
True, 0, RecordingMode.NEVER)
547 """Turn the device off."""
551 await self.
devicedevice.set_privacy(
False, prev_mic, prev_record)
554 """Restore extra state attributes on startp up."""
558 last_attrs = last_state.attributes
570 entry: UFPConfigEntry,
571 async_add_entities: AddEntitiesCallback,
573 """Set up sensors for UniFi Protect integration."""
574 data = entry.runtime_data
577 def _add_new_device(device: ProtectAdoptableDeviceModel) ->
None:
578 _make_entities = partial(async_all_device_entities, data, ufp_device=device)
579 entities: list[BaseProtectEntity] = []
580 entities += _make_entities(ProtectSwitch, _MODEL_DESCRIPTIONS)
581 entities += _make_entities(ProtectPrivacyModeSwitch, _PRIVACY_DESCRIPTIONS)
584 _make_entities = partial(async_all_device_entities, data)
585 data.async_subscribe_adopt(_add_new_device)
586 entities: list[BaseProtectEntity] = []
587 entities += _make_entities(ProtectSwitch, _MODEL_DESCRIPTIONS)
588 entities += _make_entities(ProtectPrivacyModeSwitch, _PRIVACY_DESCRIPTIONS)
589 bootstrap = data.api.bootstrap
591 if nvr.can_write(bootstrap.auth_user)
and nvr.is_insights_enabled
is not None:
594 for switch
in NVR_SWITCHES
None async_turn_on(self, **Any kwargs)
None async_turn_on(self, **Any kwargs)
None _update_previous_attr(self)
None _async_update_device_from_protect(self, ProtectDeviceType device)
None async_added_to_hass(self)
None __init__(self, ProtectData data, Camera device, ProtectSwitchEntityDescription description)
_attr_extra_state_attributes
None async_turn_off(self, **Any kwargs)
Mapping[str, Any]|None extra_state_attributes(self)
State|None async_get_last_state(self)
None async_turn_off(self, **Any kwargs)
None async_setup_entry(HomeAssistant hass, UFPConfigEntry entry, AddEntitiesCallback async_add_entities)
None _set_highfps(Camera obj, bool value)