annotate light_bridge.py @ 1:42a494b8ee1a

show report time
author drewp@bigasterisk.com
date Sun, 28 Jan 2024 15:43:54 -0800
parents 5a77696c6dab
children c6fd04e07db0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
drewp@bigasterisk.com
parents:
diff changeset
1 """
drewp@bigasterisk.com
parents:
diff changeset
2 replaces a lot of mqtt_to_rdf and rdf_to_mqtt
drewp@bigasterisk.com
parents:
diff changeset
3 """
drewp@bigasterisk.com
parents:
diff changeset
4 import asyncio
drewp@bigasterisk.com
parents:
diff changeset
5 from dataclasses import dataclass
drewp@bigasterisk.com
parents:
diff changeset
6 from functools import partial
drewp@bigasterisk.com
parents:
diff changeset
7 import json
drewp@bigasterisk.com
parents:
diff changeset
8 import logging
1
42a494b8ee1a show report time
drewp@bigasterisk.com
parents: 0
diff changeset
9 import time
0
drewp@bigasterisk.com
parents:
diff changeset
10
drewp@bigasterisk.com
parents:
diff changeset
11 import background_loop
drewp@bigasterisk.com
parents:
diff changeset
12 from patchablegraph import PatchableGraph
drewp@bigasterisk.com
parents:
diff changeset
13 from patchablegraph.handler import GraphEvents, StaticGraph
drewp@bigasterisk.com
parents:
diff changeset
14 from rdflib import Namespace
drewp@bigasterisk.com
parents:
diff changeset
15 from starlette.applications import Starlette
drewp@bigasterisk.com
parents:
diff changeset
16 from starlette.requests import Request
drewp@bigasterisk.com
parents:
diff changeset
17 from starlette.responses import JSONResponse
drewp@bigasterisk.com
parents:
diff changeset
18 from starlette.routing import Route
drewp@bigasterisk.com
parents:
diff changeset
19 from starlette_exporter import PrometheusMiddleware, handle_metrics
drewp@bigasterisk.com
parents:
diff changeset
20 from sse_starlette.sse import EventSourceResponse
drewp@bigasterisk.com
parents:
diff changeset
21
drewp@bigasterisk.com
parents:
diff changeset
22 EX = Namespace('http://example.com/')
drewp@bigasterisk.com
parents:
diff changeset
23
drewp@bigasterisk.com
parents:
diff changeset
24 logging.basicConfig(level=logging.INFO)
drewp@bigasterisk.com
parents:
diff changeset
25 log = logging.getLogger()
drewp@bigasterisk.com
parents:
diff changeset
26
drewp@bigasterisk.com
parents:
diff changeset
27
drewp@bigasterisk.com
parents:
diff changeset
28 class Color(str):
drewp@bigasterisk.com
parents:
diff changeset
29
drewp@bigasterisk.com
parents:
diff changeset
30 def to_js(self):
drewp@bigasterisk.com
parents:
diff changeset
31 return self
drewp@bigasterisk.com
parents:
diff changeset
32
drewp@bigasterisk.com
parents:
diff changeset
33
drewp@bigasterisk.com
parents:
diff changeset
34 @dataclass
drewp@bigasterisk.com
parents:
diff changeset
35 class Light:
drewp@bigasterisk.com
parents:
diff changeset
36 name: str
drewp@bigasterisk.com
parents:
diff changeset
37 address: str
drewp@bigasterisk.com
parents:
diff changeset
38 online: bool
drewp@bigasterisk.com
parents:
diff changeset
39 colorRequest: Color
drewp@bigasterisk.com
parents:
diff changeset
40 colorMessage: dict
drewp@bigasterisk.com
parents:
diff changeset
41 colorCurrent: Color
drewp@bigasterisk.com
parents:
diff changeset
42 latencyMs: float
drewp@bigasterisk.com
parents:
diff changeset
43
drewp@bigasterisk.com
parents:
diff changeset
44 def to_js(self):
drewp@bigasterisk.com
parents:
diff changeset
45 return {
drewp@bigasterisk.com
parents:
diff changeset
46 'light': {
drewp@bigasterisk.com
parents:
diff changeset
47 'name': self.name,
drewp@bigasterisk.com
parents:
diff changeset
48 'address': self.address,
drewp@bigasterisk.com
parents:
diff changeset
49 'online': self.online,
drewp@bigasterisk.com
parents:
diff changeset
50 'colorRequest': self.colorRequest.to_js(),
drewp@bigasterisk.com
parents:
diff changeset
51 'colorMessage': self.colorMessage,
drewp@bigasterisk.com
parents:
diff changeset
52 'colorCurrent': self.colorCurrent.to_js(),
drewp@bigasterisk.com
parents:
diff changeset
53 'latencyMs': self.latencyMs,
drewp@bigasterisk.com
parents:
diff changeset
54 }
drewp@bigasterisk.com
parents:
diff changeset
55 }
drewp@bigasterisk.com
parents:
diff changeset
56
drewp@bigasterisk.com
parents:
diff changeset
57
drewp@bigasterisk.com
parents:
diff changeset
58 class Lights:
drewp@bigasterisk.com
parents:
diff changeset
59 _d: dict[str, Light] = {}
drewp@bigasterisk.com
parents:
diff changeset
60
drewp@bigasterisk.com
parents:
diff changeset
61 def add(self, d: Light):
drewp@bigasterisk.com
parents:
diff changeset
62 self._d[d.name] = d
drewp@bigasterisk.com
parents:
diff changeset
63
drewp@bigasterisk.com
parents:
diff changeset
64 def byName(self, name: str) -> Light:
drewp@bigasterisk.com
parents:
diff changeset
65 return self._d[name]
drewp@bigasterisk.com
parents:
diff changeset
66
drewp@bigasterisk.com
parents:
diff changeset
67 async def changes(self): # yields None on any data change
drewp@bigasterisk.com
parents:
diff changeset
68 while True:
drewp@bigasterisk.com
parents:
diff changeset
69 yield None
drewp@bigasterisk.com
parents:
diff changeset
70 await asyncio.sleep(1)
drewp@bigasterisk.com
parents:
diff changeset
71
drewp@bigasterisk.com
parents:
diff changeset
72 def to_js(self):
drewp@bigasterisk.com
parents:
diff changeset
73 return {'lights': [d.to_js() for d in sorted(self._d.values(), key=lambda r: r.name)]}
drewp@bigasterisk.com
parents:
diff changeset
74
drewp@bigasterisk.com
parents:
diff changeset
75
drewp@bigasterisk.com
parents:
diff changeset
76 async def output(lights: Lights, request: Request) -> JSONResponse:
drewp@bigasterisk.com
parents:
diff changeset
77 light = lights.byName(request.query_params['light'])
drewp@bigasterisk.com
parents:
diff changeset
78 return JSONResponse(light.to_js())
drewp@bigasterisk.com
parents:
diff changeset
79
drewp@bigasterisk.com
parents:
diff changeset
80
drewp@bigasterisk.com
parents:
diff changeset
81 async def table(lights: Lights, req: Request) -> EventSourceResponse:
drewp@bigasterisk.com
parents:
diff changeset
82
drewp@bigasterisk.com
parents:
diff changeset
83 async def g():
drewp@bigasterisk.com
parents:
diff changeset
84 async for ping in lights.changes():
drewp@bigasterisk.com
parents:
diff changeset
85 await asyncio.sleep(1)
1
42a494b8ee1a show report time
drewp@bigasterisk.com
parents: 0
diff changeset
86 yield json.dumps({'now': time.time()} | lights.to_js())
0
drewp@bigasterisk.com
parents:
diff changeset
87
drewp@bigasterisk.com
parents:
diff changeset
88 return EventSourceResponse(g())
drewp@bigasterisk.com
parents:
diff changeset
89
drewp@bigasterisk.com
parents:
diff changeset
90
drewp@bigasterisk.com
parents:
diff changeset
91 def main():
drewp@bigasterisk.com
parents:
diff changeset
92 lights = Lights()
drewp@bigasterisk.com
parents:
diff changeset
93 lights.add(Light('do-desk', 'topic1', True, Color('#ff0000'), {'r': 255}, Color('#000000'), 100))
drewp@bigasterisk.com
parents:
diff changeset
94 lights.add(Light('do-desk2', 'topic2', True, Color('#ff00ff'), {'r': 255}, Color('#000000'), 200))
drewp@bigasterisk.com
parents:
diff changeset
95 graph = PatchableGraph()
drewp@bigasterisk.com
parents:
diff changeset
96 app = Starlette(debug=True,
drewp@bigasterisk.com
parents:
diff changeset
97 routes=[
drewp@bigasterisk.com
parents:
diff changeset
98 Route('/api/output', partial(output, lights), methods=['PUT']),
drewp@bigasterisk.com
parents:
diff changeset
99 Route('/api/table', partial(table, lights)),
drewp@bigasterisk.com
parents:
diff changeset
100 Route('/api/graph', StaticGraph(graph)),
drewp@bigasterisk.com
parents:
diff changeset
101 Route('/api/graph/events', GraphEvents(graph)),
drewp@bigasterisk.com
parents:
diff changeset
102 ])
drewp@bigasterisk.com
parents:
diff changeset
103
drewp@bigasterisk.com
parents:
diff changeset
104 app.add_middleware(PrometheusMiddleware, app_name='light-bridge')
drewp@bigasterisk.com
parents:
diff changeset
105 app.add_route("/metrics", handle_metrics)
drewp@bigasterisk.com
parents:
diff changeset
106 # app.state.loop = background_loop.loop_forever(lambda first_run=False: update(graph), 1)
drewp@bigasterisk.com
parents:
diff changeset
107
drewp@bigasterisk.com
parents:
diff changeset
108 return app
drewp@bigasterisk.com
parents:
diff changeset
109
drewp@bigasterisk.com
parents:
diff changeset
110
drewp@bigasterisk.com
parents:
diff changeset
111 app = main()