wifi-keepalive/wifi-keepalive.py

95 lines
2.5 KiB
Python

from signal import SIGTERM, signal
from subprocess import CalledProcessError, check_output
from sys import exit
from time import sleep
INITIAL_DELAY_IN_SECONDS = 40
PING_INTERVAL_IN_SECONDS = 80
class WifiKeepalive:
def __init__(self):
self.defaultRoute = None
self.initialDelay = INITIAL_DELAY_IN_SECONDS
self.pingInterval = PING_INTERVAL_IN_SECONDS
self.isConnected = False
self.pingCommand = 'ping -4 -c 1 -W 2 -n'
self.connectedMessage = 'Connected to Wifi'
self.disconnectedMessage = 'No Wifi Connection'
def run(self):
self.prepare()
while True:
self.keepalive()
sleep(self.pingInterval)
def prepare(self):
sleep(self.initialDelay)
self.updateDefaultWifiRoute()
if self.defaultRoute:
self.connect(preparing=True)
else:
self.disconnect(preparing=True)
def keepalive(self):
if self.defaultRoute:
self.connect()
self.ping() or self.updateDefaultWifiRoute()
else:
self.disconnect()
self.updateDefaultWifiRoute()
def connect(self, preparing=False):
if not self.isConnected or preparing:
print(self.connectedMessage, flush=True)
self.isConnected = True
def disconnect(self, preparing=False):
if self.isConnected or preparing:
print(self.disconnectedMessage, flush=True)
self.isConnected = False
def ping(self):
try:
check_output([*self.pingCommand.split(), self.defaultRoute])
except CalledProcessError as e:
return False
return True
def updateDefaultWifiRoute(self):
defaults = [
r['gateway'] for r in self.getRoutes() if self.isDefaultWifiRoute(r)
]
self.defaultRoute = defaults[0] if defaults else None
def getRoutes(self):
outputLines = check_output(
['route', '-n']
).decode('utf-8').splitlines()[2:]
routes = map(lambda r: self.parseRoute(r), outputLines)
return routes
def parseRoute(self, routeLine):
destination, gateway, _, _, _, _, _, interface = routeLine.split()
return {'destination': destination, 'gateway': gateway, 'interface': interface}
def isDefaultWifiRoute(self, route):
return route['destination'] == '0.0.0.0' and route['interface'].startswith('w')
def main():
signal(SIGTERM, lambda s, f: exit(0))
WifiKeepalive().run()
if __name__ == '__main__':
main()