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

I want to solve the problem that the characteristic value is not the set value.

Hello.


It is being developed using nrf52832 (S132 v7.0.1, SDK v17.0.0) as a peripheral device.

Previously, I inquired about how to add a value to the characteristic with this ticket, the error no longer occurs, I can connect, I can confirm that the value of the characteristic is set, and it is solved safely I was able to do it.

However, although no error now occurs, the characteristic value is no longer the set value.

I don't know why this is happening. Do you have any advice?

Also, I am currently inquiring with this ticket, but I am creating a process to switch the advertised UUID. Isn't this advertisement UUID and service UUID need to be linked? I searched for such a process, but couldn't find it.

Best regards.

Parents
  • Hi,

    However, although no error now occurs, the characteristic value is no longer the set value.

    I don't know why this is happening. Do you have any advice?

    What have you changed since it did work? What value do you write and what do you see? Could it be that other parts of your code sets another value, or that you do not set it at all? If you explain and show your code I can take a look and see if I spot any issues.

    Also, I am currently inquiring with this ticket, but I am creating a process to switch the advertised UUID. Isn't this advertisement UUID and service UUID need to be linked? I searched for such a process, but couldn't find it.

    If you advertise a service UUID, then that indicates that your device supports that service. There is however no direct link, so you can technically advertise any UUID(s) regardless of what services the peripheral actually implements. For instance if you take a look at examples\ble_peripheral\ble_app_hrs\main.c you can see some UUIDs that are part of the advertisement packet by looking at how m_adv_uuids is declared. Implementation-vise this is completely independent of adding the services themselves. 

  • Hello.

    Since the actual code cannot be published, some contents are different, but we are considering such code.

    // UUID Setting
    #define ADV_UUID_BASE     {0x77, 0x77, 0x66, 0x66, 0x55, 0x55, 0x44, 0x44, 0x33, 0x33, 0x22, 0x22, 0x11, 0x11, 0x00, 0x00}
    #define SERVICE_UUID_BASE {0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00}
    #define CHAR_UUID_BASE    {0xF0, 0xE0, 0xD0, 0xC0, 0xB0, 0xA0, 0x90, 0x80, 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00}
    #define BLE_UUID_CHAR     {0x1234}
    
    #define BLE_UUID_CHAR_MAX {1}
    
    // Connection Handle
    static uint16_t                 m_service_handle;   /**< Handle of local service (as provided by the BLE stack).*/
    static ble_gatts_char_handles_t m_char_handles;     /**< Handles of local characteristic (as provided by the BLE stack).*/
    static uint16_t                 conn_handle;
    
    // Characteristic
    static ble_add_char_params_t char_test_data = 
    {
        .uuid                = BLE_UUID_CHAR,
        .uuid_type           = NULL,
        .max_len             = 1,
        .init_len            = 1,
        .is_var_len          = false,
        .char_props.read     = 1,
        .read_access         = SEC_MITM,
        .is_value_user       = BLE_GATTS_VLOC_STACK,
    };
    
    // UUID Base
    static ble_uuid128_t ble_char_uuid_base[BLE_UUID_CHAR_MAX] = 
    {
        CHAR1_UUID_BASE,
    };
    
    // set the UUID here.
    static void uuid_init(void)
    {
        ret_code_t    err_code;
        ble_uuid_t    adv_uuid;
        ble_uuid_t    service_uuid;
        ble_uuid_t    char_uuid;
        ble_uuid128_t adv_uuid_base = {ADV_UUID_BASE};
        ble_uuid128_t service_uuid_base = {SERVICE_UUID_BASE};
    
        uint8_t       test_data = 0x01;
    
        // advertise setting
        err_code = sd_ble_uuid_vs_add(&adv_uuid_base, &adv_uuid.type);
        APP_ERROR_CHECK(err_code);
    
        // service setting
        err_code = sd_ble_uuid_vs_add(&service_uuid_base, &service_uuid.type);
        APP_ERROR_CHECK(err_code);
    
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &service_uuid, &m_service_handle);
        APP_ERROR_CHECK(err_code);
    
        // characteristic setting
        err_code = sd_ble_uuid_vs_add(&ble_char_uuid_base[0], &char_uuid.type);
        APP_ERROR_CHECK(err_code);
    
        add_char_params.uuid_type = char_uuid.type;
        err_code = characteristic_add(m_service_handle, &add_char_params, &m_char_handles);
        APP_ERROR_CHECK(err_code);
    
        char_data_set(m_char_handles, 1, &test_data);
    
        return;
    }
    
    // characteristic data setting.
    static void char_data_set(uint16_t handle, uint8_t len, uint8_t * value)
    {
        ret_code_t        err_code;
        ble_gatts_value_t char_value;
    
        memset(&char_value, 0, sizeof(char_value));
    
        char_value.len     = len;
        char_value.offset  = 0;
        char_value.p_value = value;
    
        err_code = sd_ble_gatts_value_set(BLE_CONN_HANDLE_INVALID, handle, &char_value);
        APP_ERROR_CHECK(err_code);
    
        return;
    }

    Since the characteristic is set to read, it is assumed that a Read Request will be received from the connected BLE device (nRF Connect) and the data will be acquired.

    In this code, it is 1Byte, but when I set the data of about 8Byte and acquired it with a BLE device, it was the same value as the address 0x00000000 in the memory. Why is the data at address 0x00000000 sent?

  • Hi,

    sdi_kei said:
    Since the characteristic is set to read, it is assumed that a Read Request will be received from the connected BLE device (nRF Connect) and the data will be acquired.

    You do not normally get a event on read requests, that is handled by the stack all by itself (you can use authorization if you need to though, see for instance this post).

    sdi_kei said:
    In this code, it is 1Byte, but when I set the data of about 8Byte and acquired it with a BLE device, it was the same value as the address 0x00000000 in the memory. Why is the data at address 0x00000000 sent?

    I am not sure about 8 byte, as the code her clearly only works with 1 byte, and that is also the max length you specified. With this code you should always read 1, as you set the value to one after adding the characteristic. From what I see you should always receive 0x01 with this code. Perhaps there is another issue somewhere else?

    If you cannot share your code, perhaps you can make a minimal failing example with just the relevant parts that I can run on my end.

  • Hello.

    You do not normally get a event on read requests, that is handled by the stack all by itself (you can use authorization if you need to though, see for instance this post).

    I created the process by referring to the link you gave me. However, when I connected and checked with nRF Connect, the data (0x00) at the 0x00000000 address was read as in the current phenomenon.

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
                ble_char_read_evt(p_ble_evt);
                break;
        
        return;     
    }
    
    static void ble_char_read_evt(ble_evt_t const * p_ble_evt)
    {
        ble_gatts_rw_authorize_reply_params_t reply_params;
        ble_gatts_evt_rw_authorize_request_t  const * p_evt_rw_auth = &p_ble_evt->evt.gatts_evt.params.authorize_request;
        ret_code_t err_code;
        uint8_t    reply_data = 0x01;
    
        memset(&reply_params, 0, sizeof(ble_gatts_rw_authorize_reply_params_t));
    
        reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
        reply_params.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
        reply_params.params.read.update = 0x01;
        reply_params.params.read.offset = 0x00;
        reply_params.params.read.len = 0x01;
        reply_params.params.read.p_data = &reply_data;
    
        err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.common_evt.conn_handle, &reply_params);
        APP_ERROR_CHECK(err_code);
    
        return;
    }

    I am not sure about 8 byte, as the code her clearly only works with 1 byte, and that is also the max length you specified.

    The explanation was insufficient. I'm sorry.
    The code described in DevZone says that it works with 1Byte, but I also confirmed the operation with the pattern that changed this to 8Byte. This is because it is not possible to know from which address the data is being referenced with only 1 byte.

    In the code I wrote, I set 0x01 to the characteristic, so I should be able to read 0x01, but in my case, it reads the data (0x00) at the address 0x00000000.

    How can I read the value I set?

    Best regards.

Reply
  • Hello.

    You do not normally get a event on read requests, that is handled by the stack all by itself (you can use authorization if you need to though, see for instance this post).

    I created the process by referring to the link you gave me. However, when I connected and checked with nRF Connect, the data (0x00) at the 0x00000000 address was read as in the current phenomenon.

    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
                ble_char_read_evt(p_ble_evt);
                break;
        
        return;     
    }
    
    static void ble_char_read_evt(ble_evt_t const * p_ble_evt)
    {
        ble_gatts_rw_authorize_reply_params_t reply_params;
        ble_gatts_evt_rw_authorize_request_t  const * p_evt_rw_auth = &p_ble_evt->evt.gatts_evt.params.authorize_request;
        ret_code_t err_code;
        uint8_t    reply_data = 0x01;
    
        memset(&reply_params, 0, sizeof(ble_gatts_rw_authorize_reply_params_t));
    
        reply_params.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
        reply_params.params.read.gatt_status = BLE_GATT_STATUS_SUCCESS;
        reply_params.params.read.update = 0x01;
        reply_params.params.read.offset = 0x00;
        reply_params.params.read.len = 0x01;
        reply_params.params.read.p_data = &reply_data;
    
        err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.common_evt.conn_handle, &reply_params);
        APP_ERROR_CHECK(err_code);
    
        return;
    }

    I am not sure about 8 byte, as the code her clearly only works with 1 byte, and that is also the max length you specified.

    The explanation was insufficient. I'm sorry.
    The code described in DevZone says that it works with 1Byte, but I also confirmed the operation with the pattern that changed this to 8Byte. This is because it is not possible to know from which address the data is being referenced with only 1 byte.

    In the code I wrote, I set 0x01 to the characteristic, so I should be able to read 0x01, but in my case, it reads the data (0x00) at the address 0x00000000.

    How can I read the value I set?

    Best regards.

Children
  • Hi,

    I see you now added code for authorization. Do you need this? (I mentioned it in my previously post as an explanation for why you don't get an event in your case, but not as a suggestion that you should do it).

    sdi_kei said:
    How can I read the value I set?

    If you don't use authorization, the stack will handle everything for you. As long as you update the value with sd_ble_gatts_value_set(), that value will be read when you read it. There is not really much more to say.

    I suggest the following:

    1. First figure out if. you need authorization or not. I have not seen any indication you do. If not, remove it.
    2. Make a example that I can test on my end on a DK and explain how to test it.,
    3. I will test and see if I spot the issue.

    The reason for the above is that as mentioned, this should just work, and I am not able to spot the error. But as I am not seeing everything you do, there might be some issue somewhere else, or I might overlook something. So giving me a minimal failing example that I can run on my end should help to find the issue faster.

  • Hello.

    I thought that by implementing it with reference to the post, the data could be sent correctly, so I added the code.
    However, I don't check the received data, so I'd like to have the stack process it all.

    I'm checking the process again, but I haven't solved the problem yet.

    One question is, in response to a Read Request, a Read Response is returned. Is there a way to confirm that this Read Response has been sent? Will any event occur?

    Best regards.

  • You do not get an even in the nRF indicating that the read response has been sent. But it will be, and if it is not being delivered for some reason, then after several attempted retransmissions, the link will be disconnected with timeout as disconnect reason. As long as this does not happen, the data has been exchanged.

  • Hello.

    I have confirmed that the response is returned when connecting with nRF Connect. However, the values are different.

    I haven't had time to create a minimal example.
    Is there an example in the SDK?

    Best regards.

  • Most of the BLE peripheral examples in the SDK includes a characteristic that is written to that you can read (though most also notify it, so you may want to disable notification if you pick for instance the Heart Rate Application example). 

Related