Files
argo/web/control-state.js
2026-08-27 18:24:22 +02:00

33 lines
2.0 KiB
JavaScript

/* Presentation derived from telemetry. No animation is allowed to set armed. */
((root) => {
function present(state, {stale=false, focused=true, pending=null, error=''}={}) {
const known = state.armed_known === true && !stale;
const online = !!state.connected && !stale;
const request = pending || state.pending_command;
const uncertain = !known && (state.armed !== null && state.armed !== undefined || !!request || state.heartbeat_age != null);
let label='ENGAGE', tone='idle', action=null, message='Connect to receive vehicle state.';
if (request === 'disarm') {
label='DISARMING…'; tone='danger'; message='Awaiting vehicle confirmation. Not yet confirmed disarmed.';
} else if (request === 'arm') {
label='ENGAGING…'; tone='pending'; action=online?'disarm':null;
message='Awaiting vehicle confirmation. Tap to request disarm.';
} else if (known && state.armed) {
label='DISARM'; tone='danger'; action=online?'disarm':null;
message=focused?'Armed · tap or F3 to disarm.':'Armed · controls neutral while the app is unfocused.';
} else if (uncertain) {
label=online?'DISARM · ?':'STATE UNKNOWN'; tone='danger'; action=online?'disarm':null;
message='Vehicle state unknown. Inputs cleared; disarm is not confirmed.';
} else if (known && online) {
action=focused?'arm':null; message='Disarmed · hold 1.4 seconds to engage.';
}
if (stale) message='Telemetry unavailable. Inputs cleared; vehicle state unknown.';
const failure=error || state.command_error;
return {label,tone,action,pending:!!request,known,
drive:known && online && state.armed === true && !request && focused,
message:failure ? `${failure} ${known ? (state.armed?'Vehicle armed.':'Vehicle disarmed.') : 'Vehicle state unknown.'}` : message,
error:!!(error || state.command_error || uncertain || stale)};
}
root.ControlState={present};
if(typeof module!=='undefined') module.exports=root.ControlState;
})(typeof window!=='undefined'?window:globalThis);