Vendor model server message receiving problem

 https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.meshsdk.v1.0.1%2Fmd_doc_getting_started_how_to_models.html

 Linkte verilen yönergeleri takip ederek satıcı modeli oluşturdum.Mesajlar için sunucu tarafında alınan, handle_set_cb iki kez çağrılır ve iki mesaj alınmış gibi görünüyor. Paketlere numara atadığımda, istemciden gönderilen bir mesaj sunucuda iki kez görüntüleniyor. Nedeni ne olabilir? Neyi kaçırıyorum?

  • Hi.

    The link you sent me is actually from the nRF5 SDK for Mesh v.1.0.1. Is this the SDK you are working with?

    I haven't looked closely at the doc. but it could be outdated information and api's if you are using a newer version of the nRF Mesh SDK.

    ___

    If you could add information about what SDK version you are using?

    Can you upload the server.c file that you are using in your project?

    Br,
    Joakim

  • Hi.

    I am using nrf52 sdk 17.0.2 ve mesh_v5.0.0 . I added the server's header and c files.

    Thanks.

    simple_on_off_server.c

    #include "simple_on_off_server.h"
    #include "simple_on_off_common.h"
    
    #include <stdint.h>
    #include <stddef.h>
    
    #include "access.h"
    #include "nrf_mesh_assert.h"
    #include "log.h"
    
    /*****************************************************************************
     * Static functions
     *****************************************************************************/
    
     void reply_status(const simple_on_off_server_t * p_server,
                             const access_message_rx_t * p_message,
                             bool present_on_off)
    {
        simple_on_off_msg_status_t status;
        status.present_on_off = present_on_off ? 1 : 0;
        access_message_tx_t reply;
        reply.opcode.opcode = SIMPLE_ON_OFF_OPCODE_STATUS;
        reply.opcode.company_id = ACCESS_COMPANY_ID_NORDIC;
        reply.p_buffer = (const uint8_t *) &status;
        reply.length = sizeof(status);
        reply.force_segmented = false;
        reply.transmic_size = NRF_MESH_TRANSMIC_SIZE_DEFAULT;
        reply.access_token = nrf_mesh_unique_token_get();
    
        (void) access_model_reply(p_server->model_handle, p_message, &reply);
    }
    
    /*****************************************************************************
     * Opcode handler callbacks
     *****************************************************************************/
    
     void handle_set_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
        simple_on_off_server_t * p_server = p_args;
      //  NRF_MESH_ASSERT(p_server->set_cb != NULL);
    
        bool value = (((simple_on_off_msg_set_t*) p_message->p_data)->on_off) > 0;
       // value = p_server->set_cb(p_server, value);
        reply_status(p_server, p_message, value);
        (void) simple_on_off_server_status_publish(p_server, value); /* We don't care about status */
         __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "handle_set_cb %d, %d ,%d \n", ((simple_on_off_msg_set_t *)p_message->p_data)->on_off, ((simple_on_off_msg_set_t *)p_message->p_data)->tid, ((simple_on_off_msg_set_t *)p_message->p_data)->deneme);
    
    }
    
     void handle_get_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
        simple_on_off_server_t * p_server = p_args;
        NRF_MESH_ASSERT(p_server->get_cb != NULL);
        reply_status(p_server, p_message, p_server->get_cb(p_server));
    }
    
     void handle_set_unreliable_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
        simple_on_off_server_t * p_server = p_args;
        NRF_MESH_ASSERT(p_server->set_cb != NULL);
        bool value = (((simple_on_off_msg_set_unreliable_t*) p_message->p_data)->on_off) > 0;
        value = p_server->set_cb(p_server, value);
        (void) simple_on_off_server_status_publish(p_server, value);
    }
    
     const access_opcode_handler_t m_opcode_handlers[] =
    {
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_SET,            ACCESS_COMPANY_ID_NORDIC), handle_set_cb},
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_GET,            ACCESS_COMPANY_ID_NORDIC), handle_get_cb},
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_SET_UNRELIABLE, ACCESS_COMPANY_ID_NORDIC), handle_set_unreliable_cb}
    };
    
     void handle_publish_timeout(access_model_handle_t handle, void * p_args)
    {
        simple_on_off_server_t * p_server = p_args;
    
        (void) simple_on_off_server_status_publish(p_server, p_server->get_cb(p_server));
    }
    
    /*****************************************************************************
     * Public API
     *****************************************************************************/
    
    uint32_t simple_on_off_server_init(simple_on_off_server_t * p_server, uint16_t element_index)
    {
        if (p_server == NULL ||
            p_server->get_cb == NULL ||
            p_server->set_cb == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        access_model_add_params_t init_params;
        init_params.element_index =  element_index;
        init_params.model_id.model_id = SIMPLE_ON_OFF_SERVER_MODEL_ID;
        init_params.model_id.company_id = ACCESS_COMPANY_ID_NORDIC;
        init_params.p_opcode_handlers = &m_opcode_handlers[0];
        init_params.opcode_count = sizeof(m_opcode_handlers) / sizeof(m_opcode_handlers[0]);
        init_params.p_args = p_server;
        init_params.publish_timeout_cb = handle_publish_timeout;
        return access_model_add(&init_params, &p_server->model_handle);
    }
    
    uint32_t simple_on_off_server_status_publish(simple_on_off_server_t * p_server, bool value)
    {
        simple_on_off_msg_status_t status;
        status.present_on_off = value ? 1 : 0;
        access_message_tx_t msg;
        msg.opcode.opcode = SIMPLE_ON_OFF_OPCODE_STATUS;
        msg.opcode.company_id = ACCESS_COMPANY_ID_NORDIC;///***************************
        msg.p_buffer = (const uint8_t *) &status;
        msg.length = sizeof(status);
        msg.force_segmented = false;
        msg.transmic_size = NRF_MESH_TRANSMIC_SIZE_DEFAULT;
        msg.access_token = nrf_mesh_unique_token_get();
        return access_model_publish(p_server->model_handle, &msg);
    }
    

    simple_on_off_server.h

    #ifndef SIMPLE_ON_OFF_SERVER_H__
    #define SIMPLE_ON_OFF_SERVER_H__
    
    #include "access.h"
    #include <stdbool.h>
    #include <stdint.h>
    
    /**
     * @defgroup SIMPLE_ON_OFF_SERVER Simple OnOff Server
     * @ingroup SIMPLE_ON_OFF_MODEL
     * This module implements a vendor specific Simple OnOff Server.
     * @{
     */
    
    /** Simple OnOff Server model ID. */
    #define SIMPLE_ON_OFF_SERVER_MODEL_ID (0x1000)
    
    /** Forward declaration. */
    typedef struct __simple_on_off_server simple_on_off_server_t;
    
    /**
     * Get callback type.
     * @param[in] p_self Pointer to the Simple OnOff Server context structure.
     * @returns @c true if the state is On, @c false otherwise.
     */
    typedef bool (*simple_on_off_get_cb_t)(const simple_on_off_server_t *p_self);
    
    /**
     * Set callback type.
     * @param[in] p_self Pointer to the Simple OnOff Server context structure.
     * @param[in] on_off Desired state
     * @returns @c true if the current state is On, @c false otherwise.
     */
    typedef bool (*simple_on_off_set_cb_t)(const simple_on_off_server_t *p_self, bool on);
    
    /** Simple OnOff Server state structure. */
    struct __simple_on_off_server {
      /** Model handle assigned to the server. */
      access_model_handle_t model_handle;
      /** Get callback. */
      simple_on_off_get_cb_t get_cb;
      /** Set callback. */
      simple_on_off_set_cb_t set_cb;
    };
    
    /**
     * Initializes the Simple OnOff server.
     *
     * @note This function should only be called _once_.
     * @note The server handles the model allocation and adding.
     *
     * @param[in] p_server      Simple OnOff Server structure pointer.
     * @param[in] element_index Element index to add the server model.
     *
     * @retval NRF_SUCCESS         Successfully added server.
     * @retval NRF_ERROR_NULL      NULL pointer supplied to function.
     * @retval NRF_ERROR_NO_MEM    No more memory available to allocate model.
     * @retval NRF_ERROR_FORBIDDEN Multiple model instances per element is not allowed.
     * @retval NRF_ERROR_NOT_FOUND Invalid element index.
     */
    uint32_t simple_on_off_server_init(simple_on_off_server_t *p_server, uint16_t element_index);
    
    /**
     * Publishes unsolicited status message.
     *
     * This API can be used to send unsolicited status messages to report updated state value as a result
     * of local action.
     *
     * @param[in]  p_server         Simple OnOff Server structure pointer
     * @param[in]  value            Current on/off value to be published
     *
     * @retval NRF_SUCCESS              Successfully queued packet for transmission.
     * @retval NRF_ERROR_NULL           NULL pointer supplied to function.
     * @retval NRF_ERROR_NO_MEM         Not enough memory available for message.
     * @retval NRF_ERROR_NOT_FOUND      Invalid model handle or model not bound to element.
     * @retval NRF_ERROR_INVALID_ADDR   The element index is greater than the number of local unicast
     *                                  addresses stored by the @ref DEVICE_STATE_MANAGER.
     * @retval NRF_ERROR_INVALID_PARAM  Model not bound to appkey, publish address not set or wrong
     *                                  opcode format.
     * @retval NRF_ERROR_INVALID_LENGTH Attempted to send message larger than @ref ACCESS_MESSAGE_LENGTH_MAX.
     *
     */
    uint32_t simple_on_off_server_status_publish(simple_on_off_server_t *p_server, bool value);
    
    /** @} end of SIMPLE_ON_OFF_SERVER */
    
    void handle_set_cb(access_model_handle_t handle, const access_message_rx_t *p_message, void *p_args);
    void handle_get_cb(access_model_handle_t handle, const access_message_rx_t *p_message, void *p_args);
    void handle_set_unreliable_cb(access_model_handle_t handle, const access_message_rx_t *p_message, void *p_args);
    void handle_publish_timeout(access_model_handle_t handle, void *p_args);
    void reply_status(const simple_on_off_server_t *p_server,
        const access_message_rx_t *p_message,
        bool present_on_off);
    #endif /* SIMPLE_ON_OFF_SERVER_H__ */

  • Thanks.

    Could you also upload the server.c file?

    Specifically to take a look at the set_unreliable function.

    Best regards,
    Joakim

  • I set up a vendor server on the light switch client instance. Therefore, I am using simple_on_off_server.c as the server.c file. Here is the function you are talking about:

     void handle_set_unreliable_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
        simple_on_off_server_t * p_server = p_args;
        NRF_MESH_ASSERT(p_server->set_cb != NULL);
        bool value = (((simple_on_off_msg_set_unreliable_t*) p_message->p_data)->on_off) > 0;
        value = p_server->set_cb(p_server, value);
        (void) simple_on_off_server_status_publish(p_server, value);
    }

Related