Hi and happy new year everyone,
I am a developer for Raytheon Anschütz GmbH in Kiel Germany and working on a Zigbee mesh sensor network. Unfortunately I am an absolute beginner for Zigbee and have a lot of basic questions I can not figure out the the documentation.
My goal is to provide temperature and voltage level from a router to the coordinator. The coordinator should request the values within an interval.
I took the Zigbee light switch example as a base and included the temp_measurement zcl for the router. What I understood from the zcl documentation a general attribute request is needed to receive the values.
I created a readTemp() function where I set up the read attribute request according to the documentation here https://www.nordicsemi.com/DocLib/Content/SDK_Doc/Thread_SDK/v2-0-0/group__read__attr__command.
Unfortunately I am not sure if I did everything correct as I do not receive any data. For example I do not understand what the cmd_ptr. is for. Should I fill it or is it filled the the response. Did I call the ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_SERVER_ROLE_INIT() and ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_CLIENT_ROLE_INIT(), correctly?
For the el_measurement zcl I wonder how to add the DC_Volt attribute to the attribute list as the Makro ZB_ZCL_DECLARE_ELECTRICAL_MEASUREMENT_ATTRIB_LIST contains only the measurement_type and dcpower attribute.
I attached the code for the router and coordinator and hope you can help me with a simple request as I am stucked and do not know how I can solve it on my own.
Thank you in advance for your help.
Best regards
Marco Runge
/** * Copyright (c) 2018, 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. * */ /** @file * * @defgroup zigbee_examples_light_coordinator main.c * @{ * @ingroup zigbee_examples * @brief Simple ZigBee network coordinator implementation. */ #include "nrf.h" #include "nrfx_timer.h" #include "bsp.h" #include "app_error.h" #include "zboss_api.h" #include "zboss_api_zdo.h" #include "zb_mem_config_max.h" #include "zb_error_handler.h" #include "boards.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #include "zb_zcl_temp_measurement.h" #define ERASE_PERSISTENT_CONFIG ZB_FALSE /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. NOTE: If this option is set to ZB_TRUE then do full device erase for all network devices before running other samples. */ #define MAX_CHILDREN 10 /**< The maximum amount of connected devices. Setting this value to 0 disables association to this device. */ #define IEEE_CHANNEL_MASK (1l << ZIGBEE_CHANNEL) /**< Scan only one, predefined channel to find the coordinator. */ #define ZIGBEE_NETWORK_STATE_LED BSP_BOARD_LED_2 /**< LED indicating that network is opened for new nodes. */ #define BMS_TEMP_ENDPOINT 1 /**< Source endpoint used to control light bulb. */ #define TEMP_FOUND_LED BSP_BOARD_LED_3 /**< LED indicating that light witch found a light bulb to control. */ #define MATCH_DESC_REQ_ROLE ZB_NWK_BROADCAST_RX_ON_WHEN_IDLE /**< Find only non-sleepy device. */ #define MATCH_DESC_REQ_START_DELAY (2 * ZB_TIME_ONE_SECOND) /**< Delay between the light switch startup and light bulb finding procedure. */ const nrfx_timer_t TIMER = NRFX_TIMER_INSTANCE(0); uint16_t devList[500] = {0}; static uint16_t iter = 0; static zb_void_t zcl_device_cb(zb_uint8_t param); void readTemp(); #ifndef ZB_COORDINATOR_ROLE #error Define ZB_COORDINATOR_ROLE to compile coordinator source code. #endif // temp measurement cluster attributes typedef struct { zb_int16_t value; zb_int16_t min_value; zb_int16_t max_value; zb_uint16_t tolerance; } bms_temp_attr_t; typedef struct temp_sensor_params_s { zb_uint8_t endpoint; zb_uint16_t short_addr; } temp_sensor_params_t; typedef struct bms_sensor_ctx_s { temp_sensor_params_t sensor_params; bms_temp_attr_t temp_attr; } bms_sensor_ctx_t; static bms_sensor_ctx_t m_device_ctx; /** * @brief Handler for timer events. */ void timer_event_handler(nrf_timer_event_t event_type, void* p_context) { switch (event_type) { case NRF_TIMER_EVENT_COMPARE0: if(devList[0] != 0) readTemp(); break; default: //Do nothing. break; } } static zb_void_t send_cb(zb_uint8_t param); //void readTemp(zb_uint8_t param) void readTemp() { NRF_LOG_INFO("read Temp...\n\r"); zb_buf_t * p_buf; zb_uint8_t *cmd_ptr = NULL; ZB_ZCL_GENERAL_INIT_READ_ATTR_REQ(p_buf, cmd_ptr, ZB_ZCL_ENABLE_DEFAULT_RESPONSE); ZB_ZCL_GENERAL_ADD_ID_READ_ATTR_REQ(cmd_ptr, ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID); ZB_ZCL_GENERAL_SEND_READ_ATTR_REQ(p_buf, cmd_ptr, devList[0], ZB_APS_ADDR_MODE_16_ENDP_PRESENT, 1, BMS_TEMP_ENDPOINT, ZB_AF_HA_PROFILE_ID, ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, send_cb); zb_buf_t *buf; zb_zcl_read_attr_res_t *read_attr_resp; ZB_ZCL_GENERAL_GET_NEXT_READ_ATTR_RES(buf, read_attr_resp); NRF_LOG_INFO("cmd = %d", *cmd_ptr); NRF_LOG_INFO("buf = %d", *(int16_t*)buf->buf); } /**@brief Function for initializing the nrf log module. */ static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); } /**@brief Function for initializing LEDs. */ static void leds_init(void) { bsp_board_init(BSP_INIT_LEDS); } /**@brief Callback used in order to visualise network steering period. * * @param[in] param Not used. Required by callback type definition. */ static zb_void_t steering_finished(zb_uint8_t param) { UNUSED_PARAMETER(param); NRF_LOG_INFO("Network steering finished"); bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED); } /**@brief Retry to form a Zigbee network. */ static zb_void_t bdb_restart_top_level_commissioning(zb_uint8_t param) { UNUSED_RETURN_VALUE(bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING)); } /**@brief Add device to device list on join */ //void simple_gw_dev_annce_cb(uint16_t addr) //{ // NRF_LOG_INFO("addr = %d\r\n", addr); // devList[iter] = addr; // iter++; // int i = 0; // while(devList[i] != 0) // { // NRF_LOG_INFO("devList[%d] = %d\r\n", i, devList[i]); // i++; // } //} static zb_void_t send_cb(zb_uint8_t param) { NRF_LOG_INFO("Send CB"); } /**@brief Callback function for handling ZCL commands. * * @param[in] param Reference to ZigBee stack buffer used to pass received data. */ static zb_void_t zcl_device_cb(zb_uint8_t param) { NRF_LOG_INFO("zcl_device_cb"); zb_uint8_t cluster_id; zb_uint8_t attr_id; zb_buf_t * p_buffer = ZB_BUF_FROM_REF(param); zb_zcl_device_callback_param_t * p_device_cb_param = ZB_GET_BUF_PARAM(p_buffer, zb_zcl_device_callback_param_t); NRF_LOG_INFO("zcl_device_cb id %hd", p_device_cb_param->device_cb_id); /* Set default response value. */ p_device_cb_param->status = RET_OK; NRF_LOG_INFO("device_cb_id: %d", p_device_cb_param->device_cb_id); switch (p_device_cb_param->device_cb_id) { case ZB_ZCL_SHADE_GET_VALUE_CB_ID: cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; NRF_LOG_INFO("cluster_id: %d", cluster_id); NRF_LOG_INFO("attr_id: %d", attr_id); switch (attr_id) { case ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID: NRF_LOG_INFO("Get temp value: %d", attr_id); break; case ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID: NRF_LOG_INFO("Get bat volt value: %d", attr_id); break; default: NRF_LOG_INFO("Unhandled cluster attribute id: %d", cluster_id); break; } break; case ZB_ZCL_SET_ATTR_VALUE_CB_ID: cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; if (cluster_id == ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) { uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8; NRF_LOG_INFO("attribute id %d", attr_id); if (attr_id == ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID) { NRF_LOG_INFO("Get temp value: %d", value); } } default: p_device_cb_param->status = RET_ERROR; break; } NRF_LOG_INFO("zcl_device_cb status: %hd", p_device_cb_param->status); } /**@brief ZigBee stack event handler. * * @param[in] param Reference to ZigBee stack buffer used to pass arguments (signal). */ void zboss_signal_handler(zb_uint8_t param) { /* Read signal description out of memory buffer. */ zb_zdo_app_signal_type_t sig = zb_get_app_signal(param, NULL); zb_ret_t status = ZB_GET_APP_SIGNAL_STATUS(param); zb_ret_t zb_err_code; zb_bool_t comm_status; NRF_LOG_INFO("signal %d. Status: %d", sig, status); switch(sig) { case ZB_BDB_SIGNAL_DEVICE_FIRST_START: // Device started and commissioned first time after NVRAM erase. case ZB_BDB_SIGNAL_DEVICE_REBOOT: // BDB initialization completed after device reboot, use NVRAM contents during initialization. Device joined/rejoined and started. if (status == RET_OK) { NRF_LOG_INFO("Device started OK. Start network steering."); bsp_board_led_on(ZIGBEE_NETWORK_STATE_LED); comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING); ZB_COMM_STATUS_CHECK(comm_status); } else { NRF_LOG_ERROR("Device startup failed. Status: %d. Retry network formation after 1 second.", status); bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED); zb_err_code = ZB_SCHEDULE_ALARM(bdb_restart_top_level_commissioning, 0, ZB_TIME_ONE_SECOND); ZB_ERROR_CHECK(zb_err_code); } break; case ZB_BDB_SIGNAL_STEERING: if (status == RET_OK) { memset(devList, 0, sizeof(devList)); /* Schedule an alarm to notify about the end of steering period */ NRF_LOG_INFO("Network steering started"); zb_err_code = ZB_SCHEDULE_ALARM(steering_finished, 0, ZB_TIME_ONE_SECOND * ZB_ZGP_DEFAULT_COMMISSIONING_WINDOW); ZB_ERROR_CHECK(zb_err_code); } else { NRF_LOG_INFO("Network steering failed to start. Status: %d. Retry network formation after 1 second.", status); bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED); zb_err_code = ZB_SCHEDULE_ALARM(bdb_restart_top_level_commissioning, 0, ZB_TIME_ONE_SECOND); ZB_ERROR_CHECK(zb_err_code); } break; case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY: if (status != RET_OK) { NRF_LOG_WARNING("Production config is not present or invalid"); } break; case ZB_ZDO_SIGNAL_DEVICE_ANNCE: { NRF_LOG_INFO("JOIND! \r\n"); zb_buf_t * p_buf = ZB_BUF_FROM_REF(param); zb_apsde_data_indication_t * p_ind = ZB_GET_BUF_PARAM(p_buf, zb_apsde_data_indication_t); // Get the pointer to the parameters buffer, which stores APS layer response devList[iter] = p_ind->src_addr; NRF_LOG_INFO("Addr = 0x%02x\r\n", devList[iter]); // zb_err_code = ZB_SCHEDULE_CALLBACK(readTemp, param); // ZB_ERROR_CHECK(zb_err_code); param = 0; // Do not free buffer - it will be reused by find_light_bulb callback nrfx_timer_enable(&TIMER); iter++; } break; default: /* Unhandled signal. For more information see: zb_zdo_app_signal_type_e and zb_ret_e */ NRF_LOG_INFO("Unhandled signal %d. Status: %d", sig, status); break; } /* All callbacks should either reuse or free passed buffers. If param == 0, the buffer is invalid (not passed) */ // if (param) // { // ZB_FREE_BUF_BY_REF(param); // } } /**@brief Function for application main entry. */ int main(void) { uint32_t time_ms = 500; //Time(in miliseconds) between consecutive compare events. uint32_t time_ticks; uint32_t err_code = NRF_SUCCESS; zb_ret_t zb_err_code; zb_ieee_addr_t ieee_addr; // Initialize. log_init(); leds_init(); /* Set ZigBee stack logging level and traffic dump subsystem. */ ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL); ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK); ZB_SET_TRAF_DUMP_OFF(); /* Initialize ZigBee stack. Pass "zdo_zc" to the stack logging system. */ ZB_INIT("zdo_zc"); /* Set device address to the value read from FICR registers. */ zb_osif_get_ieee_eui64(ieee_addr); zb_set_long_address(ieee_addr); /* Set channels on which the coordinator will try to create a new network. */ zb_set_network_coordinator_role(IEEE_CHANNEL_MASK); zb_set_max_children(MAX_CHILDREN); /* Keep or erase NVRAM to save the network parameters after device reboot or power-off. */ zb_set_nvram_erase_at_start(ERASE_PERSISTENT_CONFIG); /* Register callback for handling ZCL commands. */ ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_CLIENT_ROLE_INIT(); /** Start Zigbee Stack. */ zb_err_code = zboss_start(); ZB_ERROR_CHECK(zb_err_code); nrfx_timer_config_t timer_cfg = NRFX_TIMER_DEFAULT_CONFIG; err_code = nrfx_timer_init(&TIMER, &timer_cfg, timer_event_handler); APP_ERROR_CHECK(err_code); time_ticks = nrfx_timer_ms_to_ticks(&TIMER, time_ms); nrfx_timer_extended_compare( &TIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true); while(1) { zboss_main_loop_iteration(); UNUSED_RETURN_VALUE(NRF_LOG_PROCESS()); } } /** * @} */
/** * Copyright (c) 2018, 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. * */ /** @file * */ #include "zboss_api.h" #include "zb_mem_config_med.h" #include "zb_error_handler.h" #include "zb_nrf52840_internal.h" #include "zboss_api_zcl.h" #include "zb_zcl_power_config.h" #include "zb_zcl_el_measurement.h" #include "zb_zcl_temp_measurement.h" #include "boards.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #define ZB_HA_DEFINE_DEVICE_TEMPERATURE_SENSOR #define MAX_CHILDREN 10 /**< The maximum amount of connected devices. Setting this value to 0 disables association to this device. */ #define IEEE_CHANNEL_MASK (1l << ZIGBEE_CHANNEL) /**< Scan only one, predefined channel to find the coordinator. */ #define ERASE_PERSISTENT_CONFIG ZB_FALSE /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. */ /* Basic cluster attributes initial values. */ #define BMS_INIT_BASIC_APP_VERSION 01 /**< Version of the application software (1 byte). */ #define BMS_INIT_BASIC_STACK_VERSION 30 /**< Version of the implementation of the ZigBee stack (1 byte). */ #define BMS_INIT_BASIC_HW_VERSION 11 /**< Version of the hardware of the device (1 byte). */ #define BMS_INIT_BASIC_MANUF_NAME "RAn" /**< Manufacturer name (32 bytes). */ #define BMS_INIT_BASIC_MODEL_ID "BMS_v0.1" /**< Model number assigned by manufacturer (32-bytes long string). */ #define BMS_INIT_BASIC_DATE_CODE "20181216" /**< First 8 bytes specify the date of manufacturer of the device in ISO 8601 format (YYYYMMDD). Th rest (8 bytes) are manufacturer specific. */ #define BMS_INIT_BASIC_POWER_SOURCE ZB_ZCL_BASIC_POWER_SOURCE_BATTERY /**< Type of power sources available for the device. For possible values see section 3.2.2.2.8 of ZCL specification. */ #define BMS_INIT_BASIC_LOCATION_DESC "Battery Room" /**< Describes the physical location of the device (16 bytes). May be modified during commisioning process. */ #define BMS_INIT_BASIC_PH_ENV ZB_ZCL_BASIC_ENV_UNSPECIFIED /**< Describes the type of physical environment. For possible values see section 3.2.2.2.10 of ZCL specification. */ // Default values #define BMS_TEMP_MIN_VALUE_DEG 0 #define BMS_TEMP_MAX_VALUE_DEG 8000 #define BMS_TEMP_TOL_VALUE_DEG 2 // Device Endpoints #define HA_TEMP_SENSOR_ENDPOINT 1 /**< Device endpoint, used to receive light controlling commands. */ // LED #define ZIGBEE_NETWORK_STATE_LED BSP_BOARD_LED_2 /**< LED indicating that light switch successfully joind ZigBee network. */ #define ZIGBEE_TRANSFER_LED BSP_BOARD_LED_1 /**< LED indicating that light switch successfully joind ZigBee network. */ #if !defined ZB_ROUTER_ROLE #error Define ZB_ROUTER_ROLE to compile light BMS (Router) source code. #endif // Basic cluster attributes typedef struct { zb_uint8_t zcl_version; zb_uint8_t app_version; zb_uint8_t stack_version; zb_uint8_t hw_version; zb_char_t mf_name[32]; zb_char_t model_id[32]; zb_char_t date_code[16]; zb_uint8_t power_source; zb_char_t location_id[17]; zb_uint8_t ph_env; } bms_basic_attr_t; // Identify cluster attributes typedef struct { zb_uint16_t identify_time; zb_uint8_t commission_state; } bms_identify_attr_t; // temp measurement cluster attributes typedef struct { zb_int16_t value; zb_int16_t min_value; zb_int16_t max_value; zb_uint16_t tolerance; } bms_temp_attr_t; // Main application customizable context. Stores all settings and static values typedef struct { bms_basic_attr_t bms_basic_attr; bms_identify_attr_t bms_identify_attr; bms_temp_attr_t bms_temp_attr; } bms_ctx_t; static bms_ctx_t m_bms_dev_ctx; // Declare Attribute Lists ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_HA_ADDS_FULL(basic_attr_list, &m_bms_dev_ctx.bms_basic_attr.zcl_version, &m_bms_dev_ctx.bms_basic_attr.app_version, &m_bms_dev_ctx.bms_basic_attr.stack_version, &m_bms_dev_ctx.bms_basic_attr.hw_version, &m_bms_dev_ctx.bms_basic_attr.mf_name, &m_bms_dev_ctx.bms_basic_attr.model_id, &m_bms_dev_ctx.bms_basic_attr.date_code, &m_bms_dev_ctx.bms_basic_attr.power_source, &m_bms_dev_ctx.bms_basic_attr.location_id, &m_bms_dev_ctx.bms_basic_attr.ph_env); ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST_HA(identify_attr_list, &m_bms_dev_ctx.bms_identify_attr.identify_time, &m_bms_dev_ctx.bms_identify_attr.commission_state); ZB_ZCL_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(temp_attr_list, &m_bms_dev_ctx.bms_temp_attr.value, &m_bms_dev_ctx.bms_temp_attr.min_value, &m_bms_dev_ctx.bms_temp_attr.max_value, &m_bms_dev_ctx.bms_temp_attr.tolerance); // Declare Cluster Lists ZB_HA_DECLARE_TEMPERATURE_SENSOR_CLUSTER_LIST(temp_sensor_clusters, basic_attr_list, identify_attr_list, temp_attr_list); // Declare Endpoints ZB_HA_DECLARE_TEMPERATURE_SENSOR_EP(bms_temp_ep, HA_TEMP_SENSOR_ENDPOINT, temp_sensor_clusters); // Declare Device Contexts ZB_HA_DECLARE_TEMPERATURE_SENSOR_CTX(bms_temp_ctx, bms_temp_ep); /**@brief Function for initializing the nrf log module. */ static void log_init(void) { ret_code_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); } /**@brief Function for setting temperature. * * @param[in] new_level Light bulb brightness value. */ static void temp_set_value(zb_int16_t new_temp) { m_bms_dev_ctx.bms_temp_attr.value = new_temp; NRF_LOG_INFO("Set new temp value: %i", new_temp); } /**@brief Function for initializing all clusters attributes. */ static void bms_clusters_attr_init(void) { // Basic cluster attr init m_bms_dev_ctx.bms_basic_attr.zcl_version = ZB_ZCL_VERSION; m_bms_dev_ctx.bms_basic_attr.app_version = BMS_INIT_BASIC_APP_VERSION; m_bms_dev_ctx.bms_basic_attr.stack_version = BMS_INIT_BASIC_STACK_VERSION; m_bms_dev_ctx.bms_basic_attr.hw_version = BMS_INIT_BASIC_HW_VERSION; /* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte should * contain string length without trailing zero. * * For example "test" string wil be encoded as: * [(0x4), 't', 'e', 's', 't'] */ ZB_ZCL_SET_STRING_VAL(m_bms_dev_ctx.bms_basic_attr.mf_name, BMS_INIT_BASIC_MANUF_NAME, ZB_ZCL_STRING_CONST_SIZE(BMS_INIT_BASIC_MANUF_NAME)); ZB_ZCL_SET_STRING_VAL(m_bms_dev_ctx.bms_basic_attr.model_id, BMS_INIT_BASIC_MODEL_ID, ZB_ZCL_STRING_CONST_SIZE(BMS_INIT_BASIC_MODEL_ID)); ZB_ZCL_SET_STRING_VAL(m_bms_dev_ctx.bms_basic_attr.date_code, BMS_INIT_BASIC_DATE_CODE, ZB_ZCL_STRING_CONST_SIZE(BMS_INIT_BASIC_DATE_CODE)); m_bms_dev_ctx.bms_basic_attr.power_source = BMS_INIT_BASIC_POWER_SOURCE; ZB_ZCL_SET_STRING_VAL(m_bms_dev_ctx.bms_basic_attr.location_id, BMS_INIT_BASIC_LOCATION_DESC, ZB_ZCL_STRING_CONST_SIZE(BMS_INIT_BASIC_LOCATION_DESC)); m_bms_dev_ctx.bms_basic_attr.ph_env = BMS_INIT_BASIC_PH_ENV; // Identify cluster attributes init m_bms_dev_ctx.bms_identify_attr.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE; m_bms_dev_ctx.bms_identify_attr.commission_state = ZB_ZCL_ATTR_IDENTIFY_COMMISSION_STATE_HA_ID_DEF_VALUE; // Temp cluster attr init m_bms_dev_ctx.bms_temp_attr.value = 0; m_bms_dev_ctx.bms_temp_attr.min_value = BMS_TEMP_MIN_VALUE_DEG; m_bms_dev_ctx.bms_temp_attr.max_value = BMS_TEMP_MAX_VALUE_DEG; m_bms_dev_ctx.bms_temp_attr.tolerance = BMS_TEMP_TOL_VALUE_DEG; } /**@brief Function which tries to sleep down the MCU * * Function which sleeps the MCU on the non-sleepy End Devices to optimize the power saving. * The weak definition inside the OSIF layer provides some minimal working template */ zb_void_t zb_osif_go_idle(zb_void_t) { /* A check that we're not a Sleep End Device -- they sleep elsewhere */ if (ZB_PIBCACHE_RX_ON_WHEN_IDLE()) { //TODO: implement your own logic if needed if (NRF_LOG_PROCESS() == false) { zb_osif_wait_for_event(); } } } /**@brief Callback function for handling ZCL commands. * * @param[in] param Reference to ZigBee stack buffer used to pass received data. */ static zb_callback_t zcl_device_cb(zb_uint8_t param) { NRF_LOG_INFO("device_cb"); zb_uint8_t cluster_id; zb_uint8_t attr_id; zb_buf_t * p_buffer = ZB_BUF_FROM_REF(param); zb_zcl_device_callback_param_t * p_device_cb_param = ZB_GET_BUF_PARAM(p_buffer, zb_zcl_device_callback_param_t); /* Set default response value. */ p_device_cb_param->status = RET_OK; NRF_LOG_INFO("device_cb_id: %d", p_device_cb_param->device_cb_id); switch (p_device_cb_param->device_cb_id) { case ZB_ZCL_SHADE_GET_VALUE_CB_ID: { cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id; attr_id = p_device_cb_param->cb_param.set_attr_value_param.attr_id; NRF_LOG_INFO("cluster_id: %d", cluster_id); NRF_LOG_INFO("attr_id: %d", attr_id); switch (cluster_id) { case ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID: NRF_LOG_INFO("Get temp value: %d", attr_id); break; case ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_VOLTAGE_ID: NRF_LOG_INFO("Get bat volt value: %d", attr_id); break; default: NRF_LOG_INFO("Unhandled cluster attribute id: %d", cluster_id); break; } } break; default: p_device_cb_param->status = RET_ERROR; break; } NRF_LOG_INFO("zcl_device_cb status: %hd", p_device_cb_param->status); } zb_device_handler_t zcl_endpoint_cb(zb_uint8_t param) { NRF_LOG_INFO("endpoint_cb"); } /**@brief Perform local operation - leave network. * * @param[in] param Reference to ZigBee stack buffer that will be used to construct leave request. */ static void leave_nwk(zb_uint8_t param) { zb_ret_t zb_err_code; /* We are going to leave */ if (param) { zb_buf_t * p_buf = ZB_BUF_FROM_REF(param); zb_zdo_mgmt_leave_param_t * p_req_param; p_req_param = ZB_GET_BUF_PARAM(p_buf, zb_zdo_mgmt_leave_param_t); UNUSED_RETURN_VALUE(ZB_BZERO(p_req_param, sizeof(zb_zdo_mgmt_leave_param_t))); /* Set dst_addr == local address for local leave */ p_req_param->dst_addr = ZB_PIBCACHE_NETWORK_ADDRESS(); p_req_param->rejoin = ZB_FALSE; UNUSED_RETURN_VALUE(zdo_mgmt_leave_req(param, NULL)); } else { zb_err_code = ZB_GET_OUT_BUF_DELAYED(leave_nwk); ZB_ERROR_CHECK(zb_err_code); } } /**@brief Function for starting join/rejoin procedure. * * param[in] leave_type Type of leave request (with or without rejoin). */ static zb_void_t retry_join(zb_uint8_t leave_type) { zb_bool_t comm_status; if (leave_type == ZB_NWK_LEAVE_TYPE_RESET) { comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING); ZB_COMM_STATUS_CHECK(comm_status); } } /**@brief Function for leaving current network and starting join procedure afterwards. * * @param[in] param Optional reference to ZigBee stack buffer to be reused by leave and join procedure. */ static zb_void_t leave_and_join(zb_uint8_t param) { if (ZB_JOINED()) { /* Leave network. Joining procedure will be initiated inisde ZigBee stack signal handler. */ leave_nwk(param); } else { /* Already left network. Start joining procedure. */ retry_join(ZB_NWK_LEAVE_TYPE_RESET); if (param) { ZB_FREE_BUF_BY_REF(param); } } } /**@brief ZigBee stack event handler. * * @param[in] param Reference to ZigBee stack buffer used to pass arguments (signal). */ void zboss_signal_handler(zb_uint8_t param) { zb_zdo_app_signal_hdr_t * p_sg_p = NULL; zb_zdo_signal_leave_params_t * p_leave_params = NULL; zb_zdo_app_signal_type_t sig = zb_get_app_signal(param, NULL); zb_ret_t status = ZB_GET_APP_SIGNAL_STATUS(param); zb_ret_t zb_err_code; switch (sig) { case ZB_BDB_SIGNAL_DEVICE_FIRST_START: case ZB_BDB_SIGNAL_DEVICE_REBOOT: if (status == RET_OK) { NRF_LOG_INFO("Joined network successfully"); bsp_board_led_on(ZIGBEE_NETWORK_STATE_LED); } else { NRF_LOG_ERROR("Failed to join network. Status: %d", status); bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED); zb_err_code = ZB_SCHEDULE_ALARM(leave_and_join, 0, ZB_TIME_ONE_SECOND); ZB_ERROR_CHECK(zb_err_code); } break; case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY: if (status != RET_OK) { NRF_LOG_WARNING("Production config is not present or invalid"); } break; case ZB_ZDO_SIGNAL_LEAVE: if (status == RET_OK) { bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED); p_leave_params = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_leave_params_t); NRF_LOG_INFO("Network left. Leave type: %d", p_leave_params->leave_type); retry_join(p_leave_params->leave_type); } else { NRF_LOG_ERROR("Unable to leave network. Status: %d", status); } break; case ZB_ZDO_SIGNAL_DEVICE_ANNCE: { zb_buf_t * p_buf = ZB_BUF_FROM_REF(param); zb_apsde_data_indication_t * p_ind = ZB_GET_BUF_PARAM(p_buf, zb_apsde_data_indication_t); // Get the pointer to the parameters buffer, which stores APS layer response NRF_LOG_INFO("Joined at Addr = 0x02%x\r\n", p_ind->src_addr); break; } default: /* Unhandled signal. For more information see: zb_zdo_app_signal_type_e and zb_ret_e */ NRF_LOG_INFO("Unhandled signal %d. Status: %d", sig, status); break; } if (param) { ZB_FREE_BUF_BY_REF(param); } } /**@brief Function for application main entry. */ int main(void) { zb_ret_t zb_err_code; zb_ieee_addr_t ieee_addr; /* Initialize loging system and GPIOs. */ log_init(); /* Initialize LEDs */ bsp_board_init(BSP_INIT_LEDS); bsp_board_leds_off(); /* Set ZigBee stack logging level and traffic dump subsystem. */ ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL); ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK); ZB_SET_TRAF_DUMP_OFF(); /* Initialize ZigBee stack. */ ZB_INIT("bms_router"); /* Set device address to the value read from FICR registers. */ zb_osif_get_ieee_eui64(ieee_addr); zb_set_long_address(ieee_addr); /* Set static long IEEE address. */ zb_set_network_router_role(IEEE_CHANNEL_MASK); zb_set_nvram_erase_at_start(ERASE_PERSISTENT_CONFIG); zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000)); /* Initialize application context structure. */ UNUSED_RETURN_VALUE(ZB_MEMSET(&m_bms_dev_ctx, 0, sizeof(m_bms_dev_ctx))); bms_clusters_attr_init(); /* Register device context (endpoints). */ ZB_AF_REGISTER_DEVICE_CTX(&bms_temp_ctx); /* Register callback for handling ZCL commands. */ ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb); ZB_AF_SET_ENDPOINT_HANDLER(HA_TEMP_SENSOR_ENDPOINT, zcl_endpoint_cb); ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT_SERVER_ROLE_INIT(); temp_set_value(1234); /** Start Zigbee Stack. */ zb_err_code = zboss_start(); ZB_ERROR_CHECK(zb_err_code); while(1) { zboss_main_loop_iteration(); UNUSED_RETURN_VALUE(NRF_LOG_PROCESS()); } } /** * @} */