120 lines
2.9 KiB
Python
120 lines
2.9 KiB
Python
from typing import (
|
|
Annotated,
|
|
AsyncGenerator,
|
|
Final,
|
|
Generator,
|
|
List,
|
|
Literal,
|
|
Optional,
|
|
Tuple,
|
|
TypeVar,
|
|
TypedDict,
|
|
Any,
|
|
cast,
|
|
)
|
|
|
|
from loguru import logger
|
|
import numpy as np
|
|
import plotly.graph_objects as go
|
|
import streamlit as st
|
|
import anyio
|
|
from anyio.abc import TaskGroup, UDPSocket
|
|
from anyio import create_memory_object_stream, create_udp_socket
|
|
from anyio.streams.memory import MemoryObjectSendStream, MemoryObjectReceiveStream
|
|
from threading import Thread
|
|
from time import sleep
|
|
from pydantic import BaseModel, computed_field
|
|
from datetime import datetime
|
|
import awkward as ak
|
|
from awkward import Array as AwkwardArray, Record as AwkwardRecord
|
|
from app.model import AlgoReport
|
|
from collections import deque
|
|
|
|
|
|
# https://handmadesoftware.medium.com/streamlit-asyncio-and-mongodb-f85f77aea825
|
|
class AppState(TypedDict):
|
|
worker_thread: Thread
|
|
message_queue: MemoryObjectReceiveStream[bytes]
|
|
task_group: TaskGroup
|
|
history: deque[AlgoReport]
|
|
|
|
|
|
UDP_SERVER_HOST: Final[str] = "localhost"
|
|
UDP_SERVER_PORT: Final[int] = 50_000
|
|
MAX_LENGTH = 600
|
|
NDArray = np.ndarray
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
def unwrap(value: Optional[T]) -> T:
|
|
if value is None:
|
|
raise ValueError("Value is None")
|
|
return value
|
|
|
|
|
|
@st.cache_resource
|
|
def resource(params: Any = None):
|
|
set_ev = anyio.Event()
|
|
tx, rx = create_memory_object_stream[bytes]()
|
|
tg: Optional[TaskGroup] = None
|
|
|
|
async def poll_task():
|
|
nonlocal set_ev
|
|
nonlocal tg
|
|
tg = anyio.create_task_group()
|
|
set_ev.set()
|
|
async with tg:
|
|
async with await create_udp_socket(
|
|
local_host=UDP_SERVER_HOST, local_port=UDP_SERVER_PORT, reuse_port=True
|
|
) as udp:
|
|
async for packet, _ in udp:
|
|
await tx.send(packet)
|
|
|
|
tr = Thread(target=anyio.run, args=(poll_task,))
|
|
tr.start()
|
|
while not set_ev.is_set():
|
|
sleep(0.01)
|
|
logger.info("Poll task initialized")
|
|
state: AppState = {
|
|
"worker_thread": tr,
|
|
"message_queue": rx,
|
|
"task_group": unwrap(tg),
|
|
"history": deque(maxlen=MAX_LENGTH),
|
|
}
|
|
return state
|
|
|
|
|
|
def main():
|
|
state = resource()
|
|
logger.info("Resource created")
|
|
history = state["history"]
|
|
|
|
def on_export():
|
|
raise NotImplementedError
|
|
|
|
def on_clear():
|
|
raise NotImplementedError
|
|
|
|
st.button(
|
|
"Export", help="Export the current data to a parquet file", on_click=on_export
|
|
)
|
|
st.button("Clear", help="Clear the current data", on_click=on_clear)
|
|
pannel = st.empty()
|
|
while True:
|
|
try:
|
|
message = state["message_queue"].receive_nowait()
|
|
except anyio.WouldBlock:
|
|
continue
|
|
report = AlgoReport.unmarshal(message)
|
|
logger.info("Report: {}", report)
|
|
# TODO: plot
|
|
# fig = go.Figure(scatters)
|
|
# pannel.plotly_chart(fig)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|
|
# 1659A202
|