comparison light_bridge.py @ 2:c6fd04e07db0

refactor light.py
author drewp@bigasterisk.com
date Sun, 28 Jan 2024 15:44:10 -0800
parents 42a494b8ee1a
children 7eeda7f4f9cd
comparison
equal deleted inserted replaced
1:42a494b8ee1a 2:c6fd04e07db0
1 """ 1 """
2 replaces a lot of mqtt_to_rdf and rdf_to_mqtt 2 replaces a lot of mqtt_to_rdf and rdf_to_mqtt
3 """ 3 """
4 import asyncio
5 from dataclasses import dataclass
6 from functools import partial
7 import json 4 import json
8 import logging 5 import logging
6 from functools import partial
9 import time 7 import time
10 8
11 import background_loop 9 import background_loop
12 from patchablegraph import PatchableGraph 10 from patchablegraph import PatchableGraph
13 from patchablegraph.handler import GraphEvents, StaticGraph 11 from patchablegraph.handler import GraphEvents, StaticGraph
14 from rdflib import Namespace 12 from rdflib import Namespace
13 from sse_starlette.sse import EventSourceResponse
15 from starlette.applications import Starlette 14 from starlette.applications import Starlette
16 from starlette.requests import Request 15 from starlette.requests import Request
17 from starlette.responses import JSONResponse 16 from starlette.responses import JSONResponse
18 from starlette.routing import Route 17 from starlette.routing import Route
19 from starlette_exporter import PrometheusMiddleware, handle_metrics 18 from starlette_exporter import PrometheusMiddleware, handle_metrics
20 from sse_starlette.sse import EventSourceResponse 19
20 from light import Color, Light, Lights
21 21
22 EX = Namespace('http://example.com/') 22 EX = Namespace('http://example.com/')
23 23
24 logging.basicConfig(level=logging.INFO) 24 logging.basicConfig(level=logging.INFO)
25 log = logging.getLogger() 25 log = logging.getLogger()
26
27
28 class Color(str):
29
30 def to_js(self):
31 return self
32
33
34 @dataclass
35 class Light:
36 name: str
37 address: str
38 online: bool
39 colorRequest: Color
40 colorMessage: dict
41 colorCurrent: Color
42 latencyMs: float
43
44 def to_js(self):
45 return {
46 'light': {
47 'name': self.name,
48 'address': self.address,
49 'online': self.online,
50 'colorRequest': self.colorRequest.to_js(),
51 'colorMessage': self.colorMessage,
52 'colorCurrent': self.colorCurrent.to_js(),
53 'latencyMs': self.latencyMs,
54 }
55 }
56
57
58 class Lights:
59 _d: dict[str, Light] = {}
60
61 def add(self, d: Light):
62 self._d[d.name] = d
63
64 def byName(self, name: str) -> Light:
65 return self._d[name]
66
67 async def changes(self): # yields None on any data change
68 while True:
69 yield None
70 await asyncio.sleep(1)
71
72 def to_js(self):
73 return {'lights': [d.to_js() for d in sorted(self._d.values(), key=lambda r: r.name)]}
74 26
75 27
76 async def output(lights: Lights, request: Request) -> JSONResponse: 28 async def output(lights: Lights, request: Request) -> JSONResponse:
77 light = lights.byName(request.query_params['light']) 29 light = lights.byName(request.query_params['light'])
78 return JSONResponse(light.to_js()) 30 return JSONResponse(light.to_js())
80 32
81 async def table(lights: Lights, req: Request) -> EventSourceResponse: 33 async def table(lights: Lights, req: Request) -> EventSourceResponse:
82 34
83 async def g(): 35 async def g():
84 async for ping in lights.changes(): 36 async for ping in lights.changes():
85 await asyncio.sleep(1)
86 yield json.dumps({'now': time.time()} | lights.to_js()) 37 yield json.dumps({'now': time.time()} | lights.to_js())
87 38
88 return EventSourceResponse(g()) 39 return EventSourceResponse(g())
89 40
90 41