Compare commits
1 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
3abfe7976b |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -39,7 +39,7 @@ app = Flask(__name__)
|
|||
|
||||
# CORS(app, resources={r"/api/*": {"origins": "http://127.0.0.1:5500"}}, supports_credentials=True, expose_headers='Content-Disposition')
|
||||
|
||||
CORS(app, resources={r"/api/*": {"origins": ["http://10.10.2.47:5501","http://127.0.0.1:5501"]}}, supports_credentials=True, expose_headers='Content-Disposition')
|
||||
CORS(app, resources={r"/api/*": {"origins": ["http://172.20.10.4:5500","http://127.0.0.1:5500"]}}, supports_credentials=True, expose_headers='Content-Disposition')
|
||||
|
||||
# CORS(app, resources={r"/api/*": {"origins": "http://localhost:5173"}}) , "http://127.0.0.1:5500"
|
||||
# This tells Flask: "For any route starting with /api/, allow requests
|
||||
|
|
@ -953,5 +953,5 @@ if __name__ == '__main__':
|
|||
mqtt_thread = threading.Thread(target=start_mqtt_clients, daemon=True)
|
||||
mqtt_thread.start()
|
||||
|
||||
print(f"Starting Flask-SocketIO server on http://10.10.2.47:5000")
|
||||
socketio.run(app, host='10.10.2.47', port=5000)
|
||||
print(f"Starting Flask-SocketIO server on http://172.20.10.4:5000")
|
||||
socketio.run(app, host='172.20.10.4', port=5000)
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -150,6 +150,13 @@
|
|||
|
||||
.bat-id-big{font-size:14px;font-weight:800;border-radius:.5rem;padding:.2rem .4rem;
|
||||
background:rgba(0,0,0,.25);border:1px solid rgba(255,255,255,.10)}
|
||||
|
||||
#diag-flags-grid{
|
||||
display:grid;
|
||||
grid-template-columns: 80px 1fr; /* label col = 88px; adjust to taste */
|
||||
column-gap: 0.5rem; /* ~8px gap between columns */
|
||||
row-gap: 0.1; /* vertical spacing */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="min-h-screen text-gray-100 flex flex-col">
|
||||
|
|
@ -161,7 +168,7 @@
|
|||
|
||||
<!-- <header> -->
|
||||
<header class="relative z-10 border-b border-white/10 bg-black/20 backdrop-blur">
|
||||
<div class="mx-auto max-w-7.5xl px-3 sm:px-4 py-2 grid grid-cols-[auto_1fr_auto] items-center gap-2">
|
||||
<div class="mx-auto max-w-7xl px-3 sm:px-4 py-2 grid grid-cols-[auto_1fr_auto] items-center gap-2">
|
||||
<div class="flex items-center gap-2 sm:gap-3">
|
||||
<a href="./station_selection.html"
|
||||
class="h-9 w-9 flex items-center justify-center rounded-full bg-white/5 hover:bg-white/10 transition"
|
||||
|
|
@ -254,18 +261,16 @@
|
|||
|
||||
<aside class="w-full lg:w-96 lg:shrink-0 flex flex-col gap-3 overflow-y-auto">
|
||||
<section class="glass p-4">
|
||||
<div class="flex items-center justify-between mb-3">
|
||||
<span class="text-xm font-bold mb-2">System Diagnostics Code</span>
|
||||
<span id="station-diag-code" class="text-sm font-bold text-emerald-300">—</span>
|
||||
<span class="text-sm font-semibold text-gray-400">STATION DIAGNOSTIC CODE (SDC)</span>
|
||||
<div class="flex items-baseline gap-2 mt-1 mb-3">
|
||||
<i data-lucide="shield-alert" class="w-5 h-5 text-rose-500 flex-shrink-0"></i>
|
||||
<span id="station-diag-code-raw" class="text-xl font-extrabold text-emerald-300 flex-1 text-right">—</span>
|
||||
</div>
|
||||
<div id="diag-flags-grid" class="grid grid-cols-2 gap-x-8 gap-y-1 text-sm">
|
||||
<div class="text-rose-300 text-center">Lock Power Cut</div><div class="text-rose-300 text-center">Main Power Cut</div>
|
||||
<div class="text-rose-300 text-center">Relayboard CAN</div><div class="text-rose-300 text-center">DB CAN Recv</div>
|
||||
<div class="text-rose-300 text-center">MB Can Recv</div><div class="text-rose-300 text-center">Smoke Alarm</div>
|
||||
<div class="text-rose-300 text-center">Water Alarm</div><div class="text-rose-300 text-center">Phase Failure</div>
|
||||
<div class="text-rose-300 text-center">Earth Leakage</div>
|
||||
<!-- <div id="sdc-visual-flags" class="flex flex-wrap gap-1.5 pt-3 border-t border-white/10 flex-wrap">
|
||||
</div> -->
|
||||
<div id="diag-flags-grid" class="grid mt-3 pt-3 border-t border-white/10 content-center">
|
||||
</div>
|
||||
<span id="backup-power-chip" class="cham_chip cham_chip-slate w-full justify-center mt-3">
|
||||
<span id="backup-power-chip" class="cham_chip cham_chip-slate w-full justify-center mt-3">—</span>
|
||||
</section>
|
||||
|
||||
<section id="swap-panel" class="glass p-4 flex flex-col min-h-[220px]">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- CONFIGURATION ---
|
||||
const SOCKET_URL = "http://10.10.2.47:5000";
|
||||
const API_BASE = "http://10.10.2.47:5000/api";
|
||||
const SOCKET_URL = "http://172.20.10.4:5000";
|
||||
const API_BASE = "http://172.20.10.4:5000/api";
|
||||
|
||||
// --- DOM ELEMENT REFERENCES ---
|
||||
const stationNameEl = document.getElementById('station-name');
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
const password = document.getElementById('password').value;
|
||||
|
||||
try {
|
||||
const response = await fetch('http://10.10.2.47:5000/api/login', {
|
||||
const response = await fetch('http://172.20.10.4:5000/api/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ username, password }),
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
// frontend/js/common-header.js
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- CONFIGURATION ---
|
||||
const SOCKET_URL = "http://10.10.2.47:5000";
|
||||
const API_BASE = "http://10.10.2.47:5000/api";
|
||||
const SOCKET_URL = "http://172.20.10.4:5000";
|
||||
const API_BASE = "http://172.20.10.4:5000/api";
|
||||
|
||||
// --- STATE & SELECTED STATION ---
|
||||
let selectedStation = null;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- CONFIGURATION ---
|
||||
const SOCKET_URL = "http://10.10.2.47:5000";
|
||||
const API_BASE = "http://10.10.2.47:5000/api"; // Added for API calls
|
||||
const SOCKET_URL = "http://172.20.10.4:5000";
|
||||
const API_BASE = "http://172.20.10.4:5000/api"; // Added for API calls
|
||||
|
||||
// --- DOM ELEMENT REFERENCES ---
|
||||
const grid = document.getElementById('chambersGrid');
|
||||
|
|
@ -13,7 +13,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
const deviceIdEl = document.getElementById('device-id');
|
||||
const productIdEl = document.getElementById('product-id');
|
||||
const lastUpdateEl = document.getElementById('last-update-status');
|
||||
const stationDiagCodeEl = document.getElementById('station-diag-code');
|
||||
|
||||
const stationDiagCodeEl = document.getElementById('station-diag-code-raw'); // CHANGED ID: Use new raw code display ID
|
||||
const sdcVisualFlagsEl = document.getElementById('sdc-visual-flags');
|
||||
|
||||
const backupPowerChip = document.getElementById('backup-power-chip');
|
||||
const diagFlagsGrid = document.getElementById('diag-flags-grid');
|
||||
const audioSelect = document.getElementById('audio-command-select');
|
||||
|
|
@ -30,12 +33,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
let chamberData = Array(9).fill({ batteryPresent: false });
|
||||
|
||||
// The list of errors from your Python code
|
||||
const DIAGNOSTIC_ERRORS = [
|
||||
"Lock Power Cut", "Main Power Cut",
|
||||
"Relayboard CAN", "DB CAN Recv",
|
||||
"MB Can Recv", "Smoke Alarm",
|
||||
"Water Alarm", "Phase Failure",
|
||||
"Earth Leakage"
|
||||
// const DIAGNOSTIC_ERRORS = [
|
||||
// "Lock Power Cut", "Main Power Cut",
|
||||
// "Relayboard CAN", "DB CAN Recv",
|
||||
// "MB Can Recv", "Smoke Alarm",
|
||||
// "Water Alarm", "Phase Failure",
|
||||
// "Earth Leakage"
|
||||
// ];
|
||||
|
||||
const ALARM_GROUPS = [
|
||||
{ name: "EarthLk", start_bit: 20, count: 11 },
|
||||
{ name: "DBCF", start_bit: 5, count: 9 },
|
||||
{ name: "RBCF", start_bit: 14, count: 3 },
|
||||
{ name: "PF", start_bit: 17, count: 3 },
|
||||
{ name: "SMPS", start_bit: 0, count: 2 },
|
||||
{ name: "MBCF", start_bit: 4, count: 1 },
|
||||
{ name: "Smoke Alarm", start_bit: 2, count: 1 },
|
||||
{ name: "Water Level", start_bit: 3, count: 1 },
|
||||
];
|
||||
|
||||
const BATTERY_FAULT_MAP = {
|
||||
|
|
@ -129,6 +143,58 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
updateSwapUI();
|
||||
}
|
||||
|
||||
// asdfghjkjhgfdsdfghjkjhgfdfghghjkjhgfdsdfghjkjhgfdsdfghjkjhgfdsdfghjkjhgfdsdfghjkjhgfdsdfghjkjhgfdsdfghjkjhgf
|
||||
function toHex8(n){ return "0x" + (Number(n>>>0).toString(16).toUpperCase().padStart(8,"0")); }
|
||||
function sliceGroupBits(sdc, start, count){ return (sdc >>> start) & ((1<<count)-1); }
|
||||
function bitOnReversed(groupMask, indexFromLeft, count){
|
||||
const bitToCheck = count - 1 - indexFromLeft; // same as: num_indicators - 1 - i
|
||||
return ((groupMask >> bitToCheck) & 1) === 1;
|
||||
}
|
||||
|
||||
/* Renders quick chips row: PF/DBCF/etc lit if any bit in that group is 1 */
|
||||
function renderSdcChips(container, sdc){
|
||||
if(!container) return;
|
||||
container.innerHTML = "";
|
||||
ALARM_GROUPS.forEach(g=>{
|
||||
const anyOn = sliceGroupBits(sdc, g.start_bit, g.count) !== 0;
|
||||
const el = document.createElement("span");
|
||||
el.className = "chip " + (anyOn ? "chip-emerald" : "chip-slate");
|
||||
el.textContent = g.name;
|
||||
el.title = anyOn ? "Some bits set" : "All clear";
|
||||
container.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
||||
/* Renders the detailed dots grid; leftmost dot = highest bit */
|
||||
function renderSdcGrid(container, sdc){
|
||||
if(!container) return;
|
||||
container.innerHTML = "";
|
||||
ALARM_GROUPS.forEach(g=>{
|
||||
const label = document.createElement("div");
|
||||
label.className = "text-xs text-slate-300 font-medium py-1";
|
||||
label.textContent = g.name;
|
||||
container.appendChild(label);
|
||||
|
||||
const row = document.createElement("div");
|
||||
row.className = "flex flex-wrap gap-1 py-1";
|
||||
const mask = sliceGroupBits(sdc, g.start_bit, g.count);
|
||||
|
||||
for(let i=0;i<g.count;i++){
|
||||
const on = bitOnReversed(mask, i, g.count);
|
||||
const dot = document.createElement("div");
|
||||
dot.className = "w-5 h-5 rounded-full grid place-items-center border text-[10px] " +
|
||||
(on ? "bg-emerald-500/90 border-emerald-600 text-white"
|
||||
: "bg-slate-800 border-slate-600 text-slate-400");
|
||||
dot.textContent = (i+1).toString();
|
||||
dot.title = `Bit ${g.start_bit + (g.count - 1 - i)} = ${on?1:0}`;
|
||||
dot.setAttribute("role","switch");
|
||||
dot.setAttribute("aria-pressed", on ? "true":"false");
|
||||
row.appendChild(dot);
|
||||
}
|
||||
container.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// --- HELPER FUNCTIONS (Your original code is unchanged) ---
|
||||
|
||||
|
|
@ -188,6 +254,40 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
};
|
||||
|
||||
|
||||
// --- NEW: Function to decode the SDC and create visual pill elements ---
|
||||
/**
|
||||
* Decodes the SDC and creates visual pill elements for active faults.
|
||||
* @param {number} sdcCode The station diagnostic code as an integer.
|
||||
*/
|
||||
// const updateSdcVisuals = (sdcCode) => {
|
||||
// if (!sdcVisualFlagsEl) return;
|
||||
// sdcVisualFlagsEl.innerHTML = ''; // Clear previous flags
|
||||
|
||||
// let hasActiveFault = false;
|
||||
|
||||
// for (const bitIndex in SDC_FLAGS) {
|
||||
// const bit = parseInt(bitIndex, 10);
|
||||
// if ((sdcCode & (1 << bit)) !== 0) {
|
||||
// hasActiveFault = true;
|
||||
// const flag = SDC_FLAGS[bitIndex];
|
||||
// const pill = document.createElement('div');
|
||||
// // Tailwind class for the pill look (using your defined style)
|
||||
// pill.className = `flex items-center gap-1.5 text-xs font-medium rounded-full px-3 py-1 ${flag.style}`;
|
||||
// // Use Lucide icon from the map
|
||||
// pill.innerHTML = `<i data-lucide="${flag.icon}" class="w-3.5 h-3.5 flex-shrink-0"></i> <span>${flag.name}</span>`;
|
||||
// sdcVisualFlagsEl.appendChild(pill);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // If no active faults, display a healthy message
|
||||
// if (!hasActiveFault) {
|
||||
// sdcVisualFlagsEl.innerHTML = '<span class="text-xs text-emerald-400 font-semibold flex items-center gap-1"><i data-lucide="check-circle" class="w-4 h-4"></i> System OK</span>';
|
||||
// }
|
||||
// // Re-run Lucide to render the newly added icons (like check-circle)
|
||||
// lucide.createIcons();
|
||||
// };
|
||||
|
||||
|
||||
const updateChamberUI = (card, slot) => {
|
||||
if (!card || !slot) return;
|
||||
|
||||
|
|
@ -264,26 +364,37 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
};
|
||||
|
||||
// --- NEW: Function to decode the SDC and update the UI ---
|
||||
const updateDiagnosticsUI = (sdcCode) => {
|
||||
if (!diagFlagsGrid) return;
|
||||
diagFlagsGrid.innerHTML = ''; // Clear previous statuses
|
||||
// const updateDiagnosticsUI = (sdcCode) => {
|
||||
// if (!diagFlagsGrid) return;
|
||||
// diagFlagsGrid.innerHTML = ''; // Clear previous statuses
|
||||
|
||||
DIAGNOSTIC_ERRORS.forEach((errorText, index) => {
|
||||
// Use bitwise AND to check if the bit at this index is set
|
||||
const isActive = (sdcCode & (1 << index)) !== 0;
|
||||
// DIAGNOSTIC_ERRORS.forEach((errorText, index) => {
|
||||
// // Use bitwise AND to check if the bit at this index is set
|
||||
// const isActive = (sdcCode & (1 << index)) !== 0;
|
||||
|
||||
const div = document.createElement('div');
|
||||
div.textContent = errorText;
|
||||
// const div = document.createElement('div');
|
||||
// div.textContent = errorText;
|
||||
|
||||
// // Apply different styles based on whether the alarm is active
|
||||
// if (isActive) {
|
||||
// div.className = 'text-rose-300 text-center font-semibold';
|
||||
// } else {
|
||||
// div.className = 'text-slate-500 text-center';
|
||||
// }
|
||||
// diagFlagsGrid.appendChild(div);
|
||||
// });
|
||||
// };
|
||||
function updateDiagnosticAlarms(sdcValue){
|
||||
const sdc = Number(sdcValue);
|
||||
const hexEl = document.getElementById("station-diag-code-raw"); // hex display
|
||||
const chipsEl = document.getElementById("sdc-visual-flags"); // quick flags row
|
||||
const gridEl = document.getElementById("diag-flags-grid"); // dots grid
|
||||
|
||||
if (hexEl) hexEl.textContent = toHex8(sdc);
|
||||
renderSdcChips(chipsEl, sdc);
|
||||
renderSdcGrid(gridEl, sdc);
|
||||
}
|
||||
|
||||
// Apply different styles based on whether the alarm is active
|
||||
if (isActive) {
|
||||
div.className = 'text-rose-300 text-center font-semibold';
|
||||
} else {
|
||||
div.className = 'text-slate-500 text-center';
|
||||
}
|
||||
diagFlagsGrid.appendChild(div);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const checkStationStatus = async () => {
|
||||
|
|
@ -326,6 +437,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
card.querySelector('.filled-state').style.display = 'none';
|
||||
card.querySelector('.empty-state').style.display = 'flex';
|
||||
});
|
||||
updateDiagnosticAlarms(0);
|
||||
logToInstance("Station is offline. Clearing stale data.", "error");
|
||||
};
|
||||
|
||||
|
|
@ -500,9 +612,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
|
||||
// 1. Check if the 'stationDiagnosticCode' key exists in the data.
|
||||
if (data.hasOwnProperty('stationDiagnosticCode')) {
|
||||
const sdc = data.stationDiagnosticCode;
|
||||
stationDiagCodeEl.textContent = sdc;
|
||||
updateDiagnosticsUI(sdc);
|
||||
const sdcRaw = data.stationDiagnosticCode;
|
||||
const sdc = Number.isFinite(sdcRaw) ? Number(sdcRaw) : 0;
|
||||
updateDiagnosticAlarms(sdc);
|
||||
}
|
||||
|
||||
// 2. Check if the 'backupSupplyStatus' key exists.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// --- CONFIGURATION ---
|
||||
const SOCKET_URL = "http://10.10.2.47:5000";
|
||||
const API_BASE = "http://10.10.2.47:5000/api";
|
||||
const SOCKET_URL = "http://172.20.10.4:5000";
|
||||
const API_BASE = "http://172.20.10.4:5000/api";
|
||||
|
||||
// --- DOM ELEMENT REFERENCES ---
|
||||
const stationNameEl = document.getElementById('station-name');
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||
const stationCountEl = document.getElementById('station-count'); // Make sure you have an element with this ID in your HTML
|
||||
|
||||
// --- CONFIG & STATE ---
|
||||
const API_BASE = 'http://10.10.2.47:5000/api';
|
||||
const API_BASE = 'http://172.20.10.4:5000/api';
|
||||
let allStations = []; // Master list of stations from the API
|
||||
let pollingInterval = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
const API_BASE = 'http://10.10.2.47:5000/api';
|
||||
const API_BASE = 'http://172.20.10.4:5000/api';
|
||||
|
||||
const grid = document.getElementById('stations-grid');
|
||||
const addStationCardTmpl = document.getElementById('add-station-card-template');
|
||||
|
|
|
|||
Loading…
Reference in New Issue