Advertisement
Guest User

Untitled

a guest
Nov 15th, 2013
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.34 KB | None | 0 0
  1. import sys, os, socket, telnetlib, time, subprocess
  2. import xbmc, xbmcaddon, xbmcgui, xbmcplugin
  3.  
  4. Addon = xbmcaddon.Addon(id="vdr.powersave")
  5.  
  6.  
  7.  
  8. class Main:
  9.     _base = sys.argv[0]
  10.     _enum_forerun = [1,2,5,10,15,20]
  11.     _enum_overrun = [1,2,5,10,15,20]
  12.     _enum_idle= [5,10,15,20,25,30,40,50,60,90,120,180,240,300,360,420,480,540,600]
  13.     _sleep_interval = 60000
  14.     _poll_interval = 6
  15.     _timers = {}
  16.     _lastWakeup = 0
  17.     _idleTime = 0
  18.     _lastIdleTime = 0
  19.     _realIdleTime = 0
  20.     _isLoggedOn = False
  21.     _lastPlaying = False
  22.     _isPlaying = False
  23.     _lastRecording = False
  24.     _isRecording = False
  25.  
  26.     # main routine
  27.     def __init__(self):
  28.         print "vdr.powersave: Plugin started"
  29.         self.getSettings()
  30.         self.getTimers()
  31.         pollCounter = self._poll_interval
  32.         # main loop
  33.         while (not xbmc.abortRequested):
  34.             # reload timers periodically
  35.             if (pollCounter > self._poll_interval):
  36.                 pollCounter = 0
  37.                 self.getTimers()
  38.             else:
  39.                 pollCounter = pollCounter + 1
  40.                
  41.             # set wakeup
  42.             self.setWakeup()
  43.            
  44.             # time warp calculations demands to have our own idle timers
  45.             self._lastIdleTime = self._idleTime
  46.             self._idleTime = xbmc.getGlobalIdleTime()
  47.             if (self._idleTime > self._lastIdleTime):
  48.                 self._realIdleTime = self._realIdleTime + (self._idleTime - self._lastIdleTime)
  49.             else:
  50.                 self._realIdleTime = self._idleTime
  51.  
  52.             # notice changes in playback
  53.             self._lastPlaying = self._isPlaying
  54.             self._isPlaying = xbmc.Player().isPlaying()
  55.  
  56.             # now this one is tricky: a playback ended, idle would suggest to powersave, but we set the clock back for overrun.
  57.             # Otherwise xbmc could sleep instantly at the end of a movie
  58.             if (self._lastPlaying  == True) & (self._isPlaying == False) & (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  59.                 self._realIdleTime = self.settings['vdrps_sleepmode_after'] - self.settings['vdrps_overrun']
  60.                 #print "vdr.powersave: playback stopped!"
  61.  
  62.             # notice changes in recording
  63.             self._lastRecording = self._isRecording
  64.             self._isRecording = self.getIsRecording()
  65.  
  66.             # same trick, for recording issues - gives time to postprocess
  67.             if (self._lastRecording  == True) & (self._isRecording == False) & (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  68.                 self._realIdleTime = self.settings['vdrps_sleepmode_after'] - self.settings['vdrps_overrun']
  69.  
  70.            
  71.            
  72.             #print "vdr.powersave: Mark"
  73.  
  74.             # powersave checks ...
  75.  
  76.             if (self.settings['vdrps_sleepmode'] > 0) & \
  77.                (self._realIdleTime >= self.settings['vdrps_sleepmode_after']):
  78.                 # sleeping time already?
  79.                 if (self._isPlaying):
  80.                     print "vdr.powersave: powersave postponed - xbmc is playing ..."
  81.                 elif (self._isRecording):
  82.                     print "vdr.powersave: powersave postponed - vdr is recording ..."
  83.                 elif (check_services()):
  84.                             print "vdr.powersave: powersave postponed - Network activity ..."
  85.                 elif (self.getIsRecordPending()):
  86.                     print "vdr.powersave: powersave postponed - record upcomming ..."
  87.                 else:
  88.                     if (self.settings['vdrps_sleepmode'] == 1):
  89.                         #print "vdr.powersave: initiating sleepmode S3 ..."
  90.                         xbmc.executebuiltin('Suspend')
  91.                     elif (self.settings['vdrps_sleepmode'] == 2):
  92.                         #print "vdr.powersave: initiating sleepmode S4 ..."
  93.                         xbmc.executebuiltin('Hibernate')
  94.                     elif (self.settings['vdrps_sleepmode'] == 3):
  95.                         #print "vdr.powersave: initiating powerdown ..."
  96.                         xbmc.executebuiltin('Powerdown')
  97.            
  98.            
  99.             # Disabled due to bugged service abort on logouts
  100.             # are we logged on? (Dialog <> 10029)          
  101.             #self._isLoggedOn = (xbmcgui.getCurrentWindowId()<>10029)
  102.             # check for automatic logout ...
  103.             #if (self.settings['vdrps_autologout'] == "true") & \
  104.                #(self._idleTime > self.settings['vdrps_autologout_after']) & \
  105.                #self._isLoggedOn:
  106.                 ## logging out is safe
  107.                 #xbmc.executebuiltin('System.LogOff')
  108.            
  109.            
  110.             # sleep a little ...
  111.             xbmc.sleep(self._sleep_interval)
  112.         # last second check
  113. #       self.getTimers()
  114.         # last second alarm clock
  115.         self.setWakeup()
  116.         print "vdr.powersave: Plugin exited"
  117.        
  118.     # get settings from xbmc
  119.     def getSettings(self):
  120.         print "vdr.powersave: Getting settings ..."
  121.         self.settings = {}
  122.         self.settings['vdrps_host'] = Addon.getSetting('vdrps_host')
  123.         self.settings['vdrps_port'] = int(Addon.getSetting('vdrps_port'))
  124.         self.settings['vdrps_forerun'] = self._enum_forerun[int(Addon.getSetting('vdrps_forerun'))] * 60
  125.         self.settings['vdrps_wakecmd'] = Addon.getSetting('vdrps_wakecmd')
  126.         self.settings['vdrps_overrun'] = self._enum_forerun[int(Addon.getSetting('vdrps_overrun'))] * 60
  127.         # Disabled due to bugged service abort on logouts
  128.         #self.settings['vdrps_autologout'] = Addon.getSetting('vdrps_autologout')
  129.         #self.settings['vdrps_autologout_after'] = self._enum_idle[int(Addon.getSetting('vdrps_autologout_after'))] * 60
  130.         self.settings['vdrps_sleepmode'] = int(Addon.getSetting('vdrps_sleepmode'))
  131.         self.settings['vdrps_sleepmode_after'] = self._enum_idle[int(Addon.getSetting('vdrps_sleepmode_after'))] * 60
  132.         self.settings['vdrps_dailywakeup'] = Addon.getSetting('vdrps_dailywakeup')
  133.         self.settings['vdrps_dailywakeup_time'] = int(Addon.getSetting('vdrps_dailywakeup_time')) * 1800
  134.  
  135.     # get timers from vdr
  136.     def getTimers(self):
  137.         #print "vdr.powersave: Getting timers ..."
  138.         # contact SVDRP and parse resopnse
  139.         raw = self._querySVDRP(self.settings['vdrps_host'], self.settings['vdrps_port'])
  140.         # parse when get a response
  141.         if (raw != None):
  142.             self._parseSVDRP(raw)
  143.  
  144.     # set the alarm clock if necessary
  145.     def setWakeup(self):
  146.         # calculate next wakeup time
  147.         stampWakeup = self.getMostRecentTimer() - self.settings['vdrps_forerun']
  148.         stampNow = int(time.time())
  149.         # some extra calculations for daily wakeing
  150.         if (self.settings['vdrps_dailywakeup'] == "true"):
  151.             # extract date and time only
  152.             tupleNow = time.localtime(stampNow)
  153.             stampTimeOnly = (tupleNow.tm_hour*3600)+(tupleNow.tm_min*60)+tupleNow.tm_sec
  154.             stampDateOnly = time.mktime((tupleNow.tm_year,tupleNow.tm_mon,tupleNow.tm_mday,0,0,0,tupleNow.tm_wday,tupleNow.tm_yday,tupleNow.tm_isdst))
  155.  
  156.             # wake me today, or tomorrow?
  157.             if (self.settings['vdrps_dailywakeup_time'] > stampTimeOnly):
  158.                 stampDailyWakeup = stampDateOnly + self.settings['vdrps_dailywakeup_time']
  159.             else:
  160.                 # add a whole day
  161.                 stampDailyWakeup = stampDateOnly + self.settings['vdrps_dailywakeup_time'] + 86400
  162.  
  163.             # daily wakeup is before next timer, so set the alarm clock to it
  164.             if (stampDailyWakeup<stampWakeup):
  165.                 stampWakeup = stampDailyWakeup
  166.        
  167.         # is it in the future and not already set?
  168.         if (stampWakeup>stampNow) & (stampWakeup <> self._lastWakeup):
  169.             # yes we do have to wakeup
  170.             print "vdr.powersave: Wake up on timestamp %d (%s)" % (stampWakeup, time.asctime(time.localtime(stampWakeup)) )
  171.             # call the alarm script
  172.             os.system("%s %d" % (self.settings['vdrps_wakecmd'],stampWakeup))
  173.             # remember the stamp, not to call alarm script twice with the same value
  174.             self._lastWakeup = stampWakeup
  175.            
  176.     # contact SVDRP service and get raw timers
  177.     def _querySVDRP(self, host, port):
  178.         try:
  179.             tndata = None
  180.             # getting in contact
  181.             tnsession = telnetlib.Telnet(host,port,5)
  182.             try:
  183.                 # sending commands
  184.                 tnsession.write("LSTT\n")
  185.                 tnsession.write("QUIT\n")
  186.                 # getting data
  187.                 tndata = tnsession.read_until("closing connection")
  188.             finally:
  189.                 # clean up our mess, and get back
  190.                 tnsession.close()
  191.                 return tndata
  192.  
  193.         except:
  194.             # made a boo boo
  195.             print "vdr.powersave: cannot get list of timers from %s:%s " % (host, port)
  196.             return None
  197.            
  198.     # this function parses the SVDRP session dump for timers and returns a dictonary with status
  199.     def _parseSVDRP(self, raw):
  200.         # empty result list
  201.         timers = {}
  202.         # loop thru lines
  203.         for line in raw.splitlines():
  204.             # as we know timers getting returned with status 250 (ok)
  205.             if line.startswith("250"):
  206.                 try:
  207.                     # get into the fields
  208.                     fields = line[4:].split(":")
  209.                     # check the timer status (flags 1: enabled, 2, instant record, 4, vps, 8: active)
  210.                     timer_status = fields[0].split(" ")[1]
  211.                     # decode starting time
  212.                     timer_start = int(time.mktime(time.strptime(fields[2]+fields[3], "%Y-%m-%d%H%M")))
  213.                     # fill the timer dictonary
  214.                     if timer_start>0:
  215.                         timers[timer_start] = int(timer_status)
  216.                 except:
  217.                     # some lines may fail
  218.                     print "vdr.powersave: unable to parse line '%s' " % (line)
  219.         self._timers = timers
  220.  
  221.     # returns if any timer is actually recording
  222.     def getIsRecording(self):
  223.         for status in self._timers.values():
  224.             if (status & 8) == 8:
  225.                 return True
  226.         return False;
  227.        
  228.     # returns if a record is upcomming within forerun, or idle time to prevent powersave
  229.     def getIsRecordPending(self):
  230.         # decide which period lasts longer
  231.         if (self.settings['vdrps_forerun'] > self.settings['vdrps_sleepmode_after']):
  232.             delta = self.settings['vdrps_forerun']
  233.         else:
  234.             # odd people may set the recording prerun smaller than idle time
  235.             delta = self.settings['vdrps_sleepmode_after']
  236.         # we need the stamps
  237.         stamps = self._timers.keys()
  238.         stampNow = int(time.time())
  239.         for stamp in stamps:
  240.             if (self._timers[stamp] & 1 == 1) & (stamp-delta < stampNow ):
  241.                 # there is a record upcomming
  242.                 return True
  243.         return False
  244.  
  245.     # this returns the most recent enabled timestamp, or None
  246.     def getMostRecentTimer(self):
  247.         # we need a sorted list of the timestamps
  248.         stamps = self._timers.keys()
  249.         stamps.sort()
  250.         # now search for the first enabled one
  251.         for stamp in stamps:
  252.             if self._timers[stamp] & 1 == 1:
  253.                 return int(stamp)
  254.         return 0;
  255.  
  256. # Set of (protocol, local port) tuples.
  257. watched = {
  258.     ('tcp', 22), # SSH
  259.     ('tcp', 3000), # streamdev
  260.     ('tcp', 34892), # vnsi5
  261.     ('tcp', 34890), # vnsi
  262.     ('tcp', 49952), # torrent
  263.     ('tcp', 8082), # sickger
  264.     ('tcp', 8081), # sickbeard
  265.     ('tcp', 5000), # couch
  266.     ('tcp', 8080), # sab
  267.     ('tcp', 1935), # rtmp
  268.     ('tcp', 56680), # ftp
  269.     }
  270.  
  271. def check_services():
  272.     netstat = subprocess.check_output(['/bin/netstat', '--protocol=inet', '-n'], universal_newlines=True)
  273.  
  274.     for line in netstat.split('\n')[2:]:
  275.         items = line.split()
  276.         if len(items) < 4:
  277.             continue
  278.  
  279.         proto = items[0]
  280.         port = int(items[3].split(':')[-1])
  281.  
  282.         if (proto, port) in watched:
  283.             print("vdr.powersave: Found {} connection from {} to port {}".format(proto, items[4], port))
  284.             return True
  285.  
  286.     return False
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement