Skip to content

Commit

Permalink
fix missed exceptions for descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
chipweinberger committed May 2, 2023
1 parent a0dc6bd commit f6d3e6d
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 71 deletions.
14 changes: 6 additions & 8 deletions lib/src/bluetooth_characteristic.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,14 +94,13 @@ class BluetoothCharacteristic {
(p.characteristic.serviceUuid == request.serviceUuid))
.map((p) => p.characteristic.value);

// Important: to not miss the result, we must listen
// for results *before* invoking 'readCharacteristic'
StreamBuf<List<int>> queue = StreamBuf(responseStream);
// Start listening now to ensure we don't miss the response
Future<List<int>> futureResponse = responseStream.first;

await FlutterBluePlus.instance._channel
.invokeMethod('readCharacteristic', request.writeToBuffer());

List<int> responseValue = await queue.next();
List<int> responseValue = await futureResponse;

// Update the _value
_value.add(responseValue);
Expand Down Expand Up @@ -137,15 +136,14 @@ class BluetoothCharacteristic {
(p.request.characteristicUuid == request.characteristicUuid) &&
(p.request.serviceUuid == request.serviceUuid));

// Important: to not miss the result, we must listen
// for results *before* invoking 'writeCharacteristic'
StreamBuf<protos.WriteCharacteristicResponse> queue = StreamBuf(responseStream);
// Start listening now to ensure we don't miss the response
Future<protos.WriteCharacteristicResponse> futureResponse = responseStream.first;

await FlutterBluePlus.instance._channel
.invokeMethod('writeCharacteristic', request.writeToBuffer());

// wait for response, so that we can check for success
protos.WriteCharacteristicResponse response = await queue.next();
protos.WriteCharacteristicResponse response = await futureResponse;
if (!response.success) {
throw Exception('Failed to write the characteristic');
}
Expand Down
87 changes: 51 additions & 36 deletions lib/src/bluetooth_descriptor.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,56 +32,71 @@ class BluetoothDescriptor {
..characteristicUuid = characteristicUuid.toString()
..serviceUuid = serviceUuid.toString();

Stream<protos.ReadDescriptorResponse> responseStream =
FlutterBluePlus.instance._methodStream
.where((m) => m.method == "ReadDescriptorResponse")
.map((m) => m.arguments)
.map((buffer) => protos.ReadDescriptorResponse.fromBuffer(buffer))
.where((p) =>
(p.request.remoteId == request.remoteId) &&
(p.request.descriptorUuid == request.descriptorUuid) &&
(p.request.characteristicUuid == request.characteristicUuid) &&
(p.request.serviceUuid == request.serviceUuid));

// Start listening now to ensure we don't miss the response
Future<protos.ReadDescriptorResponse> futureResponse = responseStream.first;

await FlutterBluePlus.instance._channel
.invokeMethod('readDescriptor', request.writeToBuffer());

return FlutterBluePlus.instance._methodStream
.where((m) => m.method == "ReadDescriptorResponse")
.map((m) => m.arguments)
.map((buffer) => protos.ReadDescriptorResponse.fromBuffer(buffer))
.where((p) =>
(p.request.remoteId == request.remoteId) &&
(p.request.descriptorUuid == request.descriptorUuid) &&
(p.request.characteristicUuid == request.characteristicUuid) &&
(p.request.serviceUuid == request.serviceUuid))
.map((d) => d.value)
.first
.then((d) {
_value.add(d);
return d;
});
.invokeMethod('readDescriptor', request.writeToBuffer());

protos.ReadDescriptorResponse response = await futureResponse;

List<int> readValue = response.value;

_value.add(readValue);

return readValue;
}


/// Writes the value of a descriptor
Future<Null> write(List<int> value) async {
Future<void> write(List<int> value) async {
var request = protos.WriteDescriptorRequest.create()
..remoteId = deviceId.toString()
..descriptorUuid = uuid.toString()
..characteristicUuid = characteristicUuid.toString()
..serviceUuid = serviceUuid.toString()
..value = value;

Stream<protos.WriteDescriptorResponse> responseStream =
FlutterBluePlus.instance._methodStream
.where((m) => m.method == "WriteDescriptorResponse")
.map((m) => m.arguments)
.map((buffer) => protos.WriteDescriptorResponse.fromBuffer(buffer))
.where((p) =>
(p.request.remoteId == request.remoteId) &&
(p.request.descriptorUuid == request.descriptorUuid) &&
(p.request.characteristicUuid == request.characteristicUuid) &&
(p.request.serviceUuid == request.serviceUuid));

// Start listening now to ensure we don't miss the response
Future<protos.WriteDescriptorResponse> futureResponse = responseStream.first;

await FlutterBluePlus.instance._channel
.invokeMethod('writeDescriptor', request.writeToBuffer());

return FlutterBluePlus.instance._methodStream
.where((m) => m.method == "WriteDescriptorResponse")
.map((m) => m.arguments)
.map((buffer) => protos.WriteDescriptorResponse.fromBuffer(buffer))
.where((p) =>
(p.request.remoteId == request.remoteId) &&
(p.request.descriptorUuid == request.descriptorUuid) &&
(p.request.characteristicUuid == request.characteristicUuid) &&
(p.request.serviceUuid == request.serviceUuid))
.first
.then((w) => w.success)
.then((success) => (!success)
? throw Exception('Failed to write the descriptor')
: null)
.then((_) => _value.add(value))
.then((_) => null);
.invokeMethod('writeDescriptor', request.writeToBuffer());

protos.WriteDescriptorResponse response = await futureResponse;

if (!response.success) {
throw Exception('Failed to write the descriptor');
}

_value.add(value);

return Future.value();
}


@override
String toString() {
return 'BluetoothDescriptor{uuid: $uuid, deviceId: $deviceId, serviceUuid: $serviceUuid, characteristicUuid: $characteristicUuid, value: ${_value.value}}';
Expand Down
27 changes: 0 additions & 27 deletions lib/src/utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -194,30 +194,3 @@ Stream<T> mergeStreams<T>(List<Stream<T>> streams) {

return controller.stream;
}

// caches all items received
// this lets us access the items at a later time
class StreamBuf<T> {
final Stream<T> _stream;
final List<T> _buffer = [];
Completer<void> _completer = Completer<void>();

StreamBuf(this._stream) {
_stream.listen((event) {
_buffer.add(event);
if (!_completer.isCompleted) {
_completer.complete();
}
});
}

Future<T> next() async {
if (_buffer.isNotEmpty) {
return _buffer.removeAt(0);
} else {
await _completer.future;
_completer = Completer<void>();
return _buffer.removeAt(0);
}
}
}

0 comments on commit f6d3e6d

Please sign in to comment.