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

BLE service with multiple characteristics(client/switch and bulb/server)

I am new to C programming and BLE in general.I am trying to create a service with two characteristics,(the application simply is a modification of BLE bulb and switch). How the original application work is, on the client/switch if you push button 1, it turns on the LED 3 on the server/bulb, and when you push button 2 it turns it off.So it is only one service and one characteristic. The client acts as central and server acts as a peripheral.

What I want is to add another characteristic so that If I push button 3 on the client to turn on  LED 4 on the server .(So in short button 1 will turn LED 3 on and button 3 will turn LED4 on).So I added additional characteristic on both server and client, but the problem is I don't know how to check/distinguish whether the incoming request  on the server is which characteristic.

Question

1. How do I inspect the incoming request whether is coming from characteristic 1 or 2 in the server's main.c  led_write_handler function?

Here is the code

static void led_write_handler(uint16_t conn_handle, ble_led_service_t * p_led_service, uint8_t led_state)
{
   //HERE I WANT TO DO IF THE REQUEST IS CHARACTERSIC 1 TURN LED3 AND IF 2 TURN LED 4
     //NRF_LOG_INFO("led handled %d", p_led_service->led_3_char_handles);
    if (led_state)
    {
        bsp_board_led_on(LIGHTBULB_LED3);
        NRF_LOG_INFO("Received LED ON!");
    }
    else
    {
        bsp_board_led_off(LIGHTBULB_LED3);
        NRF_LOG_INFO("Received LED OFF!");
    }
}

  • The reason you're not able to differentiate which characteristic was written inside led_write_handler(), is because none of the arguments give any information about it. 

    The conn_handle and led_state does not tell you which characteristic was written to. You probably thought p_led_service would help you check what characteristic was written to, but this is not the case. It will be the same for both characteristics. Let me explain why:

    • The function ble_led_service_on_ble_evt() is registered through the macro NRF_SDH_BLE_OBSERVER(), and it is associated with a context (the 4'th parameter)
    • Each "observer" will then have a unique context associated with it, that is set once when registered
      • e.g. in your case the observer ble_led_service_on_ble_evt() is associated with a structure of type ble_led_service_t (please ask if you don't understand this and want me to elaborate)

    One approach to differentiate between the characteristic, could be to check the uuid:

    static void on_write(ble_led_service_t * p_led_service, ble_evt_t const * p_ble_evt)
    {
        ble_gatts_evt_write_t const * p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        
        uint16_t led_uuid = p_evt_write->uuid.uuid;
        
        if(.....){
            //Pass in uuid as an argument and take the appropriate action depending on that
            p_led_service->led_write_handler(p_ble_evt->evt.gap_evt.conn_handle, p_led_service, p_evt_write->data[0], led_uuid);
        }
    }

    Hope this helps.

    Best regards,

    Simon

  • Hi Simon thank you for taking a look.

    So it seems like I just need to change the structure of led_write_handler() to accept additional uint16_t  in .h file  right?

  • Simon ,

    I did what you advised but It seems like I am still experiencing the same issue. On main.c led_write_handler() the uuid always prints 65632 when I press button 2 or 3.

    But on led_server_service.c on_write() uuid prints correctly 2 for button 2 and 3 for button 3 which are the uuid's I defined. So the issue is still on main.c led_write_handler()

    static void led_write_handler(uint16_t conn_handle, ble_led_service_t * p_led_service, uint8_t led_state,uint16_t led_uuid)
    {
    
         NRF_LOG_INFO("led uuid= %d",led_uuid); //Always prints 65632
    
        if (led_state)
        {
            bsp_board_led_on(LIGHTBULB_LED3);
            NRF_LOG_INFO("Received LED ON!");
        }
        else
        {
            bsp_board_led_off(LIGHTBULB_LED3);
            NRF_LOG_INFO("Received LED OFF!");
        }
    }

  • I managed to make it work (led_write_handler prints correct uuid). Follow these steps exactly to make it work:

    • Download SDK 15.3.0 and place it into an appropriate location
    • Download the file two_char_leds.rar (which I have provided)
    • For the peripheral example
      • Swap <..>two_char_leds\led_periph_server/ble_lbs.c and <..>two_char_leds\led_periph_server/ble_lbs.h with nRF5_SDK_15.3.0_59ac345\components\ble\ble_services\ble_lbs\ble_lbs.c and nRF5_SDK_15.3.0_59ac345\components\ble\ble_services\ble_lbs\ble_lbs.h 
      • Swap <..>\two_char_leds\led_periph_server\main.c with nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\ble_app_blinky\main.c
    • For the central example
      • Swap <..>two_char_leds\led_central_client/ble_lbs_c.c and <..>two_char_leds\led_central_client/ble_lbs_c.h with nRF5_SDK_15.3.0_59ac345\components\ble\ble_services\ble_lbs_c\ble_lbs_c.c and nRF5_SDK_15.3.0_59ac345\components\ble\ble_services\ble_lbs_c\ble_lbs_c.h 
      • Swap <..>\two_char_leds\led_central_client\main.c with nRF5_SDK_15.3.0_59ac345\examples\ble_central\ble_app_blinky_c\main.c
    • Connect two nRF52832 DK (that is what I tested with, but it should work with nRF52840 as well) to the computer and build and flash the ble_app_blinky_c example onto one of the boards and the ble_app_blinky example onto the other board
    • Press button 1 on the central board, which should turn on/off  led 3 on the peripheral board
    • Press button 2 on the central board, which should turn on/off led 4 on the peripheral board

    two_char_leds.rar

    Best regards,

    Simon

  • Thank you, Simon, for sharing the code and taking the time to help. I am going to compare your code with mine. Right off the bat, I can see your advertising_init implementation is a little different from mine. But I am still continuing to look for discrepancies.

Related