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

How to add multiple elements in a server node?

I am experimenting with the mesh light-switch example. I want to control two LEDs on a single node using the SimpleOnOff model. I know I should add a separate element and add the second SimpleOnOff model in it, but how do I do it? Is there any sample code which you can point me to?

  • I did this in the server application application. When I press button 2 on the server board, LED 2 gets lit up, but now how do I control it from button 2 of my client board?

    diff --git a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    index 9d70cc1..312ba5f 100644
    --- a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    +++ b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    @@ -82,7 +82,7 @@
      * @note This value has to be greater than two to fit the configuration and health models,
      * plus the number of models needed by the application.
      */
    -#define ACCESS_MODEL_COUNT (3)
    +#define ACCESS_MODEL_COUNT (4)
     
     /**
      * The number of elements in the application.
    @@ -90,7 +90,7 @@
      * @warning If the application is to support multiple _instances_ of the _same_ model, they cannot
      * belong in the same element and a separate element is needed for the new instance.
      */
    -#define ACCESS_ELEMENT_COUNT (1)
    +#define ACCESS_ELEMENT_COUNT (2)
     
     /**
      * The number of allocated subscription lists for the application.
    diff --git a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c 
    b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    index 1048083..dabafd7 100644
    --- a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    +++ b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    @@ -57,12 +57,17 @@
     #define RTT_INPUT_POLL_PERIOD_MS (100)
     #define LED_PIN_NUMBER           (BSP_LED_0)
     #define LED_PIN_MASK             (1u << LED_PIN_NUMBER)
    +#define LED_PIN_NUMBER_1           (BSP_LED_1)
    +#define LED_PIN_MASK_1             (1u << LED_PIN_NUMBER_1)
    +
     #define LED_BLINK_INTERVAL_MS    (200)
     #define LED_BLINK_CNT_START      (2)
     #define LED_BLINK_CNT_RESET      (3)
     #define LED_BLINK_CNT_PROV       (4)
     
     static simple_on_off_server_t m_server;
    +static simple_on_off_server_t m_server1;
    +
     static bool                   m_device_provisioned;
     
     static void provisioning_complete_cb(void)
    @@ -89,6 +94,21 @@ static bool on_off_server_set_cb(const simple_on_off_server_t * p_server, bool v
         return value;
     }
     
    +
    +static bool on_off_server_get_cb_1(const simple_on_off_server_t * p_server)
    +{
    +    return hal_led_pin_get(LED_PIN_NUMBER);
    +}
    +
    +static bool on_off_server_set_cb_1(const simple_on_off_server_t * p_server, bool value)
    +{
    +    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Got SET command to %u\n", value);
    +    hal_led_pin_set(LED_PIN_NUMBER, value);
    +    return value;
    +}
    +
    +
    +
     static void node_reset(void)
     {
         __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- Node reset  -----\n");
    @@ -122,6 +142,16 @@ static void button_event_handler(uint32_t button_number)
                 break;
             }
     
    +        case 1:
    +        {
    +            uint8_t value = !hal_led_pin_get(LED_PIN_NUMBER_1);
    +            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "User action \n");
    +            hal_led_pin_set(LED_PIN_NUMBER_1, value);
    +            (void)simple_on_off_server_status_publish(&m_server1, value);
    +            break;
    +        }
    +
    +
             /* Initiate node reset */
             case 3:
             {
    @@ -151,7 +181,10 @@ static void models_init_cb(void)
         m_server.get_cb = on_off_server_get_cb;
         m_server.set_cb = on_off_server_set_cb;
         ERROR_CHECK(simple_on_off_server_init(&m_server, 0));
    -    ERROR_CHECK(access_model_subscription_list_alloc(m_server.model_handle));
    +
    +    m_server1.get_cb = on_off_server_get_cb_1;
    +    m_server1.set_cb = on_off_server_set_cb_1;
    +    ERROR_CHECK(simple_on_off_server_init(&m_server1, 1));
     }
     
     static void mesh_init(void)
    

  • I have been studying the server, client and provisioner application since yesterday, I understand that I would need to do some changes in the provisioner application. Can someone from Nordic respond to this question??

  • Hi,

    Yes, you have to make some changes in the provisioner application. Seems like the code in the server application is correct, I suggest you to have a look at this post.

  • Finally I was able to get it working... Here are the changes!

    diff --git a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/provisioner/src/node_setup.c b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/provisioner/src/node_setup.c
    index d9a6576..7ed5c85 100644
    --- a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/provisioner/src/node_setup.c
    +++ b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/provisioner/src/node_setup.c
    @@ -144,6 +144,7 @@ static const config_steps_t server1_server2_config_steps[] =
         NODE_SETUP_CONFIG_APPKEY_ADD,
         NODE_SETUP_CONFIG_APPKEY_BIND_HEALTH,
         NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_SERVER,
    +    NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_SERVER,
         NODE_SETUP_CONFIG_PUBLICATION_HEALTH,
         NODE_SETUP_CONFIG_PUBLICATION_ONOFF_SERVER1_2,
         NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER,
    @@ -340,6 +341,7 @@ static void config_step_execute(void)
     {
         uint32_t status;
         static uint16_t model_element_addr = 0;
    +    static bool next_element = false;
     
         /* This example configures the provisioned nodes in the following way
          * Node 0: Client node (Switch)
    @@ -394,16 +396,34 @@ static void config_step_execute(void)
             /* Bind the On/Off server to the application key: */
             case NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_SERVER:
             {
    -            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "App key bind: Simple On/Off server\n");
    -            access_model_id_t model_id;
    -            model_id.company_id = ACCESS_COMPANY_ID_NORDIC;
    -            model_id.model_id = SIMPLE_ON_OFF_SERVER_MODEL_ID;
    -            uint16_t element_address = m_current_node_addr;
    -            retry_on_fail(config_client_model_app_bind(element_address, m_appkey_idx, model_id));
    -
    -            static const uint8_t exp_status[] = {ACCESS_STATUS_SUCCESS};
    -            expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, sizeof(exp_status), exp_status);
    -            break;
    +            if (!next_element)
    +            {
    +              __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Configure first element\n");
    +              access_model_id_t model_id;
    +              model_id.company_id = ACCESS_COMPANY_ID_NORDIC;
    +              model_id.model_id = SIMPLE_ON_OFF_SERVER_MODEL_ID;
    +              uint16_t element_address = m_current_node_addr;
    +              retry_on_fail(config_client_model_app_bind(element_address, m_appkey_idx, model_id));
    +
    +              static const uint8_t exp_status[] = {ACCESS_STATUS_SUCCESS};
    +              expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, sizeof(exp_status), exp_status);
    +              next_element = true;
    +              break;
    +            }
    +            else
    +            {
    +              __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Configure next element\n");
    +              access_model_id_t model_id;
    +              model_id.company_id = ACCESS_COMPANY_ID_NORDIC;
    +              model_id.model_id = SIMPLE_ON_OFF_SERVER_MODEL_ID;
    +              uint16_t element_address = m_current_node_addr + 1;
    +              retry_on_fail(config_client_model_app_bind(element_address, m_appkey_idx, model_id));
    +
    +              static const uint8_t exp_status[] = {ACCESS_STATUS_SUCCESS};
    +              expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, sizeof(exp_status), exp_status);
    +              next_element = false;
    +              break;
    +            }
             }
     
             /* Bind the On/Off client to the application key: */
    diff --git a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    index 9d70cc1..312ba5f 100644
    --- a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    +++ b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/include/nrf_mesh_config_app.h
    @@ -82,7 +82,7 @@
      * @note This value has to be greater than two to fit the configuration and health models,
      * plus the number of models needed by the application.
      */
    -#define ACCESS_MODEL_COUNT (3)
    +#define ACCESS_MODEL_COUNT (4)
     
     /**
      * The number of elements in the application.
    @@ -90,7 +90,7 @@
      * @warning If the application is to support multiple _instances_ of the _same_ model, they cannot
      * belong in the same element and a separate element is needed for the new instance.
      */
    -#define ACCESS_ELEMENT_COUNT (1)
    +#define ACCESS_ELEMENT_COUNT (2)
     
     /**
      * The number of allocated subscription lists for the application.
    diff --git a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    index 1048083..1367e26 100644
    --- a/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    +++ b/Tools/nrf5_SDK_for_Mesh_v2.0.1_src/examples/light_switch/server/src/main.c
    @@ -57,12 +57,17 @@
     #define RTT_INPUT_POLL_PERIOD_MS (100)
     #define LED_PIN_NUMBER           (BSP_LED_0)
     #define LED_PIN_MASK             (1u << LED_PIN_NUMBER)
    +#define LED_PIN_NUMBER_1           (BSP_LED_1)
    +#define LED_PIN_MASK_1             (1u << LED_PIN_NUMBER_1)
    +
     #define LED_BLINK_INTERVAL_MS    (200)
     #define LED_BLINK_CNT_START      (2)
     #define LED_BLINK_CNT_RESET      (3)
     #define LED_BLINK_CNT_PROV       (4)
     
     static simple_on_off_server_t m_server;
    +static simple_on_off_server_t m_server1;
    +
     static bool                   m_device_provisioned;
     
     static void provisioning_complete_cb(void)
    @@ -89,6 +94,21 @@ static bool on_off_server_set_cb(const simple_on_off_server_t * p_server, bool v
         return value;
     }
     
    +
    +static bool on_off_server_get_cb_1(const simple_on_off_server_t * p_server)
    +{
    +    return hal_led_pin_get(LED_PIN_NUMBER_1);
    +}
    +
    +static bool on_off_server_set_cb_1(const simple_on_off_server_t * p_server, bool value)
    +{
    +    __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Got SET command to %u\n", value);
    +    hal_led_pin_set(LED_PIN_NUMBER_1, value);
    +    return value;
    +}
    +
    +
    +
     static void node_reset(void)
     {
         __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- Node reset  -----\n");
    @@ -122,6 +142,16 @@ static void button_event_handler(uint32_t button_number)
                 break;
             }
     
    +        case 1:
    +        {
    +            uint8_t value = !hal_led_pin_get(LED_PIN_NUMBER_1);
    +            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "User action \n");
    +            hal_led_pin_set(LED_PIN_NUMBER_1, value);
    +            (void)simple_on_off_server_status_publish(&m_server1, value);
    +            break;
    +        }
    +
    +
             /* Initiate node reset */
             case 3:
             {
    @@ -151,7 +181,10 @@ static void models_init_cb(void)
         m_server.get_cb = on_off_server_get_cb;
         m_server.set_cb = on_off_server_set_cb;
         ERROR_CHECK(simple_on_off_server_init(&m_server, 0));
    -    ERROR_CHECK(access_model_subscription_list_alloc(m_server.model_handle));
    +
    +    m_server1.get_cb = on_off_server_get_cb_1;
    +    m_server1.set_cb = on_off_server_set_cb_1;
    +    ERROR_CHECK(simple_on_off_server_init(&m_server1, 1));
     }
     
     static void mesh_init(void)
    

    Note that these changes are just to demonstrate the regions of code that you need to change for adding multiple elements. I just checked this with only 1 server board. The light switch client application already has multiple nodes in it(for 4 switches), I found it very helpful.

Related