View this page on MeshCore Docs.
Heltec V4 preview4 Bluetooth/OLED regression validation
Date: 2026-10-02. These are observations on one physical Heltec V4.3 OLED,
not qualification of every board or phone. The preview4 images are local,
unreleased builds with uncommitted changes on keymindCascade at
7324bf06efef236009dac2d507775fa4e19bc856.
Target and method
- Host: MercerWoodMesh Raspberry Pi, built-in BlueZ Bluetooth controller.
- Target: Heltec V4.3 OLED, ESP32-S3 revision 0.2, 16 MB flash, 2 MB PSRAM;
exact USB serial
44:1B:F6:69:CF:98. - Version under test:
v1.17.1.8-preview4, build 02-Oct-2026, USA Cascade Full Companion, OLED, no expansion, NimBLE-Arduino 2.5.1. - Diagnostic environment:
heltec_v4_companion_pairing_ui_hil_preview4inplatformio.heltec-v4-preview4.ini. - Diagnostic application SHA-256:
df0c109e7c3e99e43ec388a4017da8971f41572f51afeac779cddc4a56e69d14. - Helper:
tools/hil/v4_pairing_stealth.py; Linuxbleak,dbus-fast,pyserial, target-restricted passkey agent. Test PIN 246810, deliberately different from NimBLE's 123456 callback sentinel.
A complete, hash-checked 16 MB original flash backup was taken first. Only
otadata and the application were written for the temporary diagnostic image;
the bootloader, partition table, NVS and SPIFFS were retained. No other Pi radio
was flashed. The helper did not request LoRa transmissions; ordinary background
radio activity was not disabled.
COMPANION_PAIRING_UI_HIL is an opt-in diagnostic macro, absent from production
builds. It records actual startup phases, display power/pairing/USB state, public
identity, and the real 1024-byte SSD1306 framebuffer. It does not access the
private key. Frame capture occurred during an actual outstanding passkey
request, not a manually invoked firmware callback.
Observed hardware results
| Check | Result |
|---|---|
| Fresh pairing with a non-default PIN | Passed twice: exactly one actual passkey request per fresh pairing; BlueZ reported Paired and Bonded. |
| PIN display while USB remains connected | Passed twice: display on, pairing active, USB present, and captured frame containing PAIR PIN 246810. This verifies the display driver's real framebuffer and wake state, not an optical photograph. |
| Protected BLE transport | Passed: MTU 179, 82-byte device-info response and 176-byte ATT command payload, live CLI/status responses, zero core error flags. |
| Custom MAC with stealth | Passed: fresh discovery/pairing, live bonded-peer-only advertising status, bonded reconnect with no new PIN, then USB-commanded reboot and another bonded reconnect with no new PIN. |
| Saved random MAC | Passed: USB-commanded reboot retained its address with stealth enabled. |
random-after-connect, unused boot |
Passed: reboot over USB, without BLE authentication, retained the address. |
random-after-connect, authenticated boot |
Passed: actual authenticated BLE connection armed the next boot; address stayed unchanged during that session and changed on the following USB reboot. The new address was discoverable with stealth retained. |
random-every-boot |
Passed: two successive USB-commanded boots used different addresses, with stealth enabled. |
| Saved identity startup | Passed: Starting/Loading phases only, no Generating/Saving phase. The same public identity was retained throughout the run. |
The suite finished with suite_passed, six observed application addresses,
two captured OLED frames, and identity_preserved: true. An earlier harness
attempt stopped because it did not recognize a terminal prompt immediately
followed by a diagnostic line; the parser was corrected and the complete suite
rerun. This was not a BLE pairing failure.
Stealth on ESP32 uses minimal, unnamed, allowlisted advertising after pairing; it is not radio invisibility. Bonded reconnection and policy/rotation behavior were tested here. Actual advertising-payload capture and rejection of an unbonded second central were not part of this run.
Original target restored
After the suite, the complete original 16 MB image was written back. Esptool verified the flash data hash. Live serial readback then confirmed:
- Original version:
v1.18.0.1-halo-keymind-cascade-dev-app-wifi-test-6f6d1a2a, protocol 14, build 01-Oct-2026. - Original board and public identity unchanged.
- Bluetooth on, factory/default MAC, stealth off.
- Original default Bluetooth name, USB display mode
button-pairing, and USB logging off.
The full backup remains private on the Pi. Raw diagnostic logs and captured OLED pixels remain in the ignored local preview4 output folder; neither the backup nor unreviewed radio logs are published. Only test-created BlueZ device records were removed by the helper.
Automated regression coverage and builds
- 117 targeted native cases passed across identity generation, display layout, serial routing, and Companion preferences. This was not the entire native suite.
- 39 Python cases passed across the real NimBLE adapter, pairing UI, saved/new identity startup, startup display, display power, MAC/stealth contracts, settings persistence, inbox rendering, preference transaction, and Bluetooth control suites. Executable C++ fixtures use the production implementation; sanitizer-enabled fixtures also passed.
- The unit-test workflow now includes the real NimBLE callback dispatch, USB-connected pairing display, identity-startup, and startup-screen suites. No GitHub run was triggered for these uncommitted changes.
- Production V3 and V4 Full Companion preview4 builds passed linked-memory qualification. Available/required internal heap: V3 200,144/182,016 bytes; V4 252,152/177,920 bytes. Diagnostic V4: 252,136/177,920 bytes.
The NimBLE regression fixture reproduces the pinned library's dispatch rule:
a non-default static passkey bypasses onPassKeyDisplay(). Firmware now leaves
NimBLE's sentinel at 123456 and returns the actual configured PIN through that
callback, preserving authentication while notifying the UI. Tests cover random
and saved PINs, USB coexistence, button wake/navigation, disabled display/BLE,
saved identity, generation, persistence failures, and removal of the generation
label once generation finishes.
Remaining hardware gates
- Physical Heltec V3, including its user button; the Pi board here was V4.
- Optical OLED inspection and physical button gestures (covered in executable host fixtures, not remotely actuated on this board).
- Android/iOS MeshCore apps, privacy-address reconnection, and an unbonded second physical central.
- Actual post-pairing advertising payload capture.
- All-power-removed cold boot; this run used commanded reboots only.
- Destructive missing/corrupt identity and bond/write-failure injection on hardware; these branches were exercised by host fixtures without erasing the real node's identity.