Skip to content

Commit 0bda77f

Browse files
author
BESS Solutions
committed
feat: v1.6.0 - Cliente-Cero-Ready: auto-reconnect Modbus + dashboard UI
1 parent 28b9486 commit 0bda77f

7 files changed

Lines changed: 1583 additions & 10 deletions

File tree

dashboard/index.html

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
<!DOCTYPE html>
2+
<html lang="es">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>BESSAI Edge — Control Center</title>
7+
<meta name="description" content="BESSAI Edge Gateway — Panel de control industrial para sistemas BESS con IA embebida, monitoreo en tiempo real y arbitraje de energía." />
8+
<link rel="preconnect" href="https://fonts.googleapis.com" />
9+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet" />
10+
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
11+
<link rel="stylesheet" href="styles.css" />
12+
</head>
13+
<body>
14+
<!-- ── TOP NAV ──────────────────────────────────────────────── -->
15+
<nav class="topnav">
16+
<div class="nav-brand">
17+
<svg class="brand-icon" viewBox="0 0 32 32" fill="none">
18+
<rect x="2" y="8" width="28" height="16" rx="3" stroke="#6366f1" stroke-width="2"/>
19+
<rect x="30" y="12" width="2" height="8" rx="1" fill="#6366f1"/>
20+
<rect x="6" y="11" width="4" height="10" rx="1" fill="#6366f1" opacity="0.9"/>
21+
<rect x="12" y="13" width="4" height="8" rx="1" fill="#6366f1" opacity="0.7"/>
22+
<rect x="18" y="12" width="4" height="9" rx="1" fill="#22d3ee" opacity="0.9"/>
23+
<rect x="24" y="14" width="3" height="7" rx="1" fill="#22d3ee" opacity="0.6"/>
24+
</svg>
25+
<span class="brand-name">BESSAI<span class="brand-tag">Edge</span></span>
26+
</div>
27+
<div class="nav-center">
28+
<span class="site-badge" id="site-id-badge">⚙ Conectando…</span>
29+
</div>
30+
<div class="nav-right">
31+
<div class="connection-indicator" id="conn-indicator">
32+
<span class="conn-dot" id="conn-dot"></span>
33+
<span id="conn-label">Offline</span>
34+
</div>
35+
<span class="nav-time" id="nav-time">--:--:--</span>
36+
</div>
37+
</nav>
38+
39+
<!-- ── MAIN GRID ─────────────────────────────────────────────── -->
40+
<main class="dashboard-grid">
41+
42+
<!-- ROW 1: KPI cards -->
43+
<section class="kpi-row">
44+
<!-- SOC Gauge -->
45+
<div class="card card-soc" id="card-soc">
46+
<div class="card-header">
47+
<span class="card-label">Estado de Carga</span>
48+
<span class="card-unit">SOC</span>
49+
</div>
50+
<div class="gauge-wrap">
51+
<svg class="gauge-svg" viewBox="0 0 200 120">
52+
<defs>
53+
<linearGradient id="gaugeGrad" x1="0%" y1="0%" x2="100%" y2="0%">
54+
<stop offset="0%" style="stop-color:#ef4444"/>
55+
<stop offset="30%" style="stop-color:#f59e0b"/>
56+
<stop offset="70%" style="stop-color:#22c55e"/>
57+
<stop offset="100%" style="stop-color:#06b6d4"/>
58+
</linearGradient>
59+
</defs>
60+
<!-- Track -->
61+
<path d="M 20 105 A 80 80 0 0 1 180 105" stroke="#1e2a3a" stroke-width="16" fill="none" stroke-linecap="round"/>
62+
<!-- Fill -->
63+
<path id="gauge-fill" d="M 20 105 A 80 80 0 0 1 180 105" stroke="url(#gaugeGrad)" stroke-width="16" fill="none" stroke-linecap="round" stroke-dasharray="0 251"/>
64+
<!-- Needle -->
65+
<circle id="gauge-needle-dot" cx="100" cy="105" r="4" fill="#6366f1" transform="rotate(-90 100 105)"/>
66+
</svg>
67+
<div class="gauge-value-wrap">
68+
<span class="gauge-value" id="soc-value">--</span>
69+
<span class="gauge-unit">%</span>
70+
</div>
71+
</div>
72+
<div class="gauge-labels">
73+
<span>0%</span><span>50%</span><span>100%</span>
74+
</div>
75+
<div class="gauge-status" id="soc-status"></div>
76+
</div>
77+
78+
<!-- Power Flow -->
79+
<div class="card card-power">
80+
<div class="card-header">
81+
<span class="card-label">Flujo de Potencia</span>
82+
<span class="card-unit">kW</span>
83+
</div>
84+
<div class="power-display">
85+
<div class="power-value-big" id="power-value">--</div>
86+
<div class="power-direction" id="power-dir">
87+
<span class="power-dir-arrow" id="power-arrow"></span>
88+
<span id="power-dir-label"></span>
89+
</div>
90+
</div>
91+
<div class="power-flow-diagram">
92+
<div class="flow-node" id="flow-grid">
93+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/></svg>
94+
<span>Red</span>
95+
</div>
96+
<div class="flow-arrow-wrap">
97+
<div class="flow-line" id="flow-line-1"></div>
98+
<div class="flow-particles" id="particles-1"></div>
99+
</div>
100+
<div class="flow-node flow-node-bess" id="flow-bess">
101+
<svg viewBox="0 0 32 32" fill="none" stroke="currentColor" stroke-width="2"><rect x="2" y="8" width="28" height="16" rx="3"/><rect x="30" y="12" width="2" height="8" rx="1" fill="currentColor" stroke="none"/></svg>
102+
<span>BESS</span>
103+
</div>
104+
<div class="flow-arrow-wrap">
105+
<div class="flow-line" id="flow-line-2"></div>
106+
<div class="flow-particles" id="particles-2"></div>
107+
</div>
108+
<div class="flow-node" id="flow-load">
109+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/></svg>
110+
<span>Carga</span>
111+
</div>
112+
</div>
113+
<div class="mini-stats">
114+
<span>Temp: <b id="temp-val">--°C</b></span>
115+
<span>Ciclos: <b id="cycles-val">--</b></span>
116+
</div>
117+
</div>
118+
119+
<!-- AI-IDS -->
120+
<div class="card card-ids" id="card-ids">
121+
<div class="card-header">
122+
<span class="card-label">AI — Detector de Anomalías</span>
123+
<span class="ids-status-badge" id="ids-badge">IDS</span>
124+
</div>
125+
<div class="ids-score-wrap">
126+
<div class="ids-score-ring">
127+
<svg viewBox="0 0 80 80">
128+
<circle cx="40" cy="40" r="32" stroke="#1e2a3a" stroke-width="8" fill="none"/>
129+
<circle id="ids-ring" cx="40" cy="40" r="32" stroke="#22d3ee" stroke-width="8" fill="none"
130+
stroke-dasharray="201" stroke-dashoffset="201" stroke-linecap="round"
131+
transform="rotate(-90 40 40)"/>
132+
</svg>
133+
<span class="ids-score-text" id="ids-score">0.00</span>
134+
</div>
135+
<div class="ids-info">
136+
<div class="ids-stat"><span>Alertas hoy</span><b id="ids-alerts">0</b></div>
137+
<div class="ids-stat"><span>Modelo</span><b id="ids-trained"></b></div>
138+
<div class="ids-stat"><span>ONNX</span><b id="onnx-status"></b></div>
139+
<div class="ids-stat"><span>Latencia</span><b id="onnx-ms">-- ms</b></div>
140+
</div>
141+
</div>
142+
</div>
143+
144+
<!-- Arbitraje / Ahorro -->
145+
<div class="card card-arbitrage">
146+
<div class="card-header">
147+
<span class="card-label">Arbitraje de Energía</span>
148+
<span class="card-unit">CLP</span>
149+
</div>
150+
<div class="arb-value-big" id="arb-net">$0</div>
151+
<div class="arb-label">Proyección neta 24h</div>
152+
<div class="arb-stats">
153+
<div class="arb-stat">
154+
<svg viewBox="0 0 16 16" fill="none" stroke="#22c55e" stroke-width="2"><path d="M8 14V2M3 7l5-5 5 5"/></svg>
155+
<span>Carga</span>
156+
<b id="arb-charge">-- h</b>
157+
</div>
158+
<div class="arb-divider"></div>
159+
<div class="arb-stat">
160+
<svg viewBox="0 0 16 16" fill="none" stroke="#f59e0b" stroke-width="2"><path d="M8 2v12M3 9l5 5 5-5"/></svg>
161+
<span>Descarga</span>
162+
<b id="arb-discharge">-- h</b>
163+
</div>
164+
<div class="arb-divider"></div>
165+
<div class="arb-stat">
166+
<svg viewBox="0 0 16 16" fill="none" stroke="#6366f1" stroke-width="2"><circle cx="8" cy="8" r="6"/><path d="M8 5v3l2 2"/></svg>
167+
<span>Fuente</span>
168+
<b id="arb-source">--</b>
169+
</div>
170+
</div>
171+
<button class="btn-refresh" id="btn-schedule" onclick="window.bessai.loadSchedule()">↻ Actualizar</button>
172+
</div>
173+
</section>
174+
175+
<!-- ROW 2: Charts + Alerts -->
176+
<section class="charts-row">
177+
<!-- SOC + Power History Chart -->
178+
<div class="card card-chart">
179+
<div class="card-header">
180+
<span class="card-label">Historial 24h — SOC y Potencia</span>
181+
<div class="chart-legend">
182+
<span class="legend-dot" style="background:#6366f1"></span>SOC (%)
183+
<span class="legend-dot" style="background:#22d3ee;margin-left:12px"></span>Potencia (kW)
184+
</div>
185+
</div>
186+
<div class="chart-container">
187+
<canvas id="chart-main"></canvas>
188+
</div>
189+
</div>
190+
191+
<!-- Alerts Feed -->
192+
<div class="card card-alerts">
193+
<div class="card-header">
194+
<span class="card-label">Eventos del Sistema</span>
195+
<span class="alerts-count" id="alerts-count">0</span>
196+
</div>
197+
<div class="alerts-feed" id="alerts-feed">
198+
<div class="alert-empty">Sin eventos recientes</div>
199+
</div>
200+
</div>
201+
</section>
202+
203+
<!-- ROW 3: Carbon + Fleet + Safety -->
204+
<section class="metrics-row">
205+
<div class="card card-carbon">
206+
<div class="card-header"><span class="card-label">🌿 Impacto Ambiental</span></div>
207+
<div class="metric-big"><span id="co2-val">0.0</span><span class="metric-unit">kg CO₂ evitado</span></div>
208+
<div class="metric-sub"><span id="trees-val">0.0</span> árboles equivalentes</div>
209+
<div class="metric-methodology">Metodología IEA WEO 2024 + IEEE 2030.6 LCA</div>
210+
</div>
211+
<div class="card card-fleet">
212+
<div class="card-header"><span class="card-label">🌐 Fleet Status</span></div>
213+
<div class="fleet-grid">
214+
<div class="fleet-stat"><span>Sitios</span><b id="fleet-sites">--</b></div>
215+
<div class="fleet-stat"><span>SOC Prom.</span><b id="fleet-soc">--%</b></div>
216+
<div class="fleet-stat"><span>Flex. Disp.</span><b id="fleet-kw">-- kW</b></div>
217+
<div class="fleet-stat"><span>Alarmas</span><b id="fleet-alarms" class="alarm-count">0</b></div>
218+
</div>
219+
</div>
220+
<div class="card card-safety">
221+
<div class="card-header"><span class="card-label">🛡️ Safety Guard</span></div>
222+
<div class="safety-status" id="safety-status-display">
223+
<div class="safety-icon" id="safety-icon"></div>
224+
<div class="safety-text" id="safety-text">NOMINAL</div>
225+
</div>
226+
<div class="safety-limits">
227+
<div class="limit-row"><span>SOC mín</span><b>5%</b></div>
228+
<div class="limit-row"><span>SOC máx</span><b>98%</b></div>
229+
<div class="limit-row"><span>Temp máx</span><b>45°C</b></div>
230+
</div>
231+
</div>
232+
<div class="card card-p2p">
233+
<div class="card-header"><span class="card-label">⚡ P2P Energy Trading</span></div>
234+
<div class="metric-big"><span id="p2p-kwh">0.0</span><span class="metric-unit">kWh en créditos</span></div>
235+
<div class="metric-sub"><span id="p2p-minted">0</span> créditos emitidos · <span id="p2p-pending">0</span> pendientes</div>
236+
</div>
237+
</section>
238+
239+
</main>
240+
241+
<!-- ── FOOTER ────────────────────────────────────────────────── -->
242+
<footer class="dash-footer">
243+
<span>BESSAI Edge Gateway</span>
244+
<span id="footer-version">v--</span>
245+
<span>Apache 2.0 · <a href="https://github.com/bess-solutions/open-bess-edge" target="_blank">GitHub</a></span>
246+
<span id="footer-uptime">Uptime: --</span>
247+
</footer>
248+
249+
<script src="main.js"></script>
250+
</body>
251+
</html>

0 commit comments

Comments
 (0)