Speedtest-cli Internet Up-/Downlink Measurement Integration

Just my two cents. For Version 2.0.2 of /usr/local/bin/speedtest-cli --version,
Changed
speedtestCliOutput.endsWith( “Mbits/s” )
to
speedtestCliOutput.endsWith( “Mbit/s” )

Thanks a lot man. Great script. Worked like a charm just copy & paste. Great work.

Hey guys, I’m a little confused. How do I have to set the cron time to execute this rule one a day at 4 AM?

Time cron "4 0 * * * ?" or

ist that correct?

Thank you :slight_smile:

1 Like

Today I integrated this with my jython rules. Here’s a quick summary:

  • Have JSR223 jython scripting runing: GitHub - openhab-scripters/openhab-helper-libraries: Scripts and modules for use with openHAB

  • Copy speedtest.py from speedtest-cli’s github page to /etc/openhab2/automation/lib/python/personal. I used curl:

    curl -O https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
    
  • Create needed items. I’m using only 3: Download, upload and ping:

    Group GrSpeedtest "Speedtest"
    Number      Speedtest_Ping     "Ping [%.2f ms]"              (GrSpeedtest)
    Number      Speedtest_Down     "Downlink [%.2f Mbit/s]"      (GrSpeedtest)
    Number      Speedtest_Up       "Uplink [%.2f Mbit/s]"        (GrSpeedtest)
    
  • Create a rule to run speedtest. Here’s mine:

    from core.rules import rule
    from core.triggers import when
    from personal import speedtest
    
    @rule("Speedtest")
    @when("Time cron 0 */15 * * * ?")
    def executeSpeedest(event):
    
       def convert(speed):
            """Convert bits/s to MBits/s"""
            speed /= 1024 * 1024
            return speed
    
        s = speedtest.Speedtest()
        s.get_best_server()
        s.download()
        s.upload(pre_allocate=False)
        results = s.results.dict()
    
        download = convert(results["download"])
        upload = convert(results["upload"])
        ping = results["ping"]
    
        events.postUpdate("Speedtest_Down", str(download))
        events.postUpdate("Speedtest_Up", str(upload))
        events.postUpdate("Speedtest_Ping", str(ping))
    
        #log.info("Download: {0:.2f} MB  Upload: {1:.2f} MB  Ping: {2:.2f} ms".format(download, upload, ping))
    

Of course the group GrSpeedtest is persisted with MySQL and visualized with Grafana.

Few notes:

  • Script runs every 15min only for testing purposes.
  • Log line included but commented out. Create a logger if you want to use this line.
  • Memory usage rised ~20% with my 4GB RAM system and in the beginning got few memory errors and garbage collection. Anyhow system seems stable.

Hi there,

A really good idea - unfortunately I’m facing the issue that the measurement is not correct.
A speedtest with www.speedtest.net (on a windows 10 machine connected with LAN) says:
Ping: 111 ms
Download: 50 Mbps
Upload: 9.25 Mbps
… which is correct as I’ve a 50 Mbit subscription

But … command line as well as the speedtest rule on raspberry (LAN) says:
[17:23:53] openhabian@openHABianPi:/usr/local/bin$ speedtest-cli --simple
Ping: 17.89 ms
Download: 13.93 Mbit/s
Upload: 9.05 Mbit/s

Could you please help me with this…

Some ISPs are known to recognize when you go to a speedtest website and make sure you get the best possible results. They don’t always recognize when you use the cli program.

But I don’t think that is happening in this case. You are running this test from an RPi, right? Wired or wireless? Wired should be able to meet 50 Mbps but wireless should get a little better than half that. 14 Mbps still seems low but if you have wireless and not the best signal in that spot 14 isn’t that bad.

Also keep in mind that these tests cause the RPi to download files and the same USB bus is used for writing to the SD card and downloading the file which will slow things down too.

Ultimately, this isn’t something you will find much help for on this forum. It’s a problem with your specific setup/network/ISP and outside of openHAB.

Yes, both devices are wired.

Hi all,

start manually works fine. But it seems that cron triggers some problems:

2019-05-20 13:00:00.023 [INFO ] [ome.model.script.notifications.rules] - --> speedtest executed...
2019-05-20 13:00:28.710 [ERROR] [ome.model.script.notifications.rules] - --> speedtest failed. Output:
Exception in thread Thread-21:
Traceback (most recent call last):
  File "/usr/lib/python2.7/threading.py", line 801, in __bootstrap_inner
    self.run()
  File "/usr/local/lib/python2.7/dist-packages/speedtest_cli-2.1.1-py2.7.egg/speedtest.py", line 772, in run
    f = self._opener(self.request)
  File "/usr/lib/python2.7/urllib2.py", line 429, in open
    response = self._open(req, data)
  File "/usr/lib/python2.7/urllib2.py", line 447, in _open
    '_open', req)
  File "/usr/lib/python2.7/urllib2.py", line 407, in _call_chain
    result = func(*args)
  File "/usr/local/lib/python2.7/dist-packages/speedtest_cli-2.1.1-py2.7.egg/speedtest.py", line 505, in http_open
    req
  File "/usr/lib/python2.7/urllib2.py", line 1201, in do_open
    r = h.getresponse(buffering=True)
  File "/usr/lib/python2.7/httplib.py", line 1121, in getresponse
    response.begin()
  File "/usr/lib/python2.7/httplib.py", line 438, in begin

any ideas how can i solve it?

KR Rene

Any ideas?
Thank you.
Rene

Can you post more of your configuration ? Your exec binding call etc. Other items you have configured?

Hey,
this is a python error, the error is probably not openHAB related.
Might be due to some version dependencies or similar. Please go through the python setup of the toturial again. Only continue with openHAB after the speedtest on linux console works: speedtest-cli/README.rst at master · sivel/speedtest-cli · GitHub

Good luck!

Hi Maurits28,

here the items:

Group gSpeedtest <"network-icon"> (Whg)
                                                                                                                                                                                                              
String      SpeedtestSummary        "Speedtest [%s]"             <"speedtest_network">       (gSpeedtest)
Number      SpeedtestResultPing     "Ping [%.3f ms]"             <"speedtest_next5">         (gSpeedtest)
Number      SpeedtestResultDown     "Downlink [%.2f Mbit/s]"     <"speedtest_download">      (gSpeedtest)
Number      SpeedtestResultUp       "Uplink [%.2f Mbit/s]"       <"speedtest_upload">        (gSpeedtest)
String      SpeedtestRunning        "Speedtest running ... [%s]" <"speedtest_new">           (gSpeedtest)
Switch      SpeedtestRerun          "Start manually"             <"speedtest_reload2">       (gSpeedtest)
DateTime    SpeedtestResultDate     "Last executed [%1$td.%1$tm.%1$tY, %1$tH:%1$tM Uhr]"   <"speedtest_problem4">      (gSpeedtest)

Sitemap:

 Frame label="Speedtest" {                                                                                                                                                                                 
        Text item=SpeedtestSummary {                                                                                                                                                                          
            Frame label="Ergebnisse" {                                                                                                                                                                        
                Text item=SpeedtestResultDown                                                                                                                                                                 
                Text item=SpeedtestResultUp                                                                                                                                                                   
                Text item=SpeedtestResultPing                                                                                                                                                                 
            }                                                                                                                                                                                                 
    Frame label="Steuerung" {
                Text item=SpeedtestResultDate
                Text item=SpeedtestRunning label="Speedtest [%s]" visibility=[SpeedtestRunning != "-"]
                Switch item=SpeedtestRerun mappings=[ON="Start"]
            }                                                                                                                                                                                                 
    Frame label="Statistik" {
                Text label="..." icon="speedtest_analytics8"
            }                                                                                                                                                                                                 
        }                                                                                          

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 received command ON
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/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...")
                                                                                                                                                                                                              
    // 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

Hi All I get this warning and error

2019-07-17 12:11:12.834 [WARN ] [lipse.smarthome.io.net.exec.ExecUtil] - Execution failed (Exit value: -559038737. Caused by java.io.IOException: Cannot run program "/usr/local/bin/speedtest-cli" (in directory "."): error=2, No such file or directory)
2019-07-17 12:10:56.507 [ERROR] [arthome.model.script.speedtest.rules] - --> speedtest failed. Output:
2019-07-17 12:10:56.509 [vent.ItemStateChangedEvent] - SpeedtestRunning changed from data analysis... to Error during execution
2019-07-17 12:11:12.791 [vent.ItemStateChangedEvent] - SpeedtestRunning changed from Error during execution to Measurement in progress...

I did the cli installation as is and did not change anything. what do I need to change to get it working.

Note that now Network binding does provide speedtests measurements.

2 Likes

How do I check what mine should be ?

Try to execute the following in the command line:
/usr/local/bin/speedtest-cli --simple

if it’s not working you could try to find the script with locate:
locate speedtest-cli

If the script is located somewhere else, modify the rule to execute the script with the right path

Thank you. found it. just need to get the following sorted.
Think it is permission issue ? I am still learning linx and its commands

2019-07-17 14:11:52.293 [WARN ] [lipse.smarthome.io.net.exec.ExecUtil] - Execution failed (Exit value: -559038737. Caused by java.io.IOException: Cannot run program "/usr/share/doc/speedtest-cli" (in directory "."): error=13, Permission denied)

Normally following command should fix that:
sudo chmod +x /usr/share/doc/speedtest-cli

maybe you also have to change the owner of the script to the openhab user with:
sudo chown openhab:openhab /usr/share/doc/speedtest-cli

did run both of the commands .
and tested it. I still come up with the following error

2019-07-17 14:15:59.067 [ERROR] [arthome.model.script.speedtest.rules] - --> speedtest failed. Output:
2019-07-17 14:15:59.071 [vent.ItemStateChangedEvent] - SpeedtestRunning changed from data analysis... to Error during execution
2019-07-17 14:30:13.500 [vent.ItemStateChangedEvent] - SpeedtestRunning changed from Error during execution to Measurement in progress...
2019-07-17 14:30:13.562 [WARN ] [lipse.smarthome.io.net.exec.ExecUtil] - Execution failed (Exit value: -559038737. Caused by java.io.IOException: Cannot run program "/usr/share/doc/speedtest-cli" (in directory "."): error=13, Permission denied)
2019-07-17 14:30:13.577 [ERROR] [arthome.model.script.speedtest.rules] - --> speedtest failed. Output:
2019-07-17 14:30:13.590 [vent.ItemStateChangedEvent] - SpeedtestRunning changed from data analysis... to Error during execution```