Thomas' writings, builds, toys

2020-12-05

Home assistant based hands-free alarm

concept

image: cover from https://mzl.la/ihr-nov-2019

I wanted a basic home security system (burglar alarm) to offer me some piece of mind at night.

My Home Assistant instance has enough sensors to figure out what we are up to, so it was possible to create an alarm system that works autonomously. The system automatically arms and disarms while we sleep during the night and when we leave and return to the house during the day.

By applying many features and integrations that Home Assistant provides, we can implement an effective security system.

Tool Job
Zigbee motion and door sensors alarm sensors
actual sensor state and last changed attribute arm home trigger conditions
Mobile phone location tracking arm away trigger
Manual alarm component alarm state machine, UI
wall mounted touchscreen physical arm/disarm UI control
raspberry pi's hooked up to amplifiers sirens
home assistant android app alarm status notifications
'Connected' color light alarm status display

The manual alarm component

The home assistant manual alarm component implements a state machine with the typical states of an alarm system (disarmed, arming, armed_home, armed_away,triggered). The alarm can be manipulated with home assistant service calls, and its state changes can be used to trigger automations to respond appropriately.

We can arm/disarm the alarm from automations by using the alarm PIN code from the secrets.yaml file.

alarm_control_panel:
  - platform: manual
    name: Home Alarm
    code: !secret house_alarm_code
    #delay before becomming armed
    arming_time: 30
    #delay before sounding siren
    delay_time: 20
    #how long the siren sounds
    trigger_time: 20
    disarmed:
      trigger_time: 0
    armed_home:
      arming_time: 0

The sensors

For convenience and to make the automations easier to read, I created entity groups.

  • group.presence_all
  • group.presence_upstairs
  • group.presence_downstairs
  • group.armed_away_immediate_triggers
  • group.armed_away_delay_triggers
  • group.armed_home_delay_triggers
  • group.tracker_residents

Trigger issues (eg when doors are left open)

When a sensor is stuck in the 'on' state, the group is stuck in 'on' as well.

This means that leaving a door open will prevent the alarm from arming.

The most non-invasive way to handle this is to put status lights next to the doors and bed so you can easily see that everything is ready to leave or sleep.

Group configuration example

presence_all:
  name: presence_all
  entities:
    - binary_sensor.livingroom_occupancy
    - binary_sensor.frontdoor_contact
    - binary_sensor.backdoor_contact
    - binary_sensor.upstairs_staircase_occupancy
    - binary_sensor.gardenshed_contact
    - binary_sensor.garage_occupancy
presence_downstairs:
  name: presence_downstairs
  entities:
    - binary_sensor.garage_occupancy
    - binary_sensor.livingroom_occupancy
    - binary_sensor.frontdoor_contact
    - binary_sensor.backdoor_contact
    - binary_sensor.gardenshed_contact
armed_away_immediate_triggers:
  name: armed away panic triggers
  entities:
    - binary_sensor.garage_occupancy
    - binary_sensor.livingroom_occupancy
    - binary_sensor.upstairs_staircase_occupancy
    - binary_sensor.backdoor_contact
    - binary_sensor.gardenshed_contact
armed_away_delay_triggers:
  name: armed away normal triggers
  entities:
    - binary_sensor.frontdoor_contact
armed_home_delay_triggers:
  name: armed away normal triggers
  entities:
    - binary_sensor.garage_occupancy
    - binary_sensor.livingroom_occupancy
    - binary_sensor.frontdoor_contact
    - binary_sensor.backdoor_contact
    - binary_sensor.gardenshed_contact
presence_upstairs:
  name: presence_upstairs
  entities:
    - binary_sensor.upstairs_staircase_occupancy
tracker_residents:
  name: tracker_residents
  entities:
    - person.husband
    - person.wife

When home

Automatically arming when home

concept

Alarm automatically re-arming again and again during a night with a crybaby

When we go to bed, the last sensor that we trigger is the upstairs staircase motion sensor. 20 minutes after that sensor is inactive, a list of conditions must be fulfilled to enable the alarm:

  • Must be home
  • it must be nighttime (22:00 - 06:00)
  • the downstairs sensors must be idle
  • the downstairs sensors must be idle longer than the upstairs motion sensor
- id: autoarmhome
  alias: autoarmhome
  trigger:
  - platform: state
    entity_id: group.presence_upstairs
    to: "off"
    for: "00:20:00"
  condition:
    - condition: time
      after: '22:00:00'
      before: '06:00:00'
    - condition: state
      entity_id: alarm_control_panel.home_alarm
      state: disarmed
    - condition: template
      value_template: "{{(as_timestamp(states.group.presence_upstairs.last_changed) > as_timestamp(states.group.presence_downstairs.last_changed))}}"
    - condition: template
      value_template: "{{is_state('group.presence_downstairs','off')}}"
    - condition: state
      entity_id: group.tracker_residents
      state: 'home'
  action:
    service: alarm_control_panel.alarm_arm_home
    data:
      entity_id: alarm_control_panel.home_alarm
      code: !secret house_alarm_code

Automatically disarming when home

While all downstairs sensors will set of the alarm, we first have to pass the upstairs sensor in the staircase before we can trigger the alarm.

This means we can disable the alarm with a simple upstairs sensor trigger.

- alias: Auto Disarm alarm while armed home
  trigger:
  - platform: state
    entity_id: group.presence_upstairs
    to: 'on'
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_home
  action:
    service: alarm_control_panel.alarm_disarm
    data:
      entity_id: alarm_control_panel.home_alarm
      code: !secret house_alarm_code

Alarm triggers

All downstairs sensors wil trigger the alarm

- alias: Trigger alarm while armed home
  trigger:
  - platform: state
    to: 'on'
    entity_id: group.armed_home_delay_triggers
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_home
  action:
  - service: alarm_control_panel.alarm_trigger
    entity_id: alarm_control_panel.home_alarm
  - service: notify.telegramnotifyer
    data_template:
      title: 'ALARM'
      message: >-
        {% for entity in trigger.to_state.attributes.entity_id %}
          {% if states(entity) == 'on' %}
            {{ state_attr(entity, 'friendly_name') }}
          {% endif %}
        {% endfor %}

When away

Automatically arming when away

Since we don't have presence detection for everyone in the family, one way to make the automatic arming work is to only arm when the alarm sensors are completely idle when I have left the house. This avoids enabling the alarm while my wife is still at home or my parents in law are babysitting. When the whole family leaves the house, the system will arm.

- id: autoarmaway
  alias: autoarmaway
  trigger:
    - platform: state
      entity_id: group.tracker_residents
      to: "not_home"
      for:
        minutes: 15
  condition:
    - condition: state
      entity_id: alarm_control_panel.home_alarm
      state: disarmed
    - condition: state
      entity_id: group.tracker_residents
      state: "not_home"
    - condition: template
      value_template: "{{((as_timestamp(now()) - as_timestamp(states.group.presence_all.last_changed))>600)}}"
    - condition: template
      value_template: "{{is_state('group.presence_all','off')}}"
  action:
  - service: alarm_control_panel.alarm_arm_away
    data:
      entity_id: alarm_control_panel.home_alarm
      code: !secret house_alarm_code
  - service: notify.telegramnotifyer
    data:
      title: 'alarm auto aan'
      message: "vertrokken en sensors idle"

Automatically disarming when arriving home

- alias: alarm away auto disarm
  trigger:
  - platform: state
    entity_id: group.tracker_residents
    to: "home"
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_away
  action:
  - service: notify.telegramnotifyer
    data:
      title: 'thuiskomst alarm uit'
      message: "disabling alarm"
  - service: alarm_control_panel.alarm_disarm
    data:
      entity_id: alarm_control_panel.home_alarm
      code: !secret house_alarm_code

A fast responding location tracker, like WiFi Accesspoint integration. An NFC tag at the door can also be an option.

Alarm triggers when away

The alarm triggers for all sensors except the front door directly trigger the alarm directly:

- alias: armed_away anything triggers panic
  trigger:
  - platform: state
    to: 'on'
    entity_id: group.armed_away_immediate_triggers
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_away
  action:
    service: script.turn_on
    entity_id: script.panic_alarm

This is done by triggering the alarm when it's unarmed.

panic_alarm:
  sequence:
  - service: alarm_control_panel.alarm_disarm
    data:
      entity_id: alarm_control_panel.home_alarm
      code: !secret house_alarm_code
  - service: alarm_control_panel.alarm_trigger
    entity_id: alarm_control_panel.home_alarm

The front door triggers the regular alarm_trigger service.

- alias: armed_away Frontdoor triggers pre-alarm
  trigger:
  - platform: state
    entity_id: binary_sensor.frontdoor_contact
    to: 'on'
  condition:
  - condition: state
    entity_id: alarm_control_panel.home_alarm
    state: armed_away
  action:
    service: alarm_control_panel.alarm_trigger
    entity_id: alarm_control_panel.home_alarm

The siren

It's pretty easy to wire in a real alarm siren. You can use a Zigbee or Wifi power switch to feed power to a siren. This is what I use when we are on holiday.

I currently use the MPD (Music player daemon) servers on my media player raspberry pi's to notify of the 'arming' and 'triggered' states.

I want to move to a MQTT operated Python or BASH daemon that will make preserving the master mixer volume of the pi's easier.

Misc stuff

I split the automations into several files and use the !include_dir_merge_list directive in the main config.yaml:

  • alarm_away_automatic.yaml
  • alarm_home_automatic.yaml
  • alarm_notification.yaml
  • alarm_siren.yaml
  • alarm_triggers.yaml
automation: !include automations.yaml
automation old: !include_dir_merge_list automation