mirror of
https://github.com/meshtastic/firmware.git
synced 2026-09-28 17:29:06 -04:00
The transport connected and subscribed but never delivered a frame to the phone. Four things were wrong, found on the bench and fixed here: - Peers were only registered from onSubscribe/onWrite, which never fired for a central that connected through the phone-API advertising instance. Register every inbound link from the server's own onConnect callback (ESP32BLEGattMesh:: onConnect, hooked in NimbleBluetoothServerCallback::onConnect), which fires regardless of advertising instance, and also handle the raw BLE_GAP_EVENT_SUBSCRIBE in our GAP callback. - The characteristic's value handle never resolved (getHandle() == 0xFFFF): the wrapper only resolves handles inside BLEServer::start(), which it triggers from BLEAdvertising::start(). This firmware advertises through the raw ble_gap_ext_adv API and never calls the wrapper's advertising, so force server->start() after registering the service. - Notifications went through the raw NimBLE ble_gatts_notify_custom() with an esp_gatts handle, which returns success but delivers nothing. Send through the wrapper's own BLECharacteristic::notify() - the exact path the phone-API's fromNum uses. Proven on hardware: an Android client (node-kmp monitor) subscribed to the mesh-peer service receives frames the v3 originates and relays - rx counter advanced with a frame from the v3's own node number over BLE GATT. Still spike-quality: verbose diagnostic logs remain (revert), notify() broadcasts to all subscribers rather than excluding the arrival peer (dedup covers it for now), and the C3/nRF52 bring-up is unbuilt. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>