rcrf-wifi/ground-station.py
2024-08-08 20:09:32 +02:00

180 lines
5.4 KiB
Python

#!/usr/bin/env python
import asyncio
from websockets.server import serve
adminId = "1234"
BOAT_STATE_INCTRL = 1
BOAT_STATE_AVAILABLE = 0
BOAT_STATE_LOCKED = -1
boats = []
clients = []
def onCMD(data):
global boats, adminId
print("command:" + str(data))
if (len(data) != 4):
return
if (data[1] != adminId):
return
boot = int(data[2])
if (boot >= 0 and boot <= 3):
boats[boot] = data[3]
print(boats)
def sendData(data):
global boats
print("data to send: " + str(data))
async def echoBoats(client):
global boats
data = "boats:"
for boat in boats:
if (boat['state'] != BOAT_STATE_LOCKED):
data += str(boat['id']) + ";" + str(boat['name']) + ";"
if (boat["state"] == BOAT_STATE_AVAILABLE):
data += 'available:'
elif (boat["state"] == BOAT_STATE_INCTRL):
data += 'inctrl:'
await client['ws'].send(data)
async def echoLockedBoats(client):
global boats
if (client['id'] == adminId):
data = "lockedBoats:"
for boat in boats:
if (boat['state'] == BOAT_STATE_LOCKED):
data += str(boat['id']) + ";" + str(boat['name']) + ";locked:"
await client['ws'].send(data + '\n')
async def echoClients(client):
global clients
if (client['id'] == adminId):
data = "clients:"
for client in clients:
data += str(client['id']) + ";" + str(client['boat']) + ";" + str(client['state']) + ":"
await client['ws'].send(data + '\n')
async def takeControll(client, boat):
global boats
if (client['boat'] is not None):
boat["state"] = BOAT_STATE_AVAILABLE
client["boat"] = None
for b in boats:
if (b['id'] == int(boat)):
if (boat['state'] == BOAT_STATE_AVAILABLE):
boat["state"] = BOAT_STATE_INCTRL
print("take controll: " + str(client["id"]) + " -> " + boat["name"])
client["boat"] = b
return
else:
print("WARN: takeControll: " + boat["name"] + " not available (" + str(client["id"]) + ")")
break
async def freeBoat(boat):
global boats, clients
for client in clients:
if (client["boat"]['id'] == boat):
client["boat"] = None
break
for b in boats:
if (b['id'] == int(boat)):
if (boat['state'] == BOAT_STATE_INCTRL):
boat["state"] = BOAT_STATE_AVAILABLE
break
async def lockBoat(boat):
global boats, clients
for client in clients:
if (client["boat"]['id'] == boat):
client["boat"] = None
break
for b in boats:
if (b['id'] == int(boat)):
boat["state"] = BOAT_STATE_LOCKED
break
async def onMessage(message, client):
global boats
data = message.replace('\n', '').split(';')
if(data[0] != client["id"]):
print("invalid id: " + str(data[0]) + " != " + str(client["id"]))
else:
if (data[1] == "boats"):
await echoBoats(client)
elif(data[1] == "ctrl"):
takeControll(client, data[2])
elif(data[1] == "end"):
takeControll(client, -1)
elif(data[1] == "free"):
if (client["id"] == adminId):
freeBoat(data[2])
elif(data[1] == "lock"):
if (client["id"] == adminId):
lockBoat(data[2])
elif(data[1] == "locked"):
await echoLockedBoats(client)
elif(data[1] == "kick"):
print("kick")
elif(data[1] == "clients"):
await echoClients(client)
elif(data[1] == "d"):
if (client['boat'] is None):
print("WARN: controll cmd (" + client['id'] + ") to None: " + data[2])
else:
print("INFO: controll cmd (" + client['id'] + ") to " + client['boat']['name'] + ": " + data[2])
else:
print("WARN: invalid command (" + client['id'] + "): '" + data[1] + "'")
async def newClient(clientId, ws):
client = { "id": clientId, "boat": None, "ws": ws, "state": "active" }
print("new client connected: " + client['id'])
for clie in clients:
if (clie['id'] == client['id']):
clie['state'] = 'terminated'
clients.append(client)
if (client['id'] == adminId):
await echoBoats(client)
await echoLockedBoats(client)
await echoClients(client)
return client
async def newBoat(boatId, name, ws):
boat = { "id": boatId, "name": name, "ws": ws, "state": "active" }
print("new client connected: " + boatId)
for bo in boats:
if (bo['id'] == boat['id']):
bo['state'] = 'terminated'
boats.append(boat)
return boat
async def run(ws, path):
client = None
async for message in ws:
message = message.split(';')
if (len(message) == 3 and message[1] == "4675"):
client = await newClient(message[0], ws)
if (client is not None):
break
elif (len(message) == 3 and message[1] == "3440"):
client = await newBoat(message[0], message[2], ws)
if (client is not None):
break
async for message in ws:
if (client['state'] == 'active'):
await onMessage(message, client)
else:
break
async def main():
async with serve(run, "0.0.0.0", 8080):
await asyncio.Future()
asyncio.run(main())