The Google Calendar Event Display code uses the Google Calendar API's Event list endpoint to return events from a specific calendar.

The results from a GET request to this endpoint will look something like the following:

{
 "kind": "calendar#events",
 "etag": "\"p32c9b6vtqmbes0g\"",
 "summary": "Meetings",
 "updated": "2021-01-12T15:06:56.911Z",
 "timeZone": "America/New_York",
 "accessRole": "owner",
 "defaultReminders": [],
 "nextPageToken": "CigKGjMyajF0bm0xcmwzbDBnbWhmNTNyaW9xb3B2GAEggIDA3tm_zrYXGg0IABIAGJiVm_3Vlu4CIgcIBBC35scP",
 "items": [
  {
   "kind": "calendar#event",
   "etag": "\"3219736474490000\"",
   "id": "32j1tnm1rl3l0gmhf53rioqopv",
   "status": "confirmed",
   "htmlLink": "https://www.google.com/calendar/event?eid=MzJqMXRubTFybDNsMGdtaGY1M3Jpb3FvcHYgYWpmb242cGhsN24xZG1wanNkbGV2dHFhMDRAZw",
   "created": "2021-01-05T17:35:02.000Z",
   "updated": "2021-01-05T17:37:17.245Z",
   "summary": "Adafruit Show and Tell",
   "creator": {
    "email": ""
   },
   "organizer": {
    "email": "@group.calendar.google.com",
    "displayName": "Meetings",
    "self": true
   },
   "start": {
    "dateTime": "2021-01-06T19:30:00-05:00"
   },
   "end": {
    "dateTime": "2021-01-06T20:00:00-05:00"
   },
   "iCalUID": "@google.com",
   "sequence": 0,
   "reminders": {
    "useDefault": true
   }
  }
 ]
}

All events are kept within an items array which contains detailed information about each event. The code parses this array for the event's summary and the event's start dateTime

Refreshing Google API Access Token

The Google Calendar API access token expires after a specific time interval. If the access token is expired, the refresh token in secrets.py is used to POST a request to Google's servers for a new access token.

if (int(time.monotonic()) - access_token_obtained>= google_auth.access_token_expiration):
  print("Access token expired, refreshing...")
  if not google_auth.refresh_access_token():
    raise RuntimeError(
      "Unable to refresh access token - has the token been revoked?"
    )
    access_token_obtained = int(time.monotonic())

Fetching Calendar Events

Prior to calling Google Calendar, a timestamp must be obtained to display the latest events in ascending order. The code calls the Adafruit IO time service to fetch and set the timestamp we'll use for requesting data from Google Calendar.

# fetch calendar events!
print("fetching local time...")
now = get_current_time()

We'll display the current date at the top of the PyPortal. Passing a pretty_date argument formats the struct_time timestamp into a human-readable timestamp such as "January 6th, 2021"

# setup header label
pyportal.set_text(format_datetime(now, pretty_date=True), label_header)

Within get_calendar_events, we perform a HTTP GET to Google Calendar API's event list endpoint

def display_calendar_events(resp_events):
    # Display all calendar events
    for event_idx in range(len(resp_events)):
        event = resp_events[event_idx]
        # wrap event name around second line if necessary
        event_name = PyPortal.wrap_nicely(event["summary"], 25)
        event_name = "\n".join(event_name[0:2])  # only wrap 2 lines, truncate third..
        event_start = event["start"]["dateTime"]
        print("-" * 40)
        print("Event Description: ", event_name)
        print("Event Time:", format_datetime(event_start))
        print("-" * 40)
        pyportal.set_text(format_datetime(event_start), event_labels[event_idx][0])
        pyportal.set_text(event_name, event_labels[event_idx][1])

    # Clear any unused labels
    for event_idx in range(len(resp_events), MAX_EVENTS):
        pyportal.set_text("", event_labels[event_idx][0])
        pyportal.set_text("", event_labels[event_idx][1])

Finally, the display elements are displayed on the screen and the PyPortal sleeps for REFRESH_TIME minutes.

print("displaying events")
display_calendar_events(events)

print("Sleeping for %d minutes" % REFRESH_TIME)
time.sleep(REFRESH_TIME * 60)

This guide was first published on Jan 13, 2021. It was last updated on Jan 13, 2021.

This page (Code Walkthrough) was last updated on Jan 12, 2021.

Text editor powered by tinymce.