flutter_reactive_ble
flutter_reactive_ble copied to clipboard
Discover different services from Android and IOS on identical hardware
Describe the bug
when I discover a service of an OBDII UART BLE device I discover different services for IOS and Android.
Android works just fine and I expect a service ID 0000fff0-0000-1000-8000-00805f9b34fb
IOS
Android
To Reproduce Steps to reproduce the behavior: simply try to connect to the device and discover the Services
Future<bool> _discoverServices(BleDevice device) async {
try {
List<DiscoveredService> services =
await _interactor.discoverServices(device.id);
_log.finest('Services for : ${device.name} --------------------');
services.forEach((s) => _log.finest('${s.toString()}'));
_discoveredService = services.firstWhere(
(service) =>
service.serviceId.toString() ==
'0000fff0-0000-1000-8000-00805f9b34fb',
orElse: () => null);
if (_discoveredService == null) {
_log.finest(
'Could not find Services of the devices which are matching!');
return false;
}
List<DiscoveredCharacteristic> characteristics;
try {
characteristics = _discoveredService.characteristics;
} catch (error) {
_log.finest('Call to discover services failed: $error ');
return false;
}
var writeCharacteristic = characteristics.firstWhere(
(char) =>
char.characteristicId.toString() ==
'0000fff2-0000-1000-8000-00805f9b34fb',
orElse: () => null);
_writeCharacteristic = QualifiedCharacteristic(
characteristicId: writeCharacteristic.characteristicId,
serviceId: _discoveredService.serviceId,
deviceId: device.id);
var notifyCharacteristic = characteristics.firstWhere(
(char) =>
char.characteristicId.toString() ==
'0000fff1-0000-1000-8000-00805f9b34fb',
orElse: () => null);
_notifyCharacteristic = QualifiedCharacteristic(
characteristicId: notifyCharacteristic.characteristicId,
serviceId: _discoveredService.serviceId,
deviceId: device.id);
if (_notifyCharacteristic == null || _writeCharacteristic == null) {
_log.finest('Could not find required characteristics');
return false;
}
_notifySubscription =
_interactor.subScribeToCharacteristic(_notifyCharacteristic).listen(
(data) {
if (isConnected.isTrue && _disconnectLock.inLock.isFalse)
_notify.value = data;
},
);
_notifySubscription.onError((error) {
_log.finest('Error: Notify Stream error: $error');
_disconnect();
loading.value = false;
});
return true;
} catch (e) {
rethrow;
}
}
Expected behavior Identical characteristics on IOS and Android
I tried doing the same with a general BLE scanner application nRF (Android)
Smartphone / tablet
- Device: Iphone 6s and Motorola Edge 2021
- OS: [e.g. iOS 15, Android 11]
- Package version: flutter_reactive_ble: 5.0.2
- flutter version
jay@mini obdchk % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.8.1, on macOS 11.6 20G165 darwin-x64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.60.2)
[✓] VS Code (version 1.44.2)
[✓] VS Code (version 1.42.1)
[✓] VS Code (version 1.41.1)
[✓] Connected device (2 available)
Peripheral device
- Vendor, model: OBDII BLE Uart device Carista (support Bluetooth Classic and BLE)
- https://caristaapp.com/
- Does it run a custom firmware/software: no
if i change my code like this it all starts working. I would not expected that...
Future<bool> _discoverServices(BleDevice device) async {
try {
List<DiscoveredService> services =
await _interactor.discoverServices(device.id);
_log.finest('Services for : ${device.name} --------------------');
services.forEach((s) => _log.finest('${s.toString()}'));
_discoveredService = services.firstWhere(
(service) =>
service.serviceId.toString() ==
'0000fff0-0000-1000-8000-00805f9b34fb' ||
service.serviceId.toString() == 'fff0',
orElse: () => null);
if (_discoveredService == null) {
_log.finest(
'Could not find Services of the devices which are matching!');
return false;
}
List<DiscoveredCharacteristic> characteristics;
try {
characteristics = _discoveredService.characteristics;
} catch (error) {
_log.finest('Call to discover services failed: $error ');
return false;
}
var writeCharacteristic = characteristics.firstWhere(
(char) =>
char.characteristicId.toString() ==
'0000fff2-0000-1000-8000-00805f9b34fb' ||
char.characteristicId.toString() == 'fff2',
orElse: () => null);
_writeCharacteristic = QualifiedCharacteristic(
characteristicId: writeCharacteristic.characteristicId,
serviceId: _discoveredService.serviceId,
deviceId: device.id);
var notifyCharacteristic = characteristics.firstWhere(
(char) =>
char.characteristicId.toString() ==
'0000fff1-0000-1000-8000-00805f9b34fb' ||
char.characteristicId.toString() == 'fff1',
orElse: () => null);
_notifyCharacteristic = QualifiedCharacteristic(
characteristicId: notifyCharacteristic.characteristicId,
serviceId: _discoveredService.serviceId,
deviceId: device.id);
if (_notifyCharacteristic == null || _writeCharacteristic == null) {
_log.finest('Could not find required characteristics');
return false;
}
_notifySubscription =
_interactor.subScribeToCharacteristic(_notifyCharacteristic).listen(
(data) {
if (isConnected.isTrue && _disconnectLock.inLock.isFalse)
_notify.value = data;
},
);
_notifySubscription.onError((error) {
_log.finest('Error: Notify Stream error: $error');
_disconnect();
loading.value = false;
});
return true;
} catch (e) {
rethrow;
}
}
Having the same problem. It looks like with services that have the predefined postfix of "0000-1000-8000-00805f9b34fb", iOS removes the postfix, but Android keeps it in. As a cross-platform library, reactive-ble should fix this and standardize on one format or the other, and not just pass through whatever the underlying libraries pass.