# Opentherm Thermostat

**URL:** <https://discourse.nodered.org/t/opentherm-thermostat/72954>\
**Category:** Share Your Projects\
**Tags:** node-red-dashboard\
**Created:** [30 December 2022 12:39 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954 "2022-12-30T12:39:10Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![maxuser74](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxuser74/32/70109_2.png) [@maxuser74](https://discourse.nodered.org/u/maxuser74)\
**Post date:** [30 December 2022 12:39 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/1 "2022-12-30T12:39:10Z")

</div>

Hi guys,  
I want to share my implementation of Opentherm Tasmota and its integration with a template node in Node Red Dashboard.  
I use it to remotely command the central heating boiler into my holiday house.  
The hardware is based on a Wemos D1 ESP8266, with just an Opentherm Shield for levels compensation and a DS18B20 digital temperature sensor.

This is the Dashboard Template i made (with some CSS involved):

- on the left panel the measured temperature (DS18B20 sensor)
- at its right, the temperature setpoint
- at the far right, on top the power button which has three state, off (greyed out), auto (blue), heating on (red) ... this is a clickable / status button
- at its bottom, the flame status (greyed = off, red = on)
- under temp set point the two buttons to increase the temp set point or decrease it (clickable buttons with icons)
- at the very bottom, a string with all the most important datas coming from Opentherm communication with boiler

Here with heating turned off, ambient temperature = 17,3 C and setpoint ad 19,5 C

 ![Screenshot_20221230_131751](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/7/779e0bd1221bb74c82500b0979252807e2e0c1f1.jpeg)

Heating turned on (auto) but setpoint lower than ambient temperature

 ![Screenshot_20221230_131957](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/0/7/071c324ef09ffae34648ec7c9de9863fe98c1953.jpeg)

Heater turned on but flame not yet on.

 ![Screenshot_20221230_131838](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/0/d048e3b3b6c6b1d88b7f6f1a19246fce911800dd.jpeg)

Heating turned on and boiler flame on

 ![Screenshot_20221230_131920](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/8/8/8893a4c980e150391624bb12d97c7e5f280fa18f.jpeg)

In the opentherm message status row some informations are displayed, such as:  
connection status  
Flame modulation  
Boiler temperature (measured)  
Water temperature (measured)  
Central heating status (1 / 0)  
Flame status (1 / 0)  
Boiler temperature (setpoint)  
Water temperature (setpoint)  
Water pressure  
Fault status

I hope someone enjoy, feel free to ask for more information!

---

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [30 December 2022 14:23 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/2 "2022-12-30T14:23:46Z")

</div>

Would you perhaps share you code?

---

<div class="post-metadata">

**Author:** ![maxuser74](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxuser74/32/70109_2.png) [@maxuser74](https://discourse.nodered.org/u/maxuser74)\
**Post date:** [1 January 2023 17:52 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/3 "2023-01-01T17:52:15Z")

</div>

Sure,  
here it is.

Screenshot

 ![Screenshot 2023-01-01 alle 18.54.55](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/7/17f47b16118ac3938a77dc8b32d66210462bce51.png)

Code

```auto
[
    {
        "id": "7bd28316dc37d295",
        "type": "tab",
        "label": "Thermo2",
        "disabled": true,
        "info": "",
        "env": []
    },
    {
        "id": "d721b34520a32a61",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "temp_set",
        "rules": [
            {
                "t": "set",
                "p": "temp_set",
                "pt": "flow",
                "to": "19.5",
                "tot": "num"
            },
            {
                "t": "set",
                "p": "temp_set",
                "pt": "msg",
                "to": "temp_set",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 300,
        "y": 280,
        "wires": [
            [
                "fbd7edfb9e617ee1"
            ]
        ]
    },
    {
        "id": "fbd7edfb9e617ee1",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "temp_amb",
        "rules": [
            {
                "t": "set",
                "p": "temp_amb",
                "pt": "flow",
                "to": "20.0",
                "tot": "num"
            },
            {
                "t": "set",
                "p": "temp_amb",
                "pt": "msg",
                "to": "temp_amb",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 450,
        "y": 280,
        "wires": [
            [
                "5e92c010cbf93331"
            ]
        ]
    },
    {
        "id": "ae894b52eb94ae0b",
        "type": "ui_template",
        "z": "7bd28316dc37d295",
        "group": "e15b980fd008f6a8",
        "name": "Thermostat Template",
        "order": 4,
        "width": "6",
        "height": "4",
        "format": "<style>\n . {\n box-sizing: border-box;\n font-family: \"Roboto\",\"Helvetica Neue\", sans-serif ;\n }\n\n .container {\n display: flex;\n width: 100%;\n height: 100%;\n background-color: #303030;\n }\n\n\n .centerme {\n display: flex;\n text-align: center;\n justify-content: center;\n align-items: center;\n margin: 4px;\n }\n\n .roundme {\n border: 2px solid black;\n border-radius: 8px;\n background-color: #222222;\n box-shadow: inset 2px 2px 3px 4px rgba(0, 0, 0, 0.1);\n background: rgb(5, 5, 5);\n background: linear-gradient(135deg, rgba(5, 5, 5, 1) 0%, rgba(42, 42, 42, 1) 100%);\n margin: 3px;\n }\n \n .roundme2 {\n border: 2px solid black;\n border-radius: 8px;\n background-color: #222222;\n box-shadow: inset 2px 2px 3px 4px rgba(0, 0, 0, 0.1);\n background: rgb(5, 5, 5);\n margin: 3px;\n }\n\n .a1 {\n /* background-color:red; */\n height: 25px;\n margin-bottom: 1px;\n font-size: 16px;\n color: #6689A1;\n padding-bottom: 4px;\n border-bottom: 2px solid #DD7F00;\n\n }\n\n .a2 {\n /* background-color:red; */\n height: 100%;\n margin-top: 1px;\n font-size: 60px;\n color: #D7DBDD;\n\n }\n\n .b1 {\n color: #6689A1;\n height: 25px;\n margin-bottom: 1px;\n font-size: 16px;\n padding-bottom: 4px;\n border-bottom: 2px solid #DD7F00;\n }\n\n .b2 {\n height: 100%;\n margin-top: 1px; \n font-size: 28px;\n color: #D7DBDD;\n }\n\n .gradient-2 {\n background: linear-gradient(135deg, rgba(5, 5, 5, 1) 0%, rgba(42, 42, 42, 1) 100%) padding-box,\n linear-gradient(to right, #F16F0F, #F43700) border-box;\n margin-top:14px;\n border-radius: 20px;\n border: 6px solid transparent;\n }\n \n .red_color {\n color: #FF0000;\n }\n \n .grey_color {\n color: #444444;\n }\n\n .blue_color {\n color: #00DAF4;\n }\n \n \n .otstatus {\n padding-left: 6px;\n padding-top: 2px;\n font-size: 14px;\n\n }\n\n@keyframes fire {\n from {color: #FF5B33;}\n 50% {color: #FFAC33;}\n to {color: #FF5B33;}\n}\n\n.on_fire {\n animation-name: fire;\n animation-duration: 2000ms;\n animation-iteration-count:infinite;\n}\n\n\n\n</style>\n\n<div class=\"container\" layout=\"column\">\n <div layout=\"row\" flex=\"80\">\n <div layout=\"column\" flex=\"50\" class=\"roundme\">\n <div class=\"a1 centerme\">Temp Ambiente</div>\n <div class=\"a2 centerme\" ng-class=\"temp_amb_status\" ng-model=\"temp_amb_status\" ng-bind-html=\"temp_amb_ | number: 1\"></div>\n </div>\n \n <div flex=\"50\" layout=\"column\">\n <div flex=\"70\" layout=\"row\">\n \n <div layout=\"column\" flex=\"60\" class=\"roundme\">\n <div class=\"b1 centerme\">Temp Set</div>\n <div class=\"b2 centerme\" ng-bind-html=\"temp_set_ | number: 1\" ></div>\n </div>\n \n <div flex=\"40\" layout=\"column\">\n <div flex=\"50\" class=\"centerme roundme\" ng-click=\"click_power();\">\n <md-icon md-font-icon=\"power_settings_new\" style=\"font-size:32px\" ng-class=\"power_status_icon\"></md-icon>\n </div>\n <div flex=\"50\" class=\"centerme roundme\">\n <md-icon md-font-icon=\"local_fire_department\" style=\"font-size:32px\" ng-class=\"heating_status_icon\"></md-icon>\n </div>\n </div>\n \n </div>\n <div flex=\"30\">\n <div layout=\"row\" style=\"height:100%\">\n <md-button flex=\"50\" class=\"centerme roundme\" ng-click=\"click_temp_minus()\">\n <md-icon md-font-icon=\"remove\" style=\"font-size:32px\"></md-icon>\n </md-button>\n <md-button flex=\"50\" class=\"centerme roundme\" ng-click=\"click_temp_plus()\">\n <md-icon md-font-icon=\"add\" style=\"font-size:32px\"></md-icon>\n </md-button>\n </div>\n </div>\n </div>\n </div>\n\n <div layout=\"row\" flex=\"20\" class=\"roundme2 otstatus\">\n <div layout=\"column\"> \n <div flex=\"50\" ng-bind-html=\"ot_status1\"></div>\n <div flex=\"50\" ng-bind-html=\"ot_status2\"></div>\n </div>\n </div>\n</div>\n\n<script>\n (function(scope) {\n\n scope.$watch('msg', function(msg) \n {\n\n if(msg.hasOwnProperty('temp_set')) {\n scope.temp_set_ = msg.temp_set;\n }\n\n if(msg.hasOwnProperty('temp_amb')) {\n scope.temp_amb_ = msg.temp_amb;\n }\n\n if(msg.hasOwnProperty('heating')) {\n if(msg.heating==\"on\") {\n scope.temp_amb_status=\"gradient-2\";\n }\n if(msg.heating==\"off\") {\n scope.temp_amb_status=\"\";\n } \n }\n \n // Opentherm status\n if(msg.hasOwnProperty('ot_status1')) {\n scope.ot_status1 = msg.ot_status1;\n scope.ot_status2 = msg.ot_status2;\n }\n\n // Power status check \n if(msg.hasOwnProperty('power_status')) {\n if(msg.power_status==true) {\n scope.power_status_icon=\"blue_color\";\n }\n if(msg.power_status==false) {\n scope.power_status_icon=\"grey_color\";\n } \n }\n\n // Heating status check\n if(msg.hasOwnProperty('heating_status')) {\n if(msg.heating_status==1) {\n scope.power_status_icon=\"red_color\";\n }\n }\n \n // Flame status check\n if(msg.hasOwnProperty('flame_status')) {\n if(msg.flame_status==true) {\n// scope.heating_status_icon=\"red_color\";\n scope.heating_status_icon=\"on_fire\";\n\n }\n if(msg.flame_status==false) {\n scope.heating_status_icon=\"grey_color\";\n }\n }\n // End flame status check //\n\n return;\n }); \n\n scope.click_power = function() {\n scope.send({ \"payload\": \"power\"});\n }\n\n scope.click_temp_plus = function() {\n scope.send({ \"payload\": \"temp_plus\"});\n }\n\n scope.click_temp_minus = function() {\n scope.send({ \"payload\": \"temp_minus\"});\n }\n \n})(scope);\n\n</script>\n\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "resendOnRefresh": false,
        "templateScope": "local",
        "className": "",
        "x": 920,
        "y": 380,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "da16bc54c2ef5db2",
        "type": "function",
        "z": "7bd28316dc37d295",
        "name": "Thermostat logic",
        "func": "var power_status = flow.get('power_status');\nvar temp_set = flow.get('temp_set'); \nvar temp_amb = flow.get('temp_amb');\nvar heating_status = flow.get('heating_status');\nvar ot_status1 = flow.get('ot_status1');\nvar ot_status2 = flow.get('ot_status2');\nvar flame_status = flow.get('flame_status');\nvar ch_status = flow.get('ch_status');\nvar msg2 = { payload: \"payload\", topic: \"topic\" }\n\nif(msg.hasOwnProperty('ot_status1')){\n flow.set('ot_status1',msg.ot_status1);\n flow.set('ot_status2',msg.ot_status2);\n}\n\nif(msg.hasOwnProperty('flame_status')){\n flow.set('flame_status',msg.flame_status);\n}\n\nif(msg.hasOwnProperty('ch_status')){\n flow.set('ch_status',msg.ch_status);\n}\n\nif(msg.payload==\"power\"){\n power_status = !power_status;\n flow.set('power_status',power_status);\n}\n\nif(msg.payload==\"temp_plus\"){\n temp_set = temp_set + 0.5;\n flow.set('temp_set',temp_set);\n}\n\nif(msg.payload==\"temp_minus\"){\n temp_set = temp_set - 0.5;\n flow.set('temp_set',temp_set);\n}\n\nif(power_status){\n if(heating_status)\n {\n\n // riscaldamento acceso e temperatura set minore o uguale di temp ambiente\n if (temp_set <= temp_amb+0.2) {\n heating_status = false;\n }\n }\n else\n {\n // riscaldamento spento e temperatura set maggiore di temp ambiente\n if (temp_set > temp_amb+0.2) {\n heating_status = true;\n }\n\n } \n\n flow.set('heating_status', heating_status);\n}\nelse{\n heating_status = false;\n flow.set('heating_status', heating_status); \n}\n\nmsg.power_status = flow.get('power_status');\nmsg.temp_amb = flow.get('temp_amb');\nmsg.temp_set = flow.get('temp_set');\nmsg.ot_status1 = flow.get('ot_status1');\nmsg.ot_status2 = flow.get('ot_status2');\nmsg.flame_status = flow.get('flame_status');\nmsg.ch_status = flow.get('ch_status');\nmsg.heating_status = flow.get('heating_status');\n\nif (flow.get('heating_status')) {\n msg2.payload = 1;\n} else {\n msg2.payload = 0;\n}\n\nreturn [msg, msg2];",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 910,
        "y": 440,
        "wires": [
            [
                "ae894b52eb94ae0b"
            ],
            [
                "9733bb3381da8ff6"
            ]
        ]
    },
    {
        "id": "a9865b0db96580e8",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "true",
                "tot": "bool"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 660,
        "y": 600,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "3293b42b8867bdb3",
        "type": "switch",
        "z": "7bd28316dc37d295",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "eq",
                "v": "connect",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 510,
        "y": 600,
        "wires": [
            [
                "a9865b0db96580e8"
            ]
        ]
    },
    {
        "id": "820176597df91726",
        "type": "ui_ui_control",
        "z": "7bd28316dc37d295",
        "name": "",
        "events": "connect",
        "x": 340,
        "y": 600,
        "wires": [
            [
                "3293b42b8867bdb3"
            ]
        ]
    },
    {
        "id": "5c6643565e2ddab2",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": "0.2",
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 370,
        "y": 640,
        "wires": [
            [
                "3293b42b8867bdb3"
            ]
        ]
    },
    {
        "id": "5e92c010cbf93331",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "power_status",
        "rules": [
            {
                "t": "set",
                "p": "power_status",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "power_status",
                "pt": "msg",
                "to": "power_status",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 620,
        "y": 280,
        "wires": [
            [
                "c98ab4ede699f7b7"
            ]
        ]
    },
    {
        "id": "c98ab4ede699f7b7",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "heating_status",
        "rules": [
            {
                "t": "set",
                "p": "heating_status",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "heating_status",
                "pt": "msg",
                "to": "heating_status",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 180,
        "y": 340,
        "wires": [
            [
                "60021c373e8cdb53"
            ]
        ]
    },
    {
        "id": "5cb475e23794806d",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 150,
        "y": 280,
        "wires": [
            [
                "d721b34520a32a61"
            ]
        ]
    },
    {
        "id": "5c63f60ed55988e0",
        "type": "mqtt in",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "tele/thermostat/SENSOR",
        "qos": "1",
        "datatype": "auto-detect",
        "broker": "51912773f7db93ee",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 170,
        "y": 420,
        "wires": [
            [
                "191edada74781373",
                "d3347086d32027ca",
                "d321e94ddc708b4a",
                "5624399ecc1ccfc9"
            ]
        ]
    },
    {
        "id": "191edada74781373",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "payload.DS18B20.Temperature",
        "rules": [
            {
                "t": "set",
                "p": "temp_amb",
                "pt": "flow",
                "to": "payload.DS18B20.Temperature",
                "tot": "msg"
            },
            {
                "t": "set",
                "p": "temp_amb",
                "pt": "msg",
                "to": "temp_amb",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 530,
        "y": 420,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "ae60fe1eeac4218f",
        "type": "mqtt out",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "cmnd/thermostat/ot_tboiler",
        "qos": "1",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "51912773f7db93ee",
        "x": 400,
        "y": 100,
        "wires": []
    },
    {
        "id": "8af3775d92279529",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "3600",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "60",
        "payloadType": "num",
        "x": 150,
        "y": 100,
        "wires": [
            [
                "ae60fe1eeac4218f"
            ]
        ]
    },
    {
        "id": "d3347086d32027ca",
        "type": "switch",
        "z": "7bd28316dc37d295",
        "name": "OPENTHERM",
        "property": "payload.OPENTHERM",
        "propertyType": "msg",
        "rules": [
            {
                "t": "hask",
                "v": "conn",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 460,
        "y": 480,
        "wires": [
            [
                "9925554e77622b21"
            ]
        ]
    },
    {
        "id": "9925554e77622b21",
        "type": "function",
        "z": "7bd28316dc37d295",
        "name": "OT MESSAGE",
        "func": "msg.ot_status1 = msg.payload.OPENTHERM.conn +\n \"&nbsp&nbsp&nbsp&nbspFLM:\" + msg.payload.OPENTHERM.FLM +\n \"&nbsp&nbsp&nbsp&nbspTB:\" + msg.payload.OPENTHERM.TB + \n \"&nbsp&nbsp&nbsp&nbspTW:\" + msg.payload.OPENTHERM.TDHW + \n \"&nbsp&nbsp&nbsp&nbspCH:\" + msg.payload.OPENTHERM.SLAVE.CH + \n \"&nbsp&nbsp&nbsp&nbspFL:\" + msg.payload.OPENTHERM.SLAVE.FL;\n \nmsg.ot_status2 = \"TBS:\" + msg.payload.OPENTHERM.BTMP.REQ +\n \"&nbsp&nbsp&nbsp&nbspTWS:\" + msg.payload.OPENTHERM.HWTMP.REQ + \n \"&nbsp&nbsp&nbsp&nbspWP:\" + msg.payload.OPENTHERM.OT18 +\n \"&nbsp&nbsp&nbsp&nbspFAULT:\" + msg.payload.OPENTHERM.SLAVE.FAULT;\n \nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 660,
        "y": 480,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "60021c373e8cdb53",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "ot_status",
        "rules": [
            {
                "t": "set",
                "p": "ot_status1",
                "pt": "flow",
                "to": " **********************************************",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "ot_status1",
                "pt": "msg",
                "to": "ot_status1",
                "tot": "flow"
            },
            {
                "t": "set",
                "p": "ot_status2",
                "pt": "flow",
                "to": " **********************************************",
                "tot": "str"
            },
            {
                "t": "set",
                "p": "ot_status2",
                "pt": "msg",
                "to": "ot_status2",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 360,
        "y": 340,
        "wires": [
            [
                "bf555a791259f82e"
            ]
        ]
    },
    {
        "id": "9733bb3381da8ff6",
        "type": "mqtt out",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "cmnd/thermostat/ot_ch",
        "qos": "1",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "51912773f7db93ee",
        "x": 1170,
        "y": 440,
        "wires": []
    },
    {
        "id": "bf555a791259f82e",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "flame_status",
        "rules": [
            {
                "t": "set",
                "p": "flame_status",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "flame_status",
                "pt": "msg",
                "to": "flame_status",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 510,
        "y": 340,
        "wires": [
            [
                "7a139d8a4e8c1df7"
            ]
        ]
    },
    {
        "id": "d321e94ddc708b4a",
        "type": "switch",
        "z": "7bd28316dc37d295",
        "name": "OPENTHERM CH",
        "property": "payload.OPENTHERM.SLAVE",
        "propertyType": "msg",
        "rules": [
            {
                "t": "hask",
                "v": "CH",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 470,
        "y": 520,
        "wires": [
            [
                "8bddba416ec36bef"
            ]
        ]
    },
    {
        "id": "8bddba416ec36bef",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "CH STATUS",
        "rules": [
            {
                "t": "set",
                "p": "ch_status",
                "pt": "msg",
                "to": "payload.OPENTHERM.SLAVE.CH",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 670,
        "y": 520,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "5624399ecc1ccfc9",
        "type": "switch",
        "z": "7bd28316dc37d295",
        "name": "OPENTHERM FL",
        "property": "payload.OPENTHERM.SLAVE",
        "propertyType": "msg",
        "rules": [
            {
                "t": "hask",
                "v": "FL",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 1,
        "x": 470,
        "y": 560,
        "wires": [
            [
                "30909829b5045b31"
            ]
        ]
    },
    {
        "id": "30909829b5045b31",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "FL STATUS",
        "rules": [
            {
                "t": "set",
                "p": "flame_status",
                "pt": "msg",
                "to": "payload.OPENTHERM.SLAVE.FL",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 670,
        "y": 560,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "e577dd9a20a8218f",
        "type": "mqtt out",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "cmnd/thermostat/ot_twater",
        "qos": "1",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "51912773f7db93ee",
        "x": 400,
        "y": 60,
        "wires": []
    },
    {
        "id": "5fa6a6aae36ea2b0",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "3600",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "36",
        "payloadType": "num",
        "x": 150,
        "y": 60,
        "wires": [
            [
                "e577dd9a20a8218f"
            ]
        ]
    },
    {
        "id": "7a139d8a4e8c1df7",
        "type": "change",
        "z": "7bd28316dc37d295",
        "name": "ch_status",
        "rules": [
            {
                "t": "set",
                "p": "ch_status",
                "pt": "flow",
                "to": "false",
                "tot": "bool"
            },
            {
                "t": "set",
                "p": "ch_status",
                "pt": "msg",
                "to": "ch_status",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 680,
        "y": 340,
        "wires": [
            [
                "da16bc54c2ef5db2"
            ]
        ]
    },
    {
        "id": "f5aafa28f45bf19d",
        "type": "mqtt out",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "cmnd/thermostat/Restart",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "51912773f7db93ee",
        "x": 390,
        "y": 160,
        "wires": []
    },
    {
        "id": "7204c37b7a3eaae0",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "05:00",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "00 05 * * *",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "1",
        "payloadType": "num",
        "x": 150,
        "y": 160,
        "wires": [
            [
                "f5aafa28f45bf19d"
            ]
        ]
    },
    {
        "id": "fd52ae383a8b0694",
        "type": "inject",
        "z": "7bd28316dc37d295",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "3600",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "10",
        "payloadType": "num",
        "x": 150,
        "y": 220,
        "wires": [
            [
                "6cfe3bed14aba2f3"
            ]
        ]
    },
    {
        "id": "6cfe3bed14aba2f3",
        "type": "mqtt out",
        "z": "7bd28316dc37d295",
        "name": "",
        "topic": "cmnd/thermostat/TelePeriod",
        "qos": "",
        "retain": "",
        "respTopic": "",
        "contentType": "",
        "userProps": "",
        "correl": "",
        "expiry": "",
        "broker": "51912773f7db93ee",
        "x": 380,
        "y": 220,
        "wires": []
    },
    {
        "id": "e15b980fd008f6a8",
        "type": "ui_group",
        "name": "Termostato Borghi",
        "tab": "d9d243d87692d13f",
        "order": 10,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "51912773f7db93ee",
        "type": "mqtt-broker",
        "name": "Dummy MQTT",
        "broker": "0.0.0.0",
        "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": {},
        "userProps": "",
        "sessionExpiry": ""
    },
    {
        "id": "d9d243d87692d13f",
        "type": "ui_tab",
        "name": "Dashboard",
        "icon": "dashboard",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]

```

---

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [1 January 2023 19:27 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/4 "2023-01-01T19:27:38Z")

</div>

Absolutely outstanding, thanks

---

<div class="post-metadata">

**Author:** ![gerry](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gerry/32/21604_2.png) [@gerry](https://discourse.nodered.org/u/gerry)\
**Post date:** [2 January 2023 11:30 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/5 "2023-01-02T11:30:26Z")

</div>

In case you didn't think about it I would set limits on how high or low you can set the temp. I use 10 as a low limit and 25 as a high limit. This is a personal just because for me.

---

<div class="post-metadata">

**Author:** ![maxuser74](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/maxuser74/32/70109_2.png) [@maxuser74](https://discourse.nodered.org/u/maxuser74)\
**Post date:** [2 January 2023 12:35 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/6 "2023-01-02T12:35:58Z")

</div>

> In case you didn't think about it I would set limits on how high or low you can set the temp. I use 10 as a low limit and 25 as a high limit. This is a personal just because for me.

You're absolutely right.  
Thanks

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [2 January 2023 14:27 UTC](https://discourse.nodered.org/t/opentherm-thermostat/72954/7 "2023-01-02T14:27:22Z")

</div>

> [@gerry](#):
>
> 25 as a high limit

You'd need to be rich to afford that in the UK right now. ☹ My max is 20!
