This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
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

Getting hex values for entering numeric values

Hi all, I'm working on nrf52832 in segger embedded studio. Using ble scanner app, I'm entering some random values. So when i enter a value, I'm adding them to watch and checking out the value. I entered an integer value of 10, i'm expecting the same value to come in watch, but I'm getting the value as hex. For example if i enter 10, I'm getting it as 0x10.

Parents
  • Hi, 
    I am carrying out the same code and am still facing the issue of junk character while reading the custom characteristics. 
    I am attaching the file ble_cus.c where we are doing the custom characteristics and also the mobile phone screenshot showing the error.

    The custom characteristic creation is being done in line number 83 and the function name is "custom_value_char_add()".

    The below screenshot shows the init_len, offset and maximum length for the custom characteristic which is present in the same file attached, that is, ble_cus.c

    /* This code belongs in ble_cus.c*/
    #include "sdk_common.h"
    #include "ble_srv_common.h"
    #include "ble_cus.h"
    #include <string.h>
    #include "nrf_gpio.h"
    #include "boards.h"
    #include "nrf_log.h"
    
    /**@brief Function for initializing the Custom Service.
     *
     * @param[out]  p_cus       Custom Service structure. This structure will have to be supplied by
     *                          the application. It will be initialized by this function, and will later
     *                          be used to identify this particular service instance.
     * @param[in]   p_cus_init  Information needed to initialize the service.
     *
     * @return      NRF_SUCCESS on successful initialization of service, otherwise an error code.
     */
    uint32_t ble_cus_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init);
    
    uint32_t ble_cus_custom_value_update(ble_cus_t * p_cus, uint8_t custom_value)
    {
        NRF_LOG_INFO("In ble_cus_custom_value_update. \r\n"); 
        if (p_cus == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        uint32_t err_code = NRF_SUCCESS;
        ble_gatts_value_t gatts_value;
    
        // Initialize value struct.
        memset(&gatts_value, 0, sizeof(gatts_value));
    
        gatts_value.len     = sizeof(uint8_t);
        gatts_value.offset  = 0;
        gatts_value.p_value = &custom_value;
    
    
    #if 1
        // Update database.
        err_code = sd_ble_gatts_value_set(p_cus->conn_handle,
                                          p_cus->custom_value_handles.value_handle,
                                          &gatts_value);
    
    #else
        err_code = sd_ble_gatts_value_get(p_cus->conn_handle,
                                          p_cus->custom_value_handles.value_handle,
                                          &gatts_value);
    
    #endif
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
    #if 1
    
        // Send value if connected and notifying.
        if ((p_cus->conn_handle != BLE_CONN_HANDLE_INVALID)) 
        {
            ble_gatts_hvx_params_t hvx_params;
    
            memset(&hvx_params, 0, sizeof(hvx_params));
    
            hvx_params.handle = p_cus->custom_value_handles.value_handle;
            hvx_params.type   = BLE_GATT_HVX_NOTIFICATION;
            hvx_params.offset = gatts_value.offset;
            hvx_params.p_len  = &gatts_value.len;
            hvx_params.p_data = gatts_value.p_value;
    
            err_code = sd_ble_gatts_hvx(p_cus->conn_handle, &hvx_params);
        }
        else
        {
            err_code = NRF_ERROR_INVALID_STATE;
        }
    #endif
    
    
        return err_code;
    }
    
    static uint32_t custom_value_char_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init, uint16_t uuid)
    {
        uint32_t            err_code;
        ble_gatts_char_md_t char_md;
        ble_gatts_attr_md_t cccd_md;
        ble_gatts_attr_t    attr_char_value;
        ble_uuid_t          ble_uuid;
        ble_gatts_attr_md_t attr_md;
        ble_gatts_char_pf_t char_pf;
    
        memset(&char_md, 0, sizeof(char_md));
    
        char_md.char_props.read   = 1;
        char_md.char_props.write  = 1;
        char_md.char_props.notify = 0; 
        char_md.p_char_user_desc  = NULL;
        char_md.p_char_pf         = NULL;
        char_md.p_user_desc_md    = NULL;
        char_md.p_cccd_md         = NULL; 
        char_md.p_sccd_md         = NULL;
    		
        memset(&attr_md, 0, sizeof(attr_md));
    
        attr_md.read_perm  = p_cus_init->custom_value_char_attr_md.read_perm;
        attr_md.write_perm = p_cus_init->custom_value_char_attr_md.write_perm;
        attr_md.vloc       = BLE_GATTS_VLOC_STACK;
        attr_md.rd_auth    = 0;
        attr_md.wr_auth    = 0;
        attr_md.vlen       = 0;
    
        ble_uuid.type = p_cus->uuid_type;
        //ble_uuid.uuid = CUSTOM_VALUE_CHAR_UUID;
        ble_uuid.uuid = uuid;
    
        memset(&attr_char_value, 0, sizeof(attr_char_value));
    
        attr_char_value.p_uuid    = &ble_uuid;
        attr_char_value.p_attr_md = &attr_md;
    
        if(uuid == 0x9e81)
        {
          attr_char_value.init_len  = 15;
          attr_char_value.init_offs = 0;
          attr_char_value.max_len   = 15;
        }
        else if(uuid == 0x9e86)
        {
          attr_char_value.init_len  = 1;
          attr_char_value.init_offs = 0;
          attr_char_value.max_len   = 1;
        }
        else if(uuid == 0x9e87)
        {
          attr_char_value.init_len  = 4;
          attr_char_value.init_offs = 0;
          attr_char_value.max_len   = 4;
        }
        else
        {
          attr_char_value.init_len  = 45;
          attr_char_value.init_offs = 0;
          attr_char_value.max_len   = 45;
    
          //memset(&char_pf, 0, sizeof(char_pf)); 
          //char_pf.format = BLE_GATT_CPF_FORMAT_UTF8S;
          //char_md.p_char_pf         = &char_pf;
        }
    
    #if 0
        memset(&cccd_md, 0, sizeof(cccd_md));
    
        //  Read  operation on Cccd should be possible without authentication.
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
        
        cccd_md.vloc       = BLE_GATTS_VLOC_STACK;
    
        char_md.char_props.notify = 1;  
        char_md.p_cccd_md         = &cccd_md; 
    #endif
    
        err_code = sd_ble_gatts_characteristic_add(p_cus->service_handle, &char_md,
                                                   &attr_char_value,
                                                   &p_cus->custom_value_handles);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        return NRF_SUCCESS;
    }
    
    uint32_t ble_cus_init(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init)
    {
        if (p_cus == NULL || p_cus_init == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        uint32_t   err_code;
        ble_uuid_t ble_uuid;
        uint16_t   cus_char_uuid;
    
        // Initialize service structure
        p_cus->evt_handler               = p_cus_init->evt_handler;
        p_cus->conn_handle               = BLE_CONN_HANDLE_INVALID;
    
        // Add Custom Service UUID
        ble_uuid128_t base_uuid = {CUSTOM_SERVICE_UUID_BASE};
        err_code =  sd_ble_uuid_vs_add(&base_uuid, &p_cus->uuid_type);
        VERIFY_SUCCESS(err_code);
        
        ble_uuid.type = p_cus->uuid_type;
        ble_uuid.uuid = CUSTOM_SERVICE_UUID;
    
        // Add the Custom Service
        err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &ble_uuid, &p_cus->service_handle);
        if (err_code != NRF_SUCCESS)
        {
            return err_code;
        }
    
        for (int i=0; i < 8; i++)
        {
            cus_char_uuid = CUSTOM_VALUE_CHAR_UUID+ i;
    
            // Add the Custom Characteristic 0
            err_code = custom_value_char_add(p_cus, p_cus_init, cus_char_uuid);
            if (err_code != NRF_SUCCESS)
            {
                return err_code;
            }
        }
    
        return err_code;
         //return custom_value_char_add(p_cus, p_cus_init, CUSTOM_VALUE_CHAR_UUID_1);
    }
    
    /**@brief Function for handling the Connect event.
     *
     * @param[in]   p_cus       Custom Service structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_connect(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
    {
        p_cus->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
        ble_cus_evt_t evt;
    
        evt.evt_type = BLE_CUS_EVT_CONNECTED;
    
        p_cus->evt_handler(p_cus, &evt);
        
        //nrf_gpio_pin_toggle(LED_4);
    }
    
    /**@brief Function for handling the Disconnect event.
     *
     * @param[in]   p_cus       Custom Service structure.
     * @param[in]   p_ble_evt   Event received from the BLE stack.
     */
    static void on_disconnect(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
    {
        UNUSED_PARAMETER(p_ble_evt);
        p_cus->conn_handle = BLE_CONN_HANDLE_INVALID;
        //nrf_gpio_pin_toggle(LED_4);
    }
    
    static void on_write(ble_cus_t * p_cus, ble_evt_t const * p_ble_evt)
    {
        ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
    #if 0
        if(p_ble_evt->evt.gatts_evt.params.write.uuid == 0x9e82)
        {
            int i = p_ble_evt->evt.gatts_evt.params.write.len - 1;
    
            for (; i < 45; i++)
            {
              p_ble_evt->evt.gatts_evt.params.write.data[i] = 0x0;
            }
        }
    #endif
    
    #if 0
    
        sd_ble_gattc_read(p_cus->conn_handle, p_cus->custom_value_handles.value_handle, 0);
    
        ble_gattc_write_params_t write_params;
        uint8_t                  data_buf[10];
    
    
        write_params.handle  = p_cus->custom_value_handles.value_handle;
        write_params.len     = 10;
        write_params.p_value = data_buf;
        write_params.offset  = 0;
        write_params.flags   = 0x1;
    
        for (uint8_t i = 0; i < 10; i++)
        {
            data_buf[i] = i;
        }
    
        // Write data to characteristic.
        sd_ble_gattc_write(p_cus->conn_handle, &write_params);
    
    #endif
        
        // Custom Value Characteristic Written to.
        if (p_evt_write->handle == p_cus->custom_value_handles.value_handle)
        {
            nrf_gpio_pin_toggle(LED_4);
        }
    
        // Check if the Custom value CCCD is written to and that the value is the appropriate length, i.e 2 bytes.
        if ((p_evt_write->handle == p_cus->custom_value_handles.cccd_handle)
            && (p_evt_write->len == 2)
           )
        {
    
            NRF_LOG_INFO("on_write: len %d, p_evt_write->data[0]: %d, p_evt_write->data[1]: %d.",
                         p_evt_write->len,
                         p_evt_write->data[0],
                         p_evt_write->data[1]);
    
            // CCCD written, call application event handler
            if (p_cus->evt_handler != NULL)
            {
                ble_cus_evt_t evt;
    
                if (ble_srv_is_notification_enabled(p_evt_write->data))
                {
                    evt.evt_type = BLE_CUS_EVT_NOTIFICATION_ENABLED;
                }
                else
                {
                    evt.evt_type = BLE_CUS_EVT_NOTIFICATION_DISABLED;
                }
                // Call the application event handler.
                p_cus->evt_handler(p_cus, &evt);
            }
        }
    
    }
    
    void ble_cus_on_ble_evt( ble_evt_t const * p_ble_evt, void * p_context)
    {
       ble_cus_t * p_cus = (ble_cus_t *) p_context;
    
       if (p_cus == NULL || p_ble_evt == NULL)
       {
           return;
       }
       
       switch (p_ble_evt->header.evt_id)
       {
           case BLE_GAP_EVT_CONNECTED:
               on_connect(p_cus, p_ble_evt);
               break;
    
           case BLE_GAP_EVT_DISCONNECTED:
               on_disconnect(p_cus, p_ble_evt);
               break;
           case BLE_GATTS_EVT_WRITE:
               on_write(p_cus, p_ble_evt);
               break;
    
           case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
               on_write(p_cus, p_ble_evt);
               break;
    
           default:
               // No implementation needed.
               break;
       }
    }

    I am attaching the nrf Connect app's screenshot showing the junk values without even writing to these custom characteristics.

      custom_ble_service_example.zip

    Also, attaching the complete code base for this segger solution.

    PS: I am using nrf connect app and my mobile device is Moto G5 S Plus

  • Hi,

    Which SDK version do you use? Looking at you code I do not see that you set a default value (attr_char_value.p_value). Is that intentional?

  • I am using SDK version 15.0.0.
    I tried setting a default value as in , 

    "attr_char_value.p_value = NULL;"

    but still I am getting this junk data while reading from the NRFConnect app.

Reply Children
  • This is effectively the same as what you did earlier, since it was already memset to 0. The point is that this way you do not provide any default data, but you specifies that the initial length is larger than 0. That mean you will get random/uninitialized data of whatever happens to be in memory.

    If you want to initialize all custom characteristics to (say) 0, then you could add the following snippet to your custom_value_char_add() function in ble_cus.c right before you call sd_ble_gatts_characteristic_add() (around line 154):

        // Zero-initialize the data for all. It is OK to point to the
        // same buffer for all as long as it is scaled for the largest,
        // as it is copied to the stack (BLE_GATTS_VLOC_STACK),
        #define                     MAX_LEN 45
        static uint8_t              zero_init[MAX_LEN] = {0};
        attr_char_value.p_value =   zero_init;

  • Thanks for the reply Einar.

    With your change, I am able to set the default value as zero in the custom characteristics.

    Attaching the screenshot also.

  • Hi Einar, 

    I am getting one more issue. Whenever I am doing a power cycle to the Nordic device, and I connect back using nrfConnect, all the custom characteristics are coming up as 0. 
    They are not retaining the previous values. Can you please help.

  • Of course it will lose data when power cycled!

    If you want data to be retained over  a power cycle then you will need to implement some form of non-volatile storage - and reload from that on startup.

  • Hi Awneil,

    Thanks for the reply. Is there any example application in the Nordic SDK where the data is retained using flash memory storage and provided to the custom characteristics on a power cycle.

Related