A Puck has one button and three LEDs, so the button’s gestures are its whole interface. They are told apart in packages/sensors/firmware/button.ts; what each does is a setting (packages/sensors/firmware/gestures.ts), acted on in packages/sensors/firmware/main.ts.
The gestures
| Gesture | Told apart by |
|---|---|
| Press | One short press, no second within 350 ms |
| Double press | Two short presses, each within 350 ms of the last |
| Triple press | Three; reported at once on the third |
| Long press | Held 0.6 to 10 seconds |
| Hold | Held 10 seconds or more: opens pairing for 60 seconds, always, so it is never an accident and the way back in cannot be set away |
Each of press, double, triple and long press does one of three things, with an LED colour of its own (red, green, blue, or two or three of them together: yellow, cyan, magenta, white):
- Start or stop an activity of a kind (walk, run, hike, cycle, other). While an activity runs, any activity gesture stops it and never starts another, so a bumped gesture can end a session but not replace it (
activityAfterinpackages/sensors/firmware/gestures.ts). Starting blinks its colour twice, stopping once for 400 ms, and while it runs the colour blinks for 10 ms every 20 seconds, so a glance says it is on. - Drop a marker: a Button record of the gesture, blinked once for 30 ms. What a marker means (a lap, “moved it to my pocket”) is the reader’s to say.
- Nothing.
By default a triple press starts and stops a walk in green, and press (green), double press (blue) and long press (magenta) drop markers. Datler Sensors sets them with DS.gestures({...}) (Sensor Data Format); installed firmware keeps them in ds.config.
Activities
An activity is an interval of a kind, as Health Connect’s exercise session and HealthKit’s workout are. Inside one the step detector counts and a steps record is written each minute, 0 included; outside one the detector is off (it draws about 50 uA by Espruino’s figure) and no steps are written, so the steps a reader sees are the activity’s alone. Temperature and light go on hourly either way, and presses, the battery and the adverts carry on. A reader can start and stop one too, with DS.activity(kind). A device starts with none running.
Pairing
A passkey, once set, means only a reader that paired with it can use the console, and pairing is closed except for the minute a hold opens (Reaching a Puck, Pairing). The passkey is set from a reader with DS.passkey("123456") (six digits; "" for none), which installed firmware keeps in Storage. A reader that already paired keeps getting in with pairing closed; a new one pairs during the window, entering the passkey when its system asks.
Recovery
If every pairing is lost or the passkey forgotten, the way back in is Espruino’s hard reset: the button held from the battery going in for about 10 seconds, until the red LED blinks five times. It clears pairings and saved code, so the firmware is installed again afterwards. Let go sooner and the Puck starts its bootloader or skips saved code instead (Puck.js, Firmware).
NFC
A phone tapped against the Puck reads a link from its NFC tag, https://datler.ca/s/ and its device id (NFC_LINK in packages/sensors/src/format/nfc-link.ts), set when the firmware starts. Chrome claims every https link a tag reads, so Datler Sensors wins it as a verified App Link: its manifest claims https://datler.ca/s/ with autoVerify, and the site’s /.well-known/assetlinks.json names the app (Public Site). Android then opens the link in the app, which reads it (take_launch_link) and opens that sensor’s page, which connects to it; a Puck this phone has not added opens the sensors list. On a phone without the app, the browser opens the link and the site sends it to the landing page. Until the site carries the file, a phone approves the link by hand, in the app’s Open by default settings. A tap on a running app reaches it as a new intent, which its activity keeps, so the app reads it when it comes back to the front.