Flow - Auto Start loop

Hi,

I have a function node with a loop in it, it generates random time delays.

I want it to auto star when the PI reboots or when the flow gets re-deployed.

Is the below correct? From my function node.

const minDelay = 1, maxDelay =5; // seconds
var a = 1;
loop();

msg.payload = a;

function loop() {
    if (a==1) {
        node.send(msgToSend);
        msgToSend = msg;
        let delay = Math.random() * (maxDelay - minDelay) + minDelay;
        setTimeout(loop,1000 * delay);
        node.status({fill:'green',text:delay.toFixed(2)});
    }
}

When posting code, click the button that looks like </> at the top.

I see you tried, but.....

Ok, break down:
msg.payload = a;

Wrong way around - I think.
You want a to be the payload.
So it should be:
a = msg.payload

In your loop:
You only have testing for a == 1 What if it is another value?

Reading your original code again where: msg.payload = a:
So a will always be 1.
Why test at all?

Thank for the reply.

I want the payload to be one always.

Debug - error message

21/04/2020, 09:12:57node: d5575e9b.cc1ac
function : (error)
"ReferenceError: msgToSend is not defined"

I have taken the test out.

const minDelay = 1, maxDelay =5; // seconds
var a = 1;
loop();

msg.payload = a;

function loop() {

        node.send(msgToSend);
        msgToSend = msg;
        let delay = Math.random() * (maxDelay - minDelay) + minDelay;
        setTimeout(loop,1000 * delay);
        node.status({fill:'green',text:delay.toFixed(2)});

}

I think you have exceeded my skills sorry.

Whichever way you do it - you will need an inject (on start) node in front to trigger it to start running on boot.

Thank you for the reply-

I have put a inject node in front of it injecting 1 on at 0.1, but it still don't start.

image

As the error says, you have not defined msgToSend, you need var msgToSend = something somewhere before it is used. Alternatively perhaps you just need to change all uses of msgToSend to msg if it is actually a copy of the original msg that you want to send each time.

Thank you @Colin, solved.

These two wrong way around

node.send(msgToSend);
msgToSend = msg;

Correct is way
msgToSend = msg;
node.send(msgToSend);

Or just

    node.send(msg);

Can you have a var in setTimeout(loop,1000 * delay); instead of "delay"?

What do you mean? delay already is a variable.

Thanks for your response

Meant something link this:


msg.payload = a;

loop();


function loop() {
        msg.paload = 1;
        node.send(msg);
        let delay1 = 10;
        setTimeout(loop,1000 * delay1);
        node.status({fill:'green',text:delay1.toFixed(2)});
        
        msg.paload = 0;
        node.send(msg);
        let delay2 = 5;
        setTimeout(loop,delay2);
        node.status({fill:'green',text:delay2.toFixed(2)});

}

Can you describe what you mean. From that code, I'm really not sure what you intend.

send msg.payload =1 wait delay1 seconds and then send msg .payload = 0 wait delay2 seconds

Then what?

send msg.payload =1 wait delay1 seconds and then send msg .payload = 0 wait delay2 seconds and then the first msg

This node will have a interrupt statement in it

var run = context.get('state') || false;
if (msg.topic.toLowerCase() === 'control') {
    run = ! run;
}
context.set('state',run);
node.status({fill:(run) ? 'green':'red'});


var msgToSend = null;
loop();
return null;

loop();


function loop() {
        msg.paload = 1;
        node.send(msg);
        let delay1 = flow.get("ontime");
        setTimeout(loop,1000 * delay1);
        node.status({fill:'green',text:delay.toFixed(2)});
        
        msg.paload = 0;
        node.send(msg);
        let delay2 = flow.get("offtime");
        setTimeout(loop,1000 * delay2);
        node.status({fill:'green',text:delay.toFixed(2)});

}

don't you mean payload instead of paload?

Sorry Yes

var run = context.get('state') || false;
if (msg.topic.toLowerCase() === 'control') {
    run = ! run;
}
context.set('state',run);
node.status({fill:(run) ? 'green':'red'});


var msgToSend = null;
loop();
return null;

loop();


function loop() {
        msg.payload = 1;
        node.send(msg);
        let delay1 = flow.get("ontime");
        setTimeout(loop,1000 * delay1);
        node.status({fill:'green',text:delay.toFixed(2)});
        
        msg.payload = 0;
        node.send(msg);
        let delay2 = flow.get("offtime");
        setTimeout(loop,1000 * delay2);
        node.status({fill:'green',text:delay.toFixed(2)});

}

@Colin This is what I want to achieve , I don't know what standard node I can use, as we suffer from a lot of power outages and most timing nodes don't give you a output once the on time are pass or you cant set the day off week from a message input.

If you have a idea I can use I will appreciate.

The code in the above is for the Pump control

I think probably the easiest way is with a function node.

There are a couple of issues with your code.
I don't know what the var msgToSend line is doing, nor the loop() function after the return null.
You appear to be setting up two timers, I don't think you want to do that, you just want one, with the delay time alternating between the the two values.