readCharacteristic method

  1. @override
Future<BleCharacteristicValue> readCharacteristic({
  1. required BleCharacteristic characteristic,
  2. required Duration timeout,
})
override

Reads the value of a specified Bluetooth characteristic.

This method asynchronously fetches the value of a specified Bluetooth characteristic from a connected device and returns it as a BleCharacteristicValue instance.

The method will throw a TimeoutException if it does not receive a response within the specified timeout. This safeguards against situations where the asynchronous operation hangs indefinitely.

Note: A TimeoutException does not necessarily indicate a failure in reading the characteristic, but rather that a response was not received in the given timeframe. Ensure that the timeout value is appropriate for the expected device response times and consider retrying the operation if necessary.

  • address: The MAC address of the Bluetooth device. This uniquely identifies the device and is used to fetch the associated BluetoothGatt instance.
  • characteristicUuid: The UUID of the characteristic whose value is to be read. This UUID should match one of the characteristics available on the connected Bluetooth device.
  • timeout: The maximum amount of time this function will wait for a response from the platform side. If this duration is exceeded without receiving a response, a TimeoutException will be thrown. Ensure that this duration accounts for potential delays in device communication.

Returns a Future<BleCharacteristicValue> that completes with the characteristic value once it has been read.

Example usage:

try {
  BleCharacteristicValue characteristicValue = await readCharacteristic(
    address: '00:1A:7D:DA:71:13',
    characteristicUuid: '00002a00-0000-1000-8000-00805f9b34fb',
    timeout: Duration(seconds: 10),
  );
  print(characteristicValue.value);
} catch (e) {
  print('Failed to read characteristic: $e');
}

Implementation

@override
Future<BleCharacteristicValue> readCharacteristic({
  required BleCharacteristic characteristic,
  required Duration timeout,
}) async {
  final completer = Completer<BleCharacteristicValue>();

  channel.setMethodCallHandler((MethodCall call) async {
    if (call.method == 'onCharacteristicRead') {
      final BleCharacteristicValue response;
      try {
        response = BleCharacteristicValue.fromMap(call.arguments as Map<dynamic, dynamic>);
      } catch (e) {
        rethrow;
      }
      completer.complete(response);
      channel.setMethodCallHandler(
        null,
      ); // Reset the handler to avoid future calls.
    }
  });

  // Read the value of the characteristic.
  try {
    await channel.invokeMethod('readCharacteristic', {
      'address': characteristic.address,
      'characteristicUuid': characteristic.uuid,
    });
  } on PlatformException catch (e) {
    // Handle different error types accordingly.
    if (e.message?.contains('permissions') ?? false) {
      throw BluetoothPermissionException('Permission error: ${e.message}');
    } else {
      throw BluetoothReadException(
        'Failed to read BLE characteristic: ${e.message}',
      );
    }
  }

  // Implement the timeout logic.
  return completer.future.timeout(
    timeout,
    onTimeout: () {
      // If the timeout occurs, reset the method call handler and throw an error.
      channel.setMethodCallHandler(null);
      throw TimeoutException(
        'Failed to read characteristic within the given timeout',
        timeout,
      );
    },
  );
}