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,

    Thank you for the details, 

    As of now, sending custom command is pending. I will work on this in some time. 

    But current requirement I am trying to enabled the required attributes list. With reference to your code and other I have created extended list also. 

    But unoccupied, min and max, local_calibration and etc are not getting highlighted from thermostat cluster. And also Battery percentage attribute also facing same problem. they are not getting highlighted and these are must attributes (mandatory ids). 

    I have tested in SDK 3.0 I am getting highlighted below points but in SDK 4.1 i am facing this issue. Let me know why?

    Below is the image attached for both cluster. And also my thermostat.h file please check what is wrong. Why I am not getting these attributes highlighted. 

    0508.zb_zcl_thermostat.h

    5807.zb_zcl_power_config.h

    Thanks and regards

    Rohit 

  • Hi Marte, 

    Any update on this. 

    Urgent!

    Is there any difference in my file. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    Due to summer vacation you might have to expect some increase in response time, also from our developers.

    As for current consumption, you will notice a significant increase in current consumption when not using Sleepy End Device (SED) compared to a device with SED enabled. This is because with other low power modes, the radio is still always on, causing a much higher current consumption than if it is off. With SED the other hand, the radio will be off when it sleeps. However, this will make it so that the device will not be able to receive messages at all times, and cannot wake up by a command from another device, as it will not receive the message when it is sleeping. So you will have to either use SED and have the radio off at times, or you will have to have a higher current consumption. A device implemented as a SED will wake up periodically to check for messages, as I have explained earlier. It will do this by polling it's parent and asking the parent if there are any messages for it, as the parent store the messages for some time so that the SED will receive them on wake up. You can change the poll interval with zb_zdo_pim_set_long_poll_interval, to make the sleepy end device poll it's parent at a shorter interval than the default one.

    Rohit Rajapure said:
    Can we use in SDK 3.0 ? If yes the How to handle it in helper.c file or any other file. 

     The best option would be to use SDK 4.1.0 instead, but since that is not an option, you can try to add the function zigbee_power_down_unused_ram to your project yourself, as the implementation of the function is available in v4.1.0, and not an internal stack function. To do this, you must add the function to your SDK, as well as any dependencies of that function. I cannot guarantee that it will work, as there might be other changes between v3.0.0 and v4.1.0 affecting this, but it should be possible to power down the unused RAM in v3.0.0 as well.

    Rohit Rajapure said:
    "ION_RAMOFF_EVENT System ON, no RAM retention, wake on any event 0.97 μA" typically. 

     This mode and current is for the base current consumption of the chip in ON idle mode.

    • System ON: This means that the chip is in system ON, and not in system OFF, which means that the chip is in a regular state ready to run, and that the CPU is in sleep mode. The CPU is in a WFE (waitinf for event) call, and will wake when there is an interrupt. This interrupt is typically the RTC clock, but with 1 μA. the RTC is not in use.
    • no RAM retention: this means that the RAM is not conserved, and will practically mean that there is no code running on the chip.

    So you will not be able to get this current consumption and still run your application on your device. You will minimally need RAM retention, RTC to wake up at intervals, and the LF clock, which is needed for RTC. Therefore, your current consumption will be above 1 μA, even if you are using SED and powering down RAM sections. According to the specification, the expected current consumption with RAM retention and RTC is as follows:

    ION_RAMON_RTC
    System ON, full 256 kB RAM retention, wake on RTC (running from LFRC clock)
    3.16 
    µA

     However, since you are able to power down unused parts of RAM, you will not have full 256 RAM retention, which will reduce current compared to the above. Additionally, you can use LFXO as a clock source instead of LFRC, and use an external crystal, which will have slightly lower current consumption than using LFRC.

    Best regards,

    Marte

  • Hi Marte, 

    Thank you so much for response, 

    Due to summer vacation you might have to expect some increase in response time, also from our developers.

    - Okay, i will wait but need help.

    As for current consumption, you will notice a significant increase in current consumption when not using Sleepy End Device (SED) compared to a device with SED enabled. This is because with other low power modes, the radio is still always on, causing a much higher current consumption than if it is off. With SED the other hand, the radio will be off when it sleeps. However, this will make it so that the device will not be able to receive messages at all times, and cannot wake up by a command from another device, as it will not receive the message when it is sleeping. So you will have to either use SED and have the radio off at times, or you will have to have a higher current consumption. A device implemented as a SED will wake up periodically to check for messages, as I have explained earlier.

    - Okay, If I configure as SED. It will give comparatively less current than getting now correct?

    - And, If I just call sleep now () in zigbee_signal_handler means it is configured as SED. And I can comment this part from code to make SED? Correct? 

    zb_void_t zb_osif_go_idle(zb_void_t)
    {
    //TODO: implement your own logic if needed
    zb_osif_wait_for_event();
    }

    - And, in SED device wake up every 10sec correct? I read in one of the nordic link. 

    The best option would be to use SDK 4.1.0 instead, but since that is not an option, you can try to add the function zigbee_power_down_unused_ram to your project yourself, as the implementation of the function is available in v4.1.0, and not an internal stack function. To do this, you must add the function to your SDK, as well as any dependencies of that function. I cannot guarantee that it will work, as there might be other changes between v3.0.0 and v4.1.0 affecting this, but it should be possible to power down the unused RAM in v3.0.0 as well.

    - Okay, I will check. 

     However, since you are able to power down unused parts of RAM, you will not have full 256 RAM retention, which will reduce current compared to the above. Additionally, you can use LFXO as a clock source instead of LFRC, and use an external crystal, which will have slightly lower current consumption than using LFRC.

    - No, I have note configured yet. But would like to configure. But LFRC give me better result then how to configure this? Is there any example for reference? 

    Thanks and Regards

    Rohit R

  • Hi Marte, 

    Any update on above post?

    My understanding is correct to configure SED device?If yes, then will configure likewise and test for current. Let me know your feedback.

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    Rohit Rajapure said:
    If I configure as SED. It will give comparatively less current than getting now correct?

     Yes, that is correct.

    Rohit Rajapure said:
    And, If I just call sleep now () in zigbee_signal_handler means it is configured as SED

    This is not entirely correct.

    To configure the device as a SED you must call zb_set_rx_on_when_idle(ZB_FALSE) in main, such as in the multi sensor example. This enables sleepy behavior and makes your device act as a Sleepy End Device.

    You are correct in that you must call zb_sleep_now() in zboss_signal_handler(), when receiving the signal ZB_COMMON_SIGNAL_CAN_SLEEP. Again, you should do as in the multi sensor example.

    Rohit Rajapure said:
    And I can comment this part from code to make SED? Correct? 

     Yes, with SED you will use zb_sleep_now() to put the device and radio to sleep, and you can remove zb_osif_go_idle() from main.c. The function zb_osif_go_idle() is not really necessary to have in main.c if you are not using SED either, as it is already implemented in external/zboss/osif/zb_nrf52840_common.c. The only reason to use it in main.c is if you want to override the function to make it do something else than what it does in the implementation in zb_nrf52840_common.c.

    Rohit Rajapure said:
    But LFRC give me better result then how to configure this? Is there any example for reference? 

     You can read about the clock sources for the LFCLK controller here: LFCLK controller. Further down on that page you will find 32.768 kHz crystal oscillator (LFXO), where you can read about LFXO.

     You can see more about typical current consumption for nRF52840 in the electrical specification, where you can find information such as sleep current and radio transmitting/receiving current. The nRF52840 specification does not show the typical current for using LFXO, only LFRC, but the electrical specification for some of the other SoCs does, to show a comparison between using LFRC and LFXO as clock source:

    ION_RAMON_RTC System ON, Full 24 kB RAM retention, Wake on RTC (running from LFRC clock) 1.5 µA 
    ION_RAMON_RTC_LFXO System ON, Full 24 kB RAM retention, Wake on RTC (running from LFXO clock) 1.1 µA

    Please note that the above numbers are from another SoC than the nRF52840 and has different typical current consumption than nRF52840.

    Best regards,

    Marte

  • Hi Marte, 

    Thank you for the response, 

    To configure the device as a SED you must call zb_set_rx_on_when_idle(ZB_FALSE) in main, such as in the multi sensor example. This enables sleepy behavior and makes your device act as a Sleepy End Device.

    You are correct in that you must call zb_sleep_now() in zboss_signal_handler(), when receiving the signal ZB_COMMON_SIGNAL_CAN_SLEEP. Again, you should do as in the multi sensor example.

    - Okay, Noted.

     Yes, with SED you will use zb_sleep_now() to put the device and radio to sleep, and you can remove zb_osif_go_idle() from main.c. The function zb_osif_go_idle() is not really necessary to have in main.c if you are not using SED either, as it is already implemented in external/zboss/osif/zb_nrf52840_common.c. The only reason to use it in main.c is if you want to override the function to make it do something else than what it does in the implementation in zb_nrf52840_common.c.

    - Okay, Noted.

    You can read about the clock sources for the LFCLK controller here: LFCLK controller. Further down on that page you will find 32.768 kHz crystal oscillator (LFXO), where you can read about LFXO.

     You can see more about typical current consumption for nRF52840 in the electrical specification, where you can find information such as sleep current and radio transmitting/receiving current. The nRF52840 specification does not show the typical current for using LFXO, only LFRC, but the electrical specification for some of the other SoCs does, to show a comparison between using LFRC and LFXO as clock source:

    - Okay, I will check. 

    I have noted down your points for configuring SED. And as per your previous post I have discussed your points about SED with my team. But  they are like we will test the current default code on custom hardware and check the current. 

    - After testing default code on custom it gave us 3.9mA. This is too high. We are testing again on Dev-kit as well as custom. I will get back to you on result early. 

    And they want device should wake up Zigbee commands( it must) as per client requirement. But since nordic developer are busy. I will wait for something can we do here. But need help as early as possible make system wake up on Zigbee command and sleep if no commands. - Need help for this.

    One more update from my end. 

    - There is one feature in my device, that is perform "network leave or erase the current connect coordinator info"

    - To this what I done is, used zigbee_erase_persistent_storage() and set ZB_TRUE; this means by setting true it will erase the info. 

    - I did the same but it not erasing nor performing NVIC_SystemReset() correctly. 

    - My requirement is I have long button press which result in Reset of my STM8 board and that give me signal to nRF board (node) and I have perform erase info and softreset the device and start again. 

    Let me know whether I have followed correct API to execute this erase info and NVIC_SystemReset() is for software? 

    Thanks and Regards

    Rohit R

Reply
  • Hi Marte, 

    Thank you for the response, 

    To configure the device as a SED you must call zb_set_rx_on_when_idle(ZB_FALSE) in main, such as in the multi sensor example. This enables sleepy behavior and makes your device act as a Sleepy End Device.

    You are correct in that you must call zb_sleep_now() in zboss_signal_handler(), when receiving the signal ZB_COMMON_SIGNAL_CAN_SLEEP. Again, you should do as in the multi sensor example.

    - Okay, Noted.

     Yes, with SED you will use zb_sleep_now() to put the device and radio to sleep, and you can remove zb_osif_go_idle() from main.c. The function zb_osif_go_idle() is not really necessary to have in main.c if you are not using SED either, as it is already implemented in external/zboss/osif/zb_nrf52840_common.c. The only reason to use it in main.c is if you want to override the function to make it do something else than what it does in the implementation in zb_nrf52840_common.c.

    - Okay, Noted.

    You can read about the clock sources for the LFCLK controller here: LFCLK controller. Further down on that page you will find 32.768 kHz crystal oscillator (LFXO), where you can read about LFXO.

     You can see more about typical current consumption for nRF52840 in the electrical specification, where you can find information such as sleep current and radio transmitting/receiving current. The nRF52840 specification does not show the typical current for using LFXO, only LFRC, but the electrical specification for some of the other SoCs does, to show a comparison between using LFRC and LFXO as clock source:

    - Okay, I will check. 

    I have noted down your points for configuring SED. And as per your previous post I have discussed your points about SED with my team. But  they are like we will test the current default code on custom hardware and check the current. 

    - After testing default code on custom it gave us 3.9mA. This is too high. We are testing again on Dev-kit as well as custom. I will get back to you on result early. 

    And they want device should wake up Zigbee commands( it must) as per client requirement. But since nordic developer are busy. I will wait for something can we do here. But need help as early as possible make system wake up on Zigbee command and sleep if no commands. - Need help for this.

    One more update from my end. 

    - There is one feature in my device, that is perform "network leave or erase the current connect coordinator info"

    - To this what I done is, used zigbee_erase_persistent_storage() and set ZB_TRUE; this means by setting true it will erase the info. 

    - I did the same but it not erasing nor performing NVIC_SystemReset() correctly. 

    - My requirement is I have long button press which result in Reset of my STM8 board and that give me signal to nRF board (node) and I have perform erase info and softreset the device and start again. 

    Let me know whether I have followed correct API to execute this erase info and NVIC_SystemReset() is for software? 

    Thanks and Regards

    Rohit R

Children
  • Hi Marte, 

    As I said last post that I am getting 3.9mA current with this config as you explained me, 

    zb_void_t zb_osif_go_idle(zb_void_t)
    {
    //TODO: implement your own logic if needed
    zb_osif_wait_for_event();
    }

    I have tested multiple times and gave me 3.9mA. My last reading 0.03 mA was not correct. My mistake while taking readings. But I need help to reduce current. 

    Can you help me what could be the issue here?. 

    After battery life calculation we came to conclusion that we need at least 30/ 35uA only nRF part. My nrf52840 node should give me 30 to 35uA.

    Hi, 

    Please find the attached code, as per your instruction I made the changes in my code regarding sleepy end device. Let me know I have followed your all steps so that I can test the current for this. As I am getting higher current in previous code so decide to test this sleepy end device also. main.c file

    /**
     * Copyright (c) 2018 - 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.
     *
     */
    /** @file
     *
     * @defgroup zigbee_examples_light_bulb main.c
     * @{
     * @ingroup zigbee_examples
     * @brief Dimmable light sample (HA profile)
     */
    
    #include "sdk_config.h"
    #include "zboss_api.h"
    #include "zb_mem_config_med.h"
    #include "zb_error_handler.h"
    #include "zb_nrf52840_internal.h"
    #include "zigbee_helpers.h"
    
    #include "bsp.h"
    #include "boards.h"
    #include "app_timer.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    
    #include "app_uart.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "nrf.h"
    
    /**User Include file*********/
    #include "uart_config.h"
    #include "gpio_config.h"
    #include "timer_config.h"
    #include "commands.h" 
    #include "uart_statemachine.h" 
    #include "app_flash_memory.h"
    
    #include "zb_custom1_thermostat.h"
    #include "custom_app_event.h"
    
    
                                    
    /**< Scan only one, predefined channel to find the coordinator. */
    #define IEEE_CHANNEL_MASK                (ZB_TRANSCEIVER_ALL_CHANNELS_MASK)    // (1l << ZIGBEE_CHANNEL)
    
    #define ERASE_PERSISTENT_CONFIG           ZB_FALSE                              /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. */
    
    
    #define ZIGBEE_NETWORK_STATE_LED          BSP_BOARD_LED_2                       /**< LED indicating that light switch successfully joind ZigBee network. */
    
    
    #if !defined ZB_ED_ROLE
    #error Define ZB_ED_ROLE to compile End Device source code.
    #endif
    
    
    
    /******************************************************************
    * GLOBAL VARIABLES
    *
    *******************************************************************/
    uint16_t ui16CurrentTemp =0, ui16OccupiedHeatSetpoint = 0, ui16UnOccupiedHeatSetpoint = 0;
    uint8_t  ui8LocalTemperatureCalibration = 0;
    uint32_t ui32HostflagsData = 0;
    
    bool boolSetTemperature = false;
    bool boolGetStatus = false;
    bool boolSetHostflags = false;
    bool boolSendDeviceConfig = false;
    /******************************************************************************************
    *EXTERNAL VARIABLES
    *
    *******************************************************************************************/
    extern bool boolReady;
    extern bool boolMCUInterrupt;
    extern bool boolSetCommand;
    extern uint8_t ui8SendDeviceConfig[BUFFER_SIZE];
    
    extern App_tsEventUart sAppUartEvent;
    extern E_StateMachineThermostat e_StateMachineThermostat;
    /******************************************************************************************
    *FUNCTIONS 
    *
    *******************************************************************************************/
    /* Declare attribute list for Basic cluster. */
    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);
    
    /* Declare attribute list for Identify cluster. */
    ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list,
                                        &m_dev_ctx.identify_attr.identify_time);
    
    /**power attributes**/
    ZB_ZCL_DECLARE_POWER_CONFIG_BATTERY_ATTRIB_LIST_EXT(power_config_attr_list,
                                            &m_dev_ctx.power_attr.battery_voltage,
                                            &m_dev_ctx.power_attr.battery_size,
                                            &m_dev_ctx.power_attr.battery_quantity,
                                            &m_dev_ctx.power_attr.battery_rated_voltage,
                                            &m_dev_ctx.power_attr.battery_alarm_mask,
                                            &m_dev_ctx.power_attr.battery_voltage_min_threshold,
                                            &m_dev_ctx.power_attr.battery_percentage_remaining,
                                            &m_dev_ctx.power_attr.battery_voltage_threshold1,
                                            &m_dev_ctx.power_attr.battery_voltage_threshold2,
                                            &m_dev_ctx.power_attr.battery_voltage_threshold3,
                                            &m_dev_ctx.power_attr.battery_percentage_min_threshold,
                                            &m_dev_ctx.power_attr.battery_percentage_threshold1,
                                            &m_dev_ctx.power_attr.battery_percentage_threshold2,
                                            &m_dev_ctx.power_attr.battery_percentage_threshold3,
                                            &m_dev_ctx.power_attr.battery_alarm_state);
    
    ZB_ZCL_DECLARE_TIME_ATTRIB_LIST(time_attr_list,
                                    &m_dev_ctx.time_attr.timeId,
                                    &m_dev_ctx.time_attr.time_status,
                                    &m_dev_ctx.time_attr.time_zone,
                                    &m_dev_ctx.time_attr.dst_start,
                                    &m_dev_ctx.time_attr.dst_end,
                                    &m_dev_ctx.time_attr.dst_shift,
                                    &m_dev_ctx.time_attr.standard_time,
                                    &m_dev_ctx.time_attr.local_time,
                                    &m_dev_ctx.time_attr.last_settime,
                                    &m_dev_ctx.time_attr.valid_untilTime);
    
    /* Declare extended attribute list for Thermostat cluster. */
    ZB_ZCL_DECLARE_THERMOSTAT_ATTRIB_LIST_EXT(thermostat_attr_list,
                                              &m_dev_ctx.thermostat_attr.local_temperature,
                                              &m_dev_ctx.thermostat_attr.local_temperature_calibration,
                                              &m_dev_ctx.thermostat_attr.occupied_heating_setpoint,
                                              &m_dev_ctx.thermostat_attr.unoccupied_heating_setpoint,
                                              &m_dev_ctx.thermostat_attr.pi_heating_demand,
                                              &m_dev_ctx.thermostat_attr.min_heating_setpoint_limit,
                                              &m_dev_ctx.thermostat_attr.max_heating_setpoint_limit,
                                              &m_dev_ctx.thermostat_attr.remote_sensing,
                                              &m_dev_ctx.thermostat_attr.control_seq_of_operation,
                                              &m_dev_ctx.thermostat_attr.system_mode,
                                              &m_dev_ctx.thermostat_attr.trv_mode,
                                              &m_dev_ctx.thermostat_attr.set_valve_position,
                                              &m_dev_ctx.thermostat_attr.error,
                                              &m_dev_ctx.thermostat_attr.current_setpoint,
                                              &m_dev_ctx.thermostat_attr.host_flags);
    
    /* Declare cluster list for Thermostat device (Basic, Identify, Thermostat, Fan Control, Thermostat UI). */
    ZB_DECLARE_CUSTOM_THERMOSTAT_CLUSTER_LIST(thermostat_clusters,
                                          basic_attr_list,
                                          identify_attr_list,
                                          power_config_attr_list,
                                          thermostat_attr_list,
                                          time_attr_list);
    
    
    ZB_HA_DECLARE_CUSTOM_THERMOSTAT_EP(thermostat_ep,
                                   THERMOSTAT_SENSOR_ENDPOINT,
                                   thermostat_clusters);
    
    ZB_HA_DECLARE_CUSTOM_THERMOSTAT_CTX(thermostat_ctx, thermostat_ep);
    
    /**@brief Function for initializing the application timer.
     */
    static void timer_init(void)
    {
        uint32_t error_code = app_timer_init();
        APP_ERROR_CHECK(error_code);
    }
    
    /**@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 Function for initializing all clusters attributes.
    */
    static void thermostat_clusters_attr_init(void)
    {
         /* Basic cluster attributes data */
         m_dev_ctx.basic_attr.zcl_version = ZB_ZCL_VERSION;
         m_dev_ctx.basic_attr.app_version = THERMOSTAT_INIT_BASIC_APP_VERSION;
         m_dev_ctx.basic_attr.stack_version = THERMOSTAT_INIT_BASIC_STACK_VERSION;
         m_dev_ctx.basic_attr.hw_version = THERMOSTAT_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,
                              THERMOSTAT_INIT_BASIC_MANUF_NAME,
                              ZB_ZCL_STRING_CONST_SIZE(THERMOSTAT_INIT_BASIC_MANUF_NAME));
    
          ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.model_id,
                              THERMOSTAT_INIT_BASIC_MODEL_ID,
                              ZB_ZCL_STRING_CONST_SIZE(THERMOSTAT_INIT_BASIC_MODEL_ID));
    
          ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.date_code,
                              THERMOSTAT_INIT_BASIC_DATE_CODE,
                              ZB_ZCL_STRING_CONST_SIZE(THERMOSTAT_INIT_BASIC_DATE_CODE));
    
          m_dev_ctx.basic_attr.power_source = THERMOSTAT_INIT_BASIC_POWER_SOURCE;
    
          ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.location_id,
                              THERMOSTAT_INIT_BASIC_LOCATION_DESC,
                              ZB_ZCL_STRING_CONST_SIZE(THERMOSTAT_INIT_BASIC_LOCATION_DESC));
    
    
          m_dev_ctx.basic_attr.ph_env = THERMOSTAT_INIT_BASIC_PH_ENV;
          //m_dev_ctx.basic_attr.sw_ver = "00000000";
          memcpy( m_dev_ctx.basic_attr.sw_ver,"00000000", 8);
        
        /* Identify cluster attributes data */
        m_dev_ctx.identify_attr.identify_time        = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;
    
    //    /**power configuration attributes data**/
        m_dev_ctx.power_attr.battery_percentage_remaining = 0x02;
        m_dev_ctx.power_attr.battery_quantity = ZB_POWER_CONFIG_BATTERY_QUANTITY;
        m_dev_ctx.power_attr.battery_size = ZB_ZCL_POWER_CONFIG_BATTERY_SIZE_AA;
    
       /* Thermostat cluster attributes data */
        m_dev_ctx.thermostat_attr.local_temperature             = 0x07D0;
        m_dev_ctx.thermostat_attr.local_temperature_calibration = 0x00;
        m_dev_ctx.thermostat_attr.pi_heating_demand             = 0xFF;
        m_dev_ctx.thermostat_attr.occupied_heating_setpoint     = 0x07D0;
        m_dev_ctx.thermostat_attr.unoccupied_heating_setpoint   = 0x07D0;
        m_dev_ctx.thermostat_attr.min_heating_setpoint_limit    = 0x01F4;
        m_dev_ctx.thermostat_attr.max_heating_setpoint_limit    = 0x0BB8;
        m_dev_ctx.thermostat_attr.control_seq_of_operation      = ZB_ZCL_THERMOSTAT_CONTROL_SEQ_OF_OPERATION_HEATING_ONLY;
        m_dev_ctx.thermostat_attr.system_mode                   = ZB_ZCL_THERMOSTAT_SYSTEM_MODE_HEAT;
        m_dev_ctx.thermostat_attr.current_setpoint             = 0x0898;
        m_dev_ctx.thermostat_attr.trv_mode                     = ZB_ZCL_THERMOSTAT_TRV_MODE_DEFAULT_VALUE;
        m_dev_ctx.thermostat_attr.set_valve_position           = 0;
        m_dev_ctx.thermostat_attr.error                        = 0;
    
             /***time cluster attributes data**/
        m_dev_ctx.time_attr.timeId = ZB_ZCL_TIME_TIME_DEFAULT_VALUE;
        m_dev_ctx.time_attr.time_status = ZB_ZCL_TIME_TIME_STATUS_DEFAULT_VALUE;
    
        /*local temperature set attribute**/
       ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT,
                            ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                            ZB_ZCL_CLUSTER_SERVER_ROLE,
                            ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID,
                            (zb_uint8_t *)&m_dev_ctx.thermostat_attr.local_temperature,
                            ZB_FALSE);
     
        ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT,
                            ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                            ZB_ZCL_CLUSTER_SERVER_ROLE,
                            ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID,
                            (zb_uint8_t *)&m_dev_ctx.thermostat_attr.occupied_heating_setpoint,
                            ZB_FALSE);
    
        ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT,
                            ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                            ZB_ZCL_CLUSTER_SERVER_ROLE,
                            ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID,
                            (zb_uint8_t *)&m_dev_ctx.thermostat_attr.unoccupied_heating_setpoint,
                            ZB_FALSE);
    
        ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT, 
                             ZB_ZCL_CLUSTER_ID_THERMOSTAT, 
                             ZB_ZCL_CLUSTER_SERVER_ROLE, 
                             ZB_ZCL_ATTR_THERMOSTAT_HOST_FLAG_ID, 
                             (zb_uint8_t *)&m_dev_ctx.thermostat_attr.host_flags, 
                             ZB_FALSE);
    
        ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT, 
                             ZB_ZCL_CLUSTER_ID_THERMOSTAT, 
                             ZB_ZCL_CLUSTER_SERVER_ROLE, 
                             ZB_ZCL_ATTR_THERMOSTAT_TRV_MODE_ID, 
                             (zb_uint8_t *)& m_dev_ctx.thermostat_attr.trv_mode, 
                             ZB_FALSE);
    
       /**Battery percentage value**/
       ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT,
                            ZB_ZCL_CLUSTER_ID_POWER_CONFIG,
                            ZB_ZCL_CLUSTER_SERVER_ROLE,
                            ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_REMAINING_ID,
                            (zb_uint8_t *)&m_dev_ctx.power_attr.battery_percentage_remaining,
                            ZB_FALSE);  
                                      
       ZB_ZCL_SET_ATTRIBUTE(THERMOSTAT_SENSOR_ENDPOINT,
                            ZB_ZCL_CLUSTER_ID_POWER_CONFIG,
                            ZB_ZCL_CLUSTER_SERVER_ROLE,
                            ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_QUANTITY_ID,
                            (zb_uint8_t *)&m_dev_ctx.power_attr.battery_quantity,
                            ZB_FALSE);
    }
    
    /**@brief Function for local temperature
     *
     * @param[in]   new_value local temp value
     */
    void localTemperatureValue(zb_uint16_t ui16local_tempvalue)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT, 
                                         ZB_ZCL_CLUSTER_ID_THERMOSTAT, 
                                         ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                         ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_ID, 
                                         (zb_uint8_t *)&ui16local_tempvalue , 
                                         ZB_FALSE);
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set local temperature value fail. zcl_status: %d", zcl_status);
       }
    }
    void CurrentSetpointChangeValue(zb_uint16_t ui16CurrentSetpoint)
    {
       zb_zcl_status_t zcl_status;
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_CURRENT_SETPOINT_CHANGE_ID,
                                        (zb_uint8_t *)&ui16CurrentSetpoint,
                                        ZB_FALSE);
       
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Setc current set point temperature value fail. zcl_status: %d", zcl_status);
       }
    
       
       if(ui16CurrentSetpoint != 0xFFFF)
       {
          ui16CurrentTemp = ui16CurrentSetpoint;
       }
       else
       {
          ui16CurrentTemp = 0xFFFF;
       }
    
    }
    
    /**
    **function to read/write the occupied heating setpoint 
    **Any change in occupied heating value will automatically copied to set point change attribute
    **
    **/
    void OccupiedHeatingSetpoint(zb_uint16_t ui16OccupiedSetpoint)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID,
                                        (zb_uint8_t *)&ui16OccupiedSetpoint,
                                        ZB_FALSE);
       
         
       if(ui16OccupiedSetpoint != 0xFFFF)
       {
          ui16OccupiedHeatSetpoint = ui16OccupiedSetpoint;
          ui16CurrentTemp = ui16OccupiedSetpoint;
          CurrentSetpointChangeValue(ui16CurrentTemp);
       }
       else
       {
          ui16OccupiedHeatSetpoint == 0xFFFF;
       }
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set occupied heating setpoint temperature value fail. zcl_status: %d", zcl_status);
       }
    }
    
    void ReadOccupiedHeatingSetpoint(zb_uint16_t ui16ReadOccupiedSetpoint)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID,
                                        (zb_uint8_t *)&ui16ReadOccupiedSetpoint,
                                        ZB_FALSE);
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set occupied heating setpoint temperature value fail. zcl_status: %d", zcl_status);
       }
    }
    /**
    **function to read/write the unoccupied heating setpoint 
    **Any change in unoccupied heating value will automatically copied to set point change attribute
    **
    **/
    void UnOccupiedHeatingSetpoint(zb_uint16_t ui16UnOccupiedSetpoint)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID,
                                        (zb_uint8_t *)&ui16UnOccupiedSetpoint,
                                        ZB_FALSE);
       
       if(ui16UnOccupiedSetpoint != 0xFFFF)
       {
         ui16UnOccupiedHeatSetpoint = ui16UnOccupiedSetpoint;
         ui16CurrentTemp = ui16UnOccupiedSetpoint;
         CurrentSetpointChangeValue(ui16CurrentTemp);
       }
       else
       {
         ui16UnOccupiedHeatSetpoint =  0xFFFF;
       }
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set unoccupied heating setpoint temperature value fail. zcl_status: %d", zcl_status);
       }
    }
    
    /**
    **function to read value of pi heating demand
    **Any change in valve position value will be copied to PI heating demand attribute which only read attribute
    **
    **/
    static void PIHeatingDemand (zb_uint8_t ui8PiHeatingDemand)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_PI_HEATING_DEMAND_ID,
                                        &ui8PiHeatingDemand,
                                        ZB_FALSE);
       
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("read pi heating demand value fail. zcl_status: %d", zcl_status);
       }
    }
    /**
    **function for read/write local temperature calibration
    **Any change in local temperature attribute then add this value to D11 and D12 of set temperature command
    **
    **/
    static void LocalTemperatureCalibration(zb_uint8_t ui8localTempCalibration)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID,
                                        &ui8localTempCalibration,
                                        ZB_FALSE);
       
       ui8LocalTemperatureCalibration = ui8localTempCalibration;
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("local temperature calibration value fail. zcl_status: %d", zcl_status);
       }
    }
    /**
    **function to read/write the valve position
    **Any change in valve position value will be copied to PI heating demand attribute which only read attribute
    **
    **/
    void SetValvePosition(zb_uint8_t ui8ValvePosition)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_SET_VALVE_POSITION_ID,
                                        &ui8ValvePosition,
                                        ZB_FALSE);
       
       PIHeatingDemand(ui8ValvePosition);
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set valve position value fail. zcl_status: %d", zcl_status);
       }
    }
    
    void SetTRVMode (zb_uint8_t ui8TRVMode)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT,
                                        ZB_ZCL_CLUSTER_ID_THERMOSTAT,
                                        ZB_ZCL_CLUSTER_SERVER_ROLE,
                                        ZB_ZCL_ATTR_THERMOSTAT_TRV_MODE_ID,
                                        &ui8TRVMode,
                                        ZB_FALSE);
       
       
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set trv mode value fail. zcl_status: %d", zcl_status);
       }
    }
    /**@brief Function for remaining battery percentage 
     *
     * @param[in]   new_value local temp value
     */
    void ReadRemainigBatteryPercentage(zb_uint8_t ui8BatteryPercentage)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT, 
                                         ZB_ZCL_CLUSTER_ID_POWER_CONFIG, 
                                         ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                         ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_REMAINING_ID, 
                                         &ui8BatteryPercentage , 
                                         ZB_FALSE);
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Set Battery percentage value fail. zcl_status: %d", zcl_status);
       }
    }
    /**
    **function to read the error status for different valve status 
    **Any change in valve status respective error state copied to Error attribute which is read only attribute
    **
    **/
    void ReadErrorStatus(zb_uint8_t ui8ErrorStatus)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT, 
                                         ZB_ZCL_CLUSTER_ID_THERMOSTAT, 
                                         ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                         ZB_ZCL_ATTR_THERMOSTAT_ERROR_ID, 
                                         &ui8ErrorStatus , 
                                         ZB_FALSE);
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("read error status fail. zcl_status: %d", zcl_status);
       }
    }
    /**
    **function to read/write the flag status for different operation 
    **
    **
    **/
    void HostFlagStatus(zb_uint32_t ui32HostFlagsStatus)
    {
       zb_zcl_status_t zcl_status;
    
       zcl_status = zb_zcl_set_attr_val(THERMOSTAT_SENSOR_ENDPOINT, 
                                         ZB_ZCL_CLUSTER_ID_THERMOSTAT, 
                                         ZB_ZCL_CLUSTER_SERVER_ROLE, 
                                         ZB_ZCL_ATTR_THERMOSTAT_HOST_FLAG_ID, 
                                         (zb_uint8_t *)&ui32HostFlagsStatus, 
                                         ZB_FALSE);
       ui32HostflagsData = ui32HostFlagsStatus;
    
        //Rotate LCD by 180
        if((ui32HostflagsData & 0x000002)== 0x02)
        {    
          boolSetHostflags = false;
    
          boolSendDeviceConfig = true;
          if((ui8SendDeviceConfig[5] ^ DEVICE_CONFIG_BYTE_3_LCD_ROTATION) & DEVICE_CONFIG_BYTE_3_LCD_ROTATION ) 
          {
            ui8SendDeviceConfig[5] |= DEVICE_CONFIG_BYTE_3_LCD_ROTATION;        
          }
        }
        //LCD in default position
        if((ui32HostflagsData ^ 0x000002) & 0x02 )
        {
          boolSetHostflags = false;
          boolSendDeviceConfig = true;
          if(ui8SendDeviceConfig[5]  & DEVICE_CONFIG_BYTE_3_LCD_ROTATION) 
          {
            ui8SendDeviceConfig[5]  &= ui8SendDeviceConfig[5] ^ DEVICE_CONFIG_BYTE_3_LCD_ROTATION;		        
          }
        }
    
       if(zcl_status != ZB_ZCL_STATUS_SUCCESS)
       {
          NRF_LOG_INFO("Host flag status fail. zcl_status: %d", zcl_status);
       }
    }
    
    /**@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)
    {
        zb_uint16_t                cluster_id;
        zb_uint16_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)
                 {
                      if (attr_id == ZB_ZCL_ATTR_THERMOSTAT_OCCUPIED_HEATING_SETPOINT_ID)
                      {
                          zb_int16_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data16;
                          OccupiedHeatingSetpoint(value);
                           boolSetTemperature = true;
                           boolReady = true;
                           boolMCUInterrupt = false; 
                          
                      }
                      else if (attr_id == ZB_ZCL_ATTR_THERMOSTAT_UNOCCUPIED_HEATING_SETPOINT_ID)
                      {
                          zb_int16_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data16;
                          UnOccupiedHeatingSetpoint(value);
                           boolSetTemperature = true;
                           boolReady = true;
                           boolMCUInterrupt = false; 
                         
                      }
                      else if (attr_id ==ZB_ZCL_ATTR_THERMOSTAT_CURRENT_SETPOINT_CHANGE_ID)
                      {
                          zb_int16_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data16;
                          CurrentSetpointChangeValue(value);
                           boolSetTemperature = true;
                           boolReady = true;
                           boolMCUInterrupt = false; 
                           
                      }
                      else if(attr_id ==ZB_ZCL_ATTR_THERMOSTAT_LOCAL_TEMPERATURE_CALIBRATION_ID)
                      {
                          zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;
                          LocalTemperatureCalibration(value);
                      }
                      else if (attr_id ==ZB_ZCL_ATTR_THERMOSTAT_SET_VALVE_POSITION_ID)
                      {
                          zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;
                          SetValvePosition(value);
                      }
                      else if(attr_id == ZB_ZCL_ATTR_THERMOSTAT_HOST_FLAG_ID)
                      {
                         zb_uint32_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data32;
                         HostFlagStatus(value);
                         boolSetHostflags  = true; 
                         boolReady = true;
                         boolMCUInterrupt = false; 
                      }
                      else if(attr_id == ZB_ZCL_ATTR_THERMOSTAT_TRV_MODE_ID)
                      {
                         zb_uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;
                         SetTRVMode(value);
                      }
                 }
                  
              break;
    
    
            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)
    {
        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;
                    boolGetStatus = 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_COMMON_SIGNAL_CAN_SLEEP:
                {
                    zb_sleep_now(); //when receiving the signal ZB_COMMON_SIGNAL_CAN_SLEEP call sleep_now()
                }
                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);
        }
    }
    
    
    /**@brief Function for application main entry.
     */
    void main(void)
    {
        zb_ret_t       zb_err_code;
        zb_ieee_addr_t ieee_addr;
    
        nrf_delay_ms(1500);
    
        /* Initialize logging system and GPIOs. */
        timer_init();
        log_init();
    
        leds_init();
    
        Uart_Init_Func();    
    
        timer_config_func();
    
        ulp_input_pin_configuration();
     
        Flashinitialization();
    
        /* 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("thermostat");
    
        /* 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_ed_role(IEEE_CHANNEL_MASK);
        zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
    
        zb_set_ed_timeout(ED_AGING_TIMEOUT_64MIN);
        zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));
        zb_set_rx_on_when_idle(ZB_FALSE); // This enables sleepy behavior and makes your device act as a Sleepy End Device.
    
        zb_set_node_descriptor_manufacturer_code(ZB_ZCL_MANF_CODE);
    
        /* Initialize application context structure. */
        UNUSED_RETURN_VALUE(ZB_MEMSET(&m_dev_ctx, 0, sizeof(m_dev_ctx)));
    
        /* Register callback for handling ZCL commands. */
        ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);
    
        /* Register thermostat device context (endpoints). */
        ZB_AF_REGISTER_DEVICE_CTX(&thermostat_ctx);
    
        thermostat_clusters_attr_init();
        /** Start Zigbee Stack. */
        zb_err_code = zboss_start();
        ZB_ERROR_CHECK(zb_err_code);   
         
       
        CommandBootloader();  //get bootloader command 
    
        while(1)
        {
           zboss_main_loop_iteration();
           UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
    
            CommunicationStateExecution();   //MCU and NP communication state     
            DataProcessing();                //Flag bit processing
            UARTStateStateMachine();    
        }
    }
    
    
    /**
     * @}
     */
    

    Also, below snippet is regarding erasing bonding info. The snippet present in attached  uart_statemachin.c file. Let me know if I followed anything wrong here to erase info.

                  //Master reset is executed
                  if(ui8GetFlagBuffer[2] & FLAGS_BYTE_2_MASTER_RESET_REQUEST)
                  {
    //                boolReady = false; //set flag to execute communication state
    //                boolIsMCURequest = true;
                    zigbee_erase_persistent_storage(ZB_TRUE);  //erase bonding info or leave network
                  }

    /******************************************************************************
     uart_statemachine.c - uart state machine source file for communication
     Version: 0.9.1
     Created on: 21/05/2021
     Created by: Rohit Rajapure
    
     Copyright (c) 2017 Shalaka Connected Devices LLP.  All rights reserved.
     Software License Agreement
    
       Redistribution and use in source and binary forms, with or without
       modification, are not permitted.
    
       Redistributions of source code must retain the above copyright
       notice, this list of conditions and the following disclaimer.
    
       Redistributions in binary form 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.
    
       Neither the name of Shalaka Connected Devices LLP nor the names of
       its contributors may be used to endorse or promote products derived
       from this software without specific prior written permission.
    
     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     OWNER 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 <stdbool.h>
    #include <stdint.h>
    #include <stdio.h>
    #include "stdlib.h"
    #include "string.h"
    #include "zigbee_helpers.h"
    #include "app_uart.h"
    #include "app_error.h"
    #include "nrf_delay.h"
    #include "nrf.h"
    
    #include "uart_config.h"
    #include "gpio_config.h"
    #include "timer_config.h"
    #include "uart_statemachine.h" 
    #include "commands.h"
    #include "app_rtc.h"
    #include "zb_custom1_thermostat.h"
    #include "custom_app_event.h"
    
    /*******************************************************************************************
    *MACROS
    *
    *******************************************************************************************/
    
    /******************************************************************************************
    *TYPEDEFS
    *
    *******************************************************************************************/
    State CurrentState, PreviousState;
    
    State CurrentState = State_Ready;
    
    E_StateMachine e_StateMachine;
    E_StateMachineThermostat e_StateMachineThermostat;
    
    E_StateMachine e_StateMachine = IDLE_STATE;
    E_StateMachineThermostat e_StateMachineThermostat = POWER_CYCLE;
    
    App_tsEventUart sAppUartEvent;
    App_tsEventBootloader sAppBootloaderEvent;
    App_tsEventProduction sAppProductionEvent;
    
    /******************************************************************************************
    *EXTERNAL VARIABLES
    *
    *******************************************************************************************/
    
    extern bool boolReady;
    extern bool boolSetTemperature;
    extern uint8_t ui8GetCommandBuffer[BUFFER_SIZE], ui8SetCommandBuffer[BUFFER_SIZE],ui8SendDeviceConfig[BUFFER_SIZE], ui8GetFlagBuffer[BUFFER_SIZE], ui8ResponceValueSend[BUFFER_SIZE], ui8ResponceValueSend2[BUFFER_SIZE], ui8StartFirmwareUpdate[BUFFER_SIZE], ui8TransferFirmware[BUFFER_SIZE], ui8TempGetFlagBuffer[BUFFER_SIZE];
    extern bool boolGetStatus;
    extern bool boolSetHostflags;
    extern uint32_t ui32HostflagsData;
    extern bool boolSendDeviceConfig;
    /******************************************************************************************
    *LOCAL VARIABLES
    *
    *******************************************************************************************/
    uint8_t ui8ReadGetFlagBuffer[BUFFER_SIZE] = {0};
    uint8_t ui8SetpointChange[SET_POINT_CHANGE_BUFFER] = {0}; //store set point change value into buffer
    uint8_t ui8BatteryStatus[4] = {0};
    uint8_t ui8ValvePositionChange[2] = {0};
    uint8_t ui8FirmwareVersion[26] = {0};
    uint8_t ui8DeviceConfigData[6] = {0};
    uint8_t ui8GetBootloaderStatus[2] = {0};
    uint8_t ui8Rx = 0, ui8RxIndex =0, ui8Index =0;
    uint16_t ui16LocalTemperature = 0, ui16SetPointChange = 0, ui16UnOccupiedTemp = 0, ui16OccupiedTemp = 0;
    uint8_t ui8TelegramRepeatCount = 0;
    uint32_t ui32ReadHostFlagsByte = 0;
    uint32_t ui32CurrentVersion[6] = {0};
    
    char u8CurrentRFVersionString[] = "";
    char u32CurrentVersionString[] = "";
    
    uint16_t  ui16BatteryVoltage = 0;
    float flBatteryPercentage = 0.0;
    
    
    uint16_t ui16SaveAttributeID;
    uint8_t ui8TrvModeBackup;
    bool StartFrimwareUpdateTimer = false;
    
    static uint32_t ui32HostImageStartAddress;
    static uint32_t ui32HostImageEndAddress;
    bool boolSetCommand = false;
    bool boolIsMCURequest = false; //this flag is general to send getflag command whenever requried. So, set this flag accordingly.
    bool boolMCUInterrupt = false;
    bool FirmwareUpdateTransferFinished  = false;
    /******************************************************************************************
    *BOOLEAN VARIABLES FOR GETFLAG COMMANDS
    *
    *******************************************************************************************/
    //Data 01
    bool boolManualMode = false; 
    bool boolHeatingMode = false;
    bool boolKeyProtection = false;
    bool boolInternalWindowOpen = false;
    bool boolExternalWindowOpen = false;
    bool boolRTCInValid = false;
    bool boolBatteryWeak = false;
    bool boolHolidayMode = false;
    //Data 02
    bool boolEncoderChange = false;
    bool boolSetPointChange = false;
    bool boolMasterResetRequest = false;
    bool boolMeasuredTempChange = false;
    bool boolMasterResetChange = false;
    bool boolBoostModeActive = false;
    bool boolProductModeRF = false;
    bool boolValvePositionChange = false;
    //Data 03
    bool boolButton1Push = false;
    bool boolButton2Push = false;
    bool boolButton3Push = false;
    bool boolButton4Push = false;
    bool boolButton5Push = false;
    bool boolButtonShortPush = false;
    bool boolButtonLongPush = false;
    bool boolButtonVeryLongpush = false;
    //Data 04
    bool boolADAPSuccess = false;
    bool boolErrorE1State = false;
    bool boolErrorE2State = false;
    bool boolErrorE3State = false;
    bool boolPrepMode = false;
    bool boolINST = false;
    bool boolADAP = false;
    bool boolADAPNotValid = false;
    //Data 05
    bool boolPairRequest = false;
    bool boolUnPairRequest = false;
    bool boolPairTimeOut = false;
    bool boolDevicePairState = false;
    
    /******************************************************************************************
    *FUNCTIONS
    *
    *******************************************************************************************/
    
    
    /******************************************************************************************
    *function for communication state handling between MCU and Network processor 
    *(this function used to execute the state machine between Radiator and nRF node)
    *return void
    *******************************************************************************************/
    
    void CommunicationStateExecution(void)
    {
       while(boolReady)
       {
           switch(CurrentState)
           {
            case State_Ready:
                    PreviousState = CurrentState;   //if interrupt on ULP switch state to command
                    CurrentState  = State_Command;
                    ui8TelegramRepeatCount =0;
            break;
    
            case State_Command: 
                  ulp_pin_transaction();  //ULP pin toggle configuration and high for 5msec
                  //send get flag telegram message to device 
                  if(!boolIsMCURequest)
                  {
                     GetMessageIdResponse(GET_FLAGS); 
                    
                  }
                 
                  Uart_PutData(ui8GetCommandBuffer,sizeof(ui8GetCommandBuffer));           
    
                  PreviousState = CurrentState;   //after command sent switch state to read ACK
                  CurrentState  = State_ACKRead;
            break;
    
            case State_ACKRead: 
                  //after get flag read ACK and send EOC 
                  Uart_GetByte(&ui8Rx);
                  if((ui8Rx ==RESP_ACK) && (boolSetCommand == true))
                  {                      
                      
                      ui8TelegramRepeatCount =0;
                      boolSetCommand = false;
                      PreviousState = CurrentState;   //if EOC and Set command then switch to state Set_Command
                      CurrentState  = State_SetCommand;
                  }
                  else if((ui8Rx ==RESP_ACK) && (boolSetTemperature == true))
                  {          
                      
                      ui8TelegramRepeatCount =0;                  
                      PreviousState = CurrentState;   //if EOC and Set command then switch to state Set_Command
                      CurrentState  = State_SetCommand;
                  }
                  else if((ui8Rx ==RESP_ACK) && (boolSetHostflags == true))
                  {
                    
                    ui8TelegramRepeatCount =0;                       
                    PreviousState = CurrentState;   //if EOC and Set command then switch to state Set_Command
                    CurrentState  = State_SetCommand;
                  }
                  else if((ui8Rx ==RESP_ACK) && (boolSendDeviceConfig == true))
                  {
                    
                    ui8TelegramRepeatCount =0;                       
                    PreviousState = CurrentState;   //if EOC and Set command then switch to state Set_Command
                    CurrentState  = State_SetCommand;
                  }
                  else if(ui8Rx ==RESP_ACK)
                  {                 
                   
                    ui8TelegramRepeatCount =0;                       
                    PreviousState = CurrentState;   //after EOC read switch state to send EOC 
                    CurrentState  = State_SendEOC;
                  }
                  //if statement to check NACK response and perform the repeatation action 
                  if(ui8Rx == RESP_NACK)
                  {
                     ui8TelegramRepeatCount++;
    
                     if(ui8TelegramRepeatCount == 3)
                     {
                         PreviousState = CurrentState;   //After command repeatation is done for 3 times switch state to Ready state
                         CurrentState  = State_Ready;
                         ui8TelegramRepeatCount =0;
                         boolReady = false;
                     }
                     else
                     {
                         //if NACK then repeat the command for 3 time.
                         CurrentState  = PreviousState;
                     }
                  }
    
                  if(ui8Rx == RESP_TNS)
                  {
                       PreviousState = CurrentState;   //After command repeatation if it not supportive command (TNS) then go to ready state
                       CurrentState  = State_Ready;
                       boolReady = false;
                  }
            break;
    
            case State_SendEOC:
                  Uart_PutByte(EOC);
                  
                  PreviousState = CurrentState;   //after EOC read switch state to read dummy ACK
                  CurrentState  = State_ACKReadDummy;
            break;
    
            case State_ACKReadDummy: 
                  //after get flag read ACK and send EOC 
                  Uart_GetByte(&ui8Rx);
                  if(ui8Rx ==RESP_ACK)
                  {   
                        
                        ui8TelegramRepeatCount =0;
                        PreviousState = CurrentState;   //after dummy ACK read switch state to read response data 
                        CurrentState  = State_ReadDataResponse;             
                  }
            break;
    
            case State_SetCommand:
                 if((!boolSetTemperature) && (!boolSetHostflags) && (!boolSendDeviceConfig))
                 {
                   SetFlags();  //send set flag command
                   
                   Uart_PutData(ui8SetCommandBuffer,sizeof(ui8SetCommandBuffer));
                   memset(ui8SetCommandBuffer,0,sizeof(ui8SetCommandBuffer)); 
                 }
                 else if((boolSetTemperature) && (!boolSetHostflags) && (!boolSendDeviceConfig))
                 {
                   SendSetTemperature();
                  
                   boolSetTemperature = false;   
                   Uart_PutData(ui8SetCommandBuffer,sizeof(ui8SetCommandBuffer));
                   memset(ui8SetCommandBuffer,0,sizeof(ui8SetCommandBuffer)); 
                 }
                 else if(boolSetHostflags)
                 {
                   UARTStateSendFlags();  
                   boolSetHostflags = false;
                   
                   Uart_PutData(ui8SetCommandBuffer,sizeof(ui8SetCommandBuffer));
                   memset(ui8SetCommandBuffer,0,sizeof(ui8SetCommandBuffer)); 
                 }
                 else if(boolSendDeviceConfig)
                 {
                     UARTStateSendDeviceConfig();          //send set device config command
                     boolSendDeviceConfig = false;
                    
                     Uart_PutData(ui8SendDeviceConfig,sizeof(ui8SendDeviceConfig));
                     memset(ui8SendDeviceConfig,0,sizeof(ui8SendDeviceConfig)); 
                 }
                  
    
                  PreviousState = CurrentState;   //after command sent switch state to read ACK
                  CurrentState  = State_ACKRead;
             break;
    
            case State_ReadDataResponse: 
                  //read command response from MCU             
                  Uart_GetByte(&ui8Rx);
                  if(ui8Rx == SYNC)
                  { 
                     
                     //read length of data
                     Uart_GetByte(&ui8Rx);
                     ui8RxIndex = ui8Rx;
    
                     GetFlagsResponse();   //store getflag data into buffer
    
                    // after data read send ACK to device 
                     Uart_PutByte(RESP_ACK);
    
                     PreviousState = CurrentState;   //after data read send ACK to device  switch state EOC  
                     CurrentState  = State_EOCRead;
    
                  }
            break;
    
            case State_EOCRead: 
                 //After data read from MCU check for EOC
                  Uart_GetByte(&ui8Rx);
                  if(ui8Rx ==EOC)
                  {                      
                    //send ACK back
                      Uart_PutByte(RESP_ACK);
                      PreviousState = CurrentState;   //all state executed then switch to ready state
                      CurrentState  = State_Ready;
                      boolReady = false; 
                      boolMCUInterrupt = true; 
                  }              
                  ResetFlags();
            break;
    
            default:
            break;
    
             
           }
       }
    }
    
    /******************************************************************************************
    *function for read the getflag bits and store into variable
    *return void
    *******************************************************************************************/
    void GetFlagsResponse (void)
    {
         for(ui8Index = 0; ui8Index< ui8RxIndex-2; ui8Index++)  //loop to store read get flag data into variable
         {
            //store data into buffer
            Uart_GetByte(&ui8Rx);
            ui8ReadGetFlagBuffer[ui8Index] = ui8Rx;
         }
         
    }
    
    
    /******************************************************************************************
    *This function is used to process the commands based on Id comparision.
    *return void
    *******************************************************************************************/
    void DataProcessing(void)
    {
       if(boolMCUInterrupt)
       {
           switch(ui8ReadGetFlagBuffer[0])
           {
              case GET_FLAGS:
                   memcpy(ui8GetFlagBuffer,ui8ReadGetFlagBuffer,sizeof(ui8ReadGetFlagBuffer));              
                   nrf_delay_ms(100);              
    //               DecodeFlags();
    //               ProcessFlags();
    
                    //Data 01 of flag byte
                   if(ui8GetFlagBuffer[1] & FLAGS_BYTE_1_MANU_MODE)
                   {
    //                  SetTRVMode(ZB_ZCL_THERMOSTAT_TRV_MODE_DEFAULT_VALUE);
                      m_dev_ctx.thermostat_attr.trv_mode = ZB_ZCL_THERMOSTAT_TRV_MODE_DEFAULT_VALUE;
                      m_dev_ctx.thermostat_attr.host_flags |= FLAGS_BYTE_1_MANU_MODE;
    //                  HostFlagStatus(ui32ReadHostFlagsByte);
                   }
    
                   if(ui8GetFlagBuffer[1] & FLAGS_BYTE_1_KEY_PROTECTION_ACTIVE)
                   {
                     m_dev_ctx.thermostat_attr.host_flags |= 0x000080;
    //                 HostFlagStatus(ui32ReadHostFlagsByte);
                   }
                   if((ui8GetFlagBuffer[1] ^ FLAGS_BYTE_1_KEY_PROTECTION_ACTIVE)& FLAGS_BYTE_1_KEY_PROTECTION_ACTIVE)
                   {
                     m_dev_ctx.thermostat_attr.host_flags &=m_dev_ctx.thermostat_attr.host_flags ^ 0x000080;
    //                 HostFlagStatus(ui32ReadHostFlagsByte);
                   }
    
                   if(ui8GetFlagBuffer[1] & FLAGS_BYTE_1_INT_WINDOW_TRIGGERD)
                   {
                      m_dev_ctx.thermostat_attr.host_flags |= START_INTERNAL_WINDOW_OPEN;
    //                  HostFlagStatus(ui32ReadHostFlagsByte);
                   }
                  if ((ui8GetFlagBuffer[1] ^ FLAGS_BYTE_1_INT_WINDOW_TRIGGERD)& FLAGS_BYTE_1_INT_WINDOW_TRIGGERD) 
                  {
                      m_dev_ctx.thermostat_attr.host_flags &= m_dev_ctx.thermostat_attr.host_flags ^ STOP_INTERNAL_WINDOW_OPEN;
    //                  HostFlagStatus(ui32ReadHostFlagsByte);
                  }
                  
                  if (ui8GetFlagBuffer[1] & FLAGS_BYTE_1_EXT_WINDOW_ACTIVATE) 
                  {      
                  // If the external window open detection is active, the same bit is set in the RF telegram as for the internal one.
                     m_dev_ctx.thermostat_attr.host_flags |= START_INTERNAL_WINDOW_OPEN;
    //                 HostFlagStatus(ui32ReadHostFlagsByte);
                  }
    
                  if (ui8GetFlagBuffer[1] & FLAGS_BYTE_1_BATTERY_WEAK) 
                  {  
    //                  ReadErrorStatus(BATTERY_WEAK_ERROR);
                      m_dev_ctx.thermostat_attr.error |= 0x01;
                      boolReady = true; //set flag to execute communication state
                      boolIsMCURequest = true;
                      e_StateMachineThermostat = RUNNING_STATE;
                      sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_BATTERY;
                  }
    
                  if((ui8GetFlagBuffer[1] ^ FLAGS_BYTE_1_BATTERY_WEAK) & FLAGS_BYTE_1_BATTERY_WEAK )
                  {                
    //                  ui32ReadHostFlagsByte &= ui32ReadHostFlagsByte ^ 0x01;
    //                  ReadErrorStatus(0);
                      m_dev_ctx.thermostat_attr.error &=  m_dev_ctx.thermostat_attr.error ^ 0x01;
                  }
    
                   //Data 02 of flag byte
                   //Query whether setpoint temperature has been changed
                  if (ui8GetFlagBuffer[2] & FLAGS_BYTE_2_SETPOINT_CHANGED) 
                  {
                      boolReady = true; //set flag to execute communication state
                      boolIsMCURequest = true;        
                      e_StateMachineThermostat = RUNNING_STATE;
                      sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_TEMPERATURE;
                  }
                  
                  //Master reset is executed
                  if(ui8GetFlagBuffer[2] & FLAGS_BYTE_2_MASTER_RESET_REQUEST)
                  {
    //                boolReady = false; //set flag to execute communication state
    //                boolIsMCURequest = true;
                    zigbee_erase_persistent_storage(ZB_TRUE);  //erase bonding info or leave network
                  }
                  //Has the ACTUAL temperature changed, a request is sent to the controller.
                  if(ui8GetFlagBuffer[2] & FLAGS_BYTE_2_MEASURED_TEMP_CHANGED)
                  {
                      boolReady = true; //set flag to execute communication state
                      boolIsMCURequest = true;        
                      e_StateMachineThermostat = RUNNING_STATE;
                      sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_TEMPERATURE;
                  }
    
                  if(ui8GetFlagBuffer[2] & FLAGS_BYTE_2_BOOST_MODE)
                  {
                    m_dev_ctx.thermostat_attr.host_flags |= 0x04;
    //                HostFlagStatus(ui32ReadHostFlagsByte);
                  }
    
                  if((ui8GetFlagBuffer[2] ^ FLAGS_BYTE_2_BOOST_MODE) & FLAGS_BYTE_2_BOOST_MODE) 
                  {
                    m_dev_ctx.thermostat_attr.host_flags &= m_dev_ctx.thermostat_attr.host_flags ^ 0x04; 
    //                HostFlagStatus(ui32ReadHostFlagsByte);       
                  }
    
                  if (ui8GetFlagBuffer[2] & FLAGS_BYTE_2_VALVE_POSITION_CHANGED)
                  {
                     boolReady = true; //set flag to execute communication state
                     boolIsMCURequest = true;
                     e_StateMachineThermostat = RUNNING_STATE;
                     sAppUartEvent.eType_UartNextState  = APP_E_EVENT_UART_GET_VALVE_POSITION;
                  }
    
                  //Data 04 flag byte
                  if(ui8GetFlagBuffer[4] == FLAGS_BYTE_4_ADAP_SUCCESSFUL)
                  {
                    ReadErrorStatus(NO_ERROR);
                  }
                  if((ui8GetFlagBuffer[4] & (0x07)) == FLAGS_BYTE_4_ERROR_E1)
                  {
                    ReadErrorStatus(VALVE_ADAPTATION_FAIL_E1);//Error ER1 Adaptation failed because not mounted
                  }
                  if((ui8GetFlagBuffer[4] & (0x07)) == FLAGS_BYTE_4_ERROR_E2)
                  {
                    ReadErrorStatus(VALVE_MOVEMENT_SLOW_E2); //Error ER2 adaptation failed because closing point not found
                  }
                  if((ui8GetFlagBuffer[4] & (0x07)) == FLAGS_BYTE_4_ERROR_E3)
                  {
                    ReadErrorStatus(VALVE_NOT_MOVING_E3); //Error ER3 adaptation failed because valve stroke too short or adaptation not possible
                  }
    
              break;
    
              case GET_BOOTLOADER_STATE:
                   memcpy(ui8GetBootloaderStatus,ui8ReadGetFlagBuffer,sizeof(ui8GetBootloaderStatus));
    
                   if(ui8GetBootloaderStatus[1] == 0x01)
                   {
                      e_StateMachineThermostat = BOOTLOADER_STATE;
                      sAppBootloaderEvent.eType_BootloaderState = APP_E_EVENT_UART_START_FIRMWARE_UPDATE;
    //                  sAppBootloaderEvent.eType_BootloaderState = APP_E_EVENT_UART_TRANSFER_FRIMWARE_UPDATE;
                   }
                   else if(ui8GetBootloaderStatus[1] == 0x00)
                   {
                      e_StateMachineThermostat = RUNNING_STATE;
                      sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_FIRMWARE_VERSION; // this state should execute only once when device starts 
                   }
                    boolIsMCURequest = false;
              break;
    
              case GET_TEMPERATURES:
                   memcpy(ui8SetpointChange,ui8ReadGetFlagBuffer,sizeof(ui8SetpointChange));
                  
                  ui16LocalTemperature = ui8SetpointChange[1] << 8;
                  ui16LocalTemperature = ui16LocalTemperature + ui8SetpointChange[2];
                  localTemperatureValue(ui16LocalTemperature);
    
                  ui16SetPointChange   = ui8SetpointChange[5] << 8;
                  ui16SetPointChange   = ui16SetPointChange + ui8SetpointChange[6];              
                  CurrentSetpointChangeValue(ui16SetPointChange);        
                  
                  ReadOccupiedHeatingSetpoint(ui16SetPointChange);  // When get temperature in requested copy the set point value on Occupied heating point id. 
    
                  boolIsMCURequest = false;
                  nrf_delay_ms(50);  
                  e_StateMachineThermostat = RUNNING_STATE;
                  sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_BATTERY;
    
              break;
    
              case GET_BATTERY_STATUS:
                   memcpy(ui8BatteryStatus, ui8ReadGetFlagBuffer,sizeof(ui8BatteryStatus));
                   //flBatteryPercentage = ((ui8BatteryStatus[1] * 100)/255);
                   vCalculateBattery(ui8BatteryStatus[1]);
    
    //               ui16BatteryVoltage = ui8BatteryStatus[2] << 8;    /**voltage calculation**/
    //               ui16BatteryVoltage = ui16BatteryVoltage + ui8BatteryStatus[3];
                  
                   boolIsMCURequest = false;
                    nrf_delay_ms(50); 
                    if(boolGetStatus)
                    {
                        boolGetStatus = false;
                        e_StateMachineThermostat = RUNNING_STATE;
                        sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_DEVICE_CONFIG; 
                    }
                    else
                    {
                        sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
                    }
              break;
    
              case GET_FIRMWARE_VER:
                   memcpy(ui8FirmwareVersion,ui8ReadGetFlagBuffer,sizeof(ui8FirmwareVersion));
                   ui32CurrentVersion[0] = (ui8FirmwareVersion[19] - 0x30)	* 100000; 
                   ui32CurrentVersion[1] = (ui8FirmwareVersion[20] - 0x30)	* 10000; 
                   ui32CurrentVersion[2] = (ui8FirmwareVersion[21] - 0x30)	* 1000; 
                   ui32CurrentVersion[3] = (ui8FirmwareVersion[22] - 0x30)	* 100; 
                   ui32CurrentVersion[4] = (ui8FirmwareVersion[23] - 0x30)	* 10; 
                   ui32CurrentVersion[5] = (ui8FirmwareVersion[24] - 0x30); 
                    
    //               itoa(m_dev_ctx.basic_attr.app_version,u8CurrentRFVersionString,8);
    //               itoa((int*)ui32CurrentVersion,u32CurrentVersionString,8);
    
    //               strcat(u8CurrentRFVersionString, u32CurrentVersionString);
    //
    //               memcpy(m_dev_ctx.basic_attr.sw_ver,u8CurrentRFVersionString, 8);
    
                   boolIsMCURequest = false;
                   nrf_delay_ms(25); 
                   e_StateMachineThermostat = RUNNING_STATE;
                   sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_DEVICE_CONFIG;
              break;
    
              case GET_DEVICE_CONFIG:
                   memcpy(ui8DeviceConfigData,ui8ReadGetFlagBuffer,sizeof(ui8DeviceConfigData));
                   
                   if(ui8DeviceConfigData[3] == DEVICE_CONFIG_BYTE_3_VALVE_CONTROLLER)
                   {
                      m_dev_ctx.thermostat_attr.trv_mode = 0x01;     //TRV position mode 
                   }
                   boolIsMCURequest = false;
                   nrf_delay_ms(25); 
                   sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
              break;
                   
    
              case GET_POSITION:
                   memcpy(ui8ValvePositionChange,ui8ReadGetFlagBuffer, sizeof(ui8ValvePositionChange));
                   SetValvePosition(ui8ValvePositionChange[1]);   //if valve position change then set valve and copy the data on pi heating demand attribute.
                   boolIsMCURequest = false;
              break;
              
    
              default:
              break;
           }
           memset(ui8ReadGetFlagBuffer,0,sizeof(ui8ReadGetFlagBuffer)); 
           boolMCUInterrupt = false;             
       }
    }
    
    /******************************************************************************************
    *function for read bit status change whenever any command process
    *return void
    *******************************************************************************************/
    void DecodeFlags (void)
    {
       
         //Data 01
         boolManualMode = (((ui8GetFlagBuffer[1] & MANUAL_MODE_BIT) !=0)? true:false);   //manual mode
    
         boolHeatingMode = (((ui8GetFlagBuffer[1] & HEATING_MODE_BIT) !=0) ? true: false);  //heating mode
    
         boolKeyProtection = (((ui8GetFlagBuffer[1] & KEY_PROTECTION_ACTIVE) !=0) ? true: false);  //key protection active
    
         boolInternalWindowOpen = (((ui8GetFlagBuffer[1] & INTERNAL_WINDOW_OPEN) !=0) ? true: false);  //internal window open
    
         boolExternalWindowOpen = (((ui8GetFlagBuffer[1] & EXTERNAL_WINDOW_OPEN) !=0) ? true: false);  //external window open
    
         boolRTCInValid = (((ui8GetFlagBuffer[1] & RTC_INVALID) !=0) ? true: false);  //rtc invalid
    
         boolBatteryWeak = (((ui8GetFlagBuffer[1] & BATTERY_WEAK) !=0) ? true: false);  //battery weak
    
         boolHolidayMode = (((ui8GetFlagBuffer[1] & HOLIDAY_MODE_ACTIVE) !=0) ? true: false);  //holiday mode active
    
         
         //Data 02
         boolEncoderChange = (((ui8GetFlagBuffer[2] & ENCODER_CHANGED) !=0) ? true: false);  //encoder change
    
         boolSetPointChange = (((ui8GetFlagBuffer[2] & SETPOINT_CHANGED_BIT) !=0) ? true: false);  //setpoint changed
    
         boolMasterResetRequest = (((ui8GetFlagBuffer[2] & MASTER_RESET_REQUEST) !=0) ? true: false);  //master reset request
    
         boolMeasuredTempChange = (((ui8GetFlagBuffer[2] & MEASURED_TEMPERATURE_CHANGE) !=0) ? true: false);  //measured temperature change
    
         boolMasterResetChange = (((ui8GetFlagBuffer[2] & MASTER_RESET_SUCCESS) !=0) ? true: false);  //master reset success
    
         boolBoostModeActive = (((ui8GetFlagBuffer[2] & BOOST_MODE_ACTIVE) !=0) ? true: false);  //boost mode active
    
         boolProductModeRF = (((ui8GetFlagBuffer[2] & PRODUCTION_MODE_RF) !=0) ? true: false);  //production mode
    
         boolValvePositionChange = (((ui8GetFlagBuffer[2] & VALVE_POSITION_CHANGE) !=0) ? true: false);  //valve position change
    
    
         //Data 03
         boolButton1Push = (((ui8GetFlagBuffer[3] & BUTTON_1_PUSH) !=0) ? true: false);  //button 1 push
    
         boolButton2Push = (((ui8GetFlagBuffer[3] & BUTTON_2_PUSH) !=0) ? true: false);  //button 2 push
    
         boolButton3Push = (((ui8GetFlagBuffer[3] & BUTTON_3_PUSH) !=0) ? true: false);  //button 3 push
    
         boolButton4Push = (((ui8GetFlagBuffer[3] & BUTTON_4_PUSH) !=0) ? true: false);  //button 4 push
    
         boolButton5Push = (((ui8GetFlagBuffer[3] & BUTTON_5_PUSH) !=0) ? true: false);  //button 5 push
    
         boolButtonShortPush = (((ui8GetFlagBuffer[3] & BUTTON_SHORT_PUSH) !=0) ? true: false);  //button short push
    
         boolButtonLongPush = (((ui8GetFlagBuffer[3] & BUTTON_LONG_PUSH) !=0) ? true: false);  //button long push
    
         boolButtonVeryLongpush = (((ui8GetFlagBuffer[3] & BUTTON_VERY_LONG_PUSH) !=0) ? true: false);  //button very long push
         
         
         //Data 04
         boolADAPSuccess = (((ui8GetFlagBuffer[4] & ADAP_SUCCESSFUL) !=0) ? true: false);  //ADAP success
    
         boolErrorE1State = (((ui8GetFlagBuffer[4] & VALVE_ERROR_E1) !=0) ? true: false);  //valve error 1
    
         boolErrorE2State = (((ui8GetFlagBuffer[4] & MACHANICAL_FAIL_ERROR_E2) !=0) ? true: false);  //machanical fail error 2
    
         boolErrorE3State = (((ui8GetFlagBuffer[4] & VALVE_TRAVEL_SHORT_ERROR_E3) !=0) ? true: false);  //valve travel short error 3
    
         boolPrepMode = (((ui8GetFlagBuffer[4] & PREP_MOUNTING_POSITION) !=0) ? true: false);  //prep mounting position
    
         boolINST = (((ui8GetFlagBuffer[4] & INST_MOUNTING_POSITION) !=0) ? true: false);  //INST_MOUNTING_POSITION
    
         boolADAP = (((ui8GetFlagBuffer[4] & ADAP_VALVE_PROGRESS) !=0) ? true: false);  //ADAP_VALVE_PROGRESS
      
         boolADAPNotValid = (((ui8GetFlagBuffer[4] & ADAP_NOT_VALID) !=0) ? true: false);  //ADAP_NOT_VALID
    
    
         //Data 05
         boolPairRequest = (((ui8GetFlagBuffer[5] & PAIR_REQUEST) !=0) ? true: false);  //pair request
    
         boolUnPairRequest = (((ui8GetFlagBuffer[5] & UNPAIR_REQUEST) !=0) ? true: false);  //unpair request
    
         boolPairTimeOut = (((ui8GetFlagBuffer[5] & PAIR_TIMEOUT) !=0) ? true: false);  //pair time out
    
         boolDevicePairState = (((ui8GetFlagBuffer[5] & DEVICE_PAIRED) !=0) ? true: false);  //device paired    
    }
    
    /******************************************************************************************
    *function for depending on the bit status change execute the corresponding commands 
    *return void
    *******************************************************************************************/
    /**
    void ProcessFlags(void)
    {
    //      //Data 01 of getflag
          if(boolManualMode)
          {
            //process manual mode whenever it is active 
            boolManualMode = false;
            SetTRVMode(ZB_ZCL_THERMOSTAT_TRV_MODE_DEFAULT_VALUE);
            ui32HostflagsData |= FLAGS_BYTE_1_MANU_MODE;
            HostFlagStatus(ui32HostflagsData);
          }
    //      if(boolHeatingMode)
    //      {
    //        //process heating mode whenever it is active
    //        boolHeatingMode = false;
    //      }
          if(boolKeyProtection)
          {
            //process boolKeyProtection whenever it is active 
             boolKeyProtection = false;
          }
    //      if(boolInternalWindowOpen)
    //      {
    //         //process boolInternalWindowOpen whenever it is active 
    //         boolInternalWindowOpen = false;
    //      }
    //      if(boolExternalWindowOpen)
    //      {
    //         //process boolExternalWindowOpen whenever it is active 
    //         boolExternalWindowOpen = false;
    //      }
          if(boolRTCInValid)
          {
             //process boolRTCInValid whenever it is active 
             boolRTCInValid = false;   //if rtc bit is invalid then process action TBD
    //         vRTC_vRequestTimeFromCoordiantor();
          }
          if(boolBatteryWeak)
          {
             ReadErrorStatus(BATTERY_WEAK_ERROR);  //error status for battery weak detect
             //process boolBatteryWeak whenever it is active 
             boolBatteryWeak = false; //if battery weak bit is high then send "Get_battery_status" command
             boolReady = true; //set flag to execute communication state
             boolIsMCURequest = true;
             e_StateMachineThermostat = RUNNING_STATE;
             sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_BATTERY;
          }
    //      if(boolHolidayMode)
    //      {
    //        //process boolHolidayMode whenever it is active 
    //         boolHolidayMode = false;
    //      }
    
    //      //Data 02
    //      if(boolEncoderChange)
    //      {
    //         //process boolEncoderChange whenever it is active 
    //         boolEncoderChange = false;
    //      }
          //if setpoint change bit is high then send "Get_temperature" command 
          if(boolSetPointChange)
          {  
             boolSetPointChange = false;
             boolReady = true; //set flag to execute communication state
             boolIsMCURequest = true;        
             e_StateMachineThermostat = RUNNING_STATE;
             sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_GET_TEMPERATURE;
          }    
          if(boolMasterResetRequest)
          {
             //process boolMasterResetRequest whenever it is active 
             boolMasterResetRequest = false;
             zigbee_erase_persistent_storage(ZB_TRUE);
    //         NVIC_SystemReset();  //soft reset device when factory reset button pressed 
    //         CurrentState  = State_Ready;   //after Reset set to device  switch state ready         
    //         ResetFlags();
          }    
    //      if(boolMeasuredTempChange)
    //      {
    //        //process boolMeasuredTempChange whenever it is active 
    //         boolMeasuredTempChange = false;
    //      }
    //      if(boolMasterResetChange)
    //      {
    //        //process boolMasterResetChange whenever it is active 
    //         boolMasterResetChange = false;
    //      }
    //      if(boolBoostModeActive)
    //      {
    //        //process boolBoostModeActive whenever it is active 
    //         boolBoostModeActive = false;
    //                      //start boost mode bit if it is high and set host flag to 0x000004
    //      }
    //      if(boolProductModeRF)
    //      {
    //        //process boolProductModeRF whenever it is active 
    //         boolProductModeRF = false;
    //      }
          if(boolValvePositionChange)
          {
            //process boolValvePositionChange whenever it is active 
             boolValvePositionChange = false;
             boolReady = true; //set flag to execute communication state
             boolIsMCURequest = true;
             e_StateMachineThermostat = RUNNING_STATE;
             sAppUartEvent.eType_UartNextState  = APP_E_EVENT_UART_GET_VALVE_POSITION;
          }
    
    //      //Data 03 of getflag
    //      if(boolButton1Push)
    //      {
    //        //process boolButton1Push whenever it is active 
    //        boolButton1Push = false;
    //      }
    //      if(boolButton2Push)
    //      {
    //        //process boolButton2Push whenever it is active
    //        boolButton2Push = false;
    //      }
    //      if(boolButton3Push)
    //      {
    //        //process boolButton3Push whenever it is active 
    //         boolButton3Push = false;
    //      }
    //      if(boolButton4Push)
    //      {
    //         //process boolButton4Push whenever it is active 
    //         boolButton4Push = false;
    //      }
    //      if(boolButton5Push)
    //      {
    //         //process boolButton5Push whenever it is active 
    //         boolButton5Push = false;
    //      }
    //      if(boolButtonShortPush)
    //      {
    //         //process boolButtonShortPush whenever it is active 
    //         boolButtonShortPush = false;  
    //      }
    //      if(boolButtonLongPush)
    //      {
    //         //process boolButtonLongPush whenever it is active 
    //         boolButtonLongPush = false; 
    //      }
    //      if(boolButtonVeryLongPush)
    //      {
    //        //process boolButtonVeryLongPush whenever it is active 
    //         boolButtonVeryLongPush = false;
    //      }
    
    //      //Data 04 of getflag
    //      if(boolADAPSuccess)
    //      {
    //        //process boolADAPSuccess whenever it is active 
    //        boolADAPSuccess = false;
    //      }
          if(boolErrorE1State)
          {
            //process boolErrorE1State mode whenever it is active
            boolErrorE1State = false;
            ReadErrorStatus(VALVE_ADAPTATION_FAIL_E1);  //error status e1 when valve adaptation fail
          }
          if(boolErrorE2State)
          {
            //process boolErrorE2State whenever it is active 
             boolErrorE2State = false;
             ReadErrorStatus(VALVE_MOVEMENT_SLOW_E2);  //error status e2 when valve movement too slow
          }
          if(boolErrorE3State)
          {
             //process boolErrorE3State whenever it is active 
             boolErrorE3State = false;
             ReadErrorStatus(VALVE_NOT_MOVING_E3);    //error status e3 when valve not moving
          }
    //      if(boolPrepMode)
    //      {
    //         //process boolPrepMode whenever it is active 
    //         boolPrepMode = false;
    //      }
    //      if(boolINST)
    //      {
    //         //process boolINST whenever it is active 
    //         boolINST = false;   
    //      }
    //      if(boolADAP)
    //      {
    //         //process boolADAP whenever it is active 
    //         boolADAP = false; 
    //      }
    //      if(boolADAPNotValid)
    //      {
    //        //process boolADAPNotValid whenever it is active 
    //         boolADAPNotValid = false;
    //      }
    
    //      //Data 05 of getflag
    //      if(boolPairRequest)
    //      {
    //        //process boolPairRequest whenever it is active 
    //        boolPairRequest = false;
    //      }
    //      if(boolUnPairRequest)
    //      {
    //        //process boolUnPairRequest whenever it is active
    //        boolUnPairRequest = false;
    //      }
    //      if(boolPairTimeOut)
    //      {
    //        //process boolPairTimeOut whenever it is active 
    //         boolPairTimeOut = false;
    //      }
    //      if(boolDevicePairState)
    //      {
    //         //process boolDevicePairState whenever it is active 
    //         boolDevicePairState = false;
    //      }
    }
    **/
    
    //function to reset all flags 
    void ResetFlags(void)
    {
      boolReady = false;
      boolSetCommand = false;
      boolSetTemperature = false;
      boolSetHostflags = false;
      boolSetPointChange = false;
    }
    /****************************************************************************
     *
     * NAME: vUART_STATE_StateMachine
     *
     * DESCRIPTION:
     * Check different states of Thermostat and RF
     *
     * RETURNS:
     * void
     *
    ****************************************************************************/
    void UARTStateStateMachine(void)
    {
       if (e_StateMachineThermostat == BOOTLOADER_STATE)
       {
            switch (sAppBootloaderEvent.eType_BootloaderState) 
            {			
                case APP_E_EVENT_UART_START_FIRMWARE_UPDATE:                                 
                        //bRestartBootloaderMode = FALSE;  did not get declaration
                      UARTStateStartFirmwareUpdate();  
                break;
                case APP_E_EVENT_UART_TRANSFER_FRIMWARE_UPDATE:		
                        //UARTStateTransferFirmwareUpdate(); This function is not created here
                break;
                case APP_E_EVENT_BOOTLOADER_STATE_IDLE:
                break;
                default:			
                break;
            }
    
       }
       else if (e_StateMachineThermostat == PRODCUTION_MODE)
       {
    
            switch (sAppProductionEvent.eType_ProductionState) 
            {
                case APP_E_EVENT_PRODUCTION_STATE:
                     GetMessageIdResponse(GET_PRODUCTION_MODE);  // send get production mode command 
                break;
                default:
                break;
                    
            }
       }
       else if (e_StateMachineThermostat == RUNNING_STATE)
       {
                switch (sAppUartEvent.eType_UartNextState)
                {
                  case APP_E_EVENT_UART_SEND_TEMPERATURE:
                         //UARTStateSendTemperature(u16SaveAttributeID);  TBD for replacement send set temperature command
                  break;
    
                  case APP_E_EVENT_UART_GET_TEMPERATURE:                    
                        GetMessageIdResponse(GET_TEMPERATURES); //send get temeperature command
                        boolReady = true; //set flag to execute communication state
                        boolIsMCURequest = true;
                  break;
    
                  case APP_E_EVENT_UART_GET_BATTERY:                     
                         GetMessageIdResponse(GET_BATTERY_STATUS); //send get battey status command
                         boolReady = true; //set flag to execute communication state
                         boolIsMCURequest = true;
                         sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
                  break;
    
                  case APP_E_EVENT_UART_GET_COMPOSITE_DATA:                     
                          GetMessageIdResponse(GET_COMPOSITE_DATA1); //send get comosite data command
                  break;
    
                  case APP_E_EVENT_UART_ULP_WAS_TRIGGERED:                      
                          GetMessageIdResponse(GET_FLAGS);   //send get flag command
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS:                    
                       sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_AUTO_MODE:
                          UARTStateSendFlagsAuto();     //send set flag with auto mode flag command
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_MANU_MODE:
                          UARTStateSendFlagsManu();     //send set flag with manual mode flag command
                  break;
    
                  case APP_E_EVENT_UART_SEND_VALVE_POSITION:                      
                          UARTStateSendValvePosition();   //send set valve position command
                  break;
    
                  case APP_E_EVENT_UART_GET_VALVE_POSITION:                    
                          GetMessageIdResponse(GET_POSITION);   //send get valve position command
                          sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE; 
                  break;
    
                  case APP_E_EVENT_UART_SEND_DEVICE_CONFIG:                      
    //                      UARTStateSendDeviceConfig();          //send set device config command
                          sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE; 
                  break;
    
                  case APP_E_EVENT_UART_SEND_DEVICE_CONFIG_2:                    
                          UARTStateSendDeviceConfig2();           //send set device config2 command   
                  break;
    
                  case APP_E_EVENT_UART_GET_DEVICE_CONFIG:                    
                          GetMessageIdResponse(GET_DEVICE_CONFIG);   //send get device config command
                          boolReady = true; //set flag to execute communication state
                          boolIsMCURequest = true;
                          sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_JOINED:                                           
                          UARTStateSendFlagsJoined();            //send set flag command with joined parameter
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_LEAVE:                     
                          UARTStateSendFlagsLeave();             //send set flag command with leave ntw parameter
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_RF_COMMUNICATION_OK:                     
                          UARTStateSendFlagsRFCommunicationOK();   //send set flag with RF communication okay command
                  break;
    
                  case APP_E_EVENT_UART_SEND_FLAGS_RF_COMMUNICATION_LOST:                      
                          UARTStateSendFlagsRFCommunicationLost();    //send set flag with RF communication lost command
                  break;
    
                  case APP_E_EVENT_UART_SEND_RTC:
                          UARTStateSendRTC();                    //send set RTC command 
                  break;
    
                  case APP_E_EVENT_UART_GET_RTC:
                          GetMessageIdResponse(GET_RTC);          //send get RTC command
                  break;
    
                  case APP_E_EVENT_UART_GET_FIRMWARE_VERSION:                     
                          GetMessageIdResponse(GET_FIRMWARE_VER);   //send get firmware version command
                          boolReady = true; //set flag to execute communication state
                          boolIsMCURequest = true;
                          sAppUartEvent.eType_UartNextState = APP_E_EVENT_UART_IDLE;
                  break;
    
                  case APP_E_EVENT_UART_IDLE:
                         
                  break;
                  case APP_E_EVENT_UART_SEND_SYSTEM_MODE:
                         // vUART_STATE_SendDeviceConfig();    This is not created here
                  break;
    
                  case APP_E_EVENT_UART_GET_RTC_FROM_COORDINATOR:                     
                        //  vRTC_vRequestTimeFromCoordiantor();
                  break;
    
                  case APP_E_EVENT_UART_SEND_MASTER_RESET_REQUEST:
                          UARTStateMasterResetRequest();                 //send master reset with request flag command
                  break;
    
                  case APP_E_EVENT_UART_SEND_MASTER_RESET_SUCCESS:                     
                          UARTStateMasterResetSuccess();                //send master reset with rest flag command
                  break;
    
                  case APP_E_EVENT_UART_SEND_GET_PRODUCTION_MODE:
                          GetMessageIdResponse(GET_PRODUCTION_MODE);    //send get production mode command 
                  break;
    
                  case APP_E_EVENT_UART_SEND_SET_PRODUCTION_MODE_PASS:
                          UARTStateSendSetProductionModePass();    //send set production mode pass command
                  break; 
    
                  case APP_E_EVENT_UART_SEND_START_PRODUCTION_MODE:
                          UARTStateSendStartProductionMode();     //send set production mode start command
                  break;
    
                  case APP_E_EVENT_UART_LEAVE_NETWORK:                     
                       //   vUART_STATE_vLeaveNetwork();   This function not created here
                  break;
    
                  case APP_E_EVENT_UART_IDENTIFY_MODE:                     
                  break;
    
                  case APP_E_EVENT_UART_SEND_SWITCHPOINTS:
                        //UARTStateSendSwitchPoints();   //send switch point function. This function not created here
                  break;
    
    
                  default:
                  break;
                }
       }
    
    }
    
    

    - After bonding erase I would like to perform soft reset and I used NVIC_SystemReset() function here. What I observed is after reset my while(1) loop not executing and when i paused the code it show me in  nrf_log_frontend()  file's bool nrf_log_frontend_dequeue(void) function. 

    -Why reset not working correctly?Let me know your feedback on this.

    Thanks and Regards

    Rohit R

  • Hi Marte, 

    Update from my end, 

    As per your suggestion, I made the code in SED configuration. I have shared my main file in previous post. - Let me know any changes.

    But with this SED, configuration what I observed is with Dev-kit and Radiator base (STM) board I am getting 1mA current. Which is comparatively less than what I was getting previously. 

    Now I would like to do further reduction in current including nRF dev-kit and STM8 board I need almost 60uA and only nRF i need 30uA. 

    So, I decided to add ram retention also here along with sleep. Please find the attached image of my memory usage and let me know how I to power down unused ram section. 

    I request you, please give your feedback as early as possible on this. 

    And also, I would like to know can we use system off in sleepy end device and wake up on GPIO interrupt. I mean device should work as sleepy end device as well as system off mode. It should wake up periodically like SED and wake up on system off mode? Let me know your feedback on this. 

    And is there any update from developer regarding system wakeup on zigbee command? I am getting pressure from team to resolve sleep issue. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    Rohit Rajapure said:
    And is there any update from developer regarding system wakeup on zigbee command?

     I have already answered this, and explained that this is not possible with SED. With devices that are not SED, this will happen by default if you are using zb_osif_wait_for_event() to reduce power.

    • SED: A Sleepy End Device will go into sleep mode, and not only low power mode. This will, among other things, turn off the radio. So the device cannot receive Zigbee packets, as the radio is not receiving anything. Sending a command to wake the device will do nothing, as it will only receive the command after it is already awake. This is part of the Zigbee specification, for RxOnWhenIdle = false devices (some places call it RxOnIdle = false or RxOffWhenIdle = true).
    • Non-SED: Calling zb_osif_wait_for_event() makes the device go into low power mode. This is functionally the same as a single call of __WFE() instruction (wait for event). The CPU goes into a low-power state until an event occurs. Any interrupt occurring between zb_osif_wait_for_event() calls will wake up the device, same as with __WFE(). The radio is not turned off, so the device will still receive Zigbee packets. Receiving Zigbee packets will be an event, so it will wake up.
    Rohit Rajapure said:
    let me know how I to power down unused ram section. 

     As this feature is only available in v4.1.0, you must implement it yourself in v3.0.0. As I stated before you should look at the function zigbee_power_down_unused_ram() in zigbee_helpers.c in v4.1.0 to see how this can be done. After implementing the function, you should call it right after setting SED with zb_set_rx_on_when_idle() in main().

    Rohit Rajapure said:
    Let me know whether I have followed correct API to execute this erase info and NVIC_SystemReset() is for software? 

     It should be enough to define ERASE_PERSISTENT_CONFIG as ZB_TRUE and call zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG). This should erase network data on a reset or power cycle of the device. This function calls zb_set_nvram_erase_at_start(), which enables or disables NVRAM erasing on application startup. If using zigbee_erase_persistent_storage() does not work, you can try calling zb_set_nvram_erase_at_start(ZB_TRUE) directly, but I would recommend using zigbee_erase_persistent_storage() instead. You should call these functions during the initialization, and not when the application is running. The function zigbee_erase_persistent_storage() will not make the device leave the network.

    Since you are using v3.0.0, you can make your device leave the network by creating a function that does the same as light_switch_leave_nwk() in the light switch example.

    static void light_switch_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(light_switch_leave_nwk);
            ZB_ERROR_CHECK(zb_err_code);
        }
    }

    Rohit Rajapure said:
    And also, I would like to know can we use system off in sleepy end device and wake up on GPIO interrupt

    I will come back to you regarding this.

     Best regards,

    Marte

  • Hi Marte, 

    Thanks for the response. 

     I have already answered this, and explained that this is not possible with SED. With devices that are not SED, this will happen by default if you are using zb_osif_wait_for_event() to reduce power.

    - My point here is, I want less current consumption for my device it should be 30uA. As per your suggestion we tried SED because zb_osif_wait_for_event(); Didn't worked. It gave us current 3.9mA. 

    So, Till we get developer feedback on waking up device using Zigbee command. We tried SED config. And it gave us some better result around 1mA. But again this huge my target is 30uA. 

    - That's why asked any update from Developer for this? If the waking up device using Zigbee command gives us better result in current consumption I will definitely use that not SED. On other hand after configuring SED if would resulted me in uA (micro Ampear) then I would go ahead with. I didn't bother for waking up on Zigbee command. 

    - Point is, using SED or zb_osif_wait_for_event() not gave me less current. In document typical value mentioned. Also, some points regarding System ON, no ram retention but how to do that no explanation. System Off also same. Only wakeup on reset or GPIO interrupt that also not help me here. 

    Then how to reduce current?? We trying different different ways but still same result. Current not reducing below mA. 

     As this feature is only available in v4.1.0, you must implement it yourself in v3.0.0. As I stated before you should look at the function zigbee_power_down_unused_ram() in zigbee_helpers.c in v4.1.0 to see how this can be done. After implementing the function, you should call it right after setting SED with zb_set_rx_on_when_idle() in main().

    - I saw some post and suggestion followed below to configure the same. 

    NRF_POWER->RAM[0].POWERCLR = 0x3;
    NRF_POWER->RAM[1].POWERCLR = 0x3;
    NRF_POWER->RAM[2].POWERCLR = 0x3;
    NRF_POWER->RAM[3].POWERCLR = 0x3;
    NRF_POWER->RAM[4].POWERCLR = 0x3;
    NRF_POWER->RAM[5].POWERCLR = 0x3;
    NRF_POWER->RAM[6].POWERCLR = 0x3;
    NRF_POWER->RAM[7].POWERCLR = 0x3;
    NRF_POWER->RAM[8].POWERCLR = 0x3F;
    - As per our study I commented RAM[0], RAM[1] and RAM[2] and set RAM[8] = 0x3 then able to run my code. 
    - And, if i just comment RAM[0] and RAM[8] = 0x3F as per one of nrf engineer post, I am not able to run code. IT enters into hardfault. 
    - Okay, I will follows your steps. Use 4.1 to port in 3.0 SDK. 
    I will come back to you regarding this.

    - Yes, please I will wait. 

    Thanks and Regards

    Rohit R

  • Hi Rohit,

    So, Till we get developer feedback on waking up device using Zigbee command. We tried SED config. And it gave us some better result around 1mA. But again this huge my target is 30uA. 

    Can you please give some more information about what your project is doing when you are measuring the current and how you are measuring it? You say the device has joined the network, but is it performing any other actions while you are measuring the current consumption?

    You can also check out our guide Measuring current, and I recommend reading the note further down on that page. Additionally, it is suggested to cut SB40 to put P22 in series with the load, as explained in Preparing the DK. You should also set SW6 to "nRF only".

    When performing current consumption tests earlier, our developers have managed to get sleep current consumption down to 1.6-3.3 µA, depending on the amount of RAM retention. This was when the device had joined and was not performing additional actions, but being in sleep mode. However, it is difficult to compare with your results without knowing more about your test setup.

    That's why asked any update from Developer for this? If the waking up device using Zigbee command gives us better result in current consumption I will definitely use that not SED. On other hand after configuring SED if would resulted me in uA (micro Ampear) then I would go ahead with. I didn't bother for waking up on Zigbee command.

    Please read what I wrote in my previous reply about this. If you want to get the lowest possible current consumption, you should use SED. You will not get lower current consumption when not using SED. The difference between SED and non sleepy devices is that with SED the radio is turned off and does not receive or send packets. This greatly reduces current consumption.

    If you are using SED but does not see a significant impact on the current consumption, then it is possible the device does not go to sleep as it should, or that it wakes up very often.

    Also, the current consumption in SED applications is further optimized in v4.1.0 of the SDK, so you it is very likely you would get a lower current consumption using that version.

    Also, some points regarding System ON, no ram retention but how to do that no explanation.

    Please read my previous replies. I explained clearly what the parts of this configuration means:

    • System ON: This means that the chip is in system ON, and not in system OFF, which means that the chip is in a regular state ready to run, and that the CPU is in sleep mode. The CPU is in a WFE (waitinf for event) call, and will wake when there is an interrupt. This interrupt is typically the RTC clock, but with 1 μA. the RTC is not in use.
    • no RAM retention: this means that the RAM is not conserved, and will practically mean that there is no code running on the chip.

    You get System ON when the CPU is in sleep mode, so either when a SED goes to sleep, or when calling zb_osif_wait_for_event(). You must have some RAM retention, as without it, your application cannot run, but you can power down unused parts of RAM, as I have explained previously.

    And also, I would like to know can we use system off in sleepy end device and wake up on GPIO interrupt.

    In both the case of SED and non-SED devices, the stack calls zb_osif_wait_for_event(), which will behave like a single call of __WFE() instruction, from a functional point of view. So if an interrupt occurs between zb_osif_wait_for_event() calls, the device will wake up. Thus, you can implement GPIO interrupts in the same way as you would with WFE (wait for event). You must enable GPIO, configure a pin for input, and configure it to give an interrupt on pin change. An example of how you can do this is to create a gpio_init functions as follows:

    static void gpio_init(void)
    {
        ret_code_t err_code;
        
        err_code = nrf_drv_gpiote_init();
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(false);
        in_config.pull = NRF_GPIO_PIN_PULLUP;
        
        err_code = nrf_drv_gpiote_in_init(PIN_IN, &in_config, in_pin_handler);
        APP_ERROR_CHECK(err_code);
        
        nrf_drv_gpiote_in_event_enable(PIN_IN, true);
    }

    Then you can call this function in main() during initialization. You must remember to define PIN_IN as the pin you want to use for interrupts. You can also check out the GPIOTE driver for more information.

    Best regards,

    Marte

  • Related