HomeHome AutomationA budget ZigBee thermostat?

A budget ZigBee thermostat?

Hello, meet my new thermostat

My DIY Smart Heating system brings pride and joy to my life. Designed to monitor and apply multiroom temperature to my heating system with smart speaker integration and lots of bells and whistles. The biggest yet upgrade is coming this year! The inclusion of individual TRVs from Moes will take things to another level. There is one more thing that I should address.

My thermostat.

It’s… unique

ZigBee thermostat - HC-020
ZigBee thermostat – HC-020

100% functional and 100% terrifying. The synergy of the 30-year-old Honeywell analogue thermostat and Sonoff Basic R2 works as well as a scarecrow in the middle of the field. Anyone new to my household will look at it in confusion, unsure if they should ask more questions, leave immediately or dial a bomb squad.

The truth is: while I’m painfully aware of its “IED” aesthetics, the system outperformed Google Nest reliability. Four years in use, a single (self-inflicted) point of failure, that lasted approx 4h (which I fixed remotely). Can you say the same about your cloud-connected thermostat? Perhaps not. So the missing puzzle in my home automation is a ZigBee based thermostat, to match other things ZigBee.

It was easier said than done, but thanks to the generous choice of gadgets from AliExpress, I bought the HC-020. Don’t bother even looking this up on the wide world web. This thing probably doesn’t exist outside of the Tuya ecosystem and the AliExpress listing. But it comes with variants that will appeal to many.

No need for a bomb squad, I promise

I got swayed by 2 main features: a ZigBee connectivity and the ability to display 6 icons of houses. The interface was very similar to the one present on Moes TRVs so I was pleasantly surprised when the unit came with an actual LCD display instead. What was disappointing, however, was the fact that the 6 houses that looked like they could represent zones – ended up being time periods for each schedule. Not ideal, but at £25 something, it’s not a deal-breaker.

I can’t win all the battles, so I have to work with what I have. The thermostat comes in ZigBee and WiFi flavours. Obviously, I ended up with ZigBee. What’s really useful, are 3 configurations that you can pick from:

  • GA (mine) with NO/NC relay and mains control
  • GB for electrical load – like floor heating (16A)
  • GC for gas/water boilers which use a dry contact

Unlike my Sonoff Basic, HC-020 covers all heating scenarios you may have. It works with 95V-240V AC – it has got you covered wherever in the world you are.

If I’m honest, on one side the device feels a little cheap with plastic housing and buttons (M and arrow UP) that can be triggered by pressing on black panel edges, but on the other hand – it’s a nice bright LCD display and pleasant interface which isn’t terrible even if the touch controls are limited to the 4 action buttons. If you read my article about the heating system I made in NodeRED, you know that I interact with Alexa to control it, which anything else is simply secondary. Your needs may vary, but my long term goal is to remove the interaction altogether and turn it into a self-sustaining system that doesn’t waste money by being constantly set to 19℃.

Another slight annoyance is the lack of the obvious settings to turn off the beep associated with button presses and remote device changes. I don’t think you can turn this thing off. It’s not loud, but if I’m going to apply the settings remotely, I can see this getting old very quickly. If I can’t find the audio setting, I will be tempted to disconnect the buzzer inside.

The bottom line is: it’s miles better than the solution I have on my wall right now.

How to pair HC-020

What’s not explained in the manual, is how to pair the unit. It took me about 20 min to figure this out. To enter the pairing mode on the ZigBee HC-020 unit, turn off the thermostat with the middle button, then hold the arrow down for approx 5 sec. The screen will change and the device will enter the pairing mode.


Before I pair it with Tuya and NodeRED, let’s have a peek inside. The device is easy to open, the back panel contains the terminals for the power, internal relay and external temperature probe (used for floor heating by default).

The front panel can be easily removed and inside you will find a Tuya ZigBee module ZS3L mounted on a daughterboard. Since the device is using ZigBee – I have no desire to probe it further as I don’t need to hack it to interact with it.

Inside HC-020 ZigBee thermostat

It’s worth noting that apart from the external temperature sensor (you can access the value by pressing the arrow down for 5 sec) there is an internal one at the bottom of the device’s rim. Tuya app will let you pick one or both for temperature monitoring.


Pitching the HC-020 against one of the Moes temp sensors I trust with their readings, I find the sensor to be within 0.5℃ from each other. The difference could be smaller, but the thermostat’s temperature sensor has a 0.5℃ resolution. Non the less, without calibration, it’s good enough for my case and if your thermostat is placed in a room that has a lower temperature than other parts of the room, you can always offset it.

As the HC-020 works in a similar manner to TRVs it’s possible to use my auto-calibrating script and sync up the internal temperature sensor with an external one. Check out this article if you want to learn how to offer a temperature like this, and why this is important if your thermostat is placed near a heat source.


Once I found the correct pairing sequence, HC-020 paired quickly. It has a pleasant to the eye interface and a couple of buttons to access different operational modes. Tuya will automatically sync up the thermostat clock and settings.

In regards to the time and schedules, the app allows a delayed start (up to 24h), manual, programmable and eco modes. In the settings, you will find more schedules including weekday/weekend schedules with a 6 time slots, which will display on the LCD screen as the little numbered houses.

Other settings include lock, sensor calibration and eco mode. My imperial friends will appreciate the ℃ and ℉ units in the app and on the LCD display as well and the ability to limit setpoint value to a specific number. Just in case your kids keep setting heating all the way up to 30!

Lastly, if you are sold on the ease of use, you can keep it connected to a Tuya hub and take advantage of Tuya Cloud API to control your thermostat through NodeRED or Home Assistant. This way you get the best of both worlds – Tuya Google Home/Alexa integration and the ability to link it all to your custom automation.

HC-020 Thermostat and Zigbee2MQTT

It’s not the Tuya Cloud operation I was after, so it’s time to explore it in NodeRED and ZigBee2MQTT. It pairs without any issues on the latest software and is identified as Moes BHT-002-GCLZB. Knowing what I know now about the HC not having zones, I would probably pick the BHT-002-GCLZB instead, but choices had been made.

Unlike the Moes TRVs – which I highly suspected will have a similar payload, the information coming from HC-020 comes slimmed down. The fact that the temperature information needs tweaking assures me that a separate converter for this device will be needed. Upon connection HC-020 issues payload which looks like this:

	"child_lock": "UNLOCK",
	"current_heating_setpoint": 20,
	"linkquality": 120,
	"local_temperature": 2.4,
	"local_temperature_calibration": 0,
	"max_temperature": 35,
	"preset": "hold",
	"preset_mode": "hold",
	"sensor": "IN",
	"system_mode": "heat"

The HC-020 spams multiple messages at once (probably triggered by the unassigned converters in the zigbee2MQTT log:

zigbee-herdsman-converters:Moes BHT-002: Unrecognized DP #42 with data {"status":63,"transid":248,"dp":42,"datatype":2,"fn":0,"data":{"type":"Buffer","data":[0,0,0,0]}}

Until this is sorted, I will use a Delay node in the rate limit mode to prevent the MQTT from flooding my debug log.

To control the thermostat and update the LCD values, simply submit the JSON formatted information back to the /zigbee2mqtt/device_name/set. If you want to for example turn it on, your payload will look like this:

{"system_mode": "heat"}       #or off to trun it off

The possible values are listed in the table below

child_lockLOCK, UNLOCK
current_heating_setpoint int
local_temperature_calibration int
max_temperature int
preset hold, program (eco mode is missing)
preset_mode ?
sensor IN, OUT, ALL
system_mode heat, off

What’s missing is the ability to read and write the timers and set the time remotely. Setting the timers from the unit directly doesn’t change anything. Something tells me, I would have to look into Moes TRV and Moes BHT-002-GCLZB thermostat converters to merge it and make it work (maybe?). I will definitely update this NodeRED sample flow as soon as the new options are available.

Sample NodeRED flow
[{"id":"2a263973c393a887","type":"tab","label":"HC-020 ZigBee thermostat","disabled":false,"info":"","env":[]},{"id":"b5361fc6ca99c292","type":"group","z":"2a263973c393a887","name":"HC-020 feedback","style":{"label":true},"nodes":["5abee01467598baf","ad36a3da7cdb3aaf","4036a1a7ba519a40","fe0351395a3af9ae","63ac421e11fe31b4"],"x":94,"y":59,"w":812,"h":162},{"id":"654f5fce5d274dc8","type":"group","z":"2a263973c393a887","name":"Thermostat controls","style":{"label":true},"nodes":["f84429c2853f4b15","073e19fad1e7af42","28d97fa96f3a23fa","daf0d3c0699ae949","e8a7f47a13b03b88","996fe83eedb6668b","17accf3c0e69bbc5","a1f902e4669b4ce0","d7924e785f86221b","bc55caf742af9d0b","aff4720801b3141e","8da1742737cf6193","705c4a3bcbea3dcf"],"x":94,"y":239,"w":732,"h":442},{"id":"5abee01467598baf","type":"mqtt in","z":"2a263973c393a887","g":"b5361fc6ca99c292","name":"HC-020 thermostat","topic":"zigbee/Thermostat","qos":"0","datatype":"json","broker":"e65461d7cbd2a2d4","nl":false,"rap":true,"rh":0,"inputs":0,"x":210,"y":140,"wires":[["fe0351395a3af9ae"]]},{"id":"ad36a3da7cdb3aaf","type":"debug","z":"2a263973c393a887","g":"b5361fc6ca99c292","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":790,"y":140,"wires":[]},{"id":"f84429c2853f4b15","type":"mqtt out","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"HC-020 thermostat","topic":"zigbee/Thermostat/set","qos":"","retain":"","respTopic":"","contentType":"","userProps":"","correl":"","expiry":"","broker":"e65461d7cbd2a2d4","x":710,"y":380,"wires":[]},{"id":"073e19fad1e7af42","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"Preset: hold","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"preset\" : \"hold\"}","payloadType":"json","x":210,"y":280,"wires":[["f84429c2853f4b15"]]},{"id":"28d97fa96f3a23fa","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"SetPoint 20","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"current_heating_setpoint\" : 20}","payloadType":"json","x":210,"y":380,"wires":[["f84429c2853f4b15"]]},{"id":"daf0d3c0699ae949","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"system_mode\" : \"heat\"}","payloadType":"json","x":190,"y":520,"wires":[["f84429c2853f4b15"]]},{"id":"4036a1a7ba519a40","type":"comment","z":"2a263973c393a887","g":"b5361fc6ca99c292","name":"Set MQTT path","info":"I used a modified path, the default one starts with\nzigbee2mqtt\nso edit this as required","x":200,"y":100,"wires":[]},{"id":"e8a7f47a13b03b88","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"system_mode\" : \"off\"}","payloadType":"json","x":190,"y":560,"wires":[["f84429c2853f4b15"]]},{"id":"fe0351395a3af9ae","type":"delay","z":"2a263973c393a887","g":"b5361fc6ca99c292","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"3","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":440,"y":140,"wires":[["ad36a3da7cdb3aaf","63ac421e11fe31b4"]]},{"id":"996fe83eedb6668b","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"Preset: program","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"preset\" : \"program\"}","payloadType":"json","x":220,"y":320,"wires":[["f84429c2853f4b15"]]},{"id":"17accf3c0e69bbc5","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"SetPoint limit 30","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"max_temperature\" : 30}","payloadType":"json","x":220,"y":420,"wires":[["f84429c2853f4b15"]]},{"id":"a1f902e4669b4ce0","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"temp sensor calibration -3","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"local_temperature_calibration\" : -3}","payloadType":"json","x":250,"y":460,"wires":[["f84429c2853f4b15"]]},{"id":"63ac421e11fe31b4","type":"function","z":"2a263973c393a887","g":"b5361fc6ca99c292","name":"Temp fix","func":"var temp = msg.payload.local_temperature * 10;\n\nmsg.payload = \"current temp: \" + temp + \"℃\"; \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":620,"y":180,"wires":[["ad36a3da7cdb3aaf"]]},{"id":"d7924e785f86221b","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"child lock ON","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"child_lock\" : \"UNLOCK\"}","payloadType":"json","x":210,"y":600,"wires":[["f84429c2853f4b15"]]},{"id":"bc55caf742af9d0b","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"child lock OFF","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"child_lock\" : \"LOCK\"}","payloadType":"json","x":210,"y":640,"wires":[["f84429c2853f4b15"]]},{"id":"705c4a3bcbea3dcf","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"internal sensor","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"sensor\" : \"IN\"}","payloadType":"json","x":580,"y":640,"wires":[["f84429c2853f4b15"]]},{"id":"aff4720801b3141e","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"external sensor","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"sensor\" : \"OUT\"}","payloadType":"json","x":580,"y":600,"wires":[["f84429c2853f4b15"]]},{"id":"8da1742737cf6193","type":"inject","z":"2a263973c393a887","g":"654f5fce5d274dc8","name":"both sensors","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"sensor\" : \"ALL\"}","payloadType":"json","x":570,"y":560,"wires":[["f84429c2853f4b15"]]},{"id":"e65461d7cbd2a2d4","type":"mqtt-broker","name":"My MQTT","broker":"localhost","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Ideally, I would like to come up with a system where I can use the period indicators to display the leading rooms in my system. If that’s not possible, it’s not a big deal as I will have a dedicated dashboard just for the heating.

Final thoughts

I have no doubts that after my GitHub report some clever heads will figure out the way to merge the converters – I tried without luck. While the HC-020 ZigBee thermostat isn’t all I ever wanted, it’s decent enough to go on my wall, especially since the aim of my system is to be as attention free as possible with voice commands prompts managing the entire heating. If you like the looks of HC-020 or Moes BHT-002-GCLZB – grab one yourself. They are not very expensive and also serve as routers in your ZigBee network. Meanwhile, I’m off to do some programming and test the best Zigbee temperature sensors. Let me know your thoughts in this Reddit thread.


Nothing says "Thank you" better than keeping my coffee jar topped up!


Support me on Patreon and get an early access to tutorial files and videos.


Bitcoin (BTC)

Use this QR to keep me caffeinated with BTC: 1FwFqqh71mUTENcRe9q4s9AWFgoc8BA9ZU

Smart Ideas with

Automate your space in with these ecosystems and integrate it with other automation services


Learn NodeRED

NodeRED for beginners: 1. Why do you need a NodeRED server?

To server or not to server? That's a very silly question!

Best Automation Projects

Tuya SDK for beginners: Intro to Tuya Cloud API

Working with Tuya Cloud API. A guide to Cloud automation for beginners, get started with REST!

NEST your old thermostat under $5

Nest-ing up your older thermostat under $5

Nora – Google Assistant in NodeRED

Integrate Google Assistant with NodeRED thanks to Nora - NodeRED home automation

Sonoff R3 DIY mode & why it sucks

Long awaited Sonoff R3 DIY mode is even worse than I expected.

Things they don’t tell you about IKEA Trådfri

There are things you should know about IKEA Tradfri before you make your purchase

Smart Home

Best ZigBee temperature sensors

What's the best ZigBee temperature sensor money can buy? Let's test all of them and find out

A simple trick to reduce ZigBee coordinator WiFi interference

This simple trick will reduce the WiFi interference over your Raspberry Pi connected Zigbee coordinator

Is Sonoff Zigbee Dongle Plus finally ready for launch?

Testing the best firmware for Sonoff ZigBee Dongle Plus - is this budget coordinator finally ready?

A budget ZigBee thermostat?

As my DIY Smart Heating expands, I need to address the biggest issue: lack of wall mounted thermostat. Is this ZigBee thermostat one you should get?

Thermal benchmark test

I very much doubt this will attract a lot of attention, but I made a small NodeRED tool that will help me out in future thermal testing of the boards and enclosures. It gave me an opportunity to work with the dashboard in NodeRED...