From fb6f0182cc1527551185d00b7513e12019d3fc30 Mon Sep 17 00:00:00 2001 From: karim Date: Wed, 3 Jun 2026 20:34:20 +0200 Subject: [PATCH] PFD CDI softkey cycles nav source; demo reflects dataref writes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The CDI softkey was in the PFD root row but had no handler — it never cycled the HSI/CDI source (GPS↔VLOC1↔VLOC2). Wire it to write cdiSrc (HSI_source_select_pilot, now writable), cycling GPS→NAV1→NAV2. Also fix a latent demo bug: the 'needs a live sim socket' guard sat above the setDataref/command handlers, so in DEMO (no sim socket) every dataref write (transponder code, baro, AP bugs, CDI) was silently dropped. Reflect writes locally before that guard so cockpit controls respond without a sim. Co-Authored-By: Claude Opus 4.8 --- server/bridge.js | 15 +++++++++++++-- server/config.js | 1 + web/src/components/Bezel.jsx | 4 ++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/server/bridge.js b/server/bridge.js index 1855740..81427a2 100644 --- a/server/bridge.js +++ b/server/bridge.js @@ -180,6 +180,16 @@ function handleClientMessage(msg) { return; } + // Demo / no-sim: reflect dataref writes locally so cockpit controls (CDI, + // transponder, baro, AP bugs …) still respond, then stop — there's no sim to + // forward to. Must run BEFORE the live-socket guard below. + if (msg.type === 'setDataref' && (process.env.DEMO || !state.xpSocket)) { + const name = WRITABLE_DATAREFS[msg.name]; + if (!name) return log(`! unknown writable dataref alias: ${msg.name}`); + state.values[msg.name] = Number(msg.value); + return broadcast({ type: 'values', data: { [msg.name]: Number(msg.value) } }); + } + // --- everything below talks to X-Plane; needs a live sim socket --- if (!state.xpSocket || state.xpSocket.readyState !== WsClient.OPEN) return; @@ -196,8 +206,9 @@ function handleClientMessage(msg) { ); } else if (msg.type === 'setDataref') { const name = WRITABLE_DATAREFS[msg.name]; - const id = name && state.drefNameToId.get(name); - if (id == null) return log(`! unknown writable dataref alias: ${msg.name}`); + if (!name) return log(`! unknown writable dataref alias: ${msg.name}`); + const id = state.drefNameToId.get(name); + if (id == null) return log(`! writable dataref not resolved yet: ${msg.name}`); state.xpSocket.send( JSON.stringify({ req_id: state.reqId++, diff --git a/server/config.js b/server/config.js index 4b1825e..7917248 100644 --- a/server/config.js +++ b/server/config.js @@ -134,6 +134,7 @@ export const WRITABLE_DATAREFS = { apSpdBug: 'sim/cockpit2/autopilot/airspeed_dial_kts_mach', xpdrMode: 'sim/cockpit2/radios/actuators/transponder_mode', // 0 off,1 stby,2 on,3 alt xpdrCode: 'sim/cockpit2/radios/actuators/transponder_code', // 4-digit squawk + cdiSrc: 'sim/cockpit2/radios/actuators/HSI_source_select_pilot', // 0 NAV1 · 1 NAV2 · 2 GPS (CDI softkey cycles it) }; // Commands the frontend may TRIGGER (autopilot mode buttons etc.). diff --git a/web/src/components/Bezel.jsx b/web/src/components/Bezel.jsx index 5fef2ac..ad89dc4 100644 --- a/web/src/components/Bezel.jsx +++ b/web/src/components/Bezel.jsx @@ -93,6 +93,10 @@ export default function Bezel({ variant = 'pfd', xp, svt3d, onToggleSvt, inset, else if (label === 'NRST') onToggleNrst && onToggleNrst(); else if (label === 'TMR/REF') onToggleTmr && onToggleTmr(); else if (label === 'DME') onToggleDme && onToggleDme(); + else if (label === 'CDI' && xp) { // cycle the HSI/CDI nav source: GPS → NAV1 → NAV2 + const cur = Math.round(num(xp.values?.cdiSrc, 2)); + xp.setDataref('cdiSrc', (cur + 1) % 3); // 2→0→1→2 = GPS→NAV1(VLOC1)→NAV2(VLOC2) + } else if (label === 'OBS') onObs && onObs(); // suspend / OBS mode (also fires the sim softkey above) else if (label === 'CAUTION') onToggleAlerts && onToggleAlerts(); else if (label === 'XPDR') setPage('xpdr');