How to loop inside a function with delays inside the function?

724 views
Skip to first unread message

Eduardo Ibarra Arcos

unread,
Jul 3, 2017, 3:26:25 PM7/3/17
to Node-RED
Hi, what I am wanting to do is a function that takes 4 parameters, and that compare two of them while the 3 and 4 is decrementing (1 minute real time) to zero and exit the loop.
While sensor A ! = 0 ask if Tmax1 (days) is greater than zero, compare sensor value with a set value, publish comparison result, wait one minute, decrease one minute of Tmax and ask again.
Finished ask if Tmax2 (days) is greater than zero, compare sensor value with a set value, publish comparison result, wait one minute, decrease 1 minute of Tmas2 and ask again.

Csongor Varga

unread,
Jul 3, 2017, 3:42:06 PM7/3/17
to Node-RED
I have done something similar. Create a function node, wire your parameter input to this function node and also connect an inject node into it. Set up the inject to trigger every minute, and also set this inject a specific topic for example: counter.

In the function node, you can easily check if you are getting a sensor data, or a counter trigger. If you are getting a sensor data (msg.topic!=="counter"), store the parameter in the context: context.set("param1",msg.payload.param1) and so on for all 4 params.

If the trigger is the counter (msg.topic==="counter"), decrease your Tmax1, or Tmax2 counter by one.
First you need to get the previous counter value from the context: tmax1 = context.get("tmax1"). Before that, I usually check if this value exists in the context and if not you can initialize your counter. Something like this:
if (context.get("tmax1")===undefined) {
  tmax1 = 100;
  context.set("tmax1",tmax1);
}
Don't forget to store the decreased tmax1, tmax2 values back in the context before you exit the function.

You can also control under which circumstances you send a result out, simply but not executing the return msg command.

I think this should work for you.

Regards,
Csongor

Eduardo Ibarra Arcos

unread,
Jul 5, 2017, 4:03:07 PM7/5/17
to Node-RED
Hi Csongor Varga, thanks for your help. Try to do what you told me, but I could not do it, I'm new in Node Red and not a very good programmer. If it is not too much trouble and you could help me by sending me something of what you did, I would appreciate it much more.
Thank you very much, regards.

Csongor Varga

unread,
Jul 6, 2017, 3:42:07 AM7/6/17
to Node-RED
My example is quite specific and it would be difficult to understand without seeing the entire concept. But this is the main part of the code:

var devicename = "sdm120"; // Device name used for context variable

var temp = context.get(devicename+"_update"); // This is where the last update value is stored (when I got message from the device last time
var current = new Date();
msg.payload = "No data";
if (msg.topic!=="timecheck") {
    // Do not update the context if it is triggered by the timecheck inject node
    // Implement a code here to store your parameters in the context. In the below line I store the current timestamp
    context.set(devicename+"_update",current);
}
if (temp===undefined) {
    // this will be the case when node-red is booting up or redeployed and this function running for the first time
    context.set(devicename+"_update",current);
}

if (temp!==undefined) {
    // in the code below, I calculate the time passed since the last update received from the device 
    current = current - temp;
    current = Math.floor(current/1000);
    var minute = Math.floor(current/60);
    var hour = Math.floor(minute/60);
    var day = Math.floor(hour/24);
    if (current>24*60*60) {
        msg.payload = "Last update " + day + " days, " + hour%24 + " hours, " + minute%60 + " minutes, " + current%60 + " seconds ago";
    } else if (current>60*60) {
        msg.payload = "Last update " + hour%24 + " hours, " + minute%60 + " minutes, " + current%60 + " seconds ago";
    } else if (current>60) {
        msg.payload = "Last update " + minute%60 + " minutes, " + current%60 + " seconds ago";
    } else {
        msg.payload = "Last update " + current%60 + " seconds ago";
    }

}
    
node.status({fill:"blue",shape:"ring",text:msg.payload});

// you need to put this line inside in one of the if statements, not to send out result every time.
return msg;

Cheers,
Csongor
Reply all
Reply to author
Forward
0 new messages