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>
268 lines
11 KiB
HTML
268 lines
11 KiB
HTML
<!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.3.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.0–16.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.0–16.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">0–100%</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: <60°C green · 60–75°C amber · >75°C red
|
||
</div>
|
||
</div>
|
||
|
||
<!-- ╔═══════════════════ MOTOR CURRENT ═══════════════════╗ -->
|
||
<div class="card">
|
||
<div class="card-title">MOTOR CURRENT & 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>
|