Let the dog out! Motion Activated Notifications

April 23rd, 2022

Like a lot of families during lockdown, we got a puppy. Meet Biscuit the cockapoo. It turns out that dogs need to go outside regularly or you end up with puddles everywhere. I’m not always paying attention to what she’s doing and I was starting to get very frustrated with all of the cleaning.

My first attempt at trying to solve this problem was to train her to press a button whenever she went near the back door. I stuck an Ikea Shortcut button on the floor and encouraged her to press this whenever she wanted to go out. I’m still working on that training so in the meantime I needed a more passive automation. I placed an Ikea motion sensor under the lip of a coffee table, angled so as it points straight towards the door. Whenever something goes near the back door and triggers the motion sensor, an automation kicks off with an alert on all of the Echo Dots, a Sonos speaker, and a notification on my phone.

This automation evolved rapidly as I discovered its faults. I needed to reduce the false alerts rapidly or this was going to become more annoying than cleaning up the messes! The first adjustment I made was to link it to the open/close state of the back door. I’d got a SmartThings Multipurpose sensor already attached to that door, so I added a condition to prevent the automation from running if the door was already open. But what if someone was genuinely trying to open the back door and go outside? I didn’t want the automation to alert me then either. After a bit of trial and error, I figured out that usually it took about 5 seconds for a human to unlock and open the back door – so now there’s a delay on any actions for 5 seconds. After 5 seconds, if the back door is still closed, then we carry on with our action list. 

Then I got complaints from the children that the alerts from the Echo Dots and Sonos were too noisy in the evenings. But, I still needed to get an alert somehow. I solved this by adding a condition during the actions so as the noisy parts of the automation only run between 8am and 9:30pm.

Great… have I cracked it? Not quite. I work from home, but my wife doesn’t. She was getting a bit annoyed with the notifications coming through to her phone while at work asking her to let the dog out. That last bit of the puzzle was fixed with a condition before the alert to her phone is sent, making sure that her phone is at home first. 

Here’s the end result (obviously, if you use this you’ll need to replace my device/entity IDs with yours):

alias: 'Notify: Let Biscuit Out (Motion)'
description: ''
trigger:
  - type: motion
    platform: device
    device_id: 40274cfda00ca049102ed372fb1d2da9
    entity_id: binary_sensor.conservatory_motion_occupancy
    domain: binary_sensor
  - platform: state
    entity_id: binary_sensor.conservatory_door_contact
    id: door_change
condition:
  - type: is_not_open
    condition: device
    device_id: 768ea89927e512d0aaddb35eaf490d70
    entity_id: binary_sensor.conservatory_door_contact
    domain: binary_sensor
  - condition: state
    entity_id: input_boolean.manual_override
    state: 'off'
action:
  - choose:
      - conditions:
          - condition: trigger
            id: door_change
        sequence:
          - delay:
              hours: 0
              minutes: 0
              seconds: 1
              milliseconds: 0
    default:
      - delay:
          hours: 0
          minutes: 0
          seconds: 5
          milliseconds: 0
      - choose:
          - conditions:
              - type: is_not_open
                condition: device
                device_id: 768ea89927e512d0aaddb35eaf490d70
                entity_id: binary_sensor.conservatory_door_contact
                domain: binary_sensor
              - condition: state
                entity_id: input_select.home_mode
                state: Home (Day)
            sequence:
              - service: notify.oliver
                data:
                  message: Let Biscuit Out! (Motion)
              - choose:
                  - conditions:
                      - condition: state
                        entity_id: person.vicky
                        state: home
                    sequence:
                      - service: notify.vicky
                        data:
                          message: Let Biscuit Out!
                default: []
              - choose:
                  - conditions:
                      - condition: time
                        after: '08:00'
                        before: '21:30'
                    sequence:
                      - service: notify.alexa_media
                        data:
                          message: >-
                            <audio
                            src="soundbank://soundlibrary/animals/amzn_sfx_dog_med_bark_2x_02"/>
                            Let Biscuit Out
                          target: media_player.echo_dot_lounge
                          data:
                            type: tts
                      - service: notify.alexa_media
                        data:
                          message: >-
                            <audio
                            src="soundbank://soundlibrary/animals/amzn_sfx_dog_med_bark_2x_02"/>
                            Let Biscuit Out
                          target: media_player.echo_dot_bed1
                          data:
                            type: tts
                      - service: notify.alexa_media
                        data:
                          message: >-
                            <audio
                            src="soundbank://soundlibrary/animals/amzn_sfx_dog_med_bark_2x_02"/>
                            Let Biscuit Out
                          target: media_player.echo_dot_bed2
                          data:
                            type: tts
                      - service: script.play_sound_on_sonos
                        data:
                          sonos_entity: media_player.kitchen
                          soundfile_url: http://192.168.1.12:8123/local/dog_med_bark_2x2.mp3
                          volume: 0.3
                          delay: '00:00:01'
                      - service: script.play_tts_on_sonos
                        data:
                          sonos_entity: media_player.kitchen
                          tts_message: Let Biscuit Out
                          volume: 0.3
                          delay: '00:00:05'
                default: []
        default: []
mode: restart

Note that this automation also triggers when the door opens/closes. The automation’s mode is set to ‘restart’, which means that if it’s triggered whilst it’s already running then it’ll cancel that run and start again. So, if the door is opened at all then the automation will fire again and all it will do is wait 1 second to do nothing. It helps prevent some false positives. It’s not perfect and we get false positives still, especially if a cat decides to look out of the window, or if someone is taking a bit too long to open that door. But, overall, it has massively reduced the amount of cleaning I’ve needed to do.

Now… you may have looked at my automation and thought “hey, how has he managed to get an announcement out of his Echo?”. Well, there are two ways. The first one is the easiest. You pay the company behind Home Assistant, called Nabu Casa, just over $6 a month for Home Assistant Cloud. Amongst many other benefits, they’ll also link your Home Assistant installation to Amazon’s cloud services allowing you to very easily use your Echos for notifications. The second way is free but slightly more complicated and is obviously the method I’ve chosen, because, well, fun! Using HACS, which is like a special custom third-party App Store for Home Assistant, you need to install the Alexa Media Player integration. 

Once installed, you’ll need to add the integration to Home Assistant just like any other integration. This is the complicated part though – you’ll need to link it to your Amazon account, and to do that you’ll need to enable two-factor authentication. One of the biggest issues I have with this integration is that it randomly decides you need to re-authenticate, and quite often that re-authentication takes several attempts.

I’ve also managed to output notifications on a Sonos speaker. This is a lot simpler! Firstly, you need to add your Sonos speakers to Home Assistant as an integration. Mine were auto detected so basically configured themselves. Next you need to edit your configuration.yaml file. Home Assistant has a built-in text-to-speech renderer called picotts which converts any text you give it into a sound file which a speaker device can then play. You could also use Google’s text-to-speech service, which does give a more natural sounding voice, but relies on the cloud. 

You simply add the tts section to your configuration as shown in the snippet below, and an item for the picotts platform. Restart Home Assistant and you’re ready to go.

# Text to speech
tts:
  - platform: picotts
    language: "en-GB"

To make things easier, I created a couple of reusable scripts that allow me to output text or sound files on my Sonos speakers. You supply them with text, or a sound file URL, a volume value, and the speaker you want it to be played on, and the script takes care of snapshotting the speaker’s current status, playing the requested sound, and then restoring the speaker’s previous state. You can see examples of how to call both of these scripts in the previous automation snippet.

alias: Play Sound on Sonos
sequence:
  - service: sonos.snapshot
    data_template:
      entity_id: '{{ sonos_entity }}'
  - service: sonos.unjoin
    data_template:
      entity_id: '{{ sonos_entity }}'
  - service: media_player.volume_set
    data_template:
      entity_id: '{{ sonos_entity }}'
      volume_level: '{{ volume }}'
  - service: media_player.play_media
    data_template:
      entity_id: '{{ sonos_entity }}'
      media_content_id: '{{ soundfile_url }}'
      media_content_type: music
  - delay: '{{ delay }}'
  - service: sonos.restore
    data_template:
      entity_id: '{{ sonos_entity }}'
mode: single
alias: Play TTS on Sonos
sequence:
  - service: sonos.snapshot
    data_template:
      entity_id: '{{ sonos_entity }}'
  - service: sonos.unjoin
    data_template:
      entity_id: '{{ sonos_entity }}'
  - service: media_player.volume_set
    data_template:
      entity_id: '{{ sonos_entity }}'
      volume_level: '{{ volume }}'
  - service: tts.picotts_say
    data:
      entity_id: '{{ sonos_entity }}'
      message: '{{ tts_message }}'
  - delay: '{{ delay }}'
  - service: sonos.restore
    data_template:
      entity_id: '{{ sonos_entity }}'
mode: single

Anyway, I hope you find this useful, let me know if it reduces the amount of cleaning you need to do, or perhaps you’ve got a better way of doing this that you can share.

  • As an Amazon Associate I earn from qualifying purchases.