I have several home automations that run based on the day of the week. For example, there is no point opening the curtains or turning on the heating in my home office if I'm not going to be in there. As a result, most of these day-specific automations either run crudely midweek or at the weekend.
Most of the time this works; however, on days when I do work from home, I find myself having to trigger and run some of these automations manually. Wouldn't it be great if Home Assistant could look at my work calendar to determine if I'm working from home or the office that day?
Google Calendar - Working Location
At work, we use Google Workspaces, which means that I use Google Calendar to manage my work schedule.Since launching working locations, Google has added a number of improvements over time, including the ability to specify the working location for different times during a working day and making working locations available via the API! Since August 2021, Google Calendar has supported allowing you to configure and specify your work location.
Since launching working locations Google has added a number of improvements over time, including the ability to specify the working location for different times during a working day, and making working locations available via the API!
Getting access to the Working Location information
Whilst I use the Google Calendar integration for Home Assistant, it doesn't currently support interacting with working location information. However, I've done my research and know this information is fundamentally available via the Google APIs.
I already use AppDaemon in my Home Assistant setup to provide additional bits of functionality. I therefore plan to put together a basic REST endpoint in AppDaemon that will query the Google Calendar API, and will allow me to define a RESTful sensor in Home Assistant.
I have used AppDaemon in the past to provide my Home Assistant setup with additional functionality. AppDaemon defines itself as:
a loosely coupled, multi-threaded, sandboxed python execution environment for writing automation apps for home automation projects, and any environment that requires a robust event driven architecture.
Building a Working Location Sensor in Home Assistant
I will assume that you already have AppDaemon setup. If not, you can either refer to the installation instructions in my first blog post on using AppDaemon or the official documentation.
Setting up API Access
First, an API key will be required to use the Google APIs — start by creating a new project in the Google Cloud Console.
Under "Library", we will need to select and enable the Google Calendar API:
We can now create a set of API keys for Google Calendar. To do this, we will need to navigate to the credentials section of the Google Cloud console.
Click on "Configure Consent Screen" – I opted for "Internal"
On the next screen, you will prompted for a series of details. Only "App name", "User support email", and "Developer contact information" email are required.
Finally, on the next screen, you will have the option to select the scopes that are needed. Select the calendar.readonly
scope:
After selecting the scopes and finalising the consent screen, return to the main credentials screen and pick the option to create an "OAuth client ID" set of credentials:
Select "Desktop app" as the application type:
Finally, on the next screen, download the attached credentials JSON file and save it as credentials.json
– this will be needed later.
Building the Sensor
We first need to define and build our REST endpoint in AppDaemon, which will then be consumed by Home Assistant.
Before delving into the script that we'll use with AppDaemon to query the API, we first need to generate a token to use with the API from our credentials.json
file.
On your desktop, run the following script that will launch a browser window asking you to provide Google Calendar with consent to accept API calls from this project/set of credentials. Once consent has been provided, this script will generate a google_calendar_token.json
file, which will be needed later.
This script will require the following python dependencies to be installed:
pip install google-auth
pip install google-auth-oauthlib
pip install google-auth-httplib2
pip install google-api-python-client
When this script is run, it will launch a browser window that will look as follows:
When you press "Allow", the script will output a google_calendar_token.json
file that we will need later.
We've now completed all of the preparation work and can switch over to Home Assistant.
Within your AppDaemon installation folder, there will be a app/apps.yaml
file, add an entry for working_location
:
...
working_location:
module: working_location
class: WorkingLocation
...
Next, create the working_location.py
module file with the following:
import appdaemon.plugins.hass.hassapi as hass
import datetime
import os
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
class WorkingLocation(hass.Hass):
def initialize(self):
self.register_endpoint(self.working_location, 'working_location')
self.creds = Credentials.from_authorized_user_file(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'google_calendar_token.json'), SCOPES)
async def working_location(self, request, kwargs):
service = build('calendar', 'v3', credentials=self.creds)
now = datetime.datetime.now()
start_of_day = now.replace(hour=0, minute=0, second=0)
end_of_day = now.replace(hour=23, minute=59, second=59)
events_result = service.events().list(calendarId='primary',
timeMin=start_of_day.isoformat() + 'Z',
timeMax=end_of_day.isoformat() + 'Z',
singleEvents=True,
eventTypes='workingLocation',
orderBy='startTime').execute()
working_locations = []
for event in events_result.get('items', []):
start = datetime.datetime.fromisoformat(event['start'].get('dateTime', event['start'].get('date')).replace('Z', ''))
end = datetime.datetime.fromisoformat(event['end'].get('dateTime', event['end'].get('date')).replace('Z', ''))
working_locations.append({
"start": start,
"end": end,
"location": event['workingLocationProperties']
})
current_working_locations = sorted([wl for wl in working_locations if wl['start'] <= now and wl['end'] >= now],
key=lambda x: x['end'] - x['start'])
if not current_working_locations:
return {"type": "Home", "label": "Home"}, 200
else:
payload = current_working_locations[0]["location"]
if payload['type'] == 'homeOffice':
payload['label'] = 'Home'
else:
payload['label'] = payload[payload['type']]['label']
return payload, 200
Copy your google_calendar_token.json
file so that it sits in the same directory as your Python script.
This API implementation that we have written relies on a number of third-party libraries provided by Google therefore, we will need to add these to the AppDaemon configuration in Home Assistant:
Under Developer Tools reload the configuration for Reest Entities and Notify Services so that Home Assistant picks up the new RESTful sensor.
Now, we have a sensor that reflects our working location that can be displayed on a dashboard or incorporated into the logic of home automation!