Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BleClient.write: Writing characteristic failed on WebView #366

Closed
yucehasan opened this issue Jul 18, 2022 · 11 comments
Closed

BleClient.write: Writing characteristic failed on WebView #366

yucehasan opened this issue Jul 18, 2022 · 11 comments
Labels
bug Something isn't working cannot reproduce

Comments

@yucehasan
Copy link

yucehasan commented Jul 18, 2022

Describe the bug
I use a library which requires some functionality from navigator.bluetooth. My solution is creating a similar object with only the required functionalities implemented and assigning it to navigator.bluetooth. Other functions worked fine, like requestDevice, connect, getPrimaryServices etc. But the problem is with write. I cannot find additional info on why it failed.

To Reproduce

export const injectBluetooth = async (): Promise<void> => {
  await BluetoothLe.initialize({ androidNeverForLocation: true });

  const requestDevice = async (options?: RequestDeviceOptions): Promise<BluetoothDevice> => {
    const model = getDeviceModel();
    const requestOptions: RequestBleDeviceOptions = {
      services: model.bluetoothSpec ? [model.bluetoothSpec[0].serviceUuid] : [],
      optionalServices:
        options?.optionalServices?.map(service => {
          if (typeof service === 'string') {
            return service;
          }
          return numberToUUID(service);
        }) ?? [],
    };
    const bleDevice = await BleClient.requestDevice(requestOptions);
    await BluetoothLe.connect({ deviceId: bleDevice.deviceId });
    const device = bleDeviceToBluetoothDevice(bleDevice);
    (device.gatt as Partial<BluetoothRemoteGATTServer>) = {
      device,
      connected: true,
      connect: async () => {
        await BluetoothLe.connect({ deviceId: bleDevice.deviceId });
        await BluetoothLe.createBond({ deviceId: bleDevice.deviceId });
        if (!device?.gatt) {
          throw new Error('Gatt not found');
        }
        return device.gatt;
      },
      disconnect: async () => {
        await BluetoothLe.disconnect({ deviceId: bleDevice.deviceId });
      },
      getPrimaryServices: async (_service?: BluetoothServiceUUID | undefined) => {
        const bleServices = await BluetoothLe.getServices({ deviceId: bleDevice.deviceId });
        console.log('bleServices', bleServices);
        return bleServices.services
          .filter(bleService => !bleService.uuid.startsWith('0000'))
          .map(bleService => {
            return {
              device,
              uuid: bleService.uuid,
              isPrimary: true,
              getCharacteristic: async (characteristic: BluetoothCharacteristicUUID) => {
                const characteristicFound = bleService.characteristics.find(ch => {
                  if (typeof characteristic === 'string') {
                    return ch.uuid === characteristic;
                  } else {
                    return ch.uuid === webUUIDToString(characteristic);
                  }
                });
                if (!characteristicFound) {
                  throw new Error('characteristic not found');
                }
                return {
                  service: bleService,
                  uuid: characteristicFound.uuid,
                  startNotifications: async () => {
                    await BluetoothLe.startNotifications({
                      deviceId: device.id,
                      characteristic: characteristicFound?.uuid ?? '',
                      service: bleService.uuid,
                    });
                  },

                  // PROBLEM HERE!!!!
                  writeValue: async (buf: Buffer) => {
                    await BleClient.write(
                      device.id,
                      bleService.uuid,
                      characteristicFound.uuid,
                      numbersToDataView([...buf])
                    );
                  },


                } as unknown as BluetoothRemoteGATTCharacteristic;
              },
            } as BluetoothRemoteGATTService;
          });
      },
    };
    return device;
  };

  const bluetooth: Bluetooth = {
    // some other functions here
    requestDevice,
};

  // eslint-disable-next-line compat/compat
  navigator.bluetooth = bluetooth;
};

Expected behavior
Working code or better explaining error message.

Screenshots

2022-07-18 19:01:07.590 27349-27888/**** V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 108826025, pluginId: BluetoothLe, methodName: write
2022-07-18 19:01:07.591 27349-27888/**** V/Capacitor: callback: 108826025, pluginId: BluetoothLe, methodName: write, methodData: {"deviceId":"DE:F1:CB:C4:FF:2A","service":"13d63400-2c97-0004-0000-4c6564676572","characteristic":"13d63400-2c97-0004-0002-4c6564676572","value":"08 00 00 00 00"}
2022-07-18 19:01:07.591 2239-4992/? I/ContainerConfigurationPolicy: Bluetooth And NFC caller permission check
2022-07-18 19:01:07.591 2239-4992/? D/ContainerConfigurationPolicy: current version : KNOX_ENTERPRISE_SDK_VERSION_3_8, Required version : KNOX_ENTERPRISE_SDK_VERSION_2_4
2022-07-18 19:01:07.592 2239-4992/? D/BluetoothUtils: Utils::isKnoxBluetoothEnabled = true
2022-07-18 19:01:07.593 1495-1999/? D/PersonaServiceHelper: isUsbHostModeEnabledForContainer: userId-150
2022-07-18 19:01:07.595 1495-1999/? I/ContainerConfigurationPolicy: Usb Host Mode permission check
2022-07-18 19:01:07.595 1495-1999/? D/ContainerConfigurationPolicy: current version : KNOX_ENTERPRISE_SDK_VERSION_3_8, Required version : KNOX_ENTERPRISE_SDK_VERSION_2_5
2022-07-18 19:01:07.595 27349-27446/**** D/Device: reject: write|13d63400-2c97-0004-0000-4c6564676572|13d63400-2c97-0004-0002-4c6564676572 Writing characteristic failed.
2022-07-18 19:01:07.596 27349-27446/**** D/Capacitor: Sending plugin error: {"save":false,"callbackId":"108826025","pluginId":"BluetoothLe","methodName":"write","success":false,"error":{"message":"Writing characteristic failed."}}
2022-07-18 19:01:07.596 1495-1999/? D/PersonaServiceHelper: isUsbHostModeEnabledForContainer: Usb Host Mode sdcard is disabled for User-150. Ignoring USB device access request...
2022-07-18 19:01:07.598 625-625/? D/io_stats: !@   8,0 r 3351128 71898068 w 3198664 109468756 d 0 0 f 0 0 iot 1820476 0 th 0 0 0 pt 0 inp 0 277 70779.265
2022-07-18 19:01:07.599 2239-4992/? I/ContainerConfigurationPolicy: Bluetooth And NFC caller permission check
2022-07-18 19:01:07.599 2239-4992/? D/ContainerConfigurationPolicy: current version : KNOX_ENTERPRISE_SDK_VERSION_3_8, Required version : KNOX_ENTERPRISE_SDK_VERSION_2_4
2022-07-18 19:01:07.600 2239-4992/? D/BluetoothUtils: Utils::isKnoxBluetoothEnabled = true
2022-07-18 19:01:07.618 27349-27888/**** V/Capacitor/Plugin: To native (Capacitor plugin): callbackId: 108826026, pluginId: BluetoothLe, methodName: disconnect
2022-07-18 19:01:07.620 27349-27888/**** V/Capacitor: callback: 108826026, pluginId: BluetoothLe, methodName: disconnect, methodData: {"deviceId":"DE:F1:CB:C4:FF:2A"}
2022-07-18 19:01:07.621 27349-27446/**** D/BluetoothGatt: cancelOpen() - device: DE:F1:CB:C4:FF:2A
2022-07-18 19:01:07.625 926-3174/? I/[email protected]_handler: ProcessIbsCmd: Received IBS_SLEEP_IND: 0xFE
2022-07-18 19:01:07.627 2239-4992/? D/BtGatt.GattService: clientDisconnect(****) - address=DEF1CB_A, connId=20, clientIf: 20
2022-07-18 19:01:07.627 926-3174/? I/[email protected]_handler: ProcessIbsCmd: Received IBS_WAKE_IND: 0xFD
2022-07-18 19:01:07.627 926-3174/? I/[email protected]_handler: ProcessIbsCmd: Writing IBS_WAKE_ACK
2022-07-18 19:01:07.629 2239-3178/? I/bt_stack: [INFO:gatt_api.cc(1367)] GATT_Disconnect conn_id=0x0014
2022-07-18 19:01:07.629 2239-3178/? I/bt_stack: [INFO:eatt_impl.h(602)] disconnect de:f1:cb:c4:ff:2a
2022-07-18 19:01:07.629 2239-3178/? W/bt_stack: [WARNING:eatt_impl.h(606)] disconnect no eatt device found
2022-07-18 19:01:07.629 2239-3178/? W/bt_l2cap: l2cu_no_dynamic_ccbs starting IDLE timeout: 4000 ms
2022-07-18 19:01:07.629 2239-3178/? W/bt_l2cap: l2cu_no_dynamic_ccbs starting IDLE timeout: 1000 ms
2022-07-18 19:01:07.630 2239-3178/? E/bt_stack: [ERROR:bta_gattc_utils.cc(444)] bta_gattc_mark_bg_conn unable to find the bg connection mask for bd_addr=de:f1:cb:c4:ff:2a
2022-07-18 19:01:07.631 2239-2417/? D/BtGatt.GattService: onDisconnected() - clientIf=20, connId=20, status=0, address=DEF1CB_A
2022-07-18 19:01:07.632 27349-27349/**** E/Capacitor/Console: File: webpack-internal:///../****-common/src/logging/****Logger.ts - Line 20 - Msg: LedgerLocalizedError::convertToLocalizableError::error: {
      "stack": "Error: Writing characteristic failed.\n    at cap.fromNative (http://localhost/main_window.html?popup=true:413:32)\n    at <anonymous>:1:18",
      "message": "Writing characteristic failed."
    }
2022-07-18 19:01:07.634 27349-27363/**** D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=20 device=DE:F1:CB:C4:FF:2A
2022-07-18 19:01:07.648 27349-27363/**** V/Capacitor/BluetoothLe: Notifying listeners for event disconnected|DE:F1:CB:C4:FF:2A
2022-07-18 19:01:07.649 27349-27363/**** D/Capacitor/BluetoothLe: No listeners found for event disconnected|DE:F1:CB:C4:FF:2A
2022-07-18 19:01:07.649 27349-27363/**** D/BluetoothGatt: close()
`````

Plugin version:

  • @capacitor-community/bluetooth-le: 1.8.3

Smartphone (please complete the following information):

  • Device: Samsung Galaxy A52
  • OS: Android 12
  • Browser: WebView

Additional Context
Trying to connect a Ledger Nano X device

@yucehasan yucehasan added the bug Something isn't working label Jul 18, 2022
@yucehasan
Copy link
Author

@pwespi Any ideas, comments? Do I need to add more info about the problem?

@pwespi
Copy link
Member

pwespi commented Jul 25, 2022

I'm not sure what's going on. Some questions:

  • Do all writes fail or just a specific characteristic?
  • Can you write to the device in a very simple reproduction without doing all the navigator stuff?
  • In the logs, there seems to be a disconnect shortly after the write. Is this done by your app code?

@yucehasan
Copy link
Author

There is only one write characteristic to the device I am connecting. I was able to write to the device directly using this plugin, although I did not receive any feedback on this: It was just completed without errors. Disconnect happens because of the error. No disconnection on successful write. My question is, why can write be failing when passed to another library? It is successful when called manually with the same parameters.

@yucehasan
Copy link
Author

Code fails exactly here. Do you have any suggestions to debug?

@pwespi
Copy link
Member

pwespi commented Aug 9, 2022

This is the Android documentation about the write call:

About the return value it says only true, if the write operation was initiated successfully, so not much to go on. If the return value is false, maybe

  • the device is not connected anymore
  • you don't have write permission on that characteristic
  • there is an unknown error in the Android Bluetooth stack
  • there is an error in the peripheral

These are the options I can think of.

Also if bluetoothGatt is null at that point, you would also get an error. But this would mean that the device disconnected just at the time when you're making the write call, and you should see this in the logs.

Does already the first write fail or do some writes work and it fails after some time? Have you tried different Android devices?

@github-actions
Copy link

github-actions bot commented Sep 9, 2022

It looks like this issue didn't get the information it needed, so I'll close it for now. If I made a mistake, sorry! I am just a bot.

Have a great day!
Capacitor Community Bot 💙

@schnouz
Copy link

schnouz commented Sep 25, 2022

@yucehasan Hi there :) Have you finally manage to make it works ?

@yucehasan
Copy link
Author

@schnouz Hi :) Yes, we did. We tried a different strategy. Instead of injecting bluetooth to the app (navigator) we forked and replaced it in the 3rd party library that was trying to use WebBluetooth. It worked.

@AyoubKessemtini
Copy link

I have the same error,
any solution ?
thanks,

@AyoubKessemtini
Copy link

@yucehasan

@jolugama
Copy link

jolugama commented Sep 17, 2023

SOLUTION : I have 2 test phones. 1 xiaomi mi5 with android8 and neither notification nor write works to send data, and with android10 with mi9 it works perfectly. I have tried giving bluetooth permissions as the library says, but nothing. Try more current mobiles with a more modern Android version. @yucehasan

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working cannot reproduce
Projects
None yet
Development

No branches or pull requests

5 participants