This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

BLE Central bt_gatt_read_func_t fails with Read ERROR: 1 - Not sure how to debug further

To give some context to the problem I am using the nRF52833 DK as a BLE Central and a nRF52840 as a BLE peripheral in a simple use case to simply read the state of button1 on the peripheral by pressing button1 on the central using nrf Connect 1.6.1.

I based the peripheral code off the peripheral_lbs example (just renamed a bunch of functions) and confirmed it was working as expected using nRF Connect on my smartphone. Next, I based the central code off the central_bas example and kept the same structure while modifying the read functionality slightly. 

Discovery of the service and characteristics and assigning handles is successful based on log output, but upon attempting to read the button value there is always a read error that occurs somewhere internally within the gatt module.

I will add the relevant code below:

In main.c:

static void button_readval(void)
{
    int err;
    
    printk("Reading Peripheral Button 1 Value:\n");
    err = bt_service_read_peripheral_button1(&sc, read_peripheral_button_cb);
    if (err) {
            printk("Service read call error: %d\n", err);
    }
}

In service_client.c:

int bt_service_read_peripheral_button1(struct bt_service_client *sc, bt_service_read_cb func)
{
    int err;

    if (!sc || !func) {
            return -EINVAL;
    }
    if (!sc->conn) {
            return -EINVAL;
    }
    if (sc->read_cb) {
            return -EBUSY;
    }
    sc->read_cb = func;
    sc->read_params.func = read_process;
    sc->read_params.handle_count  = 1;
    sc->read_params.single.handle = sc->RX_handle;
    sc->read_params.single.offset = 0;

    err = bt_gatt_read(sc->conn, &sc->read_params);
    if (err) {
            sc->read_cb = NULL;
            printk("gatt_read ERROR: %d\n", err);
            return err;
    }
    printk("Returning successfully from bt_service_read_peripheral_button1\n");
    return 0;
}

static uint8_t read_process(struct bt_conn *conn, uint8_t err,
			     struct bt_gatt_read_params *params,
			     const void *data, uint16_t length)
{
    struct bt_service_client *sc;
    uint8_t button_val = 255;
    const uint8_t *bdata = data;

    sc = CONTAINER_OF(params, struct bt_service_client, read_params);

    if (!sc->read_cb) {
        LOG_ERR("No read callback present");
    } else  if (err) {
        LOG_ERR("Read value error: %d", err);
        sc->read_cb(sc, button_val, err);
    } else if (!data || length != 1) {
        sc->read_cb(sc,  button_val, -EMSGSIZE);
    } else {
        button_val = bdata[0];
        sc->button_val = button_val;
        sc->read_cb(sc, button_val, err);
    }

    sc->read_cb = NULL;
    return BT_GATT_ITER_STOP;
}

Log output: 

Reading Peripheral Button 1 Value:
Returning successfully from bt_service_read_peripheral_button1
E: Read value error: 1

The read_process function is passed an err variable from the gatt module so it is very difficult to see where it is originating from. The log output shows that the error occurs at some point in the read_process function, which is specifically labelled as an "Internal function to process report read and pass it further". Using the debugger, it also appears that the buffer of data is just empty from the peripheral. I am somewhat stuck as to how to fix this, aside from diving into the gatt module code itself which does not seem feasible. Appreciate any input, thanks.

Parents
  • The issue ended up being with the handles, thank you for the hint
    If anyone else runs into this issue, double check this area of the code (taken from the BAS Central example):

    gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc,
                            BT_UUID_BAS_BATTERY_LEVEL);
        if (!gatt_desc) {
            LOG_ERR("No battery level characteristic value found.");
            return -EINVAL;
    }
    I don't think this error check was working correctly in my case as it did not throw this error but the handle was not setup properly for my characteristic. 
Reply
  • The issue ended up being with the handles, thank you for the hint
    If anyone else runs into this issue, double check this area of the code (taken from the BAS Central example):

    gatt_desc = bt_gatt_dm_desc_by_uuid(dm, gatt_chrc,
                            BT_UUID_BAS_BATTERY_LEVEL);
        if (!gatt_desc) {
            LOG_ERR("No battery level characteristic value found.");
            return -EINVAL;
    }
    I don't think this error check was working correctly in my case as it did not throw this error but the handle was not setup properly for my characteristic. 
Children
No Data
Related