Files
xplane-cockpit/server/config.js
T
karim 38b048ad41 G1000: two-way sim sync, more PFD/MFD fidelity, authentic dialogs
Sync (FlyWithLua companions in plugins/ + server/fmssync.js):
- FMS flight-plan two-way sync (App <-> in-sim FMS) via fms-sync.lua
- G1000 UI-state publish (page/range/inset) via ui-sync.lua + CDI source,
  baro, map-range follow
- Terrain awareness: elevation grid probe (terrain-probe.lua) -> red/yellow
  MFD overlay vs aircraft altitude

PFD:
- AFCS mode annunciation bar from autopilot _status datarefs
- CDI source GPS/VLOC colouring, BRG1/BRG2 pointers + DME windows, marker beacons
- magenta speed/altitude trend vectors, selected-altitude alerting
- time-based (frame-rate-independent) smoothing for attitude/heading/tapes

MFD:
- nav data bar (DTK/ETE/active leg), airways overlay from earth_awy.dat,
  compass rose anchored to the ownship

Dialogs (NEAREST/FLIGHTPLAN/DIRECT-TO/PROCEDURES):
- flat, square, embedded G1000 look (no shadow/rounded/transparency)
- compact lower-right placement, no close X (softkey toggles), single window
- NEAREST 2-line entries (ILS/VFR, COM freq, runway length), PROC action menu

Service worker: network-first HTML so reloads pick up new builds (cache v2).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-02 02:17:06 +02:00

187 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Central configuration: which X-Plane datarefs/commands the cockpit needs.
//
// These are *universal* datarefs that work on virtually every aircraft.
// To add a G1000- or aircraft-specific instrument, just add its dataref name
// here under DATAREFS (read) and/or WRITABLE_DATAREFS / COMMANDS (interact).
export const CONFIG = {
// Where X-Plane's built-in web server listens (on the same PC). X-Plane 12.1.1+.
xplaneHost: process.env.XPLANE_HOST || 'localhost',
xplanePort: Number(process.env.XPLANE_PORT || 8086),
xplaneApiBase: '/api/v3',
// Where THIS bridge serves the UI + relays data. 0.0.0.0 => reachable from the LAN.
bridgeHost: process.env.BRIDGE_HOST || '0.0.0.0',
bridgePort: Number(process.env.BRIDGE_PORT || 8080),
// How often X-Plane pushes value updates (it caps near 1020 Hz anyway).
updateHz: Number(process.env.UPDATE_HZ || 20),
};
// Datarefs we SUBSCRIBE to and stream to every client. Keyed by a short alias
// the frontend uses, so the long sim/... names live in exactly one place.
export const DATAREFS = {
// --- primary flight data ---
airspeed: 'sim/cockpit2/gauges/indicators/airspeed_kts_pilot',
altitude: 'sim/cockpit2/gauges/indicators/altitude_ft_pilot',
vspeed: 'sim/cockpit2/gauges/indicators/vvi_fpm_pilot',
pitch: 'sim/cockpit2/gauges/indicators/pitch_AHARS_deg_pilot',
roll: 'sim/cockpit2/gauges/indicators/roll_AHARS_deg_pilot',
heading: 'sim/cockpit2/gauges/indicators/heading_AHARS_deg_mag_pilot',
slip: 'sim/cockpit2/gauges/indicators/slip_deg',
gForce: 'sim/flightmodel/forces/g_nrml',
// --- position / navigation (for the moving map) ---
lat: 'sim/flightmodel/position/latitude',
lon: 'sim/flightmodel/position/longitude',
groundspeed: 'sim/flightmodel/position/groundspeed', // m/s
track: 'sim/cockpit2/gauges/indicators/ground_track_mag_pilot', // deg
gpsDistNm: 'sim/cockpit2/radios/indicators/gps_dme_distance_nm',
gpsBearing: 'sim/cockpit2/radios/indicators/gps_bearing_deg_mag',
// --- engine / misc (handy on an MFD) ---
fuelTotal: 'sim/cockpit2/fuel/fuel_quantity', // array
oat: 'sim/cockpit2/temperature/outside_air_temp_degc',
// --- G1000 PFD: radios (NAV/COM active + standby) ---
nav1: 'sim/cockpit2/radios/actuators/nav1_frequency_hz',
nav1Sb: 'sim/cockpit2/radios/actuators/nav1_standby_frequency_hz',
nav2: 'sim/cockpit2/radios/actuators/nav2_frequency_hz',
nav2Sb: 'sim/cockpit2/radios/actuators/nav2_standby_frequency_hz',
com1: 'sim/cockpit2/radios/actuators/com1_frequency_hz',
com1Sb: 'sim/cockpit2/radios/actuators/com1_standby_frequency_hz',
com2: 'sim/cockpit2/radios/actuators/com2_frequency_hz',
com2Sb: 'sim/cockpit2/radios/actuators/com2_standby_frequency_hz',
// --- G1000 PFD: HSI / CDI ---
obsCrs: 'sim/cockpit2/radios/actuators/nav1_obs_deg_mag_pilot',
gsDef: 'sim/cockpit/radios/nav1_vdef', // glideslope vertical deflection (dots)
hsiDef: 'sim/cockpit2/radios/indicators/hsi_hdef_dots_pilot',
hsiToFrom: 'sim/cockpit2/radios/indicators/hsi_flag_from_to_pilot',
navBearing: 'sim/cockpit2/radios/indicators/hsi_bearing_deg_mag_pilot',
// --- bearing pointers (BRG1/BRG2) + DME + marker beacons ---
nav1Brg: 'sim/cockpit2/radios/indicators/nav1_bearing_deg_mag',
nav2Brg: 'sim/cockpit2/radios/indicators/nav2_bearing_deg_mag',
nav1Dme: 'sim/cockpit2/radios/indicators/nav1_dme_distance_nm',
nav2Dme: 'sim/cockpit2/radios/indicators/nav2_dme_distance_nm',
mkrOuter: 'sim/cockpit2/radios/indicators/outer_marker_lit',
mkrMiddle: 'sim/cockpit2/radios/indicators/middle_marker_lit',
mkrInner: 'sim/cockpit2/radios/indicators/inner_marker_lit',
// --- G1000 UI state (for display sync with the in-sim G1000) ---
// CDI/HSI source: 0 = NAV1/VLOC1, 1 = NAV2/VLOC2, 2 = GPS (standard dataref).
cdiSrc: 'sim/cockpit2/radios/actuators/HSI_source_select_pilot',
// The rest are G1000-internal, so the FlyWithLua companion (ui-sync.lua)
// publishes them as custom datarefs. Absent until the plugin runs -> the web
// G1000 just keeps its own local UI state (graceful).
uiMfdPage: 'glasscockpit/ui/mfd_page', // 0 map, 1 fpl, 2 nrst
uiMapRange: 'glasscockpit/ui/map_range_nm', // active map range, NM
uiInset: 'glasscockpit/ui/inset', // PFD inset map on/off (0/1)
// --- G1000 PFD: data fields ---
baro: 'sim/cockpit2/gauges/actuators/barometer_setting_in_hg_pilot',
tas: 'sim/cockpit2/gauges/indicators/true_airspeed_kts_pilot',
windSpd: 'sim/cockpit2/gauges/indicators/wind_speed_kts',
windDir: 'sim/cockpit2/gauges/indicators/wind_heading_deg_mag',
xpdrCode: 'sim/cockpit2/radios/actuators/transponder_code',
xpdrMode: 'sim/cockpit2/radios/actuators/transponder_mode',
fdPitch: 'sim/cockpit2/autopilot/flight_director_pitch_deg',
fdRoll: 'sim/cockpit2/autopilot/flight_director_roll_deg',
// --- G1000 MFD: engine strip (arrays — UI reads index 0/1) ---
engRpm: 'sim/cockpit2/engine/indicators/engine_speed_rpm',
fuelFlow: 'sim/cockpit2/engine/indicators/fuel_flow_kg_sec',
oilTemp: 'sim/cockpit2/engine/indicators/oil_temperature_deg_C',
oilPress: 'sim/cockpit2/engine/indicators/oil_pressure_psi',
egt: 'sim/cockpit2/engine/indicators/EGT_deg_C',
fuelQty: 'sim/cockpit2/fuel/fuel_quantity',
volts: 'sim/cockpit2/electrical/bus_volts',
amps: 'sim/cockpit2/electrical/battery_amps',
// --- autopilot readouts (live values, so the panel reflects reality) ---
apState: 'sim/cockpit2/autopilot/autopilot_state', // bitfield of active modes
apHdgBug: 'sim/cockpit2/autopilot/heading_dial_deg_mag_pilot',
apAltBug: 'sim/cockpit2/autopilot/altitude_dial_ft_pilot',
apVsBug: 'sim/cockpit2/autopilot/vvi_dial_fpm',
apSpdBug: 'sim/cockpit2/autopilot/airspeed_dial_kts_mach',
apEngaged: 'sim/cockpit2/autopilot/servos_on',
navHdef: 'sim/cockpit2/radios/indicators/hsi_relative_bearing_vor_pilot',
// --- AFCS mode annunciation (the green/white mode strip on a real G1000) ---
// X-Plane's per-mode status datarefs: 0 = off, 1 = armed, 2 = active/captured.
// These mean the AFCS bar mirrors the sim exactly, no Lua needed.
apMode: 'sim/cockpit2/autopilot/autopilot_mode', // 0 off, 1 FD, 2 AP
hdgStatus: 'sim/cockpit2/autopilot/hdg_status',
navStatus: 'sim/cockpit2/autopilot/nav_status',
gpssStatus: 'sim/cockpit2/autopilot/gpss_status',
aprStatus: 'sim/cockpit2/autopilot/approach_status',
bcStatus: 'sim/cockpit2/autopilot/backcourse_status',
altStatus: 'sim/cockpit2/autopilot/alt_hold_status',
vsStatus: 'sim/cockpit2/autopilot/vvi_status',
flcStatus: 'sim/cockpit2/autopilot/speed_status',
gsStatus: 'sim/cockpit2/autopilot/glideslope_status',
vnavStatus: 'sim/cockpit2/autopilot/vnav_status',
};
// Datarefs the frontend may WRITE (e.g. turning the heading bug knob).
export const WRITABLE_DATAREFS = {
apHdgBug: 'sim/cockpit2/autopilot/heading_dial_deg_mag_pilot',
apAltBug: 'sim/cockpit2/autopilot/altitude_dial_ft_pilot',
apVsBug: 'sim/cockpit2/autopilot/vvi_dial_fpm',
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
};
// Commands the frontend may TRIGGER (autopilot mode buttons etc.).
export const COMMANDS = {
apToggle: 'sim/autopilot/servos_toggle',
fdToggle: 'sim/autopilot/fdir_toggle',
hdg: 'sim/autopilot/heading',
nav: 'sim/autopilot/NAV',
apr: 'sim/autopilot/approach',
altHold: 'sim/autopilot/altitude_hold',
vs: 'sim/autopilot/vertical_speed',
flc: 'sim/autopilot/level_change',
vnav: 'sim/autopilot/vnav',
backCourse:'sim/autopilot/back_course',
noseUp: 'sim/autopilot/nose_up',
noseDown: 'sim/autopilot/nose_down',
altUp: 'sim/autopilot/altitude_up',
altDown: 'sim/autopilot/altitude_down',
hdgUp: 'sim/autopilot/heading_up',
hdgDown: 'sim/autopilot/heading_down',
xpdrIdent: 'sim/transponder/transponder_ident',
};
// Per-radio standby tuning (coarse = MHz, fine = kHz) + active/standby flip.
// These work regardless of the dataref's frequency units, so the web tuner just
// fires them — no risky raw frequency writes.
for (const r of ['nav1', 'nav2', 'com1', 'com2']) {
COMMANDS[`${r}CoarseUp`] = `sim/radios/stby_${r}_coarse_up`;
COMMANDS[`${r}CoarseDown`] = `sim/radios/stby_${r}_coarse_down`;
COMMANDS[`${r}FineUp`] = `sim/radios/stby_${r}_fine_up`;
COMMANDS[`${r}FineDown`] = `sim/radios/stby_${r}_fine_down`;
COMMANDS[`${r}Swap`] = `sim/radios/${r}_standby_flip`;
}
// Every clickable G1000 bezel control maps to a real X-Plane command. The PFD
// is unit n1, the MFD is unit n3 (the default C172 layout). Aliases are
// prefixed pfd_/mfd_ so the frontend just says e.g. command('mfd_fpl').
const G1000_KEYS = [
...Array.from({ length: 12 }, (_, i) => `softkey${i + 1}`),
'direct', 'menu', 'fpl', 'proc', 'clr', 'ent', 'cursor',
'fms_outer_up', 'fms_outer_down', 'fms_inner_up', 'fms_inner_down',
'range_up', 'range_down', 'pan_push', 'pan_up', 'pan_down', 'pan_left', 'pan_right',
'hdg_up', 'hdg_down', 'hdg_sync',
'alt_outer_up', 'alt_outer_down', 'alt_inner_up', 'alt_inner_down',
'crs_up', 'crs_down', 'crs_sync', 'baro_up', 'baro_down',
'nav_outer_up', 'nav_outer_down', 'nav_inner_up', 'nav_inner_down', 'nav12', 'nvol_up', 'nvol_dn',
'com_outer_up', 'com_outer_down', 'com_inner_up', 'com_inner_down', 'com12', 'cvol_up', 'cvol_dn',
'ap', 'fd', 'hdg', 'alt', 'nav', 'vnv', 'apr', 'bc', 'vs', 'flc', 'nose_up', 'nose_down',
];
for (const [unit, prefix] of [['n1', 'pfd'], ['n3', 'mfd']]) {
for (const k of G1000_KEYS) COMMANDS[`${prefix}_${k}`] = `sim/GPS/g1000${unit}_${k}`;
}