Turn a Nest Learning Thermostat (2nd gen) into a small Wi-Fi-connected Elixir device: a 320×320 round screen, a rotating ring with a press, a piezo, motion, light and climate sensors, and Wi-Fi, all driven from your own OTP application, deployed to the Nest over Wi-Fi.

The Nest first has to be rooted with No Longer Evil (their install guide). docs/install.md covers the whole route: Wi-Fi and rooting, SSH keys, installing the platform, the example app, and your own.

Status: alpha (0.1). It runs the example app, foxbus, on a real Nest every day. The public API is described in docs/api.md and the module docs. Expect API changes between 0.x minor versions (see Versioning).

Install

def deps do
  [{:nest_gen2, "~> 0.3.0"}]
end

Setting up a Nest: docs/install.md goes from a 2nd-gen Nest thermostat to the example app running on it, then to your own app (starting from examples/hello_nest). platform/install.sh does the device side; platform/README.md explains it.

Battery and sleep: on its base or stand the Nest gets only about 120 mA, so an app must let the SDK deep-sleep it, or the battery drains while "plugged in"; docs/power.md explains why and what an app should do.

Developing on your computer: run your app on a laptop or desktop with target: :host and see the Nest's screen in a browser, turning the ring with the mouse; no build or deploy for the Nest needed. See docs/host.md.

How the hardware talks: docs/backplate.md describes the backplate (the base) and its serial protocol, from our own captures and the cuckoo-nest project's research, with credits.

Example app: foxbus

foxbus is a complete application built on this SDK, kept as a GitHub repository rather than a Hex package so it can be read, forked and adapted. It shows live bus departures for two stops, a splash screen with the room temperature, disruption warnings, and a countdown with an arrival alarm, using:

Versioning

Both the SDK and foxbus follow Semantic Versioning.

  • While the SDK is 0.x, a minor release (0.1 → 0.2) may change the API; patch releases (0.1.0 → 0.1.1) only fix things. Depend on it with ~> 0.1.0 (which allows 0.1.x but not 0.2), not ~> 0.1 (which in Elixir allows anything below 1.0).
  • From 1.0, breaking changes only come with a major release.
  • Every release is a git tag (v0.1.0) with an entry in CHANGELOG.md.
  • Apps are deployed separately from the SDK. platform/deploy_app.sh refuses to install an app built against a different SDK version from the one on the device.
foxbusnest_gen2
0.1.x0.1.x
0.2.x0.2.x (adds the Wi-Fi settings screens)

Layout

FolderWhat
lib/The Elixir package: NestGen2 (events), Display, Image, Text, Backlight, Dial, Piezo, Power, Backplate, Motion, Climate, Battery, Light, Clock, Network
c_src/C helpers: evwatch (input events), bplink (backplate UART), textrender (text from the device's own fonts), regread (register reads for debugging), entropyd (keeps the kernel entropy pool topped up, run from boot)
priv/Pre-built ARM binaries of the helpers (make -C c_src)
platform/Rooting, runtime install, boot hook, app watchdog, app deploy, Wi-Fi without Nest's connection manager, host build environment, shell setup
tools/Backplate frame decoder
docs/API description

Build and test

The Nest runs OTP 26 / Elixir 1.17, so build with that toolchain:

platform/mix26 test

platform/mix26 runs mix with that toolchain (and its own Hex) whatever your shell has set up, including version managers such as mise that restore their own MIX_HOME before every prompt.

Layers

  1. Platform — the device runs our BEAM instead of Nest's software.
  2. Native helpers — small static C programs for the device nodes Erlang can't read reliably.
  3. SDK — the hex package nest_gen2 (NestGen2.*).
  4. Apps — your OTP application, e.g. foxbus.

The SDK provides mechanisms with sensible defaults and apps decide policy. The backplate keep-alive always runs.

Contributing

Issues and pull requests are welcome at github.com/integration-technology/nest_gen2_sdk. For hardware problems, please include the board (Gen 2 "Diamond"), the backplate firmware version (the 0x0001 message after a backplate reset) and what the Nest's own firmware does in the same situation.

Credits

This work stands on the shoulders of the Nest right-to-repair community:

  • NoLongerEvil-Thermostat by codykociemba — the installer we use to root the Nest and flash custom firmware. Every device running this SDK starts there. Its own credits, which we pass on:
    • grant-h / ajb142 — omap_loader, the USB bootloader tool used to flash OMAP devices.
    • exploiteers (GTVHacker) — the original research behind the Nest DFU Attack, which showed custom firmware could be flashed to Nest gen 1 and gen 2.
    • FULU and bounty backers — for funding the Nest Learning Thermostat Gen 1/2 bounty and supporting right to repair.
  • stb_truetype by Sean Barrett (public domain / MIT), vendored in c_src/vendor, which rasterises text on the device.
  • Nest Labs' published GPL kernel sources — reading the board file and drivers is how the display, dial, backlight and sensors were understood.

Licence

GPL-3.0-only; see LICENSE. If you distribute an app built on this SDK, the app must be released under a GPL-compatible licence too.

Nest's Akkurat fonts (/nestlabs/share/fonts) are commercially licensed and are not covered by this licence. This repository never contains them or anything rendered from them; the SDK renders text from the device's own copy at runtime.