view light8/dmxserver.py @ 116:9ddea0c614ee

much prettier stdout, including a clock (so you can tell the server's running) much prettier stdout, including a clock (so you can tell the server's running) and channel updates only when the levels change, and throttled to every 100 updates even then.
author drewp
date Fri, 13 Jun 2003 06:15:28 +0000
parents afbdae5e1359
children 2c25a69c084d
line wrap: on
line source

#!/usr/bin/python
"""

this is the only process to talk to the dmx hardware. other clients
can connect to this server and present dmx output, and this server
will max ('pile-on') all the client requests.

this server has a level display which is the final set of values that
goes to the hardware.

clients shall connect to the xmlrpc server and send:

  their PID (or some other cookie)

  a length-n list of 0..1 levels which will represent the channel
    values for the n first dmx channels.

server is port 8030; xmlrpc method is called outputlevels(pid,levellist).


todo:
  save dmx on quit and restore on restart
  if parport fails, run in dummy mode (and make an option for that too)
"""

from __future__ import division
from twisted.internet import reactor
from twisted.web import xmlrpc, server
import sys,time
from io import ParportDMX

class XMLRPCServe(xmlrpc.XMLRPC):
    def __init__(self):

        xmlrpc.XMLRPC.__init__(self)
        
        self.clientlevels={} # clientPID : list of levels
        self.combinedlevels=[] # list of levels, after max'ing the clients
        self.clientschanged=1 # have clients sent anything since the last send?

        print "starting parport connection"
        self.parportdmx=ParportDMX()
        self.parportdmx.golive()

        # start the loop
        self.num_unshown_updates=None
        self.sendlevels()


    def sendlevels(self):
        reactor.callLater(.02,self.sendlevels)
        if self.clientschanged:
            # recalc levels
            oldlevels=self.combinedlevels[:]
            self.combinedlevels=[]
            for chan in range(0,self.parportdmx.dimmers):
                x=0
                for clientlist in self.clientlevels.values():
                    if len(clientlist)>chan:
                        x=max(x,clientlist[chan])
                self.combinedlevels.append(x)

            if self.num_unshown_updates is None or (self.combinedlevels!=oldlevels and
                                                    self.num_unshown_updates>10):
                self.num_unshown_updates=0
                print "Levels:","".join(["% 2d "%x for x in self.combinedlevels])
            else:
                self.num_unshown_updates+=1

        if (self.num_unshown_updates-1)%100==0:
            sys.stdout.write("dmxserver up at %s   \r"%time.strftime("%H:%M:%S"))
            sys.stdout.flush()
        # now send combinedlevels (they'll get divided by 100)
        if self.parportdmx:
            self.parportdmx.sendlevels([l*100 for l in self.combinedlevels]) 
        
    def xmlrpc_echo(self,x):
        return x
    
    def xmlrpc_outputlevels(self,pid,levellist):
        self.clientlevels[pid]=levellist
        self.clientschanged=1
        return "ok"

print "starting xmlrpc server on port 8030"
reactor.listenTCP(8030,server.Site(XMLRPCServe()))
reactor.run()