Search code examples
androidionic-frameworkbluetooth-lowenergycapacitor

How to get a response from the async write function in capacitor-community / bluetooth-le


I'm working with an ESP32 chip and am trying to create an Android app (using Ionic) which allows user to send wifi credentials to the ESP32 chip via BLE. I'd like to be able to update the status of the wifi sending process for the user in the UI (which I'm developing using Angular and then converting it to an Android webapp using Ionic). To do this, I'm also using the capacitor-community/bluetooth-le library.

Can anyone explain to me what this.queue does in the async write function (code shown below) does? I thought this function returns a response from a remote BLE device after writing to a GATT characteristic, but I get absolutely nothing at all for a response.

async write(deviceId: string, service: string, characteristic: string, value: DataView): Promise<void> {
    service = validateUUID(service);
    characteristic = validateUUID(characteristic);
    return this.queue(async () => {
      if (!value?.buffer) {
        throw new Error('Invalid data.');
      }
      let writeValue: DataView | string = value;
      if (Capacitor.getPlatform() !== 'web') {
        // on native we can only write strings
        writeValue = dataViewToHexString(value);
      }
      await BluetoothLe.write({
        deviceId,
        service,
        characteristic,
        value: writeValue,
      });
    });
  }

Here's how I'm using the write function shown above:

this.bleConnectService.getBLE().then(resp => {
  this.deviceID = resp});
}

BleClient.write(this.deviceID, '021a9004-0382-4aea-bff4-6b3f1c5adfb4', '021aff54-0382-4aea-bff4-6b3f1c5adfb4', bytesOfStuff).then(resp => {
      const result2 = resp;
}

I know for a fact that the write function works because my chip is getting the data I'm sending in the right format. I'm just not getting a response back on the client side from the write function. Also, I can confirm the chip is sending a response each time it does something with the data I send to it.


Solution

  • Here's how I'm using BleClient.write to transmit information to a BLE device (recipient):

    BleClient.write(this.connectedDevice.deviceId, this.baseUUID, this.characteristicUUID, data)
    .then(console.log('BleWrite was successful.  Now let/'s do something else')
    .catch(error => console.log('BleWrite fail error: ', error))
    

    BleClient.write returns undefined (promise) when resolved. So when it resolves (ie, BleClient.write is successful), it doesn't fetch and return any confirming data from the recipient device it writes to. You could say the absence of an error implies BleClient.write was successful. If BleClient.write rejects, it will return an error.

    But just because BleClient.write resolves doesn't mean that the recipient device received and recorded the information at its end. If there's a connection breakdown between the initiating and recipient devices, BleClient.write may very well have completed its share of the transmission and resolved, but the recipient device may still not have received the data. To make sure your recipient device gets the data as intended, there has to be some logic at the recipient device's end to process the incoming data and write something to its own GATT characteristic indicating successful receipt of data from the initiating device. The initiating device can then read this information from the recipient device's GATT characteristic using BleClient.read() to get confirmation that the recipient device did in fact get the data.