BLE Fragmentation data loss

I am using an nRF52840 processor within a Particle Argon IoT module. I am polling a third party BLE peripheral (Shelly relay) for status data once a minute. The data packet that device responds with is 779 bytes long. I am consistently losing 3 bytes of that data.

Using a PC and its BLE, I poll for the exact same data from the peripheral BLE device. I have confirmed that the 3 bytes lost by the Argon device are the 245th, 490th, and 735th bytes. In other words, after the first sent packet, the first byte between each fragment is being lost.

I've reported this to Particle, and they pointed out that the fragmentation is dealt within the Nordic SoftDevice software.

Is this a known Nordic problem? 

The Particle OS does have a BLE software component to it which I believe could potentially be the source to this problem. 

Any insight would be appreciated.

Parents
  • Hello,

    The easiest way to troubleshoot this would likely be by capturing a bluetooth sniffer trace and compare the packet exchange when it works and when it doesn't. Our nRF Sniffer for Bluetooth LE is a low cost option, but it requires that you have a nRF52840 Dongle or one of the other supported boards laying around. Is the code to poll the sensor provided by Particle or is it something you have written. Either way, it would be nice to see the code showing how it is implemented if possible. I'm not aware of any known bugs in the stack that could explain the data loss.

    Best regards,

    Vidar

  • Here's their code (Particle). I call this member function getValue() four times in rapid succession asking for 244 bytes of data. I get 3 full packets of 244 bytes, and one final packet of 44 bytes for a total of 776 bytes. The message is supposed to be 779 bytes long. When I examine that data I see that the 245th, 490th, and 735th bytes are missing. (BLE_MAX_ATTR_PACKET_SIZE is 244).

    ssize_t BleCharacteristic::getValue(uint8_t* buf, size_t len) const {
        if (buf == nullptr || len == 0) {
            return SYSTEM_ERROR_INVALID_ARGUMENT;
        }
        len = std::min(len, (size_t)BLE_MAX_ATTR_VALUE_PACKET_SIZE);
        if (impl()->connHandle() != BLE_INVALID_CONN_HANDLE){
            return hal_ble_gatt_client_read(impl()->connHandle(), impl()->attrHandles().value_handle, buf, len, nullptr);
        }
        else if (impl()->isLocal()) {
            return hal_ble_gatt_server_get_characteristic_value(impl()->attrHandles().value_handle, buf, len, nullptr);
        }
        return SYSTEM_ERROR_INVALID_STATE;
    }
     
    I don't know if hal_ble_gatt_client_read is your SoftDevice layer being called, but I think so. Is there something special that needs to happen for fragmented packages?
  • Sorry, looks like there’s another layer in the Particle OS before SoftDevice. I’ll be looking into that further. 

    That said, I’d really like to get some insight into how a layer such as Particle’s OS should conduct itself when dealing with a fragmented packet being received from a peripheral device. 

Reply Children
No Data
Related