From 42c4d6d8894f6529557d57c29a29f825ec649795 Mon Sep 17 00:00:00 2001 From: Kirill Marchenko Date: Tue, 11 Nov 2025 19:52:16 +0100 Subject: [PATCH] Fix macOS BLE peripheral reconnection after sleep/wake --- lib/mac/src/ble_manager.mm | 27 +++++++++++++++++++++------ lib/noble.js | 6 +++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/lib/mac/src/ble_manager.mm b/lib/mac/src/ble_manager.mm index b82f1e96..a3996b3b 100644 --- a/lib/mac/src/ble_manager.mm +++ b/lib/mac/src/ble_manager.mm @@ -57,12 +57,27 @@ - (void)updateMtuForPeripheral:(CBPeripheral*) peripheral { - (void)centralManagerDidUpdateState:(CBCentralManager *)central { - if (central.state != self.lastState && self.lastState == CBManagerStatePoweredOff && central.state == CBManagerStatePoweredOn) { - [self.peripherals enumerateKeysAndObjectsUsingBlock:^(id key, CBPeripheral* peripheral, BOOL *stop) { - if (peripheral.state == CBPeripheralStateConnected) { - [self.centralManager cancelPeripheralConnection:peripheral]; - } - }]; + // if (central.state != self.lastState && self.lastState == CBManagerStatePoweredOff && central.state == CBManagerStatePoweredOn) { + // [self.peripherals enumerateKeysAndObjectsUsingBlock:^(id key, CBPeripheral* peripheral, BOOL *stop) { + // if (peripheral.state == CBPeripheralStateConnected) { + // [self.centralManager cancelPeripheralConnection:peripheral]; + // } + // }]; + // } + + // Detect transition from any non-powered-on state to powered-on (e.g., after sleep) + BOOL wasPoweredOff = (self.lastState != CBManagerStatePoweredOn); + BOOL isNowPoweredOn = (central.state == CBManagerStatePoweredOn); + + if (wasPoweredOff && isNowPoweredOn) { + // Force disconnect ALL peripherals that Noble was tracking before sleep + NSArray *trackedUUIDs = [self.peripherals allKeys]; + for (NSString *uuid in trackedUUIDs) { + CBPeripheral *peripheral = [self.peripherals objectForKey:uuid]; + + // Always force disconnect, regardless of the peripheral's current state + [self.centralManager cancelPeripheralConnection:peripheral]; + } } self.lastState = central.state; diff --git a/lib/noble.js b/lib/noble.js index a1e92fbb..240fe4fa 100644 --- a/lib/noble.js +++ b/lib/noble.js @@ -126,9 +126,9 @@ class Noble extends EventEmitter { debug(`stateChange ${state}`); // If the state is poweredOff and the previous state was poweredOn, clean up the peripherals - if (state === 'poweredOff' && this._state === 'poweredOn') { - this._cleanupPeriperals(); - } + // if (state === 'poweredOff' && this._state === 'poweredOn') { + // this._cleanupPeriperals(); + // } this._state = state; this.emit('stateChange', state);