Community discussions

MikroTik App
 
hci
Long time Member
Long time Member
Topic Author
Posts: 674
Joined: Fri May 28, 2004 5:10 pm

Array of Arrays

Wed Dec 06, 2023 7:10 pm

I have a script that sends an email if a certain IP fails to respond to a ping. It works but would like to improve it.
:local server "xxx.*****.org"
:local rcpt "*******@*****.com"
:local user "********@*****.org"
:local password "*******************"

:if ([/ping 192.168.35.101 count=4] = 0) do={
    /tool e-mail send to=$rcpt \
    server=[:resolve $server] port=587 tls=starttls \
    user=$user password=$password  \
    from=$user \
    subject="WEST Tower Down" body="Alarm, DOWN"
}
:if ([/ping 192.168.34.102 count=4] = 0) do={
    /tool e-mail send to=$rcpt \
    server=[:resolve $server] port=587 tls=starttls \
    user=$user password=$password  \
    from=$user \
    subject="EAST Tower Down" body="Alarm, DOWN"
}
I need to create an array like:

sites (192.168.35.101:WEST Tower, 192.168.34.102:EAST Tower)

Then use for loop rather then all these lines for each device. I would also like a loop for multiple recipients rather then one recipient.
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Wed Dec 06, 2023 9:47 pm

:local sites {"192.168.35.101"="WEST Tower"; "192.168.34.102"="EAST Tower"}
:foreach k,v in=$sites do={
  :if ([/ping $k count=4] = 0) do={
    /tool e-mail send to=$rcpt server=[:resolve $server] port=587 tls=starttls user=$user password=$password from=$user subject="$v Down" body="Alarm, DOWN"
  }
}
 
hci
Long time Member
Long time Member
Topic Author
Posts: 674
Joined: Fri May 28, 2004 5:10 pm

Re: Array of Arrays

Wed Dec 06, 2023 11:54 pm

Thanks.

Came up with:
:local server "xxx.*****.org"
:local emailToList {"*******@*****.com", "*******@*****.com"}
:local user "********@*****.org"
:local password "*******************"

:local sites {
"192.168.35.101"="WEST Tower";
"192.168.34.102"="EAST Tower";
}

:foreach k,v in=$sites do={
  :if ([/ping $k count=4] = 0) do={
    :foreach email in=$emailToList do= {
      /tool e-mail send to=$email server=[:resolve $server] \
      port=587 tls=starttls user=$user password=$password \
      from=$user subject="$v Down" body="Alarm, DOWN"
    }
  }
}
So is sites an array of arrays or is it something like a dictionary in Python?
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Thu Dec 07, 2023 1:05 am

It is handled in script like key/value dictionary (map) where "key"="value", see more at https://wiki.mikrotik.com/wiki/Manual:S ... ith_Arrays and https://help.mikrotik.com/docs/display/ROS/Scripting
 
hci
Long time Member
Long time Member
Topic Author
Posts: 674
Joined: Fri May 28, 2004 5:10 pm

Re: Array of Arrays

Mon Dec 11, 2023 8:36 pm

Could you tell me why this is not working?
:local emailToList {"*******@*****.com", "*******@*****.com"}

    :local rcpts ""
    :foreach email in=$emailToList do= {
      :if ([:len $rcpts] = 0) do={ :set rcpts "to=$email" } else={ :set rcpts "$rcpts cc=$email" }
    }
Basically I am trying to add the first email in emailToList as to= and all the following as cc= since it seems inefficient to send separate email for each recipient.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Array of Arrays

Mon Dec 11, 2023 8:55 pm

Could you tell me why this is not working?
If it's a "list", you need to do EITHER:

Parentheses and commas for a "list-like" array...

:local emailToList ("*******@*****.com", "*******@*****.com")

OR , curly braces and semi-colons (which is how you'd define a "map-like" array, but if array contains strings, then just a list too)

:local emailToList {"*******@*****.com"; "*******@*****.com"}
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12014
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Array of Arrays

Mon Dec 11, 2023 9:02 pm

Your script is wrong at the start if are present 3 addesses or more, because you can not add multiple " cc=" on same line....
Assuming you call later the command line...
Last edited by rextended on Mon Dec 11, 2023 9:03 pm, edited 1 time in total.
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Mon Dec 11, 2023 9:03 pm

@hci
You need to itterate emailToList by index to find first email in index. Also in ROS script literal array values must be separated by ;.
:local emailToList {"to_email@*****.com"; "cc_email1@*****.com"; "cc_email2@*****.com"}
:local toEmail ""
:local ccEmails ""

:for i from=0 to=([:len $emailToList] - 1) do= {
  :local email [:pick $emailToList $i]
  :if ($i = 0) do={ 
    :set toEmail "$email" 
  } else={
    if ([:len $ccEmails] > 0) do={
      :set ccEmails ($ccEmails . ",")
    }

    :set ccEmails ($ccEmails . $email)
  }
}

:put "to=$toEmail"
:put "cc=$ccEmails"
Last edited by optio on Mon Dec 11, 2023 9:06 pm, edited 1 time in total.
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12014
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Array of Arrays

Mon Dec 11, 2023 9:04 pm

Too much frills...
{
:local emailToList [:toarray "to_email@*****.com,cc_email1@*****.com,cc_email2@*****.com"]
:local toEmail     ($emailToList->0)
:local ccEmails    [:pick $emailToList 1 [:len $emailToList]]
:put "to=$toEmail"
:put "cc=$ccEmails"
}
Last edited by rextended on Mon Dec 11, 2023 9:08 pm, edited 1 time in total.
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Mon Dec 11, 2023 9:07 pm

it's faster intrepreted if is literally set :P
And in your case ccEmails is array, must be converted to comma separated string (unless /tool/e-mail/send cc= can accept array)
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12014
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Array of Arrays

Mon Dec 11, 2023 9:12 pm

A "comma separated values" inside a command line is one array....

This work
/tool e-mail send to=$toEmail cc=$ccEmails ...
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Mon Dec 11, 2023 9:18 pm

If it works then it's simpler like you did. I always check doc - 'Send a copy to listed recipients. Multiple addresses allowed, use "," to separate entries'. But It's not always clear for all cases, because print from your script is:
to_email@*****.com
cc_email1@*****.com;cc_email2@*****.com
 
User avatar
rextended
Forum Guru
Forum Guru
Posts: 12014
Joined: Tue Feb 25, 2014 12:49 pm
Location: Italy
Contact:

Re: Array of Arrays

Mon Dec 11, 2023 9:24 pm

it's just a representation from the terminal of what the array looks like.
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Mon Dec 11, 2023 9:33 pm

I understand, elements joined by ; for output string, same as [:tostr <array>]. My concern was for cc= argument or any other ROS command argument that accepts comma separated values (list of values), if they can be array type also.
I have some scripts that I use personally, always converting arrays into comma separated string before passing to command argument, but if will work as array type I will need to revise some scripts and simplify them.

Update:
And it's working with arrays, just tested with /tool/e-mail/send subject="Test subject" body="Test body" to="<myemail>" cc=({"cc_email1@some.domain";"cc_email2@some.domain"}) while /tool/e-mail/send subject="Test subject" body="Test body" to="<myemail>" cc="cc_email1@some.domain;cc_email2@some.domain" not working, because if is string must be comma separated.
So there is data type check for list command arguments or it is always peformed to get values as in script [:toarray <value>] for such arguments. It would be great that this is stated in script documentation (but a lot of things are not).
 
hci
Long time Member
Long time Member
Topic Author
Posts: 674
Joined: Fri May 28, 2004 5:10 pm

Re: Array of Arrays

Tue Dec 12, 2023 1:48 am

My primary problem was as someone pointed out:
:local emailToList {"*******@*****.com", "*******@*****.com"}
Should have been:
:local emailToList ("*******@*****.com", "*******@*****.com")
Also, stopped trying to use cc. Came up with this and appears to work.
:local server "xxx.*****.org"
:local emailToList ("*******@*****.com", "*******@*****.com")
:local user "********@*****.org"
:local password "*******************"

:local sites {
"192.168.35.101"="WEST Tower";
"192.168.34.102"="EAST Tower";
}


:foreach k,v in=$sites do={
  :if ([/ping $k count=4] = 0) do={
    :local rcpts ""
    :foreach email in=$emailToList do= {
      :if ([:len $rcpts] = 0) do={ :set rcpts "to=$email" } else={ :set rcpts ("$rcpts,$email") }
    }
    :local emailCommand ("/tool e-mail send $rcpts server=[:resolve $server] port=587 tls=starttls \
      user=$user password=$password from=$user subject=\"$v Down\" body=\"Alarm, DOWN\"")
    :execute $emailCommand
  }
}
I was thinking in past Mikrotik e-mail to= did not accept multiple comma separated recipients but apparently it does now.
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Tue Dec 12, 2023 2:12 am

Yes, can be confusing because of multiple ways to create arrays in ROS, like {"val1";"val2"} or ("val1","val2") or [:toarray "element1,element2"] and also passing them as argument as mentioned above.
 
User avatar
Amm0
Forum Guru
Forum Guru
Posts: 3509
Joined: Sun May 01, 2016 7:12 pm
Location: California

Re: Array of Arrays

Tue Dec 12, 2023 2:22 am

Yes, can be confusing because of multiple ways to create arrays in ROS, like {"val1";"val2"} or ("val1","val2") or [:toarray "element1,element2"]
And as noted above (@rextended #11), the to= takes an array type. So once you use any of the above formats, there may be no need for the rather complex inner for loop or execute.

e.g.
:global emails ("amm0@example.com","optio@example.com")
/tool/e-mail/send to=$emails body=test subject=test

(assuming you pre-set the mail server/port via "/tool/e-mail/set" (or in Winbox/Webfig in Tool>Email))
 
optio
Long time Member
Long time Member
Posts: 675
Joined: Mon Dec 26, 2022 2:57 pm

Re: Array of Arrays

Tue Dec 12, 2023 2:46 am

It makes sence that array values can be passed into command argument because they are interpreted by same interpreter. I was in mindset like writing shell scripts when you usually need to convert shell array values into some program command arguments.

Who is online

Users browsing this forum: No registered users and 3 guests