saltylab-firmware/ui/diagnostics_panel.html
sl-firmware fa75c442a7 feat: remove all STM32/Mamba/BlackPill references — ESP32-S3 only
Archive STM32 firmware to legacy/stm32/:
- src/, include/, lib/USB_CDC/, platformio.ini, test stubs, flash_firmware.py
- test/test_battery_adc.c, test_hw_button.c, test_pid_schedule.c, test_vesc_can.c, test_can_watchdog.c
- USB_CDC_BUG.md

Rename: stm32_protocol → esp32_protocol, mamba_protocol → balance_protocol,
  stm32_cmd_node → esp32_cmd_node, stm32_cmd_params → esp32_cmd_params,
  stm32_cmd.launch.py → esp32_cmd.launch.py,
  test_stm32_protocol → test_esp32_protocol, test_stm32_cmd_node → test_esp32_cmd_node

Content cleanup across all files:
- Mamba F722S → ESP32-S3 BALANCE
- BlackPill → ESP32-S3 IO
- STM32F722/F7xx → ESP32-S3
- stm32Mode/Version/Port → esp32Mode/Version/Port
- STM32 State/Mode labels → ESP32 State/Mode
- Jetson Nano → Jetson Orin Nano Super
- /dev/stm32 → /dev/esp32
- stm32_bridge → esp32_bridge
- STM32 HAL → ESP-IDF

docs/SALTYLAB.md:
- Update "Drone FC Details" to describe ESP32-S3 BALANCE board (Waveshare ESP32-S3 Touch LCD 1.28)
- Replace verbose "Self-Balancing Control" STM32 section with brief note pointing to SAUL-TEE-SYSTEM-REFERENCE.md

TEAM.md: Update Embedded Firmware Engineer role to ESP32-S3 / ESP-IDF

No new functionality — cleanup only.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-04 09:00:38 -04:00

268 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<title>Saltybot — System Diagnostics</title>
<link rel="stylesheet" href="diagnostics_panel.css">
<script src="https://cdn.jsdelivr.net/npm/roslib@1.4.0/build/roslib.min.js"></script>
</head>
<body>
<!-- ── Header ── -->
<div id="header">
<div class="logo">⚡ SALTYBOT — DIAGNOSTICS</div>
<div id="conn-bar">
<div id="conn-dot"></div>
<input id="ws-input" type="text" value="ws://localhost:9090" placeholder="ws://robot-ip:9090" />
<button id="btn-connect" class="hdr-btn">CONNECT</button>
<span id="conn-label" style="color:#4b5563;font-size:10px">Not connected</span>
</div>
<div id="refresh-info">
<div id="refresh-dot"></div>
<span>auto 2 Hz</span>
</div>
</div>
<!-- ── System status bar ── -->
<div id="status-bar">
<span style="color:#6b7280;font-size:10px">SYSTEM</span>
<span class="sys-badge badge-stale" id="system-badge">STALE</span>
<span style="color:#4b5563"></span>
<span style="color:#6b7280;font-size:10px">BATTERY</span>
<span class="sys-badge badge-stale" id="batt-badge"></span>
<span style="color:#4b5563"></span>
<span style="color:#6b7280;font-size:10px">THERMAL</span>
<span class="sys-badge badge-stale" id="temp-badge"></span>
<span style="color:#4b5563"></span>
<span style="color:#6b7280;font-size:10px">NETWORK</span>
<span class="sys-badge badge-stale" id="net-badge"></span>
<span id="last-update">Awaiting data…</span>
</div>
<!-- ── Dashboard grid ── -->
<div id="dashboard">
<!-- ╔═══════════════════ BATTERY ═══════════════════╗ -->
<div class="card span2">
<div class="card-title">
BATTERY — 4S LiPo (12.016.8 V)
<span class="badge badge-stale" id="batt-badge-2" style="font-size:9px"></span>
</div>
<!-- Big readout row -->
<div style="display:flex;gap:16px;align-items:flex-end;flex-wrap:wrap">
<div>
<div style="font-size:9px;color:#6b7280;margin-bottom:2px">VOLTAGE</div>
<div class="big-metric">
<span class="big-num" id="batt-voltage" style="color:#22c55e"></span>
</div>
</div>
<div>
<div style="font-size:9px;color:#6b7280;margin-bottom:2px">SOC</div>
<div class="big-metric">
<span class="big-num" id="batt-soc" style="color:#22c55e"></span>
</div>
</div>
<div>
<div style="font-size:9px;color:#6b7280;margin-bottom:2px">CURRENT</div>
<div class="big-metric">
<span class="big-num" id="batt-current" style="color:#06b6d4;font-size:20px"></span>
</div>
</div>
</div>
<!-- Gauge bars -->
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">Voltage</span>
<span class="gauge-value" id="batt-voltage-2" style="color:#6b7280">12.016.8 V</span>
</div>
<div class="gauge-track"><div class="gauge-fill" id="batt-volt-bar" style="width:0%"></div></div>
</div>
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">State of Charge</span>
<span class="gauge-value" style="color:#6b7280">0100%</span>
</div>
<div class="gauge-track"><div class="gauge-fill" id="batt-soc-bar" style="width:0%"></div></div>
</div>
<!-- Sparkline history -->
<div>
<div style="font-size:9px;color:#6b7280;margin-bottom:4px">VOLTAGE HISTORY (last 2 min)</div>
<canvas id="batt-sparkline" height="56"></canvas>
</div>
</div>
<!-- ╔═══════════════════ TEMPERATURES ═══════════════════╗ -->
<div class="card">
<div class="card-title">TEMPERATURES</div>
<div class="temp-grid">
<div class="temp-box" id="cpu-temp-box">
<div class="temp-label">CPU (Jetson)</div>
<div class="temp-value" id="cpu-temp-val"></div>
<div class="temp-bar-track"><div class="temp-bar-fill" id="cpu-temp-bar" style="width:0%"></div></div>
</div>
<div class="temp-box" id="gpu-temp-box">
<div class="temp-label">GPU (Jetson)</div>
<div class="temp-value" id="gpu-temp-val"></div>
<div class="temp-bar-track"><div class="temp-bar-fill" id="gpu-temp-bar" style="width:0%"></div></div>
</div>
<div class="temp-box" id="board-temp-box">
<div class="temp-label">Board / ESP32-S3</div>
<div class="temp-value" id="board-temp-val"></div>
<div class="temp-bar-track"><div class="temp-bar-fill" id="board-temp-bar" style="width:0%"></div></div>
</div>
<div class="temp-box" id="motor-temp-l-box">
<div class="temp-label">Motor L</div>
<div class="temp-value" id="motor-temp-l-val"></div>
<div class="temp-bar-track"><div class="temp-bar-fill" id="motor-temp-l-bar" style="width:0%"></div></div>
</div>
<!-- spacer to keep 2-col grid balanced if motor-temp-r is alone -->
<div class="temp-box" id="motor-temp-r-box">
<div class="temp-label">Motor R</div>
<div class="temp-value" id="motor-temp-r-val"></div>
<div class="temp-bar-track"><div class="temp-bar-fill" id="motor-temp-r-bar" style="width:0%"></div></div>
</div>
</div>
<div style="font-size:9px;color:#374151">
Zones: &lt;60°C green · 6075°C amber · &gt;75°C red
</div>
</div>
<!-- ╔═══════════════════ MOTOR CURRENT ═══════════════════╗ -->
<div class="card">
<div class="card-title">MOTOR CURRENT &amp; CMD</div>
<div class="motor-grid">
<div class="motor-box">
<div class="motor-label">LEFT WHEEL</div>
<div style="font-size:20px;font-weight:bold;font-family:monospace" id="motor-cur-l"></div>
<div class="gauge-track" style="margin-top:4px">
<div class="gauge-fill" id="motor-bar-l" style="width:0%"></div>
</div>
<div style="font-size:9px;color:#4b5563;margin-top:4px">
CMD: <span id="motor-cmd-l" style="color:#6b7280"></span>
</div>
</div>
<div class="motor-box">
<div class="motor-label">RIGHT WHEEL</div>
<div style="font-size:20px;font-weight:bold;font-family:monospace" id="motor-cur-r"></div>
<div class="gauge-track" style="margin-top:4px">
<div class="gauge-fill" id="motor-bar-r" style="width:0%"></div>
</div>
<div style="font-size:9px;color:#4b5563;margin-top:4px">
CMD: <span id="motor-cmd-r" style="color:#6b7280"></span>
</div>
</div>
</div>
<div style="font-size:10px;color:#6b7280">
Balance state: <span id="balance-state" style="color:#9ca3af;font-family:monospace"></span>
</div>
<div style="font-size:9px;color:#374151">Thresholds: warn 8A · crit 12A</div>
</div>
<!-- ╔═══════════════════ MEMORY / DISK ═══════════════════╗ -->
<div class="card">
<div class="card-title">RESOURCES</div>
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">RAM</span>
<span class="gauge-value" id="ram-val" style="color:#9ca3af"></span>
</div>
<div class="gauge-track"><div class="gauge-fill" id="ram-bar" style="width:0%"></div></div>
</div>
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">GPU Memory</span>
<span class="gauge-value" id="gpu-val" style="color:#9ca3af"></span>
</div>
<div class="gauge-track"><div class="gauge-fill" id="gpu-bar" style="width:0%"></div></div>
</div>
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">Disk</span>
<span class="gauge-value" id="disk-val" style="color:#9ca3af"></span>
</div>
<div class="gauge-track"><div class="gauge-fill" id="disk-bar" style="width:0%"></div></div>
</div>
<div style="font-size:9px;color:#374151">Warn ≥80% · Critical ≥95%</div>
</div>
<!-- ╔═══════════════════ WIFI / LATENCY ═══════════════════╗ -->
<div class="card">
<div class="card-title">NETWORK</div>
<div style="display:flex;align-items:center;gap:12px;flex-wrap:wrap">
<div id="rssi-bars" class="rssi-bars"></div>
<div>
<div style="font-size:9px;color:#6b7280">RSSI</div>
<div style="font-size:20px;font-weight:bold;font-family:monospace" id="rssi-val"></div>
<div style="font-size:9px" id="rssi-label" style="color:#6b7280"></div>
</div>
</div>
<div class="gauge-row">
<div class="gauge-label-row">
<span class="gauge-label">Rosbridge Latency</span>
<span class="gauge-value" id="latency-val" style="color:#9ca3af"></span>
</div>
</div>
<!-- MQTT status -->
<div style="margin-top:4px;padding-top:8px;border-top:1px solid #0c2a3a">
<div style="font-size:9px;color:#6b7280;margin-bottom:4px">MQTT BROKER</div>
<div class="mqtt-status">
<div class="mqtt-dot" id="mqtt-dot"></div>
<span id="mqtt-label" style="color:#6b7280">No data</span>
</div>
<div style="font-size:9px;color:#374151;margin-top:4px">
Via /diagnostics KeyValue: mqtt_connected
</div>
</div>
</div>
<!-- ╔═══════════════════ ROS2 NODE HEALTH ═══════════════════╗ -->
<div class="card span3">
<div class="card-title">
ROS2 NODE HEALTH — /diagnostics
<span style="font-size:9px;color:#4b5563" id="node-count">0 nodes</span>
</div>
<div id="node-list">
<div style="color:#374151;font-size:10px;text-align:center;padding:12px">
Waiting for /diagnostics data…
</div>
</div>
</div>
</div>
<!-- ── Footer ── -->
<div id="footer">
<span>rosbridge: <code id="footer-ws">ws://localhost:9090</code></span>
<span>diagnostics dashboard — issue #562 · auto 2Hz</span>
</div>
<script src="diagnostics_panel.js"></script>
<script>
// Sync footer WS URL
document.getElementById('ws-input').addEventListener('input', (e) => {
document.getElementById('footer-ws').textContent = e.target.value;
});
// Keep node count updated after render
const origRenderNodes = window.renderNodes;
const nodeCountEl = document.getElementById('node-count');
const _origOnDiag = window.onDiagnostics;
// Node count updates via MutationObserver on the node-list div
const nl = document.getElementById('node-list');
if (nl) {
new MutationObserver(() => {
const rows = nl.querySelectorAll('.node-row');
if (nodeCountEl) nodeCountEl.textContent = rows.length + ' node' + (rows.length !== 1 ? 's' : '');
}).observe(nl, { childList: true, subtree: false });
}
</script>
</body>
</html>