Help for a loop functiopn

Hi guys,

i'm trying to create a flow that will output the sensors in alarm to Alexa before launch a script on Home-Assistant that will close all shutter and the arm the alarm.

Main problem is when i need to send the alert to Alexa (and don't execute the service call) or just execute service call where there is no alarm.

Here is the current flow:

the function inside is this one:

var zone_status =[];
var zone_name = [];
var sensor_status = [];

// Infrarossi
zone_status[1] = msg.payload.zonesStatus.zone[2].status    // Infrarosso Cameretta
zone_name[1] = "Infrarosso Cameretta"
zone_status[2] = msg.payload.zonesStatus.zone[3].status    // Infrarosso Camera
zone_name[2] = "Infrarosso Camera"
zone_status[3] = msg.payload.zonesStatus.zone[5].status    // Infrarosso Ingresso
zone_name[3] = "Infrarosso Ingresso"

// Tapparele
zone_status[4] = msg.payload.zonesStatus.zone[27].status   // Tapparelle Camera
zone_name[4] = "Tapparelle Camera"
zone_status[5] = msg.payload.zonesStatus.zone[22].status   // Tapparelle Salone
zone_name[5] = "Tapparelle Salone"
zone_status[6] = msg.payload.zonesStatus.zone[15].status   // Tapparella Cameretta
zone_name[6] = "Tapparella Cameretta"
zone_status[7] = msg.payload.zonesStatus.zone[17].status   // Tapparella Bagno
zone_name[7] = "Tapparella Bagno"
zone_status[8] = msg.payload.zonesStatus.zone[12].status   // Tapparella Cucina
zone_name[8] = "Tapparella Cucina"

// Shock
zone_status[9] = msg.payload.zonesStatus.zone[10].status    // Shock Cucina
zone_name[9] = "Shock Cucina"
zone_status[10] = msg.payload.zonesStatus.zone[13].status   // Shock Cameretta
zone_name[10] = "Shock Cameretta"
zone_status[11] = msg.payload.zonesStatus.zone[16].status   // Shock Bagno
zone_name[11] = "Shock Bagno"
zone_status[12] = msg.payload.zonesStatus.zone[18].status   // Shock Salone Lunga
zone_name[12] = "Shock Salone Lunga"
zone_status[13] = msg.payload.zonesStatus.zone[20].status   // Shock Salone Corta
zone_name[13] = "Shock Salone Corta"
zone_status[14] = msg.payload.zonesStatus.zone[23].status   // Shock Camera Corta
zone_name[14] = "Shock Camera Corta"
zone_status[15] = msg.payload.zonesStatus.zone[25].status   // Shock Camera Lunga
zone_name[15] = "Shock Camera Lunga"

// Magneti
zone_status[16] = msg.payload.zonesStatus.zone[4].status    // Magnete Portone
zone_name[16] = "Magnete Portone"
zone_status[17] = msg.payload.zonesStatus.zone[11].status   // Magnete Cucina
zone_name[17] = "Magnete Cucina"
zone_status[18] = msg.payload.zonesStatus.zone[14].status   // Magnete Cameretta
zone_name[18] = "Magnete Cameretta"
zone_status[19] = msg.payload.zonesStatus.zone[19].status   // Magnete Salone Lunga
zone_name[19] = "Magnete Salone Lunga"
zone_status[20] = msg.payload.zonesStatus.zone[21].status   // Magnete Salone Corta
zone_name[20] = "Magnete Salone Corta"
zone_status[21] = msg.payload.zonesStatus.zone[24].status   // Magnete Camera Corta
zone_name[21] = "Magnete Camera Corta"
zone_status[22] = msg.payload.zonesStatus.zone[26].status   // Magnete Camera Lunga
zone_name[22] = "Magnete Camera Lunga"

// START FUNCTION
for (var i = 1; i < zone_status.length; i++) {
        if ((zone_status[i]) == "ALARM") {
                msg.payload = "Sensore" + (zone_name[i]) + " è in allarme,"
                node.send(msg)
            }
        else {
            msg.payload = "ok"
            node.send(msg)
        }
}

On the switch node i've put this configuration:

but i looks like that also if the first check match, it hits also the "otherwise" when "stop at first match" is selected

Can you help me?

thanks!

What do you see in the debug node when you believe it is wrongly sending to the 'otherwise' output.

i see "ok", but the problem is that i shouldn't see anything if the first node (that check "allarme" word) should stop and avoid sending to the second output.

Is it right?

If you mean that the payload contains "ok" then it does not contain "allarme" so it should be sent to output 2 (because the allarme test has failed).

[Edit] I wonder whether you meant to only send "ok" if none of the alarms is active. As you have it then you will get either an alarm message or an ok for every element of the array. If so then add a line before the loop
let ok = true
then in the else condition, instead of sending a message do
ok = false
the result will be that at the end of the loop the variable ok will tell you whether there were any alarms. Then you can add

if (ok ) {
  msg.payload = "ok"
  node.send(msg)
}

where i've to put the latest if?
inside the else or outside the loop?

After the main loop, so it will run right through the array, sending alarm messages if necessary, then after that is finished it will send ok if it did not find any alarms.

in that way?

// START FUNCTION
let ok = true
for (var i = 1; i < zone_status.length; i++) {
        if ((zone_status[i]) == "AALARM") {
                msg.payload = "Sensore" + (zone_name[i]) + " è in allarme,"
                node.send(msg)
            }
        else {
            ok = false
        }
}

if (ok) {
    node.send(msg)
}

What do you think yourself looking at the code and working out what it does?

You have lost the msg.payload = "ok"

// START FUNCTION
let ok = true
for (var i = 1; i < zone_status.length; i++) {
        if ((zone_status[i]) == "ALARM") {
                msg.payload = "Sensore" + (zone_name[i]) + " è in allarme,"
                node.send(msg)
            }
        else {
            ok = false
        }
}

if (ok) {
    msg.payload = "ok"
    node.send(msg)
}

ok, i've fixed the code, but when no "alert", the second output of the switch is not triggered

Sorry, the changes I suggested are all wrong. So wrong that I am surprised you did not see it when working out what it does :). You don't need the else at all, it should set ok to false whenever it sends a alarm message, so that it won't send ok if it sends any alarms.

let ok = true
for (var i = 1; i < zone_status.length; i++) {
        if ((zone_status[i]) == "ALARM") {
                msg.payload = "Sensore" + (zone_name[i]) + " è in allarme,"
                node.send(msg)
                ok = false
            }
}

if (ok) {
    msg.payload = "ok"
    node.send(msg)
}

yes sorry but i'm not so expert ^_^"
removing else and put the check out of the loop gives me the expected result!

thank you so much :slight_smile:

Neither am I it seems, or I would not have posted rubbish in the first place.

@stich86

@Colin latest posted code will work fine but you might his a subtle bug due to msg being an object so settings msg.payload for each alarm actually changes the value of .payload for already sent messages & could impact your flows in odd ways.

To avoid this possible anomaly, you might want to consider sending new messages...

let ok = true;
for (let i = 1; i < zone_status.length; i++) {
  if ((zone_status[i]) == "ALARM") {
    //alarm found - create and send a new message object...
    let m = { payload: "Sensore" + (zone_name[i]) + " è in allarme," }
    node.send(m);
    ok = false;
  }
}

if (ok) {
  msg.payload = "ok"
  node.send(msg)
}

I think this is not an issue as node.send() always clones the message before sending it.

1 Like

DOH - I keep forgetting that...

... I suppose its because in custom node development, the opposite is true :man_shrugging:

@stich86 ignore my previous post :smiley: