diff --git a/pdm.lock b/pdm.lock --- a/pdm.lock +++ b/pdm.lock @@ -5,7 +5,7 @@ groups = ["default", "dev"] strategy = ["cross_platform", "inherit_metadata"] lock_version = "4.4.1" -content_hash = "sha256:5393d5c679935ba9f042f2b4f4d6efd58dbf03519b2e9f25e08f1e9d421e52f1" +content_hash = "sha256:6fac24ed6ab93fd328a74d22973a01c77d9de5b4a0b22cd111a884afd99f235f" [[package]] name = "aiohttp" @@ -2315,19 +2315,6 @@ files = [ ] [[package]] -name = "zmq" -version = "0.0.0" -summary = "You are probably looking for pyzmq." -groups = ["default"] -dependencies = [ - "pyzmq", -] -files = [ - {file = "zmq-0.0.0.tar.gz", hash = "sha256:6b1a1de53338646e8c8405803cffb659e8eb7bb02fff4c9be62a7acfac8370c9"}, - {file = "zmq-0.0.0.zip", hash = "sha256:21cfc6be254c9bc25e4dabb8a3b2006a4227966b7b39a637426084c8dc6901f7"}, -] - -[[package]] name = "zope-interface" version = "6.3" requires_python = ">=3.7" diff --git a/pyproject.toml b/pyproject.toml --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,6 @@ dependencies = [ "scipy>=1.9.3", "braillegraph>=0.6", "tenacity>=8.2.2", - "zmq>=0.0.0", "mido>=1.2.10", "alsa-midi>=1.0.1", "treq>=22.2.0", diff --git a/src/light9/collector/collector.py b/src/light9/collector/collector.py --- a/src/light9/collector/collector.py +++ b/src/light9/collector/collector.py @@ -1,24 +1,38 @@ import logging import time from typing import Dict, List, Set, Tuple, cast -from light9.typedgraph import typedValue from prometheus_client import Summary from rdfdb.syncedgraph.syncedgraph import SyncedGraph -from rdflib import URIRef from light9.collector.device import resolve, toOutputAttrs from light9.collector.output import Output as OutputInstance from light9.collector.weblisteners import WebListeners from light9.effect.settings import DeviceSettings from light9.namespaces import L9, RDF -from light9.newtypes import (ClientSessionType, ClientType, DeviceAttr, DeviceClass, DeviceSetting, DeviceUri, DmxIndex, DmxMessageIndex, OutputAttr, - OutputRange, OutputUri, OutputValue, UnixTime, VTUnion, uriTail) +from light9.newtypes import ( + ClientSessionType, + ClientType, + DeviceAttr, + DeviceClass, + DeviceUri, + DmxIndex, + DmxMessageIndex, + OutputAttr, + OutputRange, + OutputUri, + OutputValue, + UnixTime, + VTUnion, + uriTail, +) +from light9.typedgraph import typedValue log = logging.getLogger('collector') STAT_SETATTR = Summary('set_attr', 'setAttr calls') + def makeDmxMessageIndex(base: DmxIndex, offset: DmxIndex) -> DmxMessageIndex: return DmxMessageIndex(base + offset - 1) diff --git a/src/light9/collector/collector_client_asyncio.py b/src/light9/collector/collector_client_asyncio.py --- a/src/light9/collector/collector_client_asyncio.py +++ b/src/light9/collector/collector_client_asyncio.py @@ -1,12 +1,12 @@ -import asyncio import json import logging import time -from light9 import networking -from light9.effect.settings import DeviceSettings + import zmq.asyncio from prometheus_client import Summary +from light9.effect.settings import DeviceSettings + log = logging.getLogger('coll_client') ZMQ_SEND = Summary('zmq_send', 'calls') diff --git a/src/light9/collector/device.py b/src/light9/collector/device.py --- a/src/light9/collector/device.py +++ b/src/light9/collector/device.py @@ -1,11 +1,20 @@ import logging -from typing import Dict, List, Any, TypeVar, cast -from light9.namespaces import L9 +from typing import Dict, List, cast + +import colormath.color_conversions +from colormath.color_objects import CMYColor, sRGBColor from rdflib import Literal, URIRef from webcolors import hex_to_rgb, rgb_to_hex -from colormath.color_objects import sRGBColor, CMYColor -import colormath.color_conversions -from light9.newtypes import VT, DeviceClass, HexColor, OutputAttr, OutputValue, DeviceUri, DeviceAttr, VTUnion + +from light9.namespaces import L9 +from light9.newtypes import ( + DeviceAttr, + DeviceClass, + HexColor, + OutputAttr, + OutputValue, + VTUnion, +) log = logging.getLogger('device') @@ -50,10 +59,7 @@ def _maxColor(values: List[HexColor]) -> return cast(HexColor, rgb_to_hex(tuple(maxes))) -def resolve( - deviceType: DeviceClass, - deviceAttr: DeviceAttr, - values: List[VTUnion]) -> VTUnion: # todo: return should be VT +def resolve(deviceType: DeviceClass, deviceAttr: DeviceAttr, values: List[VTUnion]) -> VTUnion: # todo: return should be VT """ return one value to use for this attr, given a set of them that have come in simultaneously. len(values) >= 1. @@ -82,8 +88,10 @@ def resolve( def toOutputAttrs( deviceType: DeviceClass, - deviceAttrSettings: Dict[DeviceAttr, VTUnion # TODO - ]) -> Dict[OutputAttr, OutputValue]: + deviceAttrSettings: Dict[ + DeviceAttr, + VTUnion # TODO + ]) -> Dict[OutputAttr, OutputValue]: return dict((OutputAttr(u), OutputValue(v)) for u, v in untype_toOutputAttrs(deviceType, deviceAttrSettings).items()) diff --git a/src/light9/collector/weblisteners.py b/src/light9/collector/weblisteners.py --- a/src/light9/collector/weblisteners.py +++ b/src/light9/collector/weblisteners.py @@ -1,13 +1,11 @@ import asyncio import io -import json import logging import time from typing import Any, Awaitable, Dict, List, Protocol, Tuple import fastavro from fastavro.schema import load_schema -from light9.collector.output import Output as OutputInstance from light9.newtypes import (DeviceUri, DmxIndex, DmxMessageIndex, OutputAttr, OutputUri, OutputValue) import starlette.websockets import websockets @@ -97,5 +95,4 @@ class WebListeners: out = io.BytesIO() fastavro.schemaless_writer(out, self.CollectorUpdateSchema, {'OutputAttrsSet': {'dev': dev, 'attrs': attrRows}}) msg = out.getvalue() - log.info(f'made update message {len(msg)=}') return msg diff --git a/src/light9/effect/edit.py b/src/light9/effect/edit.py --- a/src/light9/effect/edit.py +++ b/src/light9/effect/edit.py @@ -1,11 +1,11 @@ -from rdflib import URIRef, Literal +import treq +from rdfdb.patch import Patch +from rdflib import Literal, URIRef from twisted.internet.defer import inlineCallbacks, returnValue -import treq from light9 import networking from light9.curvecalc.curve import CurveResource from light9.namespaces import L9, RDF, RDFS -from rdfdb.patch import Patch def clamp(x, lo, hi): @@ -53,13 +53,10 @@ def songEffectPatch(graph, dropped, song ] + [(effect, L9['code'], c, ctx) for c in droppedCodes]) elif L9['Submaster'] in droppedTypes: quads.extend([ - (effect, L9['code'], Literal('out = %s * env' % dropped.n3()), - ctx), + (effect, L9['code'], Literal('out = %s * env' % dropped.n3()), ctx), ]) else: - raise NotImplementedError( - "don't know how to add an effect from %r (types=%r)" % - (dropped, droppedTypes)) + raise NotImplementedError("don't know how to add an effect from %r (types=%r)" % (dropped, droppedTypes)) _maybeAddMusicLine(quads, effect, song, ctx) @@ -90,8 +87,7 @@ def songNotePatch(graph, dropped, song, if L9['Effect'] in droppedTypes: musicStatus = yield getMusicStatus() songTime = musicStatus['t'] - note = _makeNote(graph, song, note, quads, ctx, dropped, songTime, - event, fade) + note = _makeNote(graph, song, note, quads, ctx, dropped, songTime, event, fade) else: raise NotImplementedError @@ -99,8 +95,7 @@ def songNotePatch(graph, dropped, song, def _point(ctx, uri, t, v): - return [(uri, L9['time'], Literal(round(t, 3)), ctx), - (uri, L9['value'], Literal(round(v, 3)), ctx)] + return [(uri, L9['time'], Literal(round(t, 3)), ctx), (uri, L9['value'], Literal(round(v, 3)), ctx)] def _finishCurve(graph, note, quads, ctx, songTime): @@ -110,9 +105,7 @@ def _finishCurve(graph, note, quads, ctx pt2 = graph.sequentialUri(curve + 'p') pt3 = graph.sequentialUri(curve + 'p') - quads.extend([(curve, L9['point'], pt2, ctx)] + - _point(ctx, pt2, songTime - origin, 1) + - [(curve, L9['point'], pt3, ctx)] + + quads.extend([(curve, L9['point'], pt2, ctx)] + _point(ctx, pt2, songTime - origin, 1) + [(curve, L9['point'], pt3, ctx)] + _point(ctx, pt3, songTime - origin + .5, 0)) @@ -199,7 +192,5 @@ def _maybeAddMusicLine(quads, effect, so for spoc in quads: if spoc[1] == L9['code'] and 'music' in spoc[2]: - quads.extend([(effect, L9['code'], - Literal('music = %s' % musicCurveForSong(song).n3()), - ctx)]) + quads.extend([(effect, L9['code'], Literal('music = %s' % musicCurveForSong(song).n3()), ctx)]) break diff --git a/src/light9/effect/effect_functions.py b/src/light9/effect/effect_functions.py --- a/src/light9/effect/effect_functions.py +++ b/src/light9/effect/effect_functions.py @@ -1,5 +1,6 @@ import logging import random +from typing import cast from PIL import Image from webcolors import rgb_to_hex @@ -7,13 +8,14 @@ from webcolors import rgb_to_hex from light9.effect.scale import scale from light9.effect.settings import DeviceSettings from light9.namespaces import L9 +from light9.newtypes import HexColor random.seed(0) log = logging.getLogger('effectfunc') -def sample8(img, x, y, repeat=False): +def sample8(img, x, y, repeat=False) -> tuple[int, int, int]: if not (0 <= y < img.height): return (0, 0, 0) if 0 <= x < img.width: @@ -54,10 +56,10 @@ def effect_image( ) -> DeviceSettings: x = int((songTime / period) * image.width) out = [] - for y, (d, da, v) in enumerate(devs.asOrderedList()): + for y, (d, da, v) in enumerate(devs.asList()): if da != L9['color']: continue color8 = sample8(image, x, y, repeat=True) - color = rgb_to_hex(tuple(color8)) - out.append((d, da, scale(color, strength * v))) - return DeviceSettings(devs.graph, out) \ No newline at end of file + color = HexColor(rgb_to_hex(color8)) + out.append((d, da, scale(color, strength * cast(float, v)))) + return DeviceSettings(devs.graph, out) diff --git a/src/light9/effect/effecteval2.py b/src/light9/effect/effecteval2.py --- a/src/light9/effect/effecteval2.py +++ b/src/light9/effect/effecteval2.py @@ -1,6 +1,6 @@ -import traceback import inspect import logging +import traceback from dataclasses import dataclass from typing import Callable, List, Optional @@ -11,7 +11,14 @@ from rdflib.term import Node from light9.effect.effect_function_library import EffectFunctionLibrary from light9.effect.settings import DeviceSettings, EffectSettings from light9.namespaces import L9 -from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, EffectFunction, EffectUri, VTUnion) +from light9.newtypes import ( + DeviceAttr, + DeviceUri, + EffectAttr, + EffectFunction, + EffectUri, + VTUnion, +) from light9.typedgraph import typedValue log = logging.getLogger('effecteval') @@ -92,7 +99,7 @@ class EffectEval2: for arg in c.funcArgs: if arg.annotation == DeviceSettings: v = c.devSettings - if v is None: # asked for ds but we have none + if v is None: # asked for ds but we have none log.debug("%s asked for devs but we have none in config", self.uri) return DeviceSettings(self.graph, []) elif arg.name == 'songTime': diff --git a/src/light9/effect/scale.py b/src/light9/effect/scale.py --- a/src/light9/effect/scale.py +++ b/src/light9/effect/scale.py @@ -1,9 +1,12 @@ +import logging from decimal import Decimal from webcolors import hex_to_rgb, rgb_to_hex from light9.newtypes import VTUnion +log = logging.getLogger('scale') + def scale(value: VTUnion, strength: float): if isinstance(value, Decimal): diff --git a/src/light9/effect/sequencer/eval_faders.py b/src/light9/effect/sequencer/eval_faders.py --- a/src/light9/effect/sequencer/eval_faders.py +++ b/src/light9/effect/sequencer/eval_faders.py @@ -1,6 +1,6 @@ -import traceback import logging import time +import traceback from dataclasses import dataclass from typing import List, Optional, cast diff --git a/src/light9/effect/sequencer/service.py b/src/light9/effect/sequencer/service.py --- a/src/light9/effect/sequencer/service.py +++ b/src/light9/effect/sequencer/service.py @@ -14,8 +14,8 @@ from starlette.applications import Starl from starlette.routing import Route from starlette_exporter import PrometheusMiddleware, handle_metrics +from light9 import networking from light9.background_loop import loop_forever -from light9 import networking from light9.collector.collector_client_asyncio import sendToCollector from light9.effect.effect_function_library import EffectFunctionLibrary from light9.effect.sequencer.eval_faders import FaderEval @@ -51,10 +51,10 @@ async def send_page_updates(request): def main(): graph = SyncedGraph(networking.rdfdb.url, "effectSequencer") logging.getLogger('sse_starlette.sse').setLevel(logging.INFO) - + logging.getLogger('autodepgraphapi').setLevel(logging.INFO) logging.getLogger('syncedgraph').setLevel(logging.INFO) - + logging.getLogger('effecteval').setLevel(logging.INFO) logging.getLogger('seq.fader').setLevel(logging.INFO) diff --git a/src/light9/effect/settings.py b/src/light9/effect/settings.py --- a/src/light9/effect/settings.py +++ b/src/light9/effect/settings.py @@ -19,7 +19,7 @@ from rdflib import Literal, URIRef from light9.collector.device import resolve from light9.localsyncedgraph import LocalSyncedGraph from light9.namespaces import L9, RDF -from light9.newtypes import (DeviceAttr, DeviceUri, EffectAttr, HexColor, VTUnion) +from light9.newtypes import DeviceAttr, DeviceUri, EffectAttr, HexColor, VTUnion log = logging.getLogger('settings')