Custom function for timer

Hello,

Please help me with this flow. I cannot understand why the function "camera state" never goes through the first output when the condition is not met. The idea is to put a timer and, when the timer is reached, turn off the light. I know it could be done directly from the state node, but I need the timer variable to depend on other factors, so I need to write a custom function.

[{"id":"b84d4a9292736038","type":"server-state-changed","z":"66e8f946d2d274c4","name":"Camera","server":"5f04c7c3.35aa98","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"light.luci_camera","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","haltifstate":"true","halt_if_type":"bool","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"}],"x":670,"y":1280,"wires":[["28523199ac937e5c"],[]]},{"id":"acd2084c1e178df0","type":"api-call-service","z":"66e8f946d2d274c4","name":"Camera OFF","server":"5f04c7c3.35aa98","version":5,"debugenabled":false,"domain":"light","service":"turn_off","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1430,"y":1300,"wires":[[]]},{"id":"c834634c5948518c","type":"api-current-state","z":"66e8f946d2d274c4","name":"Check","server":"5f04c7c3.35aa98","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"light.luci_camera","state_type":"habool","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":950,"y":1280,"wires":[["412ab48095d319c0"]]},{"id":"90e2c490bd435d56","type":"delay","z":"66e8f946d2d274c4","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":940,"y":1200,"wires":[["c834634c5948518c"]]},{"id":"28523199ac937e5c","type":"function","z":"66e8f946d2d274c4","name":"SetTime","func":"var lastChange = global.set('lastChange', new Date().getTime());\nvar timeout = global.set('timeout', 5000);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":800,"y":1280,"wires":[["c834634c5948518c"]]},{"id":"412ab48095d319c0","type":"function","z":"66e8f946d2d274c4","name":"Check Camera State","func":"var currentState = msg.payload;\nnode.warn(currentState);\nvar lastChange = global.get('lastChange');// || new Date().getTime();\nvar timeout = global.get('timeout') || 5000; // Timeout in milliseconds\nnode.warn(\"Timeout: \"+ timeout);\nnode.warn(\"Last Change: \"+lastChange);\nif (currentState) {\n    var currentTime = new Date().getTime();\n    node.warn(\"currentTime: \" + currentTime);\n    var elapsedTime = currentTime - lastChange; // in milliseconds\n    node.warn(\"elapsedTime :\" + elapsedTime);\n    if (elapsedTime > timeout) {\n        return [null, { payload: { data: { entity_id: 'light.luci_camera' } } }]; // payload to turn off the light\n    }\n} else {\n    node.warn(\"Timeout not reached\");\n    //global.set('lastChange', new Date().getTime());\n    return [msg, null];\n}\n\nreturn [null, null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1160,"y":1280,"wires":[["90e2c490bd435d56","269eda0ba0a23e24"],["acd2084c1e178df0"]],"outputLabels":["","Turn OFF"]},{"id":"269eda0ba0a23e24","type":"debug","z":"66e8f946d2d274c4","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1410,"y":1220,"wires":[]},{"id":"5f04c7c3.35aa98","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]

You are setting Last Change global in first function, so every time you get to second function the Last Change is only a few milliseconds less than currentTime, there for your if statement is always false.

Would a simple trigger delay not work for you
e.g.

[{"id":"815cb1bb31fdb223","type":"inject","z":"b9860b4b9de8c8da","name":"","props":[{"p":"payload"},{"p":"delay","v":"5000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"true","payloadType":"bool","x":150,"y":1780,"wires":[["fe1886eaed8b6fa5"]]},{"id":"fe1886eaed8b6fa5","type":"junction","z":"b9860b4b9de8c8da","x":260,"y":1780,"wires":[["9d1440ede48f4962","bd12485d02b41249"]]},{"id":"7fde16c6587c4302","type":"inject","z":"b9860b4b9de8c8da","name":"","props":[{"p":"payload"},{"p":"delay","v":"5000","vt":"num"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"false","payloadType":"bool","x":150,"y":1820,"wires":[["fe1886eaed8b6fa5"]]},{"id":"9d1440ede48f4962","type":"trigger","z":"b9860b4b9de8c8da","name":"","op1":"","op2":"false","op1type":"nul","op2type":"bool","duration":"250","extend":true,"overrideDelay":true,"units":"ms","reset":"false","bytopic":"all","topic":"topic","outputs":1,"x":340,"y":1820,"wires":[["bd12485d02b41249"]]},{"id":"bd12485d02b41249","type":"rbe","z":"b9860b4b9de8c8da","name":"","func":"rbe","gap":"","start":"","inout":"out","septopics":true,"property":"payload","topi":"topic","x":450,"y":1780,"wires":[["269eda0ba0a23e24"]]},{"id":"269eda0ba0a23e24","type":"debug","z":"b9860b4b9de8c8da","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":570,"y":1780,"wires":[]}]

The variable 'lastChange' should track the starting time when the light changes its state from off to on. 'CurrentTime' should take the time in the second function. If the difference between the two is less than 5000 ms (timeout), it should be false and proceed to the 'delay 1s' node. After re-entering the 'Check camera state' function, a new 'CurrentTime' should be obtained, which should be 1000 ms greater than the previous one. While 'lastChange' remains the same, the process should be repeated until the elapsed time becomes greater than the timeout. At that point, it should be true, indicating that the elapsed time has exceeded the timeout, and the light should be turned off. Any idea why it is not working?

I'm taking a look at your flow... It's something new to me.

How did you create the junction 'point' in the connection? Another thing is that I can't see where you 'pass' the 5000ms delay and where it's executed or it is executed directly in the inject node?. Could you explain it to me?

I have found the problem:

[{"id":"b84d4a9292736038","type":"server-state-changed","z":"66e8f946d2d274c4","name":"Camera","server":"5f04c7c3.35aa98","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"light.luci_camera","entityidfiltertype":"exact","outputinitially":false,"state_type":"habool","haltifstate":"true","halt_if_type":"bool","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":"","forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"eventData"}],"x":670,"y":1280,"wires":[["28523199ac937e5c"],[]]},{"id":"acd2084c1e178df0","type":"api-call-service","z":"66e8f946d2d274c4","name":"Camera OFF","server":"5f04c7c3.35aa98","version":5,"debugenabled":false,"domain":"light","service":"turn_off","areaId":[],"deviceId":[],"entityId":[],"data":"","dataType":"json","mergeContext":"","mustacheAltTags":false,"outputProperties":[],"queue":"none","x":1430,"y":1300,"wires":[[]]},{"id":"c834634c5948518c","type":"api-current-state","z":"66e8f946d2d274c4","name":"Check","server":"5f04c7c3.35aa98","version":3,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","entity_id":"light.luci_camera","state_type":"habool","blockInputOverrides":false,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"entityState"},{"property":"data","propertyType":"msg","value":"","valueType":"entity"}],"for":"0","forType":"num","forUnits":"minutes","override_topic":false,"state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","x":950,"y":1280,"wires":[["412ab48095d319c0"]]},{"id":"90e2c490bd435d56","type":"delay","z":"66e8f946d2d274c4","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"allowrate":false,"outputs":1,"x":940,"y":1200,"wires":[["c834634c5948518c"]]},{"id":"28523199ac937e5c","type":"function","z":"66e8f946d2d274c4","name":"SetTime","func":"var lastChange = global.set('lastChange', new Date().getTime());\nvar timeout = global.set('timeout', 5000);\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":800,"y":1280,"wires":[["c834634c5948518c"]]},{"id":"412ab48095d319c0","type":"function","z":"66e8f946d2d274c4","name":"Check Camera State","func":"var currentState = msg.payload;\n//node.warn(currentState);\nvar lastChange = global.get('lastChange');// || new Date().getTime();\nvar timeout = global.get('timeout') || 5000; // Timeout in milliseconds\n//node.warn(\"Timeout: \"+ timeout);\n//node.warn(\"Last Change: \"+lastChange);\nif (currentState) {\n    var currentTime = new Date().getTime();\n    //node.warn(\"currentTime: \" + currentTime);\n    var elapsedTime = currentTime - lastChange; // in milliseconds\n    //node.warn(\"elapsedTime :\" + elapsedTime);\n    if (elapsedTime > timeout) {\n        return [null, { payload: { data: { entity_id: 'light.luci_camera' } } }]; // payload to turn off the light\n    }\n    else {\n    //node.warn(\"Timeout not reached\");\n    //global.set('lastChange', new Date().getTime());\n    return [msg, null];\n    }\n}\n\nreturn [null, null];","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1160,"y":1280,"wires":[["90e2c490bd435d56","269eda0ba0a23e24"],["acd2084c1e178df0"]],"outputLabels":["","Turn OFF"]},{"id":"269eda0ba0a23e24","type":"debug","z":"66e8f946d2d274c4","name":"Output","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1410,"y":1220,"wires":[]},{"id":"5f04c7c3.35aa98","type":"server","name":"Home Assistant","addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"","connectionDelay":false,"cacheJson":false,"heartbeat":false,"heartbeatInterval":"","statusSeparator":"","enableGlobalContextStore":false}]

The curly bracket wasn't closed at the right "if"....anyway, thank you. It would be interessing to learn more about you way...

I can only say what i stated before.

The junction, on my browser, I press control and click the work space and a context menu appears.

The delay is set by msg.delay in the message, in this case in the inject node, but you could add it in a change or function. The trigger node accepts msg.delay (if you check the option in the config)and sets the time delay accordingly.

It is only for visual purposes or it adds some other logics?

It's just to make the flow look pretty :grin:

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