annotate light_bridge.py @ 0:5a77696c6dab

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