flutter_blue icon indicating copy to clipboard operation
flutter_blue copied to clipboard

Error with reading a characteristics: PlatformException(read_characteristic_error...

Open marileen-jansen opened this issue 6 years ago • 26 comments

Hi. I get an exeption when trying to read a characteristic ( c.read() )

Here is the exeption: Exception has occurred. PlatformException (PlatformException(read_characteristic_error, unknown reason, may occur if readCharacteristic was called before last read finished., null))

Can you please help me with this?

marileen-jansen avatar Nov 08 '19 09:11 marileen-jansen

@marileen-jansen Did you solve this problem?

flonguini avatar Nov 13 '19 09:11 flonguini

@marileen-jansen Did you solve this problem?

No I have not.

marileen-jansen avatar Nov 19 '19 06:11 marileen-jansen

add one

chaochaox1990 avatar Nov 22 '19 05:11 chaochaox1990

+1

anilslabs avatar Dec 20 '19 11:12 anilslabs

I realized I had a characteristic that did not have a read property in my list of characteristics.

I added this if statement and everything seemed to work fine.

if (c.properties.read)
        {
          List<int> value = await c.read();
          print(value);
        }

LeviDahl avatar Jan 16 '20 09:01 LeviDahl

Still same problem.

mozerrr avatar Feb 09 '20 17:02 mozerrr

This library is unfortunately have not been maintained lately. Have you guys tried https://github.com/Polidea/FlutterBleLib? It looks promising. I will move there I guess.

aytunch avatar Feb 09 '20 19:02 aytunch

@aytunch The plugin at FlutterBleLib is maintained by the Polidea folks, and utilizes their tried and tested platform libs for Android and iOS. I'm sure you'll be in good hands.

FlutterBlue is still under development and I'll be disclosing project plans for 2020 in the coming weeks.

Thanks.

pauldemarco avatar Feb 09 '20 20:02 pauldemarco

forEach doesn’t wait for callback return, it just launches them and returns. If you are going to perform async operations inside forEach, you have to use «for in» instead.

Don’t: services.forEach((service) async { // do something with service }); Do: for (BluetoothService service in services) { // do something with service }

mozerrr avatar Feb 10 '20 07:02 mozerrr

you should listen to it.

for(BluetoothService service in services){ print("service id is : ${service.uuid}"); if (_matchSmartLockServiceId(service.uuid.toString())) { var characteristics = service.characteristics; for (BluetoothCharacteristic c in characteristics) { print("### ${c.uuid}"); String c_id = c.uuid.toString(); if (_getBlueToothFunctionCode(c_id) == ""){ await c.setNotifyValue(true); c.value.listen((value) { _readInfoFromDevice(value); }); }else if (_getBlueToothFunctionCode(c_id) == ""){ _sendMsg(c); } } } _readInfoFromDevice(List values) async{ if(values.length>0){ print("value: ${values}"); } } _sendMsg(BluetoothCharacteristic c) async{ //do something }
bool _matchSmartLockServiceId(String serviceId) { //do your logic if (serviceId.isEmpty) return false; if (serviceId.substring(0, 4) == "****") return true; return false; }

CrazyAndy avatar Mar 15 '20 06:03 CrazyAndy

+ 1

jiyarong avatar Jul 09 '20 09:07 jiyarong

+1

realrk95 avatar Nov 30 '20 15:11 realrk95

+1

naxiemolv avatar Dec 05 '20 14:12 naxiemolv

Confirmed: This happens on iOS only for me now. Android is working 100%. Shifted to flutter_reactive_ble and it works perfectly there.

realrk95 avatar Dec 05 '20 21:12 realrk95

+1

HyBLF avatar Dec 11 '20 07:12 HyBLF

Note that this only works when the characteristic support Notifications - not all will do.

so check for c.isNotifying and then either read, or listen for a notification

you should listen to it.

if (_getBlueToothFunctionCode(c_id) == "****"){ await c.setNotifyValue(true); c.value.listen((value) { _readInfoFromDevice(value);

qurm avatar Jan 09 '21 05:01 qurm

I get the above mentioned error even if I try to run the Flutter Blue example code. The moment I press the sync and try enabling notifications for a characteristic, the error is thrown.

jjanixx avatar Jan 12 '21 09:01 jjanixx

@qurm I'm new to this and I'm facing the same issue. Can you please tell me what the read() and listen() functions are doing and why I should be using one over the other.

AryanSethi avatar May 07 '21 12:05 AryanSethi

Any suggestions? Same problem in version 0.8.0!

yuriboeira11tx avatar May 17 '21 14:05 yuriboeira11tx

I just hit this bug as well. The only information that I can give that might be helpful: When I place a breakpoint on the read() call it will successfully complete the read. This suggests that if you attempt to do two different actions, even on different characteristics that it will throw. For example if I'm subscribed(notify) on one characteristic and my code does something to prompt a notification and at the same time requests a read, the BLE request fails.

Outside of some lib level queue, retry or wait to guarantee that you don't do two things at once, I'm not sure how to fix/workaround.

cthurston avatar May 20 '21 23:05 cthurston

Hello everyone, the problem is finally solved. There must be a time interval between two data readings. The problem is limited to Android, and iOS devices do not have this problem. 大家好,问题最终解决了,两次数据读取必须要有一个时间间隔,问题仅限安卓,iOS设备没有此问题。

    if (charUuid == "FirstCharId") {
      await characteristic.read();
    } else if (charUuid == "SecondCharId") {
      Future.delayed(Duration(milliseconds: 500), () async {
        await characteristic.read();
      });
    }

ios9developer avatar Sep 28 '21 07:09 ios9developer

Was running into this issue, turned out to be 2 problems for me.

  1. I did not have a READ property set on my characteristic. I had NOTIFY, but not READ. This meant I could get partial data by listening, but could not read the full message.
  2. I could not read while sending a message, so I had to wait for the send to complete before I could read. Even though I was sending a message to a different characteristic.

Hope this helps someone, BLE is hard 😅

Mitchlol avatar Dec 19 '21 09:12 Mitchlol

Still couldnt find a resolve for this, please let us know if there is any update on this for a fix

hammvdh avatar Mar 09 '22 09:03 hammvdh

Hello world. I solved the problem in the following way:

  getDeviceInfo() async {
    List<BluetoothService> services = await widget.device.discoverServices();
    for (final BluetoothService service in services) {
      var characteristics = service.characteristics;
      for (final BluetoothCharacteristic c in characteristics) {
        if (c.properties.read) {
          List<int> value = await c.read();
          if (value.isNotEmpty) {
            try {
              final String decodedBytes = utf8Decoder.convert(value); //   create decoder in your class: final utf8Decoder = utf8.decoder;
              decodedValues.add(decodedBytes); // decodedValues this is an array in my class
            } catch (e) {
              print("ERROR DECODING ${e}");
            }
          } else {
            print("NO DATA");
          }
        }
      }
    }
  }

Twocram avatar Apr 13 '22 05:04 Twocram

Thanks man it's work for me.

azizur-rahaman avatar Jul 01 '23 17:07 azizur-rahaman

Other given answers helped me as well 👍🏻 I'm just trying to write what I observed.

We cannot read values from a characteristic after we have started observing them, and if we just start observing them (i.e. by setting setNotifyValue(true) and then listening to the value stream) then it won't provide any initial value, it will only start emitting if the given characteristic's value has been changed at least once.

Therefore, to tackle this issue, I first read the characteristic and cached its response in a variable, and only then started observing it.

Code example

Future<Stream<Color>> ledColor({required String initialHexColor}) async {
    final ledColorCharacteristic = characteristic(BLEConstants.ledInfoCharacteristic);

    // This can be tricky (i.e. always remember that if you want to both read
    // and observe a characteristic, then always complete the read operation
    // first and only then start observing its values, otherwise the app will
    // throw a read_characteristic_error. That's why, even though we'll not use
    // this read value instantly, we're caching it before we have to
    // setNotifyValue(true).
    final values = await ledColorCharacteristic.read();

    if (!ledColorCharacteristic.isNotifying) {
      await ledColorCharacteristic.setNotifyValue(true);
    }

    Stream<Color> getColorStream() async* {
      yield _colorFromValues(values); // Initiate the stream with the cached value
      yield* ledColorCharacteristic.value.map(_colorFromValues);
    }

    return getColorStream();
  }

shubhamsinghshubham777 avatar Jul 05 '23 04:07 shubhamsinghshubham777