changeset 1416:ab7b40d20af0

rewrite theaterConfig to a better data format Ignore-this: 54bc8ed67a85adb2e96334c2a917c83b
author Drew Perttula <drewp@bigasterisk.com>
date Fri, 10 Jun 2016 12:09:59 +0000
parents edc17fdcaaf1
children 9db73555b129
files bin/collector light9/collector/collector.py light9/collector/device.py light9/collector/output.py show/dance2016/theaterLightConfig.n3
diffstat 5 files changed, 67 insertions(+), 81 deletions(-) [+]
line wrap: on
line diff
--- a/bin/collector	Fri Jun 10 11:18:02 2016 +0000
+++ b/bin/collector	Fri Jun 10 12:09:59 2016 +0000
@@ -61,8 +61,8 @@
 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)
--- a/light9/collector/collector.py	Fri Jun 10 11:18:02 2016 +0000
+++ b/light9/collector/collector.py	Fri Jun 10 12:09:59 2016 +0000
@@ -9,35 +9,25 @@
 
 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 @@
     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 @@
         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)
 
--- a/light9/collector/device.py	Fri Jun 10 11:18:02 2016 +0000
+++ b/light9/collector/device.py	Fri Jun 10 12:09:59 2016 +0000
@@ -47,9 +47,9 @@
     
 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')
--- a/light9/collector/output.py	Fri Jun 10 11:18:02 2016 +0000
+++ b/light9/collector/output.py	Fri Jun 10 12:09:59 2016 +0000
@@ -48,13 +48,8 @@
 
 
 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 @@
                               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 @@
                               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()
--- a/show/dance2016/theaterLightConfig.n3	Fri Jun 10 11:18:02 2016 +0000
+++ b/show/dance2016/theaterLightConfig.n3	Fri Jun 10 12:09:59 2016 +0000
@@ -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 ] .