Files
tactility/.claude/skills/tactility-bluetooth/references/scan-and-reconnect.md
T
Adolfo Reyna 12035f2f39 chore: move firmware skills in-repo + AGENTS.md
- Migrates tactility-firmware and tactility-bluetooth from
  ~/.hermes/skills/ into .claude/skills/ for repo co-location
- Adds AGENTS.md with local workstation context, board table,
  board-direct build rule, Hermes PYTHONPATH pitfall, common
  Tactility pitfalls, and in-repo skill index

Refs: personal Gitea mirror
2026-07-17 09:51:08 -04:00

2.6 KiB

BLE Scan & Reconnect Fixes

Problem 1 — Nameless Filter Dropped Bonded Keyboards

Location

Platforms/platform-esp32/source/drivers/bluetooth/esp32_ble_scan.cpp:ble_gap_disc_event_handler

Old

if (!found && record.name[0] != '\0' && ctx->scan_count < 64) { store }

Fixed

if (!found && ctx->scan_count < 64) {
  // Store ALL unique advertisers, not only named
  // Bonded keyboards (e.g. Fosmon combo) may advertise with only Appearance+flags or directed RPA without name
  ctx->scan_results[ctx->scan_count]=record;
  ctx->scan_addrs[ctx->scan_count]=disc.addr;
  ctx->scan_count++;
  should_publish = true; // publish even nameless for cache
}
if (found) {
  // also update addr_type for RPA rotation
  ctx->scan_addrs[i]=disc.addr;
}

Impact

  • getScanResults() now includes unknowns → UI shows "Unknown (aabbcc...)" entries; useful debug. Can filter weak RSSI later.
  • cacheScanAddr() / getCachedScanAddrType() now works for nameless adv, so hidHostConnect gets correct type.

Problem 2 — Addr Type PUBLIC vs RANDOM

Symptom

ble_gap_connect fails rc=2 BLE_HS_EALREADY or other when using PUBLIC for device that uses RANDOM RPA.

Fix in BluetoothHidHost.cpp:hidHostConnect

  • Lookup cache: log type
  • Try PUBLIC -> if fail, retry RANDOM
  • If cached type was RANDOM and both fail, retry PUBLIC
  • Increase timeout 5000 -> 8000ms
  • Log final addr_type

Problem 3 — Single Scan Misses Wake Window

Symptom

Fosmon sleeps, stops advertising. Wakes on keypress with directed adv ~30s. If Tactility scanned just before wake, misses.

Fix

Add retry timer:

static esp_timer_handle_t hid_autoconn_retry_timer = nullptr;
static void hidAutoConnRetryCb(void*) {
  if (hidHostIsConnected()) return;
  if (!bluetooth_is_scanning(dev)) bluetooth_scan_start(dev);
}

In autoConnectHidHost() when not found but autoConnect peers exist:

esp_timer_start_once(hid_autoconn_retry_timer, 3*1e6);

Stopped in hidHostConnect() when connecting, and on successful ready chain.

Also bt_event_bridge SCAN_FINISHED already calls autoConnectHidHost, so loop: scan -> not found -> schedule 3s -> scan -> etc.

Files Changed

  • esp32_ble_scan.cpp inclusive cache + addr update
  • BluetoothHidHost.cpp dual addr fallback + retry timer + logging
  • No change needed in Bluetooth.cpp bt_event_bridge, but benefits from inclusive cache

Remaining TODO

  • Manual disconnect with autoConnect=true still retriggers immediate rescan (TODO in code "Fix auto reconnect if user manually disconnects"). Could require user to toggle Auto-connect switch off, or add 10s cooldown.