Script to powercycle modem if ping fails?

Moderator: leecollings

ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Script to powercycle modem if ping fails?

Post by ThinkPad »

Recently my internet provider has been doing some nightly maintenance a few times in the past weeks. This resulted in a not working internet connection in the morning.
I could solve it easily by powercycling the internet modem.

But this got me thinking, i got a spare 433Mhz plug, maybe it is possible to automate this powercycling with a power outlet controlled by a Domoticz script?
I was thinking about this sequence:
  1. Script pings IP like 8.8.8.8 (Google DNS) every minute
  2. No response? Turn outlet off for 30 seconds
  3. After 30s, turn power back on, if within 2 minutes ping is OK > keep power on
  4. If no ping reaction within 2 minutes, turn power off again for 30 seconds
  5. Return to step 1
In 99% this will probably fix it, but to be sure i think i would also connect the router to the same outlet, so both modem and router are powercycled to create a bigger chance that the problem is solved.

Maybe someone already has some kind of script for this? I think it is a nice gimmick to have.
Would be very nice to have this for example when being on vacation. If this happen the first day i am at vacation i can't access Domoticz until i am back :?
I am not active on this forum anymore.
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

Sounds like a good idea, one comment, power cycling the router is fine, power cycling the modem may result in a slower internet speed as your ISP may see the modem failure as a sign of poor transmission and down rate your speed, easier enough to spot by a few checks on speedtest.net.

Not sure this is quite what you want, but I have a Lua monitor script which sends me telegram messages. This could be modified to cycle a switch, as in checks if not present then switches switch off, on second failure switches switch back on, would give you a 1 minute break to save spiking the router.

Code: Select all

-- ~/home/pi/domoticz/scripts/lua/script_time_monitor.lua
function timedifference(s)
   year = string.sub(s, 1, 4)
   month = string.sub(s, 6, 7)
   day = string.sub(s, 9, 10)
   hour = string.sub(s, 12, 13)
   minutes = string.sub(s, 15, 16)
   seconds = string.sub(s, 18, 19)
   t1 = os.time()
   t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
   difference = os.difftime (t1, t2)
   return difference
end

function timeCount(numSec)
   local nSeconds = numSec
   if nSeconds == 0 then
      return  "0seconds"
   else
      local sTime = ""
      local nHours = math.floor(nSeconds/3600)
      local nMins = math.floor(nSeconds/60 - (nHours*60))
      if(nHours > 0) then
         sTime = sTime .. nHours
         if(nHours == 1) then
            sTime = sTime .. "hour "
         else
            sTime = sTime .. "hours "
         end         
      end
      if(nMins > 0) then
         sTime = sTime .. nMins
              if(nMins == 1) then
            sTime = sTime .. "minute "
         else
            sTime = sTime .. "minutes "
         end         
      end
      local nSecs = math.floor(nSeconds - nHours*3600 - nMins *60)
      if(nSecs > 0) then
         sTime = sTime .. nSecs
              if(nSecs == 1) then
            sTime = sTime .. "second"
         else
            sTime = sTime .. "seconds"
         end
      end         
      return sTime
   end
end

function monitor(failvariable, ip, description)
   print('Checking ' .. description)
   local failstate = tonumber(uservariables[failvariable])
   local ping_success=os.execute('ping -c1 -i0.2 ' .. ip )
   if ping_success then
--      print('Ping success')
      if(failstate == 1) then
         local interval = timedifference(uservariables_lastupdate[failvariable])
         print('Link to '..description..' restored after ' .. timeCount(interval))
         os.execute(TelegramScript..' msg '..TelegramTo..' "Restored - back in contact with '.. description ..' after ' .. timeCount(interval) .. '"')
--         os.execute('/home/pi/tg/scripts/generic/telegram.sh msg Simon_Gibbon "Restored - back in contact with '.. description ..' after ' .. timeCount(interval) .. '"')
         commandArray['Variable:'..failvariable] = '0'
      end
   else
--      print('Ping fail')
      if(failstate == 0) then
         commandArray['Variable:'..failvariable] = '1'
         print(description .. ' Failed')
--         os.execute('/home/pi/tg/scripts/generic/telegram.sh msg Simon_Gibbon "Failed - lost contact with ' .. description .. '"')
         os.execute(TelegramScript..' msg '..TelegramTo..' "Failed - lost contact with ' .. description .. '"')
      end
   end
   return
end

commandArray = {}

TelegramScript=os.getenv("TelegramScript")
TelegramTo=os.getenv("TelegramTo")
print('About to monitor things')
monitor('DownPowerFail','192.168.89.171','Study WiFi')
monitor('LNCFail','192.168.9.1','LNC')
monitor('EclipseFail','111.111.111.111','Eclipse')
print('Finished monitoring things')

return commandArray
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

That isn't a problem in my case, i have internet over television line (coax cable) i always get full speed back after switching the modem on/off. With ADSL/VDSL the symptom you describe is indeed something that can happen. Only problem that can happen (had that before) after a powercycle of the modem is that my outside (WAN) IP-adress changes, but i have a dynamic DNS service for that, so i can connect on that domainname instead of IP.

Thanks for your script. What does it exactly do? I find Lua a bit hard to read :D

And would Google find it OK if you ping them every minute 24/7, year in year out? Or maybe use the IP of the first hop after my own modem.... saves bandwith by not going the whole route to Google.
I am not active on this forum anymore.
Philos31
Posts: 33
Joined: Friday 15 August 2014 22:37
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Script to powercycle modem if ping fails?

Post by Philos31 »

I am doing the same, checking every 15 minutes via cron with my bash script:

offcourse you need to put your public ip or url in the first line and change the IDX (139 in this script) of the switch to your own switch IDX

Code: Select all

outsideURL="http://outside.url:8080"
insideURL="http://127.0.0.1:8080"

date
if curl --output /dev/null --silent --head --fail "$outsideURL"
then
    echo "Domoticz reachable from internet, no need to reboot"
else
    echo "Domoticz unreachable from internet, checking internal"
		if curl --output /dev/null --silent --head --fail "$insideURL"
		then
		echo "Domoticz reachable on lan, rebooting router"
# Send off command to switch twice to be sure

wget -O - -q -t 1 'http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=139&switchcmd=Off&level=0'		{
sleep 2
wget -O - -q -t 1 'http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=139&switchcmd=Off&level=0'
sleep 2

# Send on command to switch, twice to be sure
wget -O - -q -t 1 'http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=139&switchcmd=On&level=0'
sleep 2
wget -O - -q -t 1 'http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=139&switchcmd=On&level=0'

	else
		echo "Domoticz unreachable on WAN and LAN Rebooting Domoticz"
		sudo reboot
	fi
fi
RasPi2/KaKu/HUE/Xiaomi/Z-Wave/Nuki/Daikin 3,5kw Ururu Sarara/IR Heating Panels all working together with domoticz
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

Thanks, i can understand that script hehe. The logic of that script is similar to what i had in my head to build.

Would it work if i change the external URL to some webpage like http://www.google.nl ?
I am not active on this forum anymore.
Philos31
Posts: 33
Joined: Friday 15 August 2014 22:37
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Script to powercycle modem if ping fails?

Post by Philos31 »

ThinkPad wrote:Thanks, i can understand that script hehe. The logic of that script is similar to what i had in my head to build.

Would it work if i change the external URL to some webpage like http://www.google.nl ?
Yes, that should work, I check my domoticz because that is what I need to be up and running.
If you check Google and google is up, it could still be that your domoticz is unrachable because chicking google checks from your home to the internet, checking your public url will check if domoticz is reacable from the internet, so if your internet connection works, but your natting is not working then checking google will not help you reboot your router.

Do you understand? It is a bit difficult for me to explain in English what I mean.

Het kan zijn dat je verbinding van internet naar binnen niet werkt en je toch een werkende verbinding naar buiten hebt (bijvoorbeeld als je nat service in je router is omgevallen) dan helpt het checken van google niet, want dat is wel op.

If you need to check if domoticz is running and reachable from internet then do not use google but use the url you use when you try to reach domoticz from internet.
RasPi2/KaKu/HUE/Xiaomi/Z-Wave/Nuki/Daikin 3,5kw Ururu Sarara/IR Heating Panels all working together with domoticz
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

I understand. But checking myself from inside to outside seems a bit untrustable... I also read once that this reverse lookup (trying external URL that redirects to internal network source) is not always working if you try it at your own network. Not all modems/routers support this or so..
And i don't worry about Domoticz, that hasn't been a problem yet (running on Synology really makes it a lot more stable than on Pi!). It is more that my ISP (Ziggo) has been doing maintenance and the modem needs a reboot after that.

I also understand the 'problem' you are checking for, but never have seen that happening... my router is rockstable (WDR3600 with OpenWRT).
By the way, what does the curl command do? It fetches page, but how does the script know if it's good or faulty? What if don't put a webpage in, but something like Google DNS? (or any other IP that doesn't serve a webpage). Better to replace the curl with some kind of ping command then i guess?...

And you don't seem to have any waiting time for the modem/router to come back again? What if the modem is still busy booting? The script will think the connection is broken then and toggle power again? Or not?
Possible powertoggle loop there i gues... what if Domoticz crashes on 127.0.x.x ? The script will keep toggling power then (although it won't succeed because no response is given to the JSON command because Domoticz dead :mrgreen: )

I will try your script tonight or so. First going to try it with the outlet connected to a lightbulb, and with a webserver on my PC that i enable/disable. If i put the outlet between my modem now, my girlfriend will get angry while i am testing :lol:
I am not active on this forum anymore.
Philos31
Posts: 33
Joined: Friday 15 August 2014 22:37
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Script to powercycle modem if ping fails?

Post by Philos31 »

The script is run every 15 minutes vian crontab

*/15 * * * * /home/pi/domoticz/scripts/upcheck.sh &

So there is 15 minutes waiting time before trying again. If Domotiz crashes on 127.0.0.1 (the loopback adress) it will automagicaly reboot itself. In the last few lines on the bottom, just before fi fi....
Sudo Reboot...

This curl command just checks if it gets an ok back from the http server. If the server is down it will not send an ok, and the script is working with that.
RasPi2/KaKu/HUE/Xiaomi/Z-Wave/Nuki/Daikin 3,5kw Ururu Sarara/IR Heating Panels all working together with domoticz
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

Thanks!
Will try soon and report back here with my findings :)
I am not active on this forum anymore.
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

ThinkPad wrote:Thanks for your script. What does it exactly do? I find Lua a bit hard to read :D
I think anybody else's code is hard to read without a few hints or at least in a colour coding editor.

Basically the code is probably over engineered for what you want and cron plus a Bash script seems like a light way to go.

The Lua script has a key function Monitor which will ping a given ip address. On ping failure then Monitor telegrams connection lost, sets the state as disconnected using a Domoticz variable. When ping success happens then Monitor telegrams connection is back plus the time it was down calculated by using the time functions and when the Domticz variable was last updated, then resets the state to connected using the Domoticz variable. Monitor has 3 parameters, the name of the Domoticz variable, the ip address to ping and the name of the device for the telegram messge.

Code: Select all

-- ~/home/pi/domoticz/scripts/lua/script_time_monitor.lua
function timedifference(s)
   year = string.sub(s, 1, 4)
   month = string.sub(s, 6, 7)
   day = string.sub(s, 9, 10)
   hour = string.sub(s, 12, 13)
   minutes = string.sub(s, 15, 16)
   seconds = string.sub(s, 18, 19)
   t1 = os.time()
   t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
   difference = os.difftime (t1, t2)
   return difference
end

function timeCount(numSec)
   local nSeconds = numSec
   if nSeconds == 0 then
      return  "0seconds"
   else
      local sTime = ""
      local nHours = math.floor(nSeconds/3600)
      local nMins = math.floor(nSeconds/60 - (nHours*60))
      if(nHours > 0) then
         sTime = sTime .. nHours
         if(nHours == 1) then
            sTime = sTime .. "hour "
         else
            sTime = sTime .. "hours "
         end         
      end
      if(nMins > 0) then
         sTime = sTime .. nMins
              if(nMins == 1) then
            sTime = sTime .. "minute "
         else
            sTime = sTime .. "minutes "
         end         
      end
      local nSecs = math.floor(nSeconds - nHours*3600 - nMins *60)
      if(nSecs > 0) then
         sTime = sTime .. nSecs
              if(nSecs == 1) then
            sTime = sTime .. "second"
         else
            sTime = sTime .. "seconds"
         end
      end         
      return sTime
   end
end

function monitor(failvariable, ip, description)
   print('Checking ' .. description)
   local failstate = tonumber(uservariables[failvariable])
   local ping_success=os.execute('ping -c1 -i0.2 ' .. ip )
   if ping_success then
--      print('Ping success')
      if(failstate == 1) then
         local interval = timedifference(uservariables_lastupdate[failvariable])
         print('Link to '..description..' restored after ' .. timeCount(interval))
         os.execute(TelegramScript..' msg '..TelegramTo..' "Restored - back in contact with '.. description ..' after ' .. timeCount(interval) .. '"')
         commandArray['Variable:'..failvariable] = '0'
      end
   else
--      print('Ping fail')
      if(failstate == 0) then
         commandArray['Variable:'..failvariable] = '1'
         print(description .. ' Failed')
         os.execute(TelegramScript..' msg '..TelegramTo..' "Failed - lost contact with ' .. description .. '"')
      end
   end
   return
end

commandArray = {}

TelegramScript=os.getenv("TelegramScript")
TelegramTo=os.getenv("TelegramTo")
print('About to monitor things')
monitor('DownPowerFail','192.168.89.171','Study WiFi')
monitor('LNCFail','192.168.9.1','LNC')
monitor('EclipseFail','111.111.111.111','Eclipse')
print('Finished monitoring things')

return commandArray
Hope that helps, but go with cron and the Bash script.
Last edited by simonrg on Wednesday 10 June 2015 23:53, edited 1 time in total.
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

This works fine:

Code: Select all

#!/bin/ash
FirstIP="8.8.8.8" #(Google public DNS)
SecondIP="208.67.222.222" #(OpenDNS public DNS)
IDX="165"
DomoIP="127.0.0.1"
DomoPort="8084"

ping="ping -c 5 -w 3 -q "$FirstIP""
if $ping | grep -E "min/avg/max" > /dev/null
then
    echo "First IP ("$FirstIP") responds, do nothing"
else
    echo "--> No response from first IP ("$FirstIP"), now trying second one ("$SecondIP")"
      ping="ping -c 5 -w 3 -q "$SecondIP""
      if $ping | grep -E "min/avg/max" > /dev/null     
      then
      echo "Second IP ("$SecondIP") is responding, do nothing"

   else
      echo "--> Both IP's not responding, toggling power to modem"
      # Send off command to switch twice to be sure
      wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=Off&level=0'     
      sleep 2
      wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=Off&level=0'     
      sleep 2

      # Send on command to switch, twice to be sure
      wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=On&level=0'
      sleep 2
      wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=On&level=0'
      sleep 2
   fi
fi
Put it in my crontab (runs every 15 minutes):

Code: Select all

*/15     *       *       *       *       root    sh      /volume1/@appstore/domoticz/scripts/modemreboot.sh
For the router (WDR3600 with OpenWRT) i want to look for a URL to reboot it, is a bit more friendly than *BLAM* powering it off and should also be sufficient.... The modem is a dumb device which can handle that.

The setup is now brought in place, we shall seee... Nice thing is that i can look in the log of the switch in Domoticz to see if it has triggered.
I am not active on this forum anymore.
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

simonrg wrote:Hope that helps, but go with cron and the Bash script.
Sorry just thought of course now Domoticz has a pinger, it would be simpler to use inbuilt Domoticz functionality and a short script to trigger the reboot of your modem and router.
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

simonrg wrote:
simonrg wrote:Hope that helps, but go with cron and the Bash script.
Sorry just thought of course now Domoticz has a pinger, it would be simpler to use inbuilt Domoticz functionality and a short script to trigger the reboot of your modem and router.
I guess that one won't work... It will ping a device and if it gets reaction > turn switch on.
And if it won't get reaction > turn switch off.... so far it is fine, but if the switch is turned off, the modem won't get any power again and the ping will never return an answer, without first having some human intervention ;)

The script doesn't have this problem, it always turns power off, waits 2 seconds and then turn it back on again.
I am not active on this forum anymore.
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

ThinkPad wrote:
simonrg wrote:Sorry just thought of course now Domoticz has a pinger, it would be simpler to use inbuilt Domoticz functionality and a short script to trigger the reboot of your modem and router.
I guess that one won't work... It will ping a device and if it gets reaction > turn switch on.
And if it won't get reaction > turn switch off.... so far it is fine, but if the switch is turned off, the modem won't get any power again and the ping will never return an answer, without first having some human intervention ;)

The script doesn't have this problem, it always turns power off, waits 2 seconds and then turn it back on again.
Obviously the script would need to do the same things turn off, wait and turn on.
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

On the Dutch forum 'Tweakers' i also mentioned this script. 'MikeOO' came with a good comment: what if the connection stays down for a while? The script will keep interrupting power to the modem. If the connection is down the whole day, this could mean hundreds of power interruptions.....

Does anyone know how to add some logic to prevent this? Maybe a sort of counter which adds +1 to a .txt file every time a powercycle is done, and then check in the script if the counter is smaller than xx before proceeding, and if counter greater than xx stop powercycling/lower interval to once per hour or so

But i am not that handy, would be great if someone could help..... :mrgreen:
I am not active on this forum anymore.
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

ThinkPad wrote:On the Dutch forum 'Tweakers' i also mentioned this script. 'MikeOO' came with a good comment: what if the connection stays down for a while? The script will keep interrupting power to the modem. If the connection is down the whole day, this could mean hundreds of power interruptions.....

Does anyone know how to add some logic to prevent this? Maybe a sort of counter which adds +1 to a .txt file every time a powercycle is done, and then check in the script if the counter is smaller than xx before proceeding, and if counter greater than xx stop powercycling/lower interval to once per hour or so

But i am not that handy, would be great if someone could help..... :mrgreen:
:geek: Ok perhaps my Lua script is not quite so over engineered after all, just incorrectly engineered for exactly what you want. Time to learn some Lua 8-)

Currently the Lua script basically tells me when a device is no longer pingable and then tells me when it is next pingable along how long it has been down for.

So in your case, you want the modem powercylcing once and then checking on after a certain length of time, if the modem is still not pingable then either powercycle again or wait say 5 minutes before powercycling. So a Lua script that uses the time between last ping and last time the device was powercycled would do the job. Let me have a think about exactly how to code this.

Another thought is can you ping the modem both internally via your local network 192.168.x.x and via external ip address, if so then there will be no point powercycling your modem if you can't ping it internally as power is off. An issue for me as my Domoticz system is on a UPS, but various other systems aren't.
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
simonrg
Posts: 329
Joined: Tuesday 16 July 2013 22:54
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8807
Location: North East England
Contact:

Re: Script to powercycle modem if ping fails?

Post by simonrg »

simonrg wrote:
ThinkPad wrote:On the Dutch forum 'Tweakers' i also mentioned this script. 'MikeOO' came with a good comment: what if the connection stays down for a while? The script will keep interrupting power to the modem. If the connection is down the whole day, this could mean hundreds of power interruptions.....

Does anyone know how to add some logic to prevent this? Maybe a sort of counter which adds +1 to a .txt file every time a powercycle is done, and then check in the script if the counter is smaller than xx before proceeding, and if counter greater than xx stop powercycling/lower interval to once per hour or so

But i am not that handy, would be great if someone could help..... :mrgreen:
:geek: Ok perhaps my Lua script is not quite so over engineered after all, just incorrectly engineered for exactly what you want. Time to learn some Lua 8-)
It is time to learn some Lua I guess, as this script is not complicated but is a bit convoluted to do what I think you want to do.

In order to use the script you need to create a Domoticz integer user variable initialised to 0 (zero). Create the script ~/home/domoticz/scripts/lua/script_time_modem.lua based on the script below. just changing this line (3rd line from the end).

Code: Select all

MonitorAndControl('ModemFail','8.8.8.8','Modem Switch','Internet',5)
Where the parameter of MonitorAndControl in order are thename of Domoticz variable, the IP address to ping, the name of the Domoticz switch which controls the modem, the connection description text to display in messages and the number of minutes to increase retry time by after each off /on cycle failure.

If you don't want notifications just comment out the notifications.

script_time_modem is a time script, so Domoticz will execute it once a minute.

When ping fails then the modem switch will be turned off and you will be alerted, after a minute the modem will be switched back on, after a minute the script will check if the internet connection has been restored, if so it will alert you.

If after switching on and awaiting for 1 minute the ping still fails, then the script will wait for 5 minutes (retry time can be changed see above) and try on/off again, if still fails will try again after 10 minutes, then 15, then 20, then 25, ......... until successful.

Hopefully this is what you were looking for :ugeek:

Code: Select all

-- ~/home/pi/domoticz/scripts/lua/script_time_modem.lua
function timedifference(s)

   year = string.sub(s, 1, 4)
   month = string.sub(s, 6, 7)
   day = string.sub(s, 9, 10)
   hour = string.sub(s, 12, 13)
   minutes = string.sub(s, 15, 16)
   seconds = string.sub(s, 18, 19)
   t1 = os.time()
   t2 = os.time{year=year, month=month, day=day, hour=hour, min=minutes, sec=seconds}
   difference = os.difftime (t1, t2)
   return difference
end

function timeCount(numSec)
   -- Function turns seconds into hours, minutes, seconds
   local nSeconds = numSec
   if nSeconds == 0 then
      return  "0seconds"
   else
      local sTime = ""
      local nHours = math.floor(nSeconds/3600)
      local nMins = math.floor(nSeconds/60 - (nHours*60))
      if(nHours > 0) then
         sTime = sTime .. nHours
         if(nHours == 1) then
            sTime = sTime .. "hour "
         else
            sTime = sTime .. "hours "
         end
      end
      if(nMins > 0) then
         sTime = sTime .. nMins
              if(nMins == 1) then
            sTime = sTime .. "minute "
         else
            sTime = sTime .. "minutes "
         end
      end
      local nSecs = math.floor(nSeconds - nHours*3600 - nMins *60)
      if(nSecs > 0) then
         sTime = sTime .. nSecs
              if(nSecs == 1) then
            sTime = sTime .. "second"
         else
            sTime = sTime .. "seconds"
         end
      end
      return sTime
   end
end

function numbersum(n)
  if n<0 then
    return 0
  else
    return n + numbersum(n-1)
  end
end

function MonitorAndControl(failvariable, ip, modemswitch, description,retrytime)
   -- failvariable is name of Domoticz variable create and set to 0
   -- ip address to test for connectivity
   -- modemswitch name of Domoticz switch which connects
   -- description the text to put into the status message
   -- retrytime minutes to increase time before next off / on
   print('Checking ' .. description)
   local failstate = tonumber(uservariables[failvariable])
   local ping_success=os.execute('ping -c1 -W1 ' .. ip )
   local interval = timedifference(uservariables_lastupdate[failvariable])
   if ping_success then
      print('Ping success')
      if(failstate > 0) then
         interval = 60 *(math.floor(failstate/2)+retrytime*numbersum(math.floor(failstate/2)-1)) + timedifference(uservariables_lastupdate[failvariable])
         print('Link to '..description..' restored after ' .. timeCount(interval))
--         os.execute(TelegramScript..' msg '..TelegramTo..' "Restored - back in contact with '.. description ..' after ' .. timeCount(interval) .. '"')
         commandArray['SendNotification']=description..'#Restored - back in contact with '.. description ..' after ' .. timeCount(interval) .. '#0'
         commandArray['Variable:'..failvariable] = '0'
      end
   else
      print('Ping fail: '..failstate)
      -- Failstate is even
      if(failstate-2*math.floor(failstate/2)==0) then
         if(failstate == 0) then
         -- Only just failed so switch off the switch
             print(description .. ' Failed')
--             os.execute(TelegramScript..' msg '..TelegramTo..' "Failed - lost contact with ' .. description .. '"')
             commandArray['SendNotification']=description..'#Failed - lost contact with ' .. description .. '#0'
             commandArray[modemswitch] = 'Off'
             -- Ping failed so increment failstate
             commandArray['Variable:'..failvariable] = tostring(failstate+1)
         elseif(failstate > 1 and interval > (math.floor(failstate/2)*retrytime*60)-30) then
             -- Still no response after (n / 2 * retrytime) so switch off again
             commandArray[modemswitch] = 'Off'
             -- Ping failed so increment failstate
             commandArray['Variable:'..failvariable] = tostring(failstate+1)
             print('Switching off: '..interval..'seconds - even - failed # '..failstate)
          end
      else
         -- Failstate is odd
         -- Switch been off for a minute so time to switch it on again
         commandArray[modemswitch] = 'On'
         -- Ping failed so increment failstate
         commandArray['Variable:'..failvariable] = tostring(failstate+1)
         print('Switching On: '..interval..'seconds - odd - failed # '..failstate)
      end
   end
   return
end

commandArray = {}

--TelegramScript=os.getenv("TelegramScript")
--TelegramTo=os.getenv("TelegramTo")
print('About to monitor things')
MonitorAndControl('ModemFail','8.8.8.8','Modem Switch','Internet',5)
print('Finished monitoring things')

return commandArray
In fact it would nice to write a Bash script to do this, as the need for integration with Domoticz is fairly weak and it would be one less load on Domoticz which cron could cope with very well. However, the logic to allow increasing times between retries / keeping track of time etc. is not what Bash is meant for, hence more sensible to do in Lua.
Raspberry Pi 2 B - 2A@5V PSU - Raspbian + Domoticz + RFXtrx(89), LightwaveRF House(dimmers, sockets, wireless/mood switches), Owl CM113, 4 LaCross Temp / Humidity Sensors, 4 Siemens PIR, Smappee, Solaredge, ESP8266
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

Wow, thanks for the effort!!! :o

Sounds good! I will try it after i am back from holiday (leaving this weekend, for 2 weeks).
I am not active on this forum anymore.
ThinkPad
Posts: 890
Joined: Tuesday 30 September 2014 8:49
Target OS: Linux
Domoticz version: beta
Location: The Netherlands
Contact:

Re: Script to powercycle modem if ping fails?

Post by ThinkPad »

My first Bash script posted in this topic wasn't working correctly. I had another search today and found this script.

This script seems to work better:

Code: Select all

#!/bin/bash
FirstIP="8.8.8.8" #Google DNS
SecondIP="208.67.222.222" #OpenDNS Public DNS
IDX="165" #IDX of the outlet that controls power to your modem
DomoIP="127.0.0.1"
DomoPort="8084"

COUNTER=0
while [ $COUNTER -lt 3 ] ## Try 3 times before resetting the modem. Modify as needed.
do
if ping -c 1 -w 5 $FirstIP &> /dev/null ## Determine if second IP-address is reachable.
	then
	echo "First IP responds, do nothing"
	exit 1
elif ping -c 1 -w 5 $SecondIP &> /dev/null ## Determine if second IP-address server is reachable.
	then
	echo "Second IP responds, do nothing"
	exit 1
else
	let COUNTER=COUNTER+1
fi
done
#Turn modem off
wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=Off&level=0'     
echo "Turn modem off (sending command twice to Domoticz, just to be sure)"
sleep 2
wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=Off&level=0' 
echo "Now waiting 10 seconds"
sleep 10 ## Delay of 10, increase as needed.

#Turn modem back on again
wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=On&level=0'
echo "Turn modem back on again (sending command twice to Domoticz, just to be sure)"
sleep 2
wget -O /dev/null - -q -t 1 'http://'$DomoIP':'$DomoPort'/json.htm?type=command&param=switchlight&idx='$IDX'&switchcmd=On&level=0'
I also had a look at the Lua script made by Simonrg, but it is too complicated for me to understand. I trust you fully that it works, but i like to understand what a script does :D

I would also have preferred if i could reboot the modem through telnet or SSH, but it doesn't respond. Too bad, otherwise you wouldn't need the Domoticz + 433Mhz part at all and it would be more universal to use.
I am not active on this forum anymore.
jadijkstra2000
Posts: 58
Joined: Monday 26 May 2014 10:18
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Script to powercycle modem if ping fails?

Post by jadijkstra2000 »

Which outlet is best to use? Don't want a neighbour to accidentalliy turn off my modem :)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest