npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

august-connect

v4.0.0

Published

Client module for locking + unlocking August smart locks via August Connect

Downloads

26

Readme

august-connect

GitHub CI status

A simple module for locking, unlocking, and getting the status of August smart locks via the August Connect WiFi bridge.


Setup

You'll need:

  • A set up & configured August Smart Lock + August Connect WiFi bridge
  • The password to the August account you'll be using with this client
  • A valid August API key¹
npm i august-connect

Require august-connect in your project:

let august = require('august-connect')

Configuration

Calls must be made with a configuration set either as environment variables, or passed in the parameters of the method in question.

Environment variables

The following configuration environment variables are required if not passing a config object:

  • AUGUST_API_KEY - string - a valid August API key¹ (please refer notes at the bottom of this readme for more)
  • AUGUST_INSTALLID - string - referred to as the "installation" below, this string represents your authorized session; changing it will break things and require re-authorization; suggest using something reasonably long, random, and unique
  • AUGUST_PASSWORD - string - your August password
  • AUGUST_ID_TYPE - string - one of email or phone
  • AUGUST_ID - string - the corresponding account email or a phone number (phone format is +[countrycode][number] with no other symbols, i.e. +12345678901)

To work with august-connect locally, I suggest setting up your variables with dotenv.

Config object

The following configuration keys are required if not using the environment variables noted above:

  • apiKey - - string - a valid August API key¹ (please refer notes at the bottom of this readme for more)
  • installID - - string - referred to as the "installation" below, this string represents your authorized session; changing it will break things and require re-authorization; suggest using something reasonably long, random, and unique
  • password - - string - your August password
  • IDType - - string - one of email or phone
  • augustID - - string - the corresponding account email or a phone number (phone format is +[countrycode][number] with no other symbols, i.e. +12345678901)

Tokens

August's API uses short-lived tokens (JWTs); as of version 3.0 august-connect returns a token string from its first session initiation; subsequent requests may reuse the same token.

⚠️ Warning: Depending on how your processes run, network conditions, API latency, etc., these tokens may expire mid-use. If you aren't totally sure, don't reuse your token between transactions.


API

Authorization

august.authorize([params][, callback])[Promise]

⚠️ Required step!

Also aliased to august.validate()

Before you can use august-connect, you'll have to authorize an installation (i.e. your AUGUST_INSTALLID, which is just a unique identifier of your choosing that you'll continue reusing). You only need to authorize an installation one time – you should not attempt continued / ongoing reauthorization attempts.

If passed, params must be an object; this object may contain a code string, and config object, and it returns the string of the authorized installation ID.

To authorize an installation, you must input a six digit code that August will send to your email or phone ID. Here's how:

  • First, assuming your configuration env vars are set, initiate the request for an auth code by calling: august.authorize()
  • Alternately, if passing a config object, initiate the request for an auth code by calling: august.authorize({config: {...})
  • Then, complete your auth request by adding the six digit code (as a string) as the first param: august.authorize({code: '123456'})

You should now have an authorized installation!

⚠️ Warning: if you change your AUGUST_INSTALLID, or don't make use of that installation's session for 120 days, you'll have to repeat the authorization process again.

Example
// Get a second-factor code
august.authorize({
  config: {
    apiKey,
    installID,
    password,
    IDType,
    augustID
  }
}, console.log)

// Authorize
august.authorize({
  code,
  ...config
}, console.log)

Status / info

august.status([params][, callback])[Promise]

If passed, params must be an object; this object may contain a lockID string, config object, and token string.

Returns error, or object containing status and diagnostic info of a single lock, and a reusable token:

  • If your account only has access to a single lock, you can opt not to specify a lockID
  • For reference, lock states:
    • status.kAugLockState_Locked: lock is locked
    • status.kAugLockState_Unlocked: lock is unlocked
Example
// Check your lock's status
const August = require('august-connect')

August.status({ lockID: '7EDFA965E0AE0CE19772AFA435364295' }, console.log)
// {
//   status: 'kAugLockState_Locked',
//   info: { ... }
//   retryCount: 1,
//   totalTime: 1786,
//   resultsFromOperationCache: false,
//   token: 'foobar'
// }

august.locks([params][, callback])[Promise]

If passed, params must be an object, and may contain a config object, and token string.

Returns error, or object containing locks that your valid installation has access to, and a reusable token

Example
// Check to see if your lock is locked
const August = require('august-connect')

August.locks(console.log)
// {
//  '7EDFA965E0AE0CE19772AFA435364295': {
//    LockName: 'Front door',
//    UserType: 'superuser',
//    macAddress: '1A:2B:3C:4D:5E:6F',
//    HouseID: '097dcab3-a29a-491a-8468-bab41b6b7040',
//    HouseName: 'Home',
//    token: 'foobar'
//   }
// }

august.details([params][, callback])[Promise]

If passed, params must be an object, and may contain a lockID string, config object, and token string.

Returns error, or object containing lock details on a single lock, and a reusable token

  • If your account only has access to a single lock, you can opt not to specify a lockID
Examples
// Obtains details on a specific lock
const August = require('august-connect')

August.details({ lockID: '7EDFA965E0AE0CE19772AFA435364295' }, console.log)
// {
//   battery: { ... },
//  ...
// }
// Assuming your have only one August lock on your account
const August = require('august-connect')

;(async () => {
  await August.details()
})

Lock / unlock

august.lock([params][, callback])[Promise]

If passed, params must be an object, and may contain a lockID string, config object, and token string.

Returns error, or object containing status and diagnostic info after locking a single lock, and a reusable token

  • If your account only has access to a single lock, you can opt not to specify a lockID
  • If your account has access multiple locks, you must specify a lockID
    • This is to prevent locking the wrong lock, which would be pretty not good
Examples
// Lock a specific lock
const August = require('august-connect')

August.lock({ lockID: '7EDFA965E0AE0CE19772AFA435364295' }, console.log)
// {
//   status: 'kAugLockState_Locked',
//   info: { ... }
//   retryCount: 1,
//   totalTime: 1786,
//   resultsFromOperationCache: false,
//   token: 'foobar'
// }
// Assuming your have only one August lock on your account
const August = require('august-connect')

;(async () => {
  await August.lock()
})

august.unlock([params][, callback])[Promise]

If passed, params must be an object, and may contain a lockID string, config object, and token string.

Returns error, or object containing status and diagnostic info after unlocking a single lock, and a reusable token

  • If your account only has access to a single lock, you can opt not to specify a lockID
  • If your account has access multiple locks, you must specify a lockID
    • This is to prevent unlocking the wrong lock, which would be pretty not good
Examples
// Unlock a specific lock
const August = require('august-connect')

August.unlock({ lockID: '7EDFA965E0AE0CE19772AFA435364295' }, console.log)
// {
//   status: 'kAugLockState_Unlocked',
//   info: { ... }
//   retryCount: 1,
//   totalTime: 1786,
//   resultsFromOperationCache: false,
//   token: 'foobar'
// }
// Assuming your have only one August unlock on your account
const August = require('august-connect')

;(async () => {
  await August.unlock()
})

Upgrade guide

3.0

  • Version 3.0 now requires calls that methods may only be passed objects; specifically, those breaking changes would manifest in the following ways:
    • august.authorize:
      • Before: august.authorize('123456')
      • After: august.authorize({ code: '123456' })
    • august.status:
      • Before: august.status('7EDFA965E0AE0CE19772AFA435364295')
      • After: august.status({ lockID: '7EDFA965E0AE0CE19772AFA435364295' })
    • august.lock:
      • Before: august.lock('7EDFA965E0AE0CE19772AFA435364295')
      • After: august.lock({ lockID: '7EDFA965E0AE0CE19772AFA435364295' })
    • august.unlock:
      • Before: august.unlock('7EDFA965E0AE0CE19772AFA435364295')
      • After: august.unlock({ lockID: '7EDFA965E0AE0CE19772AFA435364295' })

Contributing

  • Please fork and submit PRs against master
  • Make sure unit tests pass
  • Integration tests should also pass, but are not automated
    • Because we wouldn't want real doors getting locked and unlocked in the real world, integration tests are not part of the automated test suite
    • To run them, ensure you are using a valid API key¹, set up your local .env file, and test against your own hardware with a valid installation

Acknowledgments

Big ups to Nolan Brown and Joe Lu's py-august project for paving the way!

Notes

¹ august-connect uses August's unpublished API, and August has been known to occasionally recycle their client API keys. Hard-coding a August API key into august-connect would not reliable, so you'll need to acquire a key of your own. I suggest using Nolan Brown's August API reverse engineering guide to get one – or there's always Google!

  • This module was tested with a 1st-generation August Smart Lock
    • If you have future-gen August smart locks, I'd love to know more about how the library performs for you!
  • This module does not provide an interface to August locks via BLE
  • This module is not intended to provide complete coverage of the August API, only the bare minimum necessary to operate the August Smart Lock
  • Unfortunately, August does not publish their API for consumer usage, so this may break at any time; August name etc. trademark Assa Abloy (who make some truly great locks, by the way!)
  • I am in no way responsible for any safety issues that arise from the use of this module!