fix(bluetooth): auto-reconnect to paired devices after reboot
- Auto-set enableOnBoot=true when BT is enabled or device is paired,
so board restarts with BT on and can reconnect
- Make RADIO_STATE_ON handler non-exclusive: scan for HID Host,
start HID Device, SPP and MIDI all independently (was else-if)
- Improve HID Host auto-connect for RPA: direct addr match, name-match
fallback, and direct connect to stored identity using resolving list
- Persist addrType in PairedDevice file for more reliable reconnection
- Add verbose logging for loadAll/save to debug missing files
Fixes issue where board restart did not reconnect to previously
connected BT devices. Also preserves f94cc160 fullscreen flag feature.
This commit is contained in:
@@ -115,6 +115,15 @@ static void bt_event_bridge(Device*, void* /*context*/, BtEvent event) {
|
||||
case BT_RADIO_STATE_ON:
|
||||
getMainDispatcher().dispatch([] {
|
||||
auto peers = settings::loadAll();
|
||||
LOG_I(TAG, "RADIO ON: loaded %d paired peers", (int)peers.size());
|
||||
for (const auto& p : peers) {
|
||||
LOG_I(TAG, " - peer %s name='%s' profile=%d auto=%d type=%d",
|
||||
settings::addrToHex(p.addr).c_str(),
|
||||
p.name.c_str(),
|
||||
p.profileId,
|
||||
(int)p.autoConnect,
|
||||
(int)p.addrType);
|
||||
}
|
||||
bool has_hid_host_auto = false;
|
||||
bool has_hid_device_auto = false;
|
||||
for (const auto& p : peers) {
|
||||
@@ -122,28 +131,36 @@ static void bt_event_bridge(Device*, void* /*context*/, BtEvent event) {
|
||||
if (p.profileId == BT_PROFILE_HID_HOST) has_hid_host_auto = true;
|
||||
if (p.profileId == BT_PROFILE_HID_DEVICE) has_hid_device_auto = true;
|
||||
}
|
||||
LOG_I(TAG, "RADIO ON: has_hid_host_auto=%d has_hid_device_auto=%d spp=%d midi=%d",
|
||||
(int)has_hid_host_auto, (int)has_hid_device_auto,
|
||||
(int)settings::shouldSppAutoStart(), (int)settings::shouldMidiAutoStart());
|
||||
// Start all auto-connect/auto-start roles that are configured.
|
||||
// Scanning (central) and advertising (peripheral) can run concurrently
|
||||
// on ESP32 NimBLE, so we no longer use exclusive else-if.
|
||||
if (has_hid_host_auto) {
|
||||
LOG_I(TAG, "HID host auto-connect peer found — starting scan");
|
||||
if (Device* dev = device_find_first_active_by_type(&BLUETOOTH_TYPE)) {
|
||||
bluetooth_scan_start(dev);
|
||||
}
|
||||
} else if (has_hid_device_auto) {
|
||||
}
|
||||
if (has_hid_device_auto) {
|
||||
LOG_I(TAG, "HID device auto-start (bonded peer found)");
|
||||
if (Device* dev = bluetooth_hid_device_get_device()) {
|
||||
bluetooth_hid_device_start(dev, BT_HID_DEVICE_MODE_KEYBOARD);
|
||||
}
|
||||
} else {
|
||||
if (settings::shouldSppAutoStart()) {
|
||||
LOG_I(TAG, "Auto-starting SPP server");
|
||||
if (Device* dev = bluetooth_serial_get_device()) {
|
||||
bluetooth_serial_start(dev);
|
||||
}
|
||||
}
|
||||
// SPP and MIDI are peripheral servers; start them if their global
|
||||
// auto-start flags are set, regardless of HID roles.
|
||||
if (settings::shouldSppAutoStart()) {
|
||||
LOG_I(TAG, "Auto-starting SPP server");
|
||||
if (Device* dev = bluetooth_serial_get_device()) {
|
||||
bluetooth_serial_start(dev);
|
||||
}
|
||||
if (settings::shouldMidiAutoStart()) {
|
||||
LOG_I(TAG, "Auto-starting MIDI server");
|
||||
if (Device* dev = bluetooth_midi_get_device()) {
|
||||
bluetooth_midi_start(dev);
|
||||
}
|
||||
}
|
||||
if (settings::shouldMidiAutoStart()) {
|
||||
LOG_I(TAG, "Auto-starting MIDI server");
|
||||
if (Device* dev = bluetooth_midi_get_device()) {
|
||||
bluetooth_midi_start(dev);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -176,6 +193,9 @@ static void bt_event_bridge(Device*, void* /*context*/, BtEvent event) {
|
||||
int profile_copy = event.pair_result.profile;
|
||||
memcpy(addr_buf, event.pair_result.addr, 6);
|
||||
getMainDispatcher().dispatch([addr_buf, profile_copy]() mutable {
|
||||
// Ensure Bluetooth auto-enables on boot after successful pairing,
|
||||
// so previously connected devices reconnect after a restart.
|
||||
settings::setEnableOnBoot(true);
|
||||
std::array<uint8_t, 6> peer_addr;
|
||||
memcpy(peer_addr.data(), addr_buf, 6);
|
||||
const auto hex = settings::addrToHex(peer_addr);
|
||||
@@ -185,6 +205,13 @@ static void bt_event_bridge(Device*, void* /*context*/, BtEvent event) {
|
||||
dev.name = "";
|
||||
dev.autoConnect = true;
|
||||
dev.profileId = profile_copy;
|
||||
// Try to preserve addrType from scan cache if available
|
||||
uint8_t cached_type = 0;
|
||||
if (getCachedScanAddrType(peer_addr.data(), &cached_type)) {
|
||||
dev.addrType = cached_type;
|
||||
} else {
|
||||
dev.addrType = 0;
|
||||
}
|
||||
if (settings::save(dev)) {
|
||||
LOG_I(TAG, "Saved paired peer %s (profile=%d)", hex.c_str(), profile_copy);
|
||||
}
|
||||
@@ -290,6 +317,11 @@ bool start(Device* dev) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Persist enable-on-boot so that paired devices auto-reconnect after a restart.
|
||||
// The settings file is written from the main task to avoid blocking the NimBLE host
|
||||
// task, but the dispatcher may run immediately, so we also set it here.
|
||||
settings::setEnableOnBoot(true);
|
||||
|
||||
LOG_I(TAG, "BT enabled");
|
||||
return true;
|
||||
}
|
||||
@@ -414,6 +446,9 @@ void unpair(const std::array<uint8_t, 6>& addr) {
|
||||
|
||||
void connect(const std::array<uint8_t, 6>& addr, int profileId) {
|
||||
LOG_I(TAG, "connect(profile=%d)", profileId);
|
||||
// Ensure BT restarts in the same mode after reboot, so previously connected
|
||||
// devices can be re-found (scan) or reconnected to (advertising).
|
||||
settings::setEnableOnBoot(true);
|
||||
if (profileId == BT_PROFILE_HID_HOST) {
|
||||
hidHostConnect(addr);
|
||||
} else if (profileId == BT_PROFILE_HID_DEVICE) {
|
||||
|
||||
Reference in New Issue
Block a user