Skip to content

Writting long byte returns with error on FOTA update #426

@AlejandroHCruz

Description

@AlejandroHCruz

Dear SweetBlue Team,

We've been experimenting with your library, considering the idea of fully migrating our Bluetooth communication to it with a commercial license. So far we've been able to connect our custom hardware peripheral, setup notifications and send/receive writing operations. We're really happy with the results so far on the general usage of your software.

We're now in the final test, which consists in building a successful FOTA (Firmware-Over-The-Air, as you know) update with SweetBlue. I hope you can help us or point us in the right direction, all tips and insights are welcomed!

We're using a PSoC from Cypress, which doesn't make the FOTA particularly simple, this needs to be written with a response:

  1. Enter Bootloader.
  2. Send Data*.
  3. Write Data*.
  4. Confirm Data was written successfully*.
  • = happens multiple times.

Since it's a complex OTA operation and building a custom BleTransaction.Ota has not been successful for performing all of the steps, we've stayed true to the Cypress implementation of request-response, just migrating the write and callback methods to SweetBlue.

Replacing the mBluetoothGatt.writeCharacteristic(characteristic) function and BluetoothGattCallback subclass with deviceToUpgrade.write(characteristic.getService.getUuid(), characteristic.getUuid(), valueByte, readWriteEvent -> { ... }

Specifically, we're having issues on the second step, in which we would send a byte[] array like this one:

01 39 83 00 00 3B 00 00 40 00 20 91 1D 00 00 51 88 00 00 51 88 00 00 10 B5 02 4B 83 F3 08 88 06 F0 7A FD 00 40 00 20 F7 B5 72 B6 00 24 01 22 92 4B 93 4D 21 00 2C 60 1A 70 E0 22 91 48 92 00 0A F0 8E FC 80 22 21 00 D2 00 8F 48 0A F0 88 FC 80 22 8E 49 8E 48 0A F0 7A FC 00 95 21 00 22 00 FF 25 8C 4E 28 36 8B 4B C8 58 53 00 07 00 28 40 12 18 50 00 01 30 01 33 30 18 AF 43 F3 18 01 90 01 98 98 42 07 D0 58 1E 59 D5 17

We write the operation successfully but the PSoC returns the following error, which is defined by Cypress as:

BOOTLOADER_ERR_DATA (0x04) /* The data is not of the proper form */
which probably comes from
#define Bootloader_COMMAND_DATA (0x37u) /* Queue up a block of data for programming */

-> Could it be that we shouldn't be using the write function but rather another one such as performTransaction for each line/byte[] send/write/verify?

-> Our app is paired with the peripheral through the device.bond() method, does that account as the required bonding state?

-> What else could be the issue here? The byte[], characteristic and service are exactly the same on both implementations.


This is the building method for the byte[], it shouldn't be problematic but I place it here as a reference.

`
/**
* OTA Bootloader Program row Command
* */
public void OTAProgramRowCmd(long rowMSB, long rowLSB, int arrayID, byte[] data, String checkSumType) {

    int COMMAND_DATA_SIZE = 3;
    int totalSize = BootLoaderCommands.BASE_CMD_SIZE + COMMAND_DATA_SIZE +
            data.length;
    int checksum;
    int i;
    byte[] commandBytes = new byte[totalSize];
    int startCommand = 0x01;

    commandBytes[BYTE_START_CMD] = (byte) startCommand;
    commandBytes[BYTE_CMD_TYPE] = (byte) BootLoaderCommands.PROGRAM_ROW;
    commandBytes[BYTE_CMD_DATA_SIZE] = (byte) (data.length + COMMAND_DATA_SIZE);
    commandBytes[BYTE_CMD_DATA_SIZE_SHIFT] = (byte) ((int) ((data.length + COMMAND_DATA_SIZE) >> ADDITIVE_OP));
    commandBytes[BYTE_ARRAY_ID] = (byte) arrayID;
    commandBytes[BYTE_ROW] = (byte) rowMSB;
    commandBytes[6] = (byte) rowLSB;
    for (i = 0; i < data.length; i++)
        commandBytes[i + 7] = data[i];
    checksum = BootLoaderUtils.calculateCheckSum2(Integer.parseInt(checkSumType, RADIX),
            data.length + 7, commandBytes);
    commandBytes[totalSize - 3] = (byte) checksum;
    commandBytes[totalSize - 2] = (byte) (checksum >> ADDITIVE_OP);
    commandBytes[totalSize - 1] = (byte) BootLoaderCommands.PACKET_END;

    FOTAManager.writeOTABootLoaderCommand(mOTACharacteristic, commandBytes);

}`

TL;DR:
Is there a length limit or set of best practices for sending long bytes with the multiple methods?
Is SweetBlue breaking down or wrapping up long byte arrays in the write function and we should rather be using performTransaction?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions