I'm implementing a valve check for my irrigation system. Basically I'm switching valves on and off in a certain sequence and timing, and I'm monitoring the water consumption in between, using mqtt in and out messages. Implementation is a function node with a state machine that is receiving two type of messages, mqtt water messages and event state transition messages, and is emitting two type of messages as well, mqtt valve switch messages and event state transition messages. The event state transition messages are emitted by node.send() within a setTimeout callback to one of the outputs and are routed back to the node itself.
My issue is that node-red does not like me to create the path from the output back to the input of the same node.
How would you go about this? Route it via a no-op function node?
Not sure what to say here. I guess with flow logic it would be possible ...
// 7:50 Überprüfe Hauptventilfunktion
var t5 = {
mainoff: {topic:"t5/set/10",payload:{valve:"OFF"}},
mainon: {topic:"t5/set/10",payload:{valve:"ON"}},
valve2s: {topic:"t5/set/6",payload:{"valve,1":2}},
alert: {topic:"t5/alert",payload:"Valve check error, "},
}
var st = context.get("st")
var mqtt = [];
function after(ms,sn) {
st.hl = 0;
st.sn = 1;
setTimeout(function(){node.send([{event:sn},null]);},ms);
}
function t5error(error) {
if (error) {
mqtt = [t5.mainoff,{topic:t5.alert.topic,payload:t5.alert.payload+error+" "+(st.hl/2.0).toFixed(1)+"l"}];
flow.set("valvecheckerror",true);
} else {
flow.set("valvecheckerror",false);
}
st.sn = 0;
}
if (st===undefined) {
st = {sn:0};
context.set("st",st); // Changes to st below will be reflected in the context store
}
if (st.sn==1 && msg.event>1) {
st.sn = msg.event;
}
switch (st.sn) {
case 0: // Switch main valve on, ignore flow the first five seconds, then check for one minute that no water flows
if (msg.event=="start") {
mqtt = [t5.mainon];
after(5000,2);
}
break;
case 1: // Count the half liters being consumed
if (msg.payload.topic=="hl") {
st.hl++;
}
break;
case 2: // Check for one minute that no water is in use
after(60000,3);
break;
case 3:
if (st.hl) { // We detected water running when preparing the test. Flag error.
t5error("in use");
} else { // Open pond valve for 2 seconds and check for 5 seconds that the water consumption is as expected between 1.5 and 2.5 liters
mqtt = [t5.valve2s];
after(5000,4);
}
break;
case 4:
if (st.hl<3 || st.hl>5) { // Our opening of the valve2s has resulted in unexpected water use
t5error("strange");
} else { // Close main valve and wait one second, then open pond valve again
mqtt = [t5.mainoff];
after(1000,5);
}
break;
case 5: // Open pond valve for two seconds and check for 5 seconds that no water is consumed with the main valve closed
mqtt = [t5.valve2s];
after(5000,6);
break;
case 6:
if (st.hl) { // We detected water running despite the main valve closed. Flag error.
t5error("not off");
} else { // Open main valve again and clear error. Note: Opening main valve will repressurise the system resulting in a slight flow
mqtt = [t5.mainon];
t5error();
}
break;
}
return [null,mqtt];