feat(live-atc): forward aircraft position, un-throttle bridge polling

- NormalizedTelemetry carries lat/lon (0/0 no-GPS guard, position in the
  change-detection signature) so the backend can derive distance triggers
- bridge polling moves from setInterval to a Worker tick: with the sim in the
  foreground the /live-atc tab is backgrounded and Chrome throttles plain
  intervals to ~1/min — telemetry-driven ATC lagged behind the silence fallback

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
itsrubberduck
2026-07-18 20:48:09 +02:00
parent cadc0aefb6
commit db1155c8c9
4 changed files with 52 additions and 9 deletions

View File

@@ -41,8 +41,10 @@ export interface NormalizedTelemetry {
vs_fpm?: number // vertical speed, feet/min (+climb, -descent)
heading_deg?: number // magnetic heading, 0..360
on_ground?: boolean // wheels on the ground
distance_to_dest_nm?: number // great-circle nm to destination airport
distance_to_dep_nm?: number // great-circle nm from departure airport
// Raw position in degrees. The backend derives distance_to_dep_nm /
// distance_to_dest_nm from these via the session's airport ICAO codes.
lat?: number
lon?: number
}
export interface ReadbackFieldDetail {

View File

@@ -1,6 +1,7 @@
import { computed, onMounted, onUnmounted, ref, watch, type Ref } from 'vue'
import { useRoute } from 'vue-router'
import { normalizeSimFreq, normalizeBridgeTelemetry, telemetrySignature } from '../../shared/utils/bridgeTelemetry'
import { createIntervalWorker } from '../../shared/utils/intervalWorker'
import { pmLog } from '../../shared/utils/pmLog'
import type { SimControlCommandResult } from '../../shared/utils/simControl'
import type { useFrequencyPresets } from '~/composables/useFrequencyPresets'
@@ -60,7 +61,11 @@ export function useSimBridgeSync(
// Telemetry older than this means the bridge stopped posting.
const BRIDGE_TELEMETRY_STALE_MS = 12_000
const BRIDGE_POLL_INTERVAL_MS = 3_000
let bridgePoller: ReturnType<typeof setInterval> | null = null
// Worker-based ticker: the intended setup is the sim (or WebSim tab) in the
// foreground and /live-atc in the background, where a plain setInterval gets
// throttled to ~1/min — telemetry-driven ATC (airborne handoff, level checks)
// would lag by up to a minute. A Worker tick isn't throttled.
let bridgePoller: { stop: () => void } | null = null
// Last sim active frequency we pushed into the radio — only re-tune active when
// the sim value actually changes, so manual/flow tuning isn't constantly
// overridden. Standby has no such anchor: while connected it strictly mirrors
@@ -184,12 +189,12 @@ export function useSimBridgeSync(
stopBridgeSync()
if (!bridgeToken.value) return
void pollBridgeTelemetry()
bridgePoller = setInterval(pollBridgeTelemetry, BRIDGE_POLL_INTERVAL_MS)
bridgePoller = createIntervalWorker(BRIDGE_POLL_INTERVAL_MS, () => void pollBridgeTelemetry())
}
function stopBridgeSync() {
if (bridgePoller) {
clearInterval(bridgePoller)
bridgePoller.stop()
bridgePoller = null
}
}