Mercurial > code > home > repos > light-bridge
annotate light_bridge.py @ 29:35affd4d37d4 default tip
add 1st ikea color light
author | drewp@bigasterisk.com |
---|---|
date | Sat, 14 Dec 2024 22:36:29 -0800 |
parents | 32cfefe3155b |
children |
rev | line source |
---|---|
0 | 1 """ |
2 replaces a lot of mqtt_to_rdf and rdf_to_mqtt | |
3 """ | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
4 import asyncio |
0 | 5 import json |
6 import logging | |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
7 import os |
7 | 8 import time |
2 | 9 from functools import partial |
0 | 10 |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
11 import uvicorn |
0 | 12 from patchablegraph import PatchableGraph |
13 from patchablegraph.handler import GraphEvents, StaticGraph | |
2 | 14 from sse_starlette.sse import EventSourceResponse |
0 | 15 from starlette.applications import Starlette |
16 from starlette.requests import Request | |
17 from starlette.responses import JSONResponse | |
18 from starlette.routing import Route | |
19 from starlette_exporter import PrometheusMiddleware, handle_metrics | |
2 | 20 |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
21 from color import Color |
7 | 22 from light import Lights |
14
e3dbd04dab96
add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents:
11
diff
changeset
|
23 from mqtt_io import MqttIo |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
24 |
0 | 25 logging.basicConfig(level=logging.INFO) |
26 log = logging.getLogger() | |
27 | |
28 | |
29 async def output(lights: Lights, request: Request) -> JSONResponse: | |
30 light = lights.byName(request.query_params['light']) | |
10
140633abfa2a
route colors from PUT to Light.setColor
drewp@bigasterisk.com
parents:
7
diff
changeset
|
31 body = (await request.body()).decode('utf8') |
140633abfa2a
route colors from PUT to Light.setColor
drewp@bigasterisk.com
parents:
7
diff
changeset
|
32 await light.setColor(Color.fromHex(body)) |
5
7eeda7f4f9cd
spell it to_dict, for compat with DataClassJsonMixin
drewp@bigasterisk.com
parents:
2
diff
changeset
|
33 return JSONResponse(light.to_dict()) |
0 | 34 |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
35 |
25 | 36 async def lightNames(lights: Lights, request: Request) -> JSONResponse: |
37 return JSONResponse({'lightNames': lights.allNames()}) | |
38 | |
0 | 39 |
40 async def table(lights: Lights, req: Request) -> EventSourceResponse: | |
41 | |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
42 def updateMessage(): |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
43 return json.dumps({'now': time.time()} | lights.to_dict()) |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
44 |
0 | 45 async def g(): |
11
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
46 yield updateMessage() |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
47 async for ping in lights.changes(): # broken if there's more than one caller! |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
48 log.info('send table event') |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
49 yield updateMessage() |
028ed39aa78f
more ts types; attempted multiplayer but the change events are managed wrong
drewp@bigasterisk.com
parents:
10
diff
changeset
|
50 await asyncio.sleep(.5) # slow down the inf loop |
0 | 51 |
52 return EventSourceResponse(g()) | |
53 | |
54 | |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
55 def crash(request: Request): |
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
56 log.info('crash requested') |
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
57 os.abort() |
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
58 |
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
59 |
0 | 60 def main(): |
14
e3dbd04dab96
add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents:
11
diff
changeset
|
61 mqtt = MqttIo() |
e3dbd04dab96
add mqtt; talk to first light (no throttling)
drewp@bigasterisk.com
parents:
11
diff
changeset
|
62 lights = Lights(mqtt) |
0 | 63 graph = PatchableGraph() |
64 app = Starlette(debug=True, | |
65 routes=[ | |
66 Route('/api/output', partial(output, lights), methods=['PUT']), | |
25 | 67 Route('/api/lightNames', partial(lightNames, lights), methods=['GET']), |
0 | 68 Route('/api/table', partial(table, lights)), |
69 Route('/api/graph', StaticGraph(graph)), | |
70 Route('/api/graph/events', GraphEvents(graph)), | |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
71 Route('/api/crash', crash), |
0 | 72 ]) |
73 | |
74 app.add_middleware(PrometheusMiddleware, app_name='light-bridge') | |
75 app.add_route("/metrics", handle_metrics) | |
76 | |
77 return app | |
78 | |
79 | |
27
32cfefe3155b
try harder to crash if there's an mqtt error, so k8s does a full restart
drewp@bigasterisk.com
parents:
25
diff
changeset
|
80 uvicorn.run(main, host="0.0.0.0", port=8001, log_level=logging.INFO, factory=True) |