Skip to content

Beakin — Provisioning Guide

How to assign a name, site, and planogram location to a beakin — from fresh firmware to fully provisioned.

← Handbook home · User Guide


Table of Contents


What is Provisioning?

When a beakin is first flashed, it broadcasts a BLE iBeacon signal with a UUID and a pair of numbers (major and minor). That's all the device knows about itself.

Provisioning is the process of giving a beakin a human-readable identity: a name, a store site, and a planogram location (aisle, side, section, shelf). This metadata lives in two places:

  1. The mobile app — persisted to local storage on the phone/tablet.
  2. The device's onboard storage (NVS) — written over Bluetooth so the beakin's OLED display shows the correct label and location, and so it survives firmware updates without needing to be re-provisioned.

When a beakin-server is deployed on Raspberry Pi, it becomes a third (centralized) source of truth that all field operators can sync with.


Provisioning Lifecycle

[freshly flashed board]
 ┌───────────────┐
 │ unprovisioned │  ← visible in app; no name or location assigned yet
 └───────┬───────┘
         │  tap "Set up" in the app
  ┌─────────────┐
  │    draft    │  ← form filled and saved locally; device not yet written
  └──────┬──────┘
         │  tap "Mark as Provisioned"
  ┌────────────────────┐       out of range / BLE failure
  │ provisioning...    │ ─────────────────────────────────►  ┌──────────────────────┐
  └────────┬───────────┘                                     │ provisioned-pending   │
           │  GATT write confirmed                           │ (retry on next scan)  │
           ▼                                                 └───────────────────────┘
  ┌──────────────┐
  │  provisioned │  ← app registry and device NVS are in sync
  └──────────────┘

Status Definitions

Status What it means
unprovisioned Seen on scan; no local record exists for this device
draft Setup form has been filled and saved on the phone; device has not been written yet
provisioned-pending Marked provisioned locally; Bluetooth write to the device is queued
provisioned Both the app registry and the device's onboard storage agree on the identity

Data Layers and Precedence

Provisioning data is resolved from multiple sources. Higher-numbered layers win on conflict.

Priority Layer Source Description
1 (lowest) runtime Live BLE scan Identity only — UUID, major, minor
2 seed Generated from beacons.yaml Pre-loaded names and location data
3 server Pi 5 registry API Central registry (when available)
4 (highest) local Operator edits on phone/tablet Explicit field overrides always win

In practice: the seed layer means new beakins appear in the app with their label and location already filled in, as long as beacons.yaml was synced before the app was built. Operators can then confirm or override any field.


Adding a New Beakin

Step 1 — Add to beacons.yaml

Open beakin-fw/scripts/beacons.yaml and add a new entry under devices:.

Required fields:

- serial: 98:A3:16:8F:F6:D8   # from `python3 scripts/list_mcus.py`
  label: "Product Name"
  env: xiao_esp32c6            # board type
  site_id: "heb-373"           # your store's site ID
  major: 1                     # next available major (check existing entries)
  minor: 7                     # next available minor (must be unique per site)

Common optional fields:

  power_profile: balanced      # performance | balanced | endurance
  antenna: internal            # internal | external (C6 only)
  area: "01"
  aisle: 12
  side: "A"
  section: 2
  shelf: 4
  location_type: 1
  psa_description: "Aisle 12"
  display:
    type: oled
    width: 128
    height: 64

major and minor rules: - Must be integers between 0 and 65535. - Must be unique within your site — no two beakins should share the same major/minor pair at the same site. - They are not derived from aisle or shelf numbers. Pick the next available sequential values.

Step 2 — Regenerate Tasks

After saving beacons.yaml, regenerate the VS Code tasks:

cd beakin-fw
./scripts/gen_tasks.sh

A new set of per-device tasks (flash:, monitor:, dev:, identify:) will appear in the task list for the new board.

Step 3 — Flash Firmware

Connect the board via USB-C (data cable required). Then in VS Code:

Tasks: Run Task → flash: <label> [env / sn:...]

Watch the serial log for a clean boot:

[APP] Booting...
[BLE] Advertising started

Step 4 — Generate the Provisioning Seed

The mobile app reads a pre-generated seed file that maps beakin identity to label and location. Regenerate it after any beacons.yaml change:

cd beakin-react-native
npm run provisioning:seed:generate

If you need to sync beacons.yaml from the firmware repo first:

npm run provisioning:seed:sync

After regenerating, rebuild and deploy the app to pick up the new seed data.

Step 5 — Provision via the App

Open the Beakin app and go to the Find screen. The new beakin will appear (it may show as M1-m7 or its label if the seed was loaded). Tap it, then tap Set up to begin the provisioning flow.

See Provisioning via the App below for full steps.


The Provisioning Seed

The seed is a static snapshot of beacons.yaml compiled into the mobile app. It pre-populates the provisioning registry so operators see real labels rather than raw major/minor values when they first open the app.

When to regenerate: - After adding or renaming any device in beacons.yaml - After changing planogram fields (aisle, side, shelf, etc.) - After adding a new site_id

Command:

cd beakin-react-native
npm run provisioning:seed:generate

The seed data lives in config/provisioningSeed.ts and is committed to the app repo. Operators with an older app build will see the previous seed until they update.


Provisioning via the App

Set Up a New Beakin

  1. Open the app → Find screen.
  2. Locate the beakin in the list (it shows as unprovisioned or with its seed-provided label).
  3. Tap the beakin to open its detail screen.
  4. Tap Set up.
  5. Fill in the provisioning form:
  6. Name — human-readable label (e.g. "Kids Vitamins – Aisle 23B")
  7. Site — your deployment site ID
  8. Area, Aisle, Side, Section, Shelf — planogram location
  9. Tap Save — status becomes draft.
  10. While in range of the beakin, tap Mark as Provisioned.
  11. The app connects over Bluetooth and writes the config to the device's onboard storage.
  12. Status becomes provisioned when the write is confirmed. If the beakin goes out of range first, status becomes provisioned-pending and the write will retry automatically.

Tip: Stay within 3–5 meters of the beakin when tapping "Mark as Provisioned" to ensure a reliable Bluetooth write.

Reconfigure an Existing Beakin

  1. Open the app → Find screen and tap the beakin.
  2. Tap Reconfigure (shown as ⚙ Reconfigure for already-provisioned beakins).
  3. Edit any fields on the form.
  4. Tap Save, then Mark as Provisioned to push the update to the device.

Location updates will show on the beakin's OLED display immediately after the Bluetooth write succeeds.

Retry a Pending Write

If a beakin shows as provisioned-pending, the config is saved on your phone but not yet written to the device:

  • The app retries automatically whenever the beakin is detected in range.
  • To trigger a write immediately: tap the beakin → tap Retry write.

Factory Reset a Beakin

Two methods:

Via the app: 1. Open the beakin's detail screen. 2. Tap Reconfigure → scroll down → Factory Reset. 3. The device wipes its onboard storage and reboots as unprovisioned.

Via hardware button: 1. Power on the beakin. 2. Hold the BOOT/USER button for 5 seconds during normal operation. 3. The device reboots as unprovisioned.

After a factory reset, the beakin reappears as unprovisioned in the app. Your local record is preserved and can be re-written to the device.


Device Identity Keys

Two identity key formats are used across the system:

Provisioning key (canonical)

Used in the app registry and the server database:

site_id:uuid_lowercase:major:minor

Example:

heb-373:f7826da6-4fa2-4e98-8024-bc5b71e0893e:1:7

Runtime key (gateway/MQTT)

Used for live sighting events from gateways:

site_id:major:minor

Example:

heb-373:1:7

Important rules: - site_id is a stable string per deployment site. - UUID must always be stored in lowercase. - Major and minor are plain integers (no zero-padding). - Never change a beakin's major/minor after it has been provisioned — any server-side records use this key as their identifier.


Export and Import the Registry

The app's local registry can be exported to JSON for backup, migration to a new device, or auditing.

Export: Settings → Provisioning → Export Registry

Saves a timestamped JSON file to your device's Documents folder. Share or copy it as needed.

Import: Settings → Provisioning → Import Registry

Loads a previously exported JSON file. Imported records merge with existing ones using the standard layer precedence — local edits always win.


Common Provisioning Scenarios

Replacing a failed beakin

The replacement board should flash firmware with the same major/minor as the failed unit. The app already has the provisioning record; you only need to re-do the GATT write to the new device:

  1. Flash replacement board with the same beacons.yaml entry.
  2. Power it on in range of your phone.
  3. In the app, the beakin appears as provisioned-pending (existing record, no confirmed write to new hardware).
  4. Tap Retry write to push the config to the replacement board.

Moving a beakin to a new location

  1. Update beacons.yaml with the new planogram fields.
  2. Regenerate tasks and reflash firmware (so the OLED shows the correct location).
  3. In the app, tap Reconfigure → update the location fields → Mark as Provisioned.

Setting up a batch of beakins

For a bulk deployment, set up all entries in beacons.yaml before going to the store:

  1. Add all devices to beacons.yaml with correct serials, labels, and location data.
  2. Flash all boards: Tasks: Run Task → 🔌 Flash All.
  3. Generate the provisioning seed: npm run provisioning:seed:generate.
  4. Build and deploy the updated app.

In the field, the app will show all expected beakins in the Find screen with seed-provided names. Walk the floor and tap Mark as Provisioned for each one to confirm the GATT write.

Adding a gateway

Gateways are provisioned differently from beacons — they use WiFi and MQTT credentials set at flash time, not through the app:

  1. Add a gateway entry to beacons.yaml with role: gateway and env: xiao_esp32c6_gateway.
  2. Export WiFi and MQTT credentials in your shell:
    export WIFI_SSID="YourNetwork"
    export WIFI_PASS="YourPassword"
    export MQTT_BROKER="192.168.1.50"
    export MQTT_PORT="1883"
    
  3. Run the gateway flash task: Tasks: Run Task → 📡 flash gateway: <label>.
  4. The gateway connects to WiFi on boot and begins publishing beacon sightings over MQTT.

Troubleshooting

Beakin stays "provisioned-pending" after tapping "Mark as Provisioned"

  • Move closer to the beakin (within 2–3 meters).
  • Confirm BLE is on and the app has Bluetooth permission.
  • Check the serial log — look for GATT write callbacks and any ERR: responses.
  • If the error repeats, try a factory reset and re-provision from scratch.

Beakin shows wrong label in the app

The app resolves labels from multiple layers. The most likely causes: - Wrong seed: beacons.yaml was updated but the seed was not regenerated. Run npm run provisioning:seed:generate and rebuild the app. - Local override present: a previous operator edit on the phone/tablet overrides the seed. Tap Reconfigure and clear or correct the label field.

Two beakins show the same name

Major/minor values may have been accidentally duplicated in beacons.yaml. Check that every device has a unique major/minor pair within the same site_id. Run the validator:

cd beakin-fw
python3 scripts/validate_beacons.py

Import fails or registry looks wrong after import

  • Confirm the imported JSON was exported from a Beakin app — the format is not compatible with other tools.
  • If the registry looks inconsistent, clear local storage (Settings → Provisioning → Clear Local Registry) and re-import.