How to write/notify to characteristic with identical service and char uuids in Flutter

249 Views Asked by At

This might be a package-specific issue, but I'm hoping to use the one I'm already familiar with if possible...

I am using flutter_reactive_ble to handle my ble communications from a ble device to an android/iOS device.

I've had no issues using all the typical functionalities in the past, but I'm now in a situation where I have some characteristics that only differ by their property - whether they can read/write/notify/indicate.

Using the write/subscribe functions of the package as an example, they need to take in a QualifiedCharacteristic object to perform their write/subscribe actions. That object consists only of a service uuid, char uuid and a device id. This is fine most of the time, but in the situation described above, the combination of those 3 fields isn't enough to filter things down to a single characteristic. The characteristic documentation of the ble device I'm working with shares those IDs. This results in an exception being thrown by the package's functions, because of multiple characteristic matches.

I've looked at the documentation and ble.notify() and ble.getDiscoveredServices() are the only suggestions to get around problems like this. But I tried both those solutions and while you can get the context of the right characteristic this way, you can't use that sort of data for the write/subscribe functions. They only accept a QualifiedCharacteristic object...which doesn't let you factor in other fields found in a service/characteristic object that provide the differntiation needed, like the isWritable boolean or instanceId of a particular characteristic.

Snippet of of what I've tried below:

Future<bool?> writeCharacteristic(
      String? serviceUuidString, String? charUuidString, DiscoveredDevice? device, int sentByte) async {
    final services = await ble!.getDiscoveredServices(device.id);
    Service? service;
for (int i = 0; i < services.length; ++i) {
  if (services[i].id.toString().contains(serviceUuidString)) {
    serviceUuid = services[i].id;
    service = services[i];
  }
}
if (serviceUuid == null) {
  debugPrint("No service matching input");
  return null;
}
           for (int i = 0; i < service!.characteristics.length; ++i) {
      switch (charTypeFilter) {
        case CharTypeFilter.writing:
          if (service.characteristics[i].isWritableWithResponse &&
              service.characteristics[i].id.toString().contains(charUuidString.toLowerCase())) {
            charUuid = service.characteristics[i].id;
            i = service.characteristics.length;
            break;
          }
)

Not the full code, but the example above illustrates finding the appropriate characteristic out of the list of service objects using getDiscoveredServices(). But ultimately the object has to be a QualifiedCharacteristic object when passed into the write function below...

 QualifiedCharacteristic characteristic = QualifiedCharacteristic(
   serviceId: serviceUuid,
   characteristicId: charUuid,
   deviceId: device.id,
 );

     await ble!.writeCharacteristicWithResponse(characteristic, value: [sentByte]).timeout(const Duration(seconds: 5));

Same issue with notify():

Uuid? serviceUuid = await stringToUuidParser(serviceUuidString);
Uuid? charUuid = await stringToUuidParser(charUuidString);
Characteristic? selectedCharacteristic;

final resolvedCharacteristics = await ble!.resolve(QualifiedCharacteristic(
  serviceId: serviceUuid,
  characteristicId: charUuid,
  deviceId: device.id,
));

for (Characteristic characteristic in resolvedCharacteristics) {
  if (characteristic.isWritableWithResponse && characteristic.id.toString().contains(charUuidString)) {
    selectedCharacteristic = characteristic;
    break; 
  }
}

You can get the context of the characteristic data you want, but it has to turn into a QualifiedCharacteristic object before you can attempt the write. Then you run into the ambigious characteristic problem again.

I did stumble across this github post on the same topic, but I haven't been able to make sense if these changes solve the issue https://github.com/PhilipsHue/flutter_reactive_ble/pull/776.

Been stuck on this one for awhile. Any input would be appreciated.

0

There are 0 best solutions below