setNotifyValue method

Future<bool> setNotifyValue(
  1. bool notify, {
  2. int timeout = 15,
  3. bool forceIndications = false,
})

Sets notifications or indications for the characteristic.

  • If a characteristic supports both notifications and indications, we use notifications. This is a limitation of CoreBluetooth on iOS.
  • forceIndications Android Only. force indications to be used instead of notifications.

Implementation

Future<bool> setNotifyValue(bool notify, {int timeout = 15, bool forceIndications = false}) async {
  // check connected
  if (device.isDisconnected) {
    throw FlutterBluePlusException(
        ErrorPlatform.fbp, "setNotifyValue", FbpErrorCode.deviceIsDisconnected.index, "device is not connected");
  }

  // check
  if (Platform.isMacOS || Platform.isIOS) {
    assert(forceIndications == false, "iOS & macOS do not support forcing indications");
  }

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

  try {
    var request = BmSetNotifyValueRequest(
      remoteId: remoteId,
      serviceUuid: serviceUuid,
      secondaryServiceUuid: null,
      characteristicUuid: characteristicUuid,
      forceIndications: forceIndications,
      enable: notify,
    );

    // Notifications & Indications are configured by writing to the
    // Client Characteristic Configuration Descriptor (CCCD)
    Stream<BmDescriptorData> responseStream = FlutterBluePlus._methodStream.stream
        .where((m) => m.method == "OnDescriptorWritten")
        .map((m) => m.arguments)
        .map((args) => BmDescriptorData.fromMap(args))
        .where((p) => p.remoteId == request.remoteId)
        .where((p) => p.serviceUuid == request.serviceUuid)
        .where((p) => p.characteristicUuid == request.characteristicUuid)
        .where((p) => p.descriptorUuid == cccdUuid);

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

    // invoke
    bool hasCCCD = await FlutterBluePlus._invokeMethod('setNotifyValue', request.toMap());

    // wait for CCCD descriptor to be written?
    if (hasCCCD) {
      BmDescriptorData response = await futureResponse
          .fbpEnsureAdapterIsOn("setNotifyValue")
          .fbpEnsureDeviceIsConnected(device, "setNotifyValue")
          .fbpTimeout(timeout, "setNotifyValue");

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

  return true;
}