annotate light9/collector/collector.py @ 2227:fe3543310d34

move uriTail to a better layer of code
author drewp@bigasterisk.com
date Tue, 23 May 2023 23:56:20 -0700
parents e22c7d15a504
children 2b8a2a25b154
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
2154
b6a8289b1d1e reformat
drewp@bigasterisk.com
parents: 2072
diff changeset
1 import logging
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
2 import time
2162
e69661cca1cb cleanup
drewp@bigasterisk.com
parents: 2161
diff changeset
3 from typing import Dict, List, Set, Tuple, cast
2199
ffde209f05c4 typedValue imports
drewp@bigasterisk.com
parents: 2194
diff changeset
4 from light9.typedgraph import typedValue
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
5
2154
b6a8289b1d1e reformat
drewp@bigasterisk.com
parents: 2072
diff changeset
6 from rdfdb.syncedgraph.syncedgraph import SyncedGraph
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
7 from rdflib import URIRef
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
8
2154
b6a8289b1d1e reformat
drewp@bigasterisk.com
parents: 2072
diff changeset
9 from light9.collector.device import resolve, toOutputAttrs
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
10 from light9.collector.output import Output as OutputInstance
1866
3c523c71da29 pyflakes cleanups and some refactors
Drew Perttula <drewp@bigasterisk.com>
parents: 1860
diff changeset
11 from light9.collector.weblisteners import WebListeners
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
12 from light9.effect.settings import DeviceSettings
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
13 from light9.namespaces import L9, RDF
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
14 from light9.newtypes import (ClientSessionType, ClientType, DeviceAttr, DeviceClass, DeviceSetting, DeviceUri, DmxIndex, DmxMessageIndex, OutputAttr,
2227
fe3543310d34 move uriTail to a better layer of code
drewp@bigasterisk.com
parents: 2217
diff changeset
15 OutputRange, OutputUri, OutputValue, UnixTime, VTUnion, uriTail)
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
16
1289
5a4e74f1e36a Fixed client session clearing bugs.
Drew Perttula <drewp@bigasterisk.com>
parents: 1288
diff changeset
17 log = logging.getLogger('collector')
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
18
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
19
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
20 def makeDmxMessageIndex(base: DmxIndex, offset: DmxIndex) -> DmxMessageIndex:
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
21 return DmxMessageIndex(base + offset - 1)
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
22
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
23
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
24 def _outputMap(graph: SyncedGraph, outputs: Set[OutputUri]) -> Dict[Tuple[DeviceUri, OutputAttr], Tuple[OutputUri, DmxMessageIndex]]:
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
25 """From rdf config graph, compute a map of
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
26 (device, outputattr) : (output, index)
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
27 that explains which output index to set for any device update.
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
28 """
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
29 ret = cast(Dict[Tuple[DeviceUri, OutputAttr], Tuple[OutputUri, DmxMessageIndex]], {})
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
30
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
31 for dc in graph.subjects(RDF.type, L9['DeviceClass']):
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
32 log.info('mapping devices of class %s', dc)
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
33 for dev in graph.subjects(RDF.type, dc):
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
34 dev = cast(DeviceUri, dev)
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
35 log.info(' 💡 mapping device %s', dev)
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
36 universe = typedValue(OutputUri, graph, dev, L9['dmxUniverse'])
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
37 if universe not in outputs:
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
38 raise ValueError(f'{dev=} is configured to be in {universe=}, but we have no Output for that universe')
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
39 try:
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
40 dmxBase = typedValue(DmxIndex, graph, dev, L9['dmxBase'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
41 except ValueError:
1966
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
42 raise ValueError('no :dmxBase for %s' % dev)
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
43
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
44 for row in sorted(graph.objects(dc, L9['attr']), key=str):
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
45 outputAttr = typedValue(OutputAttr, graph, row, L9['outputAttr'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
46 offset = typedValue(DmxIndex, graph, row, L9['dmxOffset'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
47 index = makeDmxMessageIndex(dmxBase, offset)
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
48 ret[(dev, outputAttr)] = (universe, index)
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
49 log.info(f' {uriTail(outputAttr):15} maps to {uriTail(universe)} index {index}')
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
50 return ret
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
51
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
52
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
53 class Collector:
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
54 """receives setAttrs calls; combines settings; renders them into what outputs like; calls Output.update"""
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
55
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
56 def __init__(self, graph: SyncedGraph, outputs: List[OutputInstance], listeners: WebListeners, clientTimeoutSec: float = 10):
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
57 self.graph = graph
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
58 self.outputs = outputs
1541
c1bf296b0a74 collector uses cyclone and gets a web ui showing output attrs
Drew Perttula <drewp@bigasterisk.com>
parents: 1506
diff changeset
59 self.listeners = listeners
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
60 self.clientTimeoutSec = clientTimeoutSec
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
61
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
62 self._initTime = time.time()
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
63 self._outputByUri: Dict[OutputUri, OutputInstance] = {}
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
64 self._deviceType: Dict[DeviceUri, DeviceClass] = {}
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
65 self.remapOut: Dict[Tuple[DeviceUri, OutputAttr], OutputRange] = {}
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
66
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
67 self.graph.addHandler(self._compile)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
68
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
69 # rename to activeSessons ?
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
70 self.lastRequest: Dict[Tuple[ClientType, ClientSessionType], Tuple[UnixTime, Dict[Tuple[DeviceUri, DeviceAttr], VTUnion]]] = {}
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
71
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
72 # (dev, devAttr): value to use instead of 0
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
73 self.stickyAttrs: Dict[Tuple[DeviceUri, DeviceAttr], VTUnion] = {}
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
74
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
75 def _compile(self):
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
76 self._outputByUri = self._compileOutputByUri()
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
77 self._outputMap = _outputMap(self.graph, set(self._outputByUri.keys()))
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
78
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
79 self._deviceType.clear()
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
80 self.remapOut.clear()
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
81 for dc in self.graph.subjects(RDF.type, L9['DeviceClass']):
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
82 dc = cast(DeviceClass, dc)
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
83 for dev in self.graph.subjects(RDF.type, dc):
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
84 dev = cast(DeviceUri, dev)
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
85 self._deviceType[dev] = dc
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
86 self._compileRemapForDevice(dev)
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
87
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
88 def _compileOutputByUri(self) -> Dict[OutputUri, OutputInstance]:
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
89 ret = {}
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
90 for output in self.outputs:
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
91 ret[OutputUri(output.uri)] = output
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
92 return ret
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
93
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
94 def _compileRemapForDevice(self, dev: DeviceUri):
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
95 for remap in self.graph.objects(dev, L9['outputAttrRange']):
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
96 attr = typedValue(OutputAttr, self.graph, remap, L9['outputAttr'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
97 start = typedValue(float, self.graph, remap, L9['start'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
98 end = typedValue(float, self.graph, remap, L9['end'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
99 self.remapOut[(dev, attr)] = OutputRange((start, end))
1448
931d2dafca12 new feature: values can have their range remapped in the device processing
drewp@bigasterisk.com
parents: 1446
diff changeset
100
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
101 def setAttrs(self, client: ClientType, clientSession: ClientSessionType, settings: DeviceSettings, sendTime: UnixTime):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
102 """
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
103 Given DeviceSettings, we resolve conflicting values,
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
104 process them into output attrs, and call Output.update
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
105 to send the new outputs.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
106
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
107 client is a string naming the type of client.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
108 (client, clientSession) is a unique client instance.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
109 clientSession is deprecated.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
110
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
111 Each client session's last settings will be forgotten
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
112 after clientTimeoutSec.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
113 """
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
114 # todo: cleanup session code if we really don't want to be able to run multiple sessions of one client
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
115 clientSession = ClientSessionType("no_longer_used")
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
116
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
117 now = UnixTime(time.time())
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
118 self._warnOnLateRequests(client, now, sendTime)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
119
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
120 self._forgetStaleClients(now)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
121
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
122 self.lastRequest[(client, clientSession)] = (now, self._resolvedSettingsDict(settings))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
123
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
124 deviceAttrs = self._merge(iter(self.lastRequest.values()))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
125
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
126 outputAttrsByDevice = self._convertToOutputAttrsPerDevice(deviceAttrs)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
127 pendingOut = self._flattenDmxOutput(outputAttrsByDevice)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
128
2217
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
129 t2 = time.time()
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
130
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
131 self._updateOutputs(pendingOut)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
132
2217
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
133 t3 = time.time()
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
134 if t2 - now > .030 or t3 - t2 > .030:
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
135 log.warning("slow setAttrs: prepare %.1fms -> updateOutputs %.1fms" % ((t2 - now) * 1000, (t3 - t2) * 1000))
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
136
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
137 def _warnOnLateRequests(self, client, now, sendTime):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
138 requestLag = now - sendTime
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
139 if requestLag > .1 and now > self._initTime + 10 and getattr(self, '_lastWarnTime', 0) < now - 3:
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
140 self._lastWarnTime = now
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
141 log.warning('collector.setAttrs from %s is running %.1fms after the request was made', client, requestLag * 1000)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
142
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
143 def _forgetStaleClients(self, now):
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
144 staleClientSessions = []
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
145 for clientSession, (reqTime, _) in self.lastRequest.items():
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
146 if reqTime < now - self.clientTimeoutSec:
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
147 staleClientSessions.append(clientSession)
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
148 for clientSession in staleClientSessions:
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
149 log.info('forgetting stale client %r', clientSession)
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
150 del self.lastRequest[clientSession]
1300
d51014267bfd move device-specific code out of collector. resolver isn't done yet. live.html can edit colors
Drew Perttula <drewp@bigasterisk.com>
parents: 1289
diff changeset
151
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
152 # todo: move to settings.py
2208
091909b4b727 seems kind of important that effecteval return DeviceSettings, not more EffectSettings
drewp@bigasterisk.com
parents: 2204
diff changeset
153 def _resolvedSettingsDict(self, settingsList: DeviceSettings) -> Dict[Tuple[DeviceUri, DeviceAttr], VTUnion]:
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
154 out: Dict[Tuple[DeviceUri, DeviceAttr], VTUnion] = {}
2208
091909b4b727 seems kind of important that effecteval return DeviceSettings, not more EffectSettings
drewp@bigasterisk.com
parents: 2204
diff changeset
155 for devUri, devAttr, val in settingsList.asList():
2183
081f36506ad3 address a bunch of type errors and loose types
drewp@bigasterisk.com
parents: 2173
diff changeset
156 if (devUri, devAttr) in out:
081f36506ad3 address a bunch of type errors and loose types
drewp@bigasterisk.com
parents: 2173
diff changeset
157 existingVal = out[(devUri, devAttr)]
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
158 out[(devUri, devAttr)] = resolve(self._deviceType[devUri], devAttr, [existingVal, val])
1372
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
159 else:
2183
081f36506ad3 address a bunch of type errors and loose types
drewp@bigasterisk.com
parents: 2173
diff changeset
160 out[(devUri, devAttr)] = val
1372
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
161 return out
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
162
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
163 def _merge(self, lastRequests):
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
164 deviceAttrs: Dict[DeviceUri, Dict[DeviceAttr, VTUnion]] = {} # device: {deviceAttr: value}
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
165 for _, lastSettings in lastRequests:
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
166 for (device, deviceAttr), value in lastSettings.items():
1448
931d2dafca12 new feature: values can have their range remapped in the device processing
drewp@bigasterisk.com
parents: 1446
diff changeset
167 if (device, deviceAttr) in self.remapOut:
931d2dafca12 new feature: values can have their range remapped in the device processing
drewp@bigasterisk.com
parents: 1446
diff changeset
168 start, end = self.remapOut[(device, deviceAttr)]
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
169 value = start + float(value) * (end - start)
1450
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
170
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
171 attrs = deviceAttrs.setdefault(device, {})
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
172 if deviceAttr in attrs:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
173 value = resolve(device, deviceAttr, [attrs[deviceAttr], value])
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
174 attrs[deviceAttr] = value
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
175 # list should come from the graph. these are attrs
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
176 # that should default to holding the last position,
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
177 # not going to 0.
1475
a749079ec774 focus should also be sticky attr
drewp@bigasterisk.com
parents: 1470
diff changeset
178 if deviceAttr in [L9['rx'], L9['ry'], L9['zoom'], L9['focus']]:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
179 self.stickyAttrs[(device, deviceAttr)] = cast(float, value)
1300
d51014267bfd move device-specific code out of collector. resolver isn't done yet. live.html can edit colors
Drew Perttula <drewp@bigasterisk.com>
parents: 1289
diff changeset
180
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
181 # e.g. don't let an unspecified rotation go to 0
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
182 for (d, da), v in self.stickyAttrs.items():
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
183 daDict = deviceAttrs.setdefault(d, {})
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
184 if da not in daDict:
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
185 daDict[da] = v
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
186
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
187 return deviceAttrs
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
188
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
189 def _convertToOutputAttrsPerDevice(self, deviceAttrs):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
190 ret: Dict[DeviceUri, Dict[OutputAttr, OutputValue]] = {}
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
191 for d, devType in self._deviceType.items():
1809
778c67ab70c9 set zmq highWaterMark to dump stale messages, especially those sent when collector isn't running
drewp@bigasterisk.com
parents: 1799
diff changeset
192 try:
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
193 ret[d] = toOutputAttrs(devType, deviceAttrs.get(d, {}))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
194 self.listeners.outputAttrsSet(d, ret[d], self._outputMap)
1809
778c67ab70c9 set zmq highWaterMark to dump stale messages, especially those sent when collector isn't running
drewp@bigasterisk.com
parents: 1799
diff changeset
195 except Exception as e:
778c67ab70c9 set zmq highWaterMark to dump stale messages, especially those sent when collector isn't running
drewp@bigasterisk.com
parents: 1799
diff changeset
196 log.error('failing toOutputAttrs on %s: %r', d, e)
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
197 return ret
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
198
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
199 def _flattenDmxOutput(self, outputAttrs: Dict[DeviceUri, Dict[OutputAttr, OutputValue]]) -> Dict[OutputUri, bytearray]:
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
200 pendingOut = cast(Dict[OutputUri, bytearray], {})
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
201 for outUri in self._outputByUri.keys():
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
202 pendingOut[outUri] = bytearray(512)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
203
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
204 for device, attrs in outputAttrs.items():
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
205 for outputAttr, value in attrs.items():
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
206 outputUri, _index = self._outputMap[(device, outputAttr)]
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
207 index = DmxMessageIndex(_index)
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
208 outArray = pendingOut[outputUri]
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
209 if outArray[index] != 0:
2202
drewp@bigasterisk.com
parents: 2199
diff changeset
210 log.warning(f'conflict: {outputUri} output array was already nonzero at 0-based index {index}')
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
211 raise ValueError(f"someone already wrote to index {index}")
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
212 outArray[index] = value
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
213 return pendingOut
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
214
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
215 def _updateOutputs(self, pendingOut: Dict[OutputUri, bytearray]):
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
216 for uri, buf in pendingOut.items():
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
217 self._outputByUri[uri].update(bytes(buf))