Script to get RSRP and then do...

Hi.

I tried to get RSRP value from LTE interface and then do somethings using “if” conditions.

I want to personalyze the numbers of leds (on/off) depending of the signal levels.

I know that you can enable this function using this:

/system leds
add interface=lte1 leds=led1,led2,led3,led4,led5 modem-signal-treshold=-91 type=modem-signal

But I want get something more personalized.

Regards.

I did some experiment on my hAP lite to represent Wifi signal strength.

Have a look here:
http://forum.mikrotik.com/t/using-wifi-or-user-led-to-show-signal-strength/125496/1

It’s a very very interesting code. The problem is that I can’t “get” the value name “RSRP”.

Regards.
Screenshot_2.png

I found this code that “captures the value” and sends to logs:

/interface lte info lte1 once do={
:log info "RSRP:= $"rsrp""}

The problem is that I not want flood the log of my device with the value of the signal strengh.

Regards.

Ok, I have news. Finally I found the way to capture the RSRP value and set it to a variable:

/interface lte info lte1 once do={:global rsrp1 $"rsrp"};

LtAP has 5 leds for signal strengh that are led1,led2,led3,led4 and led5 respectivelly

Now with the variable rsrp1 that is the signal strengh I need the following:

Between -120 and -111 only led1 on.
Between -110 and -101 led1 and led2 on.
Between -100 and -91 led1, led2 and led3 on.
Between -90 and -81 led1, led2, led3 and led4 on.
major and equal that -80 the 5 leds on.

If none on these condisions are true, set 5 leds off.

I’m very newbie with scripting in general and I will appretiate your help.

Regards.

For now I have this code:

#Create "runLoop" variable
:global runLoop true
#Do the following:
:do {
#See the info of LTE interface
	/interface lte info lte1 once do={
	#Capture RSRP value and save as "RSRP1" variable
		:global rsrp1 $"rsrp"
		#Prevents high CPU utilization
		:delay 100ms
		#End tasks
	}
	#Run it while runLoop variable is true
} while=($runLoop)

Now, I created a code but the log is crazy!

{
:global runloop true
:do {
/interface lte info lte1 once do={
:global rsrp1 $"rsrp"
:delay 100ms
:if ($rsrp1 >= -80) do={
/system leds set 1 leds=led1,led2,led3,led4,led5 type=on
} else={
:if (($rsrp1 >= -90) && ($rsrp1 <= -81)) do={
/system leds set 1 leds=led1,led2,led3,led4 type=on
} else={
:if (($rsrp1 >= -100) && ($rsrp1 <= -91)) do={
/system leds set 1 leds=led1,led2,led3 type=on
} else={
:if (($rsrp1 >= -110) && ($rsrp1 <= -101)) do={
/system leds set 1 leds=led1,led2 type=on
} else={
:if (($rsrp1 >= -120) && ($rsrp1 <= -111)) do={
/system leds set 1 leds=led1 type=on
} else={
/system leds set 1 leds=led1,led2,led3,led4,led5 type=off
}
}
}
}
}
}
} while=($runloop)
}

Regards.
Screenshot_4.png

Problem is not in syntax in mark place but before.. just “New Terminal” is not good to works with multi-line scripts.
You have a lot :do loop inside other loop. This is not a way.
Remember about one rule in scripting/programming:

a working is this:

{

# Set global $rsrp
#/interface lte info lte1 once do={:global RsrpLte1 $"RsrpLte1"}; # receive "-87dBm"
global RsrpLte1 "-79dBm";
set $RsrpLte1 [/pick $RsrpLte1 0 [/find $RsrpLte1 dBm]];
put $RsrpLte1; # Now it is "-87" without dBm word

#Testing line
/if ($RsrpLte1 > "-80") do={put "$RsrpLte1 is bigger then -80"} else={put "other: $RsrpLte1"};

:if ($RsrpLte1 >= -80) do={
  #/system leds set 1 leds=led1,led2,led3,led4,led5 type=on
  put "5led *****";
  } else={
  :if (($RsrpLte1 <= -81) && ($RsrpLte1 >= -90)) do={
    #/system leds set 1 leds=led1,led2,led3,led4 type=on
    put "4led ****";
    } else={
    :if (($RsrpLte1 <= -91) && ($RsrpLte1 >= -100)) do={
      #/system leds set 1 leds=led1,led2,led3 type=on
      put "3led ***";
      } else={
      :if (($RsrpLte1 <= -101) && ($RsrpLte1 >= -110)) do={
        #/system leds set 1 leds=led1,led2 type=on
        put "2led **";
        } else={
        :if (($RsrpLte1 <= -111) && ($RsrpLte1 >= -120)) do={
          #/system leds set 1 leds=led1 type=on
          put "1led *"
          } else={
          #/system leds set 1 leds=led1,led2,led3,led4,led5 type=off;
          put "off";
        }
      }
    }
  }
}

}

Change many stuff. Now work one time. The Scheduler should run this script every 1 minute. Maybe create a global RsrpLte1History1 … RsrpLte1History5 and if RsrpLte1AVG we use then this will be more stable and in final way we can use it to other stuff like change a SIM port to other one.

The best setup to testing debug and create a ROS script is:

And maybe better will be add at start condition to start blinking LED only when uptime is bigger then 3 minutes. This not do conflict when you powerup RB and he will be strange blinking :slight_smile:

Your script not run on my routerboard.

Anyway now is working perfectly except because my log is full while it’s running the script.

No way to “say” that not log when I change the led values?

Regards.

Your script not run on my routerboard.

Why? Any error, screenshot?
All uniq for hardware stuff are #commented and should works on any RouterOS
Means you should change this:
From this:

#/interface lte info lte1 once do={:global RsrpLte1 $"RsrpLte1"}; # receive "-87dBm"
global RsrpLte1 "-79dBm";

to this

/interface lte info lte1 once do={:global RsrpLte1 $"RsrpLte1"}; # receive "-87dBm"
#global RsrpLte1 "-79dBm";

Please add this into WinBox > System > Script and run it from CLI (WinBox > New Terminal > /system script run NameOfScript ; )
.

Anyway now is working perfectly except because my log is full while it’s running the script.
No way to “say” that not log when I change the led values?

If possible then only from WinBox > System > Logging but I not see the LED topic. Search on forum or write e-mail to support.
.

@Jotne in post have some interesting stuff about new option in controling LED. Action is not on/off but BLINKING the LEDs then ge GENERATE many those logs I think. Maybe (s)he can give you answer.

Sorry, I confussed. The script runs, but no has any effect (Or at least I can’t see it).

I attach a screen capture.

I researched about logging, but I think that is not possible because these kind of action can favor malicious activity on routerboards.

Regards.
Screenshot_5.png

I just haven’t this hardware and cannot check the Array of RSRP.

Script is working fine. Just uncomment the #/led… I comment all it because it’s breake at my hardware. Insted I create display “3 Led ***”.
And please paste and edit script inside WinBox > System > Script, not terminal.
.

.
You not write my post - just check my previouse screenshot, if you don’t know where to look then follow the helpers:
Screenshot_3.jpg
Your Part of your screenshot - at the bottom of running script you have results. I just PUT display text “5 Led *****”.
Bez-tytułu.png
Code who not work in my scenario but should work in your.
Check this out:

{

# Set global $rsrp
/interface lte info lte1 once do={:global RsrpLte1 $"RsrpLte1"}; # receive "-87dBm"
#global RsrpLte1 "-79dBm";
set $RsrpLte1 [/pick $RsrpLte1 0 [/find $RsrpLte1 dBm]];
put $RsrpLte1; # Now it is "-87" without dBm word

#Testing line
#/if ($RsrpLte1 > "-80") do={put "$RsrpLte1 is bigger then -80"} else={put "other: $RsrpLte1"};

:if ($RsrpLte1 >= -80) do={
  /system leds set 1 leds=led1,led2,led3,led4,led5 type=on
  put "5 Led *****";
  } else={
  :if (($RsrpLte1 <= -81) && ($RsrpLte1 >= -90)) do={
    /system leds set 1 leds=led1,led2,led3,led4 type=on
    put "4 Led ****";
    } else={
    :if (($RsrpLte1 <= -91) && ($RsrpLte1 >= -100)) do={
      /system leds set 1 leds=led1,led2,led3 type=on
      put "3 Led ***";
      } else={
      :if (($RsrpLte1 <= -101) && ($RsrpLte1 >= -110)) do={
        /system leds set 1 leds=led1,led2 type=on
        put "2 Led **";
        } else={
        :if (($RsrpLte1 <= -111) && ($RsrpLte1 >= -120)) do={
          /system leds set 1 leds=led1 type=on
          put "1 Led *"
          } else={
          /system leds set 1 leds=led1,led2,led3,led4,led5 type=off;
          put "- Led";
        }
      }
    }
  }
}

}

Your “/system leds…” command not work. From where you receive it? You tested it?
Screenshot_6.jpg

If I disable the previous assignments made by me, I can use scripts in my LtAP. In my case, I no have problems with it.

Later I will test again the code removing the comments character in the code using script section.

Thanks a lot and regards.

I see at Brochure of your RB LtAP LTE kit and in default state whose LED to do?
Screenshot_9.jpg
You can show some screenshot from WinBox > System > LEDs or some /system leds print detail ?

The default state is all LEDs off except the power led. By default, LED section in Winbox is empty.

Regards.

Ok. Finally I runned your script and the results are in the screenshot_6

If I modify the script changing the comment symbol and run, the results are in the screenshoot_7

Regards.
Screenshot_7.png
Screenshot_6.png

I modified my code and now only modify the LED properties when only if necessary:

{
:global ledsafter 10
:global ledsbefore 20
:global runloop true
:do {
/interface lte info lte1 once do={
:global rsrp1 $"rsrp"
:delay 100ms
:if ($rsrp1 >= -80) do={
:global ledsbefore 5
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1,led2,led3,led4,led5 type=on
:global ledsafter 5
}
} else={
:delay 100ms
:if (($rsrp1 >= -90) && ($rsrp1 <= -81)) do={
:global ledsbefore 4
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1,led2,led3,led4 type=on
:global ledsafter 4
}
} else={
:delay 100ms
:if (($rsrp1 >= -100) && ($rsrp1 <= -91)) do={
:global ledsbefore 3
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1,led2,led3 type=on
:global ledsafter 3
}
} else={
:delay 100ms
:if (($rsrp1 >= -110) && ($rsrp1 <= -101)) do={
:global ledsbefore 2
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1,led2 type=on
:global ledsafter 2
}
} else={
:delay 100ms
:if (($rsrp1 >= -120) && ($rsrp1 <= -111)) do={
:global ledsbefore 1
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1 type=on
:global ledsafter 1
}
} else={
:global ledsbefore 0
:if ($ledsafter = $ledsbefore) do={
:put "nothing to do"
} else={
/system leds set 1 leds=led1,led2,led3,led4,led5 type=off
:global ledsafter 0
}
}
}
}
}
}
}
} while=($runloop)
}

The theme is when it modifies the LED propieties, I use “ledbefore” to set the quantity of leds that are on and then with “ledafter” it check if the quantity of leds has changed. With this only logs can flood it when the signal changes many times just between 2 different signal levels.

As you can see on screenshot_8, my script i’m running on terminal, the CPU consuption is not too much, the quantity of leds on are correct, the logs are not flooding it and the signal level on the variable, match with the shown on status interface.

With this I can say that works well, but anyway I receive suggesions about it.

Regards.
Screenshot_8.png

@krafg

I tried to read your script, but it was very hard to understand do to formatting.
Please use tab for each loop when you make script. I have modified for you.
Try to copy past it to notapad++ and you see what I mean.

{
:global ledsafter 10
:global ledsbefore 20
:global runloop true
:do {
	/interface lte info lte1 once do={
		:global rsrp1 $"rsrp"
		:delay 100ms
		:if ($rsrp1 >= -80) do={
			:global ledsbefore 5
			:if ($ledsafter = $ledsbefore) do={
				:put "nothing to do"
			} else={
				/system leds set 1 leds=led1,led2,led3,led4,led5 type=on
				:global ledsafter 5
			}
		} else={
			:delay 100ms
			:if (($rsrp1 >= -90) && ($rsrp1 <= -81)) do={
				:global ledsbefore 4
				:if ($ledsafter = $ledsbefore) do={
					:put "nothing to do"
				} else={
					/system leds set 1 leds=led1,led2,led3,led4 type=on
					:global ledsafter 4
				}
			} else={
				:delay 100ms
				:if (($rsrp1 >= -100) && ($rsrp1 <= -91)) do={
					:global ledsbefore 3
					:if ($ledsafter = $ledsbefore) do={
						:put "nothing to do"
					} else={
						/system leds set 1 leds=led1,led2,led3 type=on
						:global ledsafter 3
					}
				} else={
					:delay 100ms
					:if (($rsrp1 >= -110) && ($rsrp1 <= -101)) do={
						:global ledsbefore 2
						:if ($ledsafter = $ledsbefore) do={
							:put "nothing to do"
						} else={
							/system leds set 1 leds=led1,led2 type=on
							:global ledsafter 2
						}
					} else={
						:delay 100ms
						:if (($rsrp1 >= -120) && ($rsrp1 <= -111)) do={
							:global ledsbefore 1
							:if ($ledsafter = $ledsbefore) do={
								:put "nothing to do"
							} else={
								/system leds set 1 leds=led1 type=on
								:global ledsafter 1
							}
						} else={
							:global ledsbefore 0
							:if ($ledsafter = $ledsbefore) do={
								:put "nothing to do"
							} else={
								/system leds set 1 leds=led1,led2,led3,led4,led5 type=off
								:global ledsafter 0
							}
						}
					}
				}
			}
		}
	}
} while=($runloop)
}

It also looks like many of the loop are equal, just different values. You should try to make a function of it.

:delay 100ms
:if (($rsrp1 >= -120) && ($rsrp1 <= -111)) do={
	:global ledsbefore 1
	:if ($ledsafter = $ledsbefore) do={
		:put "nothing to do"
	} else={
		/system leds set 1 leds=led1 type=on
		:global ledsafter 1
	}
}

PS First { and last } can be removed. They are only needed when cut/past to terminal. In script it works fine without.

At start, VERY THANKS for cooperate and screenshot’s.
.

Just create other, separated LogAction for System+Info topics, you can still see them in separate list of logs. To not duplicate it in default info just add !system.
Example: Tested on editing script who do the system+info change.
SystemLogging.jpg
.

the logs are not flooding it

Done. No more duplicate of the same activation LED settings, only if LED count be change then it change. Look below.
.

As you can see on screenshot_8, my script i’m running on terminal, the CPU consuption is not too much

Mutch better if you run this script in /system scheduler with interval 1s or you must see 120Hz refreshing speed :).
Script can be place inside scheduler or run external /system script with our source code.
.

With this I can say that works well, but anyway I receive suggestions about it.

First Optimization… You change simple 34 lines code into 74 lines do-if-else-loop monster :).

Now this $rsrp1 live only inside do-loop and after exiting script save it as environment. Patch:

-interface lte info lte1 once do={:global rsrp1 $"rsrp"; ...
+local Rsrp ([/interface lte info lte1 once as-value]->"rsrp")

Now we can use $Rsrp in whole area of script and we not must remove “dBm” suffix text.

Use Functions, education examples in viewtopic.php?f=9&t=151539#p746898 , simplest example:

local ChangeLeds do={put "Display $1 leds"}; # $1 - first argument
$ChangeLeds 4; # Run function and say to change leds to on 4

.
Instead creating new and new the same global’s just change it value, patch:

-global a "new value 1"
-global a "new value 2"
...
+set $a "new value 3"       
+set $a "new value 4"
# This check is global exist, true only when global exist with any of value:
put ([system script environment find name=a]!="")
# Instead:
-:global runloop true; do {...} while={$runloop}
+do while=(1=1) {delay 1s;...} # Really, Scheduler with 1s interval.

.


.
Final Release … works without duplication, base on feedback from $LedsCurrent = LastState, it’s only must be global variable . Paste in CLI and check.

global LedsCurrent 0
local LteRsrp -121

local ControlLed do={
  if ($1 != $4) do={ system leds set 1 leds=$2 type=$3 }
  return $1
}

do while=(1=1) {
  delay 1s
  set $LteRsrp ([/interface lte info lte1 once as-value]->"rsrp");
  if ($LteRsrp >= -80) do={set $LedsCurrent [$ControlLed 5 led1,led2,led3,led4,led5 on $LedsCurrent ] };
  if (($LteRsrp >= -90) && ($LteRsrp <= -81)) do={set $LedsCurrent [$ControlLed 4 led1,led2,led3,led4 on $LedsCurrent ] };
  if (($LteRsrp >= -100) && ($LteRsrp <= -91)) do={set $LedsCurrent [$ControlLed 3 led1,led2,led3 on $LedsCurrent ] };
  if (($LteRsrp >= -110) && ($LteRsrp <= -101)) do={set $LedsCurrent [$ControlLed 2 led1,led2 on $LedsCurrent ] };
  if (($LteRsrp >= -120) && ($LteRsrp <= -111)) do={set $LedsCurrent [$ControlLed 1 led1 on $LedsCurrent ] };
  if ($LteRsrp <= -121) do={set $LedsCurrent [$ControlLed 0 led1,led2,led3,led4,led5 off $LedsCurrent ] };
}

.
Additional BTW Questions:
Please put result of:

put [/interface lte get lte1 band]

or maybe this info is at WinBox > Interfaces > LTE > lte1 > General or Status tab (you show the Cellular tab before).
Cell-Monitor exist to search band/cell@BTS but maybe you know how to check current used band.

If you think this is solution for a post then mark this answer.
P.S. I am at Telegram if you not understand the final script.