annotate src/light9/collector/collector.py @ 2410:44fc477970bf

cleanup imports, reformats
author drewp@bigasterisk.com
date Sat, 18 May 2024 23:19:04 -0700
parents 4556eebe5d73
children
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
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
4
2357
ccd04278e357 metrics cleanup
drewp@bigasterisk.com
parents: 2252
diff changeset
5 from prometheus_client import Summary
2154
b6a8289b1d1e reformat
drewp@bigasterisk.com
parents: 2072
diff changeset
6 from rdfdb.syncedgraph.syncedgraph import SyncedGraph
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
7
2154
b6a8289b1d1e reformat
drewp@bigasterisk.com
parents: 2072
diff changeset
8 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
9 from light9.collector.output import Output as OutputInstance
1866
3c523c71da29 pyflakes cleanups and some refactors
Drew Perttula <drewp@bigasterisk.com>
parents: 1860
diff changeset
10 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
11 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
12 from light9.namespaces import L9, RDF
2410
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
13 from light9.newtypes import (
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
14 ClientSessionType,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
15 ClientType,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
16 DeviceAttr,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
17 DeviceClass,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
18 DeviceUri,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
19 DmxIndex,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
20 DmxMessageIndex,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
21 OutputAttr,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
22 OutputRange,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
23 OutputUri,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
24 OutputValue,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
25 UnixTime,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
26 VTUnion,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
27 uriTail,
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
28 )
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
29 from light9.typedgraph import typedValue
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
30
1289
5a4e74f1e36a Fixed client session clearing bugs.
Drew Perttula <drewp@bigasterisk.com>
parents: 1288
diff changeset
31 log = logging.getLogger('collector')
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
32
2357
ccd04278e357 metrics cleanup
drewp@bigasterisk.com
parents: 2252
diff changeset
33 STAT_SETATTR = Summary('set_attr', 'setAttr calls')
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
34
2410
44fc477970bf cleanup imports, reformats
drewp@bigasterisk.com
parents: 2376
diff changeset
35
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
36 def makeDmxMessageIndex(base: DmxIndex, offset: DmxIndex) -> DmxMessageIndex:
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
37 return DmxMessageIndex(base + offset - 1)
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
38
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
39
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
40 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
41 """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
42 (device, outputattr) : (output, index)
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
43 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
44 """
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
45 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
46
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
47 for dc in graph.subjects(RDF.type, L9['DeviceClass']):
2252
2b8a2a25b154 logging
drewp@bigasterisk.com
parents: 2227
diff changeset
48 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
49 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
50 dev = cast(DeviceUri, dev)
2252
2b8a2a25b154 logging
drewp@bigasterisk.com
parents: 2227
diff changeset
51 log.info(' 💡 mapping device %s', dev)
2155
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
52 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
53 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
54 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
55 try:
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
56 dmxBase = typedValue(DmxIndex, graph, dev, L9['dmxBase'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
57 except ValueError:
1966
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
58 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
59
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
60 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
61 outputAttr = typedValue(OutputAttr, graph, row, L9['outputAttr'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
62 offset = typedValue(DmxIndex, graph, row, L9['dmxOffset'])
092967f313e1 attempt to make things more typesafe and readable (untested)
drewp@bigasterisk.com
parents: 2154
diff changeset
63 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
64 ret[(dev, outputAttr)] = (universe, index)
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
65 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
66 return ret
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
67
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
68
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
69 class Collector:
2193
f79fff92990b collector.output use asyncio loop, not twisted loop. other cleanups.
drewp@bigasterisk.com
parents: 2183
diff changeset
70 """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
71
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
72 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
73 self.graph = graph
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
74 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
75 self.listeners = listeners
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
76 self.clientTimeoutSec = clientTimeoutSec
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
77
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
78 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
79 self._outputByUri: Dict[OutputUri, OutputInstance] = {}
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
80 self._deviceType: Dict[DeviceUri, DeviceClass] = {}
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
81 self.remapOut: Dict[Tuple[DeviceUri, OutputAttr], OutputRange] = {}
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
82
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
83 self.graph.addHandler(self._compile)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
84
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
85 # rename to activeSessons ?
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
86 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
87
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
88 # (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
89 self.stickyAttrs: Dict[Tuple[DeviceUri, DeviceAttr], VTUnion] = {}
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
90
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
91 def _compile(self):
2252
2b8a2a25b154 logging
drewp@bigasterisk.com
parents: 2227
diff changeset
92 log.info('Collector._compile:')
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
93 self._outputByUri = self._compileOutputByUri()
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
94 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
95
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
96 self._deviceType.clear()
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
97 self.remapOut.clear()
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
98 for dc in self.graph.subjects(RDF.type, L9['DeviceClass']):
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
99 dc = cast(DeviceClass, dc)
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
100 for dev in self.graph.subjects(RDF.type, dc):
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
101 dev = cast(DeviceUri, dev)
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
102 self._deviceType[dev] = dc
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
103 self._compileRemapForDevice(dev)
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
104
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
105 def _compileOutputByUri(self) -> Dict[OutputUri, OutputInstance]:
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
106 ret = {}
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
107 for output in self.outputs:
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
108 ret[OutputUri(output.uri)] = output
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
109 return ret
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
110
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
111 def _compileRemapForDevice(self, dev: DeviceUri):
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
112 for remap in self.graph.objects(dev, L9['outputAttrRange']):
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
113 attr = typedValue(OutputAttr, self.graph, remap, L9['outputAttr'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
114 start = typedValue(float, self.graph, remap, L9['start'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
115 end = typedValue(float, self.graph, remap, L9['end'])
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
116 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
117
2357
ccd04278e357 metrics cleanup
drewp@bigasterisk.com
parents: 2252
diff changeset
118 @STAT_SETATTR.time()
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
119 def setAttrs(self, client: ClientType, clientSession: ClientSessionType, settings: DeviceSettings, sendTime: UnixTime):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
120 """
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
121 Given DeviceSettings, we resolve conflicting values,
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
122 process them into output attrs, and call Output.update
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
123 to send the new outputs.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
124
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
125 client is a string naming the type of client.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
126 (client, clientSession) is a unique client instance.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
127 clientSession is deprecated.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
128
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
129 Each client session's last settings will be forgotten
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
130 after clientTimeoutSec.
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
131 """
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
132 # 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
133 clientSession = ClientSessionType("no_longer_used")
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
134
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
135 now = UnixTime(time.time())
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
136 self._warnOnLateRequests(client, now, sendTime)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
137
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
138 self._forgetStaleClients(now)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
139
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
140 self.lastRequest[(client, clientSession)] = (now, self._resolvedSettingsDict(settings))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
141
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
142 deviceAttrs = self._merge(iter(self.lastRequest.values()))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
143
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
144 outputAttrsByDevice = self._convertToOutputAttrsPerDevice(deviceAttrs)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
145 pendingOut = self._flattenDmxOutput(outputAttrsByDevice)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
146
2217
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
147 t2 = time.time()
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
148
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
149 self._updateOutputs(pendingOut)
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
150
2217
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
151 t3 = time.time()
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
152 if t2 - now > .030 or t3 - t2 > .030:
e22c7d15a504 logging fix
drewp@bigasterisk.com
parents: 2208
diff changeset
153 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
154
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
155 def _warnOnLateRequests(self, client, now, sendTime):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
156 requestLag = now - sendTime
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
157 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
158 self._lastWarnTime = now
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
159 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
160
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
161 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
162 staleClientSessions = []
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
163 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
164 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
165 staleClientSessions.append(clientSession)
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
166 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
167 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
168 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
169
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
170 # 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
171 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
172 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
173 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
174 if (devUri, devAttr) in out:
081f36506ad3 address a bunch of type errors and loose types
drewp@bigasterisk.com
parents: 2173
diff changeset
175 existingVal = out[(devUri, devAttr)]
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
176 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
177 else:
2183
081f36506ad3 address a bunch of type errors and loose types
drewp@bigasterisk.com
parents: 2173
diff changeset
178 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
179 return out
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
180
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
181 def _merge(self, lastRequests):
2170
066f05ad7900 collector: even stronger types; repair test code (some are failing)
drewp@bigasterisk.com
parents: 2162
diff changeset
182 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
183 for _, lastSettings in lastRequests:
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
184 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
185 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
186 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
187 value = start + float(value) * (end - start)
1450
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
188
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
189 attrs = deviceAttrs.setdefault(device, {})
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
190 if deviceAttr in attrs:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
191 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
192 attrs[deviceAttr] = value
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
193 # 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
194 # 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
195 # not going to 0.
1475
a749079ec774 focus should also be sticky attr
drewp@bigasterisk.com
parents: 1470
diff changeset
196 if deviceAttr in [L9['rx'], L9['ry'], L9['zoom'], L9['focus']]:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
197 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
198
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
199 # 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
200 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
201 daDict = deviceAttrs.setdefault(d, {})
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
202 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
203 daDict[da] = v
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
204
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
205 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
206
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
207 def _convertToOutputAttrsPerDevice(self, deviceAttrs):
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
208 ret: Dict[DeviceUri, Dict[OutputAttr, OutputValue]] = {}
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
209 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
210 try:
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
211 ret[d] = toOutputAttrs(devType, deviceAttrs.get(d, {}))
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
212 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
213 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
214 log.error('failing toOutputAttrs on %s: %r', d, e)
2204
3db40ecf9e61 refactor setAttrs
drewp@bigasterisk.com
parents: 2202
diff changeset
215 return ret
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
216
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
217 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
218 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
219 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
220 pendingOut[outUri] = bytearray(512)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
221
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
222 for device, attrs in outputAttrs.items():
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
223 for outputAttr, value in attrs.items():
2194
673e7a9c8bbb refactor
drewp@bigasterisk.com
parents: 2193
diff changeset
224 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
225 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
226 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
227 if outArray[index] != 0:
2202
drewp@bigasterisk.com
parents: 2199
diff changeset
228 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
229 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
230 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
231 return pendingOut
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
232
2173
f239dedb025a disable collector client sessions- we prob don't need them. refactor collector.py
drewp@bigasterisk.com
parents: 2170
diff changeset
233 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
234 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
235 self._outputByUri[uri].update(bytes(buf))