feat: UWB tag BLE configuration interface (Issue #690) #692

Merged
sl-jetson merged 1 commits from sl-uwb/issue-690-tag-ble-config into salty/uwb-tag-display-wireless 2026-03-18 10:48:20 -04:00
Collaborator

Summary

Adds BLE GATT config server so the UWB tag can be configured from a phone app (nRF Connect compatible).

Advertising:

  • Device name UWB_TAG_XXXX — last 4 hex digits of MAC, unique per board
  • Service UUID: 12345678-1234-5678-1234-56789abcdef0

Characteristics:

UUID ...abcdef Properties Purpose
Config 1 READ + WRITE Read/write JSON config
Status 2 READ + NOTIFY "+OK" or "+ERR:reason" after write

Config JSON keys:

Key Type Range Applied
sleep_timeout_s int 5..3600 immediate
display_brightness int 0..255 immediate (SSD1306 contrast)
tag_name string max 16 NVS only
uwb_channel int 1..7 next boot
ranging_interval_ms int 50..2000 immediate
battery_report bool immediate

Example write (nRF Connect):

{"display_brightness":180,"ranging_interval_ms":200,"battery_report":true}

Persistence: NVS namespace uwb_cfg — survives power cycle.

Partition: huge_app.csv added — BLE + WiFi + DW1000 requires ~1.76MB. Build: 55.8% flash, 18.1% RAM.

Test plan

  • Flash tag, verify serial: [ble] Advertising as "UWB_TAG_XXXX"
  • Open nRF Connect, scan → see "UWB_TAG_XXXX" device
  • Connect, find service 12345678-...-abcdef0
  • Read config char → verify JSON with all 6 keys
  • Write {"display_brightness":50} → Status notifies "+OK", OLED dims
  • Write {"display_brightness":300} → Status notifies "+ERR:display_brightness out of range"
  • Power cycle → reconnect, read config → brightness=50 persisted
  • Verify anchor firmware (esp32/uwb_anchor/) unchanged

🤖 Generated with Claude Code

## Summary Adds BLE GATT config server so the UWB tag can be configured from a phone app (nRF Connect compatible). **Advertising:** - Device name `UWB_TAG_XXXX` — last 4 hex digits of MAC, unique per board - Service UUID: `12345678-1234-5678-1234-56789abcdef0` **Characteristics:** | UUID | ...abcdef | Properties | Purpose | |---|---|---|---| | Config | 1 | READ + WRITE | Read/write JSON config | | Status | 2 | READ + NOTIFY | "+OK" or "+ERR:reason" after write | **Config JSON keys:** | Key | Type | Range | Applied | |---|---|---|---| | `sleep_timeout_s` | int | 5..3600 | immediate | | `display_brightness` | int | 0..255 | immediate (SSD1306 contrast) | | `tag_name` | string | max 16 | NVS only | | `uwb_channel` | int | 1..7 | next boot | | `ranging_interval_ms` | int | 50..2000 | immediate | | `battery_report` | bool | — | immediate | **Example write (nRF Connect):** ```json {"display_brightness":180,"ranging_interval_ms":200,"battery_report":true} ``` **Persistence:** NVS namespace `uwb_cfg` — survives power cycle. **Partition:** `huge_app.csv` added — BLE + WiFi + DW1000 requires ~1.76MB. Build: 55.8% flash, 18.1% RAM. ## Test plan - [ ] Flash tag, verify serial: `[ble] Advertising as "UWB_TAG_XXXX"` - [ ] Open nRF Connect, scan → see "UWB_TAG_XXXX" device - [ ] Connect, find service `12345678-...-abcdef0` - [ ] Read config char → verify JSON with all 6 keys - [ ] Write `{"display_brightness":50}` → Status notifies "+OK", OLED dims - [ ] Write `{"display_brightness":300}` → Status notifies "+ERR:display_brightness out of range" - [ ] Power cycle → reconnect, read config → brightness=50 persisted - [ ] Verify anchor firmware (`esp32/uwb_anchor/`) unchanged 🤖 Generated with [Claude Code](https://claude.com/claude-code)
sl-jetson added 1 commit 2026-03-18 10:32:31 -04:00
Adds BLE GATT config server to uwb_tag firmware:

Advertising:
- Device name "UWB_TAG_XXXX" (last 4 hex digits of WiFi MAC)
- Service UUID: 12345678-1234-5678-1234-56789abcdef0
- Compatible with nRF Connect app

Characteristics:
- Config (R/W) UUID: ...abcdef1
  Read: returns current config as JSON
  Write: accepts partial JSON with any config keys
- Status (R/N) UUID: ...abcdef2
  Notifies "+OK" or "+ERR:<reason>" after each write

Config keys (NVS-persisted, applied immediately unless noted):
  sleep_timeout_s      [5..3600]   OLED display timeout
  display_brightness   [0..255]    OLED contrast (SSD1306_SETCONTRAST)
  tag_name             [max 16]    friendly name
  uwb_channel          [1..7]      UWB RF channel (next boot)
  ranging_interval_ms  [50..2000]  minimum ranging poll interval
  battery_report       bool        include battery flag in ESP-NOW packets

Partition: huge_app.csv (3MB app) — BLE + WiFi + DW1000 needs ~1.76MB
Build: 55.8% flash, 18.1% RAM (SUCCESS)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
sl-jetson force-pushed sl-uwb/issue-690-tag-ble-config from 1eda0c12a4 to 8ee9b4cca9 2026-03-18 10:48:01 -04:00 Compare
sl-jetson merged commit 61939c6d2e into salty/uwb-tag-display-wireless 2026-03-18 10:48:20 -04:00
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: seb/saltylab-firmware#692
No description provided.