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

Using Simple message model.

Hi,

I have certain doubts regarding simple message model

1. Why simple_message_client_init or simple_message_server_init is never used? Don't we need this function to bind model to the element?

2. I am sending a message from client to server. Can I receive it from simple_message_server.c and vice versa?

3. I could not understand how the model's functions can be used and how the communication takes place.

Parents
  • Hi,

    I would not refer to this simple message model, as it is using an outdated mesh sdk. I would rather take a look at the light switch example in the newest mesh sdk v2.1.1. Follow the testing guidelines there and run a debug session or have an rtt viewer open in each of the three boards (provisioner, client, server) & take a look at how the light switch example works. 

    Also, make sure to take a look at the configuration model in the provisioner (config_client.c & config_client.h), as well as config_server.c & config_server.h in the client example. I would also recommend taking a look at this documentation, as well as the simple OnOff Model documentation.

  • Hi Bjørn,

    I am working in mesh 2.0.1. I have added this simple message model into my light switch example. What I actually want is to send a string from client to server. That is done through simple message model. But it is not handling messages as it is in simple on off model. I have gone through light switch model as well as the documentation on adding new models. I think I should merge these two models (Light switch and simple message model). Or I should remove on off model and add a new model which can send a string and can handle messages. Would that be possible?

  • What about if you create a new model based off of the simple on off model instead? If you take a look at the light switch client example, you can see that when a user presses button 1 on the dev kit, the client sends a unicast message to the first provisioned server using the simple_on_off_client_set() function. This function first makes sure that the parameter pointer p_client & the status_cb pointer are not null. Then, a check is done to make sure the client is not in an invalid state. 

    It's this struct that is interesting for us:

    /** Simple OnOff Client state structure. */
    struct __simple_on_off_client
    {
        /** Model handle assigned to the client. */
        access_model_handle_t model_handle;
        /** Status callback called after status received from server. */
        simple_on_off_status_cb_t status_cb;
        /** Timeout callback called after acknowledged message sending times out */
        simple_on_off_timeout_cb_t timeout_cb;
        /** Internal client state. */
        struct
        {
            bool reliable_transfer_active; /**< Variable used to determine if a transfer is currently active. */
            simple_on_off_msg_set_t data;  /**< Variable reflecting the data stored in the server. */
        } state;
    };

    The simple_on_off_msg_set struct contains the on_off state (i.e. whether the server light should be on or off).

    The simple_on_off_client_set() function then calls send_reliable_message(), which will then send the data via the access_model_reliable_publish() call on the access layer of the mesh stack. 

    What if you try to create a new model based on the simple on off model & then update the simple_on_off_msg_set_t struct to send a string message instead of uint8_t on_off?

    I would also recommend making a copy of each of the three light switch examples (provisioner, client, server) & modify those. This way, if you were to make a mistake & the mesh network does not work anymore, you can refer back on the working light switch example. Hope that helps!

  • Hi Bjørn,

    Thank you for that suggestion. I have created a new model based on that. How can I init that new model? I tried adding the new model in 'models_init_cb()', along with simple on off model. I added a snippet given below.

    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n");
        uint32_t status = 0;
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].status_cb = client_status_cb;
            m_clients[i].timeout_cb = client_publish_timeout_cb;
            ERROR_CHECK(simple_on_off_client_init(&m_clients[i], i + 1));
            ERROR_CHECK(access_model_subscription_list_alloc(m_clients[i].model_handle));
        }
        for (uint32_t j = 0; j < CLIENT_MODEL_INSTANCE_COUNT; ++j)
        {
            r_clients[j].status_cb = new_client_status_cb;
            r_clients[j].timeout_cb = client_publish_timeout_cb;
            ERROR_CHECK(simple_model_client_init(&r_clients[j], j + 1));
            ERROR_CHECK(access_model_subscription_list_alloc(r_clients[i].model_handle));
        }
    
    }
    

    But it is returning error. when I removed the simple on off part, it is returning NRF_SUCCESS. Should I add it in a different function similar to 'models_init_cb'? If then how should I add the new model to the structure 'mesh_stack_init_params_t'?  Like this?

    static void mesh_init(void)
    {
        mesh_stack_init_params_t init_params =
        {
            .core.irq_priority       = NRF_MESH_IRQ_PRIORITY_LOWEST,
            .core.lfclksrc           = DEV_BOARD_LF_CLK_CFG,
            .core.p_uuid             = m_client_node_uuid,
            .models.models_init_cb   = models_init_cb,
            .models.models_init_cb   = models_init_cb2,
            .models.config_server_cb = config_server_evt_cb
        };
        ERROR_CHECK(mesh_stack_init(&init_params, &m_device_provisioned));
    }
    

    Where the 'models_init_cb2' is a function which initializes only the new client model? Is it like I can not add a new model apart from simple on off model with out removing it?

Reply
  • Hi Bjørn,

    Thank you for that suggestion. I have created a new model based on that. How can I init that new model? I tried adding the new model in 'models_init_cb()', along with simple on off model. I added a snippet given below.

    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n");
        uint32_t status = 0;
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].status_cb = client_status_cb;
            m_clients[i].timeout_cb = client_publish_timeout_cb;
            ERROR_CHECK(simple_on_off_client_init(&m_clients[i], i + 1));
            ERROR_CHECK(access_model_subscription_list_alloc(m_clients[i].model_handle));
        }
        for (uint32_t j = 0; j < CLIENT_MODEL_INSTANCE_COUNT; ++j)
        {
            r_clients[j].status_cb = new_client_status_cb;
            r_clients[j].timeout_cb = client_publish_timeout_cb;
            ERROR_CHECK(simple_model_client_init(&r_clients[j], j + 1));
            ERROR_CHECK(access_model_subscription_list_alloc(r_clients[i].model_handle));
        }
    
    }
    

    But it is returning error. when I removed the simple on off part, it is returning NRF_SUCCESS. Should I add it in a different function similar to 'models_init_cb'? If then how should I add the new model to the structure 'mesh_stack_init_params_t'?  Like this?

    static void mesh_init(void)
    {
        mesh_stack_init_params_t init_params =
        {
            .core.irq_priority       = NRF_MESH_IRQ_PRIORITY_LOWEST,
            .core.lfclksrc           = DEV_BOARD_LF_CLK_CFG,
            .core.p_uuid             = m_client_node_uuid,
            .models.models_init_cb   = models_init_cb,
            .models.models_init_cb   = models_init_cb2,
            .models.config_server_cb = config_server_evt_cb
        };
        ERROR_CHECK(mesh_stack_init(&init_params, &m_device_provisioned));
    }
    

    Where the 'models_init_cb2' is a function which initializes only the new client model? Is it like I can not add a new model apart from simple on off model with out removing it?

Children
  • Hi Bjørn,

    I tried this way.

    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models1\n");
        uint32_t status = 0;
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].status_cb = client_status_cb;
            m_clients[i].timeout_cb = client_publish_timeout_cb;
            r_clients[i].status_cb = new_client_status_cb;
            r_clients[i].timeout_cb = client_publish_timeout_cb;
            ERROR_CHECK(simple_on_off_client_init(&m_clients[i], i + 1));
            ERROR_CHECK(access_model_subscription_list_alloc(m_clients[i].model_handle));
            status = simple_model_client_init(&r_clients[i], i + 2);
            ERROR_CHECK(status);
            if(status == NRF_SUCCESS)
              {
                printf("NRF_SUCCESS\n");
              }
            ERROR_CHECK(access_model_subscription_list_alloc(r_clients[i].model_handle));
        }
    }

    But it is returning this error

    app_error_weak.c,  105, Mesh error 15 at 0x000267CD. Can you help me with this?

  • Hi Arya,

    Mesh error 15 refers to NRF_ERROR_FORBIDDEN (see nrf_error.h). Do you have any idea where this error is called? What you can do is open the .map file in the build folder of your mesh example & find the location of 0x000267CD. It might be between two values.

    Most likely it is an error when you initialize the simple_model_client_init(). If it is, then the error says that "Multiple model instances per element is not allowed" (see declaration of function in simple_on_off_client.h). What this means is that you are initializing the simple_on_off_model & the simple_message_model on the same element (i.e. element indexes 2,3,4).

    I will double check about this internally & get back to you.

    Are you trying to initialize the custom client or the custom server model? The custom model should be initialized similar to the simple_on_off_client model (i.e. via the simple_on_off_client_init() function), like you have done above.

    Do you want four client models (e.g. one for each button) on the client board? 

    Kind Regards,

    Bjørn

  • Hi Bjørn,

    Sorry for the delay in reply. Error is coming from the function given below.

    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models1\n");
        uint32_t status = 0;
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].status_cb = client_status_cb;
            m_clients[i].timeout_cb = client_publish_timeout_cb;
            r_clients[i].status_cb = client_RSSI_status_cb;
            r_clients[i].timeout_cb = client_publish_timeout_cb;
            status = simple_on_off_client_init(&m_clients[i], i + 1);
            ERROR_CHECK(status);
            if(status == NRF_SUCCESS)
              {
                printf("NRF_SUCCESS\n");
              }
    
            ERROR_CHECK(access_model_subscription_list_alloc(m_clients[i].model_handle));
            status = simple_RSSI_client_init(&r_clients[i], i + 2);
            ERROR_CHECK(status);
            if(status == NRF_SUCCESS)
              {
                printf("NRF_SUCCESS\n");
              }
            ERROR_CHECK(access_model_subscription_list_alloc(r_clients[i].model_handle));
        }
    }
    

    error is in the 13th line of function given above. It executes once i.e when i = 0 and when i becomes one it gives an error at that point.

    Output is:

    NRF_SUCCESS
    NRF_SUCCESS
    <t:       7696>, app_error_weak.c,  105, Mesh error 15 at 0x000267CD

    I could not find the address 0x000267CD in .map file.

    As you said  the error is "Multiple model instances per element is not allowed".

    I have both custom server model as well as custom client model. Now I am trying to add custom client model. I am initializing my custom model like simple_on_off_client model. I have a function similar to that named simple_RSSI_client_init().

    Sorry I could not understand this question.

    "Do you want four client models (e.g. one for each button) on the client board?"

    I don't have a clear idea about element index.I still have the above error. I changed some parameters in function element_has_model_id but no change.

  • Hi Bjørn,

    It got resolved. I need only one switch for this model so I updated my function as this:

    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models1\n");
        uint32_t status = 0;
    
        for (uint32_t i = 0; i < CLIENT_MODEL_INSTANCE_COUNT; ++i)
        {
            m_clients[i].status_cb = client_status_cb;
            m_clients[i].timeout_cb = client_publish_timeout_cb;
            status = simple_on_off_client_init(&m_clients[i], i + 1);
            ERROR_CHECK(status);
            if(status == NRF_SUCCESS)
              {
                printf("NRF_SUCCESS\n");
              }
    
            ERROR_CHECK(access_model_subscription_list_alloc(m_clients[i].model_handle));
        }
        
            r_clients.status_cb = client_RSSI_status_cb;
            r_clients.timeout_cb = client_publish_timeout_cb;
            
            status = simple_RSSI_client_init(&r_clients, 0);
            ERROR_CHECK(status);
            if(status == NRF_SUCCESS)
              {
                printf("NRF_SUCCESS\n");
              }
            ERROR_CHECK(access_model_subscription_list_alloc(r_clients.model_handle));
    }
    

    changed this function too RSSI_server_index_get().

    uint32_t index = p_client - &r_clients;

    Also increased ACCESS_MODEL_COUNT. Now there is no error. Is this the correct way to do it? Assuming that this is the correct way to do it, how should I modify if I had more than one switch for this model?

  • Hi Bjørn,

    Now I don't get all those errors. But I can not send a string message. I added one button to send message using app timer in each one second using the the same function of simple message model, except that I am using my own API now. But it is returning NRF_ERROR_INVALID_PARAM. I know that this is because publication address allocation problem. How can I set my address properly? Or is it because model is not bound to appkey? The function is as shown below. 

    void address_new_set(uint16_t addr)                   //setting address for sending message
    {
      ERROR_CHECK(dsm_address_publish_add(addr, &m_central_handle));
      ERROR_CHECK(access_model_publish_address_set(r_server.model_handle, m_central_handle));
    }
    
    void send_new_message(void)                         //function for sending a simple message
    {
        uint32_t status=0;
        uint8_t buffer[5] = "hello";
        uint8_t length;
        uint16_t address;
        access_message_tx_t msg;
        length = sizeof(buffer); 
        
        if(length)
        {
          address = 0xCAFE; 
          address_new_set(address);
          SEGGER_RTT_printf(0,"Sending to group address 0x%04x\n", address);
          status= simple_RSSI_client_set_unreliable(r_clients.model_handle, &buffer, GROUP_MSG_REPEAT_COUNT);
    
          if(status == NRF_ERROR_INVALID_STATE ||
          status == NRF_ERROR_BUSY||
          status == NRF_ERROR_NO_MEM)
          {
            __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Cannot send. Device is busy.\n");
            hal_led_blink_ms(LEDS_MASK, 50, 4);
          }
          else
          {
             ERROR_CHECK(status);
          }
        }
      
    }
    

    I took this function from simple message model and modified it.

Related