Changeset - ab7b40d20af0
[Not reviewed]
default
0 5 0
Drew Perttula - 9 years ago 2016-06-10 12:09:59
drewp@bigasterisk.com
rewrite theaterConfig to a better data format
Ignore-this: 54bc8ed67a85adb2e96334c2a917c83b
5 files changed with 67 insertions and 81 deletions:
0 comments (0 inline, 0 general)
bin/collector
Show inline comments
 
@@ -61,8 +61,8 @@ def startZmq(port, collector):
 
def launch(graph):
 

	
 
    # todo: drive outputs with config files
 
    outputs = [EnttecDmx(L9['output/dmx0/'], 100, '/dev/dmx0'),
 
               Udmx(L9['output/udmx/'], 100)]
 
    outputs = [EnttecDmx(L9['output/dmx0/'], '/dev/dmx0'),
 
               Udmx(L9['output/udmx/'])]
 
    c = Collector(graph, outputs)
 

	
 
    server = WebServer(c)
light9/collector/collector.py
Show inline comments
 
@@ -9,35 +9,25 @@ log = logging.getLogger('collector')
 

	
 
def outputMap(graph, outputs):
 
    """From rdf config graph, compute a map of
 
       (device, attr) : (output, index)
 
       (device, outputattr) : (output, index)
 
    that explains which output index to set for any device update.
 
    """
 
    ret = {}
 

	
 
    outIndex = {} # port : (output, index)
 
    outputByUri = {}  # universeUri : output
 
    for out in outputs:
 
        for index, uri in out.allConnections():
 
            outIndex[uri] = (out, index)
 
        outputByUri[out.uri] = out
 

	
 
    for dev in graph.subjects(RDF.type, L9['Device']):
 
        for attr, connectedTo in graph.predicate_objects(dev):
 
            if attr == RDF.type:
 
                continue
 
            outputPorts = list(graph.subjects(L9['connectedTo'], connectedTo))
 
            if len(outputPorts) == 0:
 
                raise ValueError('no output port :connectedTo %r' % connectedTo)
 
            elif len(outputPorts) > 1:
 
                raise ValueError('multiple output ports (%r) :connectedTo %r' %
 
                                 (outputPorts, connectedTo))
 
            else:
 
                try:
 
                    output, index = outIndex[outputPorts[0]]
 
                except KeyError:
 
                    log.warn('skipping %r', outputPorts[0])
 
                    continue
 
            ret[(dev, attr)] = output, index
 
            log.debug('outputMap (%r, %r) -> %r, %r', dev, attr, output, index)
 
    
 
    for dc in graph.subjects(RDF.type, L9['DeviceClass']):
 
        for dev in graph.subjects(RDF.type, dc):
 
            output = outputByUri[graph.value(dev, L9['dmxUniverse'])]
 
            dmxBase = int(graph.value(dev, L9['dmxBase']).toPython())
 
            for row in graph.objects(dc, L9['attr']):
 
                outputAttr = graph.value(row, L9['outputAttr'])
 
                offset = int(graph.value(row, L9['dmxOffset']).toPython())
 
                index = dmxBase + offset - 1
 
                ret[(dev, outputAttr)] = (output, index)
 
                log.info('map %s,%s to %s,%s', dev, outputAttr, output, index)
 
    return ret
 
        
 
class Collector(object):
 
@@ -52,10 +42,9 @@ class Collector(object):
 
    def rebuildOutputMap(self):
 
        self.outputMap = outputMap(self.graph, self.outputs) # (device, attr) : (output, index)
 
        self.deviceType = {} # uri: type that's a subclass of Device
 
        for dev in self.graph.subjects(RDF.type, L9['Device']):
 
            for t in self.graph.objects(dev, RDF.type):
 
                if t != L9['Device']:
 
                    self.deviceType[dev] = t
 
        for dc in self.graph.subjects(RDF.type, L9['DeviceClass']):
 
            for dev in self.graph.subjects(RDF.type, dc):
 
                self.deviceType[dev] = dc
 

	
 
    def _forgetStaleClients(self, now):
 
        staleClients = []
 
@@ -97,27 +86,33 @@ class Collector(object):
 
        self.lastRequest[client] = (clientSession, now, prevClientSettings)
 

	
 

	
 
        deviceAttrs = {} # device: {attr: value}
 
        deviceAttrs = {} # device: {deviceAttr: value}
 
        for _, _, lastSettings in self.lastRequest.itervalues():
 
            for (device, attr), value in lastSettings.iteritems():
 
            for (device, deviceAttr), value in lastSettings.iteritems():
 
                attrs = deviceAttrs.setdefault(device, {})
 
                if attr in attrs:
 
                    value = resolve(device, attr, [attrs[attr], value])
 
                attrs[attr] = value
 
                if deviceAttr in attrs:
 
                    value = resolve(device, deviceAttr, [attrs[deviceAttr],
 
                                                         value])
 
                attrs[deviceAttr] = value
 

	
 
        outputAttrs = {} # device: {attr: value}
 
        outputAttrs = {} # device: {outputAttr: value}
 
        for d in deviceAttrs:
 
            outputAttrs[d] = toOutputAttrs(self.deviceType[d], deviceAttrs[d])
 
            try:
 
                devType = self.deviceType[d]
 
            except KeyError:
 
                log.warn("request for output to unconfigured device %s" % d)
 
                continue
 
            outputAttrs[d] = toOutputAttrs(devType, deviceAttrs[d])
 
        
 
        pendingOut = {} # output : values
 
        for device, attrs in outputAttrs.iteritems():
 
            for attr, value in attrs.iteritems():
 
                self.setAttr(device, attr, value, pendingOut)
 
            for outputAttr, value in attrs.iteritems():
 
                self.setAttr(device, outputAttr, value, pendingOut)
 

	
 
        self.flush(pendingOut)
 

	
 
    def setAttr(self, device, attr, value, pendingOut):
 
        output, index = self.outputMap[(device, attr)]
 
    def setAttr(self, device, outputAttr, value, pendingOut):
 
        output, index = self.outputMap[(device, outputAttr)]
 
        outList = pendingOut.setdefault(output, [])
 
        setListElem(outList, index, value, combine=max)
 

	
light9/collector/device.py
Show inline comments
 
@@ -47,9 +47,9 @@ def resolve(deviceType, deviceAttr, valu
 
    
 
def toOutputAttrs(deviceType, deviceAttrSettings):
 
    """
 
    Given settings like {L9['color']: Literal('#ff0000')}, return a
 
    similar dict where the keys are output attrs and the values are
 
    suitable for Collector.setAttr
 
    Given device attr settings like {L9['color']: Literal('#ff0000')},
 
    return a similar dict where the keys are output attrs (like
 
    L9['red']) and the values are suitable for Collector.setAttr
 
    """
 
    if deviceType == L9['ChauvetColorStrip']:
 
        color = deviceAttrSettings.get(L9['color'], '#000000')
light9/collector/output.py
Show inline comments
 
@@ -48,13 +48,8 @@ class Output(object):
 

	
 

	
 
class DmxOutput(Output):
 
    def __init__(self, baseUri, channels):
 
        self.baseUri = baseUri
 
        self.channels = channels
 

	
 
    def allConnections(self):
 
        return ((i, URIRef('%sc%s' % (self.baseUri, i + 1)))
 
                for i in range(self.channels))
 
    def __init__(self, uri):
 
        self.uri = uri
 

	
 
    def flush(self):
 
        pass
 
@@ -65,8 +60,8 @@ class EnttecDmx(DmxOutput):
 
                              scales.PmfStat('write'),
 
                              scales.PmfStat('update'))
 

	
 
    def __init__(self, baseUri, channels, devicePath='/dev/dmx0'):
 
        DmxOutput.__init__(self, baseUri, channels)
 
    def __init__(self, uri, devicePath='/dev/dmx0'):
 
        DmxOutput.__init__(self, uri)
 

	
 
        sys.path.append("dmx_usb_module")
 
        from dmx import Dmx
 
@@ -95,8 +90,8 @@ class Udmx(DmxOutput):
 
                              scales.PmfStat('update'),
 
                              scales.PmfStat('write'),
 
                              scales.IntStat('usbErrors'))
 
    def __init__(self, baseUri, channels):
 
        DmxOutput.__init__(self, baseUri, channels)
 
    def __init__(self, uri):
 
        DmxOutput.__init__(self, uri)
 
        
 
        from light9.io.udmx import Udmx
 
        self.dev = Udmx()
show/dance2016/theaterLightConfig.n3
Show inline comments
 
@@ -3,34 +3,30 @@
 
@prefix udmx: <http://light9.bigasterisk.com/output/udmx/> .
 
@prefix dmx0: <http://light9.bigasterisk.com/output/dmx0/> .
 

	
 
dmx0:c87 :connectedTo dev:colorStripMode .
 
dmx0:c88 :connectedTo dev:colorStripRed .
 
dmx0:c89 :connectedTo dev:colorStripGreen .
 
dmx0:c90 :connectedTo dev:colorStripBlue .
 

	
 
dev:colorStrip a :ChauvetColorStrip, :Device;
 
  :mode dev:colorStripMode;
 
  :red dev:colorStripRed;
 
  :green dev:colorStripGreen;
 
  :blue dev:colorStripBlue .
 
:ChauvetColorStrip a :DeviceClass .
 
:ChauvetColorStrip :attr :ccsa0 . :ccsa0 :outputAttr :mode;  :dmxOffset 0 .
 
:ChauvetColorStrip :attr :ccsa1 . :ccsa1 :outputAttr :red;   :dmxOffset 1 .
 
:ChauvetColorStrip :attr :ccsa2 . :ccsa2 :outputAttr :green; :dmxOffset 2 .
 
:ChauvetColorStrip :attr :ccsa3 . :ccsa3 :outputAttr :blue;  :dmxOffset 3 .
 

	
 
# All these bnodes don't refresh well, but they need to be rewritten
 
# as offsets from a single dmx start index, and they need to be
 
# inherited with the device type
 
dev:moving1 a :Mini15, :Device;
 
  :xRotation      [ is :connectedTo of udmx:c5 ];
 
  :xFine          [ is :connectedTo of udmx:c6 ];
 
  :yRotation      [ is :connectedTo of udmx:c7 ];
 
  :yFine          [ is :connectedTo of udmx:c8 ];
 
  :rotationSpeed  [ is :connectedTo of udmx:c9 ];
 
  :dimmer         [ is :connectedTo of udmx:c10 ];
 
  :red            [ is :connectedTo of udmx:c11 ];
 
  :green          [ is :connectedTo of udmx:c12 ];
 
  :blue           [ is :connectedTo of udmx:c13 ];
 
  :colorChange    [ is :connectedTo of udmx:c14 ];
 
  :colorSpeed     [ is :connectedTo of udmx:c15 ];
 
  :goboShake      [ is :connectedTo of udmx:c16 ];
 
  :goboChoose     [ is :connectedTo of udmx:c17 ] .
 
:Mini15 a :DeviceClass .
 
:Mini15 :attr :Mini15a0 .  :Mini15a0  :outputAttr :xRotation;     :dmxOffset 0 .
 
:Mini15 :attr :Mini15a1 .  :Mini15a1  :outputAttr :xFine;         :dmxOffset 1 .
 
:Mini15 :attr :Mini15a2 .  :Mini15a2  :outputAttr :yRotation;     :dmxOffset 2 .
 
:Mini15 :attr :Mini15a3 .  :Mini15a3  :outputAttr :yFine;         :dmxOffset 3 .
 
:Mini15 :attr :Mini15a4 .  :Mini15a4  :outputAttr :rotationSpeed; :dmxOffset 4 .
 
:Mini15 :attr :Mini15a5 .  :Mini15a5  :outputAttr :dimmer;        :dmxOffset 5 .
 
:Mini15 :attr :Mini15a6 .  :Mini15a6  :outputAttr :red;           :dmxOffset 6 .
 
:Mini15 :attr :Mini15a7 .  :Mini15a7  :outputAttr :green;         :dmxOffset 7 .
 
:Mini15 :attr :Mini15a8 .  :Mini15a8  :outputAttr :blue;          :dmxOffset 8 .
 
:Mini15 :attr :Mini15a9 .  :Mini15a9  :outputAttr :colorChange;   :dmxOffset 9 .
 
:Mini15 :attr :Mini15a10 . :Mini15a10 :outputAttr :colorSpeed;    :dmxOffset 10 .
 
:Mini15 :attr :Mini15a11 . :Mini15a11 :outputAttr :goboShake;     :dmxOffset 11 .
 
:Mini15 :attr :Mini15a12 . :Mini15a12 :outputAttr :goboChoose;    :dmxOffset 12 .
 

	
 
dev:colorStrip a :ChauvetColorStrip; :dmxUniverse dmx0:; :dmxBase 87 .
 

	
 
dev:moving1 a :Mini15; :dmxUniverse udmx:; :dmxBase 1 .
 

	
 
# [ :name "cyc-right"; :output dmx:c42 ] .
 
# [ :name "cyc-mid"; :output dmx:c43 ] .
0 comments (0 inline, 0 general)