Max minus min value after a quantity of msg.payload (people counter)

Hello.
We have a people counter that sends 4 messages every 4 hours with an increasing number each time.
I've made a flow that takes, after four messages, the largest value minus the smallest between two points in time: From the last time it updated to the current time.

The result is a payload that contains three elements:
1 Number of passages (payload.number)
2 Current time (payload.now)
3 Last time (payload.last)

The very first message will get an error because the latest time doesn't exist yet...

I'm clearly not a code expert and most of this is copy-paste from others, which certainly shows. But I hope someone can use this for their projects!

You need to install the date/time formatter “node-red-contrib-moment”.

[
    {
        "id": "c2c14d15f87984d3",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1096",
        "props": [
            {
                "p": "payload.value",
                "v": "1096",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 880,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    },
    {
        "id": "05e4fd78ad3d9364",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1095",
        "props": [
            {
                "p": "payload.value",
                "v": "1095",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 920,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    },
    {
        "id": "8b0ac756ea0912f2",
        "type": "join",
        "z": "af671d82.d368a",
        "name": "Make Array",
        "mode": "custom",
        "build": "array",
        "property": "payload.value",
        "propertyType": "msg",
        "key": "payload.value",
        "joiner": ",",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "4",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 430,
        "y": 880,
        "wires": [
            [
                "c09607629270ee1c",
                "6a2f9239020da070"
            ]
        ]
    },
    {
        "id": "7ed05b8ae028450c",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1098",
        "props": [
            {
                "p": "payload.value",
                "v": "1098",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 840,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    },
    {
        "id": "c09607629270ee1c",
        "type": "function",
        "z": "af671d82.d368a",
        "name": "max-min",
        "func": "let array1 = msg.payload.value;\nlet min = (Math.min(...array1));\nlet max = (Math.max(...array1));\n\nmsg.payload.value = (max-min);\n\nreturn msg;\n",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 640,
        "y": 880,
        "wires": [
            [
                "2850d5b64fb49246"
            ]
        ]
    },
    {
        "id": "746efe37ca4114e3",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1090",
        "props": [
            {
                "p": "payload.value",
                "v": "1090",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 960,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    },
    {
        "id": "19aa78d7b07feaaa",
        "type": "moment",
        "z": "af671d82.d368a",
        "name": "",
        "topic": "",
        "input": "payload.timestamp",
        "inputType": "msg",
        "inTz": "Europe/Stockholm",
        "adjAmount": "0",
        "adjType": "hours",
        "adjDir": "subtract",
        "format": " D MMMM YYYY, hh:mm:ss",
        "locale": "en",
        "output": "",
        "outputType": "msg",
        "outTz": "Europe/Stockholm",
        "x": 860,
        "y": 840,
        "wires": [
            [
                "2722c9b896c8a823"
            ]
        ]
    },
    {
        "id": "a814c8696968b929",
        "type": "moment",
        "z": "af671d82.d368a",
        "name": "",
        "topic": "",
        "input": "payload.timestamp",
        "inputType": "msg",
        "inTz": "Europe/Stockholm",
        "adjAmount": "0",
        "adjType": "hours",
        "adjDir": "add",
        "format": " D MMMM YYYY, hh:mm:ss",
        "locale": "en",
        "output": "",
        "outputType": "msg",
        "outTz": "Europe/Stockholm",
        "x": 860,
        "y": 800,
        "wires": [
            [
                "107f07359bf95269"
            ]
        ]
    },
    {
        "id": "2850d5b64fb49246",
        "type": "function",
        "z": "af671d82.d368a",
        "name": "Get only value",
        "func": "var Msg = { \"payload\": msg.payload.value };\n\nreturn Msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 840,
        "y": 880,
        "wires": [
            [
                "9346218bd596146b"
            ]
        ]
    },
    {
        "id": "6a2f9239020da070",
        "type": "function",
        "z": "af671d82.d368a",
        "name": "now_last",
        "func": "let msg1 = {};\nvar last = context.get(\"last\") || now;\nvar now = msg.payload;\n\ncontext.set(\"last\",now);\n\nmsg1.payload = last;\nreturn [msg,msg1];",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 640,
        "y": 820,
        "wires": [
            [
                "a814c8696968b929"
            ],
            [
                "19aa78d7b07feaaa"
            ]
        ]
    },
    {
        "id": "107f07359bf95269",
        "type": "change",
        "z": "af671d82.d368a",
        "name": "SetpayloadToNow",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "payload.now",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1090,
        "y": 800,
        "wires": [
            [
                "a8132e605353d523"
            ]
        ]
    },
    {
        "id": "2722c9b896c8a823",
        "type": "change",
        "z": "af671d82.d368a",
        "name": "SetpayloadToLast",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "payload.last",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1090,
        "y": 840,
        "wires": [
            [
                "a8132e605353d523"
            ]
        ]
    },
    {
        "id": "9346218bd596146b",
        "type": "change",
        "z": "af671d82.d368a",
        "name": "SetpayloadToCount",
        "rules": [
            {
                "t": "move",
                "p": "payload",
                "pt": "msg",
                "to": "payload.count",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1090,
        "y": 880,
        "wires": [
            [
                "a8132e605353d523"
            ]
        ]
    },
    {
        "id": "24255b018e15d6e0",
        "type": "debug",
        "z": "af671d82.d368a",
        "name": "Final",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1670,
        "y": 840,
        "wires": []
    },
    {
        "id": "a8132e605353d523",
        "type": "join",
        "z": "af671d82.d368a",
        "name": "",
        "mode": "custom",
        "build": "merged",
        "property": "payload",
        "propertyType": "msg",
        "key": "payload",
        "joiner": "\\n",
        "joinerType": "str",
        "accumulate": false,
        "timeout": "",
        "count": "3",
        "reduceRight": false,
        "reduceExp": "",
        "reduceInit": "",
        "reduceInitType": "",
        "reduceFixup": "",
        "x": 1330,
        "y": 840,
        "wires": [
            [
                "95dd948aa20e8c7f",
                "5b5b7e9c133df2be"
            ]
        ]
    },
    {
        "id": "95dd948aa20e8c7f",
        "type": "template",
        "z": "af671d82.d368a",
        "name": "",
        "field": "payload",
        "fieldType": "msg",
        "format": "handlebars",
        "syntax": "mustache",
        "template": "It been passing {{payload.count}} people between{{payload.last}} and{{payload.now}}",
        "output": "str",
        "x": 1500,
        "y": 840,
        "wires": [
            [
                "24255b018e15d6e0"
            ]
        ]
    },
    {
        "id": "719989d4742cf575",
        "type": "comment",
        "z": "af671d82.d368a",
        "name": "4Msg",
        "info": "Sends after four messages",
        "x": 410,
        "y": 840,
        "wires": []
    },
    {
        "id": "57bf97f8a6897c61",
        "type": "comment",
        "z": "af671d82.d368a",
        "name": "\"Mail output\"",
        "info": "Simulate how to configure an\noutput email",
        "x": 1510,
        "y": 800,
        "wires": []
    },
    {
        "id": "5b5b7e9c133df2be",
        "type": "debug",
        "z": "af671d82.d368a",
        "name": "Payload without template",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 1550,
        "y": 900,
        "wires": []
    },
    {
        "id": "9c093054436f5529",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1150",
        "props": [
            {
                "p": "payload.value",
                "v": "1150",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 800,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    },
    {
        "id": "1f31b0cb83b4af50",
        "type": "inject",
        "z": "af671d82.d368a",
        "name": "1200",
        "props": [
            {
                "p": "payload.value",
                "v": "1200",
                "vt": "num"
            },
            {
                "p": "payload.timestamp",
                "v": "",
                "vt": "date"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "x": 210,
        "y": 760,
        "wires": [
            [
                "8b0ac756ea0912f2"
            ]
        ]
    }
]

Confused here is that 1 msg every 4 hours or is that 4 message every 4 hours, Can we see a debug of these 4 messages to be sure.

Your flow looks a little over complicated.
may be this example will help

1 message every 4 hours.

[{"id":"1f31b0cb83b4af50","type":"inject","z":"b9860b4b9de8c8da","name":"1200","props":[{"p":"payload.value","v":"1200","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2800,"wires":[["25447ab8075b85c9"]]},{"id":"25447ab8075b85c9","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"payload.time_now","pt":"msg","to":"$moment().tz(\"Europe/Stockholm\").format(\"D MMMM YYYY, hh:mm:ss\")","tot":"jsonata"},{"t":"set","p":"payload.traffic","pt":"msg","to":"$$.payload.value - $sum([$flowContext(\"last\")])","tot":"jsonata"},{"t":"set","p":"last","pt":"flow","to":"payload.value","tot":"msg"},{"t":"set","p":"payload.time_last","pt":"msg","to":"$exists($flowContext(\"last_time\")) ? $flowContext(\"last_time\") : $$.payload.time_now","tot":"jsonata"},{"t":"set","p":"last_time","pt":"flow","to":"payload.time_now","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":2840,"wires":[["24255b018e15d6e0","95dd948aa20e8c7f"]]},{"id":"c2c14d15f87984d3","type":"inject","z":"b9860b4b9de8c8da","name":"1096","props":[{"p":"payload.value","v":"1096","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2920,"wires":[["25447ab8075b85c9"]]},{"id":"05e4fd78ad3d9364","type":"inject","z":"b9860b4b9de8c8da","name":"1095","props":[{"p":"payload.value","v":"1095","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2960,"wires":[["25447ab8075b85c9"]]},{"id":"7ed05b8ae028450c","type":"inject","z":"b9860b4b9de8c8da","name":"1098","props":[{"p":"payload.value","v":"1098","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2880,"wires":[["25447ab8075b85c9"]]},{"id":"746efe37ca4114e3","type":"inject","z":"b9860b4b9de8c8da","name":"1090","props":[{"p":"payload.value","v":"1090","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":3000,"wires":[["25447ab8075b85c9"]]},{"id":"9c093054436f5529","type":"inject","z":"b9860b4b9de8c8da","name":"1150","props":[{"p":"payload.value","v":"1150","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2840,"wires":[["25447ab8075b85c9"]]},{"id":"24255b018e15d6e0","type":"debug","z":"b9860b4b9de8c8da","name":"Final","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":2820,"wires":[]},{"id":"95dd948aa20e8c7f","type":"template","z":"b9860b4b9de8c8da","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"It been passing {{payload.traffic}} people between {{payload.time_last}} and {{payload.time_now}}","output":"str","x":640,"y":2880,"wires":[["24255b018e15d6e0"]]}]

4 messages every 4 hours

[{"id":"1f31b0cb83b4af50","type":"inject","z":"b9860b4b9de8c8da","name":"1200","props":[{"p":"payload.value","v":"1200","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2800,"wires":[["16a533c25389e908"]]},{"id":"16a533c25389e908","type":"join","z":"b9860b4b9de8c8da","name":"","mode":"custom","build":"array","property":"payload.value","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"4","reduceRight":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":330,"y":2740,"wires":[["25447ab8075b85c9"]]},{"id":"c2c14d15f87984d3","type":"inject","z":"b9860b4b9de8c8da","name":"1096","props":[{"p":"payload.value","v":"1096","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2920,"wires":[["16a533c25389e908"]]},{"id":"05e4fd78ad3d9364","type":"inject","z":"b9860b4b9de8c8da","name":"1095","props":[{"p":"payload.value","v":"1095","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2960,"wires":[["16a533c25389e908"]]},{"id":"7ed05b8ae028450c","type":"inject","z":"b9860b4b9de8c8da","name":"1098","props":[{"p":"payload.value","v":"1098","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2880,"wires":[["16a533c25389e908"]]},{"id":"746efe37ca4114e3","type":"inject","z":"b9860b4b9de8c8da","name":"1090","props":[{"p":"payload.value","v":"1090","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":3000,"wires":[["16a533c25389e908"]]},{"id":"9c093054436f5529","type":"inject","z":"b9860b4b9de8c8da","name":"1150","props":[{"p":"payload.value","v":"1150","vt":"num"},{"p":"payload.timestamp","v":"","vt":"date"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":170,"y":2840,"wires":[["16a533c25389e908"]]},{"id":"25447ab8075b85c9","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"payload.value","pt":"msg","to":"payload.value[3]","tot":"msg"},{"t":"set","p":"payload.time_now","pt":"msg","to":"$moment().tz(\"Europe/Stockholm\").format(\"D MMMM YYYY, hh:mm:ss\")","tot":"jsonata"},{"t":"set","p":"payload.traffic","pt":"msg","to":"$$.payload.value - $sum([$flowContext(\"last\")])","tot":"jsonata"},{"t":"set","p":"last","pt":"flow","to":"payload.value","tot":"msg"},{"t":"set","p":"payload.time_last","pt":"msg","to":"$exists($flowContext(\"last_time\")) ? $flowContext(\"last_time\") : $$.payload.time_now","tot":"jsonata"},{"t":"set","p":"last_time","pt":"flow","to":"payload.time_now","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":2840,"wires":[["24255b018e15d6e0","95dd948aa20e8c7f"]]},{"id":"24255b018e15d6e0","type":"debug","z":"b9860b4b9de8c8da","name":"Final","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":730,"y":2820,"wires":[]},{"id":"95dd948aa20e8c7f","type":"template","z":"b9860b4b9de8c8da","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"It been passing {{payload.traffic}} people between {{payload.time_last}} and {{payload.time_now}}","output":"str","x":640,"y":2880,"wires":[["24255b018e15d6e0"]]}]
1 Like

Tanks a lot!
Because my lack of knowledge of code I could never have done that :slight_smile:

The people counter is a Senlab PIR-Sensor that sends the payload every 4th hour.
So everytime it updates I get four payloads within one second and I don´t want to receive 4 mails.
I consider to even change the "Join-node" to wait for 12 msg, to receive one mail every 12 hours that tells me how many people have passed through the last 12 hours.

Or even better: one mail every 12 hours containing 12 lines where I can see passings each hour.
That can be my next learning project :slight_smile:

Thanks again for your improvement!