Speedtest-cli Internet Up-/Downlink Measurement Integration

Sure no problem:

// ******* Connection Speedtest ******* //
rule "Speedtest"
when
	Time cron "38 */30 * * * ?" or // every 30 minutes
    Item Speed_Run received command ON
then
	if(Speed_Run.state == OFF) {
		Speed_Run.postUpdate(ON)
	}
    // update timestamp for last execution
    Speed_Date.postUpdate(new DateTimeType())
	var String output = executeCommandLine("/usr/local/bin/SpeedTest --output json", 90000)
	val String ping = transform("JSONPATH", "$.ping",output)
 	val String down = transform("JSONPATH", "$.download",output)
 	val String up   = transform("JSONPATH", "$.upload",output)
	val float downNum = Float::parseFloat(down) / 1000000
	val float upNum = Float::parseFloat(up) / 1000000
	logInfo("+++ NETWORK", "ping: " + ping + " ms / download: " + downNum + "Mbit/sec / upload: " + upNum + "Mbit/sec")
	Speed_Ping.postUpdate(Float::parseFloat(ping))
	Speed_Down.postUpdate(downNum)
	Speed_Up.postUpdate(upNum)
	logInfo("+++ NETWORK", "--> speedtest finished.")
    Speed_Run.postUpdate(OFF)
end
// ******* Connection Speedtest END ******* //

Thanks!

no worries - that was easy :wink:

Will there be a version for OH3?
It seems that the rules are not running properly. Maybe there are some other issues too.

Just a shot in the dark and untestested (yet), but the executeCommandline option had some breaking change in openHAB 3.

Breaking changes in short:

  • Parameter order has changed
  • Timeout is now in secconds
  • Parameters don’t have to be separated with @@ anymore

So please test the following idea:

Take the example script part:

 // execute the script, you may have to change the path depending on your system
var String speedtestCliOutput = executeCommandLine("/usr/local/bin/speedtest-cli@@--simple", 120*1000)

and change the function paramaters as following:

 // execute the script, you may have to change the path depending on your system
var String speedtestCliOutput = executeCommandLine(120, "/usr/local/bin/speedtest-cli --simple")

Of course you should transfer any additions or changes you possibly made to this line yourself too. :slight_smile:

Edit:

Please give some feedback if you have tested it and it works.
I will adapt the first post of this tutorial then.

1 Like

Thank you for that quick reply. I’ve tested your changes, but without success.
I’ve attached you a screenshot with the errors on the bottom.
It seems that there is a problem with the timeout parameter and the section where the string gets splitted into the different output string.

And that’s what the openhab.log says

2020-12-22 10:45:47.489 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model ‘speedtest.rules’, using it anyway:
The constructor Float(String) is deprecated
The constructor Float(String) is deprecated
The constructor Float(String) is deprecated

Did you test the script while ignoring these error messages?
I would not wonder if the language server doesn’t know about this change too…

speedtest-cli --simple is working properly while running it from the cli.
But running the rule via the OH3 gui or the manual start button in basicui isn’t working.
Exec Binding is installed and the command is whitelisted.

It always hangs up at “Messung läuft”. Don’t know exactly where it crashes but i think the command is not executed.

And you have installed that in the location like it is shown in the example?

In my personal rule i am runngin the speedtest command without the /usr/local/bin/ so the path may be different than it is in the example.
(But i am using the ookla varian tsince some time so that may be the deifference.)

Yes, like in the example.

 // execute the script, you may have to change the path depending on your system
var String speedtestCliOutput = executeCommandLine(120, "/usr/local/bin/speedtest-cli --simple")

The syntax is not correct, it should be:

 // execute the script, you may have to change the path depending on your system
var String speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120), "/usr/local/bin/speedtest-cli", "--simple")
1 Like

That syntax works! Thanks so far.

But I noticed one more problem regarding the if statement inside the rule.
Normally the output auf the speedtest-cli looks like this

Ping: 18.958 ms
Download: 72.93 Mbit/s
Upload: 30.11 Mbit/s

The following if statement should work. And it worked on OH2.5.X.
But with OH3 it rans every time into the else statement which is not correct.

    if (speedtestCliOutput.startsWith("Ping") && speedtestCliOutput.endsWith("Mbit/s")) {
        var String[] results = speedtestCliOutput.split("\\r?\\n")
        var float ping = new java.lang.Float(results.get(0).split(" ").get(1))
        var float down = new java.lang.Float(results.get(1).split(" ").get(1))
        var float up   = new java.lang.Float(results.get(2).split(" ").get(1))
        SpeedtestResultPing.postUpdate(ping)
        SpeedtestResultDown.postUpdate(down)
        SpeedtestResultUp.postUpdate(up)
        SpeedtestSummary.postUpdate(String::format("↓  %.1f Mbit/s  ↑ %.1f Mbit/s (%.0f ms)", down, up, ping))
        SpeedtestRunning.postUpdate("-")
        logInfo(filename, "--> speedtest finished.")
    } else {
        SpeedtestResultPing.postUpdate(0)
        SpeedtestResultDown.postUpdate(0)
        SpeedtestResultUp.postUpdate(0)
        SpeedtestSummary.postUpdate("(unbekannt)")
        SpeedtestRunning.postUpdate("Fehler bei der Ausführung")
        logError(filename, "--> speedtest failed. Output:\n" + speedtestCliOutput + "\n\n")
    }

Any thought about that or maybe better way for the if statement?

1 Like

Thanks @NorbertHD!

As said this was a shot in the Dark.
@philf90 and me did already reach out to the Duration mistake and i have already corrected this in the openHAB Documentation.

But we should also add a understandable example for the multiple arguments too.
I will prepare something for this.

1 Like

didn’t help for me on OH3

my rule

then
    logInfo(filename, "--> speedtest executed...")
    SpeedtestRunning.postUpdate("Messung läuft...")

    // update timestamp for last execution
    SpeedtestResultDate.postUpdate(new DateTimeType())

    // execute the script, you may have to change the path depending on your system
    // var String speedtestCliOutput = executeCommandLine("/usr/bin/speedtest-cli@@--simple", 120*1000)   // OPENHAB 2.5
    var String speedtestCliOutput = executeCommandLine(Duration.ofSeconds(120), "/usr/bin/speedtest-cli", "--simple")    // NEU MIT OPENHAB 3

    // for debugging:
    //var String speedtestCliOutput = "Ping: 43.32 ms\nDownload: 21.64 Mbit/s\nUpload: 4.27 Mbit/s"
    //logInfo(filename, "--> 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("Ping") && speedtestCliOutput.endsWith("Mbit/s")) {
        var String[] results = speedtestCliOutput.split("\\r?\\n")
        var float ping = new java.lang.Float(results.get(0).split(" ").get(1))
        var float down = new java.lang.Float(results.get(1).split(" ").get(1))
        var float up   = new java.lang.Float(results.get(2).split(" ").get(1))
        SpeedtestResultPing.postUpdate(ping)
        SpeedtestResultDown.postUpdate(down)
        SpeedtestResultUp.postUpdate(up)
        SpeedtestSummary.postUpdate(String::format("↓  %.1f Mbit/s  ↑ %.1f Mbit/s (%.0f ms)", down, up, ping))
        SpeedtestRunning.postUpdate("-")
        logInfo(filename, "--> speedtest finished.")
    } else {
        SpeedtestResultPing.postUpdate(0)
        SpeedtestResultDown.postUpdate(0)
        SpeedtestResultUp.postUpdate(0)
        SpeedtestSummary.postUpdate("(unbekannt)")
        SpeedtestRunning.postUpdate("Fehler bei der Ausführung")
        logError(filename, "--> speedtest failed. Output:\n" + speedtestCliOutput + "\n\n")
    }
    SpeedtestRerun.postUpdate(OFF)
end
2020-12-22 21:27:33.005 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SpeedtestSummary' changed from Test ausführen! to (unbekannt) 
2020-12-22 21:27:33.008 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'SpeedtestRunning' changed from Datenauswertung... to Fehler bei der Ausführung

There should be an error log according to your rule.

logError(filename, “–> speedtest failed. Output:\n” + speedtestCliOutput + “\n\n”)

Can you look that up and post it here too?

sure, sorry

21:51:11.926 [ERROR] [hab.core.model.script.speedtest.rules] - --> speedtest failed. Output:
Ping: 26.231 ms
Download: 8.52 Mbit/s
Upload: 1.93 Mbit/s

In fact it didnt fail, but the rule didnt get the proper information from that output as it seems.

The “if” statement seems to be the problem, but not the syntax of it. If you get rid of that it works properly. Thats what I have tested.

Hi,
I had a similar issue and it turns out the endsWith check was finding an extra carriage return after the Mbits/s check so causing the else statement to be actioned instead.
I had to amend the syntax to include the extra CR, at the moment my OH3 instance isn’t running so can get at the DSL rule to confirm.

1 Like

I had a problem with the ‘if’ statement too, I simply tested the first condition and deleted the second, it seems the ‘&&’ (and) between them seems to be the culprit in OH3 vs OH2.

EDIT: btw I’m using the full json output of ‘speedtest’, not using ‘speedtest-cli’.

1 Like