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

Notifications and read function to be used in the same application

Hi Devs,

based on this example

https://github.com/NordicPlayground/nRF52-Bluetooth-Course

i was able to run it, and the value field appear below the Unknown Characteristics properties incremented every second as expected.

MY question however is whether it is possible at all to have both the enable notification and "read" button to run at the same time and update that value field. The purpose is that if i don't enable notifications, and just push the read button, the value field will be read on demand and not pushed to the client. Of course a better functionality would be if "notifications enabled" and read button pushed, both will not crash each other and just update the value field at a faster pace. Hope i have explained the situation clearly, and any help would be appreciated. thx.

Parents
  • Hi Hung,

    the "read" doesn't work in the nRF connect application. When pressed it does nothing. Does it work at your side ? thx

  • I haven't tried myself. But I don't see any reason why it wouldn't work. 

    If you are getting started and want to continue, I would suggest to have a look at the ble_app_blinky . You can use the nRFBlinky app to interact with it. The source code of the app is available on our github

    You can also have a look at ble_app_uart example . 

  • Hi Hung,

    thanks for directing me back to the basics. Helped clear my mind that i wasn't explaining the situation clearly.

    Let me try this again.

    Recently i finished projects using the ESP32, and the EVT handler had WRITE_EVT and READ_EVT;

    The nRF doesn't have READ_EVT; this seems to be done automatically by the stack on a "normal" read request. There however seems to be an authorize read/write http://developer.nordicsemi.com/nRF51_SDK/nRF51_SDK_v7.x.x/doc/7.2.0/s110/html/a00888.html ( do clarify if wrong). But I have no clue how to update the unknown characteristic value field when receiving this event. I understand that the notification evt starts a timer that does an update every second, calling the ble_cus_custom_value_update(); However, trying to run the ble_cus_custom_value_update() on RW_AUTHORIZE_REQUEST event causes a fatal error and reboots the nRF528.

    I need to do the following on a read event:

    1) Update the value field of the unknown characteristic from a sensor reading when receive a read request.

    2) Sleep after that for "some" time

    3) Wake up and advertise, re-connect , back to step 1. The cycle continues.

    So I am asking is there any way to update the custom characteristic field when receiving a authorize read request ? thx.

  • Hi Pete, 

    You are correct on that the normal read (unauthorized read) is handled by the softdevice and you have no event for that. 

    The application receive an event for authorized read. But you would need to configure the characteristic for that. Please set attr_md.rd_auth = 1 when you add the characteristic.

    If you use S132 you should look at the documentation for S132 instead of S110. Please have a look here. Make sure you call the reply api in the event so that the softdevice would be able to reply to the peer. 

    When you receive an error, please try to find the line that cause the error and the error code. With that you can compare to the description of the list of errors for the function and can find the cause. Please have a look at the debug guide here

    Regarding your requirements, at step 2 how long do you plan to sleep ? Do you plan to keep the connection ? If not, you can simply trigger a disconnection and then enter sleep mode. 

  • Hi Hung,

    regarding configuring the characteristics, here is what i have already done previously to the ble_cus.c sample provided.

    First,

    static uint32_t custom_value_char_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init){

    ....

    attr_md.rd_auth    = 1;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    .....

    }   

    Then for ,

    void ble_cus_on_ble_evt( ble_evt_t const * p_ble_evt, void * p_context)

    {..........

    ///switch statement....:

    case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
           
                ble_gatts_evt_rw_authorize_request_t  req;
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                req = p_ble_evt->evt.gatts_evt.params.authorize_request;
                            
                if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
                {
                    
                        if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
                        {      
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                        }
                        else
                        {
                                                NRF_LOG_INFO("BLE_GATTS_AUTHORIZE_Read.\r\n");
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                        }

                        auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED;
                        err_code  = sd_ble_gatts_rw_authorize_reply(
                                                                  p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
                        APP_ERROR_CHECK(err_code);
                    
                        }
                            ble_cus_evt_t evt;
                            evt.evt_type = BLE_CUS_EVT_NOTIFICATION_ENABLED;
                            p_cus->evt_handler(p_cus,&evt);
                            break;

                 }

    ...........}

    I added the case for authorize read in the switch statement, and the code following should be for sd_ble_gatts_rw_authorize_reply. Finally i tried to direct the evt type towarrds BLE_CUS_EVT_NOTIFICATION_ENABLED to trigger a value update, hoping that would show the updated value to the characteristic field, which crashed the application and caused a reboot. I will definitely try to follow the debug guide and see what went wrong, but meanwhile i am thinking that this code " p_cus->evt_handler(p_cus,&evt);" is what might be wrong. Which brings us back to the main point of why I asked for examples that show how to update the characteristic field on authorize read event.

    Regarding step2 , the connection will be disconnected for power saving considerations. The time is not fixed for now, and will likely change . Probably a variable will be defined to hold how long that sleep duration will last, but lets say that is 20 seconds. BTW , what API do i call for triggering a disconnection ?

    Lots of questions, my apologies not being familiar with the nRF device, and thx again for your help.

Reply
  • Hi Hung,

    regarding configuring the characteristics, here is what i have already done previously to the ble_cus.c sample provided.

    First,

    static uint32_t custom_value_char_add(ble_cus_t * p_cus, const ble_cus_init_t * p_cus_init){

    ....

    attr_md.rd_auth    = 1;
    attr_md.wr_auth    = 0;
    attr_md.vlen       = 0;

    .....

    }   

    Then for ,

    void ble_cus_on_ble_evt( ble_evt_t const * p_ble_evt, void * p_context)

    {..........

    ///switch statement....:

    case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
           
                ble_gatts_evt_rw_authorize_request_t  req;
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                req = p_ble_evt->evt.gatts_evt.params.authorize_request;
                            
                if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
                {
                    
                        if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
                        {      
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                        }
                        else
                        {
                                                NRF_LOG_INFO("BLE_GATTS_AUTHORIZE_Read.\r\n");
                            auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
                        }

                        auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED;
                        err_code  = sd_ble_gatts_rw_authorize_reply(
                                                                  p_ble_evt->evt.gatts_evt.conn_handle, &auth_reply);
                        APP_ERROR_CHECK(err_code);
                    
                        }
                            ble_cus_evt_t evt;
                            evt.evt_type = BLE_CUS_EVT_NOTIFICATION_ENABLED;
                            p_cus->evt_handler(p_cus,&evt);
                            break;

                 }

    ...........}

    I added the case for authorize read in the switch statement, and the code following should be for sd_ble_gatts_rw_authorize_reply. Finally i tried to direct the evt type towarrds BLE_CUS_EVT_NOTIFICATION_ENABLED to trigger a value update, hoping that would show the updated value to the characteristic field, which crashed the application and caused a reboot. I will definitely try to follow the debug guide and see what went wrong, but meanwhile i am thinking that this code " p_cus->evt_handler(p_cus,&evt);" is what might be wrong. Which brings us back to the main point of why I asked for examples that show how to update the characteristic field on authorize read event.

    Regarding step2 , the connection will be disconnected for power saving considerations. The time is not fixed for now, and will likely change . Probably a variable will be defined to hold how long that sleep duration will last, but lets say that is 20 seconds. BTW , what API do i call for triggering a disconnection ?

    Lots of questions, my apologies not being familiar with the nRF device, and thx again for your help.

Children
  • Please walk through the message sequence chart, there you will find the use for many API, including the connection termination which is here.

    Please try to test step by step. The first step is to make sure authorization read is working. From what you have in the code, it seems that it would work fine. 

    Except for this part:  evt.evt_type = BLE_CUS_EVT_NOTIFICATION_ENABLED;
                            p_cus->evt_handler(p_cus,&evt);

    It should be removed. 

    I'm not sure why you want to trigger a notification but if you want, you would need to first enable it from the client side. And then inside BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST you call ble_cus_custom_value_update() in particular sd_ble_gatts_hvx() should be called. It's described in this chart. 

Related