The 2019 Thermostat ReThink

Back in 2017 I wrote a blog entry called “A Thermostat Weekend” – some weekend that turned out to be. Well, to cut a long story short, the stat worked but I was at the time just finding out all about NEST and other modern stats and so my ESP-GO/Node-Red thermostat development started gathering dust.

Then we fitted a new Air Source Heat Pump heating system and it looked like my thermostat skills might be redundant. This new system came with a Salus IT 5000 Thermostat – absolutely lovely App, nice display and this I thought would well and truly bury my interest. How wrong could I be.

Stat web interface

Here is the latest version of my stat web display (Dashboard) – I removed the redundant FROST setting and improved the formatting today (29/02/2019). More soon no doubt

I found some issues with the original QDTECH display in terms of reset reliability bearing in mind I’m short of IO pins and reset is hooked to processor reset (I just realised I can reclaim SS pin and potentially use it to reset the display) and I’ve changed to an ILI9341 for the final version as well as fixing some bugs with AWAY timing, VASTLY improving the web stat (Dashboard) css and adding multi-functions to the two available inputs – so that “up” and “down become “auto” if pressed simultaneously OR if either of the two buttons are long-pressed. The larger display also shows full time, day and date as well as “away” status. Also not yet shown here but I’m considering touch panels for up and down depending on Aidan’s perspex engraving skills.

Buttons now have long-click functionality to handle AUTO…. Display shows humidity and more… fixed “away” timing bug in online display… this will look a LOT prettier when the front panel is done (that’s a 5v power supply in there on the left).

Mk II wall stat

The NEW Flow

Stat flow

The actual flow is on Pastebin as it is quite large: 

Our requirements are simple enough – we need remote control – and simplified controls for when we are in Spain as our UK cottage is used for holiday cottage rental. An additional complication is that you have to be sensible with air source heat, you don’t have the fast responsiveness of oil and the range of temperatures needs to be limited – a heavy responsibility for guests. And the heating controls need to be reliable.  The Salus is having none of that.

So I started looking around – Nest is lovely, probably has limit options but it doesn’t have guest controls either as far as I can tell. Indeed there appear to be only a small number of modern thermostat designs out there and up to now I’ve seen nothing that will fit the bill.

Relay boxIf you’re interested I suggest you start at the original “A thermostat Weekend” entry (there is also a very slight update at “The Thermostat Revisited”)  Right now, I’ve been making use of my ESP-GO code for the ESP (BitBucket) to form the base of a  wall “guest-level control” as I have all the remote control we need in the Dashboard Thermostat – on my Android phone (or PC). As always I was running out of inputs on the ESP8266 – needing “up”, “down” and “auto” controls and having only two inputs available I came up with a “press both buttons for auto” solution now supplemented with long-press options. In addition, manual settings revert back to auto after a couple of hours anyway.

And here it is, above, the first prototype of the guest control complete with temperature display, set-temperature control and time. I’m using existing ESP-GO code along with some new Nose-Red programming shown in the flow link above. You can see that there are two buttons on wires and there is a DHT22 sensor (the original featured a DS18B20 sensor). This then uses an inexpensive 320*240 ILI9340/9341 display. CS on the display board is grounded.

Here is a typical link for the ILI9341 displays… 2.8" 240x320 SPI TFT LCD

Originally I used - Mini 1.8 Inch Serial SPI TFT LCD Module Display – Ebay or AliExpress – I’ve used quite a few over time.

Here’s a link for the gauge..

I have a UK mains surface mount back box, I need to come up with a smoked perspex front panel; unless someone has a better idea. I now have better buttons and an ESP + uncommitted relay (NOT Sonoff, as the Sonoff relay is commoned with the power lines) to actually control the heating – the prototype is boxed and running with indicators.

Here for reference is the updated flow, using a relay ESP board called heating_relay…. the stat board you see at the top is called “stat3” in the flow. I’m now using a pair of my Timeout Node-Red nodes, delay nodes, Injects for testing and setup, Node-Red Dashboard and of course MQTT, function nodes and file nodes for storage,

This is what the original stat looked like in Chrome on a PC (frameless). Full 7-day control with hourly intervals, AWAY and frost settings – though in my case these will probably end up being set at 16c. There were some bugs in this version.

Thermostat by Scargill

Scargill's Stat - App/PC Interface

The Thermostat Flow inc Simple Wall Unit

Here’s the original flow (no longer being developed) which includes the stat and the ESP interface MQTT. If you check carefully, you’ll see my 2-button solution – thanks to Colin and others over at Node-Red Forum – I ended up coming up with my own solution but the inspiration helped as always.

As mentioned elsewhere I don’t distribute my ICONS as I’m not entirely sure what the licencing is on them – however, reader  has sent this excellent link to what looks like a marvellous open source icon library. All icons used in the little display board are included in ESP-GO firmware so we’re only talking about any icons I’ve used in Node-Red Dashboard – but hey, you can never have too many icons.

Here’s the original QDTECH Flow on Pastebin...



104 thoughts on “The 2019 Thermostat ReThink

  1. This is looking good Pete. I was looking at something pretty similar myself recently for my holiday home rather than having to use a browser front end. I'd got it narrowed down to something like this or a Nextion/MQTT based setup. As an ESPEasy fan/user I have also been playing with a Wemos D1 Mini / Rotary encoder / mini OLED setup trying to drive as much of the logic as possible via the 'rules' engine within ESPEasy but with mixed results.

    I'm watching your (much more impressive, it has to be said) results with interest.


      1. Hi Pete,
        Could you please kindly elaborate your comments on the 2 types of TFP listed in the article ? Is the 1st one bad ?
        By the way whle both description say they are SPI, I believe it is indeed IIC. Am I correct ?

  2. Ecobee supports limits and guest access controls, though they are kinda expensive and I know the appeal of making your own. I was using a DIY thermostat based on an ESP + a generic Sainsmart relay board, it was a fun project that I used for close to two years before deciding to get the Ecobee.

    1. It is interesting that you chose Ecobee. I'm in Perth, Western Australia and so it's cooling I need at the moment! I bought and fitted an Ecobee a few years ago to my reverse cycle air conditioning. I had to order it from the US, and it wasn't cheap! Fundamentally, it's very good although the biggest problem is that Ecobee quite deliberately has effectively told me that I'm on my own' as they won't support anything outside of N America (It is a Canadian company). The major irritation of this is that - because of my longitude - the 'weather forecast' is 12 hours wrong! Yes, Perth gets hot but it's not 36 at night and 22 in the afternoon!! The web application seems good, and easy to use, although, again, due to perhaps being in the southern hemisphere, it doesn't seem to want to keep records of my usage ('Whadda mean, you want cooling in January?'). Would I recommend Ecobee? Well, maybe if I were in the US or Canada, but otherwise - caveat emptor! I do run Home Assistant (sorry, Pete!) here and it plays well with that - but I'm really enjoying reading the development saga of Pete's home-made thermostat!

      1. there's nothing to be sorry, home assistant and nodered can coexist beautifully, nodered HA nodes are great, and you can have the best of both worlds: the ENORMOUS device support of HA and the way easier automation management of nodered... 🙂

      2. Ah, I didn't realize Ecobee was limited to NA. I imagine importing it to the UK would probably be pretty expensive.

        I'm not actually sure if I recommend them, either. I do actually like the device and its core functionality works well, but their API service is a little flaky and their options for local-only API control are lacking (Homekit only). I also use mine in HomeAssistant and integration is pretty good, but I don't like the imposed 5-10 minute lag on all data (especially limits the usefulness of the motion sensors). The only reason I mentioned them really is because they do have fairly comprehensive controls and access limits for landloards, which Peter was talking about.

        Making my own was fun and it worked pretty reliably, but it was kinda time consuming to program something reliable considering how expensive mistakes can be. I ultimately had something pretty cool (pun intended), with remote sensors with arbitrary weighting that could be updated throughout the day over MQTT, but also with failover to standalone if something went wrong, a nice UI etc., but nowadays I don't have as much free time and it had a couple of minor bugs/shortcomings (still needed to make a pretty enclosure), so it ended up getting replaced with something commercial. I'm moving soon, I'm still mulling giving the Ecobee to my father and replacing it with a Zwave thermostat if I can find one with remote sensors (Ecobee's real killer feature, especially when I bought it when remote sensors were fairly unique to them).

        1. Before I decided to press ahead with my own, Ecobee looked like it might be worth investigating, of course I missed the bit about them not doing the world. Good job I didnt go down that route. My "home-made" version, once I get a decent cover for it (ALWAYS the problem) is going to be in practice a lot more useful than the fancy and overly expensive offerings I've seen commercially. The Salus is very pretty but absolutely useless... It uses short range radio and cant even handle 2 cottage stone walls - if it loses the signal, someone has to be there for someone to reconnect it- utter rubbish.

          I'm about to make some improvements, for those following my stat project. "frost" is historical - the AWAY function does the same thing better - the space could be better used for a "weeks" option for AWAY timing. I also want cold weather pre-empting - air source heating takes a lot longer to reach temperature when it is cold outside - it isn't heating water at room temperature to hot like oil systems, it is trying to heat BLOODY COLD air (you can imagine the cold draft outside).

          1. My only real advice is to make sure the thermostat can run standalone as a standard dumb thermostat if it gets disconnected, or at least have it check for a timeout to the server and fail safe (i.e. off). Not quite sure from your post how much of the actual control logic is being done in NodeRed versus on the device itself, but you really don't want a disconnect from the server to cause your HVAC to get stuck turned on.

            Oh, and you probably want to include some hysteresis and minimum run time to keep it from short-cycling your HVAC. Implementing minimum run times in a robust way with all the edge cases covered was probably the most annoying part of my code...

            1. Hysteresis sorted long ago, thanks. Most logic done in node-red - ESPs just follow my Node-Red rules which say turn heating on for 5 minutes - and that is repeated every minute - if no repeat, heating turns off - unless esp relay jams on. The latter has a software controlled fladshing light and a software controlled steady power light. if the heating fails off, we have a real fire and a pair of oil heaters available. Can't cater for ANY eventuality but I'm doing my best.

    1. yet another device with yet another app. I just need something to respond to mqtt and pref: using my own ESP-GO or Tasmota - no interest in yet another standard... also not seeing this from the UK? AT $9 each plus taxes and duty that would be expensive. UK supplier?

        1. if that was your only concern, you could have just enabled mqtt in stock firmware and that's it... as soon as you enable that, you've no more shelly cloud service, and you could interact with it via mqtt, native in stock firmware...

      1. in italy there's a guy on facebook which takes tons of these devices and then sells them locally, so in 2 or 3 days you can have them, maybe someone in UK, too... i paid my shelly2 24€ shipped, and i bought it just because i could hide it in my 503 switch wall mount, nothing exposed, and app is very well done and has native "curtains" mode... works without issues on 1st connect (even the physical buttons)... i hope others will do same size devices but cheaper... the 2 is now extint, 2.5 is just out:

        the good of them, aside from small size (2.5 is even smaller than the 2, while having 10A relays instead of previous 8A ones!) is the per relay power monitoring... for example, i let my "curtain" shelly to calibrate itself: it went full off, recognized that by the 0W power consumption, then went full closed and marked that, too, so now i can say: "open curtain at 50%" and it just does that... nothing visible on my wall, all hidden in the 503 italian wall mount

  3. Thanks. We went with a Radio Thermostat CT80 for our curling club warm room in the USA. It has remote control features via wifi, a daily program, and also has "lock" capability. The lock will allow guests to alter the temperature by as much as +/- 4 degrees F from the program, and reverts to the program at the next scheduled program changepoint. This has been a win since it allows folks to have some control, but they can't go crazy. And, if there are special requests or extended downtime, we can remotely set the thermostat to idle. After three years, the unit has been totally reliable.

      1. The setting is not a real problem in my case. I have:
        1x1 Widget Size 100 100
        Widget Spacing 6 6
        Group Padding 0 0
        Group Spacing 1 1
        Dashboard Group Node "Stat" width is set to 6

        In Peter's article
        There is recommended setting for Widget size 52x52
        Now I understand better the main problem is with the following:
        * NR Dark Theme: some black fonts are not visible (Day, Frost, Away ...)
        * Gauge is missing, because Peter has it installed locally

        * icons are missing (Peter is describing he is not distributing them - pity, but I understand)

        One more hint: in the blog-post above, the flow code is not formatted, so it is not easy to get in to the clipboard.
        Anyway, thanks for sharing your work, Peter

        1. report dark theme problems to his author on his github

          about gauge and icons: in articles is said where to get them, maybe you just need to dig a bit in articles themselves and their comments...

          find them and report to Peter so he can make them more "visible" 🙂

          i don't think clipboards cares AT ALL about formatting... just paste there...

          1. All understand - I will report.

            About the code: look above in the article and try to Ctrl-C 😀
            It is not provided (I think by mistake) as the link.

        2. There IS a recommended grid size - but the phone I was using at the time I first did this was not having the recommended grid size. Ii got the flow code out of the clipboard so it will go back in.

          Icons - as I'm not 100% sure which ones were licenced for general use it woul dnot be nice of me to put them up there in a library. All are commonly available.

          1. Thanks for reply, Peter. I understand all reasons and I didn't want to bother you with such a "rubbish". My comment was mainly to find the way and give a feedback to others following your way.
            The grid is only "cosmetic" issue and can be solved with few clicks.

            icons - I have found open source icon library with the icon naming similar to yours:
            For me it works partially.

            Gauge: will be investigated 😀

              1. Changes in the path to the fonts in the following template nodes:
                Settings section: more, mmore, up, down
                Changing some styles and fonts. adding ° (degree sign).
                Now looks wee better in my Dark Theme. Thank you.
                Next week I will investigate "The Gauge" 😀

                    1. It looks js is not loaded.
                      I have double checked the path. Path is OK.
                      All files have reading rights.

                    2. .js is loaded properly.
                      If i change the name of js file, in the newergauge template, then I get the 404 error:
                      app.min.js:20 GET 404 (Not Found)

                      Problem is here:

                      scope.$watch('msg', function(msg) {
                      // if (msg.units!="") gauge.units=msg.units;

                      var gauge = new RadialGauge({

                      Uncaught ReferenceError: RadialGauge is not defined

                  1. It is matter of taste of course. I am not convinced about the size and the dark theme as well.
                    It was the way to learn. I think I didn't do all the changes the proper way. It is better to do changes more general (styles), than change the code directly in td tags for example.
                    How to put tags here in the discussion, so I can include my NR flow here?

      2. I'm playing with grid size now - that will vary from phone to phone, originally the phone I used had an aspect ratio like old-fashioned Apple, today many phones are more like 18:9 or even longer. Just adjust grid sizes.... unless you have some other code over which you have no control.

  4. Correct Antonio, thanks for filling in that detail. Here's another (resolved) complication.

    1. Even though ENABLE isn't used on those displays - the SS pin (GPIO15) is used by SPI and so can't be used elsewhere. Also, even though MOSI isn't used, SPI insists on controlling that (GPIO13) also. Which leads us to the additional complication:

    I've always tied processor reset to display reset. This works well for other displays but these litle (what I call QDTECH) displays are not always 100% happy with that and I've only just realised that. Hence later this morning I'll upload to BitBucket a mod I've made to ESP-GO - which will, for the init code for these displays only, momentarily set (otherwise never used) GPIO as an output and to ground, then back up to Vcc, before setting it back as an input. The diaplay init code is now delayed by 250ms to cater for this... hence ensuring a perfect display startup which needs to occur whenever the display logs in (ie the display may have been disconnected or otherwise rebooted) OR Node-RED starts up.

    1. BitBucket is now fully updated. I'm working on a way with 2 diodes to simulate a third input on the stat with a third button but no extra bits - but it looks like the internal pullups on gpio4 and 5 are too high to trigger the diodes... so it's looking like 4k7 external pullups right now.

        1. I have posted a question about it in to the NR group.
          I was trying to attaching my attempts to modify your code as a txt file here. No success.
          How to post it here?

            1. [{"id":"576d80bb.d779","type":"ui_template","z":"d2f37368.5b066","group":"8dff2b2d.fd0828","name":"newergauge","order":1,"width":"1","height":"3","format":"<script type=\"text/javascript\" src=\"/verejne/gauge.min.js\"></script>\n\n<canvas style=\"margin-left: auto; margin-right: auto; margin-top: auto; margin-bottom: auto; outline: none;\"\n    ng-click=\"send({payload: ' '})\"  width=95% heigth=95% id=\"canvas-id\">\n</canvas>\n\n<script>\n   (function(scope){\n        scope.$watch('msg', function(msg) {\n           gauge.value=msg.payload;\n           // if (msg.units!=\"\") gauge.units=msg.units;\n        });\n    })(scope);\n    \n//var gauge = new RadialGauge({\nvar gauge = new LinearGauge({\n    renderTo: 'canvas-id',\n    width: 90,\n    height: 300,\n    borderRadius: 12,\n    units: \"°C\",\n    animationRule: 'elastic',\n    valueBox: true,\n    valueBoxWidth:5,\n    title: \"Thermostat\",\n    minValue: 10,\n    maxValue: 30,\n    majorTicks: [\n        '10',\n        '15',\n        '20',\n        '25',\n        '30'\n    ],\n    minorTicks: 5,\n    strokeTicks: true,\n   highlights  : [\n        { from : 10,  to : 15, color : '#8888ff' },\n        { from : 15, to : 20, color :  '#88ff88' },\n        { from : 20, to : 25, color :  '#ffff00' },\n        { from : 25, to : 30, color :  '#ff8888' }\n    ],\n\n    colorPlate: \"#fff\",\n    borderShadowWidth: 0,\n    borders: true,\n    needleType: \"arrow\",\n    valueInt: 2,\n    valueDec:0,\n    needleWidth: 2,\n    fontTitleSize: 50,\n    fontNumbersSize:50,\n    fontUnitsSize:50,\n    fontValueSize:50,\n    needleCircleSize: 14,\n    needleCircleOuter: true,\n    needleCircleInner: false,\n    animationDuration: 500,\n    animationRule: \"linear\"\n}).draw();\n\ngauge.value = 18;\n\n</script>\n","storeOutMessages":false,"fwdInMessages":false,"templateScope":"local","x":1092,"y":466,"wires":[["8cffe97f.518768","219dddf6.5344b2"]]},{"id":"8dff2b2d.fd0828","type":"ui_group","z":"","name":"Stat","tab":"d2a56c85.3868a","disp":false,"width":"4","collapse":false},{"id":"d2a56c85.3868a","type":"ui_tab","z":"","name":"Stat","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
                1. Its a kind of magic.... 😀
                  I will let the secret know to Peter only, when he returns from his shopping in the afternoon 😀
                  Anyway, plugin required to do this trick is installed already in Peter's WordPress. It is the same plugin I wanted to recommend to him. It is necessary to use the proper tag, exactly as you are asking for.

                  1. Hi Petr

                    i could not find the exact hjighlighter you mentioned - I have Syntax Highlighter Evolved 3.5

                    All of the ones out there have one or two words in addition to "Syntax Highlighter" - just want to make sure we're on the same page. Back this afternoon.

                    1. Yes, we are on the same page. I have found this plugin as well yesterday night and I was doing bunch of setting experiments.
                      Finally, when I found how to use it, was trying to put all instructions here (including the tag example!).
                      In that moment I have discovered my tag example is gone 😀 This happened because on your WordPress the appropriate plugin was installed already.
                      I am attaching the tag example as a picture. Otherwise it is not visible here (and I don't know the tags to put around example, so it is not accepted as a tag by the WordPress plugin.)

                    2. Looking at the "oneliner" on your page... it does not work properly.
                      My experimental setting of the SyntaxHighlighter plugin in the attachment.
                      You can find some exampl tags down on the plugin setting page.

        1. Thank you. BTW it is all your work I think 😀
          I have ordered ESP and display and other parts two days ago and I will try to follow your way. Not easy to me. js is the HORRIBLE experience to me.
          I am a Pythonier and I am seriously lost inside all those brackets, semicolons and other stuff. How the hell you and all other people can write the code in it?

          1. Sorry - original display now junked... now using ILI9341... much better reliability. Using one with touch panel but ignoring touch panel as not supported in my code.. they were CHEAP from AliExpress. Wait for new flow - fixed lots of bugs. It is VITAL I get this right, hence willingness to change. It has to go in the house in the next week on test until April - from there it has to work 24-7 for at least 6 months - Original display wasnt starting up reliably, This is WAY better. Also fixed settings backup issues - a silly problem caused by switching some vars from global to flow. All sorted. I'm not seeing a picture.

        1. I think I found a way - the big problem was \n arrearing in the code instead of carriage return - fixed that. I've formatted as Javascript - but actually it's a complete mix of CSS and html and javascript... still - what I have now is better (refresh your browser).

    1. That is the NR formating problem.... I am lost there and always experimenting kind of with it... I don’t understand how to keep more projects inside NR (when the projects are for different screen sizes). I use my NR to monitor our deep freeze store (not active elements/settings to set the values and so on yet).
      You can see it here.
      node-ui / KotelnikFace

      In the tabs you can see some of my other attempts (I am using NR for 14 days only, so sorry about it) I am experimenting with DataTables now and with your thermomete. On my home tablet I see thermometer properly ( ) The only problem is, it does not hide the status bar automatically ... but this is a problem of the all NR screens as far I know...
      Thanks to this post I have discovered that outside of my network the Thermometer is not showing icon pictures. Inside my network it works fine.

      I will fix it later on, I think It is the nginx stuff which I am experimenting with as well....

      Can you share some experiences how to expose NR to the outside word (outside of the local network)?
      Is the NR security for this OK?

        1. Yes, you are right with VPN. But what mobile phones? I have no experiences with the VPN on mobiles. On PC (Linux, Windows) only.

          Generally I am asking about experiences/suggestions with NR built in authentication/security.
          How to use the Thermometer from the outside of local network on the mobile?

          1. Peter uses his phone to connect to his openvpn setups with easy, AFAIK... go in your device settings and see what types are available... for outside access i'll go different way, telegram, alexa or google home connected to nodered and interfacing to it locally...

            1. I see. Interesting. So, talking about Telegram, for example, you have your own "command set" and you are sending it to the NR? What about sending mqtt commands instead. I am new in this stuff, so sorry if my questions sounds dumb kind of....

                1. Using Telegram seems quite straightforward.
                  I searched ways of using Whatsapp or FB Messenger because I already have them on my mobile but there is no free API.
                  I'll give a go.

      1. I much prefer your fonts + degree symbol - and actually youir stat - what did you change?

        I dont use SSL - but then I use a VPN to access it. PIVPN (ehich mysteriously stopped working last week after months of reliable operation)

        1. I do not remember all my steps exactly.
          I will try to check your new flow you have published today and make notes about my changes. Is it OK for you?

          1. Hi Petr
            I'm miles ahead of you - I remember now how I did all the formatting - I'm changing the fonts right now, I would wait a while if I were you - more changes to come - I just lost an hour fixing my VPN... all I need from you are those degree symbols. I've no idea how to do that... please...

            1. ° is VERY easy. Open the appropriate node (SET, newergauge, ..). where the temperature is propagated from, find the sign C and append a ° sign beside it.
              For example in newergauge: units: "°C",
              Thats it. Easy peasy. HTH

              PS: your "oneline" code setting is still not OK, there are some tags in front of it and at the end.

  5. hello Pete

    A bit behind on this one, as Iv been focusing on my Orangepi 2e.

    Thought you might to see my attempts after your article on RGraph they are

    incorporated in my sons house. Might be suitable for the temperature display.


Leave a Reply

Your e-mail address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.