Home Assistant: Smoke Alarm Display & Automations

Table of contents
- Integrating Your Smoke Alarms
- Inspect and Note the Devices
- Creating a Group (Helper) for the Binary Sensors
- Dashboard Elements For Smoke + CO
- Quadrant Display For 4 Smoke Alarms With Color-Coding
- Aggregating Battery Statuses Into One Reporting Entity
- Battery level row with conditional styling for alerts
- Driving Automations/Alarming
- Low Battery Warnings
- Low Battery Notifications

Safety is paramount, and integrating smoke alarms into your Home Assistant setup is a crucial step in ensuring your home's safety. This guide provides a comprehensive overview of how to integrate smart smoke alarms into your Home Assistant dashboard and create related automations.
Integrating Your Smoke Alarms
The first step is purchasing smart smoke alarms and integrating them into your smart home system. Both Wi-Fi and Zigbee-based smoke alarms are widely available. While Zigbee devices typically cost more, they offer several benefits, including lower battery consumption, less interference with home Wi-Fi networks, and easier integration into Home Assistant. I highly recommend buying Zigbee devices whenever possible.
Inspect and Note the Devices
After integrating the devices into Home Assistant, identify the specific sensors they expose. Typically, smart smoke alarms will expose three different sensors:
Smoke Detected State: The most important sensor, usually presented as a binary sensor. Use this for alarming.
Battery Sensor: Some devices report this as a battery level percentage, while others display a binary "OK" or "not OK" state. I strongly recommend purchasing devices that report the battery level as a percentage. This allows you to monitor the battery level and take proactive steps to replace batteries before they run out.
Creating a Group (Helper) for the Binary Sensors
Here's my approach to monitoring the alarms:
I use a binary sensor group to monitor all smoke alarms collectively. I have four smoke alarms in my house. I don't need to know whether each one is on or off all the time. I just need to be alerted if any one of them goes off.
I have a home safety dashboard where I monitor all the alarms individually and their battery levels.
For smoke detection, we're going to create a group for binary sensors. Make sure that you're adding the correct sensor for each smoke alarm to the group. Add the smoke sensor, not the tamper sensors (as they might also be binary).
If you have additional home safety sensors, such as a carbon monoxide sensor, you could add all of these into one broader safety group. This way, you can minimize the number of things you have to monitor and just get an alarm if any sensor condition is positive.
Home Assistant allows you to nest groups within groups. In the safety sensor group, I didn't have to manually list each smoke sensor. Instead, I added the smoke sensor group as its own entity and added the carbon monoxide sensor on top of it.
In this default configuration, the group will switch to "on" if any smoke alarm is "on". I imagine that essentially all users would prefer this configuration.
Dashboard Elements For Smoke + CO
This is a dashboard element showing the alarm state collectively and the carbon monoxide sensor. Replace the entities with your own.
type: custom:button-card
entity: binary_sensor.smoke_alarms
name: Smoke Alarms (All)
icon: mdi:smoke-detector
show_state: true
styles:
card:
- padding: 12px
state:
- padding-top: 8px
state:
- value: "off"
color: var(--success-color)
- value: "on"
color: var(--error-color)
Quadrant Display For 4 Smoke Alarms With Color-Coding
Widget:
YAML:
title: Smoke Detectors
type: vertical-stack
cards:
- type: grid
columns: 2
square: false
padding: 5
cards:
- type: custom:button-card
entity: binary_sensor.kitchensmokedetector_smoke
name: Kitchen
styles:
card:
- padding: 12px
- margin: 5px
name:
- font-weight: bold
- color: white
state:
- color: white
state:
- value: "on"
styles:
card:
- background-color: "#ea4335"
name:
- color: white
state:
- color: white
- value: "off"
styles:
card:
- background-color: "#34a853"
name:
- color: white
state:
- color: white
- value: unavailable
styles:
card:
- background-color: "#ffa500"
name:
- color: white
state:
- color: white
- type: custom:button-card
entity: binary_sensor.office_smoke_detector_smoke
name: Office
styles:
card:
- padding: 12px
- margin: 5px
name:
- font-weight: bold
- color: white
state:
- color: white
state:
- value: "on"
styles:
card:
- background-color: "#ea4335"
name:
- color: white
state:
- color: white
- value: "off"
styles:
card:
- background-color: "#34a853"
name:
- color: white
state:
- color: white
- value: unavailable
styles:
card:
- background-color: "#ffa500"
name:
- color: white
state:
- color: white
- type: custom:button-card
entity: binary_sensor.bedroom_smoke_sensor_smoke
name: Bedroom
styles:
card:
- padding: 12px
- margin: 5px
name:
- font-weight: bold
- color: white
state:
- color: white
state:
- value: "on"
styles:
card:
- background-color: "#ea4335"
name:
- color: white
state:
- color: white
- value: "off"
styles:
card:
- background-color: "#34a853"
name:
- color: white
state:
- color: white
- value: unavailable
styles:
card:
- background-color: "#ffa500"
name:
- color: white
state:
- color: white
- type: custom:button-card
entity: binary_sensor.living_room_smoke_detector_smoke
name: Living Room
styles:
card:
- padding: 12px
- margin: 5px
name:
- font-weight: bold
- color: white
state:
- color: white
state:
- value: "on"
styles:
card:
- background-color: "#ea4335"
name:
- color: white
state:
- color: white
- value: "off"
styles:
card:
- background-color: "#34a853"
name:
- color: white
state:
- color: white
- value: unavailable
styles:
card:
- background-color: "#ffa500"
name:
- color: white
state:
- color: white
- type: markdown
style: |
ha-card {
padding: 16px;
margin-top: 16px;
}
content: >
{% set total = 4 %} {% set active = namespace(count=0) %} {% set
unavailable = namespace(count=0) %} {% set devices =
['binary_sensor.kitchensmokedetector_smoke',
'binary_sensor.office_smoke_detector_smoke',
'binary_sensor.bedroom_smoke_sensor_smoke',
'binary_sensor.living_room_smoke_detector_smoke'] %}
{% for device in devices %}
{% if states(device) == 'on' %}
{% set active.count = active.count + 1 %}
{% elif states(device) == 'unavailable' %}
{% set unavailable.count = unavailable.count + 1 %}
{% endif %}
{% endfor %} {% set online = total - unavailable.count %} {{ online }}
alarms online, {{ active.count }} activated, {{ unavailable.count }}
unavailable
Aggregating Battery Statuses Into One Reporting Entity
As mentioned earlier, different smoke sensors report their battery states in different ways. Just as with the smoke alarm sensing, we might want to try to reduce this to one sensor for convenience.
You can add a template like this into your configuration to achieve this
template:
- binary_sensor:
name: "Smoke Detector Batteries Status"
state: >
{% set bedroom = states('sensor.bedroom_smoke_sensor_battery')|float(0) %}
{% set office = states('sensor.office_smoke_detector_battery')|float(0) %}
{% set living_room = states('sensor.living_room_smoke_detector_battery')|float(0) %}
{% set kitchen = states('binary_sensor.kitchensmokedetector_battery_low') %}
{{
bedroom <= 10 or
office <= 10 or
living_room <= 10 or
kitchen == 'on'
}}
device_class: battery
Battery level row with conditional styling for alerts
This card lists the battery levels for the sensors and will only show red if any are below 10% or it's a negative binary state.
type: custom:button-card
show_name: false
show_icon: false
show_state: false
custom_fields:
battery: >
[[[
const bedroom = states['sensor.bedroom_smoke_sensor_battery'].state;
const office = states['sensor.office_smoke_detector_battery'].state;
const living = states['sensor.living_room_smoke_detector_battery'].state;
const kitchen = states['binary_sensor.kitchensmokedetector_battery_low'].state;
const kitchenStatus = kitchen === 'off' ? '✓' : '⚠';
return `BR: ${bedroom}% | OF: ${office}% | LR: ${living}% | KT: ${kitchenStatus}`;
]]]
styles:
card:
- padding: 8px
custom_fields:
battery:
- font-size: 14px
- text-align: center
- color: white
state:
- operator: template
value: >
[[[
const bedroom = Number(states['sensor.bedroom_smoke_sensor_battery'].state);
const office = Number(states['sensor.office_smoke_detector_battery'].state);
const living = Number(states['sensor.living_room_smoke_detector_battery'].state);
const kitchen = states['binary_sensor.kitchensmokedetector_battery_low'].state;
return bedroom <= 10 || office <= 10 || living <= 10 || kitchen === 'on';
]]]
styles:
card:
- background-color: "#ea4335" # Red
- operator: default
styles:
card:
- background-color: "#34a853" # Green
Driving Automations/Alarming
Finally, we get to the question of what to do about alarming. Clearly this is actually the most important part of setting up smoke alarms!
I'm using the helper grouping again in order to simplify the process of setting up an automation. I'm departing from the principle that if any smoke alarm is positive or the carbon monoxide sensor, I'll want to know about it anywhere in the house immediately. So my automation will be triggered based upon a true state on the group sensor.
You can use YAML or the Visual builder to create an automation like this.
Trigger:
If the state of my binary sensor safety group turns to ON, which would happen if any constituent sensor were to become on:
Action:
Alarming.
Then my warning sirens (another entity group) will toggle to on:
You probably also want to add additional alarming to take advantage of the fact that unlike a conventional fire alarm, smart fire alarms can notify you wherever you are.
If you are at home when a smoke alarm triggers, it's pretty obvious that you're going to be alerted to the alarm by the alarms in your house if you have them, the physical alarm on the device, or other factors.
But you might wish to configure push emergency notifications on all your connected devices that will send through a designated emergency alerting channel in the event that this state becomes positive.
Low Battery Warnings
Finally, let's add a bit of notifications to the battery level monitoring, seeing as we have it as an option.
If you have smoke alarms that are all of the same type and report their sensor type consistently, then it's easier to do this. This is a great reason, in fact, to buy your smoke alarms in a batch - You'll know that they have the exact same functionality and sensors (I just wish I had thought of this beforehand!)
Let's create a sensor group for the battery levels:
I'll call this one "smoke alarm battery levels":
You could use the minimum value as the "type":
Low Battery Notifications
alias: "Low Battery Alert - Safety Devices"
description: "Notify when smoke or CO detector batteries are low"
trigger:
# Numeric sensors
- platform: numeric_state
entity_id:
- sensor.bedroom_smoke_sensor_battery
- sensor.office_smoke_detector_battery
- sensor.living_room_smoke_detector_battery
- sensor.carbon_monoxide_alarm_battery
below: 10
# Binary sensor for kitchen (special case)
- platform: state
entity_id: binary_sensor.kitchensmokedetector_battery_low
to: "on"
condition:
# Avoid notification spam by checking if the battery is not "unknown" or "unavailable"
- condition: template
value_template: >-
{{ not is_state(trigger.entity_id, 'unknown') and
not is_state(trigger.entity_id, 'unavailable') }}
action:
- service: persistent_notification.create
data:
title: "⚠️ Low Battery Alert"
message: >-
{{ trigger.to_state.attributes.friendly_name }} is at
{% if trigger.entity_id == 'binary_sensor.kitchensmokedetector_battery_low' %}
a low level
{% else %}
{{ trigger.to_state.state }}%
{% endif %}
and needs attention!
- service: notify.mobile_app_your_phone_name # Replace with your actual mobile app notify service
data:
title: "⚠️ Low Battery Alert"
message: >-
{{ trigger.to_state.attributes.friendly_name }} is at
{% if trigger.entity_id == 'binary_sensor.kitchensmokedetector_battery_low' %}
a low level
{% else %}
{{ trigger.to_state.state }}%
{% endif %}
data:
priority: high
channel: Safety # Optional: Create a specific notification channel for safety alerts
# Optional: Repeat notification every 24 hours until fixed
- service: script.turn_on
target:
entity_id: script.battery_reminder
Subscribe to my newsletter
Read articles from Daniel Rosehill directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Daniel Rosehill
Daniel Rosehill
I believe that open source is a way of life. If I figure something out, I try to pass on what I know, even if it's the tiniest unit of contribution to the vast sum of human knowledge. And .. that's what led me to set up this page!