Changeset - 2b8a2a25b154
[Not reviewed]
default
0 3 0
drewp@bigasterisk.com - 20 months ago 2023-05-28 00:56:28
drewp@bigasterisk.com
logging
3 files changed with 3 insertions and 2 deletions:
0 comments (0 inline, 0 general)
light9/collector/collector.py
Show inline comments
 
@@ -28,96 +28,97 @@ def _outputMap(graph: SyncedGraph, outpu
 
    """
 
    ret = cast(Dict[Tuple[DeviceUri, OutputAttr], Tuple[OutputUri, DmxMessageIndex]], {})
 

	
 
    for dc in graph.subjects(RDF.type, L9['DeviceClass']):
 
        log.info('mapping devices of class %s', dc)
 
        for dev in graph.subjects(RDF.type, dc):
 
            dev = cast(DeviceUri, dev)
 
            log.info('  💡 mapping device %s', dev)
 
            universe = typedValue(OutputUri, graph, dev, L9['dmxUniverse'])
 
            if universe not in outputs:
 
                raise ValueError(f'{dev=} is configured to be in {universe=}, but we have no Output for that universe')
 
            try:
 
                dmxBase = typedValue(DmxIndex, graph, dev, L9['dmxBase'])
 
            except ValueError:
 
                raise ValueError('no :dmxBase for %s' % dev)
 

	
 
            for row in sorted(graph.objects(dc, L9['attr']), key=str):
 
                outputAttr = typedValue(OutputAttr, graph, row, L9['outputAttr'])
 
                offset = typedValue(DmxIndex, graph, row, L9['dmxOffset'])
 
                index = makeDmxMessageIndex(dmxBase, offset)
 
                ret[(dev, outputAttr)] = (universe, index)
 
                log.info(f'      {uriTail(outputAttr):15} maps to {uriTail(universe)} index {index}')
 
    return ret
 

	
 

	
 
class Collector:
 
    """receives setAttrs calls; combines settings; renders them into what outputs like; calls Output.update"""
 

	
 
    def __init__(self, graph: SyncedGraph, outputs: List[OutputInstance], listeners: WebListeners, clientTimeoutSec: float = 10):
 
        self.graph = graph
 
        self.outputs = outputs
 
        self.listeners = listeners
 
        self.clientTimeoutSec = clientTimeoutSec
 

	
 
        self._initTime = time.time()
 
        self._outputByUri: Dict[OutputUri, OutputInstance] = {}
 
        self._deviceType: Dict[DeviceUri, DeviceClass] = {}
 
        self.remapOut: Dict[Tuple[DeviceUri, OutputAttr], OutputRange] = {}
 

	
 
        self.graph.addHandler(self._compile)
 

	
 
        # rename to activeSessons ?
 
        self.lastRequest: Dict[Tuple[ClientType, ClientSessionType], Tuple[UnixTime, Dict[Tuple[DeviceUri, DeviceAttr], VTUnion]]] = {}
 

	
 
        # (dev, devAttr): value to use instead of 0
 
        self.stickyAttrs: Dict[Tuple[DeviceUri, DeviceAttr], VTUnion] = {}
 

	
 
    def _compile(self):
 
        log.info('Collector._compile:')
 
        self._outputByUri = self._compileOutputByUri()
 
        self._outputMap = _outputMap(self.graph, set(self._outputByUri.keys()))
 

	
 
        self._deviceType.clear()
 
        self.remapOut.clear()
 
        for dc in self.graph.subjects(RDF.type, L9['DeviceClass']):
 
            dc = cast(DeviceClass, dc)
 
            for dev in self.graph.subjects(RDF.type, dc):
 
                dev = cast(DeviceUri, dev)
 
                self._deviceType[dev] = dc
 
                self._compileRemapForDevice(dev)
 

	
 
    def _compileOutputByUri(self) -> Dict[OutputUri, OutputInstance]:
 
        ret = {}
 
        for output in self.outputs:
 
            ret[OutputUri(output.uri)] = output
 
        return ret
 

	
 
    def _compileRemapForDevice(self, dev: DeviceUri):
 
        for remap in self.graph.objects(dev, L9['outputAttrRange']):
 
            attr = typedValue(OutputAttr, self.graph, remap, L9['outputAttr'])
 
            start = typedValue(float, self.graph, remap, L9['start'])
 
            end = typedValue(float, self.graph, remap, L9['end'])
 
            self.remapOut[(dev, attr)] = OutputRange((start, end))
 

	
 
    def setAttrs(self, client: ClientType, clientSession: ClientSessionType, settings: DeviceSettings, sendTime: UnixTime):
 
        """
 
        Given DeviceSettings, we resolve conflicting values,
 
        process them into output attrs, and call Output.update
 
        to send the new outputs.
 

	
 
        client is a string naming the type of client.
 
        (client, clientSession) is a unique client instance.
 
        clientSession is deprecated.
 

	
 
        Each client session's last settings will be forgotten
 
        after clientTimeoutSec.
 
        """
 
        # todo: cleanup session code if we really don't want to be able to run multiple sessions of one client
 
        clientSession = ClientSessionType("no_longer_used")
 

	
 
        now = UnixTime(time.time())
 
        self._warnOnLateRequests(client, now, sendTime)
 

	
 
        self._forgetStaleClients(now)
 

	
 
        self.lastRequest[(client, clientSession)] = (now, self._resolvedSettingsDict(settings))
 

	
light9/live/Light9AttrControl.ts
Show inline comments
 
@@ -92,90 +92,90 @@ export class Light9AttrControl extends L
 
  }
 

	
 
  private onValueProperty() {
 
    if (this.deviceAttrRow === null) throw new Error();
 
    if (this.effect !== null && this.graph !== undefined) {
 
      const p = this.effect.edit(this.deviceAttrRow.device, this.deviceAttrRow.uri, this.value);
 
      if (p.adds.length || p.dels.length) {
 
        log("Effect told us to graph.patch", p, "to", this.graph);
 
        this.graph.applyAndSendPatch(p);
 
      }
 
    }
 
  }
 

	
 
  private onEffectProperty() {
 
    if (this.effect === null) throw new Error();
 
    // effect will read graph changes on its own, but emit an event when it does
 
    this.effect.settingsChanged.subscribe(() => {
 
      this.effectSettingsChanged();
 
    });
 
    this.effectSettingsChanged();
 
  }
 

	
 
  private effectSettingsChanged() {
 
    // something in the settings graph is new
 
    if (this.deviceAttrRow === null) throw new Error();
 
    if (this.effect === null) throw new Error();
 
    // log("graph->ui on ", this.deviceAttrRow.device, this.deviceAttrRow.uri);
 
    const v = this.effect.currentValue(this.deviceAttrRow.device, this.deviceAttrRow.uri);
 
    this.onGraphValueChanged(v);
 
  }
 

	
 
  private onDeviceAttrRowProperty() {
 
    if (this.deviceAttrRow === null) throw new Error();
 
    const d = this.deviceAttrRow.dataType;
 
    if (d.equals(makeType("scalar"))) {
 
      this.dataType = "scalar";
 
    } else if (d.equals(makeType("color"))) {
 
      this.dataType = "color";
 
    } else if (d.equals(makeType("choice"))) {
 
      this.dataType = "choice";
 
    }
 
  }
 

	
 
  onValueInput(ev: CustomEvent) {
 
    if (ev.detail === undefined) {
 
      // not sure what this is, but it seems to be followed by good events
 
      return;
 
    }
 
    log(ev.type, ev.detail.value);
 
    // log(ev.type, ev.detail.value);
 
    this.value = ev.detail.value;
 
    // this.graphToControls.controlChanged(this.device, this.deviceAttrRow.uri, ev.detail.value);
 
  }
 

	
 
  onGraphValueChanged(v: ControlValue | null) {
 
    if (this.deviceAttrRow === null) throw new Error();
 
    // log("change: control must display", v, "for", this.deviceAttrRow.device.value, this.deviceAttrRow.uri.value);
 
    // this.enableChange = false;
 
    if (this.dataType == "scalar") {
 
      if (v !== null) {
 
        this.value = v;
 
      } else {
 
        this.value = 0;
 
      }
 
    } else if (this.dataType == "color") {
 
      this.value = v;
 
    }
 
  }
 

	
 
  goBlack() {
 
    this.value = "#000000";
 
  }
 

	
 
  onChoice(value: any) {
 
    // if (value != null) {
 
    //   value = this.graph.Uri(value);
 
    // } else {
 
    //   value = null;
 
    // }
 
  }
 

	
 
  onChange(value: any) {
 
    // if (typeof value === "number" && isNaN(value)) {
 
    //   return;
 
    // } // let onChoice do it
 
    // //log('change: control tells graph', @deviceAttrRow.uri.value, value)
 
    // if (value === undefined) {
 
    //   value = null;
 
    // }
 
  }
 
}
light9/rdfdb/service.py
Show inline comments
 
import logging
 
import os
 
from pathlib import Path
 

	
 
from light9.run_local import log
 

	
 
import rdfdb.service
 
from rdflib import URIRef
 

	
 
from light9 import showconfig
 
logging.getLogger('rdfdb').setLevel(logging.INFO)
 
logging.getLogger('rdfdb.file').setLevel(logging.INFO)
 
logging.getLogger('rdfdb.graph').setLevel(logging.INFO)
 
logging.getLogger('rdfdb.net').setLevel(logging.DEBUG)
 
logging.getLogger('rdfdb.net').setLevel(logging.INFO)
 
rdfRoot = Path(os.environ['LIGHT9_SHOW'].rstrip('/') + '/')
 
showUri = URIRef(showconfig.showUri() + '/')
 

	
 
app = rdfdb.service.makeApp(  #
 
    dirUriMap={rdfRoot: showUri},
 
    prefixes={
 
        'show': showUri,
 
        '': URIRef('http://light9.bigasterisk.com/'),
 
        'rdf': URIRef('http://www.w3.org/1999/02/22-rdf-syntax-ns#'),
 
        'rdfs': URIRef('http://www.w3.org/2000/01/rdf-schema#'),
 
        'xsd': URIRef('http://www.w3.org/2001/XMLSchema#'),
 
        'effect': URIRef('http://light9.bigasterisk.com/effect/'),
 
        'dev': URIRef('http://light9.bigasterisk.com/theater/skyline/device/'),
 
    })
0 comments (0 inline, 0 general)