How to make a counter just using function node only?

In this case i just want to make some simple counter but not using some node counter but only using function and this my flows
image
and this my json

[
    {
        "id": "dbacc92cfb48e54e",
        "type": "function",
        "z": "2c1af103.8bdcce",
        "name": "function 7",
        "func": "var value = 0;\n\nif (msg.payload===true){\n    value = value + 1;\n}\n\nmsg.payload = {\n    \"Count Value\" : value\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 400,
        "y": 1720,
        "wires": [
            [
                "ca1525c14fcfd816"
            ]
        ]
    },
    {
        "id": "ca1525c14fcfd816",
        "type": "debug",
        "z": "2c1af103.8bdcce",
        "name": "debug 19",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 560,
        "y": 1720,
        "wires": []
    },
    {
        "id": "ce533d4493b503c5",
        "type": "inject",
        "z": "2c1af103.8bdcce",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 250,
        "y": 1720,
        "wires": [
            [
                "dbacc92cfb48e54e"
            ]
        ]
    }
]

in my debug when i press inject node it just count 1 and when i pressed again its count 1 again but not 2 can you help me please because i'm new in Node-RED

One of the basic things in Node-RED is that each node has no idea of any other node, and each message is independent of any other. So at the start of your function when you set it to 0 . That occurs every time you inject some data - so it always sets to zero - then adds 1 ...
So you need some way to store the existing count - and that is called context... see the docs here - Writing Functions : Node-RED

In fact, Exactly same example is in the docs referred by @dceejay

[{"id":"edfb3b9a4c6ae411","type":"function","z":"18c232f151ca7569","name":"function 1","func":"var count = context.get('count')||0;\ncount += 1;\n// store the value back\ncontext.set('count',count);\n// make it part of the outgoing msg object\nmsg.count = count;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":430,"y":520,"wires":[["5a49a79602fe3e66"]]},{"id":"02d392fd948e9dde","type":"inject","z":"18c232f151ca7569","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":260,"y":520,"wires":[["edfb3b9a4c6ae411"]]},{"id":"5a49a79602fe3e66","type":"debug","z":"18c232f151ca7569","name":"debug 125","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"count","targetType":"msg","statusVal":"count","statusType":"auto","x":650,"y":520,"wires":[]}]

okay i'll learn this thanks @dceejay

With a small adjustment, you could introduce a 'reset' facility for your counter using msg.topic.

count_with_reset

[{"id":"22fb22405eb6a6b6","type":"tab","label":"Counter","disabled":false,"info":"","env":[]},{"id":"edfb3b9a4c6ae411","type":"function","z":"22fb22405eb6a6b6","name":"function 1","func":"var count = context.get('count')||0;\n\nif (msg.topic == \"reset\") {\n    count = 0;\n    context.set('count',0);\n}\nelse {\n    count += 1;\n    context.set('count',count);\n}\n\n// make it part of the outgoing msg object\nmsg.count = count;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":180,"wires":[["5a49a79602fe3e66"]]},{"id":"02d392fd948e9dde","type":"inject","z":"22fb22405eb6a6b6","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payloadType":"date","x":160,"y":180,"wires":[["edfb3b9a4c6ae411"]]},{"id":"5a49a79602fe3e66","type":"debug","z":"22fb22405eb6a6b6","name":"debug 125","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"count","targetType":"msg","statusVal":"count","statusType":"auto","x":490,"y":180,"wires":[]},{"id":"1421fc9e3d5aa488","type":"inject","z":"22fb22405eb6a6b6","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","x":150,"y":220,"wires":[["edfb3b9a4c6ae411"]]}]
1 Like

okay, thanks @dynamicdave

Nice to have a reset option,
I am trying to put a Decrement Inject, but i could not build the function to have a nested IF to include one more IF condition, can you help

PS: How many flow tabs you have in the editor? I see no 34 in the example!!

Try this...


The function node will only decrement the counter if it has a value greater than zero.
It will stop decrementing when the counter value gets to zero.
You can modify the Javascript if you want to allow the counter to go negative.

[{"id":"f6bf1c3dee4d1f8a","type":"tab","label":"Counter","disabled":false,"info":"","env":[]},{"id":"7f9216ceac2d788e","type":"function","z":"f6bf1c3dee4d1f8a","name":"magic","func":"var count = context.get('count')||0;\n\nif (msg.topic == \"reset\") {\n    count = 0;\n    context.set('count',0);\n}\nelse if (msg.topic== \"increment\") {\n    count += 1;\n    context.set('count',count);\n}\nelse if ( (msg.topic == \"decrement\") && (count > 0) ) {\n        count -= 1;\n    context.set('count',count);\n}\n\n// make it part of the outgoing msg object\nmsg.count = count;\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":330,"y":180,"wires":[["b096a3199f2e2a29"]]},{"id":"3da000d4d7958cf9","type":"inject","z":"f6bf1c3dee4d1f8a","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"increment","x":160,"y":180,"wires":[["7f9216ceac2d788e"]]},{"id":"b096a3199f2e2a29","type":"debug","z":"f6bf1c3dee4d1f8a","name":"debug 125","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"count","targetType":"msg","statusVal":"count","statusType":"auto","x":490,"y":180,"wires":[]},{"id":"07690a45810ed2fe","type":"inject","z":"f6bf1c3dee4d1f8a","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"reset","x":150,"y":120,"wires":[["7f9216ceac2d788e"]]},{"id":"f761704bb5da747d","type":"inject","z":"f6bf1c3dee4d1f8a","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"decrement","x":170,"y":240,"wires":[["7f9216ceac2d788e"]]},{"id":"c62b093f66ae8f56","type":"comment","z":"f6bf1c3dee4d1f8a","name":"Decrement the counter providing it has a value greater than zero","info":"","x":510,"y":120,"wires":[]}]

Code in the function node is...

var count = context.get('count')||0;

if (msg.topic == "reset") {
    count = 0;
    context.set('count',0);
}
else if (msg.topic == "increment") {
    count += 1;
    context.set('count',count);
}
else if ( (msg.topic == "decrement") && (count > 0) ) {
        count -= 1;
    context.set('count',count);
}

msg.count = count;
return msg;

1 Like