Home Assistant and Lock Notifications

I’ve recently been porting things from Samsung Smartthings to Home Assistant. Smartthings has a significantly lower learning curve, but suffered from a reliance on the cloud. While you have a local hub, any “custom” device handlers actually ran on the cloud on Samsung servers somewhere. Which means advanced functionality was often very, very slow.

As an example, I have a Schlage Z-Wave door lock, which worked out of the box with SmartThings, albeit with limited functionality. To resolve that issue, I used RBoyApps “Universal Enhanced Z-Wave Lock” Handler. It was a much, much improved interface for the lock, allowing configuring of advanced settings. Unfortunately, using that handler meant any device interaction ran a round trip through the Samsung cloud. Trying to unlock my door from my phone often took 10-15 seconds, which doesn’t sound like much, but is slower than just typing in my code manually.

I finally decided to make the switch to Home Assistant – a self-hosted, purely local platform.

HA is much, much more hands-on. While you can do plenty of things in the UI, a lot of configuration requires manual adjustments to yaml config files. I don’t mind that. The wiki is very informative for most functionality one requires.

However, some of the more advanced functionality is kind of written between the lines in the wiki. There’s references to templates, triggers (the template object specifically), and functions, but it doesn’t seem to have the same documentation coverage.

Mostly through trial and error, I’ve learned some functionality.

Templates

You need to use >- to switch to templates instead of normal values. There is also >, and I’m not sure if the difference (if any)

# Standard value
key: value

# Templated value
key: >-
  {% if trigger %}
    Foo
  {% else %}
    Bar
  {% endif %}  

Functions have values piped into them like a unix command-line:

{% value | function(args) }%

Trigger information is available in templates

There is some very, very basic coverage of this on the wiki, but it appears to be wrong/incomplete.

You can use a trigger object to see what triggered this function, as well as compare old/new states.

However, the trigger object properties are different depending on the trigger. This makes sense, but is problematic. The trigger object (and it’s properties) differ if you’re triggering on the lock state, vs the lock entity.

  {{ trigger.to_state.name }} is {{ trigger.to_state.state }}

The Door Lock Notification automation

Below is a single automation that will notify all devices when the door is locked or unlocked. It can have multiple locks added as automation triggers, and it will use the trigger template object to output the correct notification data. It does handle a scenario of missing trigger data as well (not well, but well enough).

It also does a very basic status cleanup:

  • Replacing the “by RF” note to specifically mention Home Assistant. This is any changes made via the web UI or apps.
  • Replacing " by user 0" with nothing, because there is no user 0. This is typically locking the door via the keypad outside. We don’t need to identify this “user”.
  • Replacing “user 1” and “user 2” with our names. I’d prefer this to be a proper lookup via !secret data. However, the exact usage of those is unclear as well, so that is an exercise for another day.

Note that Home Assistant will unfortunately mangle this function into an unreadable mess if this is in your automations.yaml. Fixing that is an exercise to the reader…

automation:
  - id: '1607152528'
    alias: Door Lock Notifications
    description: ''
    mode: parallel
    max: 10
    trigger:
    - platform: state
      entity_id: lock.front_door
    action:
    - service: notify.notify
      data:
        title: >-
          {% if trigger %}
            {{ trigger.to_state.name }} is {{ trigger.to_state.state }}
          {% else %}
            Unkown Door - Status Changed
          {% endif %}          
        message: >-
          {% if trigger %}
            {% set lock_status = trigger.to_state.attributes.lock_status %}
            {% set lock_status = lock_status|replace("by RF", "by Home Assistant") %}
            {% set lock_status = lock_status|replace(" by user 0", "") %}
            {% set lock_status = lock_status|replace("user 1", "Chris") %}
            {% set lock_status = lock_status|replace("user 2", "Alexis") %}
            {{ lock_status }}
          {% else %}
            Missing trigger information
          {% endif %}