This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Zigbee CLI example and float type

I'm testing the Zigbee CLI Agent example and try to read info from my Titan wall sensor. I can read almost all info, but not values, that are using float type.

How I can add support for Type 0x39 ( for example, CO2 measurement cluster: Cluster 4: [0x040D] Concentration Cluster -- Float Point, Single-Precision, as Titan manual states -- I get error "Value type 0x39 unsupported" )?

Thanks..

Tiit

  • I see, that zb_zcl_common.h  has 

    ZB_ZCL_ATTR_TYPE_SINGLE         = 0x39, /*!< 4 byte floating point */

    and tried to add  

    case ZB_ZCL_ATTR_TYPE_SINGLE:
    bytes_written = snprintf(p_str_buf, buf_len, "%g", *((zb_float_t *)p_attr));
    break;

    to zigbee_cli_utils.c and 

    typedef float              zb_float_t;

    to zb_types.h

    but that seems to be not the right way (i got no error anymore, but get an empty value).

  • So you found the list in zb_zcl_common.h. 

    The error that is printed, "Value type 0x39 unsupported" is, as you probably found out, coming from the zcl_attr_to_str() function in zigbee_cli_utils.c, switch (attr_type) -> case ZB_ZCL_ATTR_TYPE_SINGLE, which was not implemented, and hence, the default handler prints this error.

    That being said, it is not that straight forward to print this float value. Floats are not supported in snprintf. The reason for this is that the floats library takes up alot of space. See this discussion that I found on the silbas support forum.

    However, you can work around this. Perhaps you can try something like:

            case ZB_ZCL_ATTR_TYPE_SINGLE:
                my_raw_value = (uint8_t)p_attr[0]<<0 | (uint8_t)p_attr[1]<<8 | (uint8_t)p_attr[2]<<16 | (uint8_t)p_attr[3]<<24 ;
                my_float_pointer = (float*)&my_raw_value;
                my_float_value = *my_float_pointer;
                a = (zb_uint8_t)my_float_value;
                b = (zb_uint8_t)((my_float_value*100)-a*100);
                
                bytes_written = snprintf(p_str_buf, buf_len, "%d.%d", a, b);
                break;
                
    // The following declarations are done near the top of zcl_attr_to_str(), after int i:
    
        float * my_float_pointer;
        zb_float_t my_float_value;
        zb_uint32_t my_raw_value;
        zb_uint8_t a = 0;
        zb_uint8_t b = 0;

    The reason I use all the casting is that I had some hardfaults when I set the float value directly from the p_attr like this:

    my_float_pointer = (float*)p_attr;

    my_float_value = *my_float_pointer;

    I am not sure why.

    Best regards,

    Edvim

Related