2020-11-15 17:40:18 +00:00
|
|
|
import asyncio
|
2020-12-20 01:10:19 +00:00
|
|
|
import multiprocessing
|
2020-12-20 18:52:27 +00:00
|
|
|
import queue
|
2021-02-14 13:23:51 +00:00
|
|
|
from typing import Dict, List, Optional
|
2020-11-15 17:40:18 +00:00
|
|
|
import websockets
|
|
|
|
import json
|
|
|
|
|
|
|
|
baps_clients = set()
|
2021-02-14 13:23:51 +00:00
|
|
|
channel_to_q: List[multiprocessing.Queue]
|
2020-12-20 18:52:27 +00:00
|
|
|
webstudio_to_q: List[multiprocessing.Queue]
|
2021-02-14 13:23:51 +00:00
|
|
|
server_name: str
|
2020-11-15 17:40:18 +00:00
|
|
|
|
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
|
2020-11-15 17:40:18 +00:00
|
|
|
async def websocket_handler(websocket, path):
|
|
|
|
baps_clients.add(websocket)
|
2020-11-15 17:48:05 +00:00
|
|
|
await websocket.send(json.dumps({"message": "Hello", "serverName": server_name}))
|
2020-11-15 17:40:18 +00:00
|
|
|
print("New Client: {}".format(websocket))
|
2020-12-20 18:52:27 +00:00
|
|
|
for channel in channel_to_q:
|
|
|
|
channel.put("STATUS")
|
2020-11-15 17:40:18 +00:00
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
async def handle_from_webstudio():
|
|
|
|
try:
|
|
|
|
async for message in websocket:
|
|
|
|
data = json.loads(message)
|
2021-02-14 00:29:47 +00:00
|
|
|
print(data)
|
2021-03-21 20:15:42 +00:00
|
|
|
if not "channel" in data:
|
|
|
|
# Didn't specify a channel, send to all.
|
|
|
|
for channel in range(len(channel_to_q)):
|
|
|
|
sendCommand(channel, data)
|
|
|
|
else:
|
|
|
|
channel = int(data["channel"])
|
|
|
|
sendCommand(channel, data)
|
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
|
|
|
|
await asyncio.wait([conn.send(message) for conn in baps_clients])
|
|
|
|
|
|
|
|
except websockets.exceptions.ConnectionClosedError as e:
|
|
|
|
print("RIP {}, {}".format(websocket, e))
|
|
|
|
|
2021-03-21 20:15:42 +00:00
|
|
|
# TODO: Proper Logging
|
2020-12-20 01:10:19 +00:00
|
|
|
except Exception as e:
|
|
|
|
print("Exception", e)
|
|
|
|
|
|
|
|
finally:
|
|
|
|
baps_clients.remove(websocket)
|
|
|
|
|
2021-03-21 20:15:42 +00:00
|
|
|
def sendCommand(channel, data):
|
|
|
|
if "command" in data.keys():
|
|
|
|
if data["command"] == "PLAY":
|
|
|
|
channel_to_q[channel].put("PLAY")
|
|
|
|
elif data["command"] == "PAUSE":
|
|
|
|
channel_to_q[channel].put("PAUSE")
|
|
|
|
elif data["command"] == "UNPAUSE":
|
|
|
|
channel_to_q[channel].put("UNPAUSE")
|
|
|
|
elif data["command"] == "STOP":
|
|
|
|
channel_to_q[channel].put("STOP")
|
|
|
|
elif data["command"] == "SEEK":
|
|
|
|
channel_to_q[channel].put("SEEK:" + str(data["time"]))
|
|
|
|
elif data["command"] == "LOAD":
|
|
|
|
channel_to_q[channel].put("LOAD:" + str(data["weight"]))
|
|
|
|
|
|
|
|
elif data["command"] == "AUTOADVANCE":
|
|
|
|
channel_to_q[channel].put("AUTOADVANCE:" + str(data["enabled"]))
|
|
|
|
|
|
|
|
elif data["command"] == "PLAYONLOAD":
|
|
|
|
channel_to_q[channel].put("PLAYONLOAD:" + str(data["enabled"]))
|
|
|
|
|
|
|
|
elif data["command"] == "REPEAT":
|
|
|
|
channel_to_q[channel].put("REPEAT:" + str(data["mode"]).lower())
|
|
|
|
|
|
|
|
elif data["command"] == "MOVE":
|
|
|
|
# Should we trust the client with the item info?
|
|
|
|
new_channel = int(data["new_channel"])
|
|
|
|
channel_to_q[channel].put("REMOVE:" + str(data["weight"]))
|
|
|
|
item = data["item"]
|
|
|
|
item["weight"] = int(data["new_weight"])
|
|
|
|
channel_to_q[new_channel].put("ADD:" + json.dumps(item))
|
|
|
|
|
|
|
|
elif data["command"] == "ADD":
|
|
|
|
channel_to_q[channel].put("ADD:" + json.dumps(data["newItem"]))
|
|
|
|
elif data["command"] == "REMOVE":
|
|
|
|
channel_to_q[channel].put("REMOVE:" + str(data["weight"]))
|
|
|
|
elif data["command"] == "GET_PLAN":
|
|
|
|
channel_to_q[channel].put("GET_PLAN:"+ str(data["timeslotId"]))
|
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
async def handle_to_webstudio():
|
|
|
|
while True:
|
2020-12-20 18:52:27 +00:00
|
|
|
for channel in range(len(webstudio_to_q)):
|
2020-12-20 01:10:19 +00:00
|
|
|
try:
|
2020-12-20 18:52:27 +00:00
|
|
|
message = webstudio_to_q[channel].get_nowait()
|
2021-02-14 00:29:47 +00:00
|
|
|
command = message.split(":")[0]
|
2021-02-14 17:53:28 +00:00
|
|
|
#print("Websocket Out:", command)
|
2021-02-14 00:29:47 +00:00
|
|
|
if command == "STATUS":
|
|
|
|
try:
|
|
|
|
message = message.split("OKAY:")[1]
|
|
|
|
message = json.loads(message)
|
|
|
|
except:
|
|
|
|
continue
|
|
|
|
elif command == "POS":
|
|
|
|
message = message.split(":")[1]
|
|
|
|
else:
|
|
|
|
continue
|
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
data = json.dumps({
|
2021-02-14 00:29:47 +00:00
|
|
|
"command": command,
|
2020-12-20 18:52:27 +00:00
|
|
|
"data": message,
|
|
|
|
"channel": channel
|
2020-12-20 01:10:19 +00:00
|
|
|
})
|
|
|
|
await asyncio.wait([conn.send(data) for conn in baps_clients])
|
2020-12-20 18:52:27 +00:00
|
|
|
except queue.Empty:
|
2020-12-20 01:10:19 +00:00
|
|
|
pass
|
2021-02-14 13:23:51 +00:00
|
|
|
except Exception as e:
|
|
|
|
raise e
|
2020-12-20 01:10:19 +00:00
|
|
|
await asyncio.sleep(0.01)
|
|
|
|
|
|
|
|
from_webstudio = asyncio.create_task(handle_from_webstudio())
|
2020-12-20 18:52:27 +00:00
|
|
|
to_webstudio = asyncio.create_task(handle_to_webstudio())
|
2020-11-15 17:40:18 +00:00
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
try:
|
2020-12-20 18:52:27 +00:00
|
|
|
await asyncio.gather(from_webstudio, to_webstudio)
|
2020-11-15 17:40:18 +00:00
|
|
|
finally:
|
2020-12-20 01:10:19 +00:00
|
|
|
from_webstudio.cancel()
|
2020-12-20 18:52:27 +00:00
|
|
|
to_webstudio.cancel()
|
2020-11-15 17:40:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
class WebsocketServer:
|
|
|
|
|
2020-12-20 01:10:19 +00:00
|
|
|
def __init__(self, in_q, out_q, state):
|
2020-11-15 17:40:18 +00:00
|
|
|
global channel_to_q
|
2020-12-20 18:52:27 +00:00
|
|
|
global webstudio_to_q
|
2020-11-15 17:40:18 +00:00
|
|
|
channel_to_q = in_q
|
2020-12-20 18:52:27 +00:00
|
|
|
webstudio_to_q = out_q
|
2020-11-15 17:40:18 +00:00
|
|
|
|
2020-11-15 17:48:05 +00:00
|
|
|
global server_name
|
|
|
|
server_name = state.state["server_name"]
|
|
|
|
|
2020-11-15 17:40:18 +00:00
|
|
|
websocket_server = websockets.serve(websocket_handler, state.state["host"], state.state["ws_port"])
|
|
|
|
|
|
|
|
asyncio.get_event_loop().run_until_complete(websocket_server)
|
|
|
|
asyncio.get_event_loop().run_forever()
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
print("Don't do this")
|