I´m Migrating my Existing Openhab2 Setup Step-byStep to Openhab3. I used the Speedtest Tutorial from here:
and it works fine in Openhab 2.5. I Knew the Exec Binding changed in OH3 but i dont have any idea what i have to change to get it Work with the new Syntax.
val String ruleId = "Speedtest"
val Number calc = 125000 // Converting from bits to Mbits
rule "Speedtest init"
when
System started
then
createTimer(now.plusSeconds(195))
[|
if(SpeedtestRerun.state == NULL)
{
SpeedtestRerun.postUpdate(OFF)
}
if(SpeedtestRunning.state == NULL)
{
SpeedtestRunning.postUpdate("-")
}
if(SpeedtestSummary.state == NULL || SpeedtestSummary.state == "")
{
SpeedtestSummary.postUpdate("⁉ (unbekannt)")
}
]
end
rule "Speedtest"
when
Time cron "0 0/15 * * * ?" or
Item SpeedtestRerun changed from OFF to ON or
Item SpeedtestRerun received command ON
then
//logInfo(ruleId, "--> speedtest executed...")
SpeedtestRunning.postUpdate("Messung läuft...")
// execute the script, you may have to change the path depending on your system
// Please use -f json and not -f json-pretty
val speedtestExecute = "speedtest -f json"
var speedtestCliOutput = executeCommandLine(speedtestExecute, 120*1000,)
// for debugging:
// var String speedtestCliOutput = "Ping: 43.32 ms\nDownload: 21.64 Mbit/s\nUpload: 4.27 Mbit/s"
//logInfo(ruleId, "--> speedtest output:\n" + speedtestCliOutput + "\n\n")
SpeedtestRunning.postUpdate("Datenauswertung...")
// starts off with a fairly simple error check, should be enough to catch all problems I can think of
if (speedtestCliOutput.startsWith("{\"type\":\"result\",") && speedtestCliOutput.endsWith("}}"))
{
var ping = Float::parseFloat(transform("JSONPATH", "$.ping.latency", speedtestCliOutput))
SpeedtestResultPing.postUpdate(ping)
var float down = Float::parseFloat(transform("JSONPATH", "$.download.bandwidth", speedtestCliOutput))
down = (down / calc)
SpeedtestResultDown.postUpdate(down)
var float up = Float::parseFloat(transform("JSONPATH", "$.upload.bandwidth", speedtestCliOutput))
up = (up / calc)
SpeedtestResultUp.postUpdate(up)
var String url = transform("JSONPATH", "$.result.url", speedtestCliOutput)
val img = url + ".png"
SpeedtestResultImage.postUpdate(img)
SpeedtestSummary.postUpdate(String::format("ᐁ %.1f Mbit/s ᐃ %.1f Mbit/s (%.0f ms)", down, up, ping))
SpeedtestRunning.postUpdate("-")
// update timestamp for last execution
val DateTimeType ResultDate = DateTimeType.valueOf(transform("JSONPATH", "$.timestamp", speedtestCliOutput))
SpeedtestResultDate.postUpdate(ResultDate)
}
else
{
SpeedtestResultPing.postUpdate(0)
SpeedtestResultDown.postUpdate(0)
SpeedtestResultUp.postUpdate(0)
SpeedtestSummary.postUpdate("(unbekannt)")
SpeedtestRunning.postUpdate("Fehler")
logError(ruleId, "--> speedtest failed. Output:\n" + speedtestCliOutput + "\n\n")
}
SpeedtestRerun.postUpdate(OFF)
end
Logs
2020-12-18 15:00:00.462 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'speedtest-2' failed: An error occurred during the script execution: array element type mismatch in speedtest
Why not use the Network binding with integrated speedtest?
This binding allows checking whether a device is currently available on the network. This is either done using ping or by a successful TCP connection on a specified port.
It is also capable to perform bandwidth speed tests.
I suffer from the very same issue. The original question more leads to the changes in executeCommandLine, which we try to understand and adopt the rule. Btw the rule based approach as alternative to network binding allows extraction of more data, when using json output speedtest-cli@@--json, e.g. location parameters of client and server. Not really required, but available - and only after successful executeCommandLine.
Only swapping command and timeout +change to duration does not help: var String speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120),"/usr/bin/speedtest-cli@@--json")
, as described here:
@Tiggr1994 your lines
val speedtestExecute = “speedtest -f json”
var speedtestCliOutput = executeCommandLine(speedtestExecute, 120*1000,)
should be:
var speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120), “speedtest”, “-f”, “json”)
@cwi your line
var String speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120),"/usr/bin/speedtest-cli@@–json")
should be:
var String speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120), “/usr/bin/speedtest-cli”, “–json”)
I changed my rules file as Norbert suggested, however it fails the output test now and reports error, while I get the result correctly in the log files.(if (speedtestCliOutput.startsWith("{“type”:“result”,") && speedtestCliOutput.endsWith("}}")))
Good evening,
I have the problem that when I execute var speedtestCliOutput = executeCommandLine (Duration.ofSeconds (120)," speedtest "," -f "," json ")
from Rule there seems to be no waiting for the response after 120 seconds. Putting a logInfo on the “speedtestCliOutput” variable I immediately get “null”. If I look at the processes in htop, speedtest is performed in a few milliseconds: I see it appear and then disappear. It is as if it was not executed or stopped immediately. What do you suggest me to do?
Thanks
Matteo
There are troubling spaces in your arguments please remove them and try again: var speedtestCliOutput = executeCommandLine (Duration.ofSeconds (120), "speedtest", "-f", "json")
I fixed the syntax as indicated, trying to put and remove “spaces” before the brackets, but nothing. The process starts but ends almost immediately without waiting 120 seconds. If I launch it manually everything works correctly. Could it be a permissions issue?
same problem here, running speedtest -f json manualy works, but when started in openhab i get error in openhab.log: "[ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'speedtest-2' failed: cannot invoke method public boolean java.lang.String.startsWith(java.lang.String) on null in speedtest"
I always executed the command from shell as user openhabian.
But sudo -u openhab speedtest asked me again for accept the licence.
Now I will get an other error. But this is fixable: 2021-01-13 22:12:53.781 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'speedtest-2' failed: The name 'calc' cannot be resolved to an item or type; line 61, column 24, length 4 in speedtest
I will have a Look tomorrow. Thanks so far!
UPDATE: speedtest works finde for me!
If just forgot to add the two variables at the top of the rules.
Thanks a lot!