【问题标题】:node red setInterval return same value节点红色 setInterval 返回相同的值
【发布时间】:2019-03-15 21:58:25
【问题描述】:

我的问题是我有一个函数节点,它每 2 秒从 PIR 传感器读取输入 0 或 1。一旦从传感器读取 1,我希望我的功能节点将输出 1 保持 10 秒。

var newMsg;

if (msg.payload === 1 ){
    newMsg = {payload:0};
    setInterval(returnMsg, 10000);
}

else{
    newMsg = {payload:1};
}

return newMsg;



function returnMsg(){
    return newMsg;
}

我尝试使用 setInterval 但它不起作用。

编辑:

非常感谢大家的回复!

具体来说:

flow

仪表会是这样的:

gauge

我想要做的是,一旦 PIR 传感器检测到运动,仪表将在 0 处显示 10 秒。但是现在一旦传感器的读数发生变化,仪表就会不断变化。

【问题讨论】:

  • 让它每 2 秒运行一次的代码在哪里?
  • 你认为代码会不断更新 if/else 吗?不确定您期望 returnMsg 从 setInterval 返回什么...。我认为您需要分享您实际尝试完成的工作,因为您所做的似乎是错误的。
  • @putvande 实际上不是 2s,很抱歉我试图简化我的问题。它实际上一直在从传感器读取数据。
  • @epascarello 感谢您的回复。我已经编辑了我的问题。我希望现在更具体。

标签: javascript mqtt setinterval node-red


【解决方案1】:

满足您的要求的一种可能方法是使用开关节点作为门。此门最初将打开,允许消息流动。当payload为“1”时,表示PIR被触发,函数节点内部的代码会通过改变一个控制切换节点的流上下文变量来关闭门。同时,函数节点中的代码会配置一个回调函数,在10秒内重新打开大门。

函数内部代码:

if (msg.payload === 1) {
    closeGate();
}


function closeGate() {
        flow.set("gateopen", false); //close gate
        setTimeout(openGate, 10000); // reopen gate within 10 seconds
}


function openGate() {
    flow.set("gateopen", true);
}

flow.get("gateopen") ? node.status({fill:"green",shape:"ring",text:"Opened"}) :
                       node.status({fill:"red",shape:"ring",text:"Closed"});

return msg;

流程:

[{"id":"8696aea0.42f8f","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"e3f585c9.421cb8","type":"inject","z":"8696aea0.42f8f","name":"","topic":"","payload":"0","payloadType":"num","repeat":"2","crontab":"","once":true,"onceDelay":"0.5","x":190,"y":200,"wires":[["be4bd9b8.de4d78"]]},{"id":"be4bd9b8.de4d78","type":"switch","z":"8696aea0.42f8f","name":"","property":"gateopen","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":370,"y":220,"wires":[["23cd0407.7efcec"]]},{"id":"63b4ec7c.b18904","type":"inject","z":"8696aea0.42f8f","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":240,"wires":[["be4bd9b8.de4d78"]]},{"id":"db6c9c0d.4c21b","type":"debug","z":"8696aea0.42f8f","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":670,"y":220,"wires":[]},{"id":"fbf0ec86.55906","type":"inject","z":"8696aea0.42f8f","name":"Open gate","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"0.5","x":190,"y":120,"wires":[["2325a5f7.0d1d1a"]]},{"id":"23cd0407.7efcec","type":"function","z":"8696aea0.42f8f","name":"Gate","func":"if (msg.payload === 1) {\n    closeGate();\n}\n\n\nfunction closeGate() {\n        flow.set(\"gateopen\", false); //close gate\n        setTimeout(openGate, 10000); // reopen gate within 10 seconds\n}\n\n\nfunction openGate() {\n    flow.set(\"gateopen\", true);\n}\n\nflow.get(\"gateopen\") ? node.status({fill:\"green\",shape:\"ring\",text:\"Opened\"}) :\n                       node.status({fill:\"red\",shape:\"ring\",text:\"Closed\"});\n\nreturn msg;","outputs":1,"noerr":0,"x":510,"y":220,"wires":[["db6c9c0d.4c21b"]]},{"id":"2325a5f7.0d1d1a","type":"change","z":"8696aea0.42f8f","name":"Open gate","rules":[{"t":"set","p":"gateopen","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":120,"wires":[[]]}]

如果发生新的 PIR 事件,下面是延长计时器的替代流程:

[{"id":"585ba08b.3667e","type":"tab","label":"Flow 3","disabled":false,"info":""},{"id":"4cb35501.7c04fc","type":"inject","z":"585ba08b.3667e","name":"","topic":"","payload":"0","payloadType":"num","repeat":"2","crontab":"","once":true,"onceDelay":"0.5","x":190,"y":200,"wires":[["87ab9f12.fd8ad"]]},{"id":"e1699672.cb5788","type":"switch","z":"585ba08b.3667e","name":"","property":"gateopen","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":590,"y":200,"wires":[["c40dbf1f.79ef4"]]},{"id":"aafaf20e.95d46","type":"inject","z":"585ba08b.3667e","name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":190,"y":240,"wires":[["87ab9f12.fd8ad"]]},{"id":"c40dbf1f.79ef4","type":"debug","z":"585ba08b.3667e","name":"","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"msg","x":810,"y":200,"wires":[]},{"id":"5e76c261.a4f9ac","type":"inject","z":"585ba08b.3667e","name":"Open gate","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":true,"onceDelay":"0.5","x":190,"y":120,"wires":[["b255cf40.af298"]]},{"id":"4c13bbad.850434","type":"function","z":"585ba08b.3667e","name":"Gate","func":"if (flow.get(\"gateopen\")) {\n    closeGate(); // gate is opened and will be closes it for 10 seconds\n} else {\n    extendGate(); // gate is already closed. The timer will reset and  new 10 second timeout will start\n}\n\n\nfunction closeGate() {\n        flow.set(\"gateopen\", false); //close gate\n        flow.set(\"gateid\", setTimeout(openGate, 10000));\n}\n\n\nfunction openGate() {\n    flow.set(\"gateopen\", true);\n}\n\nfunction extendGate() {\n    clearTimeout(flow.get(\"gateid\"));\n    closeGate();\n}\n\n\nreturn msg;","outputs":1,"noerr":0,"x":590,"y":240,"wires":[["c40dbf1f.79ef4"]]},{"id":"b255cf40.af298","type":"change","z":"585ba08b.3667e","name":"Open gate","rules":[{"t":"set","p":"gateopen","pt":"flow","to":"true","tot":"bool"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":120,"wires":[[]]},{"id":"87ab9f12.fd8ad","type":"switch","z":"585ba08b.3667e","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"num"},{"t":"eq","v":"1","vt":"num"}],"checkall":"true","repair":false,"outputs":2,"x":370,"y":220,"wires":[["e1699672.cb5788"],["4c13bbad.850434"]]}]

【讨论】:

  • 如果在 10 秒前又有 1 次国会会议结束,您没有清除超时以延长窗口
  • 确实,好点@hardillb。该流程的设计假设不需要扩展窗口(当然,当它已经处于活动状态时)。如果这是一个要求(这是有道理的,但在 OP 中没有明确说明),那么有必要重构流程。当超时激活时,新的“1”将永远不会到达功能门。流程的工作方式会阻止前一个节点中的有效负载(0 或 1 或其他)。
  • 感谢您的帮助。我导入了您的流程并没有更改任何内容,但它无法正常工作。注入哪个节点都没有输出,不显示节点状态。
  • @Gary Lin,我想知道您是否有不支持持久上下文的非常旧版本的 Node-RED。您能否发布您正在使用的 Node-RED 版本?
  • @AIOTMAKER 我使用的是 0.19.6
【解决方案2】:

只需检查自上次收到1 以来是否不到 10 秒:

这一行应该在读取传感器值的函数之外

var last = new Date(2000, 1, 1,  1, 1);

然后在你的函数中:

if (msg.payload === 1 ){
    last = new Date();
}

return (new Date() - last)<10000?1:0;

【讨论】:

  • 这不起作用,因为每次新消息到达时都会重置最后一个变量。函数节点的作用域会为每条传入消息重置。
  • @hardillb 它不会重置(它不在读取传感器的函数内部),如果读取值为 1,它将被设置
  • 非常感谢您的回复。我尝试了您的代码,但仍然无法正常工作。我编辑了我的问题以使其更具体。
  • 是的,整个代码块都在 Node-RED 函数节点中,每次邀请时都会抛出整个范围(每 2 秒轮询 pir 时),这是不正常的JavaScript 环境
  • @hardillb 我对此很陌生。你知道我应该怎么做吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-24
  • 1970-01-01
相关资源
最近更新 更多