diff --git a/MockCAN.py b/MockCAN.py new file mode 100644 index 0000000..fdc6a71 --- /dev/null +++ b/MockCAN.py @@ -0,0 +1,35 @@ +import numpy as np + +PUs_states = [{"PU_MODE": "OFF","ploop_setpoint":0.0},{"PU_MODE": "OFF","ploop_setpoint":0.0},{"PU_MODE": "OFF","ploop_setpoint":0.0}] # data[i] is PU_i dictionnary + +# Placeholder for CAN backend +class CANBackend: + def __init__(self): + self.connected = False + + def connect(self, node_id: int, eds_path: str) -> bool: + # Placeholder for connection logic + self.connected = True + return True + + def shutdown(self): + self.connected = False + + + def read_current_state(self,pu_number: int): + # Placeholder for reading mode command + return PUs_states[pu_number-1] + + def send_thermal_loop_cleaning(self, mode: str): + # Placeholder for thermal loop cleaning + pass + + def send_state_command(self, state: str, pu_number : int, ploop_setpoint : float): + # Placeholder for sending mode command + PUs_states[pu_number-1] = {"PU_MODE": state, "ploop_setpoint":ploop_setpoint} + + + def get_latest_data(self): + # Placeholder for getting latest TPDO data + return {"FM2" : round(1000*np.random.random(),1),"PS1" : round(10*np.random.random(),2)} + diff --git a/classCAN.py b/classCAN.py index eda934c..6e32df0 100644 --- a/classCAN.py +++ b/classCAN.py @@ -56,8 +56,14 @@ class CANBackend: def get_latest_data(self): with self.lock: return self.latest_data.copy() + + def read_current_state(self,pu_number: int): + # Placeholder for reading mode command + #TODO : CODE IT + pass - def send_state_command(self, state: str, pu_number: int): + def send_state_command(self, state: str, pu_number: int, ploop_setpoint:float): + #TODO : link ploop_setpoint if not self.connected: raise RuntimeError("CAN not connected") diff --git a/main.py b/main.py index 0c0f916..9d2d5dc 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,12 @@ -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI, HTTPException, Query from fastapi.staticfiles import StaticFiles from fastapi.responses import HTMLResponse import logging -from classCAN import CANBackend # Your real backend +import platform +if platform.system() in ['Darwin']: # macOS or Windows + from MockCAN import CANBackend +else : + from classCAN import CANBackend # Your real backend app = FastAPI() logging.basicConfig(level=logging.INFO) @@ -29,50 +33,26 @@ def connect_toggle(): return {"connected": True} @app.post("/command/{state}/pu/{pu_number}") -def send_command(state: str, pu_number: int): +def send_command(state: str, pu_number: int, ploop_setpoint: float = Query(...)): """Send a state command to a specific PU.""" - logging.info(f"Sending state '{state}' to PU {pu_number}") + logging.info(f"Sending state '{state}' to PU {pu_number} with ploop_setpoint {ploop_setpoint}") try: - can_backend.send_state_command(state.upper(), pu_number) - return {"status": "success", "command": state.upper(), "pu": pu_number} + can_backend.send_state_command(state.upper(), pu_number, ploop_setpoint) + return {"status": "success", "command": state.upper(), "pu": pu_number, "ploop_setpoint": ploop_setpoint} except Exception as e: raise HTTPException(status_code=500, detail=str(e)) - - @app.get("/monitor") def get_monitor_data(): data = can_backend.get_latest_data() print(f"[MONITOR] Latest SDO: {data}") return { - "Qperm": [0.0, data.get("FM2", 0.0), 0.0], + "Qperm": [data.get("FM2", 0.0), data.get("FM2", 0.0), 0.0], "Pdilute": [data.get("PS1", 0.0), 0.0, 0.0], "Conductivity": [0.0, 0.0, 0.0], "Pro": [0.0, 0.0, 0.0], } - -# -# @app.get("/monitor") -# def get_monitor_values(): -# """ -# Returns current machine monitoring data. -# Expected structure: -# Q_perm: [Q1, Q2, Q3] -# Pdilute: [P1, P2, P3] -# Conductivity: [C1, C2, C3] -# Pro: [PR1, PR2, PR3] -# """ -# try: -# return { -# "Q_perm": can_backend.get_q_perm(), -# "Pdilute": can_backend.get_pdilute(), -# "Conductivity": can_backend.get_conductivity(), -# "Pro": can_backend.get_pro(), -# } -# except Exception as e: -# raise HTTPException(status_code=500, detail=str(e)) - @app.get("/can_status") def can_status(): """Return current CAN connection status.""" diff --git a/static/index.html b/static/index.html index 14da391..dcc0190 100644 --- a/static/index.html +++ b/static/index.html @@ -13,12 +13,15 @@ display: flex; flex-direction: column; height: 100vh; - background-color: #f4f4f9; + background-color: #121212; + color: white; } .header { - background-color: #333; - padding: 10px; - text-align: center; + background-color: #1e1e1e; + padding: 10px 20px; + display: flex; + justify-content: space-between; + align-items: center; } .connect-button { background-color: #ff4444; @@ -28,7 +31,9 @@ font-size: 16px; cursor: pointer; border-radius: 5px; - transition: background-color 0.3s; + display: flex; + align-items: center; + gap: 10px; } .connected { background-color: #00C851; @@ -43,132 +48,169 @@ overflow-y: auto; } .left-panel { + background-color: #1e1e1e; display: flex; flex-direction: column; - gap: 15px; - background-color: #e9ecef; + gap: 10px; } .mode-block { - border: 1px solid #ccc; + background-color: #333; padding: 15px; border-radius: 5px; - background-color: #fff; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); - transition: background-color 0.3s; + display: flex; + flex-direction: column; + gap: 10px; } - .mode-block.active { - background-color: #a5d6a7; /* Light green background for active mode */ - } - .mode-block h2 { - margin-top: 0; - color: #333; + .pu-buttons { + display: flex; + gap: 10px; } .mode-block button { background-color: #4285F4; color: white; border: none; padding: 10px; - margin: 5px 0; cursor: pointer; border-radius: 5px; - width: 100%; font-size: 14px; transition: background-color 0.3s; + flex: 1; } .mode-block button:hover { background-color: #3367d6; } - .mode-block button i { - margin-right: 8px; + .mode-block button.active { + background-color: #00C851; + } + .pu-status { + margin-top: 20px; + } + .pu-item { + background-color: #333; + padding: 10px; + border-radius: 5px; + margin-bottom: 10px; + display: flex; + justify-content: space-between; + align-items: center; } .monitor-block { - border: 1px solid #ccc; + background-color: #333; padding: 15px; border-radius: 5px; - background-color: #fff; margin-bottom: 15px; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .monitor-block h2 { margin-top: 0; - color: #333; + display: flex; + align-items: center; + gap: 10px; } .monitor-values { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; + margin-top: 10px; } .monitor-value { - border: 1px solid #ddd; + background-color: #444; padding: 10px; text-align: center; border-radius: 5px; - background-color: #f8f9fa; + } + .slider-container { + margin-top: 10px; + } + .slider-container label { + display: block; + margin-bottom: 5px; + } + .slider-container input { + width: 100%; }