From eb8c71b1af83a955ed536fd1625ce431c41af228 Mon Sep 17 00:00:00 2001 From: steve Date: Mon, 10 Feb 2025 22:52:54 -0500 Subject: [PATCH 1/2] add a native method for disconnecting all connected perpherals --- BleManager.js | 2 +- .../src/main/java/it/innove/BleManager.java | 36 +++++++++++- .../src/main/java/it/innove/Peripheral.java | 51 +++++++++++++++++ ios/BleManager.h | 5 ++ ios/BleManager.m | 55 +++++++++++++++++++ 5 files changed, 147 insertions(+), 2 deletions(-) diff --git a/BleManager.js b/BleManager.js index b630d4e6..d59bbb09 100644 --- a/BleManager.js +++ b/BleManager.js @@ -133,7 +133,7 @@ class BleManager { connectLe(peripheralId) { return new Promise((fulfill, reject) => { - bleManager.connect(peripheralId, error => { + bleManager.connectLe(peripheralId, error => { if (error) { reject(error); } else { diff --git a/android/src/main/java/it/innove/BleManager.java b/android/src/main/java/it/innove/BleManager.java index 045d10e2..7762a0e8 100644 --- a/android/src/main/java/it/innove/BleManager.java +++ b/android/src/main/java/it/innove/BleManager.java @@ -40,7 +40,13 @@ import static android.bluetooth.BluetoothProfile.GATT; import static android.os.Build.VERSION_CODES.LOLLIPOP; -class BleManager extends ReactContextBaseJavaModule { +public class BleManager extends ReactContextBaseJavaModule { + + private static BleManager instance; + + public static BleManager getInstance() { + return instance; + } public static final String LOG_TAG = "ReactNativeBleManager"; private static final int ENABLE_REQUEST = 539; @@ -99,6 +105,7 @@ public void onActivityResult(Activity activity, int requestCode, int resultCode, public BleManager(ReactApplicationContext reactContext) { super(reactContext); + instance = this; // Assign instance when JS initializes it context = reactContext; this.reactContext = reactContext; reactContext.addActivityEventListener(mActivityEventListener); @@ -765,4 +772,31 @@ public void onCatalystInstanceDestroy() { scanManager.stopScan(args -> {}); } } + + /** + * Disconnects all connected peripherals by first sending a termination message. + * + * This method: + * 1. Iterates through all connected peripherals. + * 2. Calls `disconnectWithServiceUUID` on each peripheral. + * 3. Ensures all devices receive a termination message before disconnecting. + * + * @param serviceUUID The UUID of the BLE service that contains the characteristic for termination messaging. + * @param characteristicUUID The UUID of the BLE characteristic to which the termination message will be written. + * @param message A byte array containing the termination message. + * + * @note This method ensures that all connected peripherals receive a termination message before being disconnected. + */ + public void disconnectAllPeripheralsWithServiceUUID(String serviceUUID, String characteristicUUID, byte[] message) { + Log.d(LOG_TAG, "Disconnecting all connected peripherals..."); + + synchronized (peripherals) { + for (Peripheral peripheral : peripherals.values()) { + if (peripheral.isConnected()) { + peripheral.disconnectWithServiceUUID(serviceUUID, characteristicUUID, message); + } + } + } + } + } diff --git a/android/src/main/java/it/innove/Peripheral.java b/android/src/main/java/it/innove/Peripheral.java index 4a767e60..cfa2de22 100644 --- a/android/src/main/java/it/innove/Peripheral.java +++ b/android/src/main/java/it/innove/Peripheral.java @@ -1051,4 +1051,55 @@ private String generateHashKey(UUID serviceUUID, BluetoothGattCharacteristic cha return String.valueOf(serviceUUID) + "|" + characteristic.getUuid() + "|" + characteristic.getInstanceId(); } + /** + * Disconnects the peripheral by first sending a termination message to a specific BLE characteristic. + * + * This method: + * 1. Checks if the peripheral is connected. + * 2. Finds the specified service and characteristic. + * 3. Writes a termination message to the characteristic. + * 4. Disconnects the peripheral after the message is sent. + * + * @param serviceUUID The UUID of the BLE service that contains the characteristic for termination messaging. + * @param characteristicUUID The UUID of the BLE characteristic to which the termination message will be written. + * @param message A byte array containing the termination message. + * + * @note If the service or characteristic is not found, the peripheral will be disconnected immediately. + */ + public void disconnectWithServiceUUID(String serviceUUID, String characteristicUUID, byte[] message) { + if (!isConnected() || gatt == null) { + Log.e(BleManager.LOG_TAG, "Peripheral is not connected or BluetoothGatt is null. Skipping..."); + return; + } + + // Retrieve the BluetoothGattService + BluetoothGattService service = gatt.getService(UUIDHelper.uuidFromString(serviceUUID)); + if (service == null) { + Log.e(BleManager.LOG_TAG, "Service " + serviceUUID + " not found on device: " + device.getAddress()); + disconnect(true); + return; + } + + // Retrieve the BluetoothGattCharacteristic + BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUIDHelper.uuidFromString(characteristicUUID)); + if (characteristic == null) { + Log.e(BleManager.LOG_TAG, "Characteristic " + characteristicUUID + " not found on device: " + device.getAddress()); + disconnect(true); + return; + } + + // Write the termination message to the characteristic + characteristic.setValue(message); + boolean success = gatt.writeCharacteristic(characteristic); + if (success) { + Log.d(BleManager.LOG_TAG, "Termination message sent to device: " + device.getAddress()); + } else { + Log.e(BleManager.LOG_TAG, "Failed to send termination message to device: " + device.getAddress()); + } + + // Disconnect the peripheral + disconnect(true); + Log.d(BleManager.LOG_TAG, "Disconnected device: " + device.getAddress()); + } + } diff --git a/ios/BleManager.h b/ios/BleManager.h index 817cc70f..bbe1fa91 100644 --- a/ios/BleManager.h +++ b/ios/BleManager.h @@ -29,4 +29,9 @@ // For integration with external libraries, advanced use only. +(BleManager *)getInstance; +// Disconnects all currently connected Gita devices after sending a termination message. +- (void)disconnectAllPeripheralsWithServiceUUID:(NSString *)serviceUUID + characteristicUUID:(NSString *)characteristicUUID + message:(NSArray *)message; + @end diff --git a/ios/BleManager.m b/ios/BleManager.m index 2a30cbe3..2c98b9be 100644 --- a/ios/BleManager.m +++ b/ios/BleManager.m @@ -247,6 +247,61 @@ -(int) compareCBUUID:(CBUUID *) UUID1 UUID2:(CBUUID *)UUID2 return 0; } +/** + * @brief Disconnects all currently connected peripherals by sending a termination message. + * + * This method iterates through all connected peripherals, writes a specified termination message + * to a given characteristic on each device. + * + * @param serviceUUID The UUID of the BLE service that contains the characteristic for termination messaging. + * @param characteristicUUID The UUID of the BLE characteristic to which the termination message will be written. + * @param message An NSArray of NSNumber values representing the termination message in bytes. + * + * @note The termination message should be 20 bytes or less to fit in a single BLE packet. If a device is connected, + * this function will first send the message using `writeWithoutResponse`, then initiate a disconnection. + * + * @see writeWithoutResponse:serviceUUID:characteristicUUID:message:maxByteSize:callback: + */ +- (void)disconnectAllPeripheralsWithServiceUUID:(NSString *)serviceUUID + characteristicUUID:(NSString *)characteristicUUID + message:(NSArray *)message { + if (!manager) { + NSLog(@"BLE Manager is NULL. Cannot disconnect peripherals."); + return; + } + + NSLog(@"Disconnecting all connected peripherals..."); + + @synchronized(peripherals) { + for (CBPeripheral *peripheral in peripherals) { + if (peripheral.state == CBPeripheralStateConnected) { + + // Get the device UUID + NSString *deviceUUID = peripheral.identifier.UUIDString; + + // Set maximum byte size and queue sleep time (adjustable) + NSInteger maxByteSize = 20; // Default max bytes per BLE packet + NSInteger queueSleepTime = 10; // Delay between packets in ms + + NSLog(@"Sending termination message to %@ on service %@, characteristic %@", + deviceUUID, serviceUUID, characteristicUUID); + + // Call the writeWithoutResponse method directly + [self writeWithoutResponse:deviceUUID + serviceUUID:serviceUUID + characteristicUUID:characteristicUUID + message:message + maxByteSize:maxByteSize + queueSleepTime:queueSleepTime + callback:^(NSArray *response) { + NSLog(@"Termination message sent successfully to %@", deviceUUID); + }]; + } + } + } +} + + RCT_EXPORT_METHOD(getDiscoveredPeripherals:(nonnull RCTResponseSenderBlock)callback) { NSLog(@"Get discovered peripherals"); From d1826bc87ed07373355aed639d87109631235dc3 Mon Sep 17 00:00:00 2001 From: stevesuyao Date: Sun, 16 Feb 2025 17:04:18 -0500 Subject: [PATCH 2/2] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 5779051e..c770741f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-ble-manager", - "version": "8.4.3-pff", + "version": "8.4.4-pff", "description": "A BLE module for react native.", "main": "BleManager", "types": "./index.d.ts",