Record High/Low Temps for the day

Hey All,
I'm building a solar hot water heater and I'm measuring the temperature of the output water. I want to know what the hottest and lowest temps are in a day and reset those numbers at midnight.

So far I've created 2 flow variables currentExitTemp and lastHighTemp. I'm trying to compare them in a function node but something isn't right. The debug shows up as undefined.

How can I make the comparison and record the daily highs and lows?
this is the function

let currentTemp = parseFloat(msg.payload[0]);
let lastHighTemp = parseFloat(msg.payload[1]);

if (currentTemp >= lastHighTemp) {
    msg.payload = msg.payload[0];
    flow.set("lastHighTemp", msg.payload[0]);
}

else {
     msg.payload = msg.payload[1];
}

return msg;

and the flow

[
    {
        "id": "1830970fbab5a9be",
        "type": "function",
        "z": "560c131af0c0df4d",
        "name": "function 19",
        "func": "let currentTemp = parseFloat(msg.payload[0]);\nlet lastHighTemp = parseFloat(msg.payload[1]);\n\nif (currentTemp >= lastHighTemp) {\n    msg.payload = msg.payload[0];\n    flow.set(\"lastHighTemp\", msg.payload[0]);\n}\n\nelse {\n     msg.payload = msg.payload[1];\n}\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 870,
        "y": 1020,
        "wires": [
            [
                "3162e44ddd15262f"
            ]
        ]
    },
    {
        "id": "e91a94d367947402",
        "type": "ui_text",
        "z": "560c131af0c0df4d",
        "group": "7a51f7a62e395bfe",
        "order": 10,
        "width": 0,
        "height": 0,
        "name": "",
        "label": "Exit Water High Temp",
        "format": "{{flow.lastHighTemp}}",
        "layout": "row-spread",
        "className": "",
        "style": false,
        "font": "",
        "fontSize": 16,
        "color": "#000000",
        "x": 1100,
        "y": 1060,
        "wires": []
    },
    {
        "id": "5af57c58ba42dfa9",
        "type": "change",
        "z": "560c131af0c0df4d",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "lastHighTemp",
                "pt": "flow",
                "to": "0",
                "tot": "num"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 520,
        "y": 1100,
        "wires": [
            []
        ]
    },
    {
        "id": "8aad94337c8c8e47",
        "type": "inject",
        "z": "560c131af0c0df4d",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 280,
        "y": 1100,
        "wires": [
            [
                "5af57c58ba42dfa9"
            ]
        ]
    },
    {
        "id": "820bd3ee63e64e48",
        "type": "change",
        "z": "560c131af0c0df4d",
        "name": "Current/Last Temp Array",
        "rules": [
            {
                "t": "set",
                "p": "payload[0]",
                "pt": "msg",
                "to": "currentExitTemp",
                "tot": "flow",
                "dc": true
            },
            {
                "t": "set",
                "p": "payload[1]",
                "pt": "msg",
                "to": "lastHighTemp",
                "tot": "flow",
                "dc": true
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 530,
        "y": 1020,
        "wires": [
            [
                "1830970fbab5a9be"
            ]
        ]
    },
    {
        "id": "e4e0630254ab888e",
        "type": "inject",
        "z": "560c131af0c0df4d",
        "name": "lastHighTemp",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "10",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "lastHighTemp",
        "payloadType": "flow",
        "x": 860,
        "y": 1100,
        "wires": [
            [
                "e91a94d367947402"
            ]
        ]
    },
    {
        "id": "5b3b3df5856bd971",
        "type": "inject",
        "z": "560c131af0c0df4d",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "5",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "{}",
        "payloadType": "msg",
        "x": 310,
        "y": 1020,
        "wires": [
            [
                "820bd3ee63e64e48"
            ]
        ]
    },
    {
        "id": "3162e44ddd15262f",
        "type": "debug",
        "z": "560c131af0c0df4d",
        "name": "debug 368",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1030,
        "y": 960,
        "wires": []
    },
    {
        "id": "74149027be269f42",
        "type": "change",
        "z": "560c131af0c0df4d",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "currentExitTemp",
                "pt": "flow",
                "to": "msg.payload",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 610,
        "y": 920,
        "wires": [
            []
        ]
    },
    {
        "id": "c1b0bc59ccef8d2b",
        "type": "mqtt in",
        "z": "560c131af0c0df4d",
        "name": "",
        "topic": "/waterHeater/temp2",
        "qos": "2",
        "datatype": "auto-detect",
        "broker": "e8de652f3f0d5685",
        "nl": false,
        "rap": true,
        "rh": 0,
        "inputs": 0,
        "x": 190,
        "y": 860,
        "wires": [
            [
                "279fe863a247588f",
                "7efee34e59ad5c6a",
                "f64e2fcc96d980a8",
                "74149027be269f42"
            ]
        ]
    },
    {
        "id": "7a51f7a62e395bfe",
        "type": "ui_group",
        "name": "Greenhouse",
        "tab": "f3a8a67ff0904e39",
        "order": 5,
        "disp": true,
        "width": "6",
        "collapse": true,
        "className": ""
    },
    {
        "id": "e8de652f3f0d5685",
        "type": "mqtt-broker",
        "name": "",
        "broker": "192.168.1.154",
        "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": "f3a8a67ff0904e39",
        "type": "ui_tab",
        "name": "Home",
        "icon": "home",
        "order": 1,
        "disabled": false,
        "hidden": false
    }
]

Add a debug node showing what is going into the function and show us what is there. Check that the payload contains an array with the expected values.

1 Like

Your change node "set flow.currentExitTemp" [tries to] save the value of msg.msg.payload.
Does this really match the structure of your incoming message?
You seem to be doing a lot of unnecessary parseFloat() calls.
Do you not have control of the incoming message?

It is necessary to save the highest reading seen today in a context variable but (if it is not a string) you can compare it directly with msg.payload (or msg.msg.payload) as each message arrives.

Sorry but I can't get my mind round your function and the nodes leading to it.
You start by injecting msg.payload = msg.{}. No idea what that does.
Then you assign values to msg.payload[0] and msg.payload[1] even though it's not an array. Dunno what it is.
And in the function itself you have this

if (currentTemp >= lastHighTemp) {
    msg.payload = msg.payload[0];   // Does this work? Probably. I bet it destroys msg.payload[0] thouh
    flow.set("lastHighTemp", msg.payload[0]); // Can this possibly work?
}

Perhaps something like this would work?

EDIT: I shouldn't have included the bottom three nodes. That's my experiment with assigning msg.payload[0] etc.

[{"id":"d856ee7c4788bbab","type":"switch","z":"a3c3807e16ca19c8","name":"payload > flow.highest?","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"highest","vt":"flow"}],"checkall":"true","repair":false,"outputs":1,"x":450,"y":360,"wires":[["264c9990646ed1e0","7e18248c979a96d6"]]},{"id":"fba11f61df796b75","type":"inject","z":"a3c3807e16ca19c8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"99","payloadType":"num","x":210,"y":500,"wires":[["6161b6649bca37db"]]},{"id":"e4a01443dd739821","type":"inject","z":"a3c3807e16ca19c8","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"94","payloadType":"num","x":210,"y":460,"wires":[["6161b6649bca37db"]]},{"id":"264c9990646ed1e0","type":"change","z":"a3c3807e16ca19c8","name":"set flow.highest","rules":[{"t":"set","p":"highest","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":700,"y":400,"wires":[[]]},{"id":"7e18248c979a96d6","type":"debug","z":"a3c3807e16ca19c8","name":"New highest","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":340,"wires":[]},{"id":"6161b6649bca37db","type":"switch","z":"a3c3807e16ca19c8","name":"flow.highest exists?","property":"highest","propertyType":"flow","rules":[{"t":"nnull"},{"t":"else"}],"checkall":"true","repair":false,"outputs":2,"x":430,"y":480,"wires":[["d856ee7c4788bbab"],["264c9990646ed1e0","057b4436eeed5287"]]},{"id":"057b4436eeed5287","type":"debug","z":"a3c3807e16ca19c8","name":"Initial highest value","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":690,"y":520,"wires":[]},{"id":"049bacf206863946","type":"mqtt in","z":"a3c3807e16ca19c8","name":"","topic":"/waterHeater/temp2","qos":"2","datatype":"auto-detect","broker":"58adfa22bef137b0","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":420,"wires":[["6161b6649bca37db"]]},{"id":"52283d5136fad550","type":"change","z":"a3c3807e16ca19c8","name":"Delete flow.highest","rules":[{"t":"delete","p":"highest","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":450,"y":300,"wires":[[]]},{"id":"1d2f77778426744e","type":"inject","z":"a3c3807e16ca19c8","name":"Midnight","props":[{"p":"payload"}],"repeat":"","crontab":"00 00 * * *","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":200,"y":300,"wires":[["52283d5136fad550"]]},{"id":"28a9a84949374990","type":"comment","z":"a3c3807e16ca19c8","name":"No","info":"","x":470,"y":520,"wires":[]},{"id":"54a55a8bcf7efddb","type":"comment","z":"a3c3807e16ca19c8","name":"Yes","info":"","x":470,"y":440,"wires":[]},{"id":"3d43e7e435402050","type":"change","z":"a3c3807e16ca19c8","name":"","rules":[{"t":"set","p":"payload[0]","pt":"msg","to":"aaa","tot":"str"},{"t":"set","p":"payload[1]","pt":"msg","to":"bbb","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":620,"wires":[["c6d467f346e688f8"]]},{"id":"aa7ecf89a61ad987","type":"inject","z":"a3c3807e16ca19c8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":620,"wires":[["3d43e7e435402050"]]},{"id":"c6d467f346e688f8","type":"debug","z":"a3c3807e16ca19c8","name":"debug 395","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":650,"y":620,"wires":[]},{"id":"58adfa22bef137b0","type":"mqtt-broker","name":"","broker":"192.168.1.154","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":""}]
1 Like

Here is an alternate example of setting lowest and highest incoming temps using context and JSONata in a change node.

[{"id":"c1b0bc59ccef8d2b","type":"mqtt in","z":"b9860b4b9de8c8da","name":"","topic":"/waterHeater/temp2","qos":"2","datatype":"auto-detect","broker":"e8de652f3f0d5685","nl":false,"rap":true,"rh":0,"inputs":0,"x":170,"y":340,"wires":[["4d8c9fefe062f0a2"]]},{"id":"4d8c9fefe062f0a2","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"low_high","pt":"flow","to":"$append([$flowContext(\"low_high\")], $$.payload)^($)[[0,-1]]","tot":"jsonata"},{"t":"set","p":"payload","pt":"msg","to":"low_high[1]","tot":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":400,"y":400,"wires":[["ed39c45eeeb3ce2b","e91a94d367947402"]]},{"id":"3f85a1e69291ab6d","type":"inject","z":"b9860b4b9de8c8da","name":"incoming temps","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"$round($random()*20,1)","payloadType":"jsonata","x":160,"y":400,"wires":[["4d8c9fefe062f0a2"]]},{"id":"ed39c45eeeb3ce2b","type":"debug","z":"b9860b4b9de8c8da","name":"debug 331","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":630,"y":480,"wires":[]},{"id":"e91a94d367947402","type":"ui_text","z":"b9860b4b9de8c8da","group":"7a51f7a62e395bfe","order":10,"width":0,"height":0,"name":"","label":"Exit Water High Temp","format":"{{msg.payload}}","layout":"row-spread","className":"","style":false,"font":"","fontSize":16,"color":"#000000","x":660,"y":400,"wires":[]},{"id":"0a89d46653a45cfb","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"low_high","tot":"flow"},{"t":"set","p":"low_high","pt":"flow","to":"[]","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":600,"wires":[["ed39c45eeeb3ce2b"]]},{"id":"c4901ba5fcf64563","type":"inject","z":"b9860b4b9de8c8da","name":"retrieve low high","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"low_high","payloadType":"flow","x":140,"y":460,"wires":[["ed39c45eeeb3ce2b"]]},{"id":"b9c31dcf0a0adfb2","type":"inject","z":"b9860b4b9de8c8da","name":"retrieve low","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"low_high[0]","payloadType":"flow","x":130,"y":500,"wires":[["ed39c45eeeb3ce2b"]]},{"id":"c296b62d23d9f5bd","type":"inject","z":"b9860b4b9de8c8da","name":"retrieve high","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"low_high[1]","payloadType":"flow","x":130,"y":540,"wires":[["ed39c45eeeb3ce2b"]]},{"id":"0d1dff527553416c","type":"inject","z":"b9860b4b9de8c8da","name":"retrieve and reset","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":160,"y":600,"wires":[["0a89d46653a45cfb"]]},{"id":"e8de652f3f0d5685","type":"mqtt-broker","name":"","broker":"192.168.1.154","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":"7a51f7a62e395bfe","type":"ui_group","name":"Greenhouse","tab":"f3a8a67ff0904e39","order":5,"disp":true,"width":"6","collapse":true,"className":""},{"id":"f3a8a67ff0904e39","type":"ui_tab","name":"Home","icon":"home","order":1,"disabled":false,"hidden":false}]

Thanks everyone! I love how the proposed solutions became simpler and simpler.

This is a great example of my years of hand coding can be a handicap in Node-Red. I'm continually blown away by the elegance of Node-Red.

The only thing I love more than Node-Red is the Node-Red community. Thanks again!

1 Like

Like you I have a backround in coding, so when faced with a problem I automatically write function code to tackle it.
For instance I don't know if there is a node to convert a number in string format to a floating point number. No worries, there is a Javascript function for it.
Therefore my own flows are full of functions.
Answering questions here I try to use the available non-function palette before writing javascript. It's good for my understanding of Node-red :grinning:

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.