rov-autonomy/widgets/diagnostics/w_probe_api.json

8 lines
6.8 KiB
JSON

{
"html": "<div id=\"probe-root\"><div id=\"probe-methods\"></div><div id=\"probe-heading\">heading: waiting...</div><div id=\"probe-status\">status: starting</div></div>",
"css": "#probe-root { font-family: monospace; font-size: 11px; color: #00ff00; background: #111; padding: 6px; overflow-y: auto; height: 100%; } #probe-methods { margin-bottom: 6px; border-bottom: 1px solid #333; padding-bottom: 6px; } #probe-heading { font-size: 14px; color: #ffff00; margin-bottom: 4px; } #probe-status { color: #aaa; font-size: 10px; }",
"js": "// ============================================================\n// Argonaut 3 -- window.cockpit API Probe Widget\n// Purpose: enumerate every method on window.cockpit, then\n// try every plausible data-lake read method for\n// 'external/rov-heading'. Run this once to confirm\n// the correct method name before building W1-W5.\n// Version: 1.0 Date: 2026-06-22\n// Source researched: github.com/bluerobotics/cockpit\n// src/libs/external-api/api.ts (commit 52fb1a2d)\n// The External API uses postMessage (iframes only).\n// DIY widgets run inline -- window.cockpit surface is\n// different and must be probed at runtime.\n// ============================================================\n\n// --- 1. ENUMERATE window.cockpit METHODS ---\n// Run immediately so the method list appears even if\n// data-lake calls fail.\n(function enumerateCockpitMethods() {\n var el = document.getElementById('probe-methods');\n var status = document.getElementById('probe-status');\n if (!el) return;\n\n // Check whether window.cockpit exists at all\n if (typeof window.cockpit === 'undefined') {\n el.innerText = 'ERROR: window.cockpit is undefined';\n if (status) status.innerText = 'status: cockpit object missing -- Pirate Mode enabled?';\n return;\n }\n\n // Collect all own + inherited enumerable keys\n var keys = [];\n for (var k in window.cockpit) {\n try {\n keys.push(k + ' [' + typeof window.cockpit[k] + ']');\n } catch (e) {\n keys.push(k + ' [access error]');\n }\n }\n\n // Also check Object.keys for non-enumerable own props\n var ownKeys = Object.keys(window.cockpit);\n var methodLine = 'window.cockpit methods (' + keys.length + '):\\n' + keys.join('\\n');\n el.innerText = methodLine;\n if (status) status.innerText = 'status: enumerated ' + keys.length + ' keys';\n})();\n\n// --- 2. PROBE DATA-LAKE READ METHODS ---\n// We try each candidate method in sequence.\n// The first one that returns a non-undefined value for\n// 'external/rov-heading' is the correct method for W1-W5.\n\n(function probeDataLake() {\n var headingEl = document.getElementById('probe-heading');\n var statusEl = document.getElementById('probe-status');\n if (!headingEl) return;\n if (typeof window.cockpit === 'undefined') return; // already flagged above\n\n // Candidate method names to probe, in priority order.\n // Based on source research:\n // - getAllDataLakeVariablesInfo() = CONFIRMED metadata-only (id/name/type)\n // - getDataLakeVariableData() = internal Cockpit function (utils-data-lake.ts)\n // - getDataLakeVariableInfo() = paired with above in same file\n // - getDataLakeValue() = mentioned in older docs, not confirmed\n // - listenToDatalakeVariable() = External API (postMessage, for iframes)\n var VARIABLE_ID = 'external/rov-heading';\n var candidates = [\n 'getDataLakeVariableData',\n 'getDataLakeValue',\n 'getDataLakeVariableInfo',\n 'listenToDatalakeVariable'\n ];\n\n // Track which methods exist vs are callable\n var results = [];\n\n // Try synchronous getters first (candidates 0-2)\n var syncCandidates = candidates.slice(0, 3);\n for (var i = 0; i < syncCandidates.length; i++) {\n var name = syncCandidates[i];\n if (typeof window.cockpit[name] !== 'function') {\n results.push(name + ': NOT a function (type=' + typeof window.cockpit[name] + ')');\n continue;\n }\n try {\n var result = window.cockpit[name](VARIABLE_ID);\n if (result !== undefined && result !== null) {\n // Found it -- display the live value\n results.push(name + ': WORKS -> ' + JSON.stringify(result));\n headingEl.innerText = 'heading (' + name + '): ' + JSON.stringify(result);\n statusEl.innerText = 'status: live read confirmed via ' + name;\n } else {\n results.push(name + ': returned undefined/null');\n }\n } catch (e) {\n results.push(name + ': threw -> ' + e.message);\n }\n }\n\n // Try callback-based listenToDatalakeVariable last\n // It registers a callback, not a sync return\n var listenName = 'listenToDatalakeVariable';\n if (typeof window.cockpit[listenName] === 'function') {\n try {\n window.cockpit[listenName](VARIABLE_ID, function(value) {\n var el = document.getElementById('probe-heading');\n if (el) el.innerText = 'heading (listenToDatalakeVariable callback): ' + JSON.stringify(value);\n var sel = document.getElementById('probe-status');\n if (sel) sel.innerText = 'status: live callback from listenToDatalakeVariable';\n });\n results.push(listenName + ': registered callback (watching for value...)');\n } catch (e) {\n results.push(listenName + ': threw -> ' + e.message);\n }\n } else {\n results.push(listenName + ': NOT a function');\n }\n\n // Append probe results under the method list\n var methodsEl = document.getElementById('probe-methods');\n if (methodsEl) {\n methodsEl.innerText += '\\n\\n--- DATA LAKE PROBE ---\\nvar=' + VARIABLE_ID + '\\n' + results.join('\\n');\n }\n})();\n\n// --- 3. LIVE POLL --- \n// If any sync getter worked, re-call it every 2s so we can\n// confirm it tracks live updates (heading should change as\n// the cockpit_bridge publishes new values).\n// We do NOT know which method works yet, so we poll all\n// sync candidates that exist and update the display.\n(function livePoll() {\n var VARIABLE_ID = 'external/rov-heading';\n var syncCandidates = ['getDataLakeVariableData', 'getDataLakeValue', 'getDataLakeVariableInfo'];\n\n // setInterval is allowed in DIY widget JS\n setInterval(function() {\n if (typeof window.cockpit === 'undefined') return;\n for (var i = 0; i < syncCandidates.length; i++) {\n var name = syncCandidates[i];\n if (typeof window.cockpit[name] !== 'function') continue;\n try {\n var val = window.cockpit[name](VARIABLE_ID);\n if (val !== undefined && val !== null) {\n var el = document.getElementById('probe-heading');\n if (el) el.innerText = 'heading (' + name + '): ' + JSON.stringify(val);\n var sel = document.getElementById('probe-status');\n if (sel) sel.innerText = 'status: polling OK via ' + name;\n return; // first working method wins\n }\n } catch (e) { /* silent -- error shown in method list above */ }\n }\n }, 2000);\n})();"
}