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

DIS Update Serial Number

Hi,

I would like to update the Device Information Service's (DIS) serial number characteristic to reflect the actual serial number assigned by our production equipment. I understand that ble_dis.c (as supplied by Nordic) cannot do this.

Now I wonder how this is done best and surely other people wanted to do the same.

What I have done so far:

  • Added function ble_dis_update_serial (see below)
  • The function actually does something (!) but the serial number string shown in nRF Connect is not correct. To be more specific: it is too long or too short
  • I have modified attr_char_value.init_len (to the actual string length) and attr_char_value.max_len (to 16) as suggested in several posts. Unfortunately this does not help. 

Please advise how I can modify DIS "serial number" to accept variable length serial number strings. 

Thank you

Matthias

My function to update the Serial Number characteristic:

void ble_dis_update_serial (uint16_t conn_handle, ble_srv_utf8_str_t serial_num_str)
{
    uint32_t err_code;
    ble_gatts_value_t gatts_value;


    memset (&gatts_value, 0, sizeof (gatts_value));

    gatts_value.len = serial_num_str.length;
    gatts_value.offset = 0;
    gatts_value.p_value = serial_num_str.p_str;

    // Update database.
    err_code = sd_ble_gatts_value_set (conn_handle, serial_num_handles.value_handle, &gatts_value);

}

  • Hi,

    The length you are using during initialization becomes the maximum length for each characteristic, so using the maximum length for ble_dis_init_t::serial_num_str.length in the call to ble_dis_init() should be all you need to do. In what way does it not work?

    As a side note: If you want the serial number to be persistent so that the new serial number is used after reset, you have to write it to flash (for instance using FDS) and read it and set it accordingly when you call ble_dis_init() after reset.

  • Hi Einar,

    With respect to persistency: yes, of course...

    With respect to what doesn't work: The text displayed on nRF Connect (for example) is different to the string I'm passing to sd_ble_gatts_value_set. Do I need to pad out my string with \0 to max_len?

    Example:

    • assume max_len is set to 16
    • I set serial_number to "1232" -> what do I need to do?
    • I update serial number to "aaddbbtt" -> what do I need to do?
    • I update serial number to "?" -> what do I need to do?

    I would like nRF Connect to display exactly what is shown in the example.

    Cheers

    M

  • Hi,

    There is essentially two things you need to think of:

    1. The initial length becomes the maximum length.
    2. The maximum length is always used unless you set is_var_len in the characteristics properties to true (I did not mention this in my initial post).

    With those things in mind updating the serial number works when I tested on my side. You can see these modifications from SDK 15.2 where I used your code and the HRS example. Button 4 on the DK is used to update to a new and shorter serial number.

    diff --git a/examples/ble_peripheral/ble_app_hrs/main.c b/examples/ble_peripheral/ble_app_hrs/main.c
    index d797b07..9094c88 100644
    --- a/examples/ble_peripheral/ble_app_hrs/main.c
    +++ b/examples/ble_peripheral/ble_app_hrs/main.c
    @@ -84,6 +84,8 @@
     
     #define DEVICE_NAME                         "Nordic_HRM"                            /**< Name of device. Will be included in the advertising data. */
     #define MANUFACTURER_NAME                   "NordicSemiconductor"                   /**< Manufacturer. Will be passed to Device Information Service. */
    +#define SERIAL_NUMBER                       "0000000000000001"                   /**< Manufacturer. Will be passed to Device Information Service. */
    +
     #define APP_ADV_INTERVAL                    300                                     /**< The advertising interval (in units of 0.625 ms. This value corresponds to 187.5 ms). */
     
     #define APP_ADV_DURATION                    18000                                   /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    @@ -159,6 +161,9 @@ static ble_uuid_t m_adv_uuids[] =                                   /**< Univers
     };
     
     
    +extern ble_gatts_char_handles_t serial_num_handles;
    +
    +
     /**@brief Callback function for asserts in the SoftDevice.
      *
      * @details This function will be called in case of an assert in the SoftDevice.
    @@ -463,6 +468,25 @@ static void nrf_qwr_error_handler(uint32_t nrf_error)
     }
     
     
    +static void ble_dis_update_serial (uint16_t conn_handle, char * serial_num)
    +{
    +    uint32_t            err_code;
    +    ble_gatts_value_t   gatts_value;
    +    ble_srv_utf8_str_t  serial_num_str;  
    +
    +    ble_srv_ascii_to_utf8(&serial_num_str, serial_num);
    +
    +    memset(&gatts_value, 0, sizeof (gatts_value));
    +
    +    gatts_value.len       = serial_num_str.length;
    +    gatts_value.offset    = 0;
    +    gatts_value.p_value   = serial_num_str.p_str;
    +
    +    // Update database.
    +    err_code = sd_ble_gatts_value_set(conn_handle, serial_num_handles.value_handle, &gatts_value);
    +}
    +
    +
     /**@brief Function for initializing services that will be used by the application.
      *
      * @details Initialize the Heart Rate, Battery and Device Information services.
    @@ -518,6 +542,7 @@ static void services_init(void)
         memset(&dis_init, 0, sizeof(dis_init));
     
         ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, (char *)MANUFACTURER_NAME);
    +    ble_srv_ascii_to_utf8(&dis_init.serial_num_str, (char *)SERIAL_NUMBER);
     
         dis_init.dis_char_rd_sec = SEC_OPEN;
     
    @@ -820,6 +845,13 @@ void bsp_event_handler(bsp_event_t event)
                 }
                 break;
     
    +        case BSP_EVENT_KEY_3:
    +            NRF_LOG_INFO("Update serial number.");
    +            ble_dis_update_serial(
    +                m_conn_handle,
    +                (char *)"123456789");
    +            break;
    +
             default:
                 break;
         }
    

    diff --git a/components/ble/ble_services/ble_dis/ble_dis.c b/components/ble/ble_services/ble_dis/ble_dis.c
    index bfdf768..8d54b90 100644
    --- a/components/ble/ble_services/ble_dis/ble_dis.c
    +++ b/components/ble/ble_services/ble_dis/ble_dis.c
    @@ -58,7 +58,7 @@
     static uint16_t                 service_handle;
     static ble_gatts_char_handles_t manufact_name_handles;
     static ble_gatts_char_handles_t model_num_handles;
    -static ble_gatts_char_handles_t serial_num_handles;
    +ble_gatts_char_handles_t serial_num_handles;
     static ble_gatts_char_handles_t hw_rev_handles;
     static ble_gatts_char_handles_t fw_rev_handles;
     static ble_gatts_char_handles_t sw_rev_handles;
    @@ -140,6 +140,7 @@ static uint32_t char_add(uint16_t                        uuid,
         add_char_params.p_init_value    = p_char_value;
         add_char_params.char_props.read = 1;
         add_char_params.read_access     = rd_sec;
    +    add_char_params.is_var_len      = true;
     
         return characteristic_add(service_handle, &add_char_params, p_handles);
     }
    

Related