2.0.1 • Published 3 months ago

@gavinsawyer/shortcuts-api v2.0.1

Weekly downloads
-
License
MIT
Repository
github
Last release
3 months ago

ShortcutsAPI

An API and library of iOS shortcuts used to create highly detailed home automations based on the user's Focus mode, location, and time of day. The Focus mode can also be displayed on a personal website in real-time.

GitHub workflow status ShortcutsAPI version Firebase-Functions version

🎉 Multi-user support is here in ^2.0.0!

Thesis

Having somewhere to store and retrieve Focus mode, location, and time of day enables highly detailed home automations in HomeKit and the native iOS app Shortcuts. The initial problem this aimed to solve was disabling motion-activated lights while in Sleep Focus rather than at a hard-coded time. This was impossible as Home Automations run on tvOS devices which don't currently have access to the user's Focus mode. The final product is capable of doing much more, though:

An example of home automation using the On Stop Wake-Up Alarm shortcut turns off my Sleep Focus, turns on my apartment lights and espresso machine, and prompts Siri to tell me the weather and my first calendar events over intercom if I am at home when my wake-up alarm is stopped:

On Stop Wake-Up Alarm Example

An example of home state management using the Asleep and At Home shortcut reminds me to charge my iPhone before going to sleep by only turning off my bedroom lights when the charger is connected:

Asleep and At Home Example

Deployment

  1. From your Firebase Functions package root, run:
```
% npm install @gavinsawyer/shortcuts-api --save`
```
  1. Export the function by calling getShortcutsApi():

    import { CallableRequestData, CallableResponseData, getShortcutsApi } from "@gavinsawyer/shortcuts-api";
    import { getApps, initializeApp }                                     from "firebase-admin/app";
    import { CallableFunction }                                           from "firebase-functions/v2/https";
getApps()
  .length === 0 && initializeApp();

export const ShortcutsApi: CallableFunction<CallableRequestData, Promise<CallableResponseData>> = getShortcutsApi();

// Other functions...
```
  1. Deploy your Firebase Functions:

    % firebase deploy --only functions
  2. Create a Firestore Database to store public key credentials with the ID shortcuts-api and location matching the function deployment. It is recommended to choose either nam5 in North America or eur3 in Europe:

    % firebase firestore:databases:create shortcuts-api --location ${MULTI_REGION_NAME}
  3. Populate the Firestore database with a collection with ID "environment" and a document with ID "private". This document should match the PrivateDocument interface described below. Include each resident of your home with an object under users:

    {
      "environment": {                  // Collection
        "private": {                    // Document
          "users": {                    // map
            "Gavin": {                  // map
              "focus": "Developing",    // string
              "focusPrior": "Personal", // string
              "location": "At Home",    // string
              "time": "Day"             // string
            }
          }
        }
      }
    }

Usage

Download and import all items in within the shortcuts directory to your Mac or iOS device. You may organize them into folders once imported, but it's not necessary. Config requires setup including:

  • Providing your home Wi-Fi network's name, the Cloud Function's URL, and the username as it appears in Firestore ("Gavin" in code sample above).
  • Creating an Access Token

State shortcuts are left empty for you to customize. These are used to express state rather than to respond to events and must be able to be triggered repeatedly without side effects. Whether you are home is determined by your iPhone's Wi-Fi connection.

  • At Home and Awake Anytime: Partial state of your home when you are at home and awake at any time (preferred temp, etc.). This is always preceded by either:
    • At Home and Awake Before Sunset: Partial state of your home when you are at home and awake during daytime (brighter lighting, etc.).
    • At Home and Awake Before Sunrise: Partial state of your home when you are at home and awake during nighttime (dimmer lighting, etc.).
  • At Home and Asleep: Complete state of your home when you are at home and asleep
  • Away: Complete state of your home when you are away.

Additional Shared State shortcuts are available in ^2.0.0 for shared homes! These are used the same as State shortcuts, but apply to devices multiple people use such as thermostats and lights in common areas.

  • Somebody At Home and Awake Anytime: Partial state of your home when somebody at home is awake at any time (preferred temp, etc.). This is always preceded by either:
    • Somebody At Home and Awake Before Sunset: Partial state of your home when somebody at home is awake during daytime (brighter lighting, etc.).
    • Somebody At Home and Awake Before Sunrise: Partial state of your home when somebody at home is awake during nighttime (dimmer lighting, etc.).
  • Everybody At Home Asleep: Complete state of your home when everybody at home is asleep
  • Everybody Away: Complete state of your home when everybody is away.

In the Automation section of Shortcuts on iOS, create Personal Automations pointing to the Automation Trigger shortcuts for each of the following events. These shortcuts can all be customized with additional actions based on focus, location, and time of day by accessing the Private User Dictionary.

  • iPhone joins or leaves home Wi-Fi network -> On Arrive or Depart (Updates Firestore with your location)
  • You Choose -> On Start or End Focus Activity with the focus as text input. (To set your device's Focus mode programmatically–example)
  • Time of Day: Sunrise/Sunset -> On Sunrise/On Sunset (Updates Firestore with the time)
  • CarPlay: Connects/Disconnects -> On Connect or Disconnect CarPlay
  • Charger: Connects/Disconnects -> On Connect or Disconnect Charger
  • Alarm Goes Off: Any -> Get Utility Alarm, Delete Utility Alarm, Handle Utility Alarm (example)
  • Alarm Is Stopped: Wake-Up -> On Stop Wake-Up Alarm
  • ${FOCUS}: Turned on/off -> On Change Focus with the current focus as text input. (Updates Firestore with your device's Focus mode–example)

The API stores data in documents with IDs "private" and "public" so that specified fields can be displayed on a personal website in real-time. The public document only has fields for each user specified by the publicFields array in the private document:

export interface PublicDocument {
  "users": {
    [key: string]: Partial<User>,
  },
}
export interface PrivateDocument {
  "users": {
    [key: string]: User,
  },
}
export interface User {
  "focus"?: Focus,
  "focusPrior"?: Focus,
  "location"?: Location,
  "publicFields"?: ("focus" | "location" | "time")[]
  "time"?: Time,
}

Currently supported Focus modes:

export type Focus = "Developing" | "Do Not Disturb" | "Driving" | "Fitness" | "Personal" | "Sleep" | "Studying" | "Work";

Google Cloud Setup

  • Reference the access token you created in the Config shortcut as a secret by exposing the environment variable SHORTCUTS_API_ACCESS_TOKEN in Cloud Functions under shortcutsApi > Edit > Security and Image Repo.
  • Grant the Cloud Functions Invoker role to the allUsers principal in Cloud Functions under shortcutsApi > Permissions.
  • Grant the Cloud Datastore User role to the App Engine default service account principal in Service accounts under App Engine default service account > Permissions.
2.0.1

3 months ago

2.0.0

3 months ago

2.0.0-next

3 months ago

2.0.0-next1

3 months ago

2.0.0-next2

3 months ago

2.0.0-next3

3 months ago

1.7.3

8 months ago

1.7.2

8 months ago

1.7.1

8 months ago

1.7.0

8 months ago

1.5.2

10 months ago

1.6.0

8 months ago

1.5.1

10 months ago

1.5.0

10 months ago

1.7.6

8 months ago

1.7.5

8 months ago

1.7.4

8 months ago

1.2.0

1 year ago

1.1.1

1 year ago

1.3.6

1 year ago

1.3.5

1 year ago

1.4.3

1 year ago

1.3.4

1 year ago

1.4.2

1 year ago

1.3.3

1 year ago

1.4.1

1 year ago

1.3.2

1 year ago

1.2.3

1 year ago

1.4.0

1 year ago

1.3.1

1 year ago

1.2.2

1 year ago

1.1.3

1 year ago

1.3.0

1 year ago

1.2.1

1 year ago

1.1.2

1 year ago

1.1.0

1 year ago

1.0.8

1 year ago

1.0.7

1 year ago

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago

0.0.0

1 year ago