Read external data for speedtest values

Hi there,

i would like to set up an external datasource for speedtest values.
As the Raspi 3 only has an 100 Mbit/s Ethernet port and my provider delivers 400 Mbit/s download and 40 Mbit/s upload i´m not able to measure the correct bandwith.
I was thinking about another solution like my Pine64 or my Windows Server 2016 to measure the bandwith and write the result into a datasource that is readable for openHAB.

I was thinking about a locale .sh script that is executed and will return the latest entry from the external datasource.
Something like this

Does anyone has an idea how to do this?
Any hints are helpful.

Edit: I already came across this speedtest-cli solution.

external = not on the raspberry pi as the Ethernet port is limited to 100 Mbit/s and my internet bandwith is 400 Mbti/s

  • Platform information:
    • Hardware: Raspberry Pi 3B
    • OS: raspbian 9
    • Java Runtime Environment:
      • openjdk version “1.8.0_152”
        OpenJDK Runtime Environment (Zulu Embedded 8.25.0.76-linux-aarch32hf)
        OpenJDK Client VM (Zulu Embedded 8.25.0.76-linux-aarch32hf)
    • openHAB version: 2.3.0-1 (Release Build)

Not sure if it is possible, but can’t the Pine or Windows PC send the results of the test via MQTT to openHAB? Then you show it in your sitemap and you can do the persistence.

You may find some more ideas here:

1 Like

I already came across this but it‘s not external.
It‘s running on the Pi and the bandwith is limited to 100Mbit/s.

With external i don‘t mean openHAB external but Raspi external.

That‘s what i‘m asking for :slight_smile:
I haven‘t worked with MQTT before.

1 Like

Read a bit on MQTT and how to send the results from your Pine / PC to openHAB. OpenHAB for sure can process the info.

You could also use the REST api to send value to OH

IF you use the speed test on a Pine or something like that, the data transfer to openHAB is done by the REST api and therefore it is a http Call, so thatthere is no need to be on the same machine

Now i need to plan how to do this.
I´m able to write oH rules and understand some basics of other codes but building something from scratch is way over my capability.

I´m currently having the following ideas how to solve this.
All ideas are based on using the Debian Jessie Mate image for the Pine64 and changing the oH items through the REST API.

  1. Changing the original speedtest-cli to directly send the result to oH via REST
    • I need to understand the original python code and make the changes i need
  2. Building something like this and build a new python script that´s just running the speedtest-cli to parse the results.
    • Also need to understand python and build something that works
  3. Setting up another instance of openHAB to fully understand what i´m doing and have an two way communication

From my perspective option 3 seems to be a nice idea.
With two oH instances i´m able to let them communicate through REST and have the option to directly trigger an speedtest on my main instance.

What would lead to option 4, migrating the main instance to the Pine64…

Update :slight_smile:

I changed my HP MicroServer Gen8 from running Windows Server 2016 directly to an ESXi host with NextCloud, Win Server 2016 and another openHAB instance.
This second oH instance has an Gigabit network port and can run the speedtest-cli at full speed.
The next step was to get the Speedtest running and send the results to my main oH instance.

openHAB-Speedtest

val String filename = "speedtest.rules"

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 5,13 * * ?" or
    Time cron "0 0 * * * ?" or
    Item SpeedtestRerun changed from OFF to ON or
    Item SpeedtestRerun received command ON

then

    logInfo(filename, "--> speedtest executed...")
    SpeedtestRunning.postUpdate("Messung läuft...")
    sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestRunning/state", "text/plain", "Messung läuft...")

    // update timestamp for last execution
    val String ResultDate = "" + new DateTimeType()
    SpeedtestResultDate.postUpdate(ResultDate)
    sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestResultDate/state", "text/plain", ResultDate.toString)

    // 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)

    // 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...")
    sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestRunning/state", "text/plain", "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)
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestResultPing/state", "text/plain", ping.toString)
        SpeedtestResultDown.postUpdate(down)
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestResultDown/state", "text/plain", down.toString)
        SpeedtestResultUp.postUpdate(up)
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestResultUp/state", "text/plain", up.toString)
        SpeedtestSummary.postUpdate(String::format("ᐁ  %.1f Mbit/s  ᐃ %.1f Mbit/s (%.0f ms)", down, up, ping))
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestSummary/state", "text/plain", String::format("ᐁ  %.1f Mbit/s  ᐃ %.1f Mbit/s (%.0f ms)", down, up, ping))
        SpeedtestRunning.postUpdate("-")
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestRunning/state", "text/plain", "-")
        logInfo(filename, "--> speedtest finished.")
    }
    else
    {
        SpeedtestResultPing.postUpdate(0)
        SpeedtestResultDown.postUpdate(0)
        SpeedtestResultUp.postUpdate(0)
        SpeedtestSummary.postUpdate("(unbekannt)")
        sendHttpPutRequest("http://192.168.2.11:8080/rest/items/SpeedtestSummary/state", "text/plain", "Error")
        SpeedtestRunning.postUpdate("Fehler bei der Ausführung")
        logError(filename, "--> speedtest failed. Output:\n" + speedtestCliOutput + "\n\n")
    }

    SpeedtestRerun.postUpdate(OFF)
end

openHAB2 main

val String filename = "speedtest.rules"

rule "Speedtest"

when

    Item SpeedtestRerun received command ON

then

    SpeedtestRunning.postUpdate("Messung gestartet...")
    sendHttpPutRequest("http://192.168.2.111:8080/rest/items/SpeedtestRerun/state", "text/plain", "ON")

    SpeedtestRerun.postUpdate(OFF)
end

rule "Speedtest Fehler"

when

    Item SpeedtestSummary changed to "Error"

then

    logError(filename, "--> Speedtest fehlgeschlagen\nFehler auf openHAB-Speedtest (http://192.168.2.111:9001/) einsehbar")
    sendTelegram("bot1", "--> Speedtest fehlgeschlagen\nFehler auf openHAB-Speedtest (http://192.168.2.111:9001/) einsehbar")

end

Things to do:

  • Install InfluxDB and Grafana

kind regards
Michael