Selecting an object in a dictionary

Wracking my brains with this one after spending all morning reading up on dictionaries and how to manipulate them to pull a piece of data from one.

I have a template sensor called sensor.calendar_events that stores the next 12 hours worth of calendar events. That sensor has an attribute calendar_response that contains a dictionary of those events. If I display that attribute in the Developer Tools/Template Editor, I get:

or

{
  "events": [
    {
      "start": "2023-08-30T15:45:00+01:00",
      "end": "2023-08-30T16:45:00+01:00",
      "summary": "Swimming ",
      "description": "#event",
      "location": "Galashiels"
    }
  ]
}

What I’m trying to achieve is to pull out the number of calendar events in the next 12 hours then feed that into a tts daily briefing announcement followed by the names of the events and the times.

eg "You have 3 events in your calendar today. Swimming starts at 3:45pm and lasts 1 hour. Then you have xxxx starting at x:xx" etc.

How do I select the required objects from the dictionary to slot into my daily briefing file?
I don’t need any help with the structure of the briefing, I’ve got that sorted. I just need to know how to get the right piece of data from the dictionary.

From a post in this community on extracting objects from dictionaries, I understand which is the ‘0’ attribute and which is the ‘1’ attribute and the concept of tuples (well I think I do), but I think the

{
  "events": [
     {

object is adding another layer of complexity I’m not able to master.

This is how the sensor’s attributes are displayed:

calendar_response:
  events:
    - start: '2023-08-30T15:45:00+01:00'
      end: '2023-08-30T16:45:00+01:00'
      summary: 'Swimming '
      description: '#event'
      location: Galashiels
icon: mdi:calendar
friendly_name: Calendar Events
{{ state_attr('sensor.calendar_events', 'calendar_response')['events'] 
| map(attribute='summary') | list }}

Edit: Stupid “pretty” quotes…

How could that have been so simple :roll_eyes:

I guess when you know, you know.

Thanks.

Yeah I picked those up :grin:

Right, next question.

If I use that to pull out the start and end time of the event, how do I turn that into a format I can use in an as_timestamp function?

When I use

{{ state_attr('sensor.calendar_events', 'calendar_response')['events'] 
| map(attribute='start') | list }}

I get

['2023-08-30T15:45:00+01:00']

which as_timestamp doesn’t like.

That is because as_timestamp expects a datetime string or object, not a list. You can use map() to apply filters across all the members of an object or items in a list:

{{ state_attr('sensor.calendar_events', 'calendar_response')['events'] 
| map(attribute='start') | map('as_timestamp') | list }}

But that might not be the best way to approach it for your expressed goal…


{% set e_list = state_attr('sensor.calendar_events', 'calendar_response')['events']
| sort(attribute= 'start') | list %}
You have {{ e_list | count }} events in your calendar today.
{% if e_list | count > 0 %}
{%- for e in e_list %}
{{ ['Then you have ','Next is ', 'Followed by ']|random if not loop.first else ['First up is ', 'First is ']|random}}
{{- e.summary }} at {{ (e.start|as_datetime).time() }} {{-[' for ', ' lasting for ', ' that lasts ']|random}}{{- (e.end|as_datetime - e.start|as_datetime).total_seconds()/3600 }} hours.
{%- endfor %}{% endif %}
1 Like

You’ve just completely blown my mind with that last bit. But it works so thank you.

I’m off to try to pick that apart now :grin:

These "random"s are a nice touch! :slight_smile: :+1:

1 Like