diff --git a/server/bridge.js b/server/bridge.js index 81427a2..013454f 100644 --- a/server/bridge.js +++ b/server/bridge.js @@ -325,6 +325,7 @@ function startDemo() { // engine strip (arrays, like the sim) engRpm: [2410], fuelFlow: [0.0072], oilTemp: [88], oilPress: [52], egt: [720], fuelQty: [60, 58], volts: [process.env.DEMO_ALERT ? 23.4 : 28.0, 27.8], amps: [-1.5], genAmps: [20.5], engHrs: 5040, + fuelTot: 118 * 2.72, fuelMax: 144 * 2.72, // fuel totalizer: 118 of 144 gal (kg) — SYSTEM keys adjust }); // a sample plan so the map/FMS show something in demo mode fp.setPlan({ name: 'DEMO', waypoints: [ diff --git a/server/config.js b/server/config.js index 7917248..a08e566 100644 --- a/server/config.js +++ b/server/config.js @@ -96,6 +96,8 @@ export const DATAREFS = { oilPress: 'sim/cockpit2/engine/indicators/oil_pressure_psi', egt: 'sim/cockpit2/engine/indicators/EGT_deg_C', fuelQty: 'sim/cockpit2/fuel/fuel_quantity', + fuelTot: 'sim/cockpit2/fuel/fuel_totalizer_sum_kg', // pilot-set fuel totalizer (remaining, kg) + fuelMax: 'sim/aircraft/weight/acf_m_fuel_tot', // max fuel capacity (kg) — for RST FUEL volts: 'sim/cockpit2/electrical/bus_volts', // array: [0]=main bus, [1]=essential amps: 'sim/cockpit2/electrical/battery_amps', // battery (S) amps genAmps: 'sim/cockpit2/electrical/generator_amps', // alternator (M) amps @@ -135,6 +137,7 @@ export const WRITABLE_DATAREFS = { 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) + fuelTot: 'sim/cockpit2/fuel/fuel_totalizer_sum_kg', // SYSTEM → DEC/INC/RST FUEL adjusts the totalizer }; // Commands the frontend may TRIGGER (autopilot mode buttons etc.). diff --git a/server/navdata.js b/server/navdata.js index 9f8ddaa..0c40d27 100644 --- a/server/navdata.js +++ b/server/navdata.js @@ -167,9 +167,13 @@ async function parseAirways(file) { const b = index.get((p[3] || '').toUpperCase()); if (!a || !b) continue; // endpoint not in our database const name = p[p.length - 1]; + // Field 8 (index 7) = airway layer: 1 = low/Victor, 2 = high/Jet (used by the + // MFD AIRWAYS key to show all / Victor-only / Jet-only). Fall back to the name + // prefix (V… = low, J… = high) if the field is missing. + const lyr = +p[7] === 1 ? 1 : +p[7] === 2 ? 2 : /^J/i.test(name) ? 2 : /^V/i.test(name) ? 1 : 0; const k = `${Math.floor((a.lat + b.lat) / 2)},${Math.floor((a.lon + b.lon) / 2)}`; let arr = awyCells.get(k); if (!arr) { arr = []; awyCells.set(k, arr); } - arr.push({ la1: a.lat, lo1: a.lon, la2: b.lat, lo2: b.lon, name }); + arr.push({ la1: a.lat, lo1: a.lon, la2: b.lat, lo2: b.lon, name, lyr }); state.awy++; } } diff --git a/web/src/components/Bezel.jsx b/web/src/components/Bezel.jsx index ad89dc4..6188a7a 100644 --- a/web/src/components/Bezel.jsx +++ b/web/src/components/Bezel.jsx @@ -28,10 +28,11 @@ const PFD_MENU = { // page; TOPO/TERRAIN/OSM switch the base map; BACK returns. (OSM is our tuned // extra layer in an otherwise-empty slot.) const MFD_MENU = { - root: ['ENGINE', 'MAP', '', '', '', '', '', '', '', 'DCLTR', '', ''], + root: ['SYSTEM', 'MAP', '', '', '', '', '', '', '', 'DCLTR', '', ''], mapopt: ['TRAFFIC', 'PROFILE', 'TOPO', 'TERRAIN', 'AIRWAYS', 'AIRSPACE', 'NEXRAD', 'OSM', '', '', 'BACK', ''], - engine: ['DEC FUEL', 'INC FUEL', 'RST FUEL', '', '', '', '', '', '', '', 'BACK', ''], + system: ['DEC FUEL', 'INC FUEL', 'RST FUEL', '', '', '', '', '', '', '', 'BACK', ''], }; +const KG_PER_GAL = 2.72; // fuel totalizer steps in US gallons (matches the EIS readout) // autopilot_state bitfield (best-effort; tweak per aircraft) const AP_BITS = { fd: 1 << 0, hdg: 1 << 1, vs: 1 << 4, flc: 1 << 6, nav: 1 << 8, apr: 1 << 9, vnav: 1 << 11, altHold: 1 << 14, bc: 1 << 18 }; @@ -67,13 +68,16 @@ export default function Bezel({ variant = 'pfd', xp, svt3d, onToggleSvt, inset, const cycleDcltr = (setter) => setter && setter((m) => ({ ...m, dcltr: (((m.dcltr || 0) + 1) % 4) })); if (variant === 'mfd') { if (label === 'MAP') setPage('mapopt'); - else if (label === 'ENGINE') setPage('engine'); + else if (label === 'SYSTEM') setPage('system'); else if (label === 'BACK') setPage('root'); + else if (label === 'DEC FUEL' && xp) xp.setDataref('fuelTot', Math.max(0, num(xp.values?.fuelTot) - KG_PER_GAL)); + else if (label === 'INC FUEL' && xp) xp.setDataref('fuelTot', num(xp.values?.fuelTot) + KG_PER_GAL); + else if (label === 'RST FUEL' && xp) xp.setDataref('fuelTot', num(xp.values?.fuelMax) || num(xp.values?.fuelTot)); else if (label === 'TOPO') setBase('topo'); // relief on/off else if (label === 'TERRAIN') onMapMode && onMapMode((m) => ({ ...m, terrain: !m.terrain })); // awareness overlay (independent) else if (label === 'OSM') setBase('osm'); else if (label === 'DCLTR') cycleDcltr(onMapMode); - else if (label === 'AIRWAYS') onMapMode && onMapMode((m) => ({ ...m, airways: !m.airways })); + else if (label === 'AIRWAYS') onMapMode && onMapMode((m) => ({ ...m, airways: (((m.airways | 0) + 1) % 4) })); // off→all→Victor→Jet else if (label === 'AIRSPACE') onMapMode && onMapMode((m) => ({ ...m, airspace: !m.airspace })); } else { if (label === 'PFD') setPage('pfd'); @@ -149,7 +153,9 @@ export default function Bezel({ variant = 'pfd', xp, svt3d, onToggleSvt, inset,