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

Send data to selected unicast address node in mesh network

Hello 

i am working with light switch proxy client server  sdk example.i make provision light and switch using nrf mesh application.i have three nrf52832 dk board.i flashed light switch proxy client example on one  nrf52832 dk board board and light switch proxy server example on other two nrf52832 dk board.i provisioned all nodes with nrf mesh application and i successfully turn on light on two server with one client.i know all server node have unicast address.now i want to turn on light on specific server using unicast address.i know i can set server unicast address in client publication address using nrf mesh app for send messege to specific server. but i want to do this using programmatically.

so how can i do this.i read and understand current sdk proxy client server example code and i found proxy client send messege with group address so how can i send messege to specific unicast address and what changes i will have to make for the same.

Thanks.

  • Hi,

    Are you currently using mesh sdk v2.2.0? If not, I firmly recommend using the latest mesh sdk. As you can see from the button_event_handler in main.c of the proxy client example below:

        switch (button_number)
        {
            case 0:
            case 1:
                /* Demonstrate acknowledged transaction, using 1st client model instance */
                /* In this examples, users will not be blocked if the model is busy */
                (void)access_model_reliable_cancel(m_clients[0].model_handle);
                status = generic_onoff_client_set(&m_clients[0], &set_params, &transition_params);
                hal_led_pin_set(BSP_LED_0, set_params.on_off);
                break;
    
            case 2:
            case 3:
                /* Demonstrate un-acknowledged transaction, using 2nd client model instance */
                status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
                                                        &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
                hal_led_pin_set(BSP_LED_1, set_params.on_off);
                break;
          }
    

    when you press buttons 1 or 2 on the dev kit (corresponds to case 0 & 1 in button event handler), this will either send a set message to turn the light or lights on or off. The same is the case when buttons 3 & 4 on the dev kit.

    Buttons 1 & 3 turn the light(s) on, whereas pressing buttons 2 &4 turns the light(s) off. This can be seen in the switch case below:

        switch(button_number)
        {
            case 0:
            case 2:
                set_params.on_off = APP_STATE_ON;
                break;
    
            case 1:
            case 3:
                set_params.on_off = APP_STATE_OFF;
                break;
        }

    As you can see from the first code snippet, cases 0 & 1 demonstrate an acknowledged transaction, whereas cases 2 &3 demonstrate an un-acklowledged transaction. This means the server node(s) that receive the SET message will either respond (if message is acknowledged) or not respond (if un-ack).

    You should not need to make any changes in the code to send to a unicast address. Just follow the testing guidelines given in the Infocenter Documentation under "Provisioning With nRF Mesh".

    Could you please explain what you mean by "doing this programatically"? Do you want to use the regular light switch client & server examples? How do you want to provision the boards?

    Kind Regards,

    Bjørn

  • Hi Bjorn 

    thanks for your guide.i know using nrf mesh app we can set server unicast address to client publication address for send messege to specific server. 

    i mean that can we set server unicast address into programming for send messege to specific server? if i using regular light switch example and make provision using provisionor.

  • Sorry for the delayed response. This is already being done to a certain extent.

    In the provisioner example in mesh sdk v2.2.0, you should take a look at the node_setup.c file, especially the config_step_execute() function. This is where all of the client & server models are configured. You can see in the case NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER that the generic on/off server model subscription address is configured:

                address.type = NRF_MESH_ADDRESS_TYPE_GROUP;
                if (m_current_node_addr % 0x02)
                {
                    address.value  = GROUP_ADDRESS_ODD;
                }
                else
                {
                    address.value  = GROUP_ADDRESS_EVEN;
                }

    If the current node address is odd, then the GROUP_ADDRESS_ODD is configured for that node (similar for even node). In the cases NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT1 & NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT2, the two client models are configured.

    What you can do is this inside the two client cases:

    //            client_pub_state_set(&pubstate,
    //                                 m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT1,
    //                                 GROUP_ADDRESS_ODD);
                client_pub_state_set(&pubstate, m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT1,
                                     UNPROV_START_ADDRESS + CLIENT_NODE_ONOFF_CLIENT_MODEL_INSTANCES + ELEMENT_IDX_ONOFF_CLIENT1);

    //            client_pub_state_set(&pubstate,
    //                                 m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT2,
    //                                 GROUP_ADDRESS_EVEN);
                client_pub_state_set(&pubstate, m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT2,
                                     UNPROV_START_ADDRESS + CLIENT_NODE_ONOFF_CLIENT_MODEL_INSTANCES + ELEMENT_IDX_ONOFF_CLIENT2);

    Comment out the original client_pub_state_set() & replace it with the updated function arguments.

    Then, inside the client (I have used the regular client example, but it should work in the proxy client too) example, update the button_event_handler() function to this:

    static void button_event_handler(uint32_t button_number)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Button %u pressed\n", button_number);
    
        uint32_t status = NRF_SUCCESS;
        generic_onoff_set_params_t set_params;
        model_transition_t transition_params;
        static uint8_t tid = 0;
    
        /* Button 1: On, Button 2: Off, Client[0]
         * Button 2: On, Button 3: Off, Client[1]
         */
    
        switch(button_number)
        {
    //        case 0:
    //        case 2:
    //            set_params.on_off = APP_STATE_ON;
    //            break;
    //
    //        case 1:
    //        case 3:
    //            set_params.on_off = APP_STATE_OFF;
    //            break;
              case 0:
                  set_params.on_off = !hal_led_pin_get(BSP_LED_0 + button_number);
                  break;
              case 1:
                  set_params.on_off = !hal_led_pin_get(BSP_LED_0 + button_number);
                  break;
              case 2:
              case 3:
                  break;
        }
    
        set_params.tid = tid++;
        transition_params.delay_ms = APP_CONFIG_ONOFF_DELAY_MS;
        transition_params.transition_time_ms = APP_CONFIG_ONOFF_TRANSITION_TIME_MS;
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Sending msg: ONOFF SET %d\n", set_params.on_off);
    
        switch (button_number)
        {
            case 0:
            case 1:
                /* Demonstrate acknowledged transaction, using 1st client model instance */
                /* In this examples, users will not be blocked if the model is busy */
                (void)access_model_reliable_cancel(m_clients[button_number].model_handle);
                status = generic_onoff_client_set(&m_clients[button_number], &set_params, &transition_params);
                hal_led_pin_set(BSP_LED_0 + button_number, set_params.on_off);
                break;
    
            case 2:
            case 3:
    //            /* Demonstrate un-acknowledged transaction, using 2nd client model instance */
    //            status = generic_onoff_client_set_unack(&m_clients[1], &set_params,
    //                                                    &transition_params, APP_UNACK_MSG_REPEAT_COUNT);
    //            hal_led_pin_set(BSP_LED_1, set_params.on_off);
                break;
        }
    
        switch (status)
        {
            case NRF_SUCCESS:
                break;
    
            case NRF_ERROR_NO_MEM:
            case NRF_ERROR_BUSY:
            case NRF_ERROR_INVALID_STATE:
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Client %u cannot send\n", button_number);
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                break;
    
            case NRF_ERROR_INVALID_PARAM:
                /* Publication not enabled for this client. One (or more) of the following is wrong:
                 * - An application key is missing, or there is no application key bound to the model
                 * - The client does not have its publication state set
                 *
                 * It is the provisioner that adds an application key, binds it to the model and sets
                 * the model's publication state.
                 */
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Publication not configured for client %u\n", button_number);
                break;
    
            default:
                ERROR_CHECK(status);
                break;
        }
    }

    Instead of just blindly copying the code over to your example & watching it work, I would compare the button_event_handler() & the node_setup.c file between the mesh sdk v2.1.1 & v2.2.0 to see what the differences are & really try to understand why the code works. I would also recommend taking a look at the difference in the documentation (v2.1.1 & v2.2.0).

    Kind Regards,

    Bjørn

Related