Skip to content

Add device name suffix with BLE address for counter identification - #16

Merged
MacNite merged 2 commits into
mainfrom
claude/hivetraffic-mac-device-names-80v2ln
Aug 24, 2026
Merged

MacNite merged 2 commits into
mainfrom
claude/hivetraffic-mac-device-names-80v2ln

Conversation

@MacNite

@MacNite MacNite commented Aug 24, 2026

Copy link
Copy Markdown
Owner

Summary

Counters now advertise as HiveTraffic-AB:12 instead of BeeCounter, where the suffix is the last two bytes of the counter's own BLE address. This makes multiple counters in range distinguishable in a scan list without requiring users to open detail views to match physical devices to scan entries.

Key Changes

  • New header include/device_name.h: Pure C++ header that builds the advertised BLE name by appending the last two bytes of the device's address (in NimBLE little-endian format) to the product name. Includes comprehensive documentation on byte order, address selection, and failure modes.

  • Comprehensive test suite test/test_device_name/test_device_name.cpp: 8 test cases covering byte order correctness, leading zero preservation, uppercase hex rendering, all 65536 possible suffix values, fallback behavior when no address is available, buffer overflow protection, capacity validation, and uniqueness across devices.

  • Updated src/ble_link.cpp:

    • Replaced hardcoded BLE_DEVICE_NAME with dynamic deviceName buffer built from the controller's address
    • Added buildDeviceName() function that runs after NimBLEDevice::init() to construct the suffixed name
    • Updates both the advertised name and the GAP Device Name characteristic to keep them in sync
    • Gracefully falls back to unsuffixed HiveTraffic if address cannot be read
    • Updated logging to display the actual advertised name
  • Documentation updates:

    • docs/ble-mode.md: Explains the new naming scheme, address suffix format, and how it survives reboots/updates
    • Firmware/README.md: Documents the test coverage and design rationale
    • README.md: Updated user-facing description of BLE advertisement
  • Test infrastructure: Updated test/run_tests.sh to build and run the new device_name tests

  • Version bump: 0.3.0 → 0.3.1

Implementation Details

  • The suffix uses only the last two bytes of the address (val[1]:val[0] in NimBLE order), creating a 1-in-65536 collision probability for factory addresses—an accepted tradeoff documented in tests
  • Buffer overflow is prevented by refusing to write truncated names rather than silently truncating, since a partial suffix would identify the wrong device
  • The address comes from the ESP32-C6's factory eFuse MAC, requiring no per-device provisioning and surviving reboots, reflashes, and OTA updates
  • A static_assert in the header ensures the longest possible name fits within the 31-byte legacy scan response budget

https://claude.ai/code/session_01VXfRikN5G4jyYqkSLeo9nf

claude added 2 commits August 24, 2026 09:44
Every counter advertised the identical local name "BeeCounter", so an apiary
with several in range produced a scan list of identical rows: picking the right
one for pairing, or working out which of three on a bench is being flashed,
meant opening a scanner's detail view and reading addresses.

The advertised name is now built at boot as "HiveTraffic-AB:12", where the
suffix is the last two bytes of the counter's own BLE address rendered the way
a scanner prints them. NimBLE settles its own-address type before init()
returns and both the reported address and the advertised packets follow it, so
the suffix is literally the tail of the address shown beside the entry. On the
ESP32-C6 that address is the factory eFuse MAC: unique per unit and stable
across reboots, reflashes and OTA updates, with nothing to provision per
device. The same string is pushed to the GAP Device Name characteristic, so a
client that connects and reads it agrees with the scan list.

The base name changes from "BeeCounter" to the product's own name in the same
move; the former was a leftover from the easy-bee-counter days. Nothing on the
wire keys off either: HiveHub connects by the MAC paired in its portal and
never matches on the name, the measurement document is untouched, and the
protocol revision does not move. The service UUID and the beecounter_proto
namespace keep their names, being wire identifiers rather than display text.

The string itself lives in a new Arduino-free include/device_name.h, pinned by
test/test_device_name/ on a host compiler, because every way of getting it
wrong is quiet: a reversed suffix, a dropped leading zero or a truncation all
produce a name that still looks like a name while pointing at the wrong device,
and noticing on hardware requires already knowing the address you were looking
for. The header static_asserts its longest form against the 31-byte legacy scan
response, which the name now fills 19 of.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VXfRikN5G4jyYqkSLeo9nf
The name builder used a `static const char HEX[]` lookup table, and Print.h
defines `HEX` as 16. Every host check passed and the firmware build failed with
"expected unqualified-id before numeric constant" — the same collision class
this repo already hit once, where an enumerator named DISABLED met
esp32-hal-gpio.h's `#define DISABLED 0x00`.

The table is now `hex_digits`. Lower case is the actual fix: Arduino's macros
are all-caps, so a lower-case identifier cannot collide with one no matter
which of its few hundred macros a future header pulls in.

test/test_device_name/ grows the macro block test_idle_state.cpp already
carries, extended with the number-base macros (DEC/HEX/OCT/BIN) that are the
ones to bite a header doing string formatting. With them defined ahead of the
include, this exact failure now surfaces on a host compiler in under a second
instead of two and a half minutes into a firmware build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VXfRikN5G4jyYqkSLeo9nf
@MacNite
MacNite merged commit f2408f2 into main Aug 24, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants