Sorry Carlos your post came in as I was typing to Taras, looking at yours now.
In case you missed it, it’s now possible to get events from a calendar natively; there’s no need to install any third-party applications.
If that’s what you want to do then it can be done without the use of calendar.list_events
. What you described can be achieved with a Calendar Trigger.
If you mean the example in this post, then read the post prior to it. You’ll see I took someone else’s example (containing German text) and simplified its templates.
You’ll need to explain what you want exactly.
I would like to format the event times, when the TTS reads it out so that Tuesday @ 4pm etc at the moment I have
For determining if a date is today, tomorrow, in X days, etc then you may want to consider using these custom macros:
Okay thanks, I will have a read
Thanks for the tip!
I used a different approach, because I would like to send multiple notifications. I’m now using this automation at a given time:
automation:
- alias: "Notify Events for Today"
trigger:
platform: time
at: "08:00:00"
action:
service: notify.your_notification_service
data:
title: "Today's Events"
message: >-
{% set today = now().strftime('%Y-%m-%d') %}
{% set events_today = state_attr('sensor.gary_scheduled_events', 'scheduled_events') | selectattr('start', 'eq', today) | list %}
{% for e in events_today %}
{{ e.summary }}
{% endfor %}
This works like a charm!
Next step is cleaning up code (using correct names for this service) and I’ll put a ‘how to’ on this topic.
automation:
- alias: "Notify Events for Today"
trigger:
platform: time
at: "08:00:00"
action:
service: notify.your_notification_service
data:
title: "Today's Events"
message: >-
{% for e in state_attr('sensor.robin_scheduled_events', 'scheduled_events')
| selectattr('start', 'eq', now().strftime('%Y-%m-%d')) %}
{{ e.summary }}
{% endfor %}
Thanks guys for the inspiration, I could not figure out the easy time approach, I resolved it by just inserting a timestamp similar to Robin.
Garys Agenda for today: {% for e in
state_attr('sensor.garys_agenda','scheduled_events') %}
{{ as_timestamp(e.start) | timestamp_custom ('%A %H:%M %p') }}: {{ e.summary }} {% endfor %}
Christines Aganda for today: {% for e in
state_attr('sensor.christines_agenda', 'scheduled_events') %}
{{ as_timestamp(e.start) | timestamp_custom ('%A %H:%M %p') }}: {{ e.summary }} {% endfor %}
Just one thing left for me to polish it a little, just have to work out the code to do the following:
if day = now then “Today” not the day of the week.
I finally got day changed to today and tomorrow, I am not sure if there is a better way to do it? I would be interested if there was a better way, however this seems to work okay. The only issue I cant resolve is the line spaces in between each event. See Garys agenda below as apposed to Christines agenda
Gary you have {{states('sensor.garys_agenda')}} items in your Agenda: {% for
e in state_attr('sensor.garys_agenda','scheduled_events') %}
{% set start = e.start | as_datetime | as_local %}
{% if start.strftime('%A') == now().strftime('%A') %}Today at {{ as_timestamp(e.start) | timestamp_custom ('%H:%M %p')}} {{ e.summary }}{%else%}{% if start.strftime('%A') > now().strftime('%A')%}Tomorrow at {{ as_timestamp(e.start) | timestamp_custom ('%H:%M %p')}} {{ e.summary }}{% endif %}{% endif %}{% endfor %}
The blank lines seen in the output are due to this line in your template.
{% set start = e.start | as_datetime | as_local %}
It’s represented by a blank line for each iteration of the for-loop.
You can suppress it by adding hypens to the braces, like this:
{%- set start = e.start | as_datetime | as_local -%}
Reference:
Jinja2 - Whitespace control
Assuming your sensor is constrained to containing events exclusively for today and tomorrow, you can use this streamlined version:
Gary you have {{ states('sensor.garys_agenda') }} items in your Agenda:
{% for e in state_attr('sensor.garys_agenda','scheduled_events') %}
{%- set start = e.start | as_datetime | as_local -%}
{{ ['Today', 'Tomorrow'][(start.date() - now().date()).days] }} at {{ start.strftime('%H:%M %p') }} {{ e.summary }}
{% endfor %}
Thanks Taras, I did notice the {%- in a few posts, but didn’t understand the significance? Will give it a go.
Will also give the new code a go and try to understand it.
On a side note: I see you helping a number of individuals throughout the community - you must know this stuff inside out, you not only give instruction but provide insight as well, thank you and good work from the whole community.
This is a list containing two items:
['Today', 'Tomorrow']
List items are indexed starting with zero. Therefore this will display the first item in the list (Today
).
['Today', 'Tomorrow'][0]
This displays the second item in the list (Tomorrow
).
['Today', 'Tomorrow'][1]
Subtracting two datetime objects produces a timedelta object. One of the properties of a timedelta object is days
. In other words, the timedelta object’s value is reported as the number of days.
(start.date() - now().date()).days
If the difference between start.date()
and now().date()
is 0
then it means the event starts today. If the difference is 1
then it starts tomorrow. We use this difference value to get the associated item from the list.
{{ ['Today', 'Tomorrow'][(start.date() - now().date()).days] }}
Thank you for the explanation, helps a lot especially in the future,
By adding the streamline ver, I realise now why my original ver wasn’t pulling in the next day, I only defend 2 in the list, however your solution brings in the whole list and defines 2 names. Yours is streamlined but also a better solution as if I have items in the third day I can see them as below:
I have been playing around with if statements trying to get the items after tomorrow to default back to the day “Monday” etc? No success so far. Also I have been looking into “carriage returns” something so obvious seems difficult, say I want a “carriage return” after the first line, how do you do that?
It’s 8 days and dozens of posts later and I have run out of free time for this topic. Hopefully someone else can assist you. Good luck.
No problem, thank you for all your help
something is wrong here
Invalid config for [sensor.template]: [sensor] is an invalid option for [sensor.template]. Check: sensor.template->sensor. (See ?, line ?).
Yes it’s because you tried to configure a Trigger-based Template Sensor using a mixture of the formats for both a legacy and modern Template Sensor.
-
There are two ways to configure a Template Sensor, using either modern or legacy format.
-
There’s only one way to configure a Trigger-based Template Sensor and that’s using modern format.
Modern format Template entities are configured under the template:
key and use different option names from legacy format. For example, modern format doesn’t use platform: template
.