The notification system is King in my Home Assistant setup. I can have visitors that are completely unaware of smart features in my home; up until the house notifies me of finished laundry, garbage collection, an open door or that someone is approaching the house.
Because notifications are so prominent, it’s important to balance out what notifications go where, how often, and at what times of the day.
This article will focus on my notification paradigm and how a tablet dashboard plays a central role. My goal is to achieve a sufficient WAF, and at the same time allow myself some slack to explore stuff for my own satisfaction.
Mentally, I have this chart in my head when I add new notifications to the system:
There must be a balance between the grade of urgency of the message and the recipient’s acceptance for digitally created noise. I’ve found that if the information is important enough to the household, you are safe to use TTS messages throughout the house (at least during daytime). If the message is important only to you, say your 3D-print is done printing, stick to only nudging your own mobile. If the information is of marginal interest to the household, skip sound-based notifications all together or you’ll get complaints from both adults and kids.
Of course, this leaves out a lot of information from your smart home. In comes the dashboard.
Wall mounted tablets with a smart home dashboard is my household’s primary information interface with Home Assistant. The tablets work both as info screens and to configure the smart house.
Personally, I use the standard Home Assistant theme in dark mode. I find it pleasing to the eye and it didn’t require me to invent an entirely new color palette. Also, it doesn’t scream for attention, which ticks a box when it comes to the WAF.
The dashboard conveys a lot of information, but at the same time, it is easy to spot the important information quickly. I’ve tried building a user centered dashboard composed of icons that represent key features or tasks, with the most important information in the leftmost column. Top priority features get bigger icons and are easier to spot.
Granted, my proposed dashboard has a lot of icons, and to make important events/states stand out, I use colors and slowly flashing icons.
White means unknown state. It may for example be that the 3D-printer is turned off and not available.
Blue means a neutral or off state.
Blinking red is used for critical alerts like a burglar alarm, fire alarm, water leak or EV charging error. Some critical alerts also trigger sirens, voice alarms, phone alarms, etc.
Orange is used for important or useful notifications. An orange mailbox means that today is mail delivery day. An orange garbage icon means garbage collection happens tomorrow morning. An orange message icon means there are pending notifications waiting to be acknowledged. Some important or useful notifications trigger TTS on smart speakers and mobile app notifications.
Yellow means on for lights, sirens and heating sources, open for windows and doors or active for motion sensors. Some of these states may trigger a chirp.
Other variants. Some devices or services use additional colors, like the home alarm, where blinking orange means arming, or the EV charger, where blinking green means charging, and steady green means done charging.
The key is drawing attention to states the users might want to catch at a quick glance. This way, the dashboard is a non-intrusive way to give information about your smart home status. Additionally, it invites the user to use the smart home features. One of the most used features in my setup is muting the 15-minute cycle TTS notification saying the laundry is done.
I’ve built a responsive dashboard, meaning it adapts to different screen widths. Typically, responsiveness involves prioritizing content differently and using adapted layouts and spacing for desktops, tablets, and mobile phones. You only need to define an icon or component once, then re-use it in your different layouts.
To know more and learn how to set up a basic dashboard; check out my article on building a responsive dashboard. Consider the article a pre-requisite to implement what follows.
When you have your layout and your icons, you can fill them with the intended functionality.
Consider icon colors the basis of your notification system. A great starting point is using custom button cards from the button-card plugin by RomRider.
With custom button cards, icons are by default colorized with the Home Assistant theme colors corresponding to the entity your icon represents. Blue is neutral/off, yellow is on, white is unknown. The beauty is that you can easily override and tweak this behavior.
You can for example create a button card template that allows you to define standard look for a certain type of button. A simple example is a door icon, where you can combine two templates, one for size and layout, and another for icon and color:
button_tiny:
show_name: false
show_state: false
styles:
card:
- width: 27px
- height: 30px
- box-shadow: none
- background: transparent
icon:
- width: 23px
- height: 23px
grid:
- grid-template-areas: '"i"'
button_door:
state:
- value: "on"
color: var(--paper-item-icon-active-color)
icon: mdi:door-open
- value: "off"
color: rgb(68, 115, 158)
icon: mdi:door-closed
Then you assign the template to your button in your dashboard like this:
cards:
- type: "custom:button-card"
template:
- button_tiny
- button_door
entity: binary_sensor.door_mancave
You can specify styles without templates too. Take a temperature sensor inside a fridge. You’d want a fridge icon, and colors depending on the temperature inside. Then you could do something like this, combining a default template and custom styling with temperature values in Celsius:
cards:
- type: "custom:button-card"
template:
- button_tiny
icon: mdi:fridge
entity: sensor.fridge_temperature
state:
- value: 7
operator: ">"
styles:
card:
- animation: blink 2s ease infinite
icon:
- color: red
- value: 5
operator: ">"
styles:
card:
- animation: blink 2s ease infinite
icon:
- color: orange
- value: 0
operator: ">"
styles:
icon:
- color: rgb(68, 115, 158)
Normally, when clicking an icon, a default “more information” card will pop up. If you want to customize this behavior, for example in a notification center, use tap_actions like this:
card:
type: custom:button-card
template: button_sidebar_small
entity: binary_sensor.active_notifications
icon: mdi:message-text
state:
- value: "on"
styles:
card:
- animation: blink 2s ease infinite
icon:
- color: orange
tap_action: !include smarthus-dashboard/notifications.yaml
Now, the above button card code incorporates a few interesting elements. It will look like the “message” icon in the below image, and it’s going to blink orange when it’s active.
- name: Active notifications
unique_id: active_notifications
state: >
{{
is_state('alert.garage_door', 'on')
or
is_state('input_boolean.laundry_done', 'on')
or
is_state('input_boolean.3d_printer_done', 'on')
}}
Customizing popups is hugely useful, and one thing I use it for is a notification center.
NOTE! Popups have changed in browser-mod 2. See the bottom of this article!
To create a popup, add a tap_action pointing to a YAML-file. For example:
action: fire-dom-event
browser_mod:
command: popup
title: Notifications
card:
type: custom:layout-card
layout_type: custom:vertical-layout
cards:
- type: conditional
conditions:
- entity: binary_sensor.active_notifications
state: "on"
card:
type: entity-filter
entities:
- entity: alert.garage_door
- entity: input_boolean.laundry_done
- entity: input_boolean.3d_printer_done
state_filter:
- "on"
card:
type: entities
title: Active notifications
show_title: true
show_header_toggle: false
- type: entities
entities:
- entity: input_boolean.notify_garage_door
name: Enable garage door notification
- entity: input_boolean.notify_laundry
name: Enable laundry notification
- entity: input_boolean.notify_3d_printer
name: Enable 3D-printer notification
title: Configure notifications
show_header_toggle: false
Pop ups of this kind is a feature of the browser_mod plugin by Thomas Loven. This particular popup will give you a modal containing:
It’ll look like this:
This is the most used feature in my smart home. Getting notified of and being able to acknowledge repeating warnings about open doors, finished laundry and tumble drying are meaningful features even for others than myself. But how do I set up the notification based on this?
There are two ways I handle notifications: alerts and automations. Alerts are less configurable but can be set up with less code. Automations are more flexible, but also much more verbose code wise. Let’s look at the two methods.
Alerts are especially useful when you need repeating notifications that trigger on a specific entity state. They require almost no code and have acknowledging of notifications built in. If the state that triggered the alert returns to “normal”, the alert automatically stops and you don't have to do anything.
I’ll use an “open garage door” notification as an example. Firstly, I add this to alerts.yaml to create an "alert.garage_door entity":
garage_door:
name: Garage door open
message: The garage door is open
done_message: The garage door is closed
entity_id: binary_sensor.notification_garage_door_open
state: "on"
repeat: 0.5
can_acknowledge: true
skip_first: true
notifiers:
- phonenotifiers
- livingroom
The alert fires if the binary sensor “notification_garage_door_open” is on. The alert will then repeat a message every half minute via the defined notifiers. When the binary sensor turns off, or if the alert is acknowledged, it stops repeating the message. Doing something similar with automations requires a lot more code!
You probably don’t want to get notified every time your garage door is open, though. You could make the “notification_garage_door_open” a template binary sensor defined like this:
binary_sensor:
- name: "Notification garage door open"
unique_id: notification_garage_door_open
state: >
{{
is_state('input_boolean.notify_garage_door', 'on')
and
is_state('binary_sensor.garage_door_is_open', 'on')
and (
(as_timestamp(now()) - as_timestamp(states.binary_sensor.garage_door_is_open.last_changed)) > 14400 or
is_state('binary_sensor.it_is_night', 'on') or
is_state('alarm_control_panel.burglar_alarm', 'armed_home') or
(is_state('alarm_control_panel. burglar_alarm'', 'armed_away') and (as_timestamp(now()) - as_timestamp(states.alarm_control_panel. burglar_alarm'.last_changed)) > 600)
)
}}
The above code will cause the “notification_garage_door_open binary sensor to be “on” if we want to be notified (the input boolean “notify_garage_door” is on) and the garage door is open. But additionally, the garage door must have been open for 4 hours straight, or it’s night, or the burglar alarm is armed and we’re at home, or the burglar alarm has been armed for 10 minutes and we’re away.
The alert turns on when the binary sensor turns on, sending notification messages to the notifiers. I use a mix of Slack, companion app and TTS (google smart speakers), defined like this in configuration.yaml:
notify:
- name: Livingroom
platform: tts
tts_service: tts.google_say
media_player: media_player.nest_audio_livingroom
- name: Phonenotifiers
platform: group
services:
- service: mobile_app_mymobilephone
- service: my_slack_workspace_name
data:
target: "#my-smarthouse-channel"
When the alert is on, the notification center icon blinks orange on my dashboard, because it’s tied to the “active notifications” template binary sensor. Clicking the icon, opens the notification center, allowing me to acknowledge the alert, thus silencing the alerts that repeat every half minute.
The other way to do notifications, is by automations.
Alerts are normally my preferred choice for repeating notifications. However, I have set up repeating notifications via automations in some cases, like when the laundry is done. I could have used alerts, but because I had to use automations for toggling input booleans to preserve state across reboots safely, I figured it would be less confusing keeping the logic in one place.
To get notified of finished laundry, I use a set of input booleans that are toggled based upon the washing machine power consumption, measured via a smart plug. Input booleans can’t be set through templating, but they can be manipulated through automations; that’s why I use only automations and not templating plus alerts for this use case.
I have two automations that work together to determine start and end of a washing cycle.
The “laundry started” automation sets “laundry_started” to on, and “laundry_done” to off whenever the washing machine power is above 20 watts for 5 minutes:
- alias: Laundry started
description: ''
trigger:
- platform: numeric_state
entity_id: sensor.washing_machine_power
above: '20'
for:
hours: 0
minutes: 5
seconds: 0
milliseconds: 0
condition: []
action:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.laundry_started
- service: input_boolean.turn_off
target:
entity_id: input_boolean.laundry_done
mode: single
The “laundry done” automation sets “laundry_done” to on, and “laundry_started” to off, if the washing machine power is below 20 watts for 5 minutes, and the washing cycle had been initiated beforehand. When the laundry is done, and the “notify_laundry” boolean is on, the automation will repeat a message every 15 seconds:
- alias: Laundry done
description: ''
trigger:
- platform: numeric_state
entity_id: sensor.washing_machine_power
below: '20'
for:
hours: 0
minutes: 5
seconds: 0
milliseconds: 0
condition:
- condition: state
entity_id: input_boolean.laundry_started
state: 'on'
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.laundry_started
- service: input_boolean.turn_on
target:
entity_id: input_boolean.laundry_done
- repeat:
while:
- condition: state
entity_id: input_boolean.notify_laundry
state: 'on'
- condition: state
entity_id: input_boolean.laundry_done
state: 'on'
sequence:
- service: script.announcement_google_speakers_daytimeonly
data:
entity_id: media_player.nest_mancave, media_player.nest_livingroom
volume: 0.5
message: Laundry is done
message_length: 5
- delay:
hours: 0
minutes: 15
seconds: 0
milliseconds: 0
mode: single
The notification is sent to a custom script which evaluates if it’s daytime, before calling a second script which sets a common sound level, message length and message to all speakers:
announcement_google_speakers_daytimeonly:
alias: Announcement speakers daytime only
sequence:
- condition: state
entity_id: binary_sensor.it_is_night
state: "off"
- service: script.announcement_google_speakers
data:
entity_id: "{{ entity_id }}"
volume: "{{ volume }}"
message: "{{ message }}"
message_length: "{{ message_length }}"
mode: single
announcement_google_speakers:
alias: Announcement speakers
sequence:
- service: media_player.volume_set
data_template:
entity_id: "{{ entity_id }}"
volume_level: "{{ volume }}"
- delay:
milliseconds: 100
- service: tts.google_say
data:
entity_id: "{{ entity_id }}"
message: "{{ message }}"
- delay:
seconds: "{{ message_length }}"
- service: media_player.volume_set
data_template:
entity_id: "{{ entity_id }}"
volume_level: "{{ states('input_number.volume_smart_speaker_default') }}"
mode: single
Evaluation of day/night is dynamic, based upon input time helpers that are configurable via the dashboard when clicking the clock, and the built in workday integration of Home Assistant.
You can continuously see if it’s night/day and workday/holiday from the icons near the clock. Not super useful, but more of a debugging feature. Both the clock and the icons are part of a custom button card. Check out the code in my GitHub-repo to explore it further.
A t-shirt means weekend/holiday, while a suitcase means workday. Thanks to the built-in workday integration, you can define if today or tomorrow are workdays with binary sensors like this:
binary_sensor:
- platform: workday
name: workday_today
country: "NO"
- platform: workday
name: workday_tomorrow
country: "NO"
days_offset: 1
Change the country code to your country, and you Home Assistant may know about your moving holidays out of the box.
A lit up (yellow) moon and stars mean nighttime. The example above shows that nighttime starts at 23:00 (11 pm) on workdays, and midnight on weekends/holidays. Nighttime ends at 7:00 (am) on workdays, and 08:30 (am) on weekends/holidays.
It’s easy to extend the mornings if needed, and anybody can do it. It even has an immediate effect thanks to it being evaluated by a template binary sensor. Check out the “Det er natt” binary sensor in my templates file for inspiration.
The fact that the house enters “quiet mode” at night, some lights dim down at night and that some sensors are more sensitive at night, are appreciated features in my household.
This is for sure a lengthy article, but I hope it has given you some valuable input for your own Home Assistant setup. Check out this YouTube video that show you very shortly how everything works.
The key takeaways are to notify only when you need to and let the household in on the smart home system by letting them interact and tweak its workings as easily as possible.
You need to modify this code to work with browser-mod 2. The good news: it's pretty easy! You mostly only have to change the popups.
This is an example of how a popup could look like with browser-mod 2:
action: fire-dom-event
browser_mod:
service: browser_mod.popup
data:
size: wide
title: Energy consumption
content:
type: custom:layout-card
layout_type: custom:horizontal-layout
layout:
width: 400
max_cols: 3
card_margin: 15px
margin: 4px 50px 0px 50px
cards:
- type: custom:apexcharts-card
...