Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async methods and error stack traces, to reduce crashing and help debugging #126

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand
mainThreadHandler.post { messageChannel.send(message) }
}

fun trace() = Arrays.toString(Throwable().stackTrace)

override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
when (call.method) {
"isBluetoothAvailable" -> {
Expand Down Expand Up @@ -92,7 +94,7 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand
"disconnect" -> {
val deviceId = call.argument<String>("deviceId")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
cleanConnection(gatt)
result.success(null)
//FIXME If `disconnect` is called before BluetoothGatt.STATE_CONNECTED
Expand All @@ -101,7 +103,7 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand
"discoverServices" -> {
val deviceId = call.argument<String>("deviceId")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
gatt.discoverServices()
result.success(null)
}
Expand All @@ -111,15 +113,15 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand
val characteristic = call.argument<String>("characteristic")!!
val bleInputProperty = call.argument<String>("bleInputProperty")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
gatt.setNotifiable(service to characteristic, bleInputProperty)
result.success(null)
}
"requestMtu" -> {
val deviceId = call.argument<String>("deviceId")!!
val expectedMtu = call.argument<Int>("expectedMtu")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
gatt.requestMtu(expectedMtu)
result.success(null)
}
Expand All @@ -128,30 +130,30 @@ class QuickBluePlugin: FlutterPlugin, MethodCallHandler, EventChannel.StreamHand
val service = call.argument<String>("service")!!
val characteristic = call.argument<String>("characteristic")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
val readResult = gatt.getCharacteristic(service to characteristic)?.let {
gatt.readCharacteristic(it)
}
if (readResult == true)
result.success(null)
else
result.error("Characteristic unavailable", null, null)
result.error("Characteristic unavailable", null, trace())
}
"writeValue" -> {
val deviceId = call.argument<String>("deviceId")!!
val service = call.argument<String>("service")!!
val characteristic = call.argument<String>("characteristic")!!
val value = call.argument<ByteArray>("value")!!
val gatt = knownGatts.find { it.device.address == deviceId }
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", null)
?: return result.error("IllegalArgument", "Unknown deviceId: $deviceId", trace())
val writeResult = gatt.getCharacteristic(service to characteristic)?.let {
it.value = value
gatt.writeCharacteristic(it)
}
if (writeResult == true)
result.success(null)
else
result.error("Characteristic unavailable", null, null)
result.error("Characteristic unavailable", null, trace())
}
else -> {
result.notImplemented()
Expand Down Expand Up @@ -286,8 +288,9 @@ val ScanResult.manufacturerDataHead: ByteArray?
fun Short.toByteArray(byteOrder: ByteOrder = ByteOrder.LITTLE_ENDIAN): ByteArray =
ByteBuffer.allocate(2 /*Short.SIZE_BYTES*/).order(byteOrder).putShort(this).array()

fun BluetoothGatt.getCharacteristic(serviceCharacteristic: Pair<String, String>) =
getService(UUID.fromString(serviceCharacteristic.first)).getCharacteristic(UUID.fromString(serviceCharacteristic.second))
fun BluetoothGatt.getCharacteristic(serviceCharacteristic: Pair<String, String>): BluetoothGattCharacteristic {
return getService(UUID.fromString(serviceCharacteristic.first)).getCharacteristic(UUID.fromString(serviceCharacteristic.second))
}

private val DESC__CLIENT_CHAR_CONFIGURATION = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")

Expand Down
10 changes: 5 additions & 5 deletions quick_blue/lib/quick_blue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,24 @@ class QuickBlue {
static Future<bool> isBluetoothAvailable() =>
_platform.isBluetoothAvailable();

static void startScan() => _platform.startScan();
static Future<void> startScan() => _platform.startScan();

static void stopScan() => _platform.stopScan();
static Future<void> stopScan() => _platform.stopScan();

static Stream<BlueScanResult> get scanResultStream {
return _platform.scanResultStream
.map((item) => BlueScanResult.fromMap(item));
}

static void connect(String deviceId) => _platform.connect(deviceId);
static Future<void> connect(String deviceId) => _platform.connect(deviceId);

static void disconnect(String deviceId) => _platform.disconnect(deviceId);
static Future<void> disconnect(String deviceId) => _platform.disconnect(deviceId);

static void setConnectionHandler(OnConnectionChanged? onConnectionChanged) {
_platform.onConnectionChanged = onConnectionChanged;
}

static void discoverServices(String deviceId) => _platform.discoverServices(deviceId);
static Future<void> discoverServices(String deviceId) => _platform.discoverServices(deviceId);

static void setServiceHandler(OnServiceDiscovered? onServiceDiscovered) {
_platform.onServiceDiscovered = onServiceDiscovered;
Expand Down
15 changes: 8 additions & 7 deletions quick_blue_linux/lib/quick_blue_linux.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,20 +45,21 @@ class QuickBlueLinux extends QuickBluePlatform {
}

@override
void startScan() async {
Future<void> startScan() async {
await _ensureInitialized();
_log('startScan invoke success');

_activeAdapter!.startDiscovery();
final ret = _activeAdapter!.startDiscovery();
_client.devices.forEach(_onDeviceAdd);
return ret;
}

@override
void stopScan() async {
Future<void> stopScan() async {
await _ensureInitialized();
_log('stopScan invoke success');

_activeAdapter!.stopDiscovery();
return _activeAdapter!.stopDiscovery();
}

// FIXME Close
Expand All @@ -77,19 +78,19 @@ class QuickBlueLinux extends QuickBluePlatform {
}

@override
void connect(String deviceId) {
Future<void> connect(String deviceId) {
// TODO: implement connect
throw UnimplementedError();
}

@override
void disconnect(String deviceId) {
Future<void> disconnect(String deviceId) {
// TODO: implement disconnect
throw UnimplementedError();
}

@override
void discoverServices(String deviceId) {
Future<void> discoverServices(String deviceId) {
// TODO: implement discoverServices
throw UnimplementedError();
}
Expand Down
33 changes: 17 additions & 16 deletions quick_blue_platform_interface/lib/method_channel_quick_blue.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,18 @@ class MethodChannelQuickBlue extends QuickBluePlatform {

@override
Future<bool> isBluetoothAvailable() async {
bool result = await _method.invokeMethod('isBluetoothAvailable');
return result;
return await _method.invokeMethod('isBluetoothAvailable');
}

@override
void startScan() {
_method.invokeMethod('startScan')
Future<void> startScan() {
return _method.invokeMethod('startScan')
.then((_) => print('startScan invokeMethod success'));
}

@override
void stopScan() {
_method.invokeMethod('stopScan')
Future<void> stopScan() {
return _method.invokeMethod('stopScan')
.then((_) => print('stopScan invokeMethod success'));
}

Expand All @@ -50,22 +49,22 @@ class MethodChannelQuickBlue extends QuickBluePlatform {
Stream<dynamic> get scanResultStream => _scanResultStream;

@override
void connect(String deviceId) {
_method.invokeMethod('connect', {
Future<void> connect(String deviceId) {
return _method.invokeMethod('connect', {
'deviceId': deviceId,
}).then((_) => _log('connect invokeMethod success'));
}

@override
void disconnect(String deviceId) {
_method.invokeMethod('disconnect', {
Future<void> disconnect(String deviceId) {
return _method.invokeMethod('disconnect', {
'deviceId': deviceId,
}).then((_) => _log('disconnect invokeMethod success'));
}

@override
void discoverServices(String deviceId) {
_method.invokeMethod('discoverServices', {
Future<void> discoverServices(String deviceId) {
return _method.invokeMethod('discoverServices', {
'deviceId': deviceId,
}).then((_) => _log('discoverServices invokeMethod success'));
}
Expand Down Expand Up @@ -96,7 +95,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform {

@override
Future<void> setNotifiable(String deviceId, String service, String characteristic, BleInputProperty bleInputProperty) async {
_method.invokeMethod('setNotifiable', {
return _method.invokeMethod('setNotifiable', {
'deviceId': deviceId,
'service': service,
'characteristic': characteristic,
Expand All @@ -106,7 +105,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform {

@override
Future<void> readValue(String deviceId, String service, String characteristic) async {
_method.invokeMethod('readValue', {
return _method.invokeMethod('readValue', {
'deviceId': deviceId,
'service': service,
'characteristic': characteristic,
Expand All @@ -115,7 +114,7 @@ class MethodChannelQuickBlue extends QuickBluePlatform {

@override
Future<void> writeValue(String deviceId, String service, String characteristic, Uint8List value, BleOutputProperty bleOutputProperty) async {
_method.invokeMethod('writeValue', {
return _method.invokeMethod('writeValue', {
'deviceId': deviceId,
'service': service,
'characteristic': characteristic,
Expand All @@ -137,7 +136,9 @@ class MethodChannelQuickBlue extends QuickBluePlatform {
_method.invokeMethod('requestMtu', {
'deviceId': deviceId,
'expectedMtu': expectedMtu,
}).then((_) => _log('requestMtu invokeMethod success'));
}).then((_) => _log('requestMtu invokeMethod success')).catchError((e) {
_log("requestMtu error: $e"); //TODO Return future that errors if this errors
});
return await _mtuConfigController.stream.first;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,19 @@ abstract class QuickBluePlatform extends PlatformInterface {

Future<bool> isBluetoothAvailable();

void startScan();
Future<void> startScan();

void stopScan();
Future<void> stopScan();

Stream<dynamic> get scanResultStream;

void connect(String deviceId);
Future<void> connect(String deviceId);

void disconnect(String deviceId);
Future<void> disconnect(String deviceId);

OnConnectionChanged? onConnectionChanged;

void discoverServices(String deviceId);
Future<void> discoverServices(String deviceId);

OnServiceDiscovered? onServiceDiscovered;

Expand Down