PhilipsHue / flutter_reactive_ble

Flutter library that handles BLE operations for multiple devices.
https://developers.meethue.com/
Other
662 stars 326 forks source link

Responses from ble devices get trimmed #783

Closed DanielMbalyo closed 1 year ago

DanielMbalyo commented 1 year ago

Describe the bug I am sending a command to the ble device and it returns responses in chunks and they are not complete. My log printouts are as follows:

I/flutter (27750): DiscoveredDevice(id: C0:20:11:10:AD:BD, name: FR8000_AT
I/flutter (27750): [UPTE_AI/64B96F27B94C4568F97C7884/FEF59/1690457367]
I/flutter (27750): Discovered services
I/flutter (27750): Found service 0783b03e-8535-b5a0-7140-a304d2495cb7
I/flutter (27750): Found characteristics
D/BluetoothGatt(27750): setCharacteristicNotification() - uuid: 0783b03e-8535-b5a0-7140-a304d2495cb8 enable: true
I/flutter (27750): Writing to 0783b03e-8535-b5a0-7140-a304d2495cba
I/flutter (27750): Received response **DE_NA/UPTE_AI/64B96F27B94C4568F97C7884/FEF59/1690457
I/flutter (27750): Received response 3/NOT_ACTIVATED/434
I/flutter (27750): Final response: **DE_NA/UPTE_AI/64B96F27B94C4568F97C7884/FEF59/16904573/NOT_ACTIVATED/434  
I/flutter (27750): [**DE_NA/UPTE_AI/64B96F27B94C4568F97C7884/FEF59/16904573/NOT_ACTIVATED/434]

To Reproduce Steps to reproduce the behavior:

  1. Command sending implementation
  Future<String> _sendCommand(String command) async {
    StreamSubscription<List<int>>? stream;
    try {
      List<int> commandData = utf8.encode(command);
      String response = '';
      Uuid serviceUuid = Uuid.parse('0783b03e-8535-b5a0-7140-a304d2495cb7');
      Uuid writeUuid = Uuid.parse('0783b03e-8535-b5a0-7140-a304d2495cba');
      Uuid readUuid = Uuid.parse('0783b03e-8535-b5a0-7140-a304d2495cb8');
      List<DiscoveredService> services = await _flutterReactiveBle.discoverServices(_connDevice!.id);
      print('Discovered services');
      DiscoveredService? service = services.firstWhereOrNull((service) => service.serviceId == serviceUuid);
      if (service != null) {
        print('Found service ${service.serviceId}');
        List<DiscoveredCharacteristic> characteristics = service.characteristics;
        DiscoveredCharacteristic? characteristic1 = characteristics.firstWhereOrNull(
          (characteristic) => characteristic.characteristicId == writeUuid);
        DiscoveredCharacteristic? characteristic2 = characteristics.firstWhereOrNull(
          (characteristic) => characteristic.characteristicId == writeUuid);
        if (characteristic1 != null && characteristic2 != null) {
          print('Found characteristics');
          final qs1 = QualifiedCharacteristic(serviceId: serviceUuid, characteristicId: writeUuid, deviceId: _connDevice!.id); 
          final qs2 = QualifiedCharacteristic(serviceId: serviceUuid, characteristicId: readUuid, deviceId: _connDevice!.id); 
          stream = _flutterReactiveBle.subscribeToCharacteristic(qs2).listen((data) async {
            print('Received response ${utf8.decode(data)}');
            response += utf8.decode(data);
          }, onError: (dynamic error) {
            print('Encountered an error $error');
          });
          await _flutterReactiveBle.writeCharacteristicWithoutResponse(qs1, value: commandData);
          print('Writing to ${characteristic1.characteristicId}');
        }   
      }
      await Future.delayed(const Duration(milliseconds: 1000), () => print('Final response: $response'));
      return response;
    } finally {
      stream?.cancel();
    }
  }

Expected behavior I want to receive the complete command, if possible, or how can i improve receiving it. Below is an example of the command. **DE_NA/UPTE_AI/64B96F27B94C4568F97C7884/FEF59/16904573/NOT_ACTIVATED/434322##

Smartphone / tablet

Peripheral device

western-hoolock commented 1 year ago

You're receiving the data in a notification and as far as I know a single notification will never exceed the the MTU and data received by notification will not be assembled automatically. (as opposed to doing a long read yourself)

Two things you can try:

If all data you are receiving from the device through notifications is small (i.e. less than the maximum MTU both sides support) then increasing the MTU would be the best option.

DanielMbalyo commented 1 year ago

I redused the length of the commands, seems it was a device limitation and it worked well with other devices