Function Node error

Hello, can someone help me..... I want to write function node. First true signal is forwarded. after that, all signals are blocked for 30 seconds. After that, all signals are forwarded. With False, Function Node will be ready for first True Signal. I can't find the error.

let block = false;
let timer;

function node(input) {
if (input === true && !block) {
node.send(input);
block = true;
timer = setTimeout(() => {
block = false;
}, 30000);
} else if (input === false) {
block = false;
clearTimeout(timer);
}

if (!block) {
    node.send(input);
}

}

return node;

Is this the same as the question you asked before?

yes. I tested E1cid's suggestion. I understand not how that works. It doesn't work for me. I'm also a total newbie. Try to put everything together in a function node.

Try this example

[{"id":"b6aca93.d3504d8","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":1200,"wires":[["998e2ee1.065bc8"]]},{"id":"998e2ee1.065bc8","type":"switch","z":"d1395164b4eec73e","name":"","property":"stop_delay","propertyType":"flow","rules":[{"t":"istype","v":"undefined","vt":"undefined"},{"t":"else"}],"checkall":"false","repair":false,"outputs":2,"x":260,"y":1140,"wires":[["493b5acc.71c19c"],[]]},{"id":"493b5acc.71c19c","type":"trigger","z":"d1395164b4eec73e","name":"","op1":"","op2":"","op1type":"pay","op2type":"pay","duration":"30","extend":false,"overrideDelay":true,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":2,"x":430,"y":1140,"wires":[["2d59e28837486a6c"],["e6b2b1f0.ada2b8"]]},{"id":"e6b2b1f0.ada2b8","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"delete","p":"stop_delay","pt":"flow"}],"action":"","property":"","from":"","to":"","reg":false,"x":660,"y":1180,"wires":[[]]},{"id":"2d59e28837486a6c","type":"change","z":"d1395164b4eec73e","name":"","rules":[{"t":"set","p":"stop_delay","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":650,"y":1120,"wires":[["ae4ef9b4.4bd328"]]},{"id":"ae4ef9b4.4bd328","type":"debug","z":"d1395164b4eec73e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":1140,"wires":[]}]

Otherwise export your flow so we can see the inject values and your full function code. As your are not setting msg.payload and are returning node ( which you should not use as a function name, as already defined in the function node, therefore node.send would also return an error i believe), so payload would always be undefined. and sending input which should throw an error as input is not an object as far as i can see.
Also input looks to be undefined in your code.
How to import/export a flow
Set your debug to show complete message object, you will see what node returns.

In order to make code readable and usable it is necessary to surround your code with three backticks (also known as a left quote or backquote ```) You can use the </>icon to add the backticks.

``` 
   code goes here 
```

You can edit and correct your post by clicking the pencil :pencil2: icon.

See this post for more details - How to share code or flow json

[edit]
Thinking about it a simple rate limit and drop intermiedate messages should work to.

[{"id":"b6aca93.d3504d8","type":"inject","z":"d1395164b4eec73e","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":220,"y":1200,"wires":[["1a3ba0d64520256a"]]},{"id":"1a3ba0d64520256a","type":"delay","z":"d1395164b4eec73e","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seconds","rate":"1","nbRateUnits":"30","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"allowrate":false,"outputs":1,"x":480,"y":1180,"wires":[["ae4ef9b4.4bd328"]]},{"id":"ae4ef9b4.4bd328","type":"debug","z":"d1395164b4eec73e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":870,"y":1140,"wires":[]}]

thanks. Excuse me. I didn't express myself correctly here. After Blocking all signals should be forwarded without delay.

I have read your original question and this one and I'm still not clear exactly what you are trying to do.

Can you explain what your true and false messages represent in the real world?
What is the reason for this 30 seconds block after true?

Your statements "All signals are blocked for 30 seconds" and "With false, function node will be ready for the first true" confuse me.
For example: you receive true, then 10 seconds later false, then 10 seconds later true.
What happens to message 1?
What happens to message 2?
What happens to message 3?

You need to be aware that the variable block in your function does not retain it's value from one message to the next. If you want to retain a value from one message to the next you must use a context variable

let blocked = context.get("blocked") ?? false  // get the value of a context variable, or default false
...
context.set ("blocked", blocked)     // save to context variable

But I think you are mistaken to try and do this with a function node.

Still unclear as to what are the incoming messages and when they should be delayed and when forwarded with out delay.

Please take some time and explain fully with examples of messages. Step by step.

Please also respond to all requests made.

I keep Boolean true and false in my flow because I send the signals directly to Modbus. 30sec is just a value so I can test. I would like to use it to first block certain valves for underfloor heating circuits in the house without temperature monitoring, then release them with temperature monitoring. So:I need some kind of time delay or triger the first outputs true then delayed without time extension.After that, all of them will be forwarded true. With the false comes the reset and with the first true delay becomes active again

I don't necessarily need a function node.

You only have two possible messages: true or false.

true starts the 30 seconds block
false resets the block

So what messages do you want to block?
Do you just want to prevent repeated true messages?

You still have not made it clear what happens if you get a false during the 30 seconds.


flows (3).json (41.0 KB)
That's how I imagined it.

You still have not made it clear what you want to happen if you get a false during the 30 seconds after the first true.

will be reset. If a true comes up, then delay becomes active again

I think I would solve this with a simple state machine in a Function node

const timeoutInterval = 5000    // five secs
let stat = context.get("stat") || {state: "Waiting_for_true"}
// a false msg.payload always causes a return to the waiting for true state
if (!msg.payload) {
    stat.state = "Waiting_for_true"
} else {
    // true received
    switch (stat.state) {
        case "Waiting_for_true": 
            stat.state = "Waiting_for_timeout"
            // note the time
            stat.startTime = new Date().getTime()
            // do not send the message
            msg = null
            break;
        case "Waiting_for_timeout":
            if (new Date().getTime() - stat.startTime > timeoutInterval) {
                // timeout has elapsed
                stat.state = "Pass_messages"
            } else {
                // no timeout, ignore this message
                msg = null
            }
            break;
        case "Pass_messages":
            // just pass on the message
            break;
        default:
            node.warn(`Bug - unrecognised state ${stat.state} in State Machine node`)
    }
}
node.status( stat.state )
context.set("stat", stat)
return msg;
[{"id":"fa533b95925df727","type":"function","z":"bdd7be38.d3b55","name":"State machine","func":"const timeoutInterval = 5000    // five secs\nlet stat = context.get(\"stat\") || {state: \"Waiting_for_true\"}\n// a false msg.payload always causes a return to the waiting for true state\nif (!msg.payload) {\n    stat.state = \"Waiting_for_true\"\n} else {\n    // true received\n    switch (stat.state) {\n        case \"Waiting_for_true\": \n            stat.state = \"Waiting_for_timeout\"\n            // note the time\n            stat.startTime = new Date().getTime()\n            // do not send the message\n            msg = null\n            break;\n        case \"Waiting_for_timeout\":\n            if (new Date().getTime() - stat.startTime > timeoutInterval) {\n                // timeout has elapsed\n                stat.state = \"Pass_messages\"\n            } else {\n                // no timeout, ignore this message\n                msg = null\n            }\n            break;\n        case \"Pass_messages\":\n            // just pass on the message\n            break;\n        default:\n            node.warn(`Bug - unrecognised state ${stat.state} in State Machine node`)\n    }\n}\nnode.status( stat.state )\ncontext.set(\"stat\", stat)\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":3160,"wires":[["0d5a7665574c901f"]]},{"id":"48fbcdd78f0f7be6","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":170,"y":3140,"wires":[["fa533b95925df727"]]},{"id":"9802ebdb125dba5f","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":170,"y":3200,"wires":[["fa533b95925df727"]]},{"id":"0d5a7665574c901f","type":"debug","z":"bdd7be38.d3b55","name":"debug 105","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":3160,"wires":[]}]

Thanks,Thanks,the idea was first true via output1 to send. Then delay. All other true and false are sent via output 2

I don't remember seeing that in the requirement anywhere. Did you try and change my flow accordingly?

[{"id":"fa533b95925df727","type":"function","z":"bdd7be38.d3b55","name":"State machine","func":"const timeoutInterval = 5000    // five secs\nlet stat = context.get(\"stat\") || {state: \"Waiting_for_true\"}\nlet msg1 = null\nlet msg2 = null\n// a false msg.payload always causes a return to the waiting for true state\nif (!msg.payload) {\n    stat.state = \"Waiting_for_true\"\n    // send via output 2\n    msg2 = msg\n} else {\n    // true received\n    switch (stat.state) {\n        case \"Waiting_for_true\": \n            stat.state = \"Waiting_for_timeout\"\n            // note the time\n            stat.startTime = new Date().getTime()\n            // send the message to output 1\n            msg1 = msg\n            break;\n        case \"Waiting_for_timeout\":\n            if (new Date().getTime() - stat.startTime > timeoutInterval) {\n                // timeout has elapsed\n                stat.state = \"Pass_messages\"\n            } else {\n                // no timeout, send to o/p 2\n                msg2 = msg\n            }\n            break;\n        case \"Pass_messages\":\n            // just pass on the message on output2\n            msg2 = msg\n            break;\n        default:\n            node.warn(`Bug - unrecognised state ${stat.state} in State Machine node`)\n    }\n}\nnode.status( stat.state )\ncontext.set(\"stat\", stat)\nreturn [msg1, msg2];","outputs":2,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":440,"y":3160,"wires":[["0d5a7665574c901f"],["ba72673793ed219f"]]},{"id":"48fbcdd78f0f7be6","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":170,"y":3140,"wires":[["fa533b95925df727"]]},{"id":"9802ebdb125dba5f","type":"inject","z":"bdd7be38.d3b55","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":170,"y":3200,"wires":[["fa533b95925df727"]]},{"id":"0d5a7665574c901f","type":"debug","z":"bdd7be38.d3b55","name":"OP!","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":3140,"wires":[]},{"id":"ba72673793ed219f","type":"debug","z":"bdd7be38.d3b55","name":"OP2","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":650,"y":3200,"wires":[]}]

Thank you.... Yes, that was the original idea. That changed the more I was involved with the topic.

Please look at the code and make sure you know how it works. That way you will learn and also will be able to adjust the code in future if the requirement changes again.

Thank you.... I've already adjusted. functioned.