write method

Future<void> write(
  1. List<int> value, {
  2. bool withoutResponse = false,
  3. bool allowLongWrite = false,
  4. int timeout = 15,
})

Writes a characteristic.

  • withoutResponse: If true, the write is not guaranteed and always returns immediately with success. If false, the write returns error on failure.
  • allowLongWrite: if set, larger writes > MTU are allowed (up to 512 bytes). This should be used with caution. 1. it can only be used with response 2. the peripheral device must support the 'long write' ble protocol. 3. Interrupted transfers can leave the characteristic in a partially written state 4. If the mtu is small, it is very very slow.

Implementation

Future<void> write(List<int> value,
    {bool withoutResponse = false, bool allowLongWrite = false, int timeout = 15}) async {
  //  check args
  if (withoutResponse && allowLongWrite) {
    throw ArgumentError("cannot longWrite withoutResponse, not allowed on iOS or Android");
  }

  // check connected
  if (device.isDisconnected) {
    throw FlutterBluePlusException(
        ErrorPlatform.fbp, "writeCharacteristic", FbpErrorCode.deviceIsDisconnected.index, "device is not connected");
  }

  // Only allow a single ble operation to be underway at a time
  _Mutex mtx = _MutexFactory.getMutexForKey("global");
  await mtx.take();

  try {
    final writeType = withoutResponse ? BmWriteType.withoutResponse : BmWriteType.withResponse;

    var request = BmWriteCharacteristicRequest(
      remoteId: remoteId,
      characteristicUuid: characteristicUuid,
      serviceUuid: serviceUuid,
      secondaryServiceUuid: null,
      writeType: writeType,
      allowLongWrite: allowLongWrite,
      value: value,
    );

    var responseStream = FlutterBluePlus._methodStream.stream
        .where((m) => m.method == "OnCharacteristicWritten")
        .map((m) => m.arguments)
        .map((args) => BmCharacteristicData.fromMap(args))
        .where((p) => p.remoteId == request.remoteId)
        .where((p) => p.serviceUuid == request.serviceUuid)
        .where((p) => p.characteristicUuid == request.characteristicUuid);

    // Start listening now, before invokeMethod, to ensure we don't miss the response
    Future<BmCharacteristicData> futureResponse = responseStream.first;

    // invoke
    await FlutterBluePlus._invokeMethod('writeCharacteristic', request.toMap());

    // wait for response so that we can:
    //  1. check for success (writeWithResponse)
    //  2. wait until the packet has been sent, to prevent iOS & Android dropping packets (writeWithoutResponse)
    BmCharacteristicData response = await futureResponse
        .fbpEnsureAdapterIsOn("writeCharacteristic")
        .fbpEnsureDeviceIsConnected(device, "writeCharacteristic")
        .fbpTimeout(timeout, "writeCharacteristic");

    // failed?
    if (!response.success) {
      throw FlutterBluePlusException(_nativeError, "writeCharacteristic", response.errorCode, response.errorString);
    }

    return Future.value();
  } finally {
    mtx.give();
  }
}