Separates into 3 monitor pages
This commit is contained in:
parent
f3cd47432c
commit
656ae95f19
71
MockCAN.py
71
MockCAN.py
|
|
@ -29,26 +29,51 @@ class CANBackend:
|
||||||
|
|
||||||
def get_latest_data(self, pu_number=1, data={}):
|
def get_latest_data(self, pu_number=1, data={}):
|
||||||
# Simulate getting the latest data with random values
|
# Simulate getting the latest data with random values
|
||||||
return {
|
if pu_number ==1:
|
||||||
"FM2": round(1000 * np.random.random(), 1),
|
return {
|
||||||
"FM3": round(1000 * np.random.random(), 1),
|
"FM2": 1080,
|
||||||
"FM4": round(1000 * np.random.random(), 1),
|
"FM3": 1080,
|
||||||
"FM5": round(1000 * np.random.random(), 1),
|
"FM4": 1080,
|
||||||
"PS1": round(10 * np.random.random(), 2),
|
"FM5": 1080,
|
||||||
"PS2": round(10 * np.random.random(), 2),
|
"PS1": 6.2,
|
||||||
"PS3": round(10 * np.random.random(), 2),
|
"PS2": 6.2,
|
||||||
"PS4": round(10 * np.random.random(), 2),
|
"PS3": 6.2,
|
||||||
"Cond": 1* np.random.random(),
|
"PS4": 6.2,
|
||||||
"MV02": round(100 * np.random.random(), 2),
|
"Cond": 1* np.random.random(),
|
||||||
"MV02_sp": round(100 * np.random.random(), 2),
|
"MV02": round(100 * np.random.random(), 2),
|
||||||
"MV03": round(100 * np.random.random(), 2),
|
"MV02_sp": round(100 * np.random.random(), 2),
|
||||||
"MV03_sp": round(100 * np.random.random(), 2),
|
"MV03": round(100 * np.random.random(), 2),
|
||||||
"MV05": round(100 * np.random.random(), 2),
|
"MV03_sp": round(100 * np.random.random(), 2),
|
||||||
"MV05_sp": round(100 * np.random.random(), 2),
|
"MV05": round(100 * np.random.random(), 2),
|
||||||
"MV06": round(100 * np.random.random(), 2),
|
"MV05_sp": round(100 * np.random.random(), 2),
|
||||||
"MV06_sp": round(100 * np.random.random(), 2),
|
"MV06": round(100 * np.random.random(), 2),
|
||||||
"MV07": round(100 * np.random.random(), 2),
|
"MV06_sp": round(100 * np.random.random(), 2),
|
||||||
"MV07_sp": round(100 * np.random.random(), 2),
|
"MV07": round(100 * np.random.random(), 2),
|
||||||
"MV08": round(100 * np.random.random(), 2),
|
"MV07_sp": round(100 * np.random.random(), 2),
|
||||||
"MV08_sp": round(100 * np.random.random(), 2),
|
"MV08": round(100 * np.random.random(), 2),
|
||||||
}
|
"MV08_sp": round(100 * np.random.random(), 2),
|
||||||
|
}
|
||||||
|
else :
|
||||||
|
return {
|
||||||
|
"FM2": round(1000 * np.random.random(), 1),
|
||||||
|
"FM3": round(1000 * np.random.random(), 1),
|
||||||
|
"FM4": round(1000 * np.random.random(), 1),
|
||||||
|
"FM5": round(1000 * np.random.random(), 1),
|
||||||
|
"PS1": round(10 * np.random.random(), 2),
|
||||||
|
"PS2": round(10 * np.random.random(), 2),
|
||||||
|
"PS3": round(10 * np.random.random(), 2),
|
||||||
|
"PS4": round(10 * np.random.random(), 2),
|
||||||
|
"Cond": 1* np.random.random(),
|
||||||
|
"MV02": round(100 * np.random.random(), 2),
|
||||||
|
"MV02_sp": round(100 * np.random.random(), 2),
|
||||||
|
"MV03": round(100 * np.random.random(), 2),
|
||||||
|
"MV03_sp": round(100 * np.random.random(), 2),
|
||||||
|
"MV05": round(100 * np.random.random(), 2),
|
||||||
|
"MV05_sp": round(100 * np.random.random(), 2),
|
||||||
|
"MV06": round(100 * np.random.random(), 2),
|
||||||
|
"MV06_sp": round(100 * np.random.random(), 2),
|
||||||
|
"MV07": round(100 * np.random.random(), 2),
|
||||||
|
"MV07_sp": round(100 * np.random.random(), 2),
|
||||||
|
"MV08": round(100 * np.random.random(), 2),
|
||||||
|
"MV08_sp": round(100 * np.random.random(), 2),
|
||||||
|
}
|
||||||
15
main.py
15
main.py
|
|
@ -26,19 +26,9 @@ app.add_middleware(SessionMiddleware, secret_key="your_super_secret_key")
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
templates = Jinja2Templates(directory="templates")
|
templates = Jinja2Templates(directory="templates")
|
||||||
logging.basicConfig(level=logging.INFO)
|
logging.basicConfig(level=logging.INFO)
|
||||||
|
|
||||||
can_backend = CANBackend()
|
can_backend = CANBackend()
|
||||||
|
|
||||||
# Mount static files
|
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
|
||||||
|
|
||||||
|
|
||||||
can_backend = CANBackend()
|
|
||||||
|
|
||||||
# Serve static files (HTML, JS, CSS)
|
# Serve static files (HTML, JS, CSS)
|
||||||
app.mount("/static", StaticFiles(directory="static"), name="static")
|
app.mount("/static", StaticFiles(directory="static"), name="static")
|
||||||
# Jinja2 templates
|
|
||||||
templates = Jinja2Templates(directory="templates")
|
|
||||||
|
|
||||||
# CREDENTIALS
|
# CREDENTIALS
|
||||||
|
|
||||||
|
|
@ -164,6 +154,7 @@ def get_pu_status():
|
||||||
|
|
||||||
@app.get("/monitor")
|
@app.get("/monitor")
|
||||||
def get_monitor_data(pu_number: Optional[int] = Query(None)):
|
def get_monitor_data(pu_number: Optional[int] = Query(None)):
|
||||||
|
logging.info(f"[MONITOR DATA] {pu_number}")
|
||||||
def format_data(data):
|
def format_data(data):
|
||||||
return {
|
return {
|
||||||
"Qperm": data.get("FM2", 0.0),
|
"Qperm": data.get("FM2", 0.0),
|
||||||
|
|
@ -192,8 +183,8 @@ def get_monitor_data(pu_number: Optional[int] = Query(None)):
|
||||||
}
|
}
|
||||||
all_data = {}
|
all_data = {}
|
||||||
for pu in [1, 2, 3]:
|
for pu in [1, 2, 3]:
|
||||||
data = can_backend.get_latest_data(pu)
|
data = can_backend.get_latest_data(pu_number=pu)
|
||||||
print(f"[MONITOR] PU{pu}: {data}")
|
logging.info(f"[MONITOR] PU{pu}: {data}")
|
||||||
all_data[f"PU_{pu}"] = format_data(data)
|
all_data[f"PU_{pu}"] = format_data(data)
|
||||||
return all_data
|
return all_data
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,12 +28,6 @@
|
||||||
h1 {
|
h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
#puSelector {
|
|
||||||
display: block;
|
|
||||||
margin: 10px auto 20px auto;
|
|
||||||
font-size: 16px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
}
|
|
||||||
#recordButton {
|
#recordButton {
|
||||||
background-color: #ff4444;
|
background-color: #ff4444;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
@ -47,13 +41,7 @@
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>Live Monitoring Dashboard</h1>
|
<h1 id="pageTitle">Live Monitoring Dashboard</h1>
|
||||||
<label for="puSelector" style="text-align:center; display:block;">Select PU:</label>
|
|
||||||
<select id="puSelector">
|
|
||||||
<option value="1">PU 1</option>
|
|
||||||
<option value="2">PU 2</option>
|
|
||||||
<option value="3">PU 3</option>
|
|
||||||
</select>
|
|
||||||
<button id="recordButton" onclick="toggleRecording()">Record</button>
|
<button id="recordButton" onclick="toggleRecording()">Record</button>
|
||||||
<div class="plot-container">
|
<div class="plot-container">
|
||||||
<div id="flow-plot" class="large-plot"></div>
|
<div id="flow-plot" class="large-plot"></div>
|
||||||
|
|
@ -66,6 +54,11 @@
|
||||||
<div id="mv08-plot" class="small-plot"></div>
|
<div id="mv08-plot" class="small-plot"></div>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
|
// Extract PU number from URL
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const puNumber = urlParams.get('pu_number') || '1'; // Default to PU 1 if not specified
|
||||||
|
document.getElementById('pageTitle').textContent = `Live Monitoring Dashboard - PU ${puNumber}`;
|
||||||
|
|
||||||
let isRecording = false;
|
let isRecording = false;
|
||||||
let recordedData = [];
|
let recordedData = [];
|
||||||
let recordingInterval;
|
let recordingInterval;
|
||||||
|
|
@ -78,7 +71,7 @@
|
||||||
recordButton.style.backgroundColor = '#ff0000';
|
recordButton.style.backgroundColor = '#ff0000';
|
||||||
recordButton.textContent = 'Stop Recording';
|
recordButton.textContent = 'Stop Recording';
|
||||||
recordedData = [];
|
recordedData = [];
|
||||||
csvFileName = `monitoring_data_${new Date().toISOString().replace(/[:.]/g, '-')}.csv`;
|
csvFileName = `monitoring_data_PU${puNumber}_${new Date().toISOString().replace(/[:.]/g, '-')}.csv`;
|
||||||
startRecording();
|
startRecording();
|
||||||
} else {
|
} else {
|
||||||
isRecording = false;
|
isRecording = false;
|
||||||
|
|
@ -90,28 +83,29 @@
|
||||||
|
|
||||||
function startRecording() {
|
function startRecording() {
|
||||||
recordingInterval = setInterval(async () => {
|
recordingInterval = setInterval(async () => {
|
||||||
const response = await fetch(`/monitor?pu_number=${document.getElementById('puSelector').value}`);
|
const response = await fetch('/monitor');
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
console.error(`HTTP error! status: ${response.status}`);
|
console.error(`HTTP error! status: ${response.status}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const pu = await response.json();
|
const allData = await response.json();
|
||||||
|
const puData = allData[`PU_${puNumber}`];
|
||||||
recordedData.push({
|
recordedData.push({
|
||||||
timestamp: new Date().toISOString(),
|
timestamp: new Date().toISOString(),
|
||||||
Qperm: pu.Qperm,
|
Qperm: puData.Qperm,
|
||||||
Qdilute: pu.Qdilute,
|
Qdilute: puData.Qdilute,
|
||||||
Qdrain: pu.Qdrain,
|
Qdrain: puData.Qdrain,
|
||||||
Qrecirc: pu.Qrecirc,
|
Qrecirc: puData.Qrecirc,
|
||||||
Pro: pu.Pro,
|
Pro: puData.Pro,
|
||||||
Pdilute: pu.Pdilute,
|
Pdilute: puData.Pdilute,
|
||||||
Prentate: pu.Prentate,
|
Prentate: puData.Prentate,
|
||||||
MV02: pu.MV02,
|
MV02: puData.MV02,
|
||||||
MV03: pu.MV03,
|
MV03: puData.MV03,
|
||||||
MV04: pu.MV04,
|
MV04: puData.MV04,
|
||||||
MV05: pu.MV05,
|
MV05: puData.MV05,
|
||||||
MV06: pu.MV06,
|
MV06: puData.MV06,
|
||||||
MV07: pu.MV07,
|
MV07: puData.MV07,
|
||||||
MV08: pu.MV08
|
MV08: puData.MV08
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +118,6 @@
|
||||||
recordedData.map(row =>
|
recordedData.map(row =>
|
||||||
`${row.timestamp},${row.Qperm},${row.Qdilute},${row.Qdrain},${row.Qrecirc},${row.Pro},${row.Pdilute},${row.Prentate},${row.MV02},${row.MV03},${row.MV04},${row.MV05},${row.MV06},${row.MV07},${row.MV08}`
|
`${row.timestamp},${row.Qperm},${row.Qdilute},${row.Qdrain},${row.Qrecirc},${row.Pro},${row.Pdilute},${row.Prentate},${row.MV02},${row.MV03},${row.MV04},${row.MV05},${row.MV06},${row.MV07},${row.MV08}`
|
||||||
).join("\n");
|
).join("\n");
|
||||||
|
|
||||||
const encodedUri = encodeURI(csvContent);
|
const encodedUri = encodeURI(csvContent);
|
||||||
const link = document.createElement("a");
|
const link = document.createElement("a");
|
||||||
link.setAttribute("href", encodedUri);
|
link.setAttribute("href", encodedUri);
|
||||||
|
|
@ -140,14 +133,8 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Existing plot initialization and update functions
|
|
||||||
const maxPoints = 100;
|
const maxPoints = 100;
|
||||||
const time = () => new Date();
|
const time = () => new Date();
|
||||||
let selectedPU = 1;
|
|
||||||
|
|
||||||
document.getElementById("puSelector").addEventListener("change", function () {
|
|
||||||
selectedPU = parseInt(this.value);
|
|
||||||
});
|
|
||||||
|
|
||||||
function getLastMinuteRange() {
|
function getLastMinuteRange() {
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
|
|
@ -157,28 +144,28 @@
|
||||||
|
|
||||||
async function updatePlots() {
|
async function updatePlots() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(`/monitor?pu_number=${selectedPU}`);
|
const response = await fetch('/monitor');
|
||||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
const pu = await response.json();
|
const allData = await response.json();
|
||||||
|
const puData = allData[`PU_${puNumber}`];
|
||||||
const t = time();
|
const t = time();
|
||||||
Plotly.extendTraces('flow-plot', {
|
Plotly.extendTraces('flow-plot', {
|
||||||
x: [[t], [t], [t], [t]],
|
x: [[t], [t], [t], [t]],
|
||||||
y: [[pu.Qperm], [pu.Qdilute], [pu.Qdrain], [pu.Qrecirc]]
|
y: [[puData.Qperm], [puData.Qdilute], [puData.Qdrain], [puData.Qrecirc]]
|
||||||
}, [0, 1, 2, 3], maxPoints);
|
}, [0, 1, 2, 3], maxPoints);
|
||||||
Plotly.extendTraces('pressure-plot', {
|
Plotly.extendTraces('pressure-plot', {
|
||||||
x: [[t], [t], [t]],
|
x: [[t], [t], [t]],
|
||||||
y: [[pu.Pro], [pu.Pdilute], [pu.Prentate]]
|
y: [[puData.Pro], [puData.Pdilute], [puData.Prentate]]
|
||||||
}, [0, 1, 2], maxPoints);
|
}, [0, 1, 2], maxPoints);
|
||||||
//
|
// Plotly.extendTraces('mv02-plot', { x: [[t]], y: [[puData.MV02]] }, [0]);
|
||||||
// Plotly.extendTraces('mv02-plot', { x: [[t]], y: [[pu.MV02]] }, [0]);
|
// Plotly.extendTraces('mv03-plot', { x: [[t]], y: [[puData.MV03]] }, [0]);
|
||||||
// Plotly.extendTraces('mv03-plot', { x: [[t]], y: [[pu.MV03]] }, [0]);
|
|
||||||
// Plotly.extendTraces('mv04-05-plot', {
|
// Plotly.extendTraces('mv04-05-plot', {
|
||||||
// x: [[t], [t]],
|
// x: [[t], [t]],
|
||||||
// y: [[pu.MV04], [pu.MV05]]
|
// y: [[puData.MV04], [puData.MV05]]
|
||||||
// }, [0, 1]);
|
// }, [0, 1]);
|
||||||
// Plotly.extendTraces('mv06-plot', { x: [[t]], y: [[pu.MV06]] }, [0]);
|
// Plotly.extendTraces('mv06-plot', { x: [[t]], y: [[puData.MV06]] }, [0]);
|
||||||
// Plotly.extendTraces('mv07-plot', { x: [[t]], y: [[pu.MV07]] }, [0]);
|
// Plotly.extendTraces('mv07-plot', { x: [[t]], y: [[puData.MV07]] }, [0]);
|
||||||
// Plotly.extendTraces('mv08-plot', { x: [[t]], y: [[pu.MV08]] }, [0]);
|
// Plotly.extendTraces('mv08-plot', { x: [[t]], y: [[puData.MV08]] }, [0]);
|
||||||
|
|
||||||
const range = getLastMinuteRange();
|
const range = getLastMinuteRange();
|
||||||
const plotIds = [
|
const plotIds = [
|
||||||
|
|
@ -245,7 +232,7 @@
|
||||||
// }], {
|
// }], {
|
||||||
// title: 'MV08 (%)', yaxis: { range: [0, 100] }, xaxis: { type: 'date' }
|
// title: 'MV08 (%)', yaxis: { range: [0, 100] }, xaxis: { type: 'date' }
|
||||||
// });
|
// });
|
||||||
setInterval(updatePlots, 1000);
|
setInterval(updatePlots, 250);
|
||||||
}
|
}
|
||||||
|
|
||||||
window.onload = initPlots;
|
window.onload = initPlots;
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,9 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
.connected { background-color: #00C851; }
|
.connected {
|
||||||
|
background-color: #00C851;
|
||||||
|
}
|
||||||
.container {
|
.container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
|
@ -63,7 +65,10 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
}
|
}
|
||||||
.pu-buttons { display: flex; gap: 10px; }
|
.pu-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
.mode-block button {
|
.mode-block button {
|
||||||
background-color: #4285F4;
|
background-color: #4285F4;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
@ -78,10 +83,21 @@
|
||||||
.mode-block button:hover {
|
.mode-block button:hover {
|
||||||
background-color: #3367d6;
|
background-color: #3367d6;
|
||||||
}
|
}
|
||||||
.mode-block button.active { background-color: #00C851; }
|
.mode-block button.active {
|
||||||
.mode-block button.in-progress { background-color: #ffcc00; color: #000; }
|
background-color: #00C851;
|
||||||
.mode-block button.ready { background-color: #00C851; color: #fff; }
|
}
|
||||||
.mode-block button.disabled { background-color: #777; cursor: not-allowed; }
|
.mode-block button.in-progress {
|
||||||
|
background-color: #ffcc00;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.mode-block button.ready {
|
||||||
|
background-color: #00C851;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
.mode-block button.disabled {
|
||||||
|
background-color: #777;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
.in-progress {
|
.in-progress {
|
||||||
background-color: yellow !important;
|
background-color: yellow !important;
|
||||||
color: black !important;
|
color: black !important;
|
||||||
|
|
@ -94,7 +110,9 @@
|
||||||
background-color: green !important;
|
background-color: green !important;
|
||||||
color: white !important;
|
color: white !important;
|
||||||
}
|
}
|
||||||
.pu-status { margin-top: 20px; }
|
.pu-status {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
.pu-item {
|
.pu-item {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
@ -171,7 +189,9 @@
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
.monitor-link:hover { background-color: #0056b3; }
|
.monitor-link:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
.feed-valve-buttons {
|
.feed-valve-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
|
@ -189,14 +209,38 @@
|
||||||
.feed-valve-buttons button.active {
|
.feed-valve-buttons button.active {
|
||||||
background-color: #00C851;
|
background-color: #00C851;
|
||||||
}
|
}
|
||||||
|
.monitor-pu-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.monitor-pu-buttons a {
|
||||||
|
color: white;
|
||||||
|
background-color: #007bff;
|
||||||
|
padding: 10px 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.monitor-pu-buttons a:hover {
|
||||||
|
background-color: #0056b3;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h1>Hydraulic Machine Control</h1>
|
<h1>Hydraulic Machine Control</h1>
|
||||||
<a href="/monitor-page" target="_blank" rel="noopener noreferrer" class="monitor-link">
|
<div class="monitor-pu-buttons">
|
||||||
<i class="fas fa-chart-line"></i> Monitor
|
<a href="/monitor-page?pu_number=1" target="_blank" class="monitor-link">
|
||||||
</a>
|
<i class="fas fa-chart-line"></i> Monitor PU 1
|
||||||
|
</a>
|
||||||
|
<a href="/monitor-page?pu_number=2" target="_blank" class="monitor-link">
|
||||||
|
<i class="fas fa-chart-line"></i> Monitor PU 2
|
||||||
|
</a>
|
||||||
|
<a href="/monitor-page?pu_number=3" target="_blank" class="monitor-link">
|
||||||
|
<i class="fas fa-chart-line"></i> Monitor PU 3
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
<button id="connectButton" class="connect-button" onclick="toggleConnection()">
|
<button id="connectButton" class="connect-button" onclick="toggleConnection()">
|
||||||
<i class="fas fa-power-off"></i> Connect
|
<i class="fas fa-power-off"></i> Connect
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -286,7 +330,6 @@
|
||||||
function updatePloopSetpoint(value) {
|
function updatePloopSetpoint(value) {
|
||||||
document.getElementById('currentValue').textContent = value;
|
document.getElementById('currentValue').textContent = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function toggleConnection() {
|
async function toggleConnection() {
|
||||||
const response = await fetch('/connect_toggle', { method: 'POST' });
|
const response = await fetch('/connect_toggle', { method: 'POST' });
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
@ -294,14 +337,12 @@ async function toggleConnection() {
|
||||||
connectButton.classList.toggle('connected', data.connected);
|
connectButton.classList.toggle('connected', data.connected);
|
||||||
connectButton.innerHTML = `<i class="fas fa-power-off"></i> ${data.connected ? 'Disconnect' : 'Connect'}`;
|
connectButton.innerHTML = `<i class="fas fa-power-off"></i> ${data.connected ? 'Disconnect' : 'Connect'}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendCommand(state, puNumber, buttonEl) {
|
async function sendCommand(state, puNumber, buttonEl) {
|
||||||
const ploopSetpoint = document.getElementById('ploopSetpoint').value;
|
const ploopSetpoint = document.getElementById('ploopSetpoint').value;
|
||||||
await fetch(`/command/${state}/pu/${puNumber}?ploop_setpoint=${ploopSetpoint}`, { method: 'POST' });
|
await fetch(`/command/${state}/pu/${puNumber}?ploop_setpoint=${ploopSetpoint}`, { method: 'POST' });
|
||||||
document.querySelectorAll('button').forEach(btn => {
|
document.querySelectorAll('button').forEach(btn => {
|
||||||
btn.classList.remove('in-progress', 'ready', 'production');
|
btn.classList.remove('in-progress', 'ready', 'production');
|
||||||
});
|
});
|
||||||
|
|
||||||
if (state === 'PRE-PRODUCTION') {
|
if (state === 'PRE-PRODUCTION') {
|
||||||
buttonEl.classList.add('in-progress');
|
buttonEl.classList.add('in-progress');
|
||||||
buttonEl.textContent = `Waiting... PU ${puNumber}`;
|
buttonEl.textContent = `Waiting... PU ${puNumber}`;
|
||||||
|
|
@ -334,7 +375,6 @@ async function sendCommand(state, puNumber, buttonEl) {
|
||||||
buttonEl.classList.remove('in-progress', 'ready', 'production');
|
buttonEl.classList.remove('in-progress', 'ready', 'production');
|
||||||
buttonEl.classList.add('production');
|
buttonEl.classList.add('production');
|
||||||
buttonEl.textContent = `${state.replace('_', ' ')} PU ${puNumber}`;
|
buttonEl.textContent = `${state.replace('_', ' ')} PU ${puNumber}`;
|
||||||
|
|
||||||
const preProdBtn = document.querySelector(`button[data-action="PRE-PRODUCTION"][data-pu="${puNumber}"]`);
|
const preProdBtn = document.querySelector(`button[data-action="PRE-PRODUCTION"][data-pu="${puNumber}"]`);
|
||||||
if (preProdBtn) {
|
if (preProdBtn) {
|
||||||
preProdBtn.classList.remove('in-progress', 'ready', 'production');
|
preProdBtn.classList.remove('in-progress', 'ready', 'production');
|
||||||
|
|
@ -342,7 +382,6 @@ async function sendCommand(state, puNumber, buttonEl) {
|
||||||
preProdBtn.disabled = false;
|
preProdBtn.disabled = false;
|
||||||
preProdBtn.onclick = () => sendCommand("PRE-PRODUCTION", puNumber, preProdBtn);
|
preProdBtn.onclick = () => sendCommand("PRE-PRODUCTION", puNumber, preProdBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
const idleBtn = document.querySelector(`button[data-action="IDLE"][data-pu="${puNumber}"]`);
|
const idleBtn = document.querySelector(`button[data-action="IDLE"][data-pu="${puNumber}"]`);
|
||||||
if (idleBtn && idleBtn !== buttonEl) {
|
if (idleBtn && idleBtn !== buttonEl) {
|
||||||
idleBtn.classList.remove('in-progress', 'ready', 'production');
|
idleBtn.classList.remove('in-progress', 'ready', 'production');
|
||||||
|
|
@ -350,7 +389,6 @@ async function sendCommand(state, puNumber, buttonEl) {
|
||||||
idleBtn.disabled = false;
|
idleBtn.disabled = false;
|
||||||
idleBtn.onclick = () => sendCommand("IDLE", puNumber, idleBtn);
|
idleBtn.onclick = () => sendCommand("IDLE", puNumber, idleBtn);
|
||||||
}
|
}
|
||||||
|
|
||||||
const firstStartBtn = document.querySelector(`button[data-action="FIRST_START"][data-pu="${puNumber}"]`);
|
const firstStartBtn = document.querySelector(`button[data-action="FIRST_START"][data-pu="${puNumber}"]`);
|
||||||
if (firstStartBtn && firstStartBtn !== buttonEl) {
|
if (firstStartBtn && firstStartBtn !== buttonEl) {
|
||||||
firstStartBtn.classList.remove('in-progress', 'ready', 'production');
|
firstStartBtn.classList.remove('in-progress', 'ready', 'production');
|
||||||
|
|
@ -360,7 +398,6 @@ async function sendCommand(state, puNumber, buttonEl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function setFeedValve(opening, buttonEl) {
|
async function setFeedValve(opening, buttonEl) {
|
||||||
await fetch(`/command/feed_valve?MV01_opening=${opening}`, { method: 'POST' });
|
await fetch(`/command/feed_valve?MV01_opening=${opening}`, { method: 'POST' });
|
||||||
document.querySelectorAll('.feed-valve-buttons button').forEach(btn => {
|
document.querySelectorAll('.feed-valve-buttons button').forEach(btn => {
|
||||||
|
|
@ -368,7 +405,6 @@ async function setFeedValve(opening, buttonEl) {
|
||||||
});
|
});
|
||||||
buttonEl.classList.add('active');
|
buttonEl.classList.add('active');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchPUStatus() {
|
async function fetchPUStatus() {
|
||||||
const response = await fetch("/api/pu_status");
|
const response = await fetch("/api/pu_status");
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
@ -376,10 +412,8 @@ async function fetchPUStatus() {
|
||||||
document.getElementById("pu2-status").textContent = data.PU2 || "Unknown";
|
document.getElementById("pu2-status").textContent = data.PU2 || "Unknown";
|
||||||
document.getElementById("pu3-status").textContent = data.PU3 || "Unknown";
|
document.getElementById("pu3-status").textContent = data.PU3 || "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchPUStatus();
|
fetchPUStatus();
|
||||||
setInterval(fetchPUStatus, 5000);
|
setInterval(fetchPUStatus, 5000);
|
||||||
|
|
||||||
async function updateMonitorData() {
|
async function updateMonitorData() {
|
||||||
const response = await fetch('/monitor');
|
const response = await fetch('/monitor');
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
|
|
@ -405,7 +439,6 @@ async function updateMonitorData() {
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateMonitorValues(id, values, unit) {
|
function updateMonitorValues(id, values, unit) {
|
||||||
const container = document.getElementById(id);
|
const container = document.getElementById(id);
|
||||||
const valueElements = container.querySelectorAll('.monitor-value');
|
const valueElements = container.querySelectorAll('.monitor-value');
|
||||||
|
|
@ -415,9 +448,7 @@ function updateMonitorValues(id, values, unit) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(updateMonitorData, 1000);
|
setInterval(updateMonitorData, 1000);
|
||||||
|
|
||||||
async function fetchMonitorData() {
|
async function fetchMonitorData() {
|
||||||
try {
|
try {
|
||||||
const puMap = {
|
const puMap = {
|
||||||
|
|
@ -450,7 +481,6 @@ async function fetchMonitorData() {
|
||||||
console.error('Error fetching monitor data:', error);
|
console.error('Error fetching monitor data:', error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(fetchMonitorData, 1000);
|
setInterval(fetchMonitorData, 1000);
|
||||||
fetchMonitorData();
|
fetchMonitorData();
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user