WS server

This commit is contained in:
Eden Kirin
2023-03-24 08:08:38 +01:00
parent 83a54a8848
commit ee741cc924
5 changed files with 142 additions and 24 deletions

View File

@ -5,14 +5,15 @@
```plantuml ```plantuml
@startuml @startuml
participant FE as "Frontend" << React >> participant FE as "Frontend" << JavaScript >>
participant WS as "WS Server" << Python >>
participant Funnel as "Funnel" << Python >> participant Funnel as "Funnel" << Python >>
participant Segments as "ServeSegments" << Go >> participant Segments as "ServeSegments" << Go >>
participant CurrentTime as "ServeCurrentTime" << NodeJS >> participant CurrentTime as "ServeCurrentTime" << NodeJS >>
activate FE #hotpink activate FE #hotpink
FE -> FE: Load page FE -> FE: Load page
FE -> Funnel: WS Connect FE -> WS: WS Connect
loop #ivory loop #ivory
activate Funnel #gold activate Funnel #gold
@ -44,7 +45,8 @@ activate FE #hotpink
return HH:MM:SS.ms return HH:MM:SS.ms
return ms return ms
Funnel -> FE: WS: Send formatted time Funnel -> WS: WS: Send complete time
WS --> FE: WS: Send complete time
deactivate Funnel deactivate Funnel
end end
deactivate FE deactivate FE

44
src/frontend/index.html Normal file
View File

@ -0,0 +1,44 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello world</h1>
<h2 id="formatted-time">-</h2>
<h3 id="comm-cycle">-</h3>
</body>
<script type="module">
window.onload = function () {
const ws = new WebSocket('ws://localhost:5000');
ws.onmessage = function (event) {
const data = JSON.parse(event.data);
//console.log("message received:", data)
document.getElementById("formatted-time").innerHTML = data.formattedTime;
document.getElementById("comm-cycle").innerHTML = data.commCycleStr;
//ws.close();
}
ws.onopen = function () {
console.log("open");
}
ws.onclose = function () {
console.log("close");
}
ws.onerror = function () {
console.log("error");
}
}
</script>
</html>

View File

@ -1,9 +1,12 @@
import asyncio import asyncio
import json
import time import time
from contextlib import asynccontextmanager from contextlib import asynccontextmanager
from typing import AsyncGenerator, Optional from typing import AsyncGenerator, Optional
import grpc import grpc
import websockets
from websockets.server import WebSocketServerProtocol
from stubs.serve_segments_pb2 import ( from stubs.serve_segments_pb2 import (
GetHoursRequest, GetHoursRequest,
@ -21,6 +24,8 @@ SERVE_CURRENTTIME_HOST = "localhost"
SERVE_CURRENTTIME_PORT = 50000 SERVE_CURRENTTIME_PORT = 50000
SERVE_SEGMENTS_HOST = "localhost" SERVE_SEGMENTS_HOST = "localhost"
SERVE_SEGMENTS_PORT = 50001 SERVE_SEGMENTS_PORT = 50001
WS_HOST = "localhost"
WS_PORT = 5000
TIMEZONE = "Europe/Zagreb" TIMEZONE = "Europe/Zagreb"
@ -61,33 +66,62 @@ async def get_milliseconds(stub: ServeSegmentsStub) -> Optional[int]:
async def main(): async def main():
async with get_serve_segments_stub() as stub: ws_uri = f"ws://{WS_HOST}:{WS_PORT}"
while True: async with websockets.connect(uri=ws_uri) as websocket:
t = time.perf_counter() async with get_serve_segments_stub() as stub:
while True:
t = time.perf_counter()
# create tasks # create tasks
task_hours = asyncio.create_task(get_hours(stub)) task_hours = asyncio.create_task(get_hours(stub))
task_minutes = asyncio.create_task(get_minutes(stub)) task_minutes = asyncio.create_task(get_minutes(stub))
task_seconds = asyncio.create_task(get_seconds(stub)) task_seconds = asyncio.create_task(get_seconds(stub))
task_milliseconds = asyncio.create_task(get_milliseconds(stub)) task_milliseconds = asyncio.create_task(get_milliseconds(stub))
# exec tasks asynchronously # exec tasks asynchronously
await asyncio.gather( await asyncio.gather(
task_hours, task_minutes, task_seconds, task_milliseconds task_hours, task_minutes, task_seconds, task_milliseconds
) )
# get results # get results
hours = task_hours.result() hours = task_hours.result()
minutes = task_minutes.result() minutes = task_minutes.result()
seconds = task_seconds.result() seconds = task_seconds.result()
milliseconds = task_milliseconds.result() milliseconds = task_milliseconds.result()
formatted_time = (
f"{hours:02d}:{minutes:02d}:{seconds:02d}:{milliseconds:03d}"
)
comm_cycle = time.perf_counter() - t
t = time.perf_counter() - t data = {
"hours": hours,
"minutes": minutes,
"seconds": seconds,
"milliseconds": milliseconds,
"formattedTime": formatted_time,
"commCycle": comm_cycle,
"commCycleStr": f"{comm_cycle:0.4f}",
}
print( await websocket.send(json.dumps(data))
f"RESULT: {hours:02d}:{minutes:02d}:{seconds:02d}:{milliseconds:03d}, T: {t}" await websocket.recv()
)
# time.sleep(0.5)
print(f"RESULT: {formatted_time}, T: {comm_cycle}")
async def send_ws_message():
ws_uri = f"ws://{WS_HOST}:{WS_PORT}"
async with websockets.connect(ws_uri) as websocket:
data = {
"message": "some text",
"value": 12345,
}
await websocket.send(json.dumps(data))
if __name__ == "__main__": if __name__ == "__main__":
asyncio.run(main()) asyncio.run(main())
# asyncio.run(send_ws_message())

View File

@ -1,3 +1,4 @@
pydantic pydantic
grpcio grpcio
grpcio-tools grpcio-tools
websockets

37
src/funnel/ws_server.py Normal file
View File

@ -0,0 +1,37 @@
import asyncio
import json
import websockets
from websockets import broadcast
from websockets.server import WebSocketServerProtocol
WS_HOST = "localhost"
WS_PORT = 5000
connected_clients = set()
async def ws_handler(websocket: WebSocketServerProtocol):
connected_clients.add(websocket)
print("Client add: ", websocket)
try:
async for message in websocket:
broadcast(connected_clients, message)
# await websocket.send(f"Are you talking to me? {message}")
finally:
connected_clients.remove(websocket)
print("Client remove: ", websocket)
async def main():
print(f"Starting WS server on {WS_HOST}:{WS_PORT}")
async with websockets.serve(
ws_handler=ws_handler,
host=WS_HOST,
port=WS_PORT,
):
await asyncio.Future() # run forever
if __name__ == "__main__":
asyncio.run(main())