This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Read BLE characteristic with nRF52840-DK and pc-ble-driver

For my project in development I need to read characteristics from BLE devices using pc-ble-driver library.

I am using a C program, not python bindings.

The method I am using is sd_ble_gattc_read passing the characteristic's handle_value got from sd_ble_gattc_characteristics_discover .

The problem is that I obtain in p_ble_gattc_evt->params.read_rsp.data always different data from a read to another one.

Obviously no write or other changes on the device is done. reading same characteristic on the same device with other tool works fine.

Someone can help me giving me advice on here I am wrong reading characteristic value?

Parents
  • Hi Cheip, 

    Please check and verify that the handle_value (location of the attribute in the attribute table) you got from service discovery is correct. You can verify that using nRF Connect tool on PC. 

    If it's the correct handle value (it's the handle of the value of the characteristic), you may want to capture a sniffer trace to check if the read request has the correct value or not as well as checking the read response if the correct value is responded. 

  • Thank you for your helpful reply.

    I checked the handle_value and the characteristic value with nRF Connect tool and the handle_value corresponds to the one i discover with my software, and the characteristic value correspond to the value read with my "benchmark" software. So I am pretty sure my program is wrong in some point.

    unfortunately I can not try with the sniffer because I have only one board at the moment.

    I paste here the relevant portions of code if you want to take a look and say to me if you notice any trivial mistake I am doing.

    Start read:

    uint32_t read_start(uint16_t connection_handle, uint16_t value_handle)
    {
        printf("VALUE HANDLE: 0x%04X\n", value_handle); // this value corresponds
        fflush(stdout);
        
        auto error_code = sd_ble_gattc_read(adapter, connection_handle, value_handle, 0);
        if (error_code != NRF_SUCCESS)
        {
            printf("ERROR");
            fflush(stdout);
        }
        
        return error_code;
    }
    Read value event handling:
    static int offset = 0;
    static void on_read_response(ble_gattc_evt_t *const p_ble_gattc_evt)
    {
        if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
        {
            printf("ERROR");
            fflush(stdout);
            return;
        }
        
        auto result = p_ble_gattc_evt->params.read_rsp;
        
        for (size_t i = 0; i < result.len; i++)
        {
            printf("0x%02X ", result.data[i]); // this values are always different from one read to another
            fflush(stdout);
        }
        printf("\n");
        fflush(stdout);
        
        if (result.len > 0)
        {
            offset += result.len;
        
            auto error_code = sd_ble_gattc_read(adapter, p_ble_gattc_evt->conn_handle, result.handle, offset);
            if (error_code != NRF_SUCCESS) {
                printf("ERROR");
                fflush(stdout);
            }
        }
    }
Reply
  • Thank you for your helpful reply.

    I checked the handle_value and the characteristic value with nRF Connect tool and the handle_value corresponds to the one i discover with my software, and the characteristic value correspond to the value read with my "benchmark" software. So I am pretty sure my program is wrong in some point.

    unfortunately I can not try with the sniffer because I have only one board at the moment.

    I paste here the relevant portions of code if you want to take a look and say to me if you notice any trivial mistake I am doing.

    Start read:

    uint32_t read_start(uint16_t connection_handle, uint16_t value_handle)
    {
        printf("VALUE HANDLE: 0x%04X\n", value_handle); // this value corresponds
        fflush(stdout);
        
        auto error_code = sd_ble_gattc_read(adapter, connection_handle, value_handle, 0);
        if (error_code != NRF_SUCCESS)
        {
            printf("ERROR");
            fflush(stdout);
        }
        
        return error_code;
    }
    Read value event handling:
    static int offset = 0;
    static void on_read_response(ble_gattc_evt_t *const p_ble_gattc_evt)
    {
        if (p_ble_gattc_evt->gatt_status != NRF_SUCCESS)
        {
            printf("ERROR");
            fflush(stdout);
            return;
        }
        
        auto result = p_ble_gattc_evt->params.read_rsp;
        
        for (size_t i = 0; i < result.len; i++)
        {
            printf("0x%02X ", result.data[i]); // this values are always different from one read to another
            fflush(stdout);
        }
        printf("\n");
        fflush(stdout);
        
        if (result.len > 0)
        {
            offset += result.len;
        
            auto error_code = sd_ble_gattc_read(adapter, p_ble_gattc_evt->conn_handle, result.handle, offset);
            if (error_code != NRF_SUCCESS) {
                printf("ERROR");
                fflush(stdout);
            }
        }
    }
Children
  • I don't see anything suspicious here. 
    But could you describe the corrupted data you receive  ? Does it have the correct length ? 

    If you don't do any offset reading but simply read with 0 offset do you see the correct data?
    Would strongly suggest to get an extra DK to work as the sniffer, it would make it much easier to debug. 

  • I read with offset 0 the first time i call sd_ble_gattc_read and no, I do not get the correct data. Continuing the reading process with offsets I can get all 32 bytes for the characteristic value.

    Unfortunately I can not give more details on those data I get because they changes from one read and another, like I am reading "random" data.

    Maybe can I find somewhere a working example like the ones I found in pc-ble-driver repository to study a working code?

  • I'm not aware of an example beside the heart rate collector in the repo.

    I would strongly suggest to use a sniffer to catch what the actual read command is sent over the air. 


    From what you said I understand that if you send 2 sd_ble_gattc_read () with the same offset 0 you actually can get all 32 bytes ? 

    Have you tried to test with smaller characteristic size ? Says 10 bytes  ? This is because by default the ATT_MTU is 23 bytes.

  • I send in total three sd_ble_gattc_read() , first time with offset 0 and i get the first 22 bytes, then I send a second sd_ble_gattc_read() with offset 22 (length of the result I got) and I get the last 10 bytes. Then I send a thid sd_ble_gattc_read() with offset 32, I get a result with length 0, so I stop the process.

  • Hi, 

    What you described about your process to read blob is correct. But please clarify when do you receive corrupted data ? 
    If the ATT_MTU is 23 bytes it's about right that the first packet you can only receive 22 bytes. 
    If you want to read with longer data in one read request,  you need to request longer ATT_MTU. We support up to 247. 

Related