Pythonscript to read out todays agenda

I created this python script that will search my calendars and send todays events to a tts player.
I took heavy inspiration from Gettling list of day's events from a calendar - #4 by FakeThinkpad
But I quickly get brain-fog when reading those {% .... %} template/script things, so tried out the Python Scripts - Home Assistant thing

Let me know if you have solutions for the known bugs, have suggestions for improvements, or if this was of any help/inspiration to you ;-).

Known bugs

I am missing is a way to listen for an event telling me that the last message is done playing, currently i just insert a 5 sec. pause.
The type method is apparently not allowed in these scripts, so the check to see if I get a valid response from hass.states.get is not failsafe.

Dependencies

It depends on the “ical sensor” available in HACS GitHub - tybritten/ical-sensor-homeassistant: an iCal Sensor for Home Assistant
I made my script to assume that I pull 10 events from each calendar, this you define when adding calendars to the ical integration.
As my developer PC is far from the speaker i use, I loved using the GitHub - thomasloven/hass-browser_mod: 🔹 A Home Assistant integration to turn your browser into a controllable entity and media player for testing

Automation

I created the automation to trigger the script in the UI


but here is the resulting yaml as reference:

alias: kalender udtal agenda
description: ""
trigger:
 - platform: state
   entity_id:
     - binary_sensor.kokken_hojtaler_volume_down
   from: "off"
   to: "on"
condition: []
action:
 - service: python_script.todays_agenda_to_tts
   data:
     player_id: media_player.kokken_hojtaler
mode: single

The script

And here is my python script

playerId = data.get( 'player_id', "media_player.browser_CH" )

logger.debug(f'playing on {playerId}')

tts_service_data = {"entity_id": playerId,
                    "message": "uuummmhhhh",
                    "cache" : "false", }

daystart = dt_util.start_of_local_day()
dayend = daystart + datetime.timedelta(days=1)
future = daystart + datetime.timedelta(days=1000)

logger.debug(f"Timeinterval: {daystart} to {dayend}")
agenda = []
calendars = ['martin_privat',
             'martin_arbejde',
             'born',
             'alslug',]

for calendar in calendars:
    logger.debug(f'looking in {calendar}')
    for cnt in range(10):
        cal = hass.states.get( f'sensor.ical_{calendar}_event_{cnt}').attributes
        if 'start' in cal.keys():
            start = cal['start']
            if daystart < start < dayend :
                summary = cal['summary']
                agenda.append((start,summary))
        else:
            logger.warning(f"no start for sensor.ical_{calendar}_event_{cnt}")
            logger.debug(f"{cal=}")


for start, summary in sorted(agenda):
            anouncement = f'Klokken {start.hour} {start.minute:02} ... {summary}'
            logger.info(anouncement)
            tts_service_data["message"] = anouncement
            hass.services.call("tts", "google_translate_say", tts_service_data, True)
            time.sleep(5)

logger.debug(f'checking if Joe is comming home today')
anouncement = f'Joe kommer hjem i dag'  # Default.
for cnt in range(10):
    calSensor = f'sensor.ical_Joe_travel_event_{cnt}'
    cal = hass.states.get( calSensor ).attributes
    if cal is not None:
        start = cal.get('start', future)
        end = cal.get('end', future)
        if (start < dayend) & (end > dayend) :  # it has started today or earlier. and it ends after today.
            anouncement = f'Joe flyver i dag'
    else:
        logger.warning(f"Failed to get {calSensor} attributes")
        logger.debug(f"{cal=}")

logger.info(anouncement)
tts_service_data["message"] = anouncement
hass.services.call("tts", "google_translate_say", tts_service_data, True)
1 Like

Have you seen the new services with response data?

It is meant to let you return data from services like calendar for any calendar integration.

Yes I have thanks.
I actually heard that it was on the roadmap, at the time when I made my script. But I didn’t have the patience to wait :slight_smile:
Next time I get the time I will update my script to use this if possible, and then also re-evaluate if the “python scripts” module is still the best place, and either go back to a Yaml thing, or the more advanced pyscript or AppDeamon.