Before you can use the Google Calendar API to request events on your calendar, you must first authenticate the device with Google's authentication server.
We've handled this authorization "flow" by creating a CircuitPython library for Google's implementation of OAuth2.0 and an application to run on your device.
Add the Google credentials you generated to settings.toml. Also add your Adafruit IO credentials, and a TIMEZONE
value, which are used to find out what time it is.
CIRCUITPY_WIFI_SSID = "your_wifi_ssid" CIRCUITPY_WIFI_PASSWORD = "your_wifi_password" AIO_USERNAME = "your_aio_username" AIO_KEY = "your_aio_key" GOOGLE_CLIENT_ID = "YOUR_GOOGLE_CLIENT_ID" GOOGLE_CLIENT_SECRET = "YOUR_GOOGLE_CLIENT_SECRET" TIMEZONE = "Etc/UTC"
Add CircuitPython Code and Project Assets
In the embedded code element below, click on the Download Project Bundle button, and save the .zip archive file to your computer.
Then, uncompress the .zip file, it will unpack to a folder named PyPortal_Google_Calendar
Copy the contents of the PyPortal_Google_Calendar directory to your PyPortal CIRCUITPY drive.
# SPDX-FileCopyrightText: 2021 Brent Rubell, written for Adafruit Industries # # SPDX-License-Identifier: Unlicense import os from adafruit_display_text.label import Label from adafruit_bitmap_font import bitmap_font from adafruit_oauth2 import OAuth2 from adafruit_pyportal import Network, Graphics network = Network() network.connect() graphics = Graphics() # DisplayIO Setup # Set up fonts font_small = bitmap_font.load_font("/fonts/Arial-12.pcf") font_large = bitmap_font.load_font("/fonts/Arial-14.pcf") # preload fonts glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: " font_small.load_glyphs(glyphs) font_large.load_glyphs(glyphs) label_overview_text = Label( font_large, x=0, y=45, text="To authorize this device with Google:" ) graphics.splash.append(label_overview_text) label_verification_url = Label(font_small, x=0, y=100, line_spacing=1) graphics.splash.append(label_verification_url) label_user_code = Label(font_small, x=0, y=150) graphics.splash.append(label_user_code) label_qr_code = Label(font_small, x=0, y=190, text="Or scan the QR code:") graphics.splash.append(label_qr_code) # Set scope(s) of access required by the API you're using scopes = ["https://www.googleapis.com/auth/calendar.readonly"] # Initialize an oauth2 object google_auth = OAuth2( network.requests, os.getenv("GOOGLE_CLIENT_ID"), os.getenv("GOOGLE_CLIENT_SECRET"), scopes, ) # Request device and user codes # https://developers.google.com/identity/protocols/oauth2/limited-input-device#step-1:-request-device-and-user-codes google_auth.request_codes() # Display user code and verification url # NOTE: If you are displaying this on a screen, ensure the text label fields are # long enough to handle the user_code and verification_url. # Details in link below: # https://developers.google.com/identity/protocols/oauth2/limited-input-device#displayingthecode print( "1) Navigate to the following URL in a web browser:", google_auth.verification_url ) print("2) Enter the following code:", google_auth.user_code) # modify display labels to show verification URL and user code label_verification_url.text = ( "1. On your computer or mobile device,\n go to: %s" % google_auth.verification_url ) label_user_code.text = "2. Enter code: %s" % google_auth.user_code # Create a QR code graphics.qrcode(google_auth.verification_url.encode(), qr_size=2, x=170, y=165) graphics.display.root_group = graphics.splash # Poll Google's authorization server print("Waiting for browser authorization...") if not google_auth.wait_for_authorization(): raise RuntimeError("Timed out waiting for browser response!") print("Successfully Authenticated with Google!") # print formatted keys for adding to settings.toml print("Add the following lines to your settings.toml file:") print(f'GOOGLE_ACCESS_TOKEN = "{google_auth.access_token}"') print(f'GOOGLE_REFRESH_TOKEN = "{google_auth.refresh_token}"') # Remove QR code and code/verification labels graphics.splash.pop() graphics.splash.pop() graphics.splash.pop() label_overview_text.text = "Successfully Authenticated!" label_verification_url.text = ( "Check the REPL for tokens to add\n\tto your settings.toml file" ) # prevent exit while True: pass
Once all the files are copied from your computer to the CircuitPython device, you should have the following files on your CIRCUITPY drive.

Authenticator Code Usage
On your CIRCUITPY drive, rename authenticator.py to code.py.
Then, open the CircuitPython REPL using Mu or another serial monitor.
Navigate to the Google Device page and enter the code you see on your device.
Click Next
Select the Google Account you'd like to use with the calendar viewer.
- We are using the
https://www.googleapis.com/auth/calendar.readonly
scope which will gives an application read-only access to your calendar events.
Since Google has not formally verified the application you created in the previous step, you'll be greeted with a warning.
- Click Advanced
- Then, Click the Go to {your application name} link
Finally, a dialog will appear displaying the application's requested permissions.
Click Allow.
You'll be presented with a dialog telling you the device has been authenticated.
After 5 seconds, the CircuitPython REPL should print out GOOGLE_ACCESS_TOKEN
and GOOGLE_REFRESH_TOKEN
values.
Copy and paste them into the settings.toml file.
CIRCUITPY_WIFI_SSID = "your_wifi_ssid" CIRCUITPY_WIFI_PASSWORD = "your_wifi_password" AIO_USERNAME = "your_aio_username" AIO_KEY = "your_aio_key" GOOGLE_CLIENT_ID = "YOUR_GOOGLE_CLIENT_ID" GOOGLE_CLIENT_SECRET = "YOUR_GOOGLE_CLIENT_SECRET" TIMEZONE = "Etc/UTC" GOOGLE_ACCESS_TOKEN = "YOUR_GOOGLE_ACCESS_TOKEN" GOOGLE_REFRESH_TOKEN = "YOUR_GOOGLE_REFRESH_TOKEN"
Now that your device is authorized to make requests to the Google Calendar API, let's use it to fetch calendar events!
Page last edited January 22, 2025
Text editor powered by tinymce.