I am receiving data from my BLE device using the flutter_reactive_ble package.
I have the following method :
_broadcastCharacteristSubscription = _flutterReactiveBle
.subscribeToCharacteristic(_broadCastCharacteristic!)
.listen((event) {
Uint8List data = Uint8List.fromList(event);
_handleBytesReceived(data);
});
This data is byte stuffed and compressed into chunks.
I have done the byte stuffing to reconstitute the compressed content that looks like this :
I/flutter (13164): Current payload before decompression : xUO�� ��>�Ew�gL
Now i need to decompress this, so i have tried using ZLibDecoder
because my client told me they use Zlib for compression :
So i have implemented the following :
void _handleBytesReceived(Uint8List data) {
String decoded = _decoder.convert(data);
print("Ascii string compressed data : $decoded");
if (currentPayload.isEmpty) {
currentPayload = decoded;
print("Current payload is now : $currentPayload");
}
else {
for (var element in decoded.characters) {
if (element != "~") {
currentPayload += element;
}
else {
currentPayload = currentPayload.replaceAll("~", "");
print("Current payload before decompression : $currentPayload");
currentPayload = _unzipPayload(currentPayload);
print("Current payload after : $currentPayload");
currentPayload = "";
break;
}
}
}
}
String _unzipPayload(String encoded) {
return String.fromCharCodes(ZLibCodec(level: 6).decode(encoded.codeUnits));
}
And i am getting the following error :
I/flutter (13164): Error from outside Flutter : FormatException: Filter error, bad data
I/flutter (13164): #0 _FilterImpl.processed (dart:io-patch/filter_patch.dart:13:71)
I/flutter (13164): #1 _FilterSink.addSlice (dart:io/data_transformer.dart:505:29)
I/flutter (13164): #2 _FilterSink.add (dart:io/data_transformer.dart:489:5)
I/flutter (13164): #3 ZLibDecoder.convert (dart:io/data_transformer.dart:363:9)
I/flutter (13164): #4 Codec.decode (dart:convert/codec.dart:30:34)
I/flutter (13164): #5 ReactiveBleAPI._unzipPayload (package:myappname/api/reactive_ble_api.dart:213:53)
I/flutter (13164): #6 ReactiveBleAPI._handleBytesReceived (package:myappname/api/reactive_ble_api.dart:203:28)
I/flutter (13164): #7 ReactiveBleAPI._connectToDevice.<anonymous closure> (package:myappname/api/reactive_ble_api.dart:171:9)
I/flutter (13164): #8 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
I/flutter (13164): #9 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
I/flutter (13164): #10 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
I/flutter (13164): #11 _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:776:19)
I/flutter (13164): #12 _StreamController._add (dart:async/stream_controller.dart:650:7)
I/flutter (13164): #13 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
I/flutter (13164): #14 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
I/flutter (13164): #15 _DelayedData.perform (dart:async/stream_impl.dart:515:14)
I/flutter (13164): #16 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11)
I/flutter (13164): #17 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:591:7)
I/flutter (13164): #18 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
I/flutter (13164): #19 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
The decompression seems to failed, and i am pretty sure that the data is not corrupted unless i have got it wrong with my above conversions.
Am i doing something wrong with the currentPayload.codeUnits
for example ? or in any part of it ?
EDIT : Here is the new code without trying to decode the initial bytes from the BLE (removing String decoded = _decoder.convert(data)
as suggested in the comments :
void _resetPayload() {
print("Current payload before compression : $currentPayload");
List<int> finalList = [];
for (var element in currentPayload) {
if (element != 126) {
finalList.add(element);
}
}
String output = _unzipPayload(Uint8List.fromList(finalList));
print("Current payload after compression : $output");
currentPayload = Uint8List(0);
}
void _handleBytesReceived(Uint8List data) {
print("Raw data : $data");
//String decoded = _decoder.convert(data);
// print("Decoded ascii data : $decoded");
if (currentPayload.isEmpty) {
currentPayload = data;
}
print("Current payload is : $currentPayload");
for (var element in data.toList()) {
if (currentPayload.contains(126)) {
if (element == 126) {
_resetPayload();
}
else {
currentPayload.add(element);
}
}
}
}
String _unzipPayload(Uint8List encoded) {
try {
List<int> decoded = _codec.decode(encoded);
print("Decoded : $decoded");
String result = String.fromCharCodes(decoded);
print("Result : $result");
return result;
} catch (error) {
print("Error unzipping $error");
}
return "";
}
And here are the logs i am getting with the above code for example :
I/flutter (25368): Raw data : [126, 120, 1, 85, 79, 209, 10, 131, 48, 12, 252, 151, 60, 23, 113, 67, 157, 245, 103, 36]
I/flutter (25368): Current payload is : [126, 120, 1, 85, 79, 209, 10, 131, 48, 12, 252, 151, 60, 23, 113, 67, 157, 245, 103, 36]
I/flutter (25368): Current payload before compression : [120, 1, 85, 79, 209, 10, 131, 48, 12, 252, 151, 60, 23, 113, 67, 157, 245, 103, 36]
I/flutter (25368): Decoded : []
I/flutter (25368): Result :
I/flutter (25368): Current payload after compression :
D/BluetoothGatt(25368): onConnectionUpdated() - Device=C4:DE:E2:90:A6:DE interval=36 latency=0 timeout=500 status=0
I/flutter (25368): Raw data : [126, 120, 1, 85, 140, 65, 10, 133, 48, 16, 67, 239, 146, 117, 23, 174, 123, 21, 145, 207]
I/flutter (25368): Current payload is : [126, 120, 1, 85, 140, 65, 10, 133, 48, 16, 67, 239, 146, 117, 23, 174, 123, 21, 145, 207]
I/flutter (25368): Current payload before compression : [120, 1, 85, 140, 65, 10, 133, 48, 16, 67, 239, 146, 117, 23, 174, 123, 21, 145, 207]
I/flutter (25368): Decoded : []
I/flutter (25368): Result :
I/flutter (25368): Current payload after compression :
FINAL EDIT / ANSWER : Payload was empty because i was not requesting a higher MTU, not enough bytes were transferred. I have set it to 180 according to my BLE device.
You seem to be treating a stream of bytes as if they were characters. This is not a String (that's why you're seeing �; that's the decoder telling you it's not valid UTF-8). You need to operate on the Uint8List directly. You should not call String decoded = _decoder.convert(data)
.