diff --git a/README.md b/README.md index 1350f7f..3bcac97 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,15 @@ ```plantuml @startuml -participant FE as "Frontend" << React >> +participant FE as "Frontend" << JavaScript >> +participant WS as "WS Server" << Python >> participant Funnel as "Funnel" << Python >> participant Segments as "ServeSegments" << Go >> participant CurrentTime as "ServeCurrentTime" << NodeJS >> activate FE #hotpink FE -> FE: Load page - FE -> Funnel: WS Connect + FE -> WS: WS Connect loop #ivory activate Funnel #gold @@ -44,7 +45,8 @@ activate FE #hotpink return HH:MM:SS.ms return ms - Funnel -> FE: WS: Send formatted time + Funnel -> WS: WS: Send complete time + WS --> FE: WS: Send complete time deactivate Funnel end deactivate FE diff --git a/src/frontend/index.html b/src/frontend/index.html new file mode 100644 index 0000000..4bc2ddd --- /dev/null +++ b/src/frontend/index.html @@ -0,0 +1,44 @@ + + + + + + + + Document + + + +

Hello world

+ +

-

+

-

+ + + + + + \ No newline at end of file diff --git a/src/funnel/main.py b/src/funnel/main.py index 6be79a2..f875b4e 100644 --- a/src/funnel/main.py +++ b/src/funnel/main.py @@ -1,9 +1,12 @@ import asyncio +import json import time from contextlib import asynccontextmanager from typing import AsyncGenerator, Optional import grpc +import websockets +from websockets.server import WebSocketServerProtocol from stubs.serve_segments_pb2 import ( GetHoursRequest, @@ -21,6 +24,8 @@ SERVE_CURRENTTIME_HOST = "localhost" SERVE_CURRENTTIME_PORT = 50000 SERVE_SEGMENTS_HOST = "localhost" SERVE_SEGMENTS_PORT = 50001 +WS_HOST = "localhost" +WS_PORT = 5000 TIMEZONE = "Europe/Zagreb" @@ -61,33 +66,62 @@ async def get_milliseconds(stub: ServeSegmentsStub) -> Optional[int]: async def main(): - async with get_serve_segments_stub() as stub: - while True: - t = time.perf_counter() + ws_uri = f"ws://{WS_HOST}:{WS_PORT}" + async with websockets.connect(uri=ws_uri) as websocket: + async with get_serve_segments_stub() as stub: + while True: + t = time.perf_counter() - # create tasks - task_hours = asyncio.create_task(get_hours(stub)) - task_minutes = asyncio.create_task(get_minutes(stub)) - task_seconds = asyncio.create_task(get_seconds(stub)) - task_milliseconds = asyncio.create_task(get_milliseconds(stub)) + # create tasks + task_hours = asyncio.create_task(get_hours(stub)) + task_minutes = asyncio.create_task(get_minutes(stub)) + task_seconds = asyncio.create_task(get_seconds(stub)) + task_milliseconds = asyncio.create_task(get_milliseconds(stub)) - # exec tasks asynchronously - await asyncio.gather( - task_hours, task_minutes, task_seconds, task_milliseconds - ) + # exec tasks asynchronously + await asyncio.gather( + task_hours, task_minutes, task_seconds, task_milliseconds + ) - # get results - hours = task_hours.result() - minutes = task_minutes.result() - seconds = task_seconds.result() - milliseconds = task_milliseconds.result() + # get results + hours = task_hours.result() + minutes = task_minutes.result() + seconds = task_seconds.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( - f"RESULT: {hours:02d}:{minutes:02d}:{seconds:02d}:{milliseconds:03d}, T: {t}" - ) + await websocket.send(json.dumps(data)) + 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__": asyncio.run(main()) + # asyncio.run(send_ws_message()) diff --git a/src/funnel/requirements.txt b/src/funnel/requirements.txt index 221b96b..18cda57 100644 --- a/src/funnel/requirements.txt +++ b/src/funnel/requirements.txt @@ -1,3 +1,4 @@ pydantic grpcio grpcio-tools +websockets diff --git a/src/funnel/ws_server.py b/src/funnel/ws_server.py new file mode 100644 index 0000000..589449e --- /dev/null +++ b/src/funnel/ws_server.py @@ -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())