Yet Another Notification Template: a Newbie's Journey

If you feel Home Assistant is overwhelming, you are not alone. I was and I still am. That does not mean Home Assistant is necessarily difficult it just uses a lot of techniques which I have not come across before: YAML, Jinja2, etc.

I will share with you what I have learned. I cannot spend hours at a time to write a long post so I will be adding to this post as I go along.

I do want to thank the community and everyone who created blogs, videos and other resources on Home Assistant. Google continues to be my best friend as well.

I got my inspiration from the Send came snaphot notification blueprint :camera_flash: Send camera snapshot notification on motion - Blueprints Exchange - Home Assistant Community (home-assistant.io) by @vorion. However, I wanted to achieve some additional functionality.

  • send persistent notification and e-mail notification in addition to the mobile notification
  • make the notifications scripts so that they can be used in other automations
  • make the notifications optional
  • control the notifications using a alarm control panel entity
  • make mobile notification critical depending the state of the alarm control panel

The solution presented here is far from perfect, remember I am a newbie, and any suggestions to further improve it will very much appreciated.

Here are some of the things I struggled with:

  • persistent notifications link to an image rather than embedding the image within the notification
  • device_id: does not accept templates; unable to pass field or variable
  • how to send an e-mail notification to multiple recipients

Scripts
Scripts are sequence of actions which can be executed by Home Assistant using a service call. Note that useful information on actions can be found in the documentation on automation and blueprints as well.

While Home Assistent seems to support script blueprints, I have no idea how to create and use them (I noticed they are available in 2021.11.1 and need to look into them more).

I created three scripts for sending a persistent notification, e-mail notification, and mobile notification.

Persistent Notification Script
The script gets three fields when called: snapshot_title, snapshot_message, and snapshot_file. The service persistent_notification create expects the file to be located in “/local”, so replace “/config/www” by “/local” when using “/www/local”.

'{{ snapshot_file | replace("/config/www","/local") }}'

This is the full script:

persistent_notification_snapshot:
  alias: Persistent Notification Snapshot
  description: This script sends a persistent notification a snapshot
  icon: mdi:email-outline
  mode: single
  variables:
    local_file: '{{ snapshot_file | replace("/config/www","/local") }}'
  fields:
    snapshot_title:
      name: Notification title
      description: Title of the notification
      selector:
        text:
    snapshot_message:
      name: Notification body
      description: Body of the notification
      selector:
        text:
    snapshot_file:
      name: Filename
      description: Filename of snapshot
      selector:
        text:
  sequence:
  - service: persistent_notification.create
    data:
      message: '{{ snapshot_message }}<br /><br />![image]({{- local_file -}})'
      title: '{{ snapshot_title }}'

The script can be called with the follow YAML code:

  - service: script.persistent_notification_snapshot
    data:
      snapshot_title: 
      snapshot_message: 
      snapshot_file: 

It is also possible to add the script to the automation through the GUI by using a service call to script.persistent_notification_snapshot.


Important: one thing to take notice of is how persistent notifications handles images. It does not imbed the image; instead, it links to the image. This means that if you overwrite the image and send a new notification, it will include the same link. To make things more confusing, the browser will cache the image and as a result it seems that each notification displays the first image saved. If you clear the cache, all the images will display the last image saved. If you delete the image, the notification is unable to display an image.

Mobile Phone Notification
First of all, apologies to all Android users, but I wrote this script with iOS in mind. It will be very easy to adapt for Android; please have a look at the original blueprint by vorion. To make up for my lack in effort, here is a template which could replace the iOS boolean input in vorion’s blueprint. Read more on using devices in templates in the Home Assistant documentation.

{{ device_attr("device_id", "manufacturer") == "Apple" }}

There are no entities associated with a mobile phone which can be used to send a notification to a mobile phone so only a device selector can be used to selected the mobile device. One of the things which caused me a lot of pain is that “device_id:” in an action can not use a template and as a result I was not able to pass the device ID to the script. As a result, the only way I could send a notification to the mobile is to use a service call which requires me to use the name of the mobile phone. I resolved it with this template. You may have to confirm that your template gives you the correct service name.

service: 'notify.mobile_app_{{ device_attr(snapshot_target, "name") | replace("’","") | replace(" ","_") | lower}}'

This is the complete script:

ios_notification_snapshot:
  alias: iOS Notification Snapshot
  description: This script sends a persistent notification a snapshot
  icon: mdi:email-outline
  mode: single
  fields:
    snapshot_title:
      name: Notification title
      description: Title of the notification
      selector:
        text:
    snapshot_message:
      name: Notification body
      description: Body of the notification
      selector:
        text:
    snapshot_file:
      name: Filename
      description: Filename of snapshot
      selector:
        text:
    snapshot_target:
      name: Mobile
      description: Mobile phone device
      selector:
        device:
          manufacturer: "Apple"
    snapshot_critical:
      name: Critical Notification
      description: The notification is critical (1) or non-critical (0)
      selector:
        boolean:
  sequence:
  - service: 'notify.mobile_app_{{ device_attr(snapshot_target, "name") | replace("’","") | replace(" ","_") | lower}}'
    data:
      message: "{{ snapshot_message }}"
      title: '{{ snapshot_title }}'
      data: 
        image: '{{- snapshot_file | replace(''/config/www'',''/local'') -}}'
        push:
          sound:
            name: "default"
            critical: >
              {% if snapshot_critical %}
                1
              {% else %}
                0
              {% endif %}
            volume: 0.1

The script can be called with the follow YAML code:

  - service: script.ios_notification_snapshot
    data:
      snapshot_title: 
      snapshot_message: 
      snapshot_file: 
      snapshot_target: 

It is also possible to add the script to the automation through the GUI by using a service call to script.ios_notification_snapshot.

Email Notification
The last of the three scripts is the e-mail notification. This script does not contain anything exiting other than that it includes the html section which embeds the snapshot image. The html code uses the basename of the fully qualified filename passed to the script. The following template removes the folder part:

{{- snapshot_file[snapshot_file.rfind("/")+1:] -}}

To be able to send the e-mail notfication to multiple recipient, I changed the selector from a text selector to an object selector. Note that I called my SMTP integration “email” which is called using “service: notify.email”.

email_snapshot:
  alias: Email Snapshot
  description: This script emails a snapshot
  icon: mdi:email-outline
  mode: single
  variables:
    filename: '{{- snapshot_file[snapshot_file.rfind("/")+1:] -}}'
  fields:
    snapshot_title:
      name: Email title
      description: Title of the e-mail message
      selector:
        text:
    snapshot_message:
      name: Email body
      description: Body of the e-mail message
      selector:
        text:
    snapshot_target:
      name: Email address
      description: E-mail address of the recipient of the snapshot
      selector:
        object:
    snapshot_file:
      name: Filename
      description: Filename of snapshot
      selector:
        text:
  sequence:
  - service: notify.email
    data:
      message: '{{ snapshot_message }}'
      title: '{{ snapshot_title }}'
      target: '{{ snapshot_target }}'
      data:
        images:
        - '{{- snapshot_file -}}'
        html: <html> <body><p><i>{{-snapshot_message-}}</i></p><br><img src="cid:{{filename}}"> </body> </html>

The script can be called with the follow YAML code:

  - service: script.email_snapshot
    data:
      snapshot_target: 
      snapshot_title: 
      snapshot_message: 
      snapshot_file: 

It is also possible to add the script to the automation through the GUI by using a service call to script.email_snapshot.


Snapshot Alarm Control Panel
Within my automation (blueprint) I want to control when to enable sending snapshots using the notifications. By creating a manual alarm control panel, I will use the arm_home and arm_away to enable sending the snapshots and use arm_away to send a critical notification to iOS.

# Configure a manual alarm control panel
alarm_control_panel:
    - platform: manual
      name: Snapshot
snapshot_critical: '{{ states("alarm_control_panel.snapshot") == "armed_away" }}'

Final Blueprint
The blueprint assumes that you have added the above scripts to scripts.yaml.

I wanted to be able to enable or disable each individual notification. The blueprint has a boolean input to enable or disable the notification and under actions I use “choose:” with “conditions:” to execute the action depending on the value of the boolean input.

  input:
    notify_persistent:
      name: Persistent Notification
      description: Send persistent notification when motion is detected
      selector:
        boolean:

variables:
    notify_persistent: !input 'notify_persistent'

action:
  - choose:
      - alias: "If persistent notification is enabled send persistent notification"
        conditions: '{{ notify_persistent }}'
        sequence:
          service: script.persistent_notification_snapshot
          data:
            snapshot_title: '{{ title }}'
            snapshot_message: '{{ message }}'
            snapshot_file: '{{ folder }}{{ filename }}'

The complete blueprint looks like this:

blueprint:
  name: Send Snapshot after Motion
  description: Send a camera snapshot using multiple notifications after motion has
    been detected
  domain: automation
  input:
    motion_sensor:
      name: Motion Sensor
      description: This sensor will trigger a snapsot to be taken and send using the notifications
      selector:
        entity:
          domain: binary_sensor
          device_class: motion
    motion_camera:
      name: Camera
      description: The snapshot will be taken using this camera
      selector:
        entity:
          domain: camera
    title:
      name: Notification Title
      description: The title of the notification
      selector:
        text:
    message:
      name: Notification Message
      description: Message body of notification
      selector:
        text:
    notify_persistent:
      name: Persistent Notification
      description: Send persistent notification when motion is detected
      selector:
        boolean:
    notify_email:
      name: Email Notification
      description: Send e-mail notification when motion is detected
      selector:
        boolean:
    email:
      name: E-mail Address
      description: E-mail address to send notification
      selector:
        object:
    notify_mobile:
      name: Mobile Notification
      description: Send mobile notification when motion is detected
      selector:
        boolean:
    mobile:
      name: Mobile Device
      description: Mobile device to send notification
      selector:
        device:
          manufacturer: 'Apple'

variables:
    motion_camera: !input 'motion_camera'
    filename: snapshot_{{ states[motion_camera].object_id }}-{{ now().strftime("%Y%m%d%H%M%S") }}.jpg
    folder: /config/www/tmp/
    title: !input 'title'
    message: !input 'message'
    notify_persistent: !input 'notify_persistent'
    notify_email: !input 'notify_email'
    notify_mobile: !input 'notify_mobile'

trigger:
  platform: state
  entity_id: !input 'motion_sensor'
  from: 'off'
  to: 'on'

condition:
  - condition: state
    entity_id: alarm_control_panel.snapshot
    state: 
       - armed_home
       - armed_away
action:
  - service: camera.snapshot
    target:
      entity_id: !input 'motion_camera'
    data:
      filename: '{{ folder }}{{ filename }}'
  - choose:
      - alias: "If e-mail notification is enabled send e-mail notification"
        conditions: '{{ notify_email }}'
        sequence:
          service: script.email_snapshot
          data:
            snapshot_target: !input email
            snapshot_title: '{{ title }}'
            snapshot_message: '{{ message }}'
            snapshot_file: '{{ folder }}{{ filename }}'
  - choose:
      - alias: "If persistent notification is enabled send persistent notification"
        conditions: '{{ notify_persistent }}'
        sequence:
          service: script.persistent_notification_snapshot
          data:
            snapshot_title: '{{ title }}'
            snapshot_message: '{{ message }}'
            snapshot_file: '{{ folder }}{{ filename }}'
  - choose:
      - alias: "If mobile notification is enabled send mobile notification"
        conditions: '{{ notify_mobile }}'
        sequence:
          service: script.ios_notification_snapshot
          data:
            snapshot_title: '{{ title }}'
            snapshot_message: '{{ message }}'
            snapshot_file: '{{ folder }}{{ filename }}'
            snapshot_target: !input mobile
            snapshot_critical: '{{ states("alarm_control_panel.snapshot") == "armed_away" }}'

2 Likes