Last active
August 25, 2024 22:40
-
-
Save benjivesterby/2b6d3f93ef1758679cf38a83b7cd4b98 to your computer and use it in GitHub Desktop.
UniFi Protect Motion / Smart Detection Notifications
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
blueprint: | |
name: UniFi Protect Motion / Smart Detection Notifications | |
domain: automation | |
source_url: https://raw.githubusercontent.com/AngellusMortis/unifiprotect_blueprints/main/blueprints/automation/unifiprotect/notification_smart_motion_event.yaml | |
description: "## UniFi Protect Motion / Smart Detection Notifications\n\nThis blueprint | |
will send push notifications to a Home Assistant mobile app when a camera detections | |
motion or a\nsmart detection.\n\n### Required Settings\n\n - UniFi Protect Detection | |
Sensor\n\n### Optional Settings\n\n - Notification target for the [mobile app | |
notification target][1].\n - Presence filter - list of mobile phones or other | |
entities that should be within the \"home\" zone\n - Alarm entity to check arm | |
states.\n - Alarm arm states when the notifications should work. Required if | |
alarm entity is selected.\n - Time formatting strings. Timestamp is injected | |
into the notification in case the notification is delay.\n - Cooldown before | |
sending another notification\n - Silence timer for muting notifications via Actionable | |
Notification (docs: [Mobile][2])\n - Configurable lovelace view from notification\n\n | |
\ The presence filter works together with the alarm entity (you can choose presence | |
filter or alarm entity, you can choose both or nothing at all).\n\n### Requirements\n\nTo | |
take full effect of this automation blueprint, your Home Assistant instance needs | |
some setup beforehand.\n\n- An UniFi Protect camera. Only cameras that are capable | |
of smart detections (G4, AI or G5 Series cameras) will have objection detection | |
sensors.\n- A valid HTTPS certificate and [properly configured external URL][3]\n | |
\ - If you are using Home Assistant Cloud, this is already set up for you.\n - | |
If this is not setup correctly, the actionable notifications and attachments will | |
not appear in the notifications.\n - You do not need your _whole_ Home Assistant | |
to be publicly accessible. Only the paths `/api/unifiprotect/*` and\n `/api/webhook/*` | |
need to be accessible outside of your network.\n\n[1]: https://companion.home-assistant.io/docs/notifications/notifications-basic#sending-notifications-to-multiple-devices\n[2]: | |
https://companion.home-assistant.io/docs/notifications/actionable-notifications/\n[3]: | |
https://www.home-assistant.io/docs/configuration/remote/\n" | |
input: | |
obj_sensor: | |
name: Detection Sensor | |
description: 'The "Motion/Person/etc. Detected" sensor(s) to use. | |
' | |
selector: | |
entity: | |
integration: unifiprotect | |
domain: | |
- binary_sensor | |
multiple: true | |
presence_filter: | |
name: (Optional) Presence Filter | |
description: Only notify if selected presence entity is not "home". | |
default: '' | |
selector: | |
entity: | |
domain: | |
- device_tracker | |
multiple: true | |
alarm_entity: | |
name: (Optional) Alarm Entity | |
default: '' | |
description: The alarm entity to monitor for state changes. | |
selector: | |
entity: | |
domain: | |
- alarm_control_panel | |
multiple: false | |
alarm_arm_states: | |
name: Alarm Arm States | |
description: Select the alarm arm states for which you want to receive notifications. | |
Required if an Alarm Entity is set. | |
default: | |
- armed_away | |
- armed_home | |
- armed_night | |
- armed_vacation | |
- armed_custom_bypass | |
selector: | |
select: | |
options: | |
- armed_away | |
- armed_home | |
- armed_night | |
- armed_vacation | |
- armed_custom_bypass | |
multiple: true | |
sort: false | |
custom_value: false | |
notify_target_app: | |
name: (Optional) Notification Target (Mobile App) | |
description: 'The notification target for mobile apps notifications. Can be | |
`notifiy.notify` or any Mobile app notify service (starts with `notify.mobile_app_`). | |
https://companion.home-assistant.io/docs/notifications/notifications-basic#sending-notifications-to-multiple-devices | |
' | |
default: notify.notify | |
selector: | |
text: {} | |
channel: | |
name: (Optional) Notification Channel | |
description: 'Notification channel/tag to use. Will automatically be prepended | |
with "Manual " if action is triggered manually. https://companion.home-assistant.io/docs/notifications/notifications-basic#notification-channels | |
' | |
default: Smart Detection | |
selector: | |
text: {} | |
time_format: | |
name: (Optional) Time Format String | |
description: 'Python datetime format code string for the event trigger time. | |
This string is the actual time the doorbell event was triggered in case the | |
automation or notification is delayed. Manual triggers will cause this to | |
always be the time of the previous event. https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes | |
' | |
default: '%I:%M %p' | |
selector: | |
entity: {} | |
cooldown: | |
name: (Optional) Cooldown | |
description: 'Delay before sending another notification for this camera after | |
the last event. Is also the interval you have to respond to actions in notification. | |
' | |
default: 120 | |
selector: | |
number: | |
max: 300.0 | |
min: 0.0 | |
unit_of_measurement: seconds | |
mode: slider | |
step: 1.0 | |
silence_timer: | |
name: (Optional) Silence Notifications | |
description: 'How long to silence notifications for this camera when requested | |
as part of the actionable notification. The time interval you have to respond | |
to the slient action is controlled by "Cooldown". Short Cooldown timers may | |
prevent you from silencing. | |
' | |
default: 30 | |
selector: | |
number: | |
max: 300.0 | |
min: 0.0 | |
unit_of_measurement: minutes | |
mode: slider | |
step: 1.0 | |
lovelace_view: | |
name: (Optional) Lovelace View | |
description: 'Home Assistant Lovelace view to open when clicking notification. | |
If left blank, URI Notification actions will not be generated. | |
' | |
default: '' | |
selector: | |
text: {} | |
debug_event_id: | |
name: (Optional) Debug Event ID | |
description: 'Debug Event ID for UniFi Protect to use for when manually triggering | |
automation. Will be used to generate a thumbnail for testing notifications. | |
' | |
default: '' | |
selector: | |
text: {} | |
mode: single | |
max_exceeded: silent | |
variables: | |
input_obj: !input obj_sensor | |
input_channel: !input channel | |
input_lovelace_view: !input lovelace_view | |
input_notify_target_app: !input notify_target_app | |
input_silence_timer: !input silence_timer | |
input_time_format: !input time_format | |
input_presence_filter: !input presence_filter | |
input_alarm_entity: !input alarm_entity | |
input_alarm_arm_states: !input alarm_arm_states | |
input_debug_event_id: !input debug_event_id | |
input_cooldown: !input cooldown | |
lovelace_view: '{{ input_lovelace_view | trim }}' | |
is_manual: '{{ ''from_state'' not in trigger }}' | |
entity_id: '{% if is_manual %}{{ input_obj[0] }}{% else %}{{ trigger.entity_id }}{% | |
endif %}' | |
entity_name: '{{ state_attr(entity_id, ''friendly_name'') }}' | |
device_id: '{{ device_id(entity_id) }}' | |
camera_entities: '[{% for eid in device_entities(device_id) %}{%if eid.startswith(''camera'') | |
and not ''package'' in eid and not is_state(eid, ''unavailable'') %}"{{ eid }}",{% | |
endif %}{% endfor %}]' | |
camera_entity_id: '{{ camera_entities | default([None]) | first }}' | |
event_id: '{% if is_manual %}{{ input_debug_event_id }}{% else %}{{ state_attr(entity_id, | |
''event_id'') }}{% endif %}' | |
video_start: '{{ states[entity_id].last_changed.isoformat() }}' | |
trigger_time: "{% if states[entity_id] == None %}\n None\n{% else %}\n {{ as_local(states[entity_id].last_changed).strftime(input_time_format) | |
}}\n{% endif %}\n" | |
notification_channel: "{% if is_manual %}\n Manual {{ input_channel }}\n{% else | |
%}\n {{ input_channel }}\n{% endif %}\n" | |
notification_title: '{{ entity_name }}' | |
notification_tag: '{{ notification_channel.lower().replace('' '', ''-'') }}' | |
notification_message: '{{ entity_name }}{% if trigger_time != None %} at {{ trigger_time | |
}}{% endif %}.' | |
notification_image: /api/unifiprotect/thumbnail/{{ config_entry_id(entity_id) }}/{{ | |
event_id }} | |
notification_url: "{% if lovelace_view == \"\" %}\n None\n{% else %}\n {{ lovelace_view | |
}}\n{% endif %}\n" | |
silence_action: silence-smart-{{ entity_id }} | |
trigger: | |
- platform: state | |
entity_id: !input obj_sensor | |
from: 'off' | |
to: 'on' | |
condition: | |
condition: and | |
conditions: | |
- condition: or | |
conditions: | |
- condition: template | |
value_template: '{{ input_alarm_entity is not defined or input_alarm_entity | |
== '''' }}' | |
- condition: and | |
conditions: | |
- condition: template | |
value_template: '{{ input_alarm_entity is defined and input_alarm_entity != | |
'''' }}' | |
- condition: template | |
value_template: '{{ input_alarm_arm_states is defined and input_alarm_arm_states | |
| length > 0 }}' | |
- condition: template | |
value_template: '{{ states(input_alarm_entity) in input_alarm_arm_states }}' | |
- condition: or | |
conditions: | |
- condition: template | |
value_template: '{{ input_presence_filter is not defined or input_presence_filter | |
== '''' }}' | |
- condition: template | |
value_template: '{{ (input_presence_filter | select(''is_state'', ''home'') | |
| list | count) == 0 }}' | |
action: | |
- service: '{{ input_notify_target_app }}' | |
data: | |
message: '{{ notification_message }}' | |
title: '{{ notification_title }}' | |
data: | |
tag: '{{ notification_tag }}' | |
channel: '{{ notification_channel }}' | |
ttl: 0 | |
priority: high | |
alert_once: "{% if tag != \"\" %}\n true\n{% else %}\n false\n{% endif %}\n" | |
time-sensitive: 1 | |
image: '{{ notification_image }}' | |
entity_id: '{{ camera_entity_id }}' | |
actions: '[{% if notification_url != None %} { "action": "URI", "title": "Open | |
Camera", "uri": "{{ notification_url }}" }, {% endif %} {% if input_silence_timer | |
> 0 %} { "action": "{{ silence_action }}", "title": "Silence", "destructive": | |
True }, {% endif %}] | |
' | |
- wait_for_trigger: | |
- platform: event | |
event_type: mobile_app_notification_action | |
event_data: | |
action: '{{ silence_action }}' | |
- platform: event | |
event_type: mobile_app_notification_cleared | |
event_data: | |
message: '{{ notification_message }}' | |
- platform: state | |
entity_id: !input obj_sensor | |
to: 'off' | |
timeout: | |
seconds: '{{ input_cooldown }}' | |
continue_on_timeout: false | |
- choose: | |
- conditions: | |
- condition: template | |
value_template: '{{ wait.trigger.platform == ''state'' }}' | |
sequence: | |
- service: '{{ input_notify_target_app }}' | |
data: | |
message: '{{ notification_message }}' | |
title: '{{ notification_title }}' | |
data: | |
tag: '{{ notification_tag }}' | |
channel: '{{ notification_channel }}' | |
ttl: 0 | |
priority: high | |
alert_once: "{% if tag != \"\" %}\n true\n{% else %}\n false\n{% endif | |
%}\n" | |
time-sensitive: 1 | |
image: '{{ notification_image }}' | |
video: /api/unifiprotect/video/{{ config_entry_id(entity_id) }}/{{ entity_id | |
}}/{{ video_start }}/{{ states[entity_id].last_changed.isoformat() }} | |
actions: '[{% if notification_url != None %} { "action": "URI", "title": | |
"Open Camera", "uri": "{{ notification_url }}" }, {% endif %} {% if input_silence_timer | |
> 0 %} { "action": "{{ silence_action }}", "title": "Silence", "destructive": | |
True }, {% endif %}] | |
' | |
- wait_for_trigger: | |
- platform: event | |
event_type: mobile_app_notification_action | |
event_data: | |
action: '{{ silence_action }}' | |
timeout: | |
seconds: '{{ max([input_cooldown - (states[entity_id].last_changed - as_datetime(video_start)).total_seconds(), | |
5]) }}' | |
continue_on_timeout: false | |
- conditions: | |
- condition: template | |
value_template: '{{ wait.trigger.platform == ''event'' and wait.trigger.event.event_type | |
== ''mobile_app_notification_action'' }}' | |
sequence: | |
- delay: | |
minutes: '{{ input_silence_timer }}' | |
- conditions: | |
- condition: template | |
value_template: '{{ wait.trigger.platform == ''event'' and wait.trigger.event.event_type | |
== ''mobile_app_notification_cleared'' }}' | |
sequence: | |
- delay: | |
seconds: '{{ max([input_cooldown - (wait.trigger.event.time_fired - as_datetime(video_start)).total_seconds(), | |
5]) }}' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment