Here is a simple but effective way to temporarily store notifications until a certain set of conditions is fulfilled and you actually want them to fire. It’s just a few extra lines to an already existing script, but very useful; hopefully with voice making headways, we will soon have a better way to handle something like this!
If, for example, you want automation notifications to fire only after you are back home, or after you wake up, then this is for you.
Features:
- Any and multiple conditions to queue or not.
- Queueing skip; if a notification never needs to be queued, in which case it will be ignored if queueing conditions are met.
- Check and retrieve queued notifications (called by whatever means you desire) and send back to the notify script.
- Queued notification timeout, using todo’s
due_datetime
to consider a notification as “stale” after a defined period. The notification is not removed from the todo list on timeout, but it is skipped when the queue check script is called. - Do not duplicate notification in the queue (but timeout is overridden if duplicate found).
Note: This is a process that requires customization to your needs, hence only the base yaml is given below, for you to adapt (conditions, notification type, etc). If you want a full example of a working notify script (TTS) and queueing system, presence and sleep based, check out this github folder.
Prerequisites:
- Various automations that trigger notifications; any kind of notification that contains a
message
will do, TTS, persistent, etc. Those notification actions will be replaced by Service calls to the notify script below (unless you already have a notify script, in which case, you simply update it with the below logic). - A TODO list called
queued_notifications
(or something else, but then don’t forget to adjust the scripts below where appropriate). Here I used the local_todo integration, but any should work the same, as long as they support the services of todo.
Sidenote: It’s easy enough to add multilanguage support in case your home requires it, simply add a script field language
, and language-specific todo lists, then switch between them depending on the language (if language equals EN then use todo list EN
etc); works for both scripts the same.
The good stuff
alias: Notify
mode: queued
max: 20
icon: mdi:speaker-message
fields:
message:
selector:
text: null
name: Message
required: true
default: Hey there!
do_not_queue:
selector:
boolean: null
name: Do Not Queue
description: >-
Do not queue notification, even if conditions are met (ignore it instead).
required: false
queued_timeout_min:
selector:
number:
min: 0
max: 525600
step: 1
mode: box
name: Queued Timeout Min
description: >-
Queued notification timeout in minutes (if ever queued). If specified,
after that number of minutes, the notification will be skipped when the
queue is retrieved.
sequence:
- if:
# This is where the script decides if it should fire the notification immediately
# or queue it (you can check if away, if sleeping, etc)
# For example:
- condition: state
entity_id: person.you
state: not_home
then:
- if:
- condition: template
value_template: "{{ do_not_queue is not defined or not do_not_queue }}"
then:
- service: todo.get_items
target:
entity_id: todo.queued_notifications
data:
status: needs_action
response_variable: result
- if:
- condition: template
value_template: >-
{{ not message in result['todo.queued_notifications']['items'] | map(attribute='summary') }}
then:
- service: todo.add_item
data:
item: "{{ message }}"
due_datetime: >-
{{ now() + timedelta(minutes=(queued_timeout_min if (queued_timeout_min is defined and queued_timeout_min > 0) else 525600)) }}
target:
entity_id: todo.queued_notifications
else:
- service: todo.update_item
data:
item: "{{ message }}"
due_datetime: >-
{{ now() + timedelta(minutes=(queued_timeout_min if (queued_timeout_min is defined and queued_timeout_min > 0) else 525600)) }}
target:
entity_id: todo.queued_notifications
else:
# This is where your notification normally fires (immediate)
# For example:
- service: notify.persistent_notification
data:
message: "{{ message }}"
Below is the script to check for the presence of queued notifications, and if any (not timed out), feed them back (all at once, but numbered) to the notify script above (entity ID assumed to be script.notify
), then delete them from the queue.
You can easily call this script wherever appropriate (when automation detects you’re back home, or you woke up, etc).
Note: As of 2023.12.3, the Numeric state condition doesn’t show the title properly in UI if zero is used as number (bug), but the condition still works as expected.
alias: Check Queued Notifications
sequence:
- if:
- condition: numeric_state
entity_id: todo.queued_notifications
above: 0
then:
- service: todo.get_items
target:
entity_id: todo.queued_notifications
data:
status: needs_action
response_variable: result
- variables:
remaining: |-
{%- set ns = namespace(count=1) %}
{%- for i in result["todo.queued_notifications"]["items"] %}
{%- if now() <= as_datetime(i.due) %}
{{ ns.count }}. {{ i.summary }}.
{%- set ns.count = ns.count + 1 %}
{%- endif %}
{%- endfor %}
- if:
- condition: template
value_template: "{{ remaining != '' }}"
then:
- service: script.notify
data:
message: You have queued notifications. {{ remaining }}
do_not_queue: true
- service: todo.remove_item
data:
item: >-
{{ result["todo.queued_notifications"]["items"] | map(attribute='summary') | list }}
target:
entity_id: todo.queued_notifications
mode: single
icon: mdi:speaker-message
Calling the scripts - Some examples
Simple notification that will automatically queue if your conditions for it are met.
service: script.notify
data:
message: The weather is now announcing some snow.
Same as above, but with a queue timeout after 30 minutes.
In the example, we assume the notification is attached to a temperature sensor’s value, hence would no longer be considered viable after a short time.
If you were to call the queue check script over 30 minutes after the initial time of notification, that one would be skipped.
service: script.notify
data:
message: Temperature outside is nice. You should open up the house.
queued_timeout_min: 30
Never queue this notification. If conditions for queueing are met, the notification is then simply ignored.
service: script.notify
data:
message: Time to go to bed!
do_not_queue: true
Check for queued notifications
service: script.check_queued_notifications
data: {}
Feel free to correct any mistake I might have made writing this down.