commit f4191f646f047704179a2991d58dc0b89f6a0090 Author: Otto Date: Wed Jul 1 18:59:53 2026 +0200 Publish doorbell loud restore blueprint v3.0 diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..040ec88 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Changelog + +## 3.0.0 + +- Publish-ready blueprint by `lightningpicture`. +- Removed hardcoded device entities. +- Added inputs for Android ringer mode and volume sensors. +- Temporarily sets Android device to loud mode before the doorbell notification. +- Sends an alarm-stream snapshot notification. +- Plays a spoken Android TTS doorbell announcement. +- Restores previous ringer mode and volume levels after notification. + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..57cf236 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 lightningpicture + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..acd9ff1 --- /dev/null +++ b/README.md @@ -0,0 +1,55 @@ +# Doorbell Loud Restore Notification Blueprint + +Home Assistant blueprint for Android doorbell notifications. + +When the doorbell trigger fires, the blueprint: + +- reads the Android phone's current ringer mode and volume levels +- temporarily switches the phone to loud mode +- raises alarm, notification, and ringer volume +- sends an alarm-stream snapshot notification +- plays a short spoken doorbell announcement +- restores the previous ringer mode and volume levels +- keeps two actionable notification buttons available + +## Blueprint + +```text +blueprints/automation/lightningpicture/doorbell-cam-loud-restore-notification.yaml +``` + +## Requirements + +- Home Assistant Companion App for Android +- the target Android device's mobile_app notify service +- enabled Companion App sensors: + - Ringer mode + - Volume level alarm + - Volume level notification + - Volume level ringer +- a camera entity for the doorbell snapshot +- a binary sensor, switch, or other entity that turns from `off` to `on` on doorbell press + +## Important Android Permissions + +For reliable loud notifications and restore behavior, allow the Home Assistant app to: + +- change ringer mode / Do Not Disturb settings +- use notification channels that bypass Do Not Disturb +- run in the background without battery optimization blocking it + +## Default Announcement + +```text +Es hat gerade an der Haustür geklingelt. +``` + +The announcement text is configurable in the blueprint input. + +## Tested Setup + +- Home Assistant 2026.6.4 +- Android / Samsung mobile_app target +- ringer modes tested: `vibrate` and `silent` +- restore verified for ringer mode and alarm/notification/ringer volume levels + diff --git a/blueprints/automation/lightningpicture/doorbell-cam-loud-restore-notification.yaml b/blueprints/automation/lightningpicture/doorbell-cam-loud-restore-notification.yaml new file mode 100644 index 0000000..9fd9946 --- /dev/null +++ b/blueprints/automation/lightningpicture/doorbell-cam-loud-restore-notification.yaml @@ -0,0 +1,279 @@ +blueprint: + name: Doorbell loud restore notification v3.0 + description: "Version 3.0 by lightningpicture. Publish-ready Android doorbell blueprint: reads the phone's current ringer mode and volume levels, temporarily switches the phone to loud mode, sends an alarm-stream snapshot notification, plays a short spoken doorbell announcement, then restores the previous ringer mode and volume levels. Supports two actionable notification buttons." + domain: automation + input: + notification_title: + name: Notification title (Optional) + description: 'Default: "Someone at the doorbell ring!"' + default: Someone at the doorbell ring! + announcement_text: + name: Spoken doorbell announcement + description: Android TTS announcement played after the doorbell notification. + default: Es hat gerade an der Haustür geklingelt. + selector: + text: + multiline: false + multiple: false + doorbell_button: + name: Trigger entity + description: Changing state of this entity from to will start the doorbell notification automation. + selector: + entity: {} + doorbell_cam: + name: Doorbell Cam + description: The Camera from which to take a photo for the notification. + selector: + entity: + domain: + - camera + multiple: false + notify_dev: + name: Device to notify + description: Device or group of devices for notification through the mobile_app notification service. For example , + selector: + text: + type: search + multiline: false + multiple: false + ringer_mode_sensor: + name: Android ringer mode sensor + description: Ringer mode sensor of the target Android device. Usually named Ringer mode. + selector: + entity: + domain: + - sensor + multiple: false + alarm_volume_sensor: + name: Android alarm volume sensor + description: Alarm volume level sensor of the target Android device. Used to restore the previous alarm volume. + selector: + entity: + domain: + - sensor + multiple: false + notification_volume_sensor: + name: Android notification volume sensor + description: Notification volume level sensor of the target Android device. Used to restore the previous notification volume. + selector: + entity: + domain: + - sensor + multiple: false + ringer_volume_sensor: + name: Android ringer volume sensor + description: Ringer volume level sensor of the target Android device. Used to restore the previous ringer volume. + selector: + entity: + domain: + - sensor + multiple: false + ios_sound: + name: Notification sound + description: Notification sound for iOS (Optional). Default + default: US-EN-Morgan-Freeman-Someone-Is-Arriving.wav + selector: + select: + mode: dropdown + custom_value: true + options: + - US-EN-Morgan-Freeman-Someone-Is-Arriving.wav + - US-EN-Morgan-Freeman-Wife-Is-Arriving.wav + - US-EN-Morgan-Freeman-Boss-Is-Arriving.wav + - US-EN-Morgan-Freeman-Girlfriend-Is-Arriving.wav + - US-EN-Morgan-Freeman-Welcome-Home.wav + - US-EN-Morgan-Freeman-Son-Is-Arriving.wav + - US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav + - US-EN-Morgan-Freeman-Motion-Detected.wav + - US-EN-Morgan-Freeman-Motion-In-Wine-Cellar.wav + - US-EN-Morgan-Freeman-Motion-In-Garage.wav + - US-EN-Daisy-Back-Door-Motion.wav + - US-EN-Daisy-Front-Door-Motion.wav + - US-EN-Alexa-Motion-In-Garage.wav + - US-EN-Alexa-Motion-In-Back-Yard.wav + - US-EN-Alexa-Motion-Detected-Generic.wav + sort: false + multiple: false + uri_: + name: Dashboard tab + description: Dashboard tab to open by clicking the button. Default + default: /lovelace/default_view + action1_title: + name: Action 1 title (Optional) + description: Action to perform on clicking the action 1 button + default: action1 + action1: + name: Action 1 + description: Action to run when action button 1 is pressed + default: [] + selector: + action: {} + action2_title: + name: Action 2 title (Optional) + description: Action to perform on clicking the action 2 button + default: action2 + action2: + name: Action 2 + description: Action to run when action button 2 is pressed + default: [] + selector: + action: {} + delay: + name: Delay (Optional) + description: The time during which the actions in the notification are active + default: '30' + selector: + number: + min: 0.0 + max: 120.0 + unit_of_measurement: seconds + mode: slider + step: 1.0 +variables: + button: !input doorbell_button + ringer_mode_sensor: !input ringer_mode_sensor + alarm_volume_sensor: !input alarm_volume_sensor + notification_volume_sensor: !input notification_volume_sensor + ringer_volume_sensor: !input ringer_volume_sensor + image_file: /local/doorbell/{{ expand(button)[0].last_changed | as_timestamp | + timestamp_custom("%Y-%m-%d_%H-%M-%S") }}.jpg +trigger: + - entity_id: !input doorbell_button + platform: state + from: 'off' + to: 'on' +condition: [] +action: + - alias: Set up variables for the actions + variables: + action_1: '{{ ''ACTION_1'' ~ context.id }}' + action_2: '{{ ''ACTION_2'' ~ context.id }}' + ringer_mode_before: "{{ states(ringer_mode_sensor) }}" + alarm_volume_before: "{{ states(alarm_volume_sensor) }}" + notification_volume_before: "{{ states(notification_volume_sensor) }}" + ringer_volume_before: "{{ states(ringer_volume_sensor) }}" + - data_template: + entity_id: !input doorbell_cam + filename: /config/www/doorbell/{{ expand(button)[0].last_changed | as_timestamp | + timestamp_custom("%Y-%m-%d_%H-%M-%S") }}.jpg + service: camera.snapshot + - action: !input notify_dev + metadata: {} + data: + message: command_ringer_mode + data: + command: normal + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: alarm_stream + command: 999 + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: notification_stream + command: 999 + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: ring_stream + command: 999 + - delay: "00:00:01" + - action: !input notify_dev + metadata: {} + data: + title: !input notification_title + message: "{{ as_timestamp(now()) | timestamp_custom('%d.%m.%y - %H:%M', true) }}" + data: + ttl: 0 + priority: high + channel: alarm_stream + push: + interruption-level: critical + sound: !input ios_sound + image: '{{ image_file }}' + actions: + - action: '{{ action_1 }}' + title: !input action1_title + destructive: true + - action: '{{ action_2 }}' + title: !input action2_title + - action: !input notify_dev + metadata: {} + data: + message: TTS + data: + tts_text: !input announcement_text + media_stream: alarm_stream_max + - delay: "00:00:05" + - if: + - condition: template + value_template: "{{ is_number(alarm_volume_before) }}" + then: + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: alarm_stream + command: "{{ alarm_volume_before | int }}" + - if: + - condition: template + value_template: "{{ is_number(notification_volume_before) }}" + then: + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: notification_stream + command: "{{ notification_volume_before | int }}" + - if: + - condition: template + value_template: "{{ is_number(ringer_volume_before) }}" + then: + - action: !input notify_dev + metadata: {} + data: + message: command_volume_level + data: + media_stream: ring_stream + command: "{{ ringer_volume_before | int }}" + - if: + - condition: template + value_template: "{{ ringer_mode_before in ['normal', 'vibrate', 'silent'] }}" + then: + - action: !input notify_dev + metadata: {} + data: + message: command_ringer_mode + data: + command: "{{ ringer_mode_before }}" + - alias: Wait for a response + wait_for_trigger: + - platform: event + event_type: mobile_app_notification_action + event_data: + action: '{{ action_1 }}' + - platform: event + event_type: mobile_app_notification_action + event_data: + action: '{{ action_2 }}' + timeout: !input delay + continue_on_timeout: true + - alias: Perform the action + choose: + - conditions: + - condition: template + value_template: '{{ wait.trigger.event.data.action == action_1 }}' + sequence: !input action1 + - conditions: + - condition: template + value_template: '{{ wait.trigger.event.data.action == action_2 }}' + sequence: !input action2