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

Thermostat cluster enable issue

Hi All,

I am developing product using nRF52840 and SDK nRF5_SDK_for_Thread_and_Zigbee_v3.0.0_d310e71.

This product is basically, using the Thermostat cluster and Zigbee protocol to communicate with the Zigbee gateway.

So, I referred light_bulb example and followed steps to enable "Thermostat cluster and attributes".

I have included the respective files also but I am unable to execute the below callback function case statement,

static zb_void_t zcl_device_cb(zb_uint8_t param)
{
    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;

    switch (p_device_cb_param->device_cb_id)
    {
        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_THERMOSTAT)
            {
                uint16_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data16;

                NRF_LOG_INFO("thermostat local temperature: %d", value);
                if (attr_id == ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID)
                {
                    local_temperature_value(value);
                }
            }
            else
            {
                /* Other clusters can be processed here */
                NRF_LOG_INFO("Unhandled cluster attribute id: %d", cluster_id);
            }
        break;

        default:
            p_device_cb_param->status = RET_ERROR;
            break;
    }

    NRF_LOG_INFO("zcl_device_cb status: %hd", p_device_cb_param->status);
}

Also, I am attaching code for reference please let me know what else I forgot to enable the functions. It is urgent for me to solve this issue.

Radiator_nRF_v0.9.0.zip

And, with these attributes, for some of the commands, I need to implement custom attributes so if you share how to add custom attributes to this cluster.

Thanks in advance.

Regards,

Rohit R

Parents
  • Hi Marte, 

    Sorry for this inconvenience. I am not getting reply option to your latest feedback. I don't know what is wrong. 

    And to last post reply - 

    1. Yes, I have tried only current_setpoint_attribute() function also then also same problem. code line are not executing as marked in previous image. 

    2. I tried your suggestion also but still the same problem. You find the attached image where i am not able to put break point. 

    Should I share the code. but is same to last only thing is I have enabled more extended attributes. 

    Regards,

    Rohit R

  • Hi Rohit,

    I think I figured out what the issue is. Could you change cluster_id and attr_id to be unsigned 16 bit int instead of bit? So when you declare them for the first time in zcl_device_cb, you should use the following instead:

    zb_uint16_t                cluster_id;
    zb_uint16_t                attr_id;

    Please let me know whether this fixes the issue on your side or not.

    Best regards,

    Marte
  • Hi Marte, 

    Thank you so much for quick response. 

    It worked at my end. Now I can see my attribute function enable in callback.

    I will write my value parsing logic and send to Radiator to display these value. 

    Once the testing is done I will share the result with you. 

    Thanks a lot Slight smile.

    unsigned 16 bit int instead of bit?

    - Can you please explain what is the difference using this? 

    Means, I am making notes of all the resolved points so that it will help me in future for other project. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    That is great to hear!

    uint8_t and uint16_t are two data types of different sizes, where the numbers 8 and 16 specifies the size of the value in bits. So a uint8_t is an unsigned 8 bit value (or 1 byte, since 8 bits = 1 byte), and uint16_t is an unsigned 16 bit value (or 2 bytes). The u at the beginning indicates that it is unsigned. When a value is unsigned, it means that it cannot be a negative value, only zero or positive. So if you have a value that is of the data type uint8_t, the maximum value it can be is then 28-1 =  255. For uint16_t the maximum value is 216 -1 = 65 535. If you want to read more about these data types, you can find a lot of information on the internet.

    I assume you used the light bulb example to see how to add ZB_ZCL_SET_ATTR_VALUE_CB_ID etc. to your project. In that example, they can have cluster_id and attr_id as uint8_t values, as the IDs of the attributes used there are 0, and the cluster IDs are 6 and 8 (in decimal values). However, in your case, the ID of the current setpoint attribute is 0x4000 in hex, which in decimal is 16384. This value is too large for an uint8_t (0-255). So in your case, attr_id was set to 0 instead, which of course made the if-statement false, since you were then asking if 0 == 16384.

    Best regards,

    Marte

Reply
  • Hi Rohit,

    That is great to hear!

    uint8_t and uint16_t are two data types of different sizes, where the numbers 8 and 16 specifies the size of the value in bits. So a uint8_t is an unsigned 8 bit value (or 1 byte, since 8 bits = 1 byte), and uint16_t is an unsigned 16 bit value (or 2 bytes). The u at the beginning indicates that it is unsigned. When a value is unsigned, it means that it cannot be a negative value, only zero or positive. So if you have a value that is of the data type uint8_t, the maximum value it can be is then 28-1 =  255. For uint16_t the maximum value is 216 -1 = 65 535. If you want to read more about these data types, you can find a lot of information on the internet.

    I assume you used the light bulb example to see how to add ZB_ZCL_SET_ATTR_VALUE_CB_ID etc. to your project. In that example, they can have cluster_id and attr_id as uint8_t values, as the IDs of the attributes used there are 0, and the cluster IDs are 6 and 8 (in decimal values). However, in your case, the ID of the current setpoint attribute is 0x4000 in hex, which in decimal is 16384. This value is too large for an uint8_t (0-255). So in your case, attr_id was set to 0 instead, which of course made the if-statement false, since you were then asking if 0 == 16384.

    Best regards,

    Marte

Children
  • Hi Marte, 

    Thank you so much. 

    I assume you used the light bulb example to see how to add ZB_ZCL_SET_ATTR_VALUE_CB_ID etc. to your project. In that example, they can have cluster_id and attr_id as uint8_t values, as the IDs of the attributes used there are 0, and the cluster IDs are 6 and 8 (in decimal values). However, in your case, the ID of the current setpoint attribute is 0x4000 in hex, which in decimal is 16384. This value is too large for an uint8_t (0-255). So in your case, attr_id was set to 0 instead, which of course made the if-statement false, since you were then asking if 0 == 16384

    - ya, correct I used light_bulb code and started modifying as per my requirement. I didn't think of data type of attribute id and cluster id. I thought by default is required same and we can not change the parameter. 

    now I am clear that we can modify type also depending on the Attribute value. 

    Thanks and Regards

    Rohit R

  • Hi Marte, 

    I forgot to ask one thing. 

    I have one command which should be executed when end node connect to Gateway/coordinator. 

    In SDK 3.0 I use form this command when device discovered and on board LED glows. But in SDK4.1 the function is written in Zigbee_helpers.c file and I can not alter this file. If I do then it will cause SDK in all project. 

    Can let me know how I can use in main.c file. The command should not execute before connection it should only execute when network streaming complete. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    I need more information to understand what it is you want to do and to help you with how you can do it in v4.1.0. What did you use for this in v3.0.0, and how was it implemented? Which function do you refer to?

    Best regards,

    Marte

  • Hi Marte, 

    Sorry snippet didn't attached. 

    Here is the SDK 3.0 main.c file snippet, 

    void zboss_signal_handler(zb_uint8_t param)
    {
        zb_zdo_app_signal_hdr_t  * p_sg_p = NULL;
        zb_zdo_app_signal_type_t   sig    = zb_get_app_signal(param, &p_sg_p);
        zb_ret_t                   status = ZB_GET_APP_SIGNAL_STATUS(param);
        zb_bool_t                  comm_status;
    
        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);                
                    boolSetCommand  = true; 
                    boolReady = true;
                }
                else
                {
                    NRF_LOG_ERROR("Failed to join network. Status: %d", status);
                    bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED);
                    comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
                    ZB_COMM_STATUS_CHECK(comm_status);
                }
                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);
    
                    zb_zdo_signal_leave_params_t * 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);
                }
                else
                {
                    NRF_LOG_ERROR("Unable to leave network. Status: %d", status);
                }
                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);
        }
    }

    - As you can see that in zboss_signal_handler() function for case ZB_BDB_SIGNAL_DEVICE_REBOOT when LED turn ON, I have set one flag boolsetCommand = true. So when  this get true after discovery success and do my command sending process. 

    Similarly, I would like perform in SDK4.1, but here using zboss_default_signal_handler that which is present in zigbee_helpers.c file. But I can not modify this help because it affect to all project. 

    So let me know how I can use default_signal_handler function (SDK 4.1)in main file and follow my above step to send command when devices gets discovered. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    The zboss_signal_handler can be used to override how the stack signals are handled in the zboss_default_signal_handler. If you want your application to do something else than what is done in the default handler upon receiving a signal, you can handle this in zboss_signal_handler. This is what is done in your application created in v3.0.0. The default signal handler is only there to simplify the application, as most Zigbee devices behave in the same way. You can read more about this here if you are interested.

    If you want to implement a different behavior for the signals, all you have to do is to get the signal sig, as in your previous application, and then create a switch with that signal. The cases should be the different signals you want to override. Make sure to also have a default case that calls the default signal handler, such that every signal that you are not creating a custom implementation of will be handled by the default handler. Be aware that this will override the implementation of the signal in the default signal handler, so if you handle e.g. ZB_BDB_SIGNAL_DEVICE_REBOOT in zboss_signal_handler, then it will never enter the case for this signal in the default signal handler.

    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);
        zb_ret_t                       zb_err_code;
    
        /* Update network status LED */
        zigbee_led_status_update(bufid, ZIGBEE_NETWORK_STATE_LED);
    
        switch(sig)
        {
            case SIGNAL_YOU_WANT_TO_OVERRIDE:
    
                /* Your implementation of what to do when this signal is received */
    
                break;
    
            default:
                /* Call default signal handler. */
                ZB_ERROR_CHECK(zigbee_default_signal_handler(bufid));
                break;
        }
    
        if (bufid)
        {
            zb_buf_free(bufid);
        }
    }

    Best regards,

    Marte

Related