Home assistant based automatic alarm
At one point I wanted a basic home security system (burglar alarm) to offer me some peace 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, an effective security system can be implemented.
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 (e.g. 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
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 will 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
Liked something? Worked on something similar? Let me know what you think on Mastodon!
You can use your Mastodon account to reply to this post.