chipweinberger / flutter_blue_plus

Flutter plugin for connecting and communicationg with Bluetooth Low Energy devices, on Android, iOS, macOS
Other
778 stars 469 forks source link

[Help]: Android mobile receives malformed bytes from BLE device. #843

Closed ghost closed 7 months ago

ghost commented 7 months ago

Requirements

Have you checked this problem on the example app?

Yes

FlutterBluePlus Version

1.32.1

Flutter Version

3.19.3

What OS?

Android

OS Version

Android 11

Bluetooth Module

Espressif ESP32C3_DevkitC-02v1.1

What is your problem?

When listening to the onValueReceive byte stream, in Android I receive the wrong bytes that cannot be decoded with utf8 or json, in iOS I do. I receive a different array of bytes in response even though the command sent is the same.

Logs

`D/BluetoothGatt(11806): onClientConnectionState() - status=0 clientIf=6 device=58:CF:79:2A:9B:FA`
`D/[FBP-Android](11806): [FBP] onConnectionStateChange:connected`
`D/[FBP-Android](11806): [FBP]   status: SUCCESS`
`[app] [INFO] Connection state: connected`
`D/[FBP-Android](11806): [FBP] onMethodCall: requestMtu`
`D/BluetoothGatt(11806): configureMTU() - device: 58:CF:79:2A:9B:FA mtu: 512`
`D/BluetoothGatt(11806): onConnectionUpdated() - Device=58:CF:79:2A:9B:FA interval=6 latency=0 timeout=500 status=0`
`D/BluetoothGatt(11806): onConfigureMTU() - Device=58:CF:79:2A:9B:FA mtu=500 status=0`
`D/[FBP-Android](11806): [FBP] onMtuChanged:`
`D/[FBP-Android](11806): [FBP]   mtu: 500`
`D/[FBP-Android](11806): [FBP]   status: GATT_SUCCESS (0)`
`D/[FBP-Android](11806): [FBP] onMethodCall: discoverServices`
`[app] [INFO] Mtu: 500`
`D/BluetoothGatt(11806): discoverServices() - device: 58:CF:79:2A:9B:FA`
`[app] [INFO] Mtu: 500`
`D/BluetoothGatt(11806): onSearchComplete() = Device=58:CF:79:2A:9B:FA Status=0`
`D/[FBP-Android](11806): [FBP] onServicesDiscovered:`
`D/[FBP-Android](11806): [FBP]   count: 3`
`D/[FBP-Android](11806): [FBP]   status: 0GATT_SUCCESS`
`D/BluetoothGatt(11806): onConnectionUpdated() - Device=58:CF:79:2A:9B:FA interval=32 latency=0 timeout=400 status=0`
`D/[FBP-Android](11806): [FBP] onMethodCall: setNotifyValue`
`D/BluetoothGatt(11806): setCharacteristicNotification() - uuid: 00002b2a-0000-1000-8000-00805f9b34fb enable: true`
`W/[FBP-Android](11806): [FBP] CCCD descriptor for characteristic not found: 2b2a`
`D/[FBP-Android](11806): [FBP] onMethodCall: writeCharacteristic`
`D/[FBP-Android](11806): [FBP] onCharacteristicWrite:`
`D/[FBP-Android](11806): [FBP]   chr: 2b2e`
`D/[FBP-Android](11806): [FBP]   status: GATT_SUCCESS (0)D/[FBP-Android](11806): [FBP] onMethodCall: readCharacteristic`
`[app] [INFO] {"command":"read_BTMesh"} sent.`
`D/[FBP-Android](11806): [FBP] onCharacteristicRead:`
`D/[FBP-Android](11806): [FBP]   chr: 2b2a`
`D/[FBP-Android](11806): [FBP]   status: GATT_SUCCESS (0)`
`[app] [INFO] �� R���{������`
`[app] [WARNING] [FormatException] Enable to parse [246, 238, 32, 82, 169, 26, 151, 245, 123, 232, 202, 3, 240, 128, 140, 238].`
chipweinberger commented 7 months ago

what are the exact bytes you get on iOS vs Android?

TBH, this is very unlikely to be a problem in FBP, and most likely a problem with you device or other code.

chipweinberger commented 7 months ago

closing. no response.

ghost commented 7 months ago

Hi, sorry for the delay, I've just wanted to be sure. It seems something about the characteristics inside the code. You can find the bytes in the last rows of the code added above.

�� R����{������� [246, 238, 32, 82, 169, 26, 151, 245, 123, 232, 202, 3, 240, 128, 140, 238]

The BLE device has a properly characteristic dedicated to write commands and an other one dedicated to sending the bytes to be read.

Is it correct if I use a characteristic as a variable in my provider class?

Future readCharacteristicInit() async {
  try {
    BluetoothService service = services.firstWhere(
        (service) => service.characteristics.any((chr) =>
            listEquals(chr.characteristicUuid.bytes, "2b2a".convertToIntList)),
        orElse: () {
      throw Exception("This device has not a read data dedicated service.");
    });

    readChr = service.characteristics.firstWhere((chr) => listEquals(
          chr.characteristicUuid.bytes,
          "2b2a".convertToIntList,
        ));
    await readChr!.setNotifyValue(true);
    readChrDataStream = readChr!.lastValueStream.listen((data) {
      try {
        logger.info("[READ] ${utf8.decode(data)}");
      } catch (e) {
        logger.warning("Error while parsing data from Read Chr.");
        logger.info(data);
      }
    });
    if (readChrDataStream != null)
      device.cancelWhenDisconnected(readChrDataStream!);
    logger.info("Read chr configured successfully.");
    notifyListeners();
  } on Exception catch (e) {
    logger.shout(e);
  }
}

Future writeCharacteristicInit() async {
  try {
    BluetoothService service = services.firstWhere(
        (service) => service.characteristics.any((chr) =>
            listEquals(chr.characteristicUuid.bytes, "2b2e".convertToIntList)),
        orElse: () {
      throw Exception("This device has not a write command dedicated service.");
    });
    writeChr = service.characteristics.firstWhere((chr) => listEquals(
          chr.characteristicUuid.bytes,
          "2b2e".convertToIntList,
        ));
    logger.info("Write chr configured successfully.");
    notifyListeners();
  } on Exception catch (e) {
    logger.shout(e);
  }
}

Future sendCommand(String command) async {
  if (writeChr != null) {
    try {
      await writeChr!.write(
        utf8.encode(command),
        withoutResponse: writeChr!.properties.writeWithoutResponse,
        allowLongWrite: true,
      );
      logger.info("Write: $command");
      if (Platform.isAndroid) {
        await readChr!.read();
      }
    } catch (e) {
      logger.shout(ExceptionExtension.printException("Write error error", e));
    }
  }
}