Internet test

Manage the internet router

It’s a common experience to have no more internet connection even if the service provider router returns no alarms. Most of the times the usual switch-off/switch-on is enough to have back the internet service again. If this occurs when nobody is using internet or when no one is present, the internet connection remain down for a long time, loosing the update of the cloud services and excluding the possibility to connect the LAN from outside via VPN or OpenHAB cloud service.

Using the example supplied the internet connection can be supervised continuosly.

Classic UI example:

Using this UI the speedtest as well as the router reset can be forced manually at any moment.

This graph example shows the historycal status of the connection also evidencing some possible downgrade:

Manage the internet router

The OpenHAB community is, as usual, full of suggestions. This tutorial on speedtest-cli internet up/downlink measurement is the starting point for the example. The internet connection is tested every 5 minutes. The results are displayed as actual measure for the standard UI and stored in InfluxDB. This is the configuration: items/speedtest.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]"   <"speedtest_problem4">      (gSpeedtest)
Number      SpeedtestCountOK        "Test OK [%d times]"         <"speedtest_network">       (gSpeedtest)
Number      SpeedtestCountKO        "Test KO [%d times]"         <"speedtest_network">       (gSpeedtest)
Number      RouterRestartCount      "Restarted [%d times]"       <"speedtest_network">       (gSpeedtest)
Switch      RouterRestart           "Restart Internet Router"    <"network">                 (gSpeedtest)
Some items is used to display values, other just as a temporary variable. rules/speedtest.rules
val String filename = "speedtest.rules"
var Number speedtestVarOK
var Number speedtestVarKO
var Number routerRestartCountVar

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("⁉ (Sconosciuto)")
    ]
    speedtestVarOK = 0
    speedtestVarKO = 0
    routerRestartCount = 0
end

rule "Speedtest"
when
    //Time cron "0 0 5,13 * * ?" or
    Time cron "0 0/5 * * * ?" or
    Item SpeedtestRerun received command ON
then
    logInfo(filename, "--> speedtest executed...")
    SpeedtestRunning.postUpdate("Misura in corso...")

    // 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@@--server@@395 ", 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("Analisi dei dati...")

    // 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 jav.lang.Float(results.get(0).split(" ").get(1))
        var float down = new jav.lang.Float(results.get(1).split(" ").get(1))
        var float up   = new jav.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("-")
        speedtestVarOK = speedtestVarOK + 1
        speedtestVarKO = 0
        SpeedtestCountOK.postUpdate(speedtestVarOK)
        SpeedtestCountKO.postUpdate(speedtestVarKO)
        logInfo(filename, "--> speedtest finished.")
    } 
    else 
    {
        SpeedtestResultPing.postUpdate(0)
        SpeedtestResultDown.postUpdate(0)
        SpeedtestResultUp.postUpdate(0)
        SpeedtestSummary.postUpdate("(sconosciuto)")
        SpeedtestRunning.postUpdate("Errore durante l'esecuzione")
        speedtestVarKO = speedtestVarKO + 1
        SpeedtestCountKO.postUpdate(speedtestVarKO)
        logError(filename, "--> speedtest failed. Output:\n" + speedtestCliOutput + "\n\n")
        if (speedtestVarKO > 3)
        {
            sendCommand(Rele2, ON)
            speedtestVarKO = 0
            routerRestartCountVar = routerRestartCountVar + 1
            RouterRestartCount.postUpdate(routerRestartCountVar)
            set_timer = createTimer(now.plusSeconds(5))
            [
                sendCommand(Rele2, OFF)
                RouterRestart.postUpdate(ON)
	            set_timer = null
            ] 
        }
    }
    SpeedtestRerun.postUpdate(OFF)
end

rule "Router Restart"
when 
    Item RouterRestart changed
then
    sendCommand(Rele2, ON)
    set_timer = createTimer(now.plusSeconds(5))
    [
        sendCommand(Rele2, OFF)
        RouterRestart.postUpdate(ON)
	    set_timer = null
    ] 
end 
  The failed tests are cumulated in a variable, when the faults number is higher than a given threshold the relay is energized for 5 seconds, the NC contact opens the circuit and cut off the power supply for the router along the same time. The internet router power plug is tied to the normally closed contact of the relay so energizing the relay the router is switched off for a while resetting the connection.

Share