There may be an obvious answer I’m missing but I’ve been unable to really find a clear way of how to do this.
I am looking to send notifications to my device based on the due date of a to-do list task. Essentially, when the task is due that day (or ideally even that hour), send a notification to my companion app. How would I do this please?
I echo this request! Can anyone assist with this? I already have it setup when an item is added I get a notification but would be great if I could get one when it’s due(maybe even add an option to snooze it?!?!)
Here’s what I have so far, feel free to try it yourself. Currently doesn’t work as it always evaluates to False - don’t know why. 0 should equal 0 but apparently not here. I’ve tested the outputs from delta.days and it definitely returns 0, so yeah.
description: To-do Notifications
trigger:
- platform: time_pattern
hours: "*"
minutes: "*"
condition: []
action:
- service: todo.get_items
metadata: {}
data:
status: needs_action
response_variable: todovar
target:
entity_id: todo.[PUT YOUR LIST NAME HERE]
- if:
- condition: template
value_template: |
{%- for item in todovar['todo.YOURLISTHERE']['items'] %}
{% if 'due' in item%}
{% set delta = as_local(strptime(item['due'], "%Y-%m-%d")) - today_at("00:00") %}
{% if delta.days == 0 %} True
{% elif delta.days < 0 %} True
{% elif delta.days > 0 %} False
{% endif %}
{% endif %}
{%- endfor %}
then:
- service: persistent_notification.create
data:
notification_id: TASK DUE
title: A task is due today!
message: A task is due today, check your to-do!!
mode: single
I got it working, I had to add {% break %} to each section. EDIT: I’ve added functionality to alert you to which task is due (not sure if you have multiple on the same day but hey). I’ve also made it so it notifies my phone, but you can modify it to suit your needs (persistent notification is there just disabled, copying message content to it should be enough). Full code:
alias: YOUR's To-Do Notification
description: To-do Notifications
trigger:
- platform: time
at: "08:00:00"
- platform: time
at: "12:00:00"
- platform: time
at: "15:00:00"
condition: []
action:
- service: todo.get_items
metadata: {}
data:
status: needs_action
response_variable: todovar
target:
entity_id: todo.YOUR_to_do
- if:
- condition: template
value_template: |-
{%- for item in todovar['todo.YOUR_to_do']['items'] %}
{% if 'due' in item%}
{% set delta = as_local(strptime(item['due'], "%Y-%m-%d")) - today_at("00:00") %}
{% if delta.days == 0 %}
True
{% break %}
{% elif delta.days < 0 %}
True
{% break %}
{% endif %}
{% endif %}
{% endfor -%}
then:
- service: persistent_notification.create
data:
notification_id: TASK DUE
title: A task is due today!
message: A task is due today, check your to-do!!
enabled: false
- service: notify.mobile_app_YOURfone
data:
title: A task is due!
message: |
{%- for item in todovar['todo.YOUR_to_do']['items'] %}
{% if 'due' in item%}
{% set delta = as_local(strptime(item['due'], "%Y-%m-%d")) - today_at("00:00") %}
{% if delta.days < 0 %} Task OVERDUE by {{ (delta.days | abs) }} day(s) {{ '\n\n' -}} {{ item['summary'] }}
{% elif delta.days == 0 %} Task due TODAY {{ '\n\n' -}} {{ item['summary'] }}
{% endif %}
{% endif %}
{% endfor -%}
data:
ttl: 0
priority: high
mode: single
I implemented this but having an issue with the mobile notification(which is what I want!). Logic for overdue works and if I enable the persistent notification it works fine. It’s when I try to have it notify my phone(with your message format) with doesn’t seem to send any notification. I can simplify your message with something simple like “Task Due” and that works fine but when I try to use your message format to get more details in the message(which again is what I was looking for) it just doesn’t send out a message.
I’m getting these errors when trying to execute it:
Home To-Do Notification: If at step 2: Error executing script. Error for call_service at pos 1: Error rendering data template: ValueError: Template error: strptime got invalid input ‘2024-03-06T14:07:00-05:00’ when rendering template ‘{%- for item in todovar[‘todo.home_list’][‘items’] %} {% if ‘due’ in item%} {% set delta = as_local(strptime(item[‘due’], “%Y-%m-%d”)) - today_at(“00:00”) %} {% if delta.days < 0 %} Task OVERDUE by {{ (delta.days | abs) }} day(s) {{ ‘\n\n’ -}} {{ item[‘summary’] }} {% elif delta.days == 0 %} Task due TODAY {{ ‘\n\n’ -}} {{ item[‘summary’] }} {% endif %} {% endif %} {% endfor -%}’ but no default was specified
Home To-Do Notification: Error executing script. Error for if at pos 2: Error rendering data template: ValueError: Template error: strptime got invalid input ‘2024-03-06T14:07:00-05:00’ when rendering template ‘{%- for item in todovar[‘todo.home_list’][‘items’] %} {% if ‘due’ in item%} {% set delta = as_local(strptime(item[‘due’], “%Y-%m-%d”)) - today_at(“00:00”) %} {% if delta.days < 0 %} Task OVERDUE by {{ (delta.days | abs) }} day(s) {{ ‘\n\n’ -}} {{ item[‘summary’] }} {% elif delta.days == 0 %} Task due TODAY {{ ‘\n\n’ -}} {{ item[‘summary’] }} {% endif %} {% endif %} {% endfor -%}’ but no default was specified
Try removing the due time. May need to update the strptime to include HH MM like this %Y-%m-%dT%H:%M:%S%z otherwise, I didn’t account for that. I can certainly try to, but it’s more than I bargained for given how annoying and limited this code format is to work with…
BOOM! I’m going to try and take logic from another to-do automation so it works on all to-do lists so I don’t have to create an automation for each list. Not sure if you are interested but will keep you posted if you are!
Sure post anything here if you make changes, might help other people looking for answers. I guess you could just create a variable for your lists to pass into the rest of the automation or even just stick all the lists in an area and target that - I’m only really concerned with my main list but can see why that functionality would be appealing.
I’m sort of at a loss on how to do this. Like I said I have another automation that sends me a notification anytime an item is added to any to-do list but it works by using different logic. I attached it below if that helps at all.
trigger:
- platform: event
event_type: call_service
event_data:
domain: todo
service: add_item
variables:
list_name: >
{{ state_attr((trigger.event.data.service_data.entity_id)[0],
'friendly_name') }}
item: "{{ trigger.event.data.service_data.item | title }}"
user_name: >
{% set uid = trigger.event.context.user_id %}
{% set user = None %}
{% set matching_users = states.person |
selectattr('attributes.uid','==', uid) | list %}
{% set user = matching_users|first if matching_users|length > 0 else
"System" %}
{{ user if user == "System" else
state_attr(user.entity_id,"friendly_name") }}
context: {}
condition: []
I think that works by monitoring the parent to-do service call, so that would be list agnostic which I don’t think would work here. The notification has to explicitly load the contents of the list into a variable in order to pull out the due dates, so that needs to be specified. You can get the contents of all the lists by creating an area and assigning to-do lists to it. This will give you a nested dictionary with all lists and their content within that area.
Try putting {{ todovar }} in the message output so you can see what it spits out, it’s basically a dictionary within dictionaries. You would basically just need to modify the for loop to account for the extra keys and values. Maybe something like for key, value in todovar.items():.
Sorry this completely fell off my radar. The more I thought about this I think I can survive with just one list and honestly didn’t quite understand your suggestion. If you have time to take a stab at it I would appreciate it but if not I am happy with what you already provided!!
Thank you very much!
I confirm: if there is a time in the task, an error is caused, but if there is only a date, everything is OK, this is not a problem - you can change it. I tweaked it for myself - everything works fine.
I don’t understand what i am doing wrong but it is not working. Automation stops at “if” condition. What can be wrong? Also I have never identified “todovar” variable. Should I create helper for that or not?
Hey, check out my Github for a working version if you’re having problems. The todovar is entirely contained within the YAML configuration. If you’re stopping at the “if” you probably aren’t using a break in the code, I had the same problem, but yeah check my HA repo.
I have updated it to account for times as well, it just needed a split variable for when the time is present. Repo above if you’re interested, but if you figured it out too, great!
I made similar automations, one for when the task is due to the present day and one for tasks that are overdue (due yesterday or before it). The summary of every due task is shown in the notification too. Note that both ignore the time and use only the due date, even if there is a due time.