Files
moodconsole/main.py

107 lines
2.6 KiB
Python

#!/usr/bin/env python
# WS server example that synchronizes state across clients
import os
import asyncio
import json
import logging
import websockets
import processor
import random
import time
import state
import tornado.ioloop
import tornado.web
logging.basicConfig()
USERS = set()
def state_event(state):
return json.dumps({
"type": "state",
"payload": {**state}
})
def options_event():
return json.dumps({
"type": "options",
"payload": {
**processor.get_options()
}
})
def users_event():
return json.dumps({"type": "users", "count": len(USERS)})
async def notify_state(old_state, new_state):
if USERS: # asyncio.wait doesn't accept an empty list
message = state_event(new_state)
await asyncio.wait([user.send(message) for user in USERS])
async def notify_users():
if USERS: # asyncio.wait doesn't accept an empty list
message = users_event()
await asyncio.wait([user.send(message) for user in USERS])
async def register(websocket):
USERS.add(websocket)
await notify_users()
async def unregister(websocket):
USERS.remove(websocket)
await notify_users()
async def ws_handler(websocket, path):
# register(websocket) sends user_event() to websocket
await register(websocket)
try:
await websocket.send(state_event(state.get_data()))
await websocket.send(options_event())
async for message in websocket:
data = json.loads(message)
if data["type"] == "mutation":
asyncio.create_task(state.propagate(data["payload"]))
else:
logging.error("unsupported event: {}", data)
finally:
await unregister(websocket)
async def serve_ws():
state.register_on_change_callback(notify_state)
await state.inc_initialized()
start_server = websockets.serve(ws_handler, "0.0.0.0", 6789)
await start_server
async def tick():
while True:
logging.warning("tick")
await asyncio.sleep(1)
async def serve_http():
settings={
"static_path": os.path.join(os.path.dirname(__file__), "frontend"),
"static_url_prefix": "/",
"static_handler_args": dict(default_filename="index.html")
}
app = tornado.web.Application(
[ (r"/(.*)", tornado.web.StaticFileHandler, dict(path=settings['static_path'], default_filename="index.html")) ],
**settings)
app.listen(8888)
async def main():
random.seed(time.time())
await asyncio.gather(
tick(),
serve_ws(),
serve_http(),
processor.main(["192.168.178.123", "192.168.178.124"]),
)
asyncio.run(main())