Compare Two Temperature Readings

Thought this was going to be simple, but I am having a heck of a time getting this right. Read a few threads that are attempting to do something similar, but I was not able get things working from those either.

My overall goal is to compare the temperature readings from two sensors in adjoining rooms. If the difference in temperature is greater than say 3 degrees I want to turn on a ceiling fan. I want to do this regardless of which sensor has the higher temperature.

My thoughts were to get the temperature values from the current state node, convert those strings to numbers, store those values as a flow context and then use a function node to get the absolute value of the difference between the two values. I got as far as storing the values as a flow context (I think?) Any manipulation of the flow context values throws some sort of error. Often NaN (not a number). If I make the function node just try to output the flow context as a msg I get am undefined error?

[{"id":"7aa8c4c163a28492","type":"tab","label":"Flow 8","disabled":false,"info":"","env":[]},{"id":"a628025a0f27d945","type":"debug","z":"7aa8c4c163a28492","name":"debug 64","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":300,"wires":[]},{"id":"ee4a1bc6d22b5341","type":"api-current-state","z":"7aa8c4c163a28492","name":"Family Room Temp","server":"b4312dad.7f0fd","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.family_room_temperature","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":130,"y":140,"wires":[["8593fbb9d1cad670"]]},{"id":"5463b5fa51bb3d2d","type":"api-current-state","z":"7aa8c4c163a28492","name":"Kitchen Temp","server":"b4312dad.7f0fd","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.kitchen_sensor_temperature","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":120,"y":200,"wires":[["904e7fdac7afb6aa"]]},{"id":"b6be20abed27559a","type":"inject","z":"7aa8c4c163a28492","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":100,"y":80,"wires":[["ee4a1bc6d22b5341","5463b5fa51bb3d2d"]]},{"id":"e5b865c328a3fedf","type":"change","z":"7aa8c4c163a28492","name":"Kitchen to Flow","rules":[{"t":"set","p":"Kitchen_Temp","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":520,"y":200,"wires":[["f2e382aa069fb9e9"]]},{"id":"8593fbb9d1cad670","type":"function","z":"7aa8c4c163a28492","name":"Fam Convert to #","func":"var text = msg.payload;\nmsg.payload = parseFloat(text);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":140,"wires":[["758f65fbde507b0b"]]},{"id":"904e7fdac7afb6aa","type":"function","z":"7aa8c4c163a28492","name":"Kitchen Convert to #","func":"var text2 = msg.payload;\nmsg.payload = parseFloat(text2);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":200,"wires":[["e5b865c328a3fedf"]]},{"id":"ead9b1e2a558fe7c","type":"debug","z":"7aa8c4c163a28492","name":"debug 66","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":680,"y":140,"wires":[]},{"id":"19824ef575a85fd0","type":"function","z":"7aa8c4c163a28492","name":"Flow to msg.payload","func":"msg.payload = flow.Kitchen_Temp;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":340,"y":300,"wires":[["a628025a0f27d945"]]},{"id":"9ece613225e4482d","type":"inject","z":"7aa8c4c163a28492","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":300,"wires":[["19824ef575a85fd0"]]},{"id":"f2e382aa069fb9e9","type":"debug","z":"7aa8c4c163a28492","name":"debug 67","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":680,"y":200,"wires":[]},{"id":"758f65fbde507b0b","type":"change","z":"7aa8c4c163a28492","name":"Fam to Flow","rules":[{"t":"set","p":"Kitchen_Temp","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":510,"y":140,"wires":[["ead9b1e2a558fe7c"]]},{"id":"b4312dad.7f0fd","type":"server","name":"Home Assistant","addon":true}]

I see now that I can force the current state node to output a number rather than a string so the first function node can be removed. Still not sure what I am doing wrong from there. Something obvious I’m sure. :grinning:

Since you are already using function nodes, then you might as well go further and extract your sensor values from the Global.
Click the Context Data icon in the upper right corner and then click the refresh icon next to the Global headline.
You will then see the Global values and one should be for homeassistant.

Here is an example on how to extract values from the sun sensor.

[{"id":"f57d7589dd5a9b5c","type":"inject","z":"be03f9025a1f137a","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":185,"y":75,"wires":[["fcb8501ba4e0c02b"]]},{"id":"fcb8501ba4e0c02b","type":"function","z":"be03f9025a1f137a","name":"function 1","func":"msg.sun = global.get('homeassistant').homeAssistant.states[\"sun.sun\"];\nmsg.sun_state = global.get('homeassistant').homeAssistant.states[\"sun.sun\"].state;\nmsg.sun_attr_next_dawn = global.get('homeassistant').homeAssistant.states[\"sun.sun\"].attributes.next_dawn;\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":375,"y":75,"wires":[["36f148efe227cbac"]]},{"id":"36f148efe227cbac","type":"debug","z":"be03f9025a1f137a","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":540,"y":75,"wires":[]}]

You can use a “render template node” with a standard jinja template:

[{"id":"ff26d1dd7cb95cd3","type":"api-render-template","z":"fa91f8f42ea22e06","name":"Higher then 3 degrees?","server":"1190584e6afd2564","version":0,"template":"{% if ((float(states('sensor.temp1')) - float(states('sensor.temp2'))) | abs > 3 ) %}\ntrue\n{% else %}\nfalse\n{% endif %}\n","resultsLocation":"payload","resultsLocationType":"msg","templateLocation":"payload","templateLocationType":"msg","x":330,"y":500,"wires":[["afb7243a05b7d0be"]]},{"id":"17e849a542083b98","type":"inject","z":"fa91f8f42ea22e06","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":120,"y":500,"wires":[["ff26d1dd7cb95cd3"]]},{"id":"afb7243a05b7d0be","type":"switch","z":"fa91f8f42ea22e06","name":"true?","property":"payload","propertyType":"msg","rules":[{"t":"regex","v":"true","vt":"str","case":false}],"checkall":"false","repair":false,"outputs":1,"x":530,"y":500,"wires":[["c8e9013f7a0e723d"]]},{"id":"3e3516f3cc75e815","type":"api-call-service","z":"fa91f8f42ea22e06","name":"turn ceiling fan on","server":"1190584e6afd2564","version":5,"debugenabled":false,"domain":"homeassistant","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.extra"],"data":"","dataType":"jsonata","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":910,"y":500,"wires":[[]]},{"id":"c8e9013f7a0e723d","type":"api-current-state","z":"fa91f8f42ea22e06","name":"ceiling fan off?","server":"1190584e6afd2564","version":3,"outputs":2,"halt_if":"false","halt_if_type":"str","halt_if_compare":"is","entity_id":"switch.airco_hk","state_type":"habool","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":0,"forType":"num","forUnits":"minutes","x":700,"y":500,"wires":[["3e3516f3cc75e815"],[]]},{"id":"1190584e6afd2564","type":"server","name":"Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]

Cool. I can see where you located the path for the various sun sensor values in the Context menus and how the function node returned those as string values in the msg. Using that process for my application, how would I then find the absolute value of the difference between two numbers from the two sensors?

Your goal was to find a absolute difference of 3 degrees between two temps and then switch the ceilling fan that’s what my flow does.

I wouldn’t bother with trying to save any values in global or flow variables. Just grab every temperature change from both sensors and compare that to the other sensor real-time. Then calculate the difference and turn the fan on or off accordingly.

[{"id":"7aa8c4c163a28492","type":"tab","label":"Flow 8","disabled":false,"info":"","env":[]},{"id":"9e418a14b1ae7d82","type":"function","z":"7aa8c4c163a28492","name":"Determine temp difference","func":"msg.difference = Math.abs(msg.upstairs_temp) - Math.round(msg.kitchen_temp);\nmsg.difference = Math.round(msg.difference);\n\nreturn msg;\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":540,"y":120,"wires":[["5a14822cb0c888e7","2aa7503fbded9482","d3d06543fad12d16","80d4c947fd5dc3cd"]]},{"id":"9c4e9729e8ce0d3a","type":"server-state-changed","z":"7aa8c4c163a28492","name":"Kitchen Temp","server":"8be923df.d66f9","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.motion_sensor_kitchen_corner_temperature","entityidfiltertype":"exact","outputinitially":true,"state_type":"num","haltifstate":"","halt_if_type":"num","halt_if_compare":"is","outputs":1,"output_only_on_state_change":false,"for":"0","forType":"num","forUnits":"minutes","ignorePrevStateNull":true,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"kitchen_temp","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":90,"y":60,"wires":[["f4a8fbb404c20dbc"]]},{"id":"682f03c1766e273d","type":"server-state-changed","z":"7aa8c4c163a28492","name":"UpStairs Temp","server":"8be923df.d66f9","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.terrapin_station_upstairs_temperature","entityidfiltertype":"exact","outputinitially":true,"state_type":"num","haltifstate":"","halt_if_type":"num","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":"upstairs_temp","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"","valueType":"triggerId"}],"x":100,"y":180,"wires":[["8e75902e16c3c6f0"]]},{"id":"5a14822cb0c888e7","type":"debug","z":"7aa8c4c163a28492","name":"debug 7","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"difference","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":220,"wires":[]},{"id":"2aa7503fbded9482","type":"debug","z":"7aa8c4c163a28492","name":"debug 8","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"kitchen_temp","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":260,"wires":[]},{"id":"d3d06543fad12d16","type":"debug","z":"7aa8c4c163a28492","name":"debug 9","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"upstairs_temp","targetType":"msg","statusVal":"","statusType":"auto","x":640,"y":300,"wires":[]},{"id":"f4a8fbb404c20dbc","type":"api-current-state","z":"7aa8c4c163a28492","name":"Get Upstairs Temp","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"num","halt_if_compare":"is","entity_id":"sensor.terrapin_station_upstairs_temperature","state_type":"num","blockInputOverrides":false,"outputProperties":[{"property":"upstairs_temp","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":310,"y":60,"wires":[["9e418a14b1ae7d82"]]},{"id":"8e75902e16c3c6f0","type":"api-current-state","z":"7aa8c4c163a28492","name":"Get Kitchen Temp","server":"8be923df.d66f9","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"sensor.motion_sensor_kitchen_corner_temperature","state_type":"str","blockInputOverrides":false,"outputProperties":[{"property":"kitchen_temp","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":310,"y":180,"wires":[["9e418a14b1ae7d82"]]},{"id":"0ef4bb37a52bc3fb","type":"api-call-service","z":"7aa8c4c163a28492","name":"Turn Fan On","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"switch","service":"turn_on","areaId":[],"deviceId":[],"entityId":["switch.shelly1_downstairs_bath_fan"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":270,"y":280,"wires":[[]]},{"id":"4cee80a4da7e9244","type":"api-call-service","z":"7aa8c4c163a28492","name":"Turn Fan On","server":"8be923df.d66f9","version":5,"debugenabled":false,"domain":"switch","service":"turn_off","areaId":[],"deviceId":[],"entityId":["switch.shelly1_downstairs_bath_fan"],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":270,"y":340,"wires":[[]]},{"id":"80d4c947fd5dc3cd","type":"switch","z":"7aa8c4c163a28492","name":"","property":"difference","propertyType":"msg","rules":[{"t":"gt","v":"3","vt":"num"},{"t":"lte","v":"3","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":110,"y":300,"wires":[["0ef4bb37a52bc3fb"],["4cee80a4da7e9244"]]},{"id":"8be923df.d66f9","type":"server","name":"homeassistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
1 Like

Yes it does. Thank you. My previous message was to another poster. To make sure I understand what your flow is doing, it grabs the sensor data (states), makes it a number (float), performs the math (-), takes the absolute value (abs) and determines whether it is greater than 3 (true) or else (false).

Correct?

Yes correct :+1:

I set the values into a msg object, but you could just do something like msg.diff = global.get…-global.get…

Hey, FWIW I adapted this flow to have my propane stove supplement my heat pump when the room temperature is at least 5° F lower than the heat pump setpoint. My heat pumps use inefficient resistive heating elements when the temperature gap is high to ramp up the temperature more quickly. I’d rather use the stove in those cases.