rov-autonomy/widgets/w4_mission_setup_button.html

177 lines
5.7 KiB
HTML

<!DOCTYPE html>
<!--
============================================================
ARGONAUT 3 — MISSION SETUP BUTTON
Widget 4
============================================================
Purpose : Open the mission setup page in a new browser tab
without leaving the Cockpit dive view.
Visual : Subdued (dim) when a mission is active (running or
paused) to indicate it is available but not the
current priority. Full brightness when IDLE —
prompts the operator to configure before diving.
Data : Reads rov_mission_state to detect active mission.
Action : window.open() to setup page URL.
Config : Edit SETUP_URL below to match your deployment.
Import : Cockpit → Edit mode → Add DIY Widget →
gear icon → Import → select this file
Version : 1.0
============================================================
-->
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
:root {
--bg: #09111a;
--border: #1e3050;
--text0: #d8eeff;
--text1: #6a9bbf;
--accent: #00c8f0;
--dim: #1a2d42;
--amber: #ffb830;
--mono: 'Courier New', monospace;
}
body {
background: var(--bg);
color: var(--text0);
font-family: var(--mono);
height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
padding: 10px;
gap: 6px;
}
/* ── Setup button ────────────────────────────────────────── */
#setup-btn {
width: 100%;
padding: 10px 0;
background: transparent;
border: 1px solid var(--accent);
border-radius: 5px;
color: var(--accent);
font-family: var(--mono);
font-size: 12px;
font-weight: bold;
letter-spacing: 0.1em;
text-transform: uppercase;
cursor: pointer;
transition: background 0.2s, border-color 0.2s, color 0.2s, opacity 0.3s;
}
#setup-btn:hover {
background: rgba(0,200,240,0.1);
box-shadow: 0 0 10px rgba(0,200,240,0.3);
}
/* Subdued state when mission is active */
#setup-btn.subdued {
border-color: var(--dim);
color: var(--text1);
opacity: 0.5;
}
#setup-btn.subdued:hover {
opacity: 0.75;
background: transparent;
box-shadow: none;
}
/* ── Status line ─────────────────────────────────────────── */
#status {
font-size: 9px;
color: var(--text1);
text-align: center;
}
#status.active-warn { color: var(--amber); }
</style>
<body>
<button id="setup-btn">⚙ Mission Setup</button>
<div id="status"></div>
</body>
<script>
// ── Config ────────────────────────────────────────────────
// URL for the mission setup page served by the extension backend
const SETUP_URL = 'http://blueos.local:8081/setup';
// Data lake variable for mission state (to detect active mission)
const VAR_STATE = 'rov_mission_state';
const POLL_MS = 1000; // less frequent poll — state changes slowly
// Mission state values (matches rov_interfaces/MissionStatus)
const STATE_IDLE = 0;
const STATE_RUNNING = 1;
const STATE_PAUSED = 2;
const STATE_COMPLETE = 3;
const STATE_ABORTED = 4;
// ── DOM references ────────────────────────────────────────
const setupBtn = document.getElementById('setup-btn');
const statusEl = document.getElementById('status');
// ── Button click — open setup page ───────────────────────
setupBtn.addEventListener('click', () => {
window.open(SETUP_URL, '_blank', 'noopener,noreferrer');
});
// ── Poll mission state to control button appearance ───────
function poll() {
try {
if (typeof window.cockpit === 'undefined' ||
typeof window.cockpit.getDataLakeValue !== 'function') {
// API not ready — show neutral state
setupBtn.classList.remove('subdued');
statusEl.className = '';
statusEl.textContent = 'Connecting…';
return;
}
const stateRaw = window.cockpit.getDataLakeValue(VAR_STATE);
if (stateRaw === null || stateRaw === undefined) {
// Bridge not running — show button normally (no mission context)
setupBtn.classList.remove('subdued');
statusEl.className = '';
statusEl.textContent = 'No mission loaded';
return;
}
const state = parseInt(stateRaw, 10);
if (state === STATE_RUNNING || state === STATE_PAUSED) {
// Mission in progress — subdue the button (still accessible)
setupBtn.classList.add('subdued');
statusEl.className = 'active-warn';
statusEl.textContent = state === STATE_RUNNING
? 'Mission running — setup changes not recommended'
: 'Mission paused — setup changes not recommended';
} else {
// IDLE / COMPLETE / ABORTED — full brightness
setupBtn.classList.remove('subdued');
statusEl.className = '';
statusEl.textContent = state === STATE_IDLE
? 'No mission loaded — configure before diving'
: 'Ready to configure next mission';
}
} catch (err) {
console.error('[Setup Button Widget]', err);
}
}
// ── Start ─────────────────────────────────────────────────
setTimeout(poll, 300);
setInterval(poll, POLL_MS);
</script>