Timer for count total time when get trigger from inject node true

Hi, I'm new in node red and I confused when I try to make some simple timer to count for a total time when the true value injected here's the code I write

var counterLStime = flow.get("counter")||0;
var trigger = msg.payload;
var time = setInterval(getcounter, 1000);
var count = 0;

function getcounter() {
    if (trigger == false) {
        clearInterval(time);
        flow.set("counter", 0)
    }
    else if (trigger == true) {
        ++counterLStime;
        flow.set("counter", counterLStime)
    }
}

msg.payload = {
    "Total Time": counterLStime
}
return msg;

and flow I make

[
    {
        "id": "0c3e6e4c03fba675",
        "type": "function",
        "z": "6c67e417f0d6a0e7",
        "name": "function 21",
        "func": "var counterLStime = flow.get(\"counter\")||0;\nvar trigger = msg.payload;\nvar time = setInterval(getcounter, 1000);\nvar count = 0;\n\nfunction getcounter() {\n    if (trigger == false) {\n        clearInterval(time);\n        flow.set(\"counter\", 0)\n    }\n    else if (trigger == true) {\n        ++counterLStime;\n        flow.set(\"counter\", counterLStime)\n    }\n}\n\nmsg.payload = {\n    \"Total Time\": counterLStime\n}\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 910,
        "y": 420,
        "wires": [
            [
                "9d65ca5725ee1baf"
            ]
        ]
    },
    {
        "id": "48b35364becfe3f6",
        "type": "inject",
        "z": "6c67e417f0d6a0e7",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "true",
        "payloadType": "bool",
        "x": 710,
        "y": 400,
        "wires": [
            [
                "0c3e6e4c03fba675"
            ]
        ]
    },
    {
        "id": "b0fca08d5c4b4469",
        "type": "inject",
        "z": "6c67e417f0d6a0e7",
        "name": "",
        "props": [
            {
                "p": "payload"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "false",
        "payloadType": "bool",
        "x": 710,
        "y": 440,
        "wires": [
            [
                "0c3e6e4c03fba675"
            ]
        ]
    },
    {
        "id": "9d65ca5725ee1baf",
        "type": "debug",
        "z": "6c67e417f0d6a0e7",
        "name": "debug 134",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "false",
        "statusVal": "",
        "statusType": "auto",
        "x": 1090,
        "y": 420,
        "wires": []
    }
]

Maybe can you help me what wrong with this code because the value are showed in debug but when I pressed false the value still counting and not reset to 0.

Can you explain the goal (bigger picture) of the purpose of this flow ?

My goal is to count time when my sensor get true on door opened so I can know how much time when the door has opened

Even bigger picture, because I assume you want to do something with the time the door was opened ?

just for showing how much time and I'll count how many times it's get opened

You are creating a new timer each time you call the function, you need to keep the timer handle in context and only start a new one the first time in.

so I must change the flow to context ? @Colin

I just change to context and its still count when I pressed the false trigger @Colin

Why use setInterval, just store timestamp on true and when false retrieve timestamp and deduct from new timestamp.
e.g.

let trigger = msg.payload;
let time_since = 0;
let time_now = new Date().getTime();
let first_true = flow.get("true_start");
if (trigger === false) {
    if(!first_true){
         first_true = time_now;
    }
    time_since = time_now - first_true
    if(time_since > 0){
        msg.payload = {"Total Time":  time_since}
        flow.set("true_start", undefined)
    }else{
        msg = null;
    }
}else{
    if(!first_true){
        flow.set("true_start", time_now)
    }
    msg = null;
}
return msg;

No, that is not what I meant. I will explain in more detail.
The first time you pass in a msg with payload true it starts a timer using setInterval and saves the handle to the timer in the variable time.
Then if you pass in a message with payload false it calls setInterval again which starts a new timer and again stores the handle if a variable time. This is not the same variable where you stored the first handle, as function variables are recreated each time. Then you test the payload and call clearInterval on the timer you have just created, but the original timer is still running, and you have no way of stopping it because you did not save the original handle in context (node context or flow context, it doesn't matter which).
To fix it you need to store the handle (the variable time) in context and pick it up when you come back into the function again (the same as you have for the counter). Then if it is not zero (so the counter is running) you can call setInterval to stop it. After stopping the timer, clear the variable and write it back to context so the next time you will know to create the timer again.

Okay thanks for the sharing I'll learn it

Thankyou for sharing about the explain it's good for me to learn more

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