diff --git a/install b/install index 791a711..3546814 100755 --- a/install +++ b/install @@ -1,6 +1,8 @@ #! /usr/bin/env python3 import os +import sys + from string import Template from subprocess import check_call @@ -12,7 +14,8 @@ CURRENT_DIR = os.path.dirname(os.path.realpath(__file__)) EXEC_PATH = os.path.join(CURRENT_DIR, EXEC) SERVICE_TEMPLATE = os.path.join(CURRENT_DIR, SERVICE) SERVICE_FILE = os.path.join(SYSTEM_DIR, SERVICE) -EXEC_START = f'python3 {EXEC}' +PYTHON = sys.executable +EXEC_START = f'{PYTHON} {EXEC}' with open(SERVICE_TEMPLATE) as f: serviceTemplate = Template(f.read()) diff --git a/wifi-keepalive.py b/wifi-keepalive.py index 92f318c..0061ac2 100644 --- a/wifi-keepalive.py +++ b/wifi-keepalive.py @@ -3,30 +3,89 @@ from subprocess import CalledProcessError, check_output from sys import exit from time import sleep +INITIAL_DELAY_IN_SECONDS = 40 PING_INTERVAL_IN_SECONDS = 80 -signal(SIGTERM, lambda signum, frame: exit(0)) + +class WifiKeepalive: + + def __init__(self): + self.defaultRoute = self.getDefaultWifiRoute() + self.initialDelay = INITIAL_DELAY_IN_SECONDS + self.pingInterval = PING_INTERVAL_IN_SECONDS + self.isConnected = True + self.pingCommand = 'ping -c 1 -W 2 -n' + + def run(self): + sleep(self.initialDelay) + + while self.isRunning(): + self.keepalive() + sleep(self.pingInterval) + + def isRunning(self): + return True + + def keepalive(self): + if self.defaultRoute: + self.pingDefaultRoute() + else: + self.attemptWifiConnection() + + def pingDefaultRoute(self): + if not self.isConnected: + print('Connected to Wifi', flush=True) + + self.isConnected = True + isPingSuccess = self.ping() + + if not isPingSuccess: + self.defaultRoute = self.getDefaultWifiRoute() + + def attemptWifiConnection(self): + if self.isConnected: + print('No Wifi Connection', flush=True) + + self.isConnected = False + self.defaultRoute = self.getDefaultWifiRoute() + + def ping(self): + try: + check_output([*self.pingCommand.split(), self.defaultRoute]) + except CalledProcessError as e: + return False + + return True + + def getDefaultWifiRoute(self): + defaults = [ + r['gateway'] for r in self.getRoutes() if self.isDefaultWifiRoute(r) + ] + + return 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 getDefaultRoute(): - routes = check_output(['route', '-n']).decode('utf-8').splitlines() - defaults = [r.split()[1] for r in routes if r.startswith('0.0.0.0')] - - return defaults[0] if defaults else None +def main(): + signal(SIGTERM, lambda s, f: exit(0)) + WifiKeepalive().run() -def keepalive(defaultRoute): - while True: - sleep(PING_INTERVAL_IN_SECONDS) - ping(defaultRoute) - - -def ping(address): - try: - check_output(['ping', '-c', '1', address]) - except CalledProcessError as e: - pass - - -defaultRoute = getDefaultRoute() -keepalive(defaultRoute) if defaultRoute else print('No default route') +if __name__ == '__main__': + main()