Files
argo/web/index.html
T

216 lines
16 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">
<title>Sub Control</title>
<link rel="stylesheet" href="styles.css?v=20260930-dialogs-v1">
</head>
<body>
<main class="app-shell">
<!-- ── DECK (Connection, 3D Model, Battery, Deck Controls, Status) ── -->
<aside class="sidebar-deck" aria-label="Vehicle Deck and Status">
<div class="sidebar-drag-surface pywebview-drag-region" aria-hidden="true"></div>
<!-- Connection Controls -->
<div class="deck-connection">
<div class="port-row">
<select id="port" aria-label="Serial port">
<option value="demo" selected>Demo Mode (no hardware)</option>
</select>
<button id="refresh" class="icon-button" title="Refresh ports" aria-label="Refresh ports">
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 7v5h-5M4 17v-5h5M18.5 9A7 7 0 0 0 6.8 6.8L4 10m16 4-2.8 3.2A7 7 0 0 1 5.5 15"/></svg>
</button>
<button class="icon-button" data-open="link-modal" title="Link settings" aria-label="Link settings">
<svg class="dots-icon" viewBox="0 0 24 24" aria-hidden="true"><circle cx="5" cy="12" r="1.25"/><circle cx="12" cy="12" r="1.25"/><circle cx="19" cy="12" r="1.25"/></svg>
</button>
</div>
<button id="connect" class="button connect-button" aria-label="Toggle connection">
<span class="btn-spinner" aria-hidden="true"></span>
<span class="btn-label">Connect</span>
</button>
</div>
<!-- Telemetry / Status Zone -->
<section class="telemetry-zone" aria-label="Vehicle Telemetry and Status">
<div class="deck-card model-card">
<div class="rov-stage" aria-label="Top view of three-thruster ROV">
<canvas id="model-canvas" aria-label="Interactive STL vehicle model"></canvas>
<div id="model-status" class="model-status">Initializing…</div>
<div class="model-tools">
<button id="load-model">Load STL</button>
<input id="model-input" type="file" accept=".stl,.STL" hidden>
</div>
</div>
</div>
<!-- Battery Status -->
<button class="battery-card ghost" data-open="battery-modal">
<span><small>Battery</small><strong id="battery-title">—</strong></span><i id="battery-percent">waiting</i>
<b><em id="battery-fill"></em></b>
</button>
<button id="link-quality" type="button" class="link-quality" data-grade="offline" title="Open link-quality details" aria-haspopup="dialog" aria-controls="link-quality-modal">
<span class="link-quality-dot" aria-hidden="true"></span>
<span><small>Data link</small><strong id="link-quality-grade">Offline</strong></span>
<i><span id="link-quality-roundtrip">waiting for connection</span><span id="link-quality-downlink"></span></i>
</button>
<div class="deck-status-bar">
<ol class="activity-history" aria-label="Last three events" aria-live="polite">
<li id="activity-oldest" hidden></li>
<li id="activity-previous" hidden></li>
<li id="status-text">Not connected</li>
</ol>
<header class="activity-heading"><span>Recent activity</span><span class="activity-actions"><button type="button" id="console" class="logs-link" title="Read live console" aria-label="Read live console">Console</button><button type="button" id="logs" class="logs-link" title="Open session logs" aria-label="Open session logs">Logs</button></span></header>
</div>
</section>
</aside>
<!-- ── PRIMARY CONTROL ZONE ── -->
<section class="controls-workspace" aria-label="Primary Vehicle Controls">
<!-- Frameless Drag & Window Controls Header -->
<div class="workspace-topbar">
<div class="workspace-drag-area pywebview-drag-region"></div>
<div class="window-actions">
<button id="window-min" aria-label="Minimize" title="Minimize"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 12h14"/></svg></button>
<button id="window-max" aria-label="Maximize" title="Maximize"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="5" y="5" width="14" height="14" rx="1.5"/></svg></button>
<button id="window-close" class="window-close" aria-label="Close" title="Close"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m6 6 12 12M18 6 6 18"/></svg></button>
</div>
</div>
<section class="primary-control-zone" aria-label="Primary Control Zone">
<!-- Reserved Engage / Disarm row -->
<div class="engage-header-zone">
<button id="engage" class="button subtle engage-button" aria-label="Engage" aria-describedby="control-status" title="Engage (F2)">
<span class="engage-face">
<span id="engage-label" class="engage-label">engage</span>
<span class="engage-sheen-label" aria-hidden="true">engage</span>
<span class="engage-progress-label" aria-hidden="true">engage</span>
</span>
</button>
<p id="control-status" class="control-status" role="status" aria-live="polite">Connect to receive vehicle state.</p>
</div>
<!-- Main Joysticks & Thrust Control Grid -->
<div class="controls-grid">
<!-- Steering / Throttle Joystick -->
<article class="control-card steer-card">
<header>
<div><small>steer + throttle</small></div>
<span class="key-hint">w a s d</span>
</header>
<div class="joystick-pad">
<div id="joystick" class="joystick" touch-action="none">
<canvas id="joystick-canvas" aria-label="Steering and throttle joystick; W A S D keys"></canvas>
</div>
</div>
<footer>
<span class="steer-readout-left">surge <b id="surge-readout">—</b></span>
<span class="steer-readout-right"><b id="yaw-readout">—</b> turn</span>
</footer>
</article>
<!-- Vertical Thruster Slider -->
<article class="control-card vertical-card">
<header>
<div><small>vertical</small></div>
<span class="key-hint">r / f</span>
</header>
<div class="heave-pad">
<div class="vertical-control">
<span>rise</span>
<div id="heave" class="heave-track" touch-action="none">
<div class="heave-center"></div>
<div id="heave-fill" class="heave-fill"></div>
<div id="heave-knob" class="heave-knob"></div>
</div>
<span>dive</span>
</div>
</div>
<footer>
<span><b id="heave-readout">—</b> vertical</span>
</footer>
</article>
</div>
<div class="control-toolbar">
<label class="output-limit">
<span>Output limit <b id="gain-value">20%</b></span>
<div class="range-pill">
<button id="gain-down" type="button" aria-label="Decrease output limit"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="m14 6-6 6 6 6"/></svg></button>
<input id="gain" aria-label="Output limit" type="range" min="5" max="50" value="20">
<button id="gain-up" type="button" aria-label="Increase output limit"><svg viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="m10 6 6 6-6 6"/></svg></button>
</div>
</label>
<button class="button subtle config-btn" data-open="motors-modal">Motor setup</button>
</div>
</section>
</section>
</main>
<div id="toast" class="toast"></div>
<!-- Modals -->
<dialog id="link-modal" class="modal" aria-labelledby="link-title">
<button class="modal-close" type="button" data-close aria-label="Close window">×</button><small>Connection</small><h2 id="link-title">Link settings</h2>
<form id="link-form">
<section class="settings-section"><h3>Serial connection</h3>
<div class="form-grid two"><label><span>Baud rate</span><select id="baud" name="baud"><option value="9600">9600</option><option value="19200">19200</option><option value="38400">38400</option><option value="57600" selected>57600</option><option value="115200">115200</option></select></label><label><span>Control rate · Hz</span><select id="rate" name="control_hz"><option value="10">10</option><option value="20" selected>20</option></select></label></div>
<p class="note">Baud changes apply on the next connection.</p>
<label class="custom-port-label"><span>Custom port or endpoint</span><div class="custom-port-row"><input id="custom-port-input" placeholder="COM3 or tcp:127.0.0.1:5760" autocomplete="off"><button type="button" id="custom-port-btn" class="button subtle">Use port</button></div></label>
<p id="custom-port-status" class="note" role="status"></p>
</section>
<section class="settings-section"><h3>Live updates</h3>
<div class="form-grid two">
<label><span>Quality check · Hz</span><select name="ping_hz"><option value="1" selected>1</option><option value="2">2</option><option value="5">5</option><option value="10">10</option></select></label>
<label><span>Battery / system · Hz</span><select name="system_hz"><option value="0">Off</option><option value="1" selected>1</option><option value="2">2</option><option value="5">5</option><option value="10">10</option></select></label>
<label><span>Motor outputs · Hz</span><select name="servo_hz"><option value="0">Off</option><option value="1">1</option><option value="2" selected>2</option><option value="5">5</option><option value="10">10</option></select></label>
<label><span>RC channels · Hz</span><select name="rc_hz"><option value="0">Off</option><option value="1">1</option><option value="2" selected>2</option><option value="5">5</option><option value="10">10</option></select></label>
<label><span>ESC telemetry · Hz</span><select name="esc_hz"><option value="0">Off</option><option value="1" selected>1</option><option value="2">2</option><option value="5">5</option><option value="10">10</option></select></label>
</div>
<p class="note">Lower rates leave more bandwidth for controls. Vehicle telemetry rates reset after a reboot.</p>
</section>
<p class="form-feedback" role="alert" hidden></p>
<div class="modal-actions"><button type="button" class="button subtle" data-close>Cancel</button><button type="submit" class="button modal-primary">Apply settings</button></div>
</form>
</dialog>
<dialog id="link-quality-modal" class="modal quality-modal" aria-labelledby="quality-title">
<button class="modal-close" type="button" data-close aria-label="Close window">×</button><small>Connection</small><h2 id="quality-title">Link quality</h2>
<p class="note">The live check watches round-trip replies, incoming packet loss, and heartbeat freshness.</p>
<div class="quality-summary"><div><span>Round trip</span><strong id="quality-detail-rtt">—</strong></div><div><span>Probe loss</span><strong id="quality-detail-loss">—</strong></div><div><span>FC → PC loss</span><strong id="quality-detail-downlink">—</strong></div></div>
<section class="heavy-test-panel"><h3>Extended test</h3><p class="note">Checks 1, 5, then 10 Hz for about 35 seconds. Run while disarmed; the live echo resumes afterward.</p>
<div id="heavy-quality-status" class="heavy-quality-status" role="status">Connect to run an extended test.</div>
<div id="heavy-quality-results" class="heavy-quality-results"></div>
<p id="heavy-quality-error" class="form-feedback" role="alert" hidden></p>
<div class="modal-actions"><button id="heavy-quality-run" type="button" class="button modal-primary">Run extended test</button><button id="heavy-quality-cancel" type="button" class="button subtle" hidden>Stop test</button></div>
</section>
</dialog>
<dialog id="battery-modal" class="modal" aria-labelledby="battery-title-modal">
<button class="modal-close" type="button" data-close aria-label="Close window">×</button><small>Power</small><h2 id="battery-title-modal">Battery settings</h2><p class="note">Charge is estimated from voltage. Capacity and C rating describe your battery.</p>
<form id="battery-form">
<div class="form-grid two"><label><span>Cells · S</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease Cells · S">‹</button><input name="cells" type="number" min="1" step="1" max="16" required><button type="button" class="num-step up" aria-label="Increase Cells · S">›</button></div></label><label><span>Capacity · mAh</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease Capacity · mAh">‹</button><input name="capacity_mah" type="number" min="50" step="50" required><button type="button" class="num-step up" aria-label="Increase Capacity · mAh">›</button></div></label><label><span>C rating</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease C rating">‹</button><input name="c_rating" type="number" min="1" step="0.1" required><button type="button" class="num-step up" aria-label="Increase C rating">›</button></div></label><label><span>Low charge warning · %</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease Low charge warning · %">‹</button><input name="warning_percent" type="number" min="0" step="1" max="100" required><button type="button" class="num-step up" aria-label="Increase Low charge warning · %">›</button></div></label></div>
<section class="settings-section"><h3>Voltage per cell</h3><div class="form-grid two"><label><span>Full · V</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease Full · V">‹</button><input name="full_v_per_cell" type="number" min="0.01" step="0.01" required><button type="button" class="num-step up" aria-label="Increase Full · V">›</button></div></label><label><span>Empty · V</span><div class="number-pill"><button type="button" class="num-step down" aria-label="Decrease Empty · V">‹</button><input name="empty_v_per_cell" type="number" min="0.01" step="0.01" required><button type="button" class="num-step up" aria-label="Increase Empty · V">›</button></div></label></div></section>
<p class="form-feedback" role="alert" hidden></p>
<div class="modal-actions"><button type="button" class="button subtle" data-close>Cancel</button><button type="submit" class="button modal-primary">Save battery</button></div>
</form>
</dialog>
<dialog id="motors-modal" class="modal motor-modal" aria-labelledby="motors-title">
<button class="modal-close" type="button" data-close aria-label="Close window">×</button><small>Configuration</small><h2 id="motors-title">Motor outputs</h2><p id="motor-status" class="note" role="status">Waiting for motor assignments.</p>
<p id="motor-feedback" class="form-feedback" role="alert" hidden></p>
<div class="motor-head"><span>Output</span><span>Assignment</span><span>Direction</span><span></span></div><div id="motor-list" class="motor-list"></div>
</dialog>
<dialog id="console-modal" class="modal console-modal" aria-labelledby="console-title">
<button class="modal-close" type="button" data-close aria-label="Close window">×</button><small>Local session</small><h2 id="console-title">Live console</h2>
<div class="console-toolbar"><p id="console-state" class="note" role="status">Live · follows new messages</p><button id="console-pause" type="button" class="button subtle" aria-pressed="false">Pause</button></div>
<div class="console-split"><section><header><i class="rx-dot"></i><span>RX</span><small>Vehicle → PC</small></header><pre id="console-rx-output" tabindex="0" aria-label="Received messages">Waiting for vehicle data…</pre></section><section><header><i class="tx-dot"></i><span>TX</span><small>PC → Vehicle</small></header><pre id="console-tx-output" tabindex="0" aria-label="Sent messages">Waiting for transmitted data…</pre></section></div>
</dialog>
<script src="model-viewer.js?v=20260826-controls-v2"></script>
<script src="joystick-3d.js?v=20260827-keyboard-v7"></script>
<script src="control-state.js?v=20260827-state-v1"></script>
<script src="app.js?v=20260930-dialogs-v1"></script>
<script src="cursor-light.js?v=20260827-directional-v10"></script>
</body>
</html>