From 4ac07d9352ebbed41f715e9b554e4d393767ce75 Mon Sep 17 00:00:00 2001 From: itsrubberduck Date: Sun, 15 Feb 2026 16:16:42 +0100 Subject: [PATCH] Connect bridge telemetry to FlightLab with auto-advance triggers Map raw bridge fields (ias_kt, on_ground, etc.) to FlightLabTelemetryState format, add direct telemetry polling endpoint for solo mode, and show sim condition panel in sidebar regardless of auto-advance toggle state. Co-Authored-By: Claude Opus 4.6 --- server/api/bridge/data.post.ts | 59 ++++++++++++++++------------------ 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/server/api/bridge/data.post.ts b/server/api/bridge/data.post.ts index f538e1b..037706d 100644 --- a/server/api/bridge/data.post.ts +++ b/server/api/bridge/data.post.ts @@ -2,41 +2,36 @@ import { createError, defineEventHandler, readBody } from 'h3' import { BridgeToken } from '../../models/BridgeToken' import { getBridgeTokenFromHeader } from '../../utils/bridge' import { flightlabTelemetryStore } from '../../utils/flightlabTelemetry' +import type { FlightLabTelemetryState } from '../../../shared/data/flightlab/types' /** - * Receives MSFS SimConnect telemetry data from an external bridge application. + * Receives telemetry data from an external bridge application. * - * The bridge should POST telemetry data with an x-bridge-token header so we - * can route the data to the correct FlightLab WebSocket session. - * - * ────────────────────────────────────────── - * EXAMPLE REQUEST (from SimBridge app): - * ────────────────────────────────────────── + * The bridge sends raw SimConnect-style fields which are mapped to the + * FlightLabTelemetryState format before storage. * * POST /api/bridge/data * x-bridge-token: - * Content-Type: application/json - * - * { - * "AIRSPEED_INDICATED": 145.2, - * "GROUND_VELOCITY": 142.8, - * "VERTICAL_SPEED": 0, - * "PLANE_ALTITUDE": 364, - * "PLANE_PITCH_DEGREES": 0.5, - * "TURB_ENG_N1_1": 87.3, - * "TURB_ENG_N1_2": 86.9, - * "SIM_ON_GROUND": true, - * "GEAR_HANDLE_POSITION": true, - * "FLAPS_HANDLE_INDEX": 2, - * "BRAKE_PARKING_POSITION": false, - * "AUTOPILOT_MASTER": false - * } - * - * ────────────────────────────────────────── - * RESPONSE: 204 No Content (success) - * 401 Unauthorized (missing/invalid token) - * ────────────────────────────────────────── */ + +/** Map raw bridge field names to FlightLabTelemetryState keys */ +function mapBridgeTelemetry(raw: Record): FlightLabTelemetryState { + return { + AIRSPEED_INDICATED: raw.ias_kt ?? raw.AIRSPEED_INDICATED ?? 0, + GROUND_VELOCITY: raw.groundspeed_kt ?? raw.GROUND_VELOCITY ?? 0, + VERTICAL_SPEED: raw.vertical_speed_fpm ?? raw.VERTICAL_SPEED ?? 0, + PLANE_ALTITUDE: raw.altitude_ft_indicated ?? raw.altitude_ft_true ?? raw.PLANE_ALTITUDE ?? 0, + PLANE_PITCH_DEGREES: raw.pitch_deg ?? raw.PLANE_PITCH_DEGREES ?? 0, + TURB_ENG_N1_1: raw.n1_pct ?? raw.TURB_ENG_N1_1 ?? 0, + TURB_ENG_N1_2: raw.n1_pct_2 ?? raw.TURB_ENG_N1_2 ?? 0, + SIM_ON_GROUND: raw.on_ground ?? raw.SIM_ON_GROUND ?? false, + GEAR_HANDLE_POSITION: raw.gear_handle ?? raw.GEAR_HANDLE_POSITION ?? false, + FLAPS_HANDLE_INDEX: raw.flaps_index ?? raw.FLAPS_HANDLE_INDEX ?? 0, + BRAKE_PARKING_POSITION: raw.parking_brake ?? raw.BRAKE_PARKING_POSITION ?? false, + AUTOPILOT_MASTER: raw.autopilot_master ?? raw.AUTOPILOT_MASTER ?? false, + } +} + export default defineEventHandler(async (event) => { const bridgeToken = getBridgeTokenFromHeader(event) if (!bridgeToken) { @@ -52,12 +47,12 @@ export default defineEventHandler(async (event) => { const body = await readBody(event) const telemetryKeys = body && typeof body === 'object' ? Object.keys(body as Record) : [] console.info( - `\x1b[35m[bridge:data]\x1b[0m token=\x1b[96m${bridgeToken.slice(0, 6)}...\x1b[0m user=\x1b[92m${userId}\x1b[0m telemetryKeys=\x1b[92m${telemetryKeys.length}\x1b[0m payload=`, - body, + `\x1b[35m[bridge:data]\x1b[0m token=\x1b[96m${bridgeToken.slice(0, 6)}...\x1b[0m user=\x1b[92m${userId}\x1b[0m telemetryKeys=\x1b[92m${telemetryKeys.length}\x1b[0m`, ) - // Store telemetry and broadcast to WebSocket subscribers - flightlabTelemetryStore.update(userId, body) + // Map raw bridge fields to FlightLab format and store + const mapped = mapBridgeTelemetry(body) + flightlabTelemetryStore.update(userId, mapped) event.node.res.statusCode = 204 })