diff --git a/README b/README new file mode 100644 index 0000000..3981799 --- /dev/null +++ b/README @@ -0,0 +1,8 @@ +cloned this xbmc inhibit shutdown script. +originally it blocks shutdown on active tcp connections. + +I've added: +- inhibit shutdown on torrent downloads (Transmission) +- inhibit shutdown if a "lockfile" is present on the system +- add a delay before allowing shutdown again if it was inhibited (this is to make sure we do not shut down directly after dropping a remote connection. If i am logged in remotely, and want to reconnect, i do not want the machine to go down) +- changed the sleep time loop to allow xbmc to shutdown without a long delay diff --git a/addon.xml b/addon.xml index bf32c9a..acdce4b 100644 --- a/addon.xml +++ b/addon.xml @@ -1,12 +1,12 @@ - + linux - Inhibit idle shutdown when TCP conections are open. - Inhibit idle shutdown when specified network connections are opened to this computer. + Inhibit idle shutdown when TCP conections are open, or torrents are downloading. + Inhibit idle shutdown when specified network connections are opened to this computer, or transmission is downloading torrents. diff --git a/inhibit_shutdown.py b/inhibit_shutdown.py index 38ac51e..6adc453 100644 --- a/inhibit_shutdown.py +++ b/inhibit_shutdown.py @@ -5,6 +5,15 @@ import xbmcaddon import subprocess import re +from os import path, popen +global sleep_time, watched_local, watched_remote, counterdefault, addon +global lockfilepaths, transmisionMinimalSpeed , transmissionCmd, debugMe + +class MyMonitor( xbmc.Monitor ): + def __init__( self, *args, **kwargs ): + xbmc.Monitor.__init__( self ) + def onSettingsChanged( self ): + load_settings() def port_set(string): ret = set() @@ -16,18 +25,19 @@ def port_set(string): ret.add(port) return ret -def log(msg): - print("{}: {}".format(addon.getAddonInfo('id'), msg)) +def mylog(msg): + if debugMe: + print("{}: {}".format(addon.getAddonInfo('id'), msg)) -def check_services(): +def check_services(watchlocal, watchremote): """ Check if any of the watched services is running. """ netstat = subprocess.check_output(['/bin/netstat', '-t', '-n'], universal_newlines=True) for line in netstat.split('\n')[2:]: items = line.split() - if len(items) < 4: - continue + if len(items) < 4: continue + if not ("udp" in items[0] or "tcp" in items[0] or "raw" in items[0]): continue local_addr, local_port = items[3].rsplit(':', 1) remote_addr, remote_port = items[4].rsplit(':', 1) @@ -40,32 +50,104 @@ def check_services(): local_port = int(local_port) - if ((local_addr != remote_addr) and (local_port in watched_remote)) or \ - ((local_addr == remote_addr) and (local_port in watched_local)): - log("Found connection from {} to {}:{}".format(remote_addr, local_addr, local_port)) + if ((local_addr != remote_addr) and (local_port in watchremote)) or \ + ((local_addr == remote_addr) and (local_port in watchlocal)): + mylog("Found connection from {} to {}:{}".format(remote_addr, local_addr, local_port)) + return True + + mylog("No connection found.") + return False + +def check_lockfiles(lockfilelist=[]): + for i in lockfilelist: + if path.exists(i): + mylog("lockfile(s) found: %s" %(i)) + return True + return False + +# function to check the status of transmission. if running, it checks if the downloads are going fast enough to keep the system awake +def check_transmission(transmissioncommand,transmissionminimalspeed=10.0): + try: transmissioninfo = popen(transmissioncommand).read() + except: + mylog("transmission-remote error. is transmission-remote installed on this system?") + return False + else: + if transmissioninfo == '': + mylog("transmission not running or not giving any response") + return False + elif float(transmissioninfo.split()[-1]) >= transmissionminimalspeed: + mylog("transmission downloading: %s kb/s" %(transmissioninfo.split()[-1])) return True + else: + mylog("transmission downloading too slow: %s kb/s" %(transmissioninfo.split()[-1])) + return False + return False - log("No connection found.") +def check_all(watchlocal=set(), watchremote=set(), lockfilelist=[], transmissioncommand="", transmissionminimalspeed=0.0): + # this routine checks if the system is active. If it finds an activity, it will return True and not check other activities. + if lockfilelist: + if check_lockfiles(lockfilelist): + return True + if watchlocal or watchremote: + if check_services(watchlocal,watchremote): + return True + if transmissioncommand: + if check_transmission(transmissioncommand, transmissionminimalspeed): + return True return False +def load_settings(): + global sleep_time, watched_local, watched_remote, counterdefault, addon + global lockfilepaths, transmisionMinimalSpeed , transmissionCmd, debugMe + + addon = xbmcaddon.Addon() + s = addon.getSetting + try: + sleep_time = int(s('sleep')) + except ValueError: + sleep_time = 60 + watched_local = port_set(s('localports')) + watched_remote = port_set(s('remoteports')) + counterdefault = int(s('idlecount')) + lockfilepaths=s('lockfilepaths') + if lockfilepaths: + lockfilepaths=lockfilepaths.split(";") + else: + lockfilepaths=[] + checkTransmission = s('checktransmission') == 'true' + transmisionMinimalSpeed = float(s('transmissionminspeed')) + transmissionUsername = s('transmissionuser') + transmissionPasswd = s('transmissionpass') + if not checkTransmission: + transmissionCmd = "" + elif transmissionUsername and transmissionPasswd: + transmissionCmd = "transmission-remote -n %s:%s -l" %(transmissionUsername, transmissionPasswd) + else: + transmissionCmd = "transmission-remote -l" + debugMe = s('debugme') == 'true' + #FIXME: I need to check if transmission-remote always returns kb/s -addon = xbmcaddon.Addon() -s = addon.getSetting -try: - sleep_time = int(float(s('sleep')) * 1000) -except ValueError: - sleep_time = 60 * 1000 -watched_local = port_set(s('localports')) -watched_remote = port_set(s('remoteports')) +load_settings() +counter = counterdefault -log("Watching for remote connections to ports {} and for local connections to ports {}, sleep time is {:0.2f} s.".format( +mylog("Watching for remote connections to ports {} and for local connections to ports {}, sleep time is {} s.".format( ', '.join(str(x) for x in watched_remote), ', '.join(str(x) for x in watched_local), - sleep_time / 1000.0)) + sleep_time)) while not xbmc.abortRequested: - if check_services(): - xbmc.executebuiltin('InhibitIdleShutdown(true)') - else: - xbmc.executebuiltin('InhibitIdleShutdown(false)') - xbmc.sleep(sleep_time) + for i in range(sleep_time): + if xbmc.abortRequested: break + load_settings() + if i==0: + if check_all(watched_local, watched_remote, lockfilepaths, transmissionCmd, transmisionMinimalSpeed): + mylog("Setting InhibitIdleShutdown to true") + xbmc.executebuiltin('InhibitIdleShutdown(true)') + counter = counterdefault + elif counter > 0: # if we have a value on the counter, we leave shutdown as it is. + counter = counter -1 + mylog("Delay counter is: %i. Not changing InhibitIdleShutdown." %(counter)) + else: + mylog("Setting InhibitIdleShutdown to false") + xbmc.executebuiltin('InhibitIdleShutdown(false)') + xbmc.sleep(1000) diff --git a/resources/settings.xml b/resources/settings.xml index e5a5b9b..e3a2db6 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,8 +1,17 @@ - + + + + + + + + + +