From d5b6d3640a5617ec041e836d44eca23e15295e91 Mon Sep 17 00:00:00 2001 From: rlKoekie Date: Mon, 15 Jul 2013 14:12:57 +0200 Subject: [PATCH 1/4] added readme, incomplete --- README | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 README diff --git a/README b/README new file mode 100644 index 0000000..7e1cd44 --- /dev/null +++ b/README @@ -0,0 +1,8 @@ +cloned this xbmc inhibit shutdown script. +originally it blocks shutdown on active tcp connections. + +I'll be adding features such as: +-inhibit shutdown on torrent downloads (Transmission) +-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) +-... + From ab8fb39dd4560834ba7652e345bb4435ca7613e9 Mon Sep 17 00:00:00 2001 From: rlKoekie Date: Mon, 15 Jul 2013 15:03:54 +0200 Subject: [PATCH 2/4] added idle delay counter (untested). this will not disable the shutdowninhibitor until the counter is empty. --- inhibit_shutdown.py | 20 ++++++++++++++------ resources/settings.xml | 2 ++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/inhibit_shutdown.py b/inhibit_shutdown.py index 38ac51e..2293e11 100644 --- a/inhibit_shutdown.py +++ b/inhibit_shutdown.py @@ -19,15 +19,15 @@ def port_set(string): def log(msg): 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,8 +40,8 @@ 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)): + if ((local_addr != remote_addr) and (local_port in watchremote)) or \ + ((local_addr == remote_addr) and (local_port in watclocal)): log("Found connection from {} to {}:{}".format(remote_addr, local_addr, local_port)) return True @@ -57,6 +57,9 @@ def check_services(): sleep_time = 60 * 1000 watched_local = port_set(s('localports')) watched_remote = port_set(s('remoteports')) +# useless double conversion here, but prevents slightly against idiot input +counterdefault = int(float(s('idlecount'))) +counter = counterdefault log("Watching for remote connections to ports {} and for local connections to ports {}, sleep time is {:0.2f} s.".format( ', '.join(str(x) for x in watched_remote), @@ -64,8 +67,13 @@ def check_services(): sleep_time / 1000.0)) while not xbmc.abortRequested: - if check_services(): + if check_services(watched_local, watched_remote): 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 + log("Delay counter is: %i. Not changing InhibitIdleShutdown.") else: + log("Setting InhibitIdleShutdown to false") xbmc.executebuiltin('InhibitIdleShutdown(false)') xbmc.sleep(sleep_time) diff --git a/resources/settings.xml b/resources/settings.xml index e5a5b9b..037228c 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -4,5 +4,7 @@ + + From 934f92f048bd30940032c919c58d21ee6e473407 Mon Sep 17 00:00:00 2001 From: Hans van Schoot Date: Thu, 6 Mar 2014 08:50:04 +0100 Subject: [PATCH 3/4] A lot of changes. Fixed xbmc shutdown delay, added transmission torrents monitor, added lockfile support, added an option to set a delay before allowing the shutdown again. --- README | 10 ++-- addon.xml | 2 +- inhibit_shutdown.py | 122 ++++++++++++++++++++++++++++++++--------- resources/settings.xml | 9 ++- 4 files changed, 109 insertions(+), 34 deletions(-) diff --git a/README b/README index 7e1cd44..3981799 100644 --- a/README +++ b/README @@ -1,8 +1,8 @@ cloned this xbmc inhibit shutdown script. originally it blocks shutdown on active tcp connections. -I'll be adding features such as: --inhibit shutdown on torrent downloads (Transmission) --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) --... - +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..57d6ee3 100644 --- a/addon.xml +++ b/addon.xml @@ -1,5 +1,5 @@ - + diff --git a/inhibit_shutdown.py b/inhibit_shutdown.py index 2293e11..662d296 100644 --- a/inhibit_shutdown.py +++ b/inhibit_shutdown.py @@ -5,6 +5,9 @@ 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 def port_set(string): ret = set() @@ -16,8 +19,9 @@ 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(watchlocal, watchremote): """ Check if any of the watched services is running. """ @@ -41,39 +45,103 @@ def check_services(watchlocal, watchremote): local_port = int(local_port) if ((local_addr != remote_addr) and (local_port in watchremote)) or \ - ((local_addr == remote_addr) and (local_port in watclocal)): - log("Found connection from {} to {}:{}".format(remote_addr, local_addr, local_port)) + ((local_addr == remote_addr) and (local_port in watchlocal)): + mylog("Found connection from {} to {}:{}".format(remote_addr, local_addr, local_port)) return True - log("No connection found.") + 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 + +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 -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')) -# useless double conversion here, but prevents slightly against idiot input -counterdefault = int(float(s('idlecount'))) +def getSettings(): + 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 + +getSettings() 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(watched_local, watched_remote): - 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 - log("Delay counter is: %i. Not changing InhibitIdleShutdown.") - else: - log("Setting InhibitIdleShutdown to false") - xbmc.executebuiltin('InhibitIdleShutdown(false)') - xbmc.sleep(sleep_time) + for i in range(sleep_time): + if xbmc.abortRequested: break + getSettings() + 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 037228c..e3a2db6 100644 --- a/resources/settings.xml +++ b/resources/settings.xml @@ -1,10 +1,17 @@ - + + + + + + + + From 45040edc95f56931cb3a49804a320ab074ae8e88 Mon Sep 17 00:00:00 2001 From: Hans van Schoot Date: Thu, 6 Mar 2014 09:05:08 +0100 Subject: [PATCH 4/4] merged the immmediate settings loading code --- addon.xml | 6 +++--- inhibit_shutdown.py | 12 +++++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/addon.xml b/addon.xml index 57d6ee3..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 662d296..6adc453 100644 --- a/inhibit_shutdown.py +++ b/inhibit_shutdown.py @@ -9,6 +9,12 @@ 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() for port in re.findall("[0-9]+", string): @@ -90,7 +96,7 @@ def check_all(watchlocal=set(), watchremote=set(), lockfilelist=[], transmission return True return False -def getSettings(): +def load_settings(): global sleep_time, watched_local, watched_remote, counterdefault, addon global lockfilepaths, transmisionMinimalSpeed , transmissionCmd, debugMe @@ -121,7 +127,7 @@ def getSettings(): debugMe = s('debugme') == 'true' #FIXME: I need to check if transmission-remote always returns kb/s -getSettings() +load_settings() counter = counterdefault mylog("Watching for remote connections to ports {} and for local connections to ports {}, sleep time is {} s.".format( @@ -132,7 +138,7 @@ def getSettings(): while not xbmc.abortRequested: for i in range(sleep_time): if xbmc.abortRequested: break - getSettings() + load_settings() if i==0: if check_all(watched_local, watched_remote, lockfilepaths, transmissionCmd, transmisionMinimalSpeed): mylog("Setting InhibitIdleShutdown to true")