Giter VIP home page Giter VIP logo

multiplatformbleadapter's Introduction

MultiPlatformBleAdapter

Middle layer between crossplatform BLE libraries (react-native-ble-plx and FlutterBleLib) and iOS/Android system for manipulating Bluetooth Low Energy peripherals. Internally uses:

If you'd like to use it in your own library, you should start from BleAdapter on either platform.

Maintained by

This library is maintained by Intent

Contact us

License

Copyright 2023 intent sp. z o.o

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

multiplatformbleadapter's People

Contributors

bartoszwilk avatar below avatar bntnam avatar dariuszseweryn avatar gmiszewski-intent avatar hans00 avatar kamilnatonek avatar lemusadr000 avatar mikolak avatar pawelbyszewski avatar piotrdubiel avatar tomolv avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

multiplatformbleadapter's Issues

Why is the Client Characteristic Configuration Descriptor explicitly not allowed?

Hello,
I'm trying to work with a bluetooth service which explicitly requires that my app write to this descriptor (2902) to enable notifications for certain characteristics. I found that I was getting a 506 denied error and went looking through the source code. I found the change was introduced on this PR:
https://github.com/Polidea/MultiPlatformBleAdapter/pull/40/files

https://github.com/Polidea/MultiPlatformBleAdapter/blob/883ea0802867b86fb1a63776dde584de68c125f8/iOS/classes/BleModule.swift#L1166

is the line which disables this functionality. I've not been able to find documentation online that suggests this be a recommended behavior for a BLE client library. Is there a reason why this is not allowed?

Issues with iOS 15 SDK

Due to changes in the CoreBluetooth API, parts of the code break:

…/RestoredState.swift:68:105: error: value of optional type 'CBPeripheral?' must be unwrapped to a value of type 'CBPeripheral'
                                                      peripheral: RxCBPeripheral(peripheral: $0.service.peripheral)),
                                                                                                        ^
…/MultiplatformBleAdapter/iOS/RxBluetoothKit/RxCBCharacteristic.swift:59:52: error: value of optional type 'CBService?' must be unwrapped to a value of type 'CBService'
        return RxCBService(service: characteristic.service)
                                                   ^                                                      peripheral: RxCBPeripheral(peripheral: $0.service.peripheral)),
…/RxCBDescriptor.swift:43:62: error: value of optional type 'CBCharacteristic?' must be unwrapped to a value of type 'CBCharacteristic'
        return RxCBCharacteristic(characteristic: descriptor.characteristic)
                                                             ^

it doesn't seem to characteristicUpdates monitor work in iOS

hi

I connect to a test BLE device and write commands to the BLE device. Then the BLE device sends the commands to the app through the data UUID.

The versions I tested are as follows:
Android version: 12
iOS version: 16.4.1

I use to FlutterBleLib 2.3.2

Here's the code:
When connecting to the BLE device and entering the AcScreen, I activate the monitor for the ReadCharacteristic UUID to receive commands from the BLE device in the app. Additionally, using WriteCharacteristic, the app can receive commands from the BLE device.

  typedef OperationFunction = Future<void> Function();
  
  class AcScreen extends StatefulWidget {
    final Device device;
  
    AcScreen({Key? key, required this.device})
        : assert(device.type == DeviceType.ac),
          super(key: key);
  
    @override
    State<AcScreen> createState() => _AcScreenState();
  }
  
  class _AcScreenState extends State<AcScreen> {
    double temp = 1;
    DeviceDetailsBloc? _deviceDetailsBloc;
  
    StreamSubscription? _appStateSubscription;
    bool _shouldRunOnResume = true;
  
    String acTransaction = "Ac";
    late final BleManager? _bleManager;
  
    StreamSubscription<double>? _monitoringStreamSubscription;
    
    //UUID
    static final String TestService = Platform.isAndroid ? "0000FFF0-0000-1000-8000-00805F9B34FB" : "FFF0";
    static final String ReadCharacteristic = Platform.isAndroid ? "0000FFF1-0000-1000-8000-00805F9B34FB" : "FFF1";
    static final String WrtieCharacteristic = Platform.isAndroid ? "0000FFF2-0000-1000-8000-00805F9B34FB" : "FFF2";
    
  
    //Level Control
    Uint8List level_1 = Uint8List.fromList([0x02, 0x31, 0x43, 0xC3, 0x31, 0x36, 0x3A, 0x03]);
    Uint8List level_2 = Uint8List.fromList([0x02, 0x31, 0x43, 0xC3, 0x32, 0x36, 0x3B, 0x03]);
    Uint8List level_3 = Uint8List.fromList([0x02, 0x31, 0x43, 0xC3, 0x33, 0x36, 0x3C, 0x03]);
    
    @override
    void didChangeDependencies() {
      super.didChangeDependencies();
      Fimber.d("didChangeDependencies");
      if (_deviceDetailsBloc == null) {
        _deviceDetailsBloc = DeviceDetailsBlocProvider.of(context);
        _bleManager = _deviceDetailsBloc?.getBleManager();
        if (_shouldRunOnResume) {
          _shouldRunOnResume = false;
          _onResume();
        }
      }
    }
  
    void _onResume() {
      Fimber.d("onResume");
      _deviceDetailsBloc?.init();
      _appStateSubscription =
          _deviceDetailsBloc?.disconnectedDevice.listen((bleDevice) async {
            Fimber.d("navigate to details");
            _onPause();
            Navigator.pop(context);
            _shouldRunOnResume = true;
            Fimber.d("back from details");
          });
      readWriteMonitorCharacteristicForTest(TestService,ReadCharacteristic,acTransaction);
      
      writeCharacter(TestService,WrtieCharacteristic,level_3);
    }
  
    void _onPause() {
      Fimber.d("onPause");
      _appStateSubscription?.cancel();
      _deviceDetailsBloc?.dispose();
    }
  
    @override
    void dispose() {
      Fimber.d("dispose");
      _onPause();
      super.dispose();
      print("dispose");
      cancelMonitoring(acTransaction);
    }
    
    
    void writeCharacter(String svcUuid, String writeCharacterUuid,Uint8List data) {
      _deviceDetailsBloc?.writeCharacter(svcUuid,writeCharacterUuid,data);
    }
  
    Future<void> _runWithErrorHandling(OperationFunction Function) async {
      try {
        await Function();
      } on BleError catch (e) {
        print("BleError caught: ${e.errorCode.value} ${e.reason}");
      } catch (e) {
        if (e is Error) {
          //debugPrintStack(stackTrace: e.stackTrace);
        }
        print("${e.runtimeType}: $e");
      }
    }
    Future<void> cancelMonitoring(String transactionId) async {
      _monitoringStreamSubscription?.cancel();
      await _bleManager?.cancelTransaction(transactionId);
    }
    void startMonitoring(
        Stream<Uint8List> characteristicUpdates) async {
      await _monitoringStreamSubscription?.cancel();
      _monitoringStreamSubscription =
      characteristicUpdates.listen(
            (temperature) {
          String hex = temperature.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(' ');
          print("testWrite Read Data: ${hex}");
        },
        onError: (error) {
          print("Read Data \n$error");
        },
        cancelOnError: true,
      ) as StreamSubscription<double>?;
    }
    Future<void> readWriteMonitorCharacteristicForTest(String svcUuid, String writeCharacterUuid, String transactionId) async {
      await _runWithErrorHandling(() async {
        print("Start monitoring readWriteMonitorCharacteristicFortest");
        var peripheral = _deviceDetailsBloc?.getBleDevice().peripheral;
  
        startMonitoring(
          peripheral!
              .monitorCharacteristic(svcUuid,
              writeCharacterUuid,
              transactionId: transactionId)
              .map((characteristic) => characteristic.value)
        );
      });
    }

Currently, it is possible to send commands to the BLE device from the app on both Android and iOS. However, on iOS, the commands from the BLE device are not being received.

Please refer to the following Android and iOS logs:

[Android Log]

✓  Built build/app/outputs/flutter-apk/app-debug.apk.
D/FLUTTER_CALL(15956): registered channel:aesDecrypt
D/FLUTTER_CALL(15956): registered channel:aesEncrypt
D/FLUTTER_CALL(15956): registered channel:argon2d
D/FLUTTER_CALL(15956): registered channel:argon2i
D/FLUTTER_CALL(15956): registered channel:argon2id
D/FlutterGeolocator(15956): Attaching Geolocator to activity
W/FlutterActivityAndFragmentDelegate(15956): A splash screen was provided to Flutter, but this is deprecated. See flutter.dev/go/android-splash-migration for migration steps.
D/FlutterGeolocator(15956): Creating service.
D/FlutterGeolocator(15956): Binding to location service.
D/FlutterGeolocator(15956): Geolocator foreground service connected
D/FlutterGeolocator(15956): Initializing Geolocator services
Debug service listening on ws://127.0.0.1:60457/j7H80HbHsp8=/ws
Syncing files to device SM G991N...
I/ble_lib_exampl(15956): Compiler allocated 4632KB to compile void android.view.ViewRootImpl.performTraversals()
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 0
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 1
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: isClientCreated
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: createClient
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: getState
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: startDeviceScan
I/BluetoothAdapter(15956): STATE_ON
I/BluetoothAdapter(15956): STATE_ON
I/BluetoothAdapter(15956): STATE_ON
I/BluetoothAdapter(15956): STATE_ON
D/BluetoothLeScanner(15956): Start Scan with callback
D/BluetoothLeScanner(15956): onScannerRegistered() - status=0 scannerId=11 mScannerId=0
I/flutter (15956): Build row for 0
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 0
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 1
I/flutter (15956): clicked device: TEST PORTABLE AIR_40449E 
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: stopDeviceScan
I/BluetoothAdapter(15956): STATE_ON
I/BluetoothAdapter(15956): STATE_ON
D/BluetoothLeScanner(15956): Stop Scan with callback
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: stopDeviceScan
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: isDeviceConnected
I/flutter (15956): Build row for 0
I/flutter (15956): didChangeDependencies
I/flutter (15956): onResume
D/CompatibilityChangeReporter(15956): Compat change id reported: 147798919; UID 10396; state: DISABLED
V/Toast   (15956): show: caller = io.github.ponnamkarthik.toast.fluttertoast.MethodCallHandlerImpl.onMethodCall:102 
V/Toast   (15956): show: focusDisplayId = 0, isFocusInDesktop = false mCustomDisplayId=-1 isDexDualMode=false
V/Toast   (15956): show: isActivityContext = false
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: stopDeviceScan
I/ViewRootImpl@f4d22d3[Toast](15956): setView = android.widget.FrameLayout@6a64e10 TM=true
I/ViewRootImpl@f4d22d3[Toast](15956): Relayout returned: old=(0,80,1080,2256) new=(227,2031,853,2156) req=(626,125)0 dur=6 res=0x7 s={true 521376462880} ch=true fn=-1
I/ViewRootImpl@f4d22d3[Toast](15956): [DP] dp(1) 0 android.view.ViewRootImpl.reportNextDraw:11233 android.view.ViewRootImpl.performTraversals:4075 android.view.ViewRootImpl.doTraversal:2819 
D/ViewRootImpl@f4d22d3[Toast](15956): Creating frameCompleteCallback mNextDrawUseBlastSync=false mReportNextDraw=true commitCallbacks size=0
I/flutter (15956): PeripheralConnectionState.disconnected
D/ViewRootImpl@f4d22d3[Toast](15956): Received frameCompleteCallback frameNum=1
I/ViewRootImpl@f4d22d3[Toast](15956): [DP] pdf(0) 0 android.view.ViewRootImpl.lambda$createFrameCompleteCallback$3$ViewRootImpl:4833 android.view.ViewRootImpl$$ExternalSyntheticLambda15.run:6 android.os.Handler.handleCallback:938 
I/ViewRootImpl@f4d22d3[Toast](15956): [DP] rdf()
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: logLevel
I/flutter (15956): try to get log level from: NONE
I/flutter (15956): Connection_to log level LogLevel.none
I/flutter (15956): Connection_to log level to debug
I/flutter (15956): set log level to debug
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: setLogLevel
D/com.polidea.flutter_ble_lib.delegate.LogLevelDelegate(15956): set log level to: debug
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: logLevel
I/flutter (15956): try to get log level from: DEBUG
I/flutter (15956): Connection_to log level LogLevel.debug
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: observeConnectionState
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: connectToDevice
I/flutter (15956): PeripheralConnectionState.disconnected
I/flutter (15956): PeripheralConnectionState.connecting
D/RxBle#ClientOperationQueue(15956): QUEUED   ConnectOperation(137452352)
D/RxBle#ClientOperationQueue(15956): STARTED  ConnectOperation(137452352)
I/BluetoothAdapter(15956): STATE_ON
D/BluetoothGatt(15956): connect() - device: 5C:F2:86:40:44:9E, auto: false
I/BluetoothAdapter(15956): isSecureModeEnabled
D/BluetoothGatt(15956): registerApp()
D/BluetoothGatt(15956): registerApp() - UUID=f42c2506-82a1-4d0a-8847-79f40cf38442
D/BluetoothGatt(15956): onClientRegistered() - status=0 clientIf=11
D/BluetoothGatt(15956): onTimeSync() - eventCount=0 offset=345
D/BluetoothGatt(15956): onClientConnectionState() - status=0 clientIf=11 device=5C:F2:86:40:44:9E
D/RxBle#BluetoothGatt$1(15956): onConnectionStateChange newState=2 status=0
D/RxBle#ClientOperationQueue(15956): FINISHED ConnectOperation(137452352) in 1752 ms
I/flutter (15956): PeripheralConnectionState.connected
V/Toast   (15956): show: caller = io.github.ponnamkarthik.toast.fluttertoast.MethodCallHandlerImpl.onMethodCall:102 
V/Toast   (15956): show: focusDisplayId = 0, isFocusInDesktop = false mCustomDisplayId=-1 isDexDualMode=false
V/Toast   (15956): show: isActivityContext = false
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: discoverAllServicesAndCharacteristics
D/RxBle#ConnectionOperationQueue(15956): QUEUED   ServiceDiscoveryOperation(167459844)
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: cancelTransaction
D/RxBle#ConnectionOperationQueue(15956): STARTED  ServiceDiscoveryOperation(167459844)
D/BluetoothGatt(15956): discoverServices() - device: 5C:F2:86:40:44:9E
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: discoverAllServicesAndCharacteristics
D/BluetoothGatt(15956): onTimeSync() - eventCount=16 offset=385
D/BluetoothGatt(15956): onConnectionUpdated() - Device=5C:F2:86:40:44:9E interval=6 latency=0 timeout=500 status=0
D/BluetoothGatt(15956): onSearchComplete() = Device=5C:F2:86:40:44:9E Status=0
D/RxBle#BluetoothGatt$1(15956): onServicesDiscovered status=0
D/RxBle#ConnectionOperationQueue(15956): FINISHED ServiceDiscoveryOperation(167459844) in 110 ms
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: services
I/flutter (15956): PRINTING SERVICES for 
I/flutter (15956): TEST PORTABLE AIR_40449E 
I/flutter (15956): PRINTING CHARACTERISTICS FOR SERVICE 
I/flutter (15956): 00001800-0000-1000-8000-00805f9b34fb
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: characteristicsForService
I/flutter (15956): 00002a00-0000-1000-8000-00805f9b34fb
I/flutter (15956): 00002a01-0000-1000-8000-00805f9b34fb
I/flutter (15956): 00002a04-0000-1000-8000-00805f9b34fb
I/flutter (15956): 00002aa6-0000-1000-8000-00805f9b34fb
I/flutter (15956): PRINTING CHARACTERISTICS FROM 
I/flutter (15956): PERIPHERAL for the same service
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: characteristics
I/flutter (15956): Found characteristic 
I/flutter (15956):  00002a00-0000-1000-8000-00805f9b34fb
I/flutter (15956): Found characteristic 
I/flutter (15956):  00002a01-0000-1000-8000-00805f9b34fb
I/flutter (15956): Found characteristic 
I/flutter (15956):  00002a04-0000-1000-8000-00805f9b34fb
I/flutter (15956): Found characteristic 
I/flutter (15956):  00002aa6-0000-1000-8000-00805f9b34fb
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: descriptorsForDevice
I/flutter (15956): #0      new Characteristic.fromJson (package:flutter_ble_lib/characteristic.dart:48:20)
I/flutter (15956): #1      DiscoveryMixin.descriptorsForPeripheral (package:flutter_ble_lib/src/bridge/discovery_mixin.dart:93:24)
I/flutter (15956): <asynchronous suspension>
I/flutter (15956): #2      PeripheralOperations.discovery.<anonymous closure> (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:70:23)
I/flutter (15956): <asynchronous suspension>
I/flutter (15956): #3      PeripheralOperations._runWithErrorHandling (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:754:7)
I/flutter (15956): <asynchronous suspension>
I/flutter (15956): #4      PeripheralOperations.discovery (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:43:37)
I/flutter (15956): <asynchronous suspension>
I/flutter (15956): Requesting MTU = 512
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: requestMtu
D/com.polidea.flutter_ble_lib.delegate.MtuDelegate(15956): Request MTU 512
D/RxBle#ConnectionOperationQueue(15956): QUEUED   MtuRequestOperation(87562539)
D/RxBle#ConnectionOperationQueue(15956): STARTED  MtuRequestOperation(87562539)
D/BluetoothGatt(15956): configureMTU() - device: 5C:F2:86:40:44:9E mtu: 512
D/BluetoothGatt(15956): onTimeSync() - eventCount=29 offset=353
D/BluetoothGatt(15956): onConnectionUpdated() - Device=5C:F2:86:40:44:9E interval=39 latency=0 timeout=500 status=0
I/ViewRootImpl@f4d22d3[Toast](15956): dispatchDetachedFromWindow
D/InputTransport(15956): Input channel destroyed: '53000d6', fd=144
I/ViewRootImpl@ad1b959[Toast](15956): setView = android.widget.FrameLayout@59b391e TM=true
I/ViewRootImpl@ad1b959[Toast](15956): Relayout returned: old=(0,80,1080,2256) new=(258,2031,821,2156) req=(563,125)0 dur=5 res=0x7 s={true 521376480320} ch=true fn=-1
I/ViewRootImpl@ad1b959[Toast](15956): [DP] dp(1) 0 android.view.ViewRootImpl.reportNextDraw:11233 android.view.ViewRootImpl.performTraversals:4075 android.view.ViewRootImpl.doTraversal:2819 
D/ViewRootImpl@ad1b959[Toast](15956): Creating frameCompleteCallback mNextDrawUseBlastSync=false mReportNextDraw=true commitCallbacks size=0
D/ViewRootImpl@ad1b959[Toast](15956): Received frameCompleteCallback frameNum=1
I/ViewRootImpl@ad1b959[Toast](15956): [DP] pdf(0) 0 android.view.ViewRootImpl.lambda$createFrameCompleteCallback$3$ViewRootImpl:4833 android.view.ViewRootImpl$$ExternalSyntheticLambda15.run:6 android.os.Handler.handleCallback:938 
I/ViewRootImpl@ad1b959[Toast](15956): [DP] rdf()
D/BluetoothGatt(15956): onConfigureMTU() - Device=5C:F2:86:40:44:9E mtu=247 status=0
D/RxBle#BluetoothGatt$1(15956): onMtuChanged mtu=247 status=0
I/flutter (15956): SetMtuSize MTU = 247
I/flutter (15956): negotiated MTU 247
D/RxBle#ConnectionOperationQueue(15956): FINISHED MtuRequestOperation(87562539) in 68 ms
I/ViewRootImpl@ad1b959[Toast](15956): dispatchDetachedFromWindow
D/InputTransport(15956): Input channel destroyed: '716669c', fd=172
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 0
I/ViewRootImpl@f13eae4[MainActivity](15956): ViewPostIme pointer 1
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: isDeviceConnected
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: stopDeviceScan
I/flutter (15956): Start monitoring readWriteMonitorCharacteristicForTEST
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin(15956): on native side observed method: monitorCharacteristicForDevice
E/flutter (15956): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type '_ForwardingStreamSubscription<CharacteristicWithValueAndTransactionId, Uint8List>' is not a subtype of type 'StreamSubscription<double>?' in type cast
E/flutter (15956): #0      _AcScreenState.startMonitoring (package:flutter_ble_lib_example/features/devices/presentation/views/ac.dart:431:7)
E/flutter (15956): <asynchronous suspension>
E/flutter (15956): 
D/BluetoothGatt(15956): setCharacteristicNotification() - uuid: 0000fff1-0000-1000-8000-00805f9b34fb enable: true
D/RxBle#ConnectionOperationQueue(15956): QUEUED   DescriptorWriteOperation(205982959)
D/RxBle#ConnectionOperationQueue(15956): STARTED  DescriptorWriteOperation(205982959)
D/BluetoothGatt(15956): onTimeSync() - eventCount=134 offset=369
D/BluetoothGatt(15956): onConnectionUpdated() - Device=5C:F2:86:40:44:9E interval=30 latency=0 timeout=400 status=0
D/RxBle#BluetoothGatt$1(15956): onDescriptorWrite descriptor=00002902-0000-1000-8000-00805f9b34fb status=0
D/RxBle#ConnectionOperationQueue(15956): FINISHED DescriptorWriteOperation(205982959) in 106 ms
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03
D/RxBle#BluetoothGatt$1(15956): onCharacteristicChanged characteristic=0000fff1-0000-1000-8000-00805f9b34fb
I/flutter (15956): testWrite Read Data: 02 31 52 bf 30 30 3a 34 03`

[IOS Log]

`2023-05-18 11:14:25.617881+0900 Runner[461:11075] flutter: Build row for 0
2023-05-18 11:14:29.860895+0900 Runner[461:11075] flutter: clicked device: TEST PORTABLE AIR_40449E
2023-05-18 11:14:29.901367+0900 Runner[461:11075] flutter: Build row for 0
2023-05-18 11:14:29.922328+0900 Runner[461:11075] flutter: didChangeDependencies
2023-05-18 11:14:29.922519+0900 Runner[461:11075] flutter: onResume
2023-05-18 11:14:29.932295+0900 Runner[461:11075] flutter: PeripheralConnectionState.disconnected
2023-05-18 11:14:29.933561+0900 Runner[461:11075] flutter: try to get log level from: None
2023-05-18 11:14:29.933747+0900 Runner[461:11075] flutter: Connection_to log level LogLevel.none
2023-05-18 11:14:29.933763+0900 Runner[461:11075] flutter: Connection_to log level to debug
2023-05-18 11:14:29.933832+0900 Runner[461:11075] flutter: set log level to debug
2023-05-18 11:14:29.934108+0900 Runner[461:11075] flutter: try to get log level from: Debug
2023-05-18 11:14:29.934140+0900 Runner[461:11075] flutter: Connection_to log level LogLevel.debug
2023-05-18 11:14:29.937005+0900 Runner[461:11075] flutter: PeripheralConnectionState.disconnected
2023-05-18 11:14:29.937122+0900 Runner[461:11075] flutter: PeripheralConnectionState.connecting
[RxBLEKit|DEBG|02:14:29.937]: CentralManager(10757624832) retrievePeripherals(
withIdentifiers: [0A7E41A1-68E8-8194-1D9C-17548EF293C1])
[RxBLEKit|DEBG|02:14:29.938]: CentralManager(10757624832) connect(
peripheral: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")),
options: nil)
2023-05-18 11:14:31.223673+0900 Runner[461:11075] flutter: PeripheralConnectionState.connected
[RxBLEKit|DEBG|02:14:31.238]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) discoverServices(
serviceUUIDs: nil)
[RxBLEKit|DEBG|02:14:31.249]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) discoverServices(
serviceUUIDs: nil)
[RxBLEKit|DEBG|02:14:31.340]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didDiscoverServices(services
: Optional("[Service(uuid: FFF0, id: 10795226240)]"),
error: nil)
[RxBLEKit|DEBG|02:14:31.343]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) discoverCharacteristics(
characteristicUUIDs: nil,
for: Service(uuid: FFF0, id: 10795226240))
[RxBLEKit|DEBG|02:14:31.343]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didDiscoverServices(services
: Optional("[Service(uuid: FFF0, id: 10795226240)]"),
error: nil)
[RxBLEKit|DEBG|02:14:31.459]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didDiscoverCharacteristicsFor(for:
Service(uuid: FFF0, id: 10795226240), characteristics:
Optional("[Characteristic(uuid: FFF1, id: 10743800352), Characteristic(uuid: FFF2, id: 10743804672)]"),
error: nil)
[RxBLEKit|DEBG|02:14:31.461]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) discoverDescriptors(
for: Characteristic(uuid: FFF1, id: 10743800352))
[RxBLEKit|DEBG|02:14:31.461]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) discoverDescriptors(
for: Characteristic(uuid: FFF2, id: 10743804672))
[RxBLEKit|DEBG|02:14:31.520]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didDiscoverDescriptorsFor
(for:Characteristic(uuid: FFF1, id: 10743800352), descriptors:
Optional("[Descriptor(uuid: Client Characteristic Configuration, id: 10784087936)]"),
error: nil)
[RxBLEKit|DEBG|02:14:31.579]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didDiscoverDescriptorsFor
(for:Characteristic(uuid: FFF2, id: 10743804672), descriptors:
Optional("[]"),
error: nil)
2023-05-18 11:14:31.581312+0900 Runner[461:11075] flutter: PRINTING SERVICES for 
TEST PORTABLE AIR_40449E
2023-05-18 11:14:31.581530+0900 Runner[461:11075] flutter: PRINTING CHARACTERISTICS FOR SERVICE 
0000fff0-0000-1000-8000-00805f9b34fb
2023-05-18 11:14:31.582915+0900 Runner[461:11075] flutter: 0000fff1-0000-1000-8000-00805f9b34fb
2023-05-18 11:14:31.582952+0900 Runner[461:11075] flutter: 0000fff2-0000-1000-8000-00805f9b34fb
2023-05-18 11:14:31.582974+0900 Runner[461:11075] flutter: PRINTING CHARACTERISTICS FROM 
PERIPHERAL for the same service
2023-05-18 11:14:31.583614+0900 Runner[461:11075] flutter: Found characteristic 
 0000fff1-0000-1000-8000-00805f9b34fb
2023-05-18 11:14:31.583643+0900 Runner[461:11075] flutter: Found characteristic 
 0000fff2-0000-1000-8000-00805f9b34fb
2023-05-18 11:14:31.591657+0900 Runner[461:11075] flutter: #0      new Characteristic.fromJson (package:flutter_ble_lib/characteristic.dart:47:14)
2023-05-18 11:14:31.591702+0900 Runner[461:11075] flutter: #1      DiscoveryMixin.descriptorsForPeripheral (package:flutter_ble_lib/src/bridge/discovery_mixin.dart:93:24)
2023-05-18 11:14:31.591721+0900 Runner[461:11075] flutter: <asynchronous suspension>
2023-05-18 11:14:31.591741+0900 Runner[461:11075] flutter: #2      PeripheralOperations.discovery.<anonymous closure> (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:70:23)
2023-05-18 11:14:31.591758+0900 Runner[461:11075] flutter: <asynchronous suspension>
2023-05-18 11:14:31.591774+0900 Runner[461:11075] flutter: #3      PeripheralOperations._runWithErrorHandling (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:754:7)
2023-05-18 11:14:31.591789+0900 Runner[461:11075] flutter: <asynchronous suspension>
2023-05-18 11:14:31.591832+0900 Runner[461:11075] flutter: #4      PeripheralOperations.discovery (package:flutter_ble_lib_example/test_scenarios/peripheral_operations.dart:43:37)
2023-05-18 11:14:31.591908+0900 Runner[461:11075] flutter: <asynchronous suspension>
2023-05-18 11:14:31.592327+0900 Runner[461:11075] flutter: Requesting MTU = 512
2023-05-18 11:14:31.592800+0900 Runner[461:11075] flutter: SetMtuSize MTU = 247
2023-05-18 11:14:31.592838+0900 Runner[461:11075] flutter: negotiated MTU 247
2023-05-18 11:14:34.897117+0900 Runner[461:11075] flutter: Start monitoring readWriteMonitorCharacteristicForTest
2023-05-18 11:14:34.934725+0900 Runner[461:11075] [VERBOSE-2:dart_vm_initializer.cc(41)] Unhandled Exception: type '_ForwardingStreamSubscription<CharacteristicWithValueAndTransactionId, Uint8List>' is not a subtype of type 'StreamSubscription<double>?' in type cast
#0      _AcScreenState.startMonitoring (package:flutter_ble_lib_example/features/devices/presentation/views/ac.dart:431:7)
<asynchronous suspension>
[RxBLEKit|DEBG|02:14:34.937]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) setNotifyValue(
enabled: true,
for: Characteristic(uuid: FFF1, id: 10743800352))
[RxBLEKit|DEBG|02:14:34.999]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateNotificationStateFor(
for:Characteristic(uuid: FFF1, id: 10743800352), isNotifying: true,
error: nil)
[RxBLEKit|DEBG|02:14:35.148]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:36.139]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:37.160]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:38.149]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:39.169]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:40.160]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
[RxBLEKit|DEBG|02:14:41.148]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)

Based on the logs, we can see that in the case of Android, continuous reception of hex commands is observed from the BLE device. However, in the case of iOS, only the following log is repeatedly occurring, and the code inside the startMonitoring function is not being executed.

The peculiar thing is that in the case of writeCharacteristic, both Android and IOS work normally.

[RxBLEKit|DEBG|02:14:41.148]: Peripheral(uuid: 0A7E41A1-68E8-8194-1D9C-17548EF293C1, name: Optional("TEST PORTABLE AIR_40449E\r")) didUpdateValueFor(for:Characteristic(uuid: FFF1, id: 10743800352),
value: Optional("023152bf30303a3403"),
error: nil)
 void startMonitoring(
      Stream<Uint8List> characteristicUpdates) async {
    await _monitoringStreamSubscription?.cancel();
    _monitoringStreamSubscription =
    characteristicUpdates.listen(
          (temperature) {
        String hex = temperature.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join(' ');
        print("CowayWrite Read Data: ${hex}");
      },
      onError: (error) {
        print("Read Data \n$error");
      },
      cancelOnError: true,
    ) as StreamSubscription<double>?;
  }

Am I missing something? Although I can see commands being received from the BLE device in the iOS log, why is the characteristicUpdates.listen function not being executed?

Please help me.

module map file '/Users/t2b/Library/Developer/Xcode/DerivedData/blem2m-ecdewydnbimghkedqzzpibcfvgxw/Build/Intermediates.noindex/ArchiveIntermediates/blem2m/BuildProductsPath/Release-iphoneos/MultiplatformBleAdapter/MultiplatformBleAdapter.modulemap' not found

module map file '/Users/t2b/Library/Developer/Xcode/DerivedData/blem2m-ecdewydnbimghkedqzzpibcfvgxw/Build/Intermediates.noindex/ArchiveIntermediates/blem2m/BuildProductsPath/Release-iphoneos/MultiplatformBleAdapter/MultiplatformBleAdapter.modulemap' not found

Working fine in android, ios debug but not working in ios release

duplicate interface definition for class 'MultiPlatformBLEAdapter'

While trying to build a React Native project using react-native-ble-plx, I am getting hundreds of errors like these:

› Compiling react-native-ble-plx Pods/MultiplatformBleAdapter » Zip+arity\ 2.swift

❌  (/Users/ted.hayes/Documents/litetime-configurator-app/ios/Pods/Headers/Public/MultiplatformBleAdapter/MultiPlatformBLEAdapter.h:11:1)

   9 | #import <Foundation/Foundation.h>
  10 | 
> 11 | @interface MultiPlatformBLEAdapter : NSObject
     | ^ duplicate interface definition for class 'MultiPlatformBLEAdapter'
  12 | 
  13 | @end
  14 | 

Anyone know what's up?

[Android] RefreshGattMoment is useless

Actually RefreshGattMoment enum consists of just one value and thus it can be replaced by simple boolean param (in connectToDevice method) indicating whether we should perform BT adapter reset or not.

Please fix the bug in android 12... targetSdkVersion 31

D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 2092): on native side observed method: getState
D/com.polidea.flutter_ble_lib.FlutterBleLibPlugin( 2092): on native side observed method: startDeviceScan
4
I/BluetoothAdapter( 2092): STATE_ON
D/BluetoothLeScanner( 2092): Start Scan with callback
W/System.err( 2092): io.reactivex.exceptions.CompositeException: 2 exceptions occurred.
W/System.err( 2092): at io.reactivex.internal.observers.LambdaObserver.onError(LambdaObserver.java:80)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.checkTerminate(ObservableFlatMap.java:496)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drainLoop(ObservableFlatMap.java:334)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.drain(ObservableFlatMap.java:326)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onError(ObservableFlatMap.java:575)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableDoOnEach$DoOnEachObserver.onError(ObservableDoOnEach.java:117)
W/System.err( 2092): at io.reactivex.internal.observers.BasicFuseableObserver.onError(BasicFuseableObserver.java:100)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onError(ObservableUnsubscribeOn.java:70)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.tryOnError(ObservableCreate.java:84)
W/System.err( 2092): at com.polidea.rxandroidble2.internal.serialization.FIFORunnableEntry$1$1.onError(FIFORunnableEntry.java:73)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn$UnsubscribeObserver.onError(ObservableUnsubscribeOn.java:70)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.tryOnError(ObservableCreate.java:84)
W/System.err( 2092): at com.polidea.rxandroidble2.internal.operations.ScanOperation.protectedRun(ScanOperation.java:50)
W/System.err( 2092): at com.polidea.rxandroidble2.internal.QueueOperation$1.subscribe(QueueOperation.java:41)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableCreate.subscribeActual(ObservableCreate.java:40)
W/System.err( 2092): at io.reactivex.Observable.subscribe(Observable.java:12284)
W/System.err( 2092): at io.reactivex.internal.operators.observable.ObservableUnsubscribeOn.subscribeActual(ObservableUnsubscribeOn.java:32)
W/System.err( 2092): at io.reactivex.Observable.subscribe(Observable.java:12284)
W/System.err( 2092): at com.polidea.rxandroidble2.internal.serialization.FIFORunnableEntry$1.run(FIFORunnableEntry.java:56)
W/System.err( 2092): at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:38)
W/System.err( 2092): at io.reactivex.internal.schedulers.ScheduledDirectTask.call(ScheduledDirectTask.java:26)
W/System.err( 2092): at java.util.concurrent.FutureTask.run(FutureTask.java:266)
W/System.err( 2092): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
W/System.err( 2092): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
W/System.err( 2092): at java.lang.Thread.run(Thread.java:920)
W/System.err( 2092): ComposedException 1 :

About rxandroidble version

Hello, I notice this library is currently using com.polidea.rxandroidble:rxandroidble:1.7.0 which was released a year ago, is there plan to upgrade to com.polidea.rxandroidble2 with latest changes? Thanks!

Leaking BleAdapter

If you create multiple clients when FlutterBleLibPlugin.createClient() overwrites the existing BleAdapter.

This means you can never destroy the previous clients, I'm pretty sure that this could cause a memory leaks as there are listeners attached etc.

[1.0.0-beta][Android] io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with.

Hi guys, I'm using version 1.0.0-beta and having this issue on Android: when a disconnection appears while monitoring some characteristic, the app will crash. Here is the error messages:

io.reactivex.exceptions.UndeliverableException: The exception could not be delivered to the consumer because it has already canceled/disposed the flow or the exception has nowhere to go to begin with. Further reading: https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#error-handling | com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from MAC='XX:XX:XX:XX:XX:XX' with status 0 (GATT_SUCCESS)
        at io.reactivex.plugins.RxJavaPlugins.onError(RxJavaPlugins.java:367)
        at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.dispose(ObservableFlatMap.java:313)
        at io.reactivex.internal.disposables.DisposableHelper.dispose(DisposableHelper.java:124)
        at io.reactivex.internal.operators.observable.ObservableReplay$ReplayObserver.dispose(ObservableReplay.java:271)
        at io.reactivex.internal.disposables.DisposableHelper.dispose(DisposableHelper.java:124)
        at io.reactivex.internal.operators.observable.ObservableRefCount.timeout(ObservableRefCount.java:156)
        at io.reactivex.internal.operators.observable.ObservableRefCount.cancel(ObservableRefCount.java:103)
        at io.reactivex.internal.operators.observable.ObservableRefCount$RefCountObserver.dispose(ObservableRefCount.java:252)
        at io.reactivex.internal.disposables.DisposableHelper.dispose(DisposableHelper.java:124)
        at io.reactivex.internal.operators.mixed.CompletableAndThenObservable$AndThenObservableObserver.dispose(CompletableAndThenObservable.java:86)
        at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.disposeAll(ObservableFlatMap.java:504)
        at io.reactivex.internal.operators.observable.ObservableFlatMap$InnerObserver.onError(ObservableFlatMap.java:572)
        at io.reactivex.internal.operators.observable.ObservableAmb$AmbInnerObserver.onError(ObservableAmb.java:181)
        at io.reactivex.internal.util.HalfSerializer.onError(HalfSerializer.java:132)
        at io.reactivex.internal.operators.observable.ObservableTakeUntil$TakeUntilMainObserver.onError(ObservableTakeUntil.java:85)
        at io.reactivex.internal.util.HalfSerializer.onError(HalfSerializer.java:132)
        at io.reactivex.internal.operators.observable.ObservableMergeWithCompletable$MergeWithObserver.onError(ObservableMergeWithCompletable.java:84)
        at io.reactivex.internal.observers.BasicFuseableObserver.onError(BasicFuseableObserver.java:100)
        at io.reactivex.internal.observers.BasicFuseableObserver.onError(BasicFuseableObserver.java:100)
        at io.reactivex.observers.SerializedObserver.onError(SerializedObserver.java:153)
        at io.reactivex.internal.operators.observable.ObservableDelay$DelayObserver$OnError.run(ObservableDelay.java:128)
        at io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66)
        at io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57)
        at java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:307)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1137)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:637)
        at java.lang.Thread.run(Thread.java:1012)
     Caused by: com.polidea.rxandroidble2.exceptions.BleDisconnectedException: Disconnected from MAC='XX:XX:XX:XX:XX:XX' with status 0 (GATT_SUCCESS)
        at com.polidea.rxandroidble2.internal.connection.RxBleGattCallback$2.onConnectionStateChange(RxBleGattCallback.java:81)
        at android.bluetooth.BluetoothGatt$1$5.run(BluetoothGatt.java:365)
        at android.bluetooth.BluetoothGatt.runOrQueueCallback(BluetoothGatt.java:1006)
        at android.bluetooth.BluetoothGatt.-$$Nest$mrunOrQueueCallback(Unknown Source:0)
        at android.bluetooth.BluetoothGatt$1.onClientConnectionState(BluetoothGatt.java:360)
        at android.bluetooth.IBluetoothGattCallback$Stub.onTransact(IBluetoothGattCallback.java:135)
        at android.os.Binder.execTransactInternal(Binder.java:1321)

Backpressure strategy API

PR #45 has introduced a workaround for short-term bursts of notifications/indications that might cause MissingBackpressureException on Android OS. This exception is raised if a producer (of notifications) is quicker than the consumer (React Native bridge). On short* bursts it is possible to buffer all notifications and deliver them more slowly — however if the burst is prolonged an OutOfMemoryException may be expected.

RxJava which is the implementation detail of MBA implementation for Android allows for different backpressure strategies:

  • buffer (as described above)
  • drop — newest, overflown, emissions are dropped
  • latest — oldest emissions are forgotten

Which strategy is the best fit for a particular application is unknown and there might be a need for exposing backpressure property to MBA API.

(Personally I do not think this issue has a high priority, we could wait if this behaviour will be requested by the users)

* short — bursts containing less data that is possible to buffer in memory — YMMV

Outdated RxBluetoothKit

Hey, it seems that this project is using some outdated version of RxBluetoothKit and also probably we could use cocoapods to manage this dependency.

Are there any plans to upgrade any time soon?

Some bluetooth devices are no longer showing up after upgrade to 0.2.0

We are using this library through react-native-ble-plx. We noticed that since MultiplatformBleAdapter was upgraded, we can no longer detect our bluetooth beacons. They are very simple bluetooth devices without any characteristics or services. Is it possible that these properties break the library?

Release master branch as newest version

Hi there, I'm sorry to ask this so directly as I know this is probably maintained by volunteers, but is it possible to release the version on master with an official tag? React Native repo's with a podspec containing this package can't point to the master branch but only to version tags. Since iOS 15, the latest version (0.1.8) of this package doesn't work anymore, and patching the dependent packages to include the master branch doesn't seem to be possible :(

iOS call to writeWithoutResponse is not resolving the Promise

Calling writeWithoutResponse on a characteristic that is not accepting writeWithoutResponse is not causing the Promise to reject, it is just not resolving at all.

Current work around is checking the char property before calling the write function.

Not sure the behavior for writeWithResponse is behaving the same?!?

macOS Support

I want to use this library in the macOS app.
Do you have any plans to support it?

Add ability to filter on other attributes in ScanFilter (Android)

https://github.com/Polidea/MultiPlatformBleAdapter/blob/d2279e0621b285f2d16382af668ae3981abf0639/android/library/src/main/java/com/polidea/multiplatformbleadapter/BleModule.java#L1232

Afternoon! I think a good addition to this library would be the ability to specify other ScanFilter attributes for Android (see https://developer.android.com/reference/android/bluetooth/le/ScanFilter for the full available list). If there is no bandwidth for this, would a PR be appreciated?

Does this allow to build Peripherals?

I know that the cross platform libraries that build on top of MultiPlatformBleAdapter cannot be used in the peripheral mode but only in central mode.

Is this functionality simply not exposed to the higher level library or is this middleware also not capable of functioning in peripheral mode?

Android is incorrectly handling multiple scans

scanSubscription is being overwritten every time startDeviceScan is called and stopDeviceScan only cancels the last subscription.

The solution for now is to cancel any ongoing scan in safeStartDeviceScan().

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.