You’ve made your code overloaded with lots of unneeded stuff.
For what reason are you using :foreach cycle, if you have only one UPS on every device?
You are (again) reading UPS data twice.
If you left ups name (or leaving anything else in the code) just to “know” about it, but it’s not actually used, then comment it, so it won’t be executed.
:local upsPrefix "[UPS]:"
#:local iupsname [get $item name]
:local threshold 115
:local upsData [/system ups monitor ([find]->0) once as-value]; # Read UPS data ONCE
:local rawvolt ($upsData->"line-voltage")
:local voltage ($rawvolt / 100)
:if ($voltage < $threshold) do={
:log info "$upsPrefix UPS input voltage is $voltage"
}
:local online ($upsData->"on-line")
:if (! $online) do={
:log info "$upsPrefix UPS is offline"
}
Only attribute names are problematic, paths/dir are not variables nor passed anywhere.
Perhaps not best choice using { } after a path in the example. But it's perfect valid and does create a new scope for :local - something OP asked about.
But the problem here is we go from "I have one UPS" to "I need a :foreach" somehow. There is no need for [find] if it's one static UPS. The .id will always be same and safe.
For
.1 : correct, but better habit to not use at all name already defined…
.2 : correct, but better habit to not create useless nested scopes…
@teslasystems
.1: The foreach | [find]->0 is present because seem that on some device the ups name change, and is for not hardcode name or .id,
AND, if is not present at all one UPS, foreach do not do nothing…
.2: correct…
.3: correct…
In case, if there will be no any UPS (for example, some cable issue or whatever), I think it’s better to use :onerror handler, so the script will know about issue and can report about it.
:foreach will behave silently and won’t report about issue.
Only as a side-side note, IMHO “static” variable assignments, (threshold, logprefix) should normally be outside any loop, they are assigned once at script start and not-reassigned at each loop iteration, of course since here there will be only one iteration it doesn’t change anything.
@Teslasystem
You are using way too many if/else’s for my personal tastes, of course in this specific case it won’t matter, but in more complex scripts they are likely to bite you back.
@all
What happens if the UPS is NOT found to variable “voltage”?
It is declared as 0 at the beginning of the script, but what value (if any) does it get if NO UPS is connected?
In (say) batch, I would NOT define the variable at all at the beginning, and then use
IF DEFINED
if it is defined, then look at its value, otherwise it means that no UPS was found and there is no real need of checking “on-line” as it clearly it isn’t.
(just thinking aloud)