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

How to configure a node for control model?

How to configure a node for control model. I have used light switch on/off template to implement a control mode but i i don't know how to make a control logic for client. Have to use only client at a time but if i run the code i'm getting error and it run both client and sever at same time. I have merge the client and server program for control model but i'm getting a error as NRF_INVALID_STATE which is in nrf_mesh_init function.Please help me and thanks in advance.

Parents
  • Which mesh sdk version are you currently using? Have you taken a look at the creating new models documentation? This documentation might also be helpful. What error are you currently receiving? As far as I know, we have not implemented a control model yet, but I have asked about this internally & will get back to you soon. 

  • Thanks for your reply. I'm using mesh sdk 2.1.1. For control model i used light switch control example by merge client and server main.c i'm getting error as NRF_INVALID_STATE. I have problem to initialize mesh stack & softdevice for both client and server same time. only for first time i can use mesh stack and softdevice if use the same for server i get this error.

    I have added the log which i get error:

    <t: 0>, mesh_softdevice_init.c, 117, Initializing SoftDevice...
    <t: 0>, mesh_softdevice_init.c, 75, Enabling BLE...
    <t: 16>, mesh_softdevice_init.c, 109, sd_ble_enable: app_ram_base should be adjusted to 0x20002DA0
    <t: 58413>, main.c, 303, Initializing and adding models
    <t: 63311>, main.c, 366, Device UUID : 0059ABCDEFABCDEFACCDEFABCDEFABCD
    <t: 63318>, main.c, 443, ----- BLE Mesh Light Switch Server Demo -----
    <t: 63325>, app_error_weak.c, 105, Mesh error 8 at 0x00000000 (:0)

  • I have resolved the problem while combining light switch control with server and client but now i have problem while provisioning the devices.


    <t: 158537>, main.c, 362, Waiting for Client node to be provisioned ...
    <t: 163291>, provisioner_helper.c, 282, Scanning For Unprovisioned Devices
    <t: 206105>, provisioner_helper.c, 144, UUID seen: 0059FFFF00000000975B2B98BE9A8FF2
    <t: 219947>, provisioner_helper.c, 144, UUID seen: 0059ABCDEFABCDEFACCDEFABCDEFABCD
    <t: 219950>, provisioner_helper.c, 95, UUID filter matched
    <t: 220510>, provisioner_helper.c, 259, Provisioning link established
    <t: 233829>, provisioner_helper.c, 254, Static authentication data provided
    <t: 245727>, provisioner_helper.c, 192, Provisioning completed received
    <t: 245729>, provisioner_helper.c, 197, Adding device address, and device keys
    <t: 245734>, provisioner_helper.c, 214, Addr: 0x0100 addr_handle: 0 netkey_handle: 0 devkey_handle: 2
    <t: 248926>, provisioner_helper.c, 155, Local provisioning link closed: prov_state: 2 remaining retries: 2
    <t: 248930>, main.c, 283, Provisioning successful
    <t: 248932>, provisioner_helper.c, 181, Provisioning complete. Node addr: 0x0100 elements: 5
    <t: 248936>, node_setup.c, 673, Configuring Node: 0x0100
    <t: 248939>, node_setup.c, 587, Config client setup: devkey_handle:2 addr_handle:0
    <t: 248942>, node_setup.c, 361, Getting composition data
    <t: 248984>, main.c, 118, Flash write complete
    <t: 251601>, main.c, 333, Config client event
    <t: 251603>, node_setup.c, 371, Adding appkey
    <t: 254563>, main.c, 333, Config client event
    <t: 254565>, node_setup.c, 272, opcode status field: 0
    <t: 254567>, node_setup.c, 382, App key bind: Health server
    <t: 255377>, main.c, 333, Config client event
    <t: 255379>, node_setup.c, 272, opcode status field: 0
    <t: 255381>, node_setup.c, 450, Setting publication address for the health server to 0x0001
    <t: 258290>, main.c, 333, Config client event
    <t: 258292>, node_setup.c, 272, opcode status field: 0
    <t: 258295>, node_setup.c, 416, App key bind: Simple On/Off client on element 0x0101
    <t: 259935>, main.c, 333, Config client event
    <t: 259937>, node_setup.c, 272, opcode status field: 2
    <t: 259940>, main.c, 276, Configuration of device 0 failed. Press Button 1 to retry.

  • It seems to me as if the provisioner is able to successfully provision the client node, but has trouble configuring the client node. The health server seems to be added correctly, but the problem is most likely in the newly added control model. Did you update the simple on off client model & simple on off server models to be control models instead of only client/server models? 

    You mentioned that you merged the main.c files of the server & the client example in the light switch example. What is the reasoning behind this choice? Didn't you want to just update the simple on off server & client models to be control models instead? Or do you want to add a new control model with different functionality?

    Could you show me the code for the new control model you created?

  • /* Simple on/off model*/
    
    #include "simple_on_off_client.h"
    #include "simple_on_off_server.h"
    #include "simple_on_off_common.h"
    
    #include <stdint.h>
    #include <stddef.h>
    
    #include "access.h"
    #include "access_config.h"
    #include "access_reliable.h"
    #include "device_state_manager.h"
    #include "nrf_mesh.h"
    #include "nrf_mesh_assert.h"
    #include "log.h"
    
    /*****************************************************************************
     * Static variables
     *****************************************************************************/
    
    /** Keeps a single global TID for all transfers. */
    static uint8_t m_tid;
    
    /*****************************************************************************
     * Static functions
     *****************************************************************************/
    
    static void reliable_status_cb(access_model_handle_t model_handle,
                                   void * p_args,
                                   access_reliable_status_t status)
    {
        simple_on_off_client_t * p_client = p_args;
        NRF_MESH_ASSERT(p_client->status_cb != NULL);
    
        p_client->state.reliable_transfer_active = false;
        switch (status)
        {
            case ACCESS_RELIABLE_TRANSFER_SUCCESS:
                /* Ignore */
                break;
            case ACCESS_RELIABLE_TRANSFER_TIMEOUT:
                p_client->status_cb(p_client, SIMPLE_ON_OFF_STATUS_ERROR_NO_REPLY, NRF_MESH_ADDR_UNASSIGNED);
                break;
            case ACCESS_RELIABLE_TRANSFER_CANCELLED:
                p_client->status_cb(p_client, SIMPLE_ON_OFF_STATUS_CANCELLED, NRF_MESH_ADDR_UNASSIGNED);
                break;
            default:
                /* Should not be possible. */
                NRF_MESH_ASSERT(false);
                break;
        }
    }
    
    /** Returns @c true if the message received was from the address corresponding to the clients
     * publish address. */
    static bool is_valid_source(const simple_on_off_client_t * p_client,
                                const access_message_rx_t * p_message)
    {
        /* Check the originator of the status. */
        dsm_handle_t publish_handle;
        nrf_mesh_address_t publish_address;
        if (access_model_publish_address_get(p_client->model_handle, &publish_handle) != NRF_SUCCESS ||
            publish_handle == DSM_HANDLE_INVALID ||
            dsm_address_get(publish_handle, &publish_address) != NRF_SUCCESS ||
            publish_address.value != p_message->meta_data.src.value)
        {
            return false;
        }
        else
        {
            return true;
        }
    }
    
    static uint32_t send_reliable_message(const simple_on_off_client_t * p_client,
                                          simple_on_off_opcode_t opcode,
                                          const uint8_t * p_data,
                                          uint16_t length)
    {
        access_reliable_t reliable;
        reliable.model_handle = p_client->model_handle;
        reliable.message.p_buffer = p_data;
        reliable.message.length = length;
        reliable.message.opcode.opcode = opcode;
        reliable.message.opcode.company_id = SIMPLE_ON_OFF_COMPANY_ID;
        reliable.message.force_segmented = false;
        reliable.message.transmic_size = NRF_MESH_TRANSMIC_SIZE_DEFAULT;
        reliable.message.access_token = nrf_mesh_unique_token_get();
        reliable.reply_opcode.opcode = SIMPLE_ON_OFF_OPCODE_STATUS;
        reliable.reply_opcode.company_id = SIMPLE_ON_OFF_COMPANY_ID;
        reliable.timeout = ACCESS_RELIABLE_TIMEOUT_MIN;
        reliable.status_cb = reliable_status_cb;
    
        return access_model_reliable_publish(&reliable);
    }
    
    /*****************************************************************************
     * Static functions
     *****************************************************************************/
    
    static 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 = SIMPLE_ON_OFF_COMPANY_ID;
        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 callback(s)
     *****************************************************************************/
    
    static void handle_status_cb(access_model_handle_t handle, const access_message_rx_t * p_message, void * p_args)
    {
        simple_on_off_client_t * p_client = p_args;
        NRF_MESH_ASSERT(p_client->status_cb != NULL);
    
        if (!is_valid_source(p_client, p_message))
        {
            return;
        }
    
        simple_on_off_msg_status_t * p_status =
            (simple_on_off_msg_status_t *) p_message->p_data;
        simple_on_off_status_t on_off_status = (p_status->present_on_off ?
                                                  SIMPLE_ON_OFF_STATUS_ON : SIMPLE_ON_OFF_STATUS_OFF);
        p_client->status_cb(p_client, on_off_status, p_message->meta_data.src.value);
    }
    
    //static const access_opcode_handler_t m_opcode_handlers[] =
    //{
      //  {{SIMPLE_ON_OFF_OPCODE_STATUS, SIMPLE_ON_OFF_COMPANY_ID}, handle_status_cb}
    //};
     
    static void handle_publish_timeout(access_model_handle_t handle, void * p_args)
    {
        simple_on_off_client_t * p_client = p_args;
    
        if (p_client->timeout_cb != NULL)
        {
            p_client->timeout_cb(handle, p_args);
        }
    }
    
    /*****************************************************************************
     * Opcode handler callbacks
     *****************************************************************************/
    
    static 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 */
    }
    
    static 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));
    }
    
    static 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);
    }
    
    static const access_opcode_handler_t m_opcode_handlers[] =
    {
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_SET,            SIMPLE_ON_OFF_COMPANY_ID), handle_set_cb},
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_GET,            SIMPLE_ON_OFF_COMPANY_ID), handle_get_cb},
        {ACCESS_OPCODE_VENDOR(SIMPLE_ON_OFF_OPCODE_SET_UNRELIABLE, SIMPLE_ON_OFF_COMPANY_ID), handle_set_unreliable_cb},
        {{SIMPLE_ON_OFF_OPCODE_STATUS, SIMPLE_ON_OFF_COMPANY_ID}, handle_status_cb}
    };
    
    /*****************************************************************************
     * Public API
     *****************************************************************************/
    
    uint32_t simple_on_off_client_init(simple_on_off_client_t * p_client, uint16_t element_index)
    {
        if (p_client == NULL ||
            p_client->status_cb == NULL)
        {
            return NRF_ERROR_NULL;
        }
    
        access_model_add_params_t init_params;
        init_params.model_id.model_id = SIMPLE_ON_OFF_CLIENT_MODEL_ID;
        init_params.model_id.company_id = SIMPLE_ON_OFF_COMPANY_ID;
        init_params.element_index = element_index;
        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_client;
        init_params.publish_timeout_cb = handle_publish_timeout;
        return access_model_add(&init_params, &p_client->model_handle);
    }
    
    uint32_t simple_on_off_client_set(simple_on_off_client_t * p_client, bool on_off)
    {
        if (p_client == NULL || p_client->status_cb == NULL)
        {
            return NRF_ERROR_NULL;
        }
        else if (p_client->state.reliable_transfer_active)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        p_client->state.data.on_off = on_off ? 1 : 0;
        p_client->state.data.tid = m_tid++;
    
        uint32_t status = send_reliable_message(p_client,
                                                SIMPLE_ON_OFF_OPCODE_SET,
                                                (const uint8_t *)&p_client->state.data,
                                                sizeof(simple_on_off_msg_set_t));
        if (status == NRF_SUCCESS)
        {
            p_client->state.reliable_transfer_active = true;
        }
        return status;
    
    }
    
    uint32_t simple_on_off_client_set_unreliable(simple_on_off_client_t * p_client, bool on_off, uint8_t repeats)
    {
        simple_on_off_msg_set_unreliable_t set_unreliable;
        set_unreliable.on_off = on_off ? 1 : 0;
        set_unreliable.tid = m_tid++;
    
        access_message_tx_t message;
        message.opcode.opcode = SIMPLE_ON_OFF_OPCODE_SET_UNRELIABLE;
        message.opcode.company_id = SIMPLE_ON_OFF_COMPANY_ID;
        message.p_buffer = (const uint8_t*) &set_unreliable;
        message.length = sizeof(set_unreliable);
        message.force_segmented = false;
        message.transmic_size = NRF_MESH_TRANSMIC_SIZE_DEFAULT;
    
        uint32_t status = NRF_SUCCESS;
        for (uint8_t i = 0; i < repeats; ++i)
        {
            message.access_token = nrf_mesh_unique_token_get();
            status = access_model_publish(p_client->model_handle, &message);
            if (status != NRF_SUCCESS)
            {
                break;
            }
        }
        return status;
    }
    
    uint32_t simple_on_off_client_get(simple_on_off_client_t * p_client)
    {
        if (p_client == NULL || p_client->status_cb == NULL)
        {
            return NRF_ERROR_NULL;
        }
        else if (p_client->state.reliable_transfer_active)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        uint32_t status = send_reliable_message(p_client,
                                                SIMPLE_ON_OFF_OPCODE_GET,
                                                NULL,
                                                0);
        if (status == NRF_SUCCESS)
        {
            p_client->state.reliable_transfer_active = true;
        }
        return status;
    }
    
    /**
     * Cancel any ongoing reliable message transfer.
     *
     * @param[in] p_client Pointer to the client instance structure.
     */
    void simple_on_off_client_pending_msg_cancel(simple_on_off_client_t * p_client)
    {
        (void)access_model_reliable_cancel(p_client->model_handle);
    }
    
    /*****************************************************************************
     * 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 = SIMPLE_ON_OFF_COMPANY_ID;
        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 = NULL;
        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 = SIMPLE_ON_OFF_COMPANY_ID;
        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);
    }
    

    #include <stdint.h>
    #include <string.h>
    
    #include "boards.h"
    #include "simple_hal.h"
    #include "log.h"
    #include "access_config.h"
    #include "simple_on_off_client.h"
    #include "simple_on_off_server.h"
    #include "rtt_input.h"
    #include "device_state_manager.h"
    #include "light_switch_example_common.h"
    #include "mesh_app_utils.h"
    #include "net_state.h"
    #include "mesh_stack.h"
    #include "mesh_softdevice_init.h"
    #include "mesh_provisionee.h"
    #include "nrf_mesh_config_examples.h"
    #include "nrf_mesh_configure.h"
    #include "app_timer.h"
    #include "nrf_mesh_events.h"
    #include "nrf_nvic.h"
    #include "nrf_delay.h"
    
    /* client */
    #define RTT_INPUT_POLL_PERIOD_MS (100)
    #define GROUP_MSG_REPEAT_COUNT   (2)
    
    #define LED_BLINK_INTERVAL_MS       (200)
    #define LED_BLINK_SHORT_INTERVAL_MS (50)
    #define LED_BLINK_CNT_START         (2)
    #define LED_BLINK_CNT_RESET         (3)
    #define LED_BLINK_CNT_PROV          (4)
    #define LED_BLINK_CNT_NO_REPLY      (6)
    
    /* Server */
    //#define RTT_INPUT_POLL_PERIOD_MS (100)
    #define LED_PIN_NUMBER           (BSP_LED_0)
    #define LED_PIN_MASK             (1u << LED_PIN_NUMBER)
    #define LED_BLINK_INTERVAL_MS    (200)
    //#define LED_BLINK_CNT_START      (2)
    //#define LED_BLINK_CNT_RESET      (3)
    //#define LED_BLINK_CNT_PROV       (4)
    
    /* client */
    static simple_on_off_client_t m_clients[CLIENT_MODEL_INSTANCE_COUNT];
    //static const uint8_t          m_client_node_uuid[NRF_MESH_UUID_SIZE] = CLIENT_NODE_UUID;
    static bool                   m_device_provisioned;
    
    /* Server */
    static simple_on_off_server_t m_server;
    
    //static bool                   m_device_provisioned;
    
    static const uint8_t          m_c_s_node_uuid[NRF_MESH_UUID_SIZE] = CS_NODE_UUID;
    
    /* common */
    static void provisioning_complete_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Successfully provisioned\n");
    
        dsm_local_unicast_address_t node_address;
        dsm_local_unicast_addresses_get(&node_address);
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Node Address: 0x%04x \n", node_address.address_start);
    
        hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF);
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_PROV);
    }
    
    /* client */
    static uint32_t server_index_get(const simple_on_off_client_t * p_client)
    {
        uint32_t index = p_client - &m_clients[0];
        NRF_MESH_ASSERT(index < SERVER_NODE_COUNT);
        return index;
    }
    
    /* Server */
    static bool on_off_server_get_cb(const simple_on_off_server_t * p_server)
    {
        return hal_led_pin_get(LED_PIN_NUMBER);
    }
    
    /* Server */
    static bool on_off_server_set_cb(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;
    }
    
    /* client */
    static void client_publish_timeout_cb(access_model_handle_t handle, void * p_self)
    {
         __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Acknowledged send timedout\n");
    }
    
    /* client */
    static void client_status_cb(const simple_on_off_client_t * p_self, simple_on_off_status_t status, uint16_t src)
    {
        uint32_t server_index = server_index_get(p_self);
    
        switch (status)
        {
            case SIMPLE_ON_OFF_STATUS_ON:
                 
                  hal_led_pin_set(BSP_LED_0 + server_index, true); 
                       
              __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "OnOff server %u status ON\n", server_index);
                break;
    
            case SIMPLE_ON_OFF_STATUS_OFF:
                hal_led_pin_set(BSP_LED_0 + server_index, false);
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "OnOff server %u status OFF\n", server_index);
                break;
    
            case SIMPLE_ON_OFF_STATUS_ERROR_NO_REPLY:
                hal_led_blink_ms(LEDS_MASK, LED_BLINK_SHORT_INTERVAL_MS, LED_BLINK_CNT_NO_REPLY);
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "No reply from OnOff server %u\n", server_index);
                break;
    
            case SIMPLE_ON_OFF_STATUS_CANCELLED:
                __LOG(LOG_SRC_APP, LOG_LEVEL_WARN, "Message to server %u cancelled\n", server_index);
                break;
            default:
                __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Unknown status \n");
                break;
        }
    }
    
    /* common */
    static void node_reset(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- Node reset  -----\n");
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_RESET);
        /* This function may return if there are ongoing flash operations. */
        mesh_stack_device_reset();
    }
    
    /* common */
    static void config_server_evt_cb(const config_server_evt_t * p_evt)
    {
        if (p_evt->type == CONFIG_SERVER_EVT_NODE_RESET)
        {
            node_reset();
        }
    }
    
    /* client */
    
    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;
        switch (button_number)
        {
            case 0:
            case 1:
                /* send unicast message, with inverted GPIO pin value */
                status = simple_on_off_client_set(&m_clients[button_number],
                                                  !hal_led_pin_get(BSP_LED_0 + button_number));
    											  							  
                break;
    
            case 2:
            case 3:
                /* send a group message to the ODD group, with inverted GPIO pin value */
                status = simple_on_off_client_set_unreliable(&m_clients[button_number],
                                                             !hal_led_pin_get(BSP_LED_0 + button_number),
                                                             GROUP_MSG_REPEAT_COUNT);
                if (status == NRF_SUCCESS)
                {
                    hal_led_pin_set(BSP_LED_0 + button_number, !hal_led_pin_get(BSP_LED_0 + button_number));
                }
                break;
            default:
                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, "Cannot send - client %u is busy\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;
        }
    }
    
    /* server */
    static void button_ser_event_handler(uint32_t button_number)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Button %u pressed\n", button_number);
        switch (button_number)
        {
            /* Pressing SW1 on the Development Kit will result in LED state to toggle and trigger
            the STATUS message to inform client about the state change. This is a demonstration of
            state change publication due to local event. */
            case 0:
            {
                uint8_t value = !hal_led_pin_get(LED_PIN_NUMBER);
                __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "User action \n");
                hal_led_pin_set(LED_PIN_NUMBER, value);
                (void)simple_on_off_server_status_publish(&m_server, value);
                break;
            }
    
            /* Initiate node reset */
            case 3:
            {
                /* Clear all the states to reset the node. */
                mesh_stack_config_clear();
                node_reset();
                break;
            }
    
            default:
                break;
        }
    }
    
    
    /* client */
    static void rtt_input_handler(int key)
    {
        if (key >= '0' && key <= '3')
        {
            uint32_t button_number = key - '0';
            button_event_handler(button_number);
        }
    }
    
    /* sever */
    static void app_rtt_input_handler(int key)
    {
        if (key >= '0' && key <= '4')
        {
            uint32_t button_number = key - '0';
            button_ser_event_handler(button_number);
        }
    }
    
    /* client */
    static void models_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n");
    
        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));
        }
    }
    
    /* server */
    static void models_server_init_cb(void)
    {
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n");
        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));
    }
    
    /* own */
    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_c_s_node_uuid,
            .models.models_init_cb   = models_init_cb, 
    	.models.models_init_cb	 = models_server_init_cb,	
            .models.config_server_cb = config_server_evt_cb
        };
    	ERROR_CHECK(mesh_stack_init(&init_params, &m_device_provisioned));
    }
    
    
    static void initialize(void)
    {
        __LOG_INIT(LOG_SRC_APP | LOG_SRC_ACCESS, LOG_LEVEL_INFO, LOG_CALLBACK_DEFAULT);
         __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- BLE Mesh Light Switch Client Demo -----\n");
        __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- BLE Mesh Light Switch Server Demo -----\n");
    
        ERROR_CHECK(app_timer_init());
        hal_leds_init();
        led_init();
    #if BUTTON_BOARD
        ERROR_CHECK(hal_buttons_init(button_event_handler));
    #endif
    
    #if BUTTON_BOARD
        ERROR_CHECK(hal_buttons_init(button_ser_event_handler));
    #endif
    
        nrf_clock_lf_cfg_t lfc_cfg = DEV_BOARD_LF_CLK_CFG;
        ERROR_CHECK(mesh_softdevice_init(lfc_cfg));
        mesh_init();
    
    }
    
    static void start(void)
    {
        rtt_input_enable(rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS);
        rtt_input_enable(app_rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS);
        ERROR_CHECK(mesh_stack_start());
    
        if (!m_device_provisioned)
        {
            static const uint8_t static_auth_data[NRF_MESH_KEY_SIZE] = STATIC_AUTH_DATA;
            mesh_provisionee_start_params_t prov_start_params =
            {
                .p_static_data    = static_auth_data,
                .prov_complete_cb = provisioning_complete_cb,
                .p_device_uri = NULL
            };
            ERROR_CHECK(mesh_provisionee_prov_start(&prov_start_params));
        }
    
        const uint8_t *p_uuid = nrf_mesh_configure_device_uuid_get();
        __LOG_XB(LOG_SRC_APP, LOG_LEVEL_INFO, "Device UUID ", p_uuid, NRF_MESH_UUID_SIZE);
    
        hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF);
        hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_START);
    }
    
    int main(void)
    {
    	 
    	initialize();
            execution_start(start);
            
        
        for (;;)
        {
                                   
            (void)sd_app_evt_wait();
                
        }   
    }
    
    

    For my project i have to use control model to act as client and server.A control model may contain client model functionality to communicate with other server models and server model functionality to communicate with other client models. I want to configure control model as mentioned.

  • Bj¢rn, can you please refer the snippet which i have already post and give me the solution, thanks in advance

  •  I have to use 6 servers to communicate with a client from control model and another client will need to communicate with server from control model. I like to implement like this. That's y i asked about control model.

Reply Children
Related