I have successfully managed to both provision and configure the simple:_on_of_client.
but i'm having troubles configuring the simple_on_off server. I really have no idea how to fix the issue, but what seems to be the problem is getting a response from the server node. all this happens at the intial step (in the switch case).
Server output:
<t: 0>, main.c, 191, ----- BLE Mesh Light Switch Server Demo ----- <t: 13242>, main.c, 171, Initializing and adding models <t: 13244>, simple_on_off_server.c, 137, MODEL INIT SUCCESS <t: 17997>, mesh_app_utils.c, 65, Device UUID (raw): ABA35353C189664FB261427FA6ACB866 <t: 18000>, mesh_app_utils.c, 70, Device UUID : 5353A3AB-89C1-4F66-B261-427FA6ACB866 <t: 1125039>, main.c, 151, Successfully provisioned <t: 1125044>, main.c, 162, Node Address: 0x0102
provisioner output:
<t: 828781>, provisioner_helper.c, 303, Scanning For Unprovisioned Devices <t: 828818>, main.c, 109, Flash write complete <t: 829891>, provisioner_helper.c, 138, UUID : ABA35353C189664FB261427FA6ACB866 <t: 829894>, provisioner_helper.c, 142, ^RSSI: -66 <t: 829896>, provisioner_helper.c, 147, ^URI Hash: 74F97940 <t: 829901>, provisioner_helper.c, 153, URI hash matched. Provisioning ... <t: 837008>, provisioner_helper.c, 274, Provisioning link established <t: 915600>, provisioner_helper.c, 269, Static authentication data provided <t: 1054423>, provisioner_helper.c, 207, Provisioning completed received <t: 1054426>, provisioner_helper.c, 212, Adding device address, and device keys <t: 1054431>, provisioner_helper.c, 229, Addr: 0x0102 addr_handle: 1 netkey_handle: 0 devkey_handle: 3 <t: 1058004>, provisioner_helper.c, 166, Local provisioning link closed: prov_state: 2 remaining retries: 2 <t: 1058008>, main.c, 298, Provisioning successful <t: 1058011>, provisioner_helper.c, 196, Provisioning complete. Node addr: 0x0102 elements: 1 <t: 1058015>, node_setup.c, 699, Configuring Node: 0x0102 <t: 1058018>, node_setup.c, 592, Config client setup: devkey_handle:3 addr_handle:1 <t: 1058022>, node_setup.c, 325, SERVER about to be configured <t: 1058024>, node_setup.c, 354, Getting composition data <t: 1058035>, node_setup.c, 356, status in NODE_SETUP_CONFIG_COMPOSITION_GET is: 0 <t: 1058038>, node_setup.c, 358, exiting NODE_SETUP_CONFIG_COMPOSITION_GET <t: 1058074>, main.c, 109, Flash write complete <t: 1058108>, main.c, 109, Flash write complete <t: 1140794>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -63 <t: 1143383>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -58 <t: 1468648>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -64 <t: 1471110>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -64 <t: 1796645>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -59 <t: 1799119>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -59 <t: 2124352>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -61 <t: 2126786>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -61 <t: 2451865>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -65 <t: 2454435>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -65 <t: 2779514>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -61 <t: 2782278>, main.c, 329, Node 0x0100 alive with 0 active fault(s), RSSI: -61 <t: 3024114>, main.c, 350, Config client event <t: 3024116>, node_setup.c, 640, Acknowledged message status not received <t: 3024119>, node_setup.c, 644, Retry ...
The node_setup.c is modified to support the simple_on_off server/client, by only using one address, instead of the ODD EVEN method. But i doubt that matters, since the error already happens at NODE_SETUP_CONFIG_COMPOSITION_GET
node_setup.c:
/* Copyright (c) 2010 - 2019, Nordic Semiconductor ASA * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this * list of conditions and the following disclaimer. * * 2. Redistributions in binary form, except as embedded into a Nordic * Semiconductor ASA integrated circuit in a product or a software update for * such product, must reproduce the above copyright notice, this list of * conditions and the following disclaimer in the documentation and/or other * materials provided with the distribution. * * 3. Neither the name of Nordic Semiconductor ASA nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * 4. This software, with or without modification, must only be used with a * Nordic Semiconductor ASA integrated circuit. * * 5. Any software provided in binary form under this license must not be reverse * engineered, decompiled, modified and/or disassembled. * * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <stdint.h> #include <stdbool.h> #include <string.h> #include <stdarg.h> #include "nrf_mesh_utils.h" #include "device_state_manager.h" #include "timer_scheduler.h" #include "config_client.h" #include "config_server.h" #include "access_config.h" #include "generic_level_server.h" #include "generic_level_client.h" #include "generic_onoff_server.h" #include "generic_onoff_client.h" #include "health_common.h" #include "provisioner_helper.h" #include "node_setup.h" #include "example_common.h" #include "example_network_config.h" #include "light_switch_example_common.h" #include "mesh_app_utils.h" #include "log.h" #include "nrf_mesh_assert.h" /* USER_NOTE: Add more steps here is you want to customize the nodes further. */ /* Node setup steps */ typedef enum { NODE_SETUP_IDLE, NODE_SETUP_CONFIG_COMPOSITION_GET, NODE_SETUP_CONFIG_NETWORK_TRANSMIT, NODE_SETUP_CONFIG_APPKEY_ADD, NODE_SETUP_CONFIG_APPKEY_BIND_HEALTH, NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_SERVER, NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_CLIENT, NODE_SETUP_CONFIG_PUBLICATION_HEALTH, NODE_SETUP_CONFIG_PUBLICATION_ONOFF_SERVER, NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT1, NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT2, NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER, NODE_SETUP_DONE, } config_steps_t; /* Structure to hold the composition data */ typedef struct { uint16_t len; struct { uint8_t page_number; uint8_t data[NRF_MESH_SEG_PAYLOAD_SIZE_MAX]; }composition; } composition_data_t; /* Expected status structure, used for setup state machine */ typedef struct { uint8_t num_statuses; uint16_t expected_opcode; const access_status_t * p_statuses; } expected_status_list_t; typedef struct { uint8_t count; timer_event_t timer; } client_send_retry_t; typedef enum { STATUS_CHECK_PASS, STATUS_CHECK_FAIL, STATUS_CHECK_UNEXPECTED_OPCODE } status_check_t; /* USER_NOTE: You can define one or more such configuration steps for a given node in your network. The choice of the steps can be done in @ref setup_select_steps() function. */ /* Sequence of steps for the client nodes */ static const config_steps_t client_config_steps[] = { NODE_SETUP_CONFIG_COMPOSITION_GET, NODE_SETUP_CONFIG_NETWORK_TRANSMIT, NODE_SETUP_CONFIG_APPKEY_ADD, NODE_SETUP_CONFIG_APPKEY_BIND_HEALTH, NODE_SETUP_CONFIG_PUBLICATION_HEALTH, NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_CLIENT, //NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_CLIENT, NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT1, //NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT2, NODE_SETUP_DONE }; /* Sequence of steps for the server nodes */ static const config_steps_t server_config_steps[] = { NODE_SETUP_CONFIG_COMPOSITION_GET, NODE_SETUP_CONFIG_NETWORK_TRANSMIT, NODE_SETUP_CONFIG_APPKEY_ADD, NODE_SETUP_CONFIG_APPKEY_BIND_HEALTH, NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_SERVER, NODE_SETUP_CONFIG_PUBLICATION_ONOFF_SERVER, NODE_SETUP_CONFIG_PUBLICATION_HEALTH, NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER, NODE_SETUP_DONE }; static uint16_t m_current_node_addr; static uint16_t m_retry_count; static client_send_retry_t m_send_timer; static const uint8_t * mp_appkey; static uint16_t m_appkey_idx; static uint16_t m_netkey_idx; static access_model_id_t m_client_model_id; static access_model_id_t m_server_model_id; static const config_steps_t m_idle_step = NODE_SETUP_IDLE; static const config_steps_t * mp_config_step = &m_idle_step; static node_setup_successful_cb_t m_node_setup_success_cb; static node_setup_failed_cb_t m_node_setup_failed_cb; static expected_status_list_t m_expected_status_list; /* Forward declaration */ static void config_step_execute(void); /*************************************************************************************************/ static void node_setup_state_clear(void) { timer_sch_abort(&m_send_timer.timer); mp_config_step = &m_idle_step; } static void node_setup_succeed(void) { node_setup_state_clear(); m_node_setup_success_cb(); } static void node_setup_fail(void) { node_setup_state_clear(); m_node_setup_failed_cb(); } /* Set expected status opcode and acceptable value of status codes */ static void expected_status_set(uint32_t opcode, uint32_t n, const access_status_t * p_list) { if (n > 0) { NRF_MESH_ASSERT(p_list != NULL); } m_expected_status_list.expected_opcode = opcode; m_expected_status_list.num_statuses = n; m_expected_status_list.p_statuses = p_list; } static void config_step_retry_schedule(void) { NRF_MESH_ASSERT_DEBUG(m_send_timer.count > 0); m_send_timer.count--; timestamp_t next_timeout = timer_now() + MS_TO_US(CLIENT_BUSY_SEND_RETRY_DELAY_MS); timer_sch_reschedule(&m_send_timer.timer, next_timeout); } /* Callback for the timer event */ static void client_send_timer_cb(timestamp_t timestamp, void * p_context) { /* retry the last step */ config_step_execute(); } /** * When config client status message is received, this function checks for the expected opcode, and * status values. It is required by the node setup state machine. */ static status_check_t check_expected_status(uint16_t rx_opcode, const config_msg_t * p_msg) { uint8_t status = 0xFF; if (rx_opcode != m_expected_status_list.expected_opcode) { __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Unexpected opcode: exp 0x%04x rx 0x%04x\n", m_expected_status_list.expected_opcode, rx_opcode); return STATUS_CHECK_UNEXPECTED_OPCODE; } switch (rx_opcode) { /* These messages do not have a STATUS field. */ case CONFIG_OPCODE_COMPOSITION_DATA_STATUS: case CONFIG_OPCODE_NETWORK_TRANSMIT_STATUS: break; case CONFIG_OPCODE_MODEL_APP_STATUS: status = p_msg->app_status.status; break; case CONFIG_OPCODE_MODEL_PUBLICATION_STATUS: status = p_msg->publication_status.status; break; case CONFIG_OPCODE_MODEL_SUBSCRIPTION_STATUS: status = p_msg->subscription_status.status; break; case CONFIG_OPCODE_APPKEY_STATUS: status = p_msg->appkey_status.status; break; default: /** USER_TO_CONFIGURE: Resolve additional required statuses in above switch case */ __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Handle additional statuses here"); ERROR_CHECK(NRF_ERROR_NOT_FOUND); break; } if (m_expected_status_list.num_statuses == 0) { return STATUS_CHECK_PASS; } __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "opcode status field: %d \n", status); for (uint32_t i = 0; i < m_expected_status_list.num_statuses; i++) { if (status == m_expected_status_list.p_statuses[i]) { return STATUS_CHECK_PASS; } } return STATUS_CHECK_FAIL; } /*************************************************************************************************/ /* Application-specific functions for combining some commonly used structure assignments */ static void client_pub_state_set(config_publication_state_t *p_pubstate, uint16_t element_addr, uint16_t publish_addr) { p_pubstate->element_address = element_addr; p_pubstate->publish_address.type = nrf_mesh_address_type_get(publish_addr); p_pubstate->publish_address.value = publish_addr; p_pubstate->appkey_index = m_appkey_idx; p_pubstate->frendship_credential_flag = false; p_pubstate->publish_ttl = (SERVER_NODE_COUNT > NRF_MESH_TTL_MAX ? NRF_MESH_TTL_MAX : SERVER_NODE_COUNT); p_pubstate->publish_period.step_num = 0; p_pubstate->publish_period.step_res = ACCESS_PUBLISH_RESOLUTION_100MS; p_pubstate->retransmit_count = 1; p_pubstate->retransmit_interval = 0; p_pubstate->model_id.company_id = m_client_model_id.company_id; p_pubstate->model_id.model_id = m_client_model_id.model_id; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Set: on/off client: 0x%04x pub addr: 0x%04x\n", p_pubstate->element_address, p_pubstate->publish_address.value); } /*************************************************************************************************/ /* Node setup functionality related static functions */ /* USER_NOTE: You can code any suitable logic here to select the configuration steps for a given node in your network. */ /** * Selects the configuration steps for the node. * * In this example, first device is always a light-switch Client. Subsequent devices are servers * First two servers will act as unicast devices and other servers will be subscribed to the * ODD or EVEN groups. * * @param[in] addr Address of the device being configured. * */ static void setup_select_steps(uint16_t addr) { if (addr == UNPROV_START_ADDRESS) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "CLIENT about to be configured\n"); mp_config_step = client_config_steps; } else { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "SERVER about to be configured\n"); mp_config_step = server_config_steps; } } /** Step execution function for the configuration state machine. */ static void config_step_execute(void) { uint32_t status = NRF_ERROR_INVALID_STATE; static uint16_t model_element_addr = 0; /* This example configures the provisioned nodes in the following way * Node 0: Client node (Switch) * Node 1,2,3 ...: Server nodes (Lights) * * Group Even: All nodes with even address * Group Odd: All nodes with odd address */ /* Customize configuration steps for client vs. server nodes. * For client nodes: Skip, usual publication and subscription */ switch (*mp_config_step) { /* Read the composition data from the node: */ case NODE_SETUP_CONFIG_COMPOSITION_GET: { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Getting composition data\n"); status = config_client_composition_data_get(0x00); __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "status in NODE_SETUP_CONFIG_COMPOSITION_GET is: %d \n",status); expected_status_set(CONFIG_OPCODE_COMPOSITION_DATA_STATUS, 0, NULL); __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "exiting NODE_SETUP_CONFIG_COMPOSITION_GET \n" ); break; } case NODE_SETUP_CONFIG_NETWORK_TRANSMIT: { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Updating network transmit: count: %d steps: %d\n", NETWORK_TRANSMIT_COUNT, NETWORK_TRANSMIT_INTERVAL_STEPS); status = config_client_network_transmit_set(NETWORK_TRANSMIT_COUNT, NETWORK_TRANSMIT_INTERVAL_STEPS); expected_status_set(CONFIG_OPCODE_NETWORK_TRANSMIT_STATUS, 0 , NULL); break; } /* Add the application key to the node: */ case NODE_SETUP_CONFIG_APPKEY_ADD: { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Adding appkey\n"); status = config_client_appkey_add(m_netkey_idx, m_appkey_idx, mp_appkey); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS, ACCESS_STATUS_KEY_INDEX_ALREADY_STORED}; expected_status_set(CONFIG_OPCODE_APPKEY_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } /* Bind the health server to the application key: */ case NODE_SETUP_CONFIG_APPKEY_BIND_HEALTH: { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "App key bind: Health server\n"); access_model_id_t model_id; model_id.company_id = ACCESS_COMPANY_ID_NONE; model_id.model_id = HEALTH_SERVER_MODEL_ID; uint16_t element_address = m_current_node_addr; status = config_client_model_app_bind(element_address, m_appkey_idx, model_id); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } /* 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: 0x%04x server\n", m_server_model_id.model_id); access_model_id_t model_id; model_id.company_id = m_server_model_id.company_id; model_id.model_id = m_server_model_id.model_id; uint16_t element_address = m_current_node_addr; status = config_client_model_app_bind(element_address, m_appkey_idx, model_id); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } /* Bind the On/Off client to the application key: */ case NODE_SETUP_CONFIG_APPKEY_BIND_ONOFF_CLIENT: { if (model_element_addr == 0) { model_element_addr = m_current_node_addr + 1; } __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "App key bind: 0x%04x client on element 0x%04x\n", m_client_model_id.model_id, model_element_addr); access_model_id_t model_id; model_id.company_id = m_client_model_id.company_id; model_id.model_id = m_client_model_id.model_id; uint16_t element_address = model_element_addr; status = config_client_model_app_bind(element_address, m_appkey_idx, model_id); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_APP_STATUS, ARRAY_SIZE(exp_status), exp_status); if (status == NRF_SUCCESS) { model_element_addr++; } break; } /* Configure the publication parameters for the Health server: */ case NODE_SETUP_CONFIG_PUBLICATION_HEALTH: { config_publication_state_t pubstate = {0}; pubstate.element_address = m_current_node_addr; pubstate.publish_address.type = NRF_MESH_ADDRESS_TYPE_UNICAST; pubstate.publish_address.value = PROVISIONER_ADDRESS; pubstate.appkey_index = m_appkey_idx; pubstate.frendship_credential_flag = false; pubstate.publish_ttl = (SERVER_NODE_COUNT > NRF_MESH_TTL_MAX ? NRF_MESH_TTL_MAX : SERVER_NODE_COUNT); pubstate.publish_period.step_num = 1; pubstate.publish_period.step_res = ACCESS_PUBLISH_RESOLUTION_10S; pubstate.retransmit_count = 1; pubstate.retransmit_interval = 0; pubstate.model_id.company_id = ACCESS_COMPANY_ID_NONE; pubstate.model_id.model_id = HEALTH_SERVER_MODEL_ID; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Setting publication address for the health server to 0x%04x\n", pubstate.publish_address.value); status = config_client_model_publication_set(&pubstate); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_PUBLICATION_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } /* Configure the publication parameters for the On/Off servers to publish to the corresponding On/Off clients (ODD servers: Client on Element 1 and EVEN servers: Client on element 2, of the client example). This demonstrates the state change publication due to local event on the server. */ case NODE_SETUP_CONFIG_PUBLICATION_ONOFF_SERVER: { config_publication_state_t pubstate = {0}; pubstate.element_address = m_current_node_addr; pubstate.publish_address.type = NRF_MESH_ADDRESS_TYPE_UNICAST; /** if ((m_current_node_addr % 2) == 0) { pubstate.publish_address.value = UNPROV_START_ADDRESS + ELEMENT_IDX_ONOFF_CLIENT2; } else { pubstate.publish_address.value = UNPROV_START_ADDRESS + ELEMENT_IDX_ONOFF_CLIENT1; } **/ pubstate.publish_address.value = UNPROV_START_ADDRESS + ELEMENT_IDX_ONOFF_CLIENT1; pubstate.appkey_index = m_appkey_idx; pubstate.frendship_credential_flag = false; pubstate.publish_ttl = (SERVER_NODE_COUNT > NRF_MESH_TTL_MAX ? NRF_MESH_TTL_MAX : SERVER_NODE_COUNT); pubstate.publish_period.step_num = 0; pubstate.publish_period.step_res = ACCESS_PUBLISH_RESOLUTION_100MS; pubstate.retransmit_count = 1; pubstate.retransmit_interval = 0; pubstate.model_id.company_id = m_server_model_id.company_id; pubstate.model_id.model_id = m_server_model_id.model_id; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Set: 0x%04x server pub addr: 0x%04x\n", m_server_model_id.model_id, pubstate.publish_address.value); status = config_client_model_publication_set(&pubstate); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_PUBLICATION_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } /* Configure subscription address for the On/Off server */ case NODE_SETUP_CONFIG_SUBSCRIPTION_ONOFF_SERVER: { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Adding subscription\n"); uint16_t element_address = m_current_node_addr; nrf_mesh_address_t address = {NRF_MESH_ADDRESS_TYPE_INVALID, 0, NULL}; address.type = NRF_MESH_ADDRESS_TYPE_GROUP; /** if (m_current_node_addr % 0x02) { address.value = GROUP_ADDRESS_ODD; } else { address.value = GROUP_ADDRESS_EVEN; } **/ address.value = GROUP_ADDRESS_ODD; access_model_id_t model_id; model_id.company_id = m_server_model_id.company_id; model_id.model_id = m_server_model_id.model_id; status = config_client_model_subscription_add(element_address, address, model_id); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_SUBSCRIPTION_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } case NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT1: { config_publication_state_t pubstate = {0}; client_pub_state_set(&pubstate, m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT1, GROUP_ADDRESS_ODD); status = config_client_model_publication_set(&pubstate); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_PUBLICATION_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } case NODE_SETUP_CONFIG_PUBLICATION_ONOFF_CLIENT2: { config_publication_state_t pubstate = {0}; client_pub_state_set(&pubstate, m_current_node_addr + ELEMENT_IDX_ONOFF_CLIENT2, GROUP_ADDRESS_EVEN); status = config_client_model_publication_set(&pubstate); static const access_status_t exp_status[] = {ACCESS_STATUS_SUCCESS}; expected_status_set(CONFIG_OPCODE_MODEL_PUBLICATION_STATUS, ARRAY_SIZE(exp_status), exp_status); break; } default: ERROR_CHECK(NRF_ERROR_NOT_FOUND); break; } if (status != NRF_SUCCESS) { config_client_pending_msg_cancel(); if (m_send_timer.count > 0) { config_step_retry_schedule(); } else { node_setup_fail(); } } } /** * This function retrieves the device key for the given address, and configures the tx and rx paths * of the config client model. */ static void setup_config_client(uint16_t target_addr) { dsm_handle_t addr_handle = DSM_HANDLE_INVALID; dsm_handle_t devkey_handle = DSM_HANDLE_INVALID; nrf_mesh_address_t addr; addr.type = NRF_MESH_ADDRESS_TYPE_UNICAST; addr.value = target_addr; /* Provisioner helper has stored address and device keys already. Retrieve them. */ ERROR_CHECK(dsm_address_handle_get(&addr, &addr_handle)); ERROR_CHECK(dsm_devkey_handle_get(addr.value, &devkey_handle)); /* Configure client to communicate with server at the given address */ ERROR_CHECK(config_client_server_bind(devkey_handle)); ERROR_CHECK(config_client_server_set(devkey_handle, addr_handle)); __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Config client setup: devkey_handle:%d addr_handle:%d\n", devkey_handle, addr_handle); } static void config_client_msg_handle(const config_client_event_t * p_event, uint16_t length) { if (*mp_config_step == NODE_SETUP_IDLE || *mp_config_step == NODE_SETUP_DONE) { __LOG(LOG_SRC_APP, LOG_LEVEL_WARN, "Got unexpected config client message in state %u\n", *mp_config_step); return; } else { status_check_t status = check_expected_status(p_event->opcode, p_event->p_msg); if (status == STATUS_CHECK_PASS) { mp_config_step++; m_send_timer.count = CLIENT_BUSY_SEND_RETRY_LIMIT; if (*mp_config_step == NODE_SETUP_DONE) { node_setup_succeed(); } else { config_step_execute(); } } else if (status == STATUS_CHECK_FAIL) { node_setup_fail(); } } } /*************************************************************************************************/ /* Public functions */ /** * Proccess the config client model events, and advances the node setup state machine to the next * state, if expected status message is received. */ void node_setup_config_client_event_process(config_client_event_type_t event_type, const config_client_event_t * p_event, uint16_t length) { if (event_type == CONFIG_CLIENT_EVENT_TYPE_TIMEOUT) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Acknowledged message status not received \n"); if (m_retry_count > 0) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Retry ...\n"); m_retry_count--; config_step_execute(); } else { node_setup_fail(); } } else if (event_type == CONFIG_CLIENT_EVENT_TYPE_MSG) { NRF_MESH_ASSERT_DEBUG(p_event != NULL); config_client_msg_handle(p_event, length); } } /** * Begins the node setup process. */ void node_setup_start(uint16_t address, uint8_t retry_cnt, const uint8_t * p_appkey, uint16_t appkey_idx, uint16_t netkey_idx, const char * p_client_uri) { if (*mp_config_step != NODE_SETUP_IDLE) { __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Cannot start. Node setup procedure is in progress.\n"); return; } m_current_node_addr = address; m_retry_count = retry_cnt; m_send_timer.timer.cb = client_send_timer_cb; m_send_timer.count = CLIENT_BUSY_SEND_RETRY_LIMIT; mp_appkey = p_appkey; m_appkey_idx = appkey_idx; m_netkey_idx = netkey_idx; /* The filter match will decide, which model pairs to pick up */ if (strcmp(p_client_uri, EX_URI_LS_CLIENT) == 0 || strcmp(p_client_uri, EX_URI_ENOCEAN) == 0) { m_client_model_id.model_id = GENERIC_ONOFF_CLIENT_MODEL_ID; m_server_model_id.model_id = GENERIC_ONOFF_SERVER_MODEL_ID; } else if (strcmp(p_client_uri, EX_URI_DM_CLIENT) == 0) { m_client_model_id.model_id = GENERIC_LEVEL_CLIENT_MODEL_ID; m_server_model_id.model_id = GENERIC_LEVEL_SERVER_MODEL_ID; } else { __LOG(LOG_SRC_APP, LOG_LEVEL_ERROR, "Invalid client URI identifier.\n"); NRF_MESH_ASSERT(false); } m_client_model_id.company_id = ACCESS_COMPANY_ID_NORDIC; m_server_model_id.company_id = ACCESS_COMPANY_ID_NORDIC; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Configuring Node: 0x%04X\n", m_current_node_addr); setup_config_client(m_current_node_addr); setup_select_steps(m_current_node_addr); config_step_execute(); } void node_setup_cb_set(node_setup_successful_cb_t config_success_cb, node_setup_failed_cb_t config_failed_cb) { NRF_MESH_ASSERT(config_success_cb != NULL); NRF_MESH_ASSERT(config_failed_cb != NULL); m_node_setup_success_cb = config_success_cb; m_node_setup_failed_cb = config_failed_cb; }
I expect the mistake to be in the server implementation, since it is the one NOT acknowledging the configuration, but i really can't tell.
main.c (server)
#include <stdint.h> #include <string.h> /* HAL */ #include "boards.h" #include "simple_hal.h" #include "app_timer.h" /* Core */ #include "nrf_mesh_config_core.h" #include "nrf_mesh_gatt.h" #include "nrf_mesh_configure.h" #include "nrf_mesh.h" #include "mesh_stack.h" #include "device_state_manager.h" #include "access_config.h" #include "proxy.h" /* Provisioning and configuration */ #include "mesh_provisionee.h" #include "mesh_app_utils.h" /* Models */ #include "C:\nRF_work\nrf5SDKforMeshv320src\models\vendor\simple_on_off\include\simple_on_off_server.h" //#include "C:\Users\RAbbas\OneDrive - Emerson\Documents\repos\mesh test\model\server_models\s_model.h" /* Logging and RTT */ #include "log.h" #include "rtt_input.h" /* Example specific includes */ #include "app_config.h" #include "example_common.h" #include "nrf_mesh_config_examples.h" #include "light_switch_example_common.h" //#include "app_onoff.h" #include "ble_softdevice_support.h" //#define ONOFF_SERVER_0_LED (BSP_LED_0) //#define APP_ONOFF_ELEMENT_INDEX (0) #define ON_OFF_MODEL_ELEMENT_INDEX (0) static bool m_device_provisioned= 0; /*************************************************************************************************/ //probably bad practice, but this is model value static uint8_t value_of_on_off_model=0; static bool app_on_off_model_server_set_cb(const simple_on_off_server_t * p_server, uint8_t value); static bool app_on_off_model_server_get_cb(const simple_on_off_server_t * p_server, uint8_t * p_present_value); // Generic OnOff server structure definition and initialization /* APP_TEST_MODEL_SERVER_DEF(m_test_model_server_0, app_test_model_server_set_cb, app_test_model_server_get_cb) */ const simple_on_off_server_t m_on_off_model_server_0 = { .set_cb = app_on_off_model_server_set_cb, .get_cb = app_on_off_model_server_get_cb }; // Callback for updating the hardware state //static void app_onoff_server_set_cb(const app_onoff_server_t * p_server, bool onoff) static bool app_on_off_model_server_set_cb(const simple_on_off_server_t * p_server, uint8_t value) { // Resolve the server instance here if required, this example uses only 1 instance. //__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Setting GPIO value: %d\n", onoff) value_of_on_off_model=value; __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "exiting set_cb, value is: %d \n", value_of_on_off_model); //hal_led_pin_set(ONOFF_SERVER_0_LED, onoff); return true; } //m Callback for reading the hardware state //static void app_onoff_server_get_cb(const app_onoff_server_t * p_server, bool * p_present_onoff) static bool app_on_off_model_server_get_cb(const simple_on_off_server_t * p_server, uint8_t * p_present_value) { // Resolve the server instance here if required, this example uses only 1 instance. *p_present_value=value_of_on_off_model; //*p_present_onoff = hal_led_pin_get(ONOFF_SERVER_0_LED); __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "exiting get_cb, value is: %d \n", value_of_on_off_model); return true; } static void app_model_init(void) { /* Instantiate onoff server on element index APP_ONOFF_ELEMENT_INDEX */ //ERROR_CHECK(app_onoff_init(&m_onoff_server_0, APP_ONOFF_ELEMENT_INDEX)); ERROR_CHECK(simple_on_off_server_init(&m_on_off_model_server_0, ON_OFF_MODEL_ELEMENT_INDEX)); //__LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "App OnOff Model Handle: %d\n", m_onoff_server_0.server.model_handle); } /*************************************************************************************************/ 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(); } static void config_server_evt_cb(const config_server_evt_t * p_evt) { if (p_evt->type == CONFIG_SERVER_EVT_NODE_RESET) { node_reset(); } } /* static void app_rtt_input_handler(int key) { if (key >= '0' && key <= '4') { uint32_t button_number = key - '0'; button_event_handler(button_number); } } */ static void device_identification_start_cb(uint8_t attention_duration_s) { hal_led_mask_set(LEDS_MASK, false); hal_led_blink_ms(BSP_LED_2_MASK | BSP_LED_3_MASK, LED_BLINK_ATTENTION_INTERVAL_MS, LED_BLINK_ATTENTION_COUNT(attention_duration_s)); } static void provisioning_aborted_cb(void) { hal_led_blink_stop(); } static void provisioning_complete_cb(void) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Successfully provisioned\n"); #if MESH_FEATURE_GATT_ENABLED /* Restores the application parameters after switching from the Provisioning * service to the Proxy */ gap_params_init(); conn_params_init(); #endif 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_blink_stop(); hal_led_mask_set(LEDS_MASK, LED_MASK_STATE_OFF); hal_led_blink_ms(LEDS_MASK, LED_BLINK_INTERVAL_MS, LED_BLINK_CNT_PROV); } static void models_init_cb(void) { __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "Initializing and adding models\n"); app_model_init(); } 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 = NULL, .models.models_init_cb = models_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_FRIEND, LOG_LEVEL_DBG1, LOG_CALLBACK_DEFAULT); __LOG(LOG_SRC_APP, LOG_LEVEL_INFO, "----- BLE Mesh Light Switch Server Demo -----\n"); ERROR_CHECK(app_timer_init()); hal_leds_init(); #if BUTTON_BOARD // ERROR_CHECK(hal_buttons_init(button_event_handler)); #endif ble_stack_init(); #if MESH_FEATURE_GATT_ENABLED gap_params_init(); conn_params_init(); #endif mesh_init(); } static void start(void) { // rtt_input_enable(app_rtt_input_handler, RTT_INPUT_POLL_PERIOD_MS); 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, .prov_device_identification_start_cb = device_identification_start_cb, .prov_device_identification_stop_cb = NULL, .prov_abort_cb = provisioning_aborted_cb, .p_device_uri = EX_URI_LS_SERVER }; ERROR_CHECK(mesh_provisionee_prov_start(&prov_start_params)); } mesh_app_uuid_print(nrf_mesh_configure_device_uuid_get()); ERROR_CHECK(mesh_stack_start()); 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(); start(); for (;;) { (void)sd_app_evt_wait(); } }