Files
James RichandClaude Fable 5.1 3022a37768 Add the BLE-GATT mesh-peer transport: a phone connects to the node as a mesh peer
The SIG-Mesh "GATT proxy" role: the node runs a GATT server on a private
service, phones connect to it as centrals and exchange whole mesh frames over a
write/notify characteristic, without a phone-API session. Point-to-point where
LoRa and the advertisement transport are one-to-many; a broadcast is N notifies.

Two halves:

- BLEGattMeshHandler (platform-neutral, built into the native suite): fragment
  framing shared byte-for-byte with the node-kmp client, bounded reassembly
  (per-peer and per-in-flight caps, expiry), the ingress guards the UDP and
  advertisement transports already apply (validate-before-relay, drop senderless
  / self-claimed / impossible-hop packets, strip local-only metadata), a per-peer
  TX ring, and no-echo-back-to-the-arrival-peer via a small (from,id)->peer table.

- ESP32BLEGattMesh (NimBLE): its own connectable advertising set on instance 2
  carrying the service UUID, per-connection notifies, an MTU-derived chunk size,
  and a GAP handler chained ahead of the Arduino wrapper's so the server's
  connection/MTU/subscription bookkeeping covers these links too. A mesh-peer
  disconnect is gated out of the PhoneAPI session teardown.

Registry-gated on the new BLE_GATT_PEER protocol flag, so it carries outbound
packets only while a phone is being served as a peer. The sdkconfig bump that the
second connection needs (CONFIG_BT_NIMBLE_MAX_CONNECTIONS=2, CONFIG_BT_CTRL_BLE_MAX_ACT=6)
lands here with the service rather than ahead of it. Protobufs pointer bumped for
the TRANSPORT_BLE_GATT and BLE_GATT_PEER enums; generated headers regenerated.

Proven: native suite 1418/1418 (26 new cases for this transport); heltec-v3
(ESP32-S3) builds and, with WiFi off, brings the service up and advertises on
instance 2 with no OOM / NimBLE 519 / crash at the 2-connection config.
Not yet proven: a phone connecting as a mesh peer and a frame crossing device to
phone (bench-gated); ESP32-C3 and nRF52 are unbuilt.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 22:02:16 -05:00
..