annotate light9/collector/collector.py @ 2072:d5f1cc9615af

collector: rewrites for asyncio
author drewp@bigasterisk.com
date Sun, 22 May 2022 03:03:43 -0700
parents f66dbe512025
children b6a8289b1d1e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
1 import time
1289
5a4e74f1e36a Fixed client session clearing bugs.
Drew Perttula <drewp@bigasterisk.com>
parents: 1288
diff changeset
2 import logging
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
3 from typing import cast, List, Dict, Tuple, Optional, Set
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
4
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
5 from rdflib import Graph, Literal
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
6
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
7 from light9.collector.device import toOutputAttrs, resolve
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
8 from light9.collector.output import Output as OutputInstance
1866
3c523c71da29 pyflakes cleanups and some refactors
Drew Perttula <drewp@bigasterisk.com>
parents: 1860
diff changeset
9 from light9.collector.weblisteners import WebListeners
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.namespaces import L9, RDF
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
11 from rdfdb.syncedgraph.syncedgraph import SyncedGraph
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.newtypes import ClientType, ClientSessionType, OutputUri, DeviceUri, DeviceClass, DmxIndex, DmxMessageIndex, DeviceAttr, OutputAttr, OutputValue, UnixTime, OutputRange
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
13
1289
5a4e74f1e36a Fixed client session clearing bugs.
Drew Perttula <drewp@bigasterisk.com>
parents: 1288
diff changeset
14 log = logging.getLogger('collector')
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
15
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
16
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
17 def outputMap(graph: SyncedGraph, outputs: List[OutputInstance]) -> Dict[Tuple[DeviceUri, OutputAttr], Tuple[OutputInstance, DmxMessageIndex]]:
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
18 """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
19 (device, outputattr) : (output, index)
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
20 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
21 """
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
22 ret = {}
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
23
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
24 outputByUri: Dict[OutputUri, OutputInstance] = {}
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
25 for out in outputs:
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
26 outputByUri[OutputUri(out.uri)] = out
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
27
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
28 for dc in graph.subjects(RDF.type, L9['DeviceClass']):
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
29 log.info('mapping DeviceClass %s', dc)
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
30 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
31 dev = cast(DeviceUri, dev)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
32 log.info(' mapping device %s', dev)
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
33 universe = cast(OutputUri, graph.value(dev, L9['dmxUniverse']))
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
34 try:
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
35 output = outputByUri[universe]
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
36 except Exception:
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
37 log.warn('dev %r :dmxUniverse %r', dev, universe)
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
38 raise
1966
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
39 base = graph.value(dev, L9['dmxBase'])
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
40 if base is None:
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
41 raise ValueError('no :dmxBase for %s' % dev)
e4bdc5370fa7 collector erroring
drewp@bigasterisk.com
parents: 1884
diff changeset
42 dmxBase = DmxIndex(cast(Literal, base).toPython())
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
43 for row in graph.objects(dc, L9['attr']):
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
44 outputAttr = cast(OutputAttr, graph.value(row, L9['outputAttr']))
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
45 offset = DmxIndex(cast(Literal, graph.value(row, L9['dmxOffset'])).toPython())
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
46 index = DmxMessageIndex(dmxBase + offset - 1)
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
47 ret[(dev, outputAttr)] = (output, index)
1541
c1bf296b0a74 collector uses cyclone and gets a web ui showing output attrs
Drew Perttula <drewp@bigasterisk.com>
parents: 1506
diff changeset
48 log.debug(' map %s to %s,%s', outputAttr, output, index)
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
49 return ret
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
50
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
51
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
52 class Collector:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
53 """receives setAttrs calls; combines settings; renders them into what outputs like; call Output.update"""
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
54
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
55 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
56 self.graph = graph
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
57 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
58 self.listeners = listeners
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
59 self.clientTimeoutSec = clientTimeoutSec
1542
60e559cb1a5e collector now runs the device function even on devs that have no settings, in case they have some fixed output values (e.g. light mode)
Drew Perttula <drewp@bigasterisk.com>
parents: 1541
diff changeset
60 self.initTime = time.time()
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
61 self.allDevices: Set[DeviceUri] = set()
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
62
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
63 self.graph.addHandler(self.rebuildOutputMap)
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
64
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
65 # client : (session, time, {(dev,devattr): latestValue})
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
66 self.lastRequest: Dict[Tuple[ClientType, ClientSessionType], Tuple[UnixTime, Dict[Tuple[DeviceUri, DeviceAttr], float]]] = {}
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
67
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
68 # (dev, devAttr): value to use instead of 0
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 self.stickyAttrs: Dict[Tuple[DeviceUri, DeviceAttr], float] = {}
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
70
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
71 def rebuildOutputMap(self):
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
72 self.outputMap = outputMap(self.graph, self.outputs)
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
73 self.deviceType: Dict[DeviceUri, DeviceClass] = {}
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
74 self.remapOut: Dict[Tuple[DeviceUri, OutputAttr], OutputRange] = {}
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
75 for dc in self.graph.subjects(RDF.type, L9['DeviceClass']):
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
76 dc = cast(DeviceClass, dc)
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
77 for dev in self.graph.subjects(RDF.type, dc):
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
78 dev = cast(DeviceUri, dev)
1542
60e559cb1a5e collector now runs the device function even on devs that have no settings, in case they have some fixed output values (e.g. light mode)
Drew Perttula <drewp@bigasterisk.com>
parents: 1541
diff changeset
79 self.allDevices.add(dev)
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
80 self.deviceType[dev] = dc
1307
8863b4485fd4 collector uses rdfdb
Drew Perttula <drewp@bigasterisk.com>
parents: 1302
diff changeset
81
1448
931d2dafca12 new feature: values can have their range remapped in the device processing
drewp@bigasterisk.com
parents: 1446
diff changeset
82 for remap in self.graph.objects(dev, L9['outputAttrRange']):
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
83 attr = OutputAttr(self.graph.value(remap, L9['outputAttr']))
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
84 start = cast(Literal, self.graph.value(remap, L9['start'])).toPython()
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
85 end = cast(Literal, self.graph.value(remap, L9['end'])).toPython()
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
86 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
87
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
88 def _forgetStaleClients(self, now):
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
89 # type: (float) -> None
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
90 staleClientSessions = []
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
91 for c, (t, _) in self.lastRequest.items():
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
92 if t < now - self.clientTimeoutSec:
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
93 staleClientSessions.append(c)
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
94 for c in staleClientSessions:
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
95 log.info('forgetting stale client %r', c)
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
96 del self.lastRequest[c]
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
97
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
98 # todo: move to settings.py
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
99 def resolvedSettingsDict(self, settingsList: List[Tuple[DeviceUri, DeviceAttr, float]]) -> Dict[Tuple[DeviceUri, DeviceAttr], float]:
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
100 out: Dict[Tuple[DeviceUri, DeviceAttr], float] = {}
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
101 for d, da, v in settingsList:
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
102 if (d, da) in out:
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
103 out[(d, da)] = resolve(d, da, [out[(d, da)], v])
1372
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
104 else:
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
105 out[(d, da)] = v
1372
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
106 return out
f427801da9f6 collector properly merges repeated attr settings in the same message
Drew Perttula <drewp@bigasterisk.com>
parents: 1307
diff changeset
107
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
108 def _warnOnLateRequests(self, client, now, sendTime):
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
109 requestLag = now - sendTime
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
110 if requestLag > .1 and now > self.initTime + 10 and getattr(self, '_lastWarnTime', 0) < now - 3:
1799
0bb7b9df12e5 collector warnings and errors. the reactor.crash isn't working.
drewp@bigasterisk.com
parents: 1700
diff changeset
111 self._lastWarnTime = now
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
112 log.warn('collector.setAttrs from %s is running %.1fms after the request was made', client, requestLag * 1000)
1289
5a4e74f1e36a Fixed client session clearing bugs.
Drew Perttula <drewp@bigasterisk.com>
parents: 1288
diff changeset
113
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
114 def _merge(self, lastRequests):
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
115 deviceAttrs: Dict[DeviceUri, Dict[DeviceAttr, float]] = {} # 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
116 for _, lastSettings in lastRequests:
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
117 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
118 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
119 start, end = self.remapOut[(device, deviceAttr)]
931d2dafca12 new feature: values can have their range remapped in the device processing
drewp@bigasterisk.com
parents: 1446
diff changeset
120 value = Literal(start + float(value) * (end - start))
1450
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
121
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
122 attrs = deviceAttrs.setdefault(device, {})
ddb7622698a8 don't mix remapped values with unremapped ones
drewp@bigasterisk.com
parents: 1448
diff changeset
123 if deviceAttr in attrs:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
124 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
125 attrs[deviceAttr] = value
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
126 # 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
127 # 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
128 # not going to 0.
1475
a749079ec774 focus should also be sticky attr
drewp@bigasterisk.com
parents: 1470
diff changeset
129 if deviceAttr in [L9['rx'], L9['ry'], L9['zoom'], L9['focus']]:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
130 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
131
1470
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
132 # 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
133 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
134 daDict = deviceAttrs.setdefault(d, {})
b1d8abc96f06 don't run rotations to zero when no one is requesting them.
drewp@bigasterisk.com
parents: 1450
diff changeset
135 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
136 daDict[da] = v
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
137
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
138 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
139
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
140 def setAttrs(self, client: ClientType, clientSession: ClientSessionType, settings: List[Tuple[DeviceUri, DeviceAttr, float]], sendTime: UnixTime):
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
141 """
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
142 settings is a list of (device, attr, value). These attrs are
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
143 device attrs. We resolve conflicting values, process them into
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
144 output attrs, and call Output.update to send the new outputs.
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
145
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
146 client is a string naming the type of client. (client,
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
147 clientSession) is a unique client instance.
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
148
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
149 Each client session's last settings will be forgotten after
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
150 clientTimeoutSec.
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
151 """
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
152 now = UnixTime(time.time())
1602
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
153 self._warnOnLateRequests(client, now, sendTime)
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
154
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
155 self._forgetStaleClients(now)
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
156
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
157 uniqueSettings = self.resolvedSettingsDict(settings)
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
158 self.lastRequest[(client, clientSession)] = (now, uniqueSettings)
0fc61e701347 collector: don't confuse two clients with the same name- use the session
Drew Perttula <drewp@bigasterisk.com>
parents: 1596
diff changeset
159
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
160 deviceAttrs = self._merge(iter(self.lastRequest.values()))
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
161
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
162 outputAttrs: Dict[DeviceUri, Dict[OutputAttr, OutputValue]] = {}
1542
60e559cb1a5e collector now runs the device function even on devs that have no settings, in case they have some fixed output values (e.g. light mode)
Drew Perttula <drewp@bigasterisk.com>
parents: 1541
diff changeset
163 for d in self.allDevices:
1416
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
164 try:
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
165 devType = self.deviceType[d]
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
166 except KeyError:
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
167 log.warn("request for output to unconfigured device %s" % d)
ab7b40d20af0 rewrite theaterConfig to a better data format
Drew Perttula <drewp@bigasterisk.com>
parents: 1412
diff changeset
168 continue
1809
778c67ab70c9 set zmq highWaterMark to dump stale messages, especially those sent when collector isn't running
drewp@bigasterisk.com
parents: 1799
diff changeset
169 try:
778c67ab70c9 set zmq highWaterMark to dump stale messages, especially those sent when collector isn't running
drewp@bigasterisk.com
parents: 1799
diff changeset
170 outputAttrs[d] = toOutputAttrs(devType, deviceAttrs.get(d, {}))
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
171 self.listeners.outputAttrsSet(d, outputAttrs[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
172 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
173 log.error('failing toOutputAttrs on %s: %r', d, e)
1858
7772cc48e016 reformat all python
drewp@bigasterisk.com
parents: 1809
diff changeset
174
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
175 pendingOut: Dict[OutputUri, Tuple[OutputInstance, bytearray]] = {}
1437
d149a2c2236c always send trailing zeros to dmx
drewp@bigasterisk.com
parents: 1436
diff changeset
176 for out in self.outputs:
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
177 pendingOut[OutputUri(out.uri)] = (out, bytearray(512))
1506
37cbb245d93c fix tests. add logging, some mypy types.
Drew Perttula <drewp@bigasterisk.com>
parents: 1492
diff changeset
178
1859
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
179 for device, attrs in outputAttrs.items():
f066d6e874db 2to3 with these fixers: all idioms set_literal
drewp@bigasterisk.com
parents: 1858
diff changeset
180 for outputAttr, value in attrs.items():
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
181 output, _index = self.outputMap[(device, outputAttr)]
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
182 outputUri = OutputUri(output.uri)
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
183 index = DmxMessageIndex(_index)
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
184 _, outArray = pendingOut[outputUri]
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
185 if outArray[index] != 0:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
186 log.warn(f'conflict: {output} 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
187 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
188 outArray[index] = value
1288
5e76c8fd8a03 rewrite dmx outputter to a new service
Drew Perttula <drewp@bigasterisk.com>
parents:
diff changeset
189
1436
d0d5900a8031 collector run the blocking dmx output calls in another thread, so they don't add delay to our http server
drewp@bigasterisk.com
parents: 1426
diff changeset
190 dt1 = 1000 * (time.time() - now)
1884
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
191 for uri, (out, buf) in pendingOut.items():
5cde72dfdc22 change collector output code to use very specific types. Might fix bugs too.
Drew Perttula <drewp@bigasterisk.com>
parents: 1866
diff changeset
192 out.update(bytes(buf))
1436
d0d5900a8031 collector run the blocking dmx output calls in another thread, so they don't add delay to our http server
drewp@bigasterisk.com
parents: 1426
diff changeset
193 dt2 = 1000 * (time.time() - now)
1676
103d67ebf5e2 collector: less log
drewp@bigasterisk.com
parents: 1602
diff changeset
194 if dt1 > 30:
2072
d5f1cc9615af collector: rewrites for asyncio
drewp@bigasterisk.com
parents: 1975
diff changeset
195 log.warn("slow setAttrs: %.1fms -> flush -> %.1fms. lr %s da %s oa %s" % (dt1, dt2, len(self.lastRequest), len(deviceAttrs), len(outputAttrs)))