Thermostat which is not a thermostat with Node RED

Hi all,

I’m new in here so I do hope you’ll be not too hard with me :sweat_smile:

So, this is what I have in my home:
I have a heater system which measure the temperature of the room and has a temperature setting.
This can be access with REST API.
I already success to read the temperature sensor with Node RED and linked with HA entity and make a dashboard card working well to test
I already success to change the temperature setpoint from Node RED to the web server.

Here bellow my Node RED:

My willing is to get that thermostat nice and look card:

Unfortunately I’m totally lost on the way to do that !

Any help would be nice !

(I already spent days for the small success of what I achieved and hours on how to make this thermostat)

I tried this kind of existing thermostat but not successful:

If I understand correctly, you should give generic thermostat a try. After to have it set up, you can use the event of the temperature attribute changing to set the actual temperature of your device from NR.

Hi @Kermit,

Thank you.
I gave it a try:

  • 1st thing is that I needed to setup a switch in Node RED linked to this thermostat in order to not get the “idle’” info in my HA Generic Thermostat. I have “integration error” in Node RED but it seams ok in HA.
    image
    image

  • 2nd is that I don’t want the thermostat give me a on / off command depending of my temperature setting point. So to avoid this I set the 2 parameters far away (in degree Celsius):

    • cold_tolerance: 0
    • hot_tolerance: 20
      Still far away to be perfect as such I got some Idle when I stop / start the thermostat.
  • 3rd thing is that I tried to find event of the temperature setting point in Node RED in order to set the temperature setting point of my regulation but I didn’t find it. Same for the status of the generic thermostat (hvac_mode or operation status):

image

I tried several things in Node RED without knowing what I’m doing as well :sweat_smile:

image

@Kermit in any case I wasn’t precised enough, I made this request which should be more precise than my initial post in here:

[{"id":"ba9c73bcc97781fd","type":"ha-switch","z":"c89d915bdff0f798","name":"dummy climate switch","version":0,"debugenabled":false,"inputs":0,"outputs":2,"entityConfig":"16f355dd4fbd4642","enableInput":false,"outputOnStateChange":false,"outputProperties":[{"property":"outputType","propertyType":"msg","value":"state change","valueType":"str"},{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":212,"y":2400,"wires":[[],[]]},{"id":"bca147d802f459be","type":"comment","z":"c89d915bdff0f798","name":"just here because the generic thermostat requires a switch. won't be used for anything","info":"","x":644,"y":2400,"wires":[]},{"id":"126c9338cbc8d6d2","type":"server-state-changed","z":"c89d915bdff0f798","name":"listen for changes to set temperature","server":"","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.thermostat","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"$entity().attributes.temperature","valueType":"jsonata"}],"x":252,"y":2496,"wires":[["dee69006ecd824ba"]]},{"id":"dee69006ecd824ba","type":"rbe","z":"c89d915bdff0f798","name":"block unless value changes","func":"rbe","gap":"","start":"","inout":"out","septopics":false,"property":"payload","topi":"topic","x":548,"y":2496,"wires":[["be0b44fe123a8fce"]]},{"id":"be0b44fe123a8fce","type":"debug","z":"c89d915bdff0f798","name":"payload contains set temperature ","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":840,"y":2496,"wires":[]},{"id":"8684f3e4a3dce1a5","type":"server-state-changed","z":"c89d915bdff0f798","name":"listen for changes to state of climate (off/heat)","server":"","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"climate.thermostat","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"x":282,"y":2544,"wires":[["0535ab16456a130a"]]},{"id":"0535ab16456a130a","type":"debug","z":"c89d915bdff0f798","name":"payload contains off/heat","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":586,"y":2544,"wires":[]},{"id":"b255152fdd5c44e3","type":"comment","z":"c89d915bdff0f798","name":"listen for events","info":"","x":192,"y":2448,"wires":[]},{"id":"c498cd87157a8069","type":"ha-sensor","z":"c89d915bdff0f798","name":"set current temp sensor","entityConfig":"86f24ae74fa0ed81","version":0,"state":"payload","stateType":"msg","attributes":[],"inputOverride":"allow","outputProperties":[],"x":658,"y":2352,"wires":[[]]},{"id":"ecccc5c5324231bd","type":"inject","z":"c89d915bdff0f798","name":"flow to set current temp to be used with climate entity","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":326,"y":2352,"wires":[["c498cd87157a8069"]]},{"id":"16f355dd4fbd4642","type":"ha-entity-config","server":"2dad33ee.42bf5c","deviceConfig":"","name":"dummy climate switch","version":"6","entityType":"switch","haConfig":[{"property":"name","value":"dummy climate switch"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""}],"resend":false,"debugEnabled":false},{"id":"86f24ae74fa0ed81","type":"ha-entity-config","server":"2dad33ee.42bf5c","deviceConfig":"","name":"current temp sensor","version":"6","entityType":"sensor","haConfig":[{"property":"name","value":"climate current temperature"},{"property":"icon","value":""},{"property":"entity_category","value":""},{"property":"entity_picture","value":""},{"property":"device_class","value":""},{"property":"unit_of_measurement","value":""},{"property":"state_class","value":""}],"resend":false,"debugEnabled":false}]
climate:
  - platform: generic_thermostat
    name: Climate
    heater: switch.dummy_switch
    target_sensor: sensor.temperature
    min_temp: 15
    max_temp: 25
    target_temp: 17
    initial_hvac_mode: "heat"
1 Like

Wonderful, thank you a lot !

Hi @Kermit,

I added a telegram notification to this in order to track every change of my temperature setting:

Then funny thing is that I know that nobody changed it but my telegram notification is often notify me of some changes :sweat_smile:

Do you have any idea why HA decide to refresh the value ?

[{“id”:“3737d34f0ebbdcc0”,“type”:“tab”,“label”:“Flow 1”,“disabled”:false,“info”:"",“env”:[]},{“id”:“5375771a5e87ea38”,“type”:“http request”,“z”:“3737d34f0ebbdcc0”,“name”:“Get SessionId”,“method”:“GET”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:“https://xxx.xxx.xxx.xxx/api/auth/login.json?user=xxxxxxx&pwd=yyyyyyy",“tls”:“90f9ea5422086ff9”,“persist”:true,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“credentials”:{“user”:"",“password”:""},“x”:860,“y”:60,“wires”:[[“eabd13827185e683”]]},{“id”:“eabd13827185e683”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:"http constitution”,“func”:“var newMsg = “https://xxx.xxx.xxx.xxx/api/menutree/write_datapoint.json?SessionId=”;\nmsg.path = newMsg + msg.payload.SessionId + “&Id=698&Type=Enumeration&Value=” + String(flow.get(“mode_salon”));\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:1080,“y”:60,“wires”:[[“a36772d46bbc47b8”]]},{“id”:“a36772d46bbc47b8”,“type”:“http request”,“z”:“3737d34f0ebbdcc0”,“name”:“Id 698 = on/off salon”,“method”:“GET”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"{{{path}}}",“tls”:“90f9ea5422086ff9”,“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“credentials”:{“user”:"",“password”:""},“x”:1360,“y”:60,“wires”:[[]]},{“id”:“ba9ed1fcb5984f03”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:“Save mode_salon”,“func”:“if (msg.payload === “off”) {\n msg.payload = 0;\n} else {\n msg.payload = 1;\n}\nflow.set(“mode_salon”, msg.payload)\nmsg.payload = flow.get(“mode_salon”)\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:870,“y”:120,“wires”:[[“cfb95afde96e9771”]]},{“id”:“14e7e456ed075147”,“type”:“rbe”,“z”:“3737d34f0ebbdcc0”,“name”:“block unless value changes”,“func”:“rbe”,“gap”:"",“start”:"",“inout”:“out”,“septopics”:false,“property”:“payload”,“topi”:“topic”,“x”:600,“y”:60,“wires”:[[“ba9ed1fcb5984f03”,“5375771a5e87ea38”]]},{“id”:“9051fae2f073fa0e”,“type”:“server-state-changed”,“z”:“3737d34f0ebbdcc0”,“name”:“listen for changes to state of climate.salon (off/heat)”,“server”:“a6d3a29f.c532”,“version”:4,“exposeToHomeAssistant”:false,“haConfig”:[{“property”:“name”,“value”:""},{“property”:“icon”,“value”:""}],“entityidfilter”:“climate.salon”,“entityidfiltertype”:“exact”,“outputinitially”:false,“state_type”:“str”,“haltifstate”:"",“halt_if_type”:“str”,“halt_if_compare”:“is”,“outputs”:1,“output_only_on_state_change”:true,“for”:“0”,“forType”:“num”,“forUnits”:“minutes”,“ignorePrevStateNull”:false,“ignorePrevStateUnknown”:false,“ignorePrevStateUnavailable”:false,“ignoreCurrentStateUnknown”:false,“ignoreCurrentStateUnavailable”:false,“outputProperties”:[{“property”:“payload”,“propertyType”:“msg”,“value”:"",“valueType”:“entityState”}],“x”:230,“y”:60,“wires”:[[“14e7e456ed075147”]]},{“id”:“a64ef79956c03183”,“type”:“http request”,“z”:“3737d34f0ebbdcc0”,“name”:“Get SessionId”,“method”:“GET”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:“https://xxx.xxx.xxx.xxx/api/auth/login.json?user=xxxxxxxx&pwd=yyyyyy",“tls”:“90f9ea5422086ff9”,“persist”:true,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“credentials”:{“user”:"",“password”:""},“x”:860,“y”:180,“wires”:[[“da61364b99bae622”]]},{“id”:“da61364b99bae622”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:"http constitution”,“func”:“var newMsg = “https://xxx.xxx.xxx.xxx/api/menutree/write_datapoint.json?SessionId=”;\nmsg.path = newMsg + msg.payload.SessionId + “&Id=695&Type=Enumeration&Value=” + String(flow.get(“mode_etage”));\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:1080,“y”:180,“wires”:[[“787a410b4ea6bae3”]]},{“id”:“787a410b4ea6bae3”,“type”:“http request”,“z”:“3737d34f0ebbdcc0”,“name”:“Id 695 = on/off étage”,“method”:“GET”,“ret”:“obj”,“paytoqs”:“ignore”,“url”:"{{{path}}}",“tls”:“90f9ea5422086ff9”,“persist”:false,“proxy”:"",“insecureHTTPParser”:false,“authType”:"",“senderr”:false,“headers”:[],“x”:1360,“y”:180,“wires”:[[]]},{“id”:“2a9bf928b4de7845”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:“Save mode_etage”,“func”:“if (msg.payload === “off”) {\n msg.payload = 0;\n} else {\n msg.payload = 1;\n}\nflow.set(“mode_etage”, msg.payload)\nmsg.payload = flow.get(“mode_etage”)\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:"",“finalize”:"",“libs”:[],“x”:870,“y”:240,“wires”:[[“cb293fb75deeaa89”]]},{“id”:“0d66da851a044731”,“type”:“rbe”,“z”:“3737d34f0ebbdcc0”,“name”:“block unless value changes”,“func”:“rbe”,“gap”:"",“start”:"",“inout”:“out”,“septopics”:false,“property”:“payload”,“topi”:“topic”,“x”:600,“y”:180,“wires”:[[“2a9bf928b4de7845”,“a64ef79956c03183”]]},{“id”:“2f452c21e3162a09”,“type”:“server-state-changed”,“z”:“3737d34f0ebbdcc0”,“name”:“listen for changes to state of climate.etage (off/heat)”,“server”:“a6d3a29f.c532”,“version”:4,“exposeToHomeAssistant”:false,“haConfig”:[{“property”:“name”,“value”:""},{“property”:“icon”,“value”:""}],“entityidfilter”:“climate.etage”,“entityidfiltertype”:“exact”,“outputinitially”:false,“state_type”:“str”,“haltifstate”:"",“halt_if_type”:“str”,“halt_if_compare”:“is”,“outputs”:1,“output_only_on_state_change”:true,“for”:“0”,“forType”:“num”,“forUnits”:“minutes”,“ignorePrevStateNull”:false,“ignorePrevStateUnknown”:false,“ignorePrevStateUnavailable”:false,“ignoreCurrentStateUnknown”:false,“ignoreCurrentStateUnavailable”:false,“outputProperties”:[{“property”:“payload”,“propertyType”:“msg”,“value”:"",“valueType”:“entityState”}],“x”:230,“y”:180,“wires”:[[“0d66da851a044731”]]},{“id”:“0356919d3496d30d”,“type”:“telegram sender”,“z”:“3737d34f0ebbdcc0”,“name”:“Info mode salon changé”,“bot”:“2dee45ff92f31786”,“haserroroutput”:false,“outputs”:1,“x”:1370,“y”:120,“wires”:[[]]},{“id”:“cfb95afde96e9771”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:“Prepare message content”,“func”:“if (msg.payload === 0) {\n msg.payload = “arrêt”;\n} else {\n msg.payload = “automatique”;\n}\nflow.set(“mode_salon_message”, msg.payload)\nmsg.payload = flow.get(“mode_salon_message”)\nmsg.payload = { “options”: { “parse_mode”: “Markdown” }, “type”: “message”, “chatId”: 999999999, “content”: “Le chauffage du salon est passé à " + flow.get(“mode_salon_message”)}\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:”",“finalize”:"",“libs”:[],“x”:1110,“y”:120,“wires”:[[“0356919d3496d30d”]]},{“id”:“ccd8bd191a55b95d”,“type”:“telegram sender”,“z”:“3737d34f0ebbdcc0”,“name”:“Info mode étage changé”,“bot”:“2dee45ff92f31786”,“haserroroutput”:false,“outputs”:1,“x”:1370,“y”:240,“wires”:[[]]},{“id”:“cb293fb75deeaa89”,“type”:“function”,“z”:“3737d34f0ebbdcc0”,“name”:“Prepare message content”,“func”:“if (msg.payload === 0) {\n msg.payload = “arrêt”;\n} else {\n msg.payload = “automatique”;\n}\nflow.set(“mode_etage_message”, msg.payload)\nmsg.payload = flow.get(“mode_etage_message”)\nmsg.payload = { “options”: { “parse_mode”: “Markdown” }, “type”: “message”, “chatId”: 999999999, “content”: “Le chauffage de l’étage est passé en mode " + flow.get(“mode_etage_message”)}\nreturn msg;”,“outputs”:1,“noerr”:0,“initialize”:”",“finalize”:"",“libs”:[],“x”:1110,“y”:240,“wires”:[[“ccd8bd191a55b95d”]]},{“id”:“90f9ea5422086ff9”,“type”:“tls-config”,“name”:"",“cert”:"",“key”:"",“ca”:"",“certname”:"",“keyname”:"",“caname”:"",“servername”:"",“verifyservercert”:false,“alpnprotocol”:""},{“id”:“a6d3a29f.c532”,“type”:“server”,“name”:“Home Assistant”,“addon”:true,“rejectUnauthorizedCerts”:true,“ha_boolean”:"",“connectionDelay”:false,“cacheJson”:false,“heartbeat”:false,“heartbeatInterval”:"",“areaSelector”:“friendlyName”,“entitySelector”:“id”,“statusSeparator”:"/",“statusYear”:“numeric”,“statusMonth”:“2-digit”,“statusDay”:“2-digit”,“statusHourCycle”:“h23”,“statusTimeFormat”:“h:m:s”,“enableGlobalContextStore”:false},{“id”:“2dee45ff92f31786”,“type”:“telegram bot”,“botname”:“Domotic_Panissage_bot”,“usernames”:“user”,“chatids”:“999999999”,“baseapiurl”:"",“updatemode”:“polling”,“pollinterval”:“300”,“usesocks”:false,“sockshost”:"",“socksprotocol”:“socks5”,“socksport”:“6667”,“socksusername”:“anonymous”,“sockspassword”:"",“bothost”:"",“botpath”:"",“localbotport”:“8443”,“publicbotport”:“8443”,“privatekey”:"",“certificate”:"",“useselfsignedcertificate”:false,“sslterminated”:false,“verboselogging”:false,“credentials”:{}}]