changeset 134:f2f73a2171e6

many adjustments to the loops and timing many adjustments to the loops and timing now sends the hardware updates only when clients change, but at least 1Hz new option to adjust the rate of the loop that considers sending changes (if the lights have changed)
author drewp
date Sat, 14 Jun 2003 14:59:09 +0000
parents e7b531d10cf9
children 5670f66845ce
files light8/dmxserver.py
diffstat 1 files changed, 45 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/light8/dmxserver.py	Sat Jun 14 14:58:53 2003 +0000
+++ b/light8/dmxserver.py	Sat Jun 14 14:59:09 2003 +0000
@@ -42,36 +42,53 @@
         self.combinedlevels=[] # list of levels, after max'ing the clients
         self.clientschanged=1 # have clients sent anything since the last send?
         self.options=options
+        self.lastupdate=0 # time of last dmx send
+        self.laststatsprint=0  # time
+
+        # desired seconds between sendlevels() calls
+        self.calldelay=1/options.updates_per_sec 
 
         print "starting parport connection"
         self.parportdmx=ParportDMX()
         self.parportdmx.golive()
 
-        # start the loop
-        self.updatefreq=Updatefreq()
+        self.updatefreq=Updatefreq() # freq of actual dmx sends
         self.num_unshown_updates=None
         self.lastshownlevels=None
+        # start the loop
         self.sendlevels()
+
+        # the other loop
+        self.purgeclients()
         
-
     def purgeclients(self):
         
         """forget about any clients who haven't sent levels in a while
-        (5 seconds)"""
+        (5 seconds). this runs in a loop"""
+
+        purge_age=10 # seconds
+        
+        reactor.callLater(1,self.purgeclients)
+
         now=time.time()
         for cid,lastseen in self.lastseen.items():
-            if lastseen<now-5:
-                print "forgetting client %s (no activity for 5sec)" % cid
+            if lastseen<now-purge_age:
+                print ("forgetting client %s (no activity for %s sec)" %
+                       (cid,purge_age))
                 del self.clientlevels[cid]
                 del self.lastseen[cid]
                 del self.clientfreq[cid]
         
     def sendlevels(self):
-        reactor.callLater(1/20,self.sendlevels)
+        
+        """sends to dmx if levels have changed, or if we havent sent
+        in a while"""
+
+        reactor.callLater(self.calldelay,self.sendlevels)
+
         if self.clientschanged:
             # recalc levels
 
-            self.purgeclients()
             self.calclevels()
          
             if (self.num_unshown_updates is None or # first time
@@ -84,11 +101,16 @@
             else:
                 self.num_unshown_updates+=1
 
-        if (self.num_unshown_updates-1)%50==0:
+        if time.time()>self.laststatsprint+2:
+            self.laststatsprint=time.time()
             self.printstats()
-            
-        self.sendlevels_dmx()
 
+        if self.clientschanged or time.time()>self.lastupdate+1:
+            self.lastupdate=time.time()
+            self.sendlevels_dmx()
+
+        self.clientschanged=0 # clear the flag
+        
     def calclevels(self):
         """combine all the known client levels into self.combinedlevels"""
         self.combinedlevels=[]
@@ -101,7 +123,6 @@
                     x=max(x,cl)
             self.combinedlevels.append(x)
 
-
     def printlevels(self):
         """write all the levels to stdout"""
         print "Levels:","".join(["% 2d "%(x*100) for
@@ -110,7 +131,7 @@
     def printstats(self):
         """print the clock, freq, etc, with a \r at the end"""
 
-        sys.stdout.write("dmxserver up at %s, [server %s] "%
+        sys.stdout.write("dmxserver up at %s, [polls %s] "%
                          (time.strftime("%H:%M:%S"),
                           str(self.updatefreq),
                           ))
@@ -119,7 +140,6 @@
         sys.stdout.write("\r")
         sys.stdout.flush()
 
-    
     def sendlevels_dmx(self):
         """output self.combinedlevels to dmx, and keep the updates/sec stats"""
         # they'll get divided by 100
@@ -133,11 +153,13 @@
     def xmlrpc_outputlevels(self,cid,levellist):
         """send a unique id for your client (name+pid maybe), then
         the variable-length dmx levellist (scaled 0..1)"""
-        self.clientlevels[cid]=levellist
-        self.clientschanged=1
-        if cid not in self.lastseen:
-            print "hello new client %s" % cid
-            self.clientfreq[cid]=Updatefreq()
+        if levellist!=self.clientlevels.get(cid,[]):
+            self.clientlevels[cid]=levellist
+            self.clientschanged=1
+            if cid not in self.lastseen:
+                print "hello new client %s" % cid
+                self.clientfreq[cid]=Updatefreq()
+                
         self.lastseen[cid]=time.time()
         self.clientfreq[cid].update()
         return "ok"
@@ -146,8 +168,12 @@
 parser.add_option("-f","--fast-updates",action='store_true',
                   help=('display all dmx output to stdout instead '
                         'of the usual reduced output'))
+parser.add_option("-r","--updates-per-sec",type='float',default=20,
+                  help=('dmx output frequency'))
 (options,songfiles)=parser.parse_args()
 
+print options
+
 print "starting xmlrpc server on port 8030"
 reactor.listenTCP(8030,server.Site(XMLRPCServe(options)))
 reactor.run()