Mercurial > code > home > repos > light9
comparison light8/dmxserver.py @ 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 | 2c25a69c084d |
children | 8e6165bc1ca5 |
comparison
equal
deleted
inserted
replaced
133:e7b531d10cf9 | 134:f2f73a2171e6 |
---|---|
40 self.clientfreq={} # clientID : updatefreq | 40 self.clientfreq={} # clientID : updatefreq |
41 | 41 |
42 self.combinedlevels=[] # list of levels, after max'ing the clients | 42 self.combinedlevels=[] # list of levels, after max'ing the clients |
43 self.clientschanged=1 # have clients sent anything since the last send? | 43 self.clientschanged=1 # have clients sent anything since the last send? |
44 self.options=options | 44 self.options=options |
45 self.lastupdate=0 # time of last dmx send | |
46 self.laststatsprint=0 # time | |
47 | |
48 # desired seconds between sendlevels() calls | |
49 self.calldelay=1/options.updates_per_sec | |
45 | 50 |
46 print "starting parport connection" | 51 print "starting parport connection" |
47 self.parportdmx=ParportDMX() | 52 self.parportdmx=ParportDMX() |
48 self.parportdmx.golive() | 53 self.parportdmx.golive() |
49 | 54 |
50 # start the loop | 55 self.updatefreq=Updatefreq() # freq of actual dmx sends |
51 self.updatefreq=Updatefreq() | |
52 self.num_unshown_updates=None | 56 self.num_unshown_updates=None |
53 self.lastshownlevels=None | 57 self.lastshownlevels=None |
58 # start the loop | |
54 self.sendlevels() | 59 self.sendlevels() |
60 | |
61 # the other loop | |
62 self.purgeclients() | |
55 | 63 |
56 | |
57 def purgeclients(self): | 64 def purgeclients(self): |
58 | 65 |
59 """forget about any clients who haven't sent levels in a while | 66 """forget about any clients who haven't sent levels in a while |
60 (5 seconds)""" | 67 (5 seconds). this runs in a loop""" |
68 | |
69 purge_age=10 # seconds | |
70 | |
71 reactor.callLater(1,self.purgeclients) | |
72 | |
61 now=time.time() | 73 now=time.time() |
62 for cid,lastseen in self.lastseen.items(): | 74 for cid,lastseen in self.lastseen.items(): |
63 if lastseen<now-5: | 75 if lastseen<now-purge_age: |
64 print "forgetting client %s (no activity for 5sec)" % cid | 76 print ("forgetting client %s (no activity for %s sec)" % |
77 (cid,purge_age)) | |
65 del self.clientlevels[cid] | 78 del self.clientlevels[cid] |
66 del self.lastseen[cid] | 79 del self.lastseen[cid] |
67 del self.clientfreq[cid] | 80 del self.clientfreq[cid] |
68 | 81 |
69 def sendlevels(self): | 82 def sendlevels(self): |
70 reactor.callLater(1/20,self.sendlevels) | 83 |
84 """sends to dmx if levels have changed, or if we havent sent | |
85 in a while""" | |
86 | |
87 reactor.callLater(self.calldelay,self.sendlevels) | |
88 | |
71 if self.clientschanged: | 89 if self.clientschanged: |
72 # recalc levels | 90 # recalc levels |
73 | 91 |
74 self.purgeclients() | |
75 self.calclevels() | 92 self.calclevels() |
76 | 93 |
77 if (self.num_unshown_updates is None or # first time | 94 if (self.num_unshown_updates is None or # first time |
78 self.options.fast_updates or # show always | 95 self.options.fast_updates or # show always |
79 (self.combinedlevels!=self.lastshownlevels and # changed | 96 (self.combinedlevels!=self.lastshownlevels and # changed |
82 self.printlevels() | 99 self.printlevels() |
83 self.lastshownlevels=self.combinedlevels[:] | 100 self.lastshownlevels=self.combinedlevels[:] |
84 else: | 101 else: |
85 self.num_unshown_updates+=1 | 102 self.num_unshown_updates+=1 |
86 | 103 |
87 if (self.num_unshown_updates-1)%50==0: | 104 if time.time()>self.laststatsprint+2: |
105 self.laststatsprint=time.time() | |
88 self.printstats() | 106 self.printstats() |
89 | |
90 self.sendlevels_dmx() | |
91 | 107 |
108 if self.clientschanged or time.time()>self.lastupdate+1: | |
109 self.lastupdate=time.time() | |
110 self.sendlevels_dmx() | |
111 | |
112 self.clientschanged=0 # clear the flag | |
113 | |
92 def calclevels(self): | 114 def calclevels(self): |
93 """combine all the known client levels into self.combinedlevels""" | 115 """combine all the known client levels into self.combinedlevels""" |
94 self.combinedlevels=[] | 116 self.combinedlevels=[] |
95 for chan in range(0,self.parportdmx.dimmers): | 117 for chan in range(0,self.parportdmx.dimmers): |
96 x=0 | 118 x=0 |
99 # clamp client levels to 0..1 | 121 # clamp client levels to 0..1 |
100 cl=max(0,min(1,clientlist[chan])) | 122 cl=max(0,min(1,clientlist[chan])) |
101 x=max(x,cl) | 123 x=max(x,cl) |
102 self.combinedlevels.append(x) | 124 self.combinedlevels.append(x) |
103 | 125 |
104 | |
105 def printlevels(self): | 126 def printlevels(self): |
106 """write all the levels to stdout""" | 127 """write all the levels to stdout""" |
107 print "Levels:","".join(["% 2d "%(x*100) for | 128 print "Levels:","".join(["% 2d "%(x*100) for |
108 x in self.combinedlevels]) | 129 x in self.combinedlevels]) |
109 | 130 |
110 def printstats(self): | 131 def printstats(self): |
111 """print the clock, freq, etc, with a \r at the end""" | 132 """print the clock, freq, etc, with a \r at the end""" |
112 | 133 |
113 sys.stdout.write("dmxserver up at %s, [server %s] "% | 134 sys.stdout.write("dmxserver up at %s, [polls %s] "% |
114 (time.strftime("%H:%M:%S"), | 135 (time.strftime("%H:%M:%S"), |
115 str(self.updatefreq), | 136 str(self.updatefreq), |
116 )) | 137 )) |
117 for cid,freq in self.clientfreq.items(): | 138 for cid,freq in self.clientfreq.items(): |
118 sys.stdout.write("[%s %s] " % (cid,str(freq))) | 139 sys.stdout.write("[%s %s] " % (cid,str(freq))) |
119 sys.stdout.write("\r") | 140 sys.stdout.write("\r") |
120 sys.stdout.flush() | 141 sys.stdout.flush() |
121 | 142 |
122 | |
123 def sendlevels_dmx(self): | 143 def sendlevels_dmx(self): |
124 """output self.combinedlevels to dmx, and keep the updates/sec stats""" | 144 """output self.combinedlevels to dmx, and keep the updates/sec stats""" |
125 # they'll get divided by 100 | 145 # they'll get divided by 100 |
126 if self.parportdmx: | 146 if self.parportdmx: |
127 self.parportdmx.sendlevels([l*100 for l in self.combinedlevels]) | 147 self.parportdmx.sendlevels([l*100 for l in self.combinedlevels]) |
131 return x | 151 return x |
132 | 152 |
133 def xmlrpc_outputlevels(self,cid,levellist): | 153 def xmlrpc_outputlevels(self,cid,levellist): |
134 """send a unique id for your client (name+pid maybe), then | 154 """send a unique id for your client (name+pid maybe), then |
135 the variable-length dmx levellist (scaled 0..1)""" | 155 the variable-length dmx levellist (scaled 0..1)""" |
136 self.clientlevels[cid]=levellist | 156 if levellist!=self.clientlevels.get(cid,[]): |
137 self.clientschanged=1 | 157 self.clientlevels[cid]=levellist |
138 if cid not in self.lastseen: | 158 self.clientschanged=1 |
139 print "hello new client %s" % cid | 159 if cid not in self.lastseen: |
140 self.clientfreq[cid]=Updatefreq() | 160 print "hello new client %s" % cid |
161 self.clientfreq[cid]=Updatefreq() | |
162 | |
141 self.lastseen[cid]=time.time() | 163 self.lastseen[cid]=time.time() |
142 self.clientfreq[cid].update() | 164 self.clientfreq[cid].update() |
143 return "ok" | 165 return "ok" |
144 | 166 |
145 parser=OptionParser() | 167 parser=OptionParser() |
146 parser.add_option("-f","--fast-updates",action='store_true', | 168 parser.add_option("-f","--fast-updates",action='store_true', |
147 help=('display all dmx output to stdout instead ' | 169 help=('display all dmx output to stdout instead ' |
148 'of the usual reduced output')) | 170 'of the usual reduced output')) |
171 parser.add_option("-r","--updates-per-sec",type='float',default=20, | |
172 help=('dmx output frequency')) | |
149 (options,songfiles)=parser.parse_args() | 173 (options,songfiles)=parser.parse_args() |
174 | |
175 print options | |
150 | 176 |
151 print "starting xmlrpc server on port 8030" | 177 print "starting xmlrpc server on port 8030" |
152 reactor.listenTCP(8030,server.Site(XMLRPCServe(options))) | 178 reactor.listenTCP(8030,server.Site(XMLRPCServe(options))) |
153 reactor.run() | 179 reactor.run() |
154 | 180 |