ZigBee multi-sensor example with zephyr Error.

I have been working with multi-sensor example of ZigBee to develop it in zephyr. every things went well of endpoint sensor except that the coordinator suppose to receive the reading of temperature sensor.

The output error of coordinator are: Unimplemented signal (signal: 50, status: 0). the error appeared also in endpoint multi-sensor that I implemented from nrf5 SDK to nRF Connect SDK (zephyr).

      

according to Internal ZBOSS error codes the error appeared because of  RET_CONVERSION_ERROR ! I don't know what is mean or where I can fix this error! by the way the coordinator is the same of the light example coordinator.

any one can help?

I'm using zephyr nRF Connect SDK 1.18.0 with nrf52833.

  • Hi,

    Can you share your implementation of the multi sensor? Have you made any changes to the network coordinator sample?

    Can you get a sniffer log of the issue? If you have an additional nRF52840 DK or Dongle you can use nRF Sniffer for 802.15.4. Please start the sniffer before starting the Zigbee network so the sniffer has the network key.

    Best regards,

    Marte

  • Thanks for your replay Marte Smile

    This is the main of multi-sensor implementation:

    /*
     * Copyright (c) 2021 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
     */
    
    /** @file
     *
     * @brief Zigbee application template.
     */
    
    #include <zephyr.h>
    #include <logging/log.h>
    #include <dk_buttons_and_leds.h>
    
    #include <zboss_api.h>
    #include <zigbee/zigbee_error_handler.h>
    #include <zigbee/zigbee_app_utils.h>
    #include <zb_nrf_platform.h>
    #include <sys/printk.h>
    #include "zb_multi_sensor.h"
    
    #include <stdio.h>
    #include <sys/printk.h>
    #include <device.h>
    #include <drivers/sensor.h>
    #include <drivers/spi.h>
    #include <time.h>
    
    /* Device endpoint, used to receive ZCL commands. */
    #define APP_TEMPLATE_ENDPOINT               11
    
    /* Type of power sources available for the device.
     * For possible values see section 3.2.2.2.8 of ZCL specification.
     */
    #define TEMPLATE_INIT_BASIC_POWER_SOURCE    ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE
    
    /* LED indicating that device successfully joined Zigbee network. */
    #define ZIGBEE_NETWORK_STATE_LED            DK_LED3
    
    /* LED used for device identification. */
    #define IDENTIFY_LED                        DK_LED4
    
    /* Button used to enter the Identify mode. */
    #define IDENTIFY_MODE_BUTTON                DK_BTN4_MSK
    
    
    LOG_MODULE_REGISTER(app, LOG_LEVEL_INF);
    
    /* Main application customizable context.
     * Stores all settings and static values.
     */
    struct zb_device_ctx {
    	zb_zcl_basic_attrs_t     basic_attr;
    	zb_zcl_identify_attrs_t  identify_attr;
    };
    
    /* Zigbee device application context storage. */
    static struct zb_device_ctx dev_ctx;
    static sensor_device_ctx_t m_dev_ctx;
    
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, &m_dev_ctx.identify_attr.identify_time);
    
    ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT(basic_attr_list,
                                         &m_dev_ctx.basic_attr.zcl_version,
                                         &m_dev_ctx.basic_attr.app_version,
                                         &m_dev_ctx.basic_attr.stack_version,
                                         &m_dev_ctx.basic_attr.hw_version,
                                         m_dev_ctx.basic_attr.mf_name,
                                         m_dev_ctx.basic_attr.model_id,
                                         m_dev_ctx.basic_attr.date_code,
                                         &m_dev_ctx.basic_attr.power_source,
                                         m_dev_ctx.basic_attr.location_id,
                                         &m_dev_ctx.basic_attr.ph_env,
                                         m_dev_ctx.basic_attr.sw_ver);
    
    
    ZB_ZCL_DECLARE_TEMP_MEASUREMENT_ATTRIB_LIST(temperature_attr_list, 
                                                &m_dev_ctx.temp_attr.measure_value,
                                                &m_dev_ctx.temp_attr.min_measure_value, 
                                                 &m_dev_ctx.temp_attr.max_measure_value, 
                                                &m_dev_ctx.temp_attr.tolerance);
    
    ZB_ZCL_DECLARE_PRESSURE_MEASUREMENT_ATTRIB_LIST(pressure_attr_list, 
                                                &m_dev_ctx.pres_attr.measure_value, 
                                                &m_dev_ctx.pres_attr.min_measure_value, 
                                                &m_dev_ctx.pres_attr.max_measure_value, 
                                                &m_dev_ctx.pres_attr.tolerance);
    
    
    ZB_DECLARE_MULTI_SENSOR_CLUSTER_LIST(multi_sensor_clusters,
                                         basic_attr_list,
                                         identify_attr_list,
                                         temperature_attr_list,
                                         pressure_attr_list);
    
    ZB_ZCL_DECLARE_MULTI_SENSOR_EP(multi_sensor_ep,
                                   MULTI_SENSOR_ENDPOINT,
                                   multi_sensor_clusters);
    
    
    ZBOSS_DECLARE_DEVICE_CTX_1_EP(multi_sensor_ctx, multi_sensor_ep);
    
    
    
    
    struct k_timer my_timer;
    #define TIMER_INTERVAL_SEC 3
     
    
    /**@brief Function for initializing all clusters attributes. */
    static void app_clusters_attr_init(void)
    {
    	/* Basic cluster attributes data */
    	dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION;
    	dev_ctx.basic_attr.power_source = TEMPLATE_INIT_BASIC_POWER_SOURCE;
    
    	/* Identify cluster attributes data. */
    	dev_ctx.identify_attr.identify_time =
    		ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;
            
            /* Basic cluster attributes data */
        m_dev_ctx.basic_attr.zcl_version   = ZB_ZCL_VERSION;
        m_dev_ctx.basic_attr.app_version   = SENSOR_INIT_BASIC_APP_VERSION;
        m_dev_ctx.basic_attr.stack_version = SENSOR_INIT_BASIC_STACK_VERSION;
        m_dev_ctx.basic_attr.hw_version    = SENSOR_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_dev_ctx.basic_attr.mf_name,
                              SENSOR_INIT_BASIC_MANUF_NAME,
                              ZB_ZCL_STRING_CONST_SIZE(SENSOR_INIT_BASIC_MANUF_NAME));
    
        ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.model_id,
                              SENSOR_INIT_BASIC_MODEL_ID,
                              ZB_ZCL_STRING_CONST_SIZE(SENSOR_INIT_BASIC_MODEL_ID));
    
        ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.date_code,
                              SENSOR_INIT_BASIC_DATE_CODE,
                              ZB_ZCL_STRING_CONST_SIZE(SENSOR_INIT_BASIC_DATE_CODE));
    
        m_dev_ctx.basic_attr.power_source = SENSOR_INIT_BASIC_POWER_SOURCE;
    
        ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.location_id,
                              SENSOR_INIT_BASIC_LOCATION_DESC,
                              ZB_ZCL_STRING_CONST_SIZE(SENSOR_INIT_BASIC_LOCATION_DESC));
    
    
        m_dev_ctx.basic_attr.ph_env = SENSOR_INIT_BASIC_PH_ENV;
    
        /* Identify cluster attributes data */
        m_dev_ctx.identify_attr.identify_time        = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;
    
        /* Temperature measurement cluster attributes data */
        m_dev_ctx.temp_attr.measure_value            = ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_UNKNOWN;
        m_dev_ctx.temp_attr.min_measure_value        = ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_MIN_VALUE;
        m_dev_ctx.temp_attr.max_measure_value        = ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_MAX_VALUE;
        m_dev_ctx.temp_attr.tolerance                = ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_MAX_VALUE;
    
    }
    
    /**@brief Function to toggle the identify LED
     *
     * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
     */
    static void toggle_identify_led(zb_bufid_t bufid)
    {
    	static int blink_status;
    
    	dk_set_led(IDENTIFY_LED, (++blink_status) % 2);
    	ZB_SCHEDULE_APP_ALARM(toggle_identify_led, bufid, ZB_MILLISECONDS_TO_BEACON_INTERVAL(100));
    }
    
    /**@brief Function to handle identify notification events on the first endpoint.
     *
     * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
     */
    static void identify_cb(zb_bufid_t bufid)
    {
    	zb_ret_t zb_err_code;
    
    	if (bufid) {
    		/* Schedule a self-scheduling function that will toggle the LED */
    		ZB_SCHEDULE_APP_CALLBACK(toggle_identify_led, bufid);
    	} else {
    		/* Cancel the toggling function alarm and turn off LED */
    		zb_err_code = ZB_SCHEDULE_APP_ALARM_CANCEL(toggle_identify_led, ZB_ALARM_ANY_PARAM);
    		ZVUNUSED(zb_err_code);
    
    		dk_set_led(IDENTIFY_LED, 0);
    	}
    }
    
    
    ///
    static void zb_app_timer_handler(struct device *dev)
    {
        zb_zcl_status_t zcl_status;
        static zb_int16_t new_temp_value;
        int ret;
       // const struct device *dev;
        struct sensor_value val;
        zb_uint16_t coordinator_address = 0xffff;
    
    // this will be in main and called there passing device !!
    
        dev = device_get_binding(DT_LABEL(DT_INST(0, maxim_max6675)));
    
        if (dev == NULL) {
    		printk("Could not obtain MAX6675 device\n");
    		return ;
                    }
     
        ret = sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP);
        if (ret < 0) {
    			printk("Could not fetch temperature (%d)\n", ret);
    			return;
    		}
         ret = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &val);
         if (ret < 0){
                            printk("Could not get temperature (%d)\n", ret);
    			return;
    		}
    
        printk(" Temperature: %.2f C\n", sensor_value_to_double(&val));
        /* Get new temperature measured value */
        new_temp_value = (zb_int16_t)sensor_value_to_double(&val);
        zcl_status = zb_zcl_set_attr_val(MULTI_SENSOR_ENDPOINT, 
                                         ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, 
                                         ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                         ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, 
                                         (zb_uint8_t *)&new_temp_value, 
                                         ZB_FALSE);
    
    
        if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
        {
            LOG_INF("Set temperature value fail. zcl_status: %d", zcl_status);
        }
        else
        { 
            LOG_INF("Set temperature value. zcl_status: %d", zcl_status);
        }
     }
    
    /**@breif Starts identifying the device.
     *
     * @param  bufid  Unused parameter, required by ZBOSS scheduler API.
     */
    static void start_identifying(zb_bufid_t bufid)
    {
    	zb_ret_t zb_err_code;
    
    	ZVUNUSED(bufid);
    
    	/* Check if endpoint is in identifying mode,
    	 * if not put desired endpoint in identifying mode.
    	 */
    	if (dev_ctx.identify_attr.identify_time ==
    	    ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE) {
    		LOG_INF("Enter identify mode");
    		zb_err_code = zb_bdb_finding_binding_target(
    			APP_TEMPLATE_ENDPOINT);
    		ZB_ERROR_CHECK(zb_err_code);
    	} else {
    		LOG_INF("Cancel identify mode");
    		zb_bdb_finding_binding_target_cancel();
    	}
    }
    
    /**@brief Callback for button events.
     *
     * @param[in]   button_state  Bitmask containing buttons state.
     * @param[in]   has_changed   Bitmask containing buttons
     *                            that have changed their state.
     */
    static void button_changed(uint32_t button_state, uint32_t has_changed)
    {
    	/* Calculate bitmask of buttons that are pressed
    	 * and have changed their state.
    	 */
    	uint32_t buttons = button_state & has_changed;
    
    	if (buttons & IDENTIFY_MODE_BUTTON) {
    		ZB_SCHEDULE_APP_CALLBACK(start_identifying, 0);
    	}
    }
    
    /**@brief Function for initializing LEDs and Buttons. */
    static void configure_gpio(void)
    {
    	int err;
    
    	err = dk_buttons_init(button_changed);
    	if (err) {
    		LOG_ERR("Cannot init buttons (err: %d)", err);
    	}
    
    	err = dk_leds_init();
    	if (err) {
    		LOG_ERR("Cannot init LEDs (err: %d)", err);
    	}
    }
    
    /**@brief Zigbee stack event handler.
     *
     * @param[in]   bufid   Reference to the Zigbee stack buffer
     *                      used to pass signal.
     */
    void zboss_signal_handler(zb_bufid_t bufid)
    {       
            zb_zdo_app_signal_hdr_t  * p_sg_p      = NULL;
            zb_zdo_app_signal_type_t   sig         = zb_get_app_signal(bufid, &p_sg_p);
            zb_ret_t                   status      = ZB_GET_APP_SIGNAL_STATUS(bufid);
    
    	/* Update network status LED. */
    	zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED);
    
            switch (sig)
            {
            case ZB_BDB_SIGNAL_DEVICE_REBOOT:
                /* fall-through */
            case ZB_BDB_SIGNAL_STEERING:
                /* Call default signal handler. */
                ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
                if (status == RET_OK)
                {
                    //ret_code_t err_code = app_timer_start(zb_app_timer, APP_TIMER_TICKS(1000), NULL);
                   // APP_ERROR_CHECK(err_code);
                   printk("start timing Temp to Send it!\n");
                   k_timer_start(&my_timer, K_SECONDS(TIMER_INTERVAL_SEC), K_SECONDS(TIMER_INTERVAL_SEC));
                   printk("done start timing! \n");
                }
                break;
            case ZB_ZDO_SIGNAL_DEVICE_ANNCE:
                LOG_INF("ZB_ZDO_SIGNAL_DEVICE_ANNCE");
                break;
            default:
    
    	/* No application-specific behavior is required.
    	 * Call default signal handler.
    	 */
    	ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
            break;
            }
    
    	/* All callbacks should either reuse or free passed buffers.
    	 * If bufid == 0, the buffer is invalid (not passed).
    	 */
    	if (bufid) {
    		zb_buf_free(bufid);
    	}
    }
    
    
    
    K_WORK_DEFINE(my_work, zb_app_timer_handler);
    
    void my_timer_handler(struct k_timer *dummy)
    {
        k_work_submit(&my_work);
    }
    
    
    void main(void)
    {
    	LOG_INF("Starting Zigbee application template example");
            const struct device *dev;
            struct sensor_value val;
             
            dev = device_get_binding(DT_LABEL(DT_INST(0, maxim_max6675)));
    	if (dev == NULL) {
    		printk("Could not obtain MAX6675 device\n");
                    return;
    	}
    
    	
    
    	/* Initialize */
    	configure_gpio();
    
          //  dev = device_get_binding(DT_LABEL(DT_INST(0, maxim_max6675)));
          //  if (dev == NULL) {
        		//printk("Could not obtain MAX6675 device\n");
        		//return ;
          //              }
            
            k_timer_init(&my_timer, my_timer_handler, NULL);
    
    	///* Register device context (endpoints). */
    	//ZB_AF_REGISTER_DEVICE_CTX(&app_template_ctx);
           /* Register temperature sensor device context (endpoints). */
            ZB_AF_REGISTER_DEVICE_CTX(&multi_sensor_ctx);
    
    	app_clusters_attr_init();
    
    	/* Register handlers to identify notifications */
    	//ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(APP_TEMPLATE_ENDPOINT, identify_cb);
            ZB_AF_SET_IDENTIFY_NOTIFICATION_HANDLER(APP_TEMPLATE_ENDPOINT, zb_app_timer_handler);
    
    
    
    
    
    
    
    	/* Start Zigbee default thread */
    	zigbee_enable();
    
    	LOG_INF("Zigbee application template started");
        printk("\nExtenad PAN ID:( 0x%04hx )\n",  ZB_PIBCACHE_EXTENDED_ADDRESS());
        printk("\r( PAN ID: 0x%04hx, Node ID: 0x%04hx ) \n", ZB_PIBCACHE_PAN_ID(), ZB_PIBCACHE_NETWORK_ADDRESS());
    
    }
    
     

    I did not made any change in source code of network coordinator. 
    I use nRF sniffer and get this log: (coordinator + multi-sensor that I implement)

    multi-sensor.pcapng

  • Hi,

    Can you share your implementation of the multi sensor device in zb_multi_sensor.h, as other files or changes required to build the sample besides what is already in the nRF Connect SDK?

    The packets in the sniffer are encrypted, so I am unable to see the content. Please share the network key so I can decrypt the packets, or start the sniffer before the coordinator starts the network.

    Best regards,

    Marte

  • 4442.zb_multi_sensor.h

    multi-sensor2.pcapng

    I reprogram the coordinator and start sniffer than start the coordinator with multi-sensor.
    I did not add any other change  to build multi-sensor sample! the only change was in main source that I uploaded before.

    Thanks,

      

  • Hi,

    The last sniffer only contains packets of the device joining the network, and not any packets where you send simple descriptor request or any other packets that might be relevant to this issue. Can you get a sniffer log of when the problem happens? Remember to start the sniffer first.

    kalbani said:
    I did not add any other change  to build multi-sensor sample! the only change was in main source that I uploaded before.

    Are you copying the multi sensor files (zb_multi_sensor.h, zb_zcl_pressure_measurement.h, etc.) directly from nRF5 SDK and adding them to your project in nRF Connect SDK? The two SDKs are not compatible, and you cannot use something from nRF5 SDK directly in a nRF Connect SDK project like that. You will have to implement the relevant files and functionalities in nRF Connect SDK. If you want to create a multi sensor in nRF Connect SDK I recommend checking out our guide Adding ZCL clusters to application, which explains how to make a temperature sensor.

    Best regards,

    Marte

Related