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

NRF_THINGY52 Configuration characteristics and Custom_Services

Hi, I am trying to create a custom_service for my application.

I am using nRF52832 SDK_16

SES

I want to create the BLE_SERVICES

which has send characteristics and read characteristics , like multiple characteristics in single SERVICES 

1. First characteristics              - need to send INT value

2. Second characteristics       - need to send STRING value / TEXT

3. Third characteristics            -  need to receive INT value

4. Fourth characteristics          - need to receive STRING value / TEXT

this is my case

I have refereed  nRF THINGY52 .

there some custom services like TES, TMS, TCS

While checking nRF THINGY 52 with the nRF CONNECT and nRF THINGY mobile app

I came with few queries

1. WRITE NOT PERMIT

       I have look custom services in thingy52 . in that every service has configuration characteristics. that can be changed via nRF thingy mobile app

and while using nRF CONNECT app    not able to write . is there any format i need to work on this configuration

what is work of this functions

on_write

static void on_write(ble_tes_t * p_tes, ble_evt_t * p_ble_evt)
{
    ble_gatts_evt_write_t * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;

    if ( (p_evt_write->handle == p_tes->temperature_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        bool notif_enabled;

        notif_enabled = ble_srv_is_notification_enabled(p_evt_write->data);

        if (p_tes->is_temperature_notif_enabled != notif_enabled)
        {
            p_tes->is_temperature_notif_enabled = notif_enabled;

            if (p_tes->evt_handler != NULL)
            {
                p_tes->evt_handler(p_tes, BLE_TES_EVT_NOTIF_TEMPERATURE, p_evt_write->data, p_evt_write->len);
            }
        }
    }
    else if ( (p_evt_write->handle == p_tes->pressure_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        bool notif_enabled;

        notif_enabled = ble_srv_is_notification_enabled(p_evt_write->data);

        if (p_tes->is_pressure_notif_enabled != notif_enabled)
        {
            p_tes->is_pressure_notif_enabled = notif_enabled;

            if (p_tes->evt_handler != NULL)
            {
                p_tes->evt_handler(p_tes, BLE_TES_EVT_NOTIF_PRESSURE, p_evt_write->data, p_evt_write->len);
            }
        }
    }
    else if ( (p_evt_write->handle == p_tes->humidity_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        bool notif_enabled;

        notif_enabled = ble_srv_is_notification_enabled(p_evt_write->data);

        if (notif_enabled != p_tes->is_humidity_notif_enabled)
        {
            p_tes->is_humidity_notif_enabled = notif_enabled;

            if (p_tes->evt_handler != NULL)
            {
                p_tes->evt_handler(p_tes, BLE_TES_EVT_NOTIF_HUMIDITY, p_evt_write->data, p_evt_write->len);
            }
        }
    }
    else if ( (p_evt_write->handle == p_tes->gas_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        bool notif_enabled;

        notif_enabled = ble_srv_is_notification_enabled(p_evt_write->data);

        if (notif_enabled != p_tes->is_gas_notif_enabled)
        {
            p_tes->is_gas_notif_enabled = notif_enabled;

            if (p_tes->evt_handler != NULL)
            {
                p_tes->evt_handler(p_tes, BLE_TES_EVT_NOTIF_GAS, p_evt_write->data, p_evt_write->len);
            }
        }
    }
    else if ( (p_evt_write->handle == p_tes->color_handles.cccd_handle) &&
         (p_evt_write->len == 2) )
    {
        bool notif_enabled;

        notif_enabled = ble_srv_is_notification_enabled(p_evt_write->data);

        if (notif_enabled != p_tes->is_color_notif_enabled)
        {
            p_tes->is_color_notif_enabled = notif_enabled;

            if (p_tes->evt_handler != NULL)
            {
                p_tes->evt_handler(p_tes, BLE_TES_EVT_NOTIF_COLOR, p_evt_write->data, p_evt_write->len);
            }
        }
    }
    else
    {
        // Do Nothing. This event is not relevant for this service.
    }
}

on_authorize_req

static void on_authorize_req(ble_tes_t * p_tes, ble_evt_t * p_ble_evt)
{
    ble_gatts_evt_rw_authorize_request_t * p_evt_rw_authorize_request = &p_ble_evt->evt.gatts_evt.params.authorize_request;
    uint32_t err_code;

    if (p_evt_rw_authorize_request->type  == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
    {
        if (p_evt_rw_authorize_request->request.write.handle == p_tes->config_handles.value_handle)
        {
            ble_gatts_rw_authorize_reply_params_t rw_authorize_reply;
            bool                                  valid_data = true;

            // Check for valid data
            if(p_evt_rw_authorize_request->request.write.len != sizeof(ble_tes_config_t))
            {
                valid_data = false;
            }
            else
            {
                ble_tes_config_t * p_config = (ble_tes_config_t *)p_evt_rw_authorize_request->request.write.data;

                if ( (p_config->temperature_interval_ms < BLE_TES_CONFIG_TEMPERATURE_INT_MIN)    ||
                     (p_config->temperature_interval_ms > BLE_TES_CONFIG_TEMPERATURE_INT_MAX)    ||
                     (p_config->pressure_interval_ms < BLE_TES_CONFIG_PRESSURE_INT_MIN)          ||
                     (p_config->pressure_interval_ms > BLE_TES_CONFIG_PRESSURE_INT_MAX)          ||
                     (p_config->humidity_interval_ms < BLE_TES_CONFIG_HUMIDITY_INT_MIN)          ||
                     (p_config->humidity_interval_ms > BLE_TES_CONFIG_HUMIDITY_INT_MAX)          ||
                     (p_config->color_interval_ms < BLE_TES_CONFIG_COLOR_INT_MIN)         ||
                     (p_config->color_interval_ms > BLE_TES_CONFIG_COLOR_INT_MAX)         ||
                     (p_config->gas_interval_mode < BLE_TES_CONFIG_GAS_MODE_MIN)                 ||
                     ((int)p_config->gas_interval_mode > (int)BLE_TES_CONFIG_GAS_MODE_MAX))
                {
                    valid_data = false;
                }
            }

            rw_authorize_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;

            if (valid_data)
            {
                rw_authorize_reply.params.write.update      = 1;
                rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                rw_authorize_reply.params.write.p_data      = p_evt_rw_authorize_request->request.write.data;
                rw_authorize_reply.params.write.len         = p_evt_rw_authorize_request->request.write.len;
                rw_authorize_reply.params.write.offset      = p_evt_rw_authorize_request->request.write.offset;
            }
            else
            {
                rw_authorize_reply.params.write.update      = 0;
                rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED;
            }

            err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle,
                                                       &rw_authorize_reply);
            APP_ERROR_CHECK(err_code);

            if ( valid_data && (p_tes->evt_handler != NULL))
            {
                p_tes->evt_handler(p_tes,
                                   BLE_TES_EVT_CONFIG_RECEIVED,
                                   p_evt_rw_authorize_request->request.write.data,
                                   p_evt_rw_authorize_request->request.write.len);
            }
        }
    }
}

and on_connect , on_disconnect :

means is that particular service will work after the ble is connected to the host . and stops after it disconnect ?

static void on_connect(ble_tes_t * p_tes, ble_evt_t * p_ble_evt)
{
    p_tes->conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
}



static void on_disconnect(ble_tes_t * p_tes, ble_evt_t * p_ble_evt)
{
    UNUSED_PARAMETER(p_ble_evt);
    p_tes->conn_handle = BLE_CONN_HANDLE_INVALID;
}

2. Is THINGY has memory

               while i tried to changed the value of the temperature interval update to 1000ms in thingy app . and it updated and works even after power off .

       IS THINGY use external memory like EEPROM

3.   HOW TO NAME CUSTOM SERVICES AND CHARACTERISTICS

     while creating any custom service it shows unknown services

but in THINGY device in nRF CONNECT app is shows the name . how to name to custom services

Parents
  • Hello,

    1. The reason you are able to write in the thingy app, but not in the nRF Connect is that the characteristic requires that you are paired in order to use those characteristics. Try to bond, and see if you are able to use the characteristics then.

    2. Thingy has memory.

     

    IS THINGY use external memory like EEPROM

     No. The nRF52832 (and all the other nRF5 chips) has internal flash, so these settings are stored in flash, so that it is not lost over power cycles.

    3. It is not possible to name services. The name of the services aren't stored in the service, but nRF Connect has stored some UUIDs. 

    In nRF Connect for Destkop it is possible to add custom names to UUIDs, but it is unfortunately not possible on the nRF Connect for iOS. (Not sure whether it is possible on Android. You can check in the settings in the app).

    Best regards,

    Edvin

  • Hi Edvin,

    on_authorize_req

    can you explain this functionality 

    1. The reason you are able to write in the thingy app, but not in the nRF Connect is that the characteristic requires that you are paired in order to use those characteristics. Try to bond, and see if you are able to use the characteristics then.

    can you share me pictures how to send "ENVIRONMENTAL CONFIGURATION CHARACTERISTICS" . because it has temperature, PRESSURE and other configuration in one characteristics . 

    so don't know how to send a data

    it should be uint8 or byte or byte array or 

    please post any screenshot it will helpful.

    The nRF52832 (and all the other nRF5 chips) has internal flash, so these settings are stored in flash, so that it is not lost over power cycles.

    can you share related documents 

    if i do DFU, the application layer double that time the flash memory will reduce ?

    will the application (app size increase )  will effect flash storage?

    https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v16.0.0%2Flib_bootloader_dfu_process.html

  • Sunil vignesh said:

    on_authorize_req

    can you explain this functionality 

     This function is called whenever the connected device wants to write to any of the characteristics. The function is a custom function (not part of the BLE stack) that just checks whether the parameters that the connected device writes is within some certain limits. If everything is ok, then it will apply the settings. If not, it will  deny them.

     

    Sunil vignesh said:

    can you share me pictures how to send "ENVIRONMENTAL CONFIGURATION CHARACTERISTICS" . because it has temperature, PRESSURE and other configuration in one characteristics . 

    so don't know how to send a data

    it should be uint8 or byte or byte array or 

    please post any screenshot it will helpful.

     This is the same characteristic as above, right?

    It is all in the source code. Yopu can see from the on_authorize_req() that the input is cast to a ble_tes_config_t.

    It has this form:

    typedef PACKED( struct
    {
        uint16_t                temperature_interval_ms;
        uint16_t                pressure_interval_ms;
        uint16_t                humidity_interval_ms;
        uint16_t                color_interval_ms;
        uint8_t                 gas_interval_mode;
        ble_tes_color_config_t  color_config;
    }) ble_tes_config_t;

    So, first 16 bits are temperature interval in ms, second is pressure interval in ms, and so on... (nb: gas interval is 8 bits). Lastly the color config is this (but I guess you see it in the source code)

    typedef PACKED( struct
    {
        uint8_t  led_red;
        uint8_t  led_green;
        uint8_t  led_blue;
    }) ble_tes_color_config_t;

    These settings are stored a different place than the application itself. DFU is quite complex, but you can look at the figure here, to see where things are stored. From address 0 the order is:

    1.Softdevice

    2. application

    3. flash data storage (FDS) for settings storage (marked "Application Data" in the figure).

    4. Bootloader.

    1 and 2 are placed directly from 0x0000000 in flash, while 3 and 4 are pushed as close to the end of the flash as possible.

    When you do a DFU, the application is first deleted, and then the bootloader will receive the new application. This way the flash will not fill up. As long as the new application use the same format on the application data settings, then these will remain the same accross DFU.

    Again, DFU is quite complex. You can read through this blog post to see how to get started with DFU.

    Please note that the Thingy:52 comes shipped with a bootloader, but that is a signed bootloader. If you want to perform DFU, you must flash your own bootloader (with a programmer). It is not possible to use the one that is already programmed. This one is only for FW updates from Nordic Semiconductor.

    Best regards,

    Edvin

  • By the way, I suggest you try to connect to the thingy using nRF Connect for Desktop, to see what the services and characteristics looks like. It may be a good way to try and find out how these characteristics work.

    BR,

    Edvin

  • Hi Edvin, 

      Thank you, Finally i know how to write.

    I want to write the full data .

    if i want to change the temperature interval means . i have to change the value for temperature char and along with that i need to send all other char value also to write.

    if i didn't send other value means . it will create error  right?

     is this  the function of on_authorize_req ? 

    on_authorize_req   only check the written data size is matched with the configured data after that only it will write or overwrite the data. otherwise it will reject . is it right?

    if i done the above process without on_authorize_req . only temperature char only write in the sense it will write or it will reject .?

    i will check regarding bootloader (your 3rd and 4th point)

  • Sunil vignesh said:
    if i didn't send other value means . it will create error  right?

     Yes.

     

    Sunil vignesh said:
    on_authorize_req   only check the written data size is matched with the configured data after that only it will write or overwrite the data. otherwise it will reject . is it right?

     Yes.

     

    Sunil vignesh said:
    if i done the above process without on_authorize_req . only temperature char only write in the sense it will write or it will reject .?

    Look at this part from on_authorize_req():

                if (valid_data)
                {
                    rw_authorize_reply.params.write.update      = 1;
                    rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                    rw_authorize_reply.params.write.p_data      = p_evt_rw_authorize_request->request.write.data;
                    rw_authorize_reply.params.write.len         = p_evt_rw_authorize_request->request.write.len;
                    rw_authorize_reply.params.write.offset      = p_evt_rw_authorize_request->request.write.offset;
                }
                else
                {
                    rw_authorize_reply.params.write.update      = 0;
                    rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED;
                }

    If valid_data == true, then it will update.

    If valid_data == false, it will not update the parameters.

    sd_ble_gatts_rw_authorize_reply() will reply with rw_authorize_reply.params.write.update. If this is set to 1, then you will update. If not, then no update.

Reply
  • Sunil vignesh said:
    if i didn't send other value means . it will create error  right?

     Yes.

     

    Sunil vignesh said:
    on_authorize_req   only check the written data size is matched with the configured data after that only it will write or overwrite the data. otherwise it will reject . is it right?

     Yes.

     

    Sunil vignesh said:
    if i done the above process without on_authorize_req . only temperature char only write in the sense it will write or it will reject .?

    Look at this part from on_authorize_req():

                if (valid_data)
                {
                    rw_authorize_reply.params.write.update      = 1;
                    rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                    rw_authorize_reply.params.write.p_data      = p_evt_rw_authorize_request->request.write.data;
                    rw_authorize_reply.params.write.len         = p_evt_rw_authorize_request->request.write.len;
                    rw_authorize_reply.params.write.offset      = p_evt_rw_authorize_request->request.write.offset;
                }
                else
                {
                    rw_authorize_reply.params.write.update      = 0;
                    rw_authorize_reply.params.write.gatt_status = BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED;
                }

    If valid_data == true, then it will update.

    If valid_data == false, it will not update the parameters.

    sd_ble_gatts_rw_authorize_reply() will reply with rw_authorize_reply.params.write.update. If this is set to 1, then you will update. If not, then no update.

Children
No Data
Related