Beakin — User Guide¶
A practical reference for operating, monitoring, and maintaining a Beakin deployment.
← Handbook home · Provisioning Guide
Table of Contents¶
- System Overview
- The Fleet Config File
- Hardware: Boards and Roles
- Status LED Patterns
- Connecting a Beakin via USB
- Flashing Firmware
- Monitoring Serial Output
- Identifying a Beakin
- Using the Mobile App
- Using the Server Dashboard
- Common Tasks
- Troubleshooting
System Overview¶
A Beakin deployment consists of:
| Component | Role |
|---|---|
| Beakin (beacon HW) | Broadcasts its identity (UUID + major + minor) over BLE from a fixed location. May include an OLED display and battery. |
| Gateway (gateway HW) | A scanning version of the beakin board — listens for nearby beakins and forwards sightings to the server over MQTT. Requires WiFi. |
| Mobile app | iOS/Android field tool for scanning, identifying, and provisioning beakins. |
| beakin-server | Raspberry Pi backend — central registry, live dashboard, and MQTT event store. Optional for basic operation. |
Most day-to-day tasks involve three activities: flashing firmware onto a board, provisioning its location identity via the app, and monitoring that it is advertising correctly.
The Fleet Config File¶
beakin-fw/scripts/beacons.yaml is the source of truth for your physical fleet. Every board that you own should have an entry here.
Reading an entry¶
- serial: 98:A3:16:8F:F6:D8 # board's hardware ID (MAC or USB serial)
label: Kids Vitamins # human-readable location name
env: xiao_esp32c6 # board type (determines firmware build)
site_id: "heb-373" # deployment site namespace
power_profile: performance # performance | balanced | endurance
antenna: external # internal (default) | external (C6 only)
major: 1 # iBeacon major value — opaque device ID
minor: 1 # iBeacon minor value — opaque device ID
area: "01" # planogram area code
aisle: 23 # aisle number
side: "B" # aisle side
section: 3 # section within aisle/side
shelf: 8 # shelf level
psa_description: "Aisle 23" # display description
display:
type: oled
width: 128
height: 64 # 32 = small display, 64 = large display
battery:
connected: auto # auto | yes | no
capacity_mah: 1000
Key points:
serialis the unique identifier for the physical board. Never change it once set.majorandminorare opaque integers — they identify the device, not its location. Location is tracked separately in the provisioning layer.site_idmust match the site namespace used in the mobile app and server.- After any change to this file, regenerate VS Code tasks (see Regenerating Tasks).
Supported board types (env)¶
| Value | Board |
|---|---|
xiao_esp32c6 |
XIAO ESP32-C6 (default beacon board) |
xiao_esp32s3 |
XIAO ESP32-S3 |
xiao_nrf52840_sense |
XIAO nRF52840 Sense |
xiao_esp32c6_gateway |
XIAO ESP32-C6 configured as gateway |
Hardware: Boards and Roles¶
Beacon boards¶
All three XIAO variants can act as beacons. The ESP32-C6 is the default because it offers WiFi 6, external antenna support, and the best cost-to-performance ratio for a beacon role.
| Board | BLE TX Power | Best for |
|---|---|---|
| ESP32-C6 | up to +9 dBm | Primary beacon — good range, supports external antenna |
| ESP32-S3 | up to +9 dBm | General beacon; slightly more flash/RAM |
| nRF52840 Sense | up to +4 dBm | Battery-sensitive deployments; has onboard IMU |
Gateway boards¶
Gateways run a different firmware role — they scan for nearby beakins and publish sighting events over MQTT. Only ESP32 boards support the gateway role (WiFi is required). Use env: xiao_esp32c6_gateway in beacons.yaml.
Gateways require WiFi credentials at flash time. Set these in your shell environment before running the gateway flash task:
export WIFI_SSID="YourNetworkName"
export WIFI_PASS="YourPassword"
export MQTT_BROKER="192.168.1.50"
export MQTT_PORT="1883"
Status LED Patterns¶
Every board has a status LED that shows what the firmware is doing — no serial monitor needed.
| Pattern | What it means |
|---|---|
| Fast blink (5 Hz) | Booting — running startup checks |
| Medium blink (2 Hz) | Initializing BLE stack |
| Short pulse + long pause | Healthy — advertising iBeacon packets normally |
| Triple flash + pause | Error — check serial output for details |
On the nRF52840 Sense, the RGB LED adds color coding:
| Color | State |
|---|---|
| 🔵 Blue | Booting |
| 🩵 Cyan | BLE initializing |
| 🟢 Green | Advertising (healthy) |
| 🔴 Red | Error |
On ESP32 boards, there is only a single amber LED, so only the blink pattern matters.
Tip: If you see the error pattern (triple flash), connect over USB and open the serial monitor to read the failure reason.
Connecting a Beakin via USB¶
Use a data-capable USB-C cable. Charge-only cables will not work.
To list all connected boards and their serial IDs:
Example output:
Product Name Serial Port
XIAO-ESP32C6 98:A3:16:8F:F6:D8 /dev/cu.usbmodem11401
XIAO-ESP32S3 84:FC:E6:78:25:58 /dev/cu.usbmodem11501
Use the Serial column value when adding new devices to beacons.yaml.
nRF52840 bootloader mode¶
If an nRF52840 board fails to upload normally:
- Double-press the RESET button quickly.
- The board appears as a USB mass storage drive.
- Then retry the flash task.
Flashing Firmware¶
Using VS Code tasks (recommended)¶
After generating tasks (see below), open the VS Code command palette:
Per-device task labels follow this pattern:
flash: Kids Vitamins [xiao_esp32c6 / sn:98:A3...]dev: Kids Vitamins [...]— flash then open serial monitor
Aggregate tasks:
⚡ Build All— compile all environments🔌 Flash All— flash every device inbeacons.yaml🚀 Dev All (flash then monitor)— flash all, then tail all serial logs
Regenerating Tasks¶
Run this after any change to beacons.yaml:
This rewrites .vscode/tasks.json with up-to-date per-device tasks that resolve USB ports dynamically.
Using the CLI directly¶
To build one board type:
To flash manually (you need to know the port):
Monitoring Serial Output¶
Serial monitor baud rate: 115200
Via VS Code task: monitor: <label>
Via CLI:
What to look for at boot¶
A healthy boot log looks like:
[APP] Booting...
[APP] Board: XIAO ESP32-C6
[APP] Power profile: performance
[APP] UUID: f7826da6-4fa2-4e98-8024-bc5b71e0893e
[APP] Major: 1 Minor: 1
[BLE] Initializing...
[BLE] Advertising started
Log prefixes:
[APP]— application layer[BLE]— Bluetooth stack[POWER]— power profile[DEMO]— demo scenario (if applicable)[MQTT]— gateway MQTT events
Identifying a Beakin¶
Sometimes you need to confirm which physical board corresponds to which beacons.yaml entry — especially when boards are installed in the field.
Via USB (serial identify)¶
# Blink the LED on a specific board
python3 scripts/identify.py --serial 98:A3:16:8F:F6:D8
# Blink all connected boards sequentially
python3 scripts/identify.py --all
The target board's LED will flash rapidly for a few seconds so you can spot it.
Via the mobile app (BLE identify)¶
From the Find screen in the Beakin app, tap a beakin in the list, then tap ⚡ Identify. The board's LED flashes briefly to confirm which physical unit was contacted.
Using the Mobile App¶
The Beakin mobile app (iOS and Android) is the field tool for scanning, identifying, and provisioning beakins.
Find screen¶
- Lists all beakins visible via BLE scan.
- Shows signal strength (RSSI) per device.
- Color-coded signal bars: 🟢 excellent / 🟡 good / 🟠 fair / 🔴 weak.
- Provisioned beakins show their label and location. Unprovisioned ones appear as their major/minor values until provisioned.
Beacon detail screen¶
Tap any beakin in the list to see:
- Signal strength and TX power
- UUID, major, and minor
- Provisioning status and assigned location fields
- Identify and provision actions
Provisioning status badges¶
| Badge | Meaning |
|---|---|
| Unprovisioned | No name or location assigned yet |
| Draft | Form saved locally; not yet written to the device |
| Provisioned (pending) | Saved locally; waiting to write to device hardware |
| Provisioned | Device and app registry are in sync |
See Provisioning Guide for full step-by-step flows.
Using the Server Dashboard¶
When a beakin-server instance is running on your Raspberry Pi 5, access the web dashboard at:
The dashboard shows:
- Live gateway sighting events via MQTT
- Beacon registry — all provisioned devices and their locations
- Gateway health — WiFi status, beacon count, last-seen timestamps
- Battery telemetry for devices with battery monitors enabled
The server is deployed by running the 🚀 Deploy VS Code task from the beakin-server folder, or:
Common Tasks¶
Add a new beakin to the fleet¶
- Plug in the new board via USB.
- Run
python3 scripts/list_mcus.pyto get the serial ID. - Add an entry to
beacons.yamlwith the serial, label, site_id, env, major, minor, and location fields. - Run
./scripts/gen_tasks.shto regenerate tasks. - Flash firmware using the new per-device task.
- Open the mobile app and provision the beakin from the Find screen.
Full details: Provisioning Guide → Adding a New Beakin.
Replace a failed beakin¶
- Flash the replacement board using the same
beacons.yamlentry (same major/minor). - The provisioning registry in the app already has the location data — the replacement board doesn't need to be re-provisioned in the app unless the GATT write to NVS failed previously.
- If the GATT write is needed, tap Retry write on the beakin's detail screen.
Change a beakin's location¶
- Update the planogram fields (
aisle,side,section,shelf, etc.) inbeacons.yaml. - Re-run
./scripts/gen_tasks.sh. - Reflash firmware (the planogram fields are compiled in as display/status data).
- In the app, tap Reconfigure on the beakin and update the location fields, then tap Mark as Provisioned.
Check battery status¶
Battery voltage is logged on the serial monitor and (if MQTT is configured) sent to the server. For a quick field check, connect over USB and open the monitor — battery voltage is logged periodically at the configured log_interval_ms.
Troubleshooting¶
Board not found in list_mcus.py¶
- Try a different USB-C cable (must be data-capable).
- Check that the board appears in System Information → USB.
- On nRF52840: double-press RESET to enter bootloader mode.
Upload fails ("port not found")¶
Port detection uses the serial ID. If the port changes after a reflash, the script will re-resolve it automatically on next run. If it still fails:
- Confirm the board is connected:
ls /dev/cu.usbmodem* - Check
beacons.yamlhas the correct serial.
Beakin not visible in app¶
- Confirm the UUID in
config/beakin.config.tsin the app matches the UUID compiled into firmware (include/config.h→BEACON_UUID). - Confirm BLE is enabled on the phone/tablet.
- Check the serial log — look for
[BLE] Advertising started.
Serial log shows [BLE] Error¶
BLE init failures are usually caused by:
- BLE stack already initialized (reflash the firmware).
- Insufficient NVS space (rare; contact the engineering team).
nRF52840 upload hangs or fails¶
DFU uploads are serialized. If a previous task was force-killed, stale lock files may remain:
Then retry the flash task.