Hello ,
want to know how can I make a script that give me the device that connected latest.
for example:
/interface wireless registration-table print
# INTERFACE RADIO-NAME MAC-ADDRESS AP SIGNAL-STRENGTH TX-RATE UPTIME
0 wlan1 120 00:11:F5:6F:C3:85 yes -43dBm@6Mbps 18.0... 36m41s
1 wlan1 122 00:11:F5:6F:C3:68 yes -44dBm@6Mbps 12.0... 34m47s
so I want to get the mac-address of radio 122 , because he connect for 34:47m and the first one connect 36:41m
is it always be the lower one? I mean the last in the list? can I count on it ?
Thanks ,
I don’t think you can count on it being the last, since order is not important in this menu… And I also don’t know of any built in sorting or min/max functions in RouterOS.
The best you can do is “print as-value”, look for the minimum uptime, and get that item’s mac-address.
e.g.
:local regTable [/interface wireless registration-table print as-value];
:if ([:len $regTable] = 0) {
#Empty reg table... What now?
} else={
:local minUptime ([:pick $regTable 0]->"uptime");
:local lastMac ([:pick $regTable 0]->"mac-address");
:foreach v in=$regTable do={
:if (($v->"uptime") < $minUptime) do={
:set minUptime ($v->"uptime");
:set lastMac ($v->"mac-address");
}
}
#The variable $lastMac now contains the latest registered mac-address
}
EDIT: Wait, what happened with your post a moment ago? Did you realized your error and immediately deleted it?
The “print” command, unless it has “as-value” will just print the results on screen.
You could use “find” to get the IDs, and then, as you do, use “get”, but that’s less efficient (CPU wise) from “print as-value”. Also BTW, you’re writing to the same file multiple times… you should collect the contents in a separate variable, and write it all at once afterwards, so f.e.
:local fileContents "";
:foreach i in=[/interface wireless registration-table as-value] do={
:set fileContents ($fileContents . ($i->"signal-strength") . "\n");
}
/file set test.txt contents=$fileContents;
(Note that this assumes test.txt already exists; RouterOS will error at the “/file set” command if it doesn’t)
I see what you have done- thanks !
can you explain to e some things inside the script
- what does “print as value” mean?
I know what it mean --print as an array , but how can I see it to more understand what I can look from there ? or it is as I see it on “print” command?
- what does this part do -
([:pick $regTable 0]->"uptime");
?
if I understand right -
you pick the first data (this is why you took 0) from the “uptime” column and save it ? then you compare it to all other data in the other lines? right? so if i know I have 4 device connected I can also start from the last one and
:pick $regTable 3]->"uptime"
, (I know there is no meaning of this - just want to see I understand the command )
3. now if I want to change the parameter I look for , how can I do this ?
I want to look for the lowest signal-strength, but when I change I get :
I understand I need to remove the dB part of the signal
so I did this :
global MinStrength ([:pick $FullStrength 0 [:find $FullStrength dBm]])
and now I can get just the number -65 , and before I got -65dBm@18Mbps
so can you help me with writing the code with this command -
so in the end the script will remove the one with the lowest signal connected ?
this is what I got so far , and I stuck and the "foreach v " part
I get en empty line when I try to print the “temp”
the script is working because if I write numbers (1,2..) instead of “$v” i can see the right answer
so I assume it’s a simple thing I have miss
:local regTable [/interface wireless registration-table print as-value];
:if ([:len $regTable] = 0) do={
:log warning "No one connect";
} else={
:global Signal ([:pick $regTable 0]->"signal-strength");
:global LowSignal ([:pick $Signal 0 [:find $Signal dBm]]);
:global lastMac ([:pick $regTable 0]->"mac-address");
:log warning "$Signal ---> $LowSignal";
:foreach v in=$regTable do={
:global TempSignal ([:pick $regTable $v]->"signal-strength");
:global TempLow ([:pick $TempSignal $v [:find $TempSignal dBm]]);
:log warning "$TempSignal ---> $TempLow";
:if ($TempLow < $LowSignal) do={
:set LowSignal ($v->"signal-strength");
:set lastMac ($v->"mac-address");
}
}
#The variable $lastMac now contains the latest registered mac-address
:log warning "$lastMac";
}
Thanks ,
- what does “print as value” mean?
I know what it mean --print as an array , but how can I see it to more understand what I can look from there ? or it is as I see it on “print” command?
It’s an array where each item is the item from the list. The item itself is presented as an associative array. The array key is the property name (as you see it outputted on screen), and the array value is the property’s value (again, as seen in the output on screen).
- what does this part do -
Code: Select all
([:pick $regTable 0]->“uptime”);?
if I understand right -
you pick the first data (this is why you took 0) from the “uptime” column and save it ? then you compare it to all other data in the other lines? right?
in order to find the minimum, yes.
- now if I want to change the parameter I look for , how can I do this ?
I want to look for the lowest signal-strength, but when I change I get :
I understand I need to remove the dB part of the signal
You need to first store the part with the “dB”, and process that.
this is what I got so far , and I stuck and the "foreach v " part
The variable $v holds the actual associative array. You don’t need to “:pick” anything. The “:foreach” has already done that.
So rather than
:global TempSignal ([:pick $regTable $v]->"signal-strength");
you’d have
:global TempSignal ($v->"signal-strength");
and analogously for the rest.
BTW, it’s important that you use :local variables instead of :global ones, as :global variables only get the specified value if they don’t exist already.
o.k.
what do I need to change in the “TempLow”?
it doesn’t make the adjustment i want and need for the signal
:local TempSignal ($v->"signal-strength"); ## I have change it like you told me
:local TempLow ([:pick $TempSignal $v [:find $TempSignal dBm]]); ## what to do here ??
:log warning "$TempSignal --> $TempLow";
this is all the script if you want to see
:local regTable [/interface wireless registration-table print as-value];
:if ([:len $regTable] = 0) do={
:log warning "No one connect";
} else={
:local Signal ([:pick $regTable 0]->"signal-strength");
:local LowSignal ([:pick $Signal 0 [:find $Signal dBm]]);
:local lastMac ([:pick $regTable 0]->"mac-address");
:log warning " $Signal --> $LowSignal";
:foreach v in=$regTable do={
:local TempSignal ($v->"signal-strength");
:local TempLow ([:pick $TempSignal $v [:find $TempSignal dBm]]);
:log warning "$v- $TempSignal --> $TempLow";
:if ($TempLow < $LowSignal) do={
:set LowSignal ($v->"signal-strength");
:set lastMac ($v->"mac-address");
}
}
#The variable $lastMac now contains the latest registered mac-address
:log warning " $lastMac";
}
Thanks ,
:local TempLow ([:pick $TempSignal $v [:find $TempSignal dBm]]); ## what to do here ??
The :pick on this line is supposed to pick out characters out of $TempSignal, not items out of $regTable
=>
use 0 here, since you want to get everything from the first character, up to the point where the string “dBm” is, i.e.
:local TempLow ([:pick $TempSignal 0 [:find $TempSignal dBm]]);
Also, replace
:set LowSignal ($v->"signal-strength");
with
:set Signal ($v->"signal-strength");
:set LowSignal ([:pick $Signal 0 [:find $Signal dBm]]);
as otherwise, the 3rd iteration around, you’ll be doing comparrisons between the number and the string with “dBm”.
Thanks I understand now and it’s working !
thank you for your help - I think it a good script
now I need to make the script work for up to 3 connections
meaning
while registration>3 run the script and remove the worst connection.
if registration<3 do= open all wds connections
else if registration=3 do=close all inactive wds
I will try to this on my own , and if I get stuck I will ask here (you
) again
Thanks ,
this is the final script
can you see if I did it good?
it’s working, but just to be sure
:global WDSApprove 3;
:local regTable [/interface wireless registration-table print as-value];
while ([:len $regTable] > $WDSApprove) do={
:local Signal ([:pick $regTable 0]->"signal-strength");
:local LowSignal ([:pick $Signal 0 [:find $Signal dBm]]);
:local lastMac ([:pick $regTable 0]->"mac-address");
:log warning " $Signal --> $LowSignal";
:foreach v in=$regTable do={
:local TempSignal ($v->"signal-strength");
:local TempLow ([:pick $TempSignal 0 [:find $TempSignal dBm]]);
:log warning "$v- $TempSignal --> $TempLow";
:if ($TempLow < $LowSignal) do={
:set LowSignal ($v->"signal-strength");
:set LowSignal ([:pick $LowSignal 0 [:find $LowSignal dBm]]);
:set lastMac ($v->"mac-address");
}
}
local WDSName [/interface wireless wds get value-name=name [find where wds-address=$lastMac]];
:log warning " WDS that will remove is - $WDSName";
/interface wireless wds disable [find where wds-address=$lastMac]
:set regTable [/interface wireless registration-table print as-value];
}
if ([:len $regTable]= $WDSApprove ) do={/interface wireless wds disable [find where running=no]; log warning "stay as is "} else={:if ([:len $regTable]< $WDSApprove) do={:log warning "do nothing,all good";}
}
Thanks ,
The registration table includes not just WDS enabled devices, but also “normal” wireless clients.
So you might want to adjust your “print” to only match WDS devices, i.e.
replace both
[/interface wireless registration-table print as-value]
with
[/interface wireless registration-table print as-value where wds=yes]
all the connection are going to be WDS - but I guess you are right this is for the best to do this.
to eliminate future problems
Thanks ,
the rest of the script is o.k. right?
Well, I would add “:” in front of the “while” and the “local”, just in case you later modify the script to go to a particular menu before this section is hit… But yeah, it’s OK.