diff --git a/main.py b/main.py index 524a5a9..d710775 100644 --- a/main.py +++ b/main.py @@ -46,13 +46,19 @@ app.mount("/static", StaticFiles(directory="static"), name="static") ## BUFFER CREATION AND HELPER # Global object to store the latest data latest_data: Dict[str, Any] = { - "PU_1": None, - "PU_2": None, - "PU_3": None, + "PU_1": {"Ploop_sp": 0.0, "Qperm_sp": 0.0}, + "PU_2": {"Ploop_sp": 0.0, "Qperm_sp": 0.0}, + "PU_3": {"Ploop_sp": 0.0, "Qperm_sp": 0.0}, "DS": None, "PatientSkid": {"QSkid": 0.0}, } +latest_setpoints: Dict[str, Any] = { + "PU_1": {"Ploop_sp": 2.5, "Qperm_sp": 1200}, + "PU_2": {"Ploop_sp": 2.5, "Qperm_sp": 1200}, + "PU_3": {"Ploop_sp": 2.5, "Qperm_sp": 1200}, +} + active_PUs: list[int] = [] # RECORDER @@ -110,6 +116,20 @@ def format_DS_data(data): "Qoutlet": np.round(data.get("Outlet_flow", 0.0), 1), } +## Fetch setpoints +def update_setpoints(p_loop_setpoint : float, q_perm_setpoint : float, pu : int): + global latest_setpoints + pu_key = "PU_"+str(pu) + latest_setpoints[pu_key]["Ploop_sp"] = p_loop_setpoint + latest_setpoints[pu_key]["Qperm_sp"] = q_perm_setpoint + +def format_setpoints(pu: int): # THis is a bit convoluted to pass from an object to another but it works + global latest_setpoints, latest_data + pu_key = "PU_" + str(pu) + latest_data[pu_key]["Ploop_sp"] = latest_setpoints[pu_key]["Ploop_sp"] + latest_data[pu_key]["Qperm_sp"] = latest_setpoints[pu_key]["Qperm_sp"] + + # CREDENTIALS CREDENTIAL_PATH = Path("credentials.json") if CREDENTIAL_PATH.exists(): @@ -255,6 +275,7 @@ def send_command(state: str, pu_number: int, ploop_setpoint: float = Query(...), raise HTTPException(status_code=400, detail=f"Invalid state '{state}'") logging.info(f"Sending state '{state}' to PU {pu_number}") + update_setpoints(ploop_setpoint, qperm_setpoint, pu_number) pu_number = [pu_number] if pu_number !=3 else [1,2] # Temporary way of starting two pus @@ -296,14 +317,14 @@ def get_pu_status(): "PU2": can_backend.read_current_state(2), "PU3": can_backend.read_current_state(3), } - logging.info(f"[PU STATUS] {states}") + logging.debug(f"[PU STATUS] {states}") active_PUs = [ index + 1 for index, (pu, status) in enumerate(states.items()) if status != "Offline" ] - logging.info(f"[ACTIVE PU] {active_PUs}") + logging.debug(f"[ACTIVE PU] {active_PUs}") return JSONResponse(content=states) @@ -318,6 +339,7 @@ async def update_latest_data(): for pu in active_PUs: data = can_backend.get_latest_data(pu_number=pu) latest_data[f"PU_{pu}"] = format_PU_data(data) + format_setpoints(pu) logging.debug(f"[MONITOR DS BUFFER] latest_data: {latest_data}") await asyncio.sleep(0.05) @@ -325,7 +347,6 @@ async def update_latest_data(): @app.get("/monitor") async def get_monitor_data(): return latest_data - # return JSONResponse(content=latest_data) # LOCAL RECORDER @app.post("/start_recording") diff --git a/static/monitor_PU.html b/static/monitor_PU.html index 2ced5b4..1b874af 100644 --- a/static/monitor_PU.html +++ b/static/monitor_PU.html @@ -83,20 +83,22 @@ const DSData = allData[`DS`]; const t = new Date(puData.timestamp); - Plotly.extendTraces('flow-plot-1', { - x: [[t], [t]], - y: [[puData.Qperm], [puData.Qdilute]] - }, [0, 1], maxPoints); + Plotly.extendTraces('flow-plot-1', + { x: [[t], [t], [t]], y: [[puData.Qperm], [puData.Qdilute], [puData.Qperm_sp]] }, + [0, 1, 2], + maxPoints + ); Plotly.extendTraces('flow-plot-2', { x: [[t], [t], [t], [t], [t], [t]], y: [[puData.Qdrain], [puData.Qrecirc], [SkidData.QSkid], [puData.QdrainEDI], [DSData.Qconso], [puData.Qdrain_sp]] }, [0, 1, 2, 3, 4, 5], maxPoints); - Plotly.extendTraces('pressure-plot-1', { - x: [[t], [t]], - y: [[puData.Pro], [puData.Pretentate]] - }, [0, 1], maxPoints); + Plotly.extendTraces('pressure-plot-1', + { x: [[t], [t], [t]], y: [[puData.Pro], [puData.Pretentate], [puData.Ploop_sp]] }, + [0, 1, 2], + maxPoints + ); Plotly.extendTraces('pressure-plot-2', { x: [[t]], @@ -167,12 +169,15 @@ Plotly.newPlot('flow-plot-1', [ { x: time0, y: [0], name: 'Qperm', mode: 'lines' }, - { x: time0, y: [0], name: 'Qdilute', mode: 'lines' } + { x: time0, y: [0], name: 'Qdilute', mode: 'lines' }, + { x: time0, y: [0], name: 'Qperm_sp', mode: 'lines', line: { dash: 'dash', color: 'red' } } ], { title: 'Qperm and Qdilute', - xaxis: { type: 'date' }, yaxis: { title: 'Flow (L/h)' } + xaxis: { type: 'date' }, + yaxis: { title: 'Flow (L/h)' } }); + Plotly.newPlot('flow-plot-2', [ { x: time0, y: [0], name: 'Qdrain', mode: 'lines' }, { x: time0, y: [0], name: 'Qrecirc', mode: 'lines' }, @@ -186,9 +191,12 @@ Plotly.newPlot('pressure-plot-1', [ { x: time0, y: [0], name: 'Pro', mode: 'lines' }, - { x: time0, y: [0], name: 'Pretentate', mode: 'lines' } + { x: time0, y: [0], name: 'Pretentate', mode: 'lines' }, + { x: time0, y: [0], name: 'Ploop_sp', mode: 'lines', line: { dash: 'dash', color: 'red' } } ], { - title: 'Pro and Pretentate ', xaxis: { type: 'date' }, yaxis: { title: 'Pressure (bar)' } + title: 'Pro and Pretentate', + xaxis: { type: 'date' }, + yaxis: { title: 'Pressure (bar)' } }); Plotly.newPlot('pressure-plot-2', [ diff --git a/static/multi_pu_dashboard.html b/static/multi_pu_dashboard.html index 1744dff..767015a 100644 --- a/static/multi_pu_dashboard.html +++ b/static/multi_pu_dashboard.html @@ -14,10 +14,27 @@ h1 { text-align: center; } + .status-container { + display: flex; + justify-content: center; + gap: 20px; + margin: 10px 0; + padding: 10px; + background-color: #f5f5f5; + border-radius: 8px; + } + .status-box { + padding: 8px 15px; + border-radius: 5px; + background-color: #e0e0e0; + font-weight: bold; + min-width: 100px; + text-align: center; + } .plot-container { display: flex; flex-direction: column; - gap: 10px; + gap: 5px; align-items: center; } .plot { @@ -28,6 +45,14 @@