mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-03 15:36:24 +08:00
Implements the open items from docs/plans/2026-07-14-frequency-sim-control-design.md §4/§"Offen für die Implementierungsphase": a per-bridge-token in-memory command queue piggybacked on the existing telemetry channel, plus the client-side gate and TTS confirmations. - server/utils/simControlQueue.ts: TTL-based queue keyed by bridge token (enqueue → drainPending → resolve → drainResultsForClient). - server/api/bridge/data.post.ts: response gains a `commands` field the bridge drains on its next telemetry POST. - server/api/bridge/command.post.ts (new): client enqueues a parsed command, re-validated server-side via isValidSimControlCommand. - server/api/bridge/command-result.post.ts (new): bridge reports ok/failed. - server/api/bridge/live.get.ts: response gains `commandResults` so the client can announce outcomes. - shared/utils/simControl.ts: wire types, isValidSimControlCommand, and simControlRejectionSpeech/simControlResultSpeech TTS phrasing. - useLiveAtcSession.ts: parseSimControl() gated on bridgeConnected, wired in right after the local special cases and before the frequency check — matched commands never reach radioBackend.transmit(). - useSimBridgeSync.ts / live-atc.vue: bridgeToken threaded through, command results forwarded from the telemetry poll to TTS. 43 new tests (shared parser/validation/speech + server queue lifecycle/TTL). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
39 lines
1.3 KiB
TypeScript
39 lines
1.3 KiB
TypeScript
import { createError } from 'h3'
|
|
import { BridgeToken } from '../../models/BridgeToken'
|
|
import { getBridgeTokenFromHeader } from '../../utils/bridge'
|
|
import { flightlabTelemetryStore } from '../../utils/flightlabTelemetry'
|
|
import { simControlQueue } from '../../utils/simControlQueue'
|
|
|
|
export default defineEventHandler(async (event) => {
|
|
const token = getBridgeTokenFromHeader(event)
|
|
if (!token) {
|
|
throw createError({ statusCode: 401, statusMessage: 'x-bridge-token header fehlt oder ist ungültig.' })
|
|
}
|
|
|
|
const bridgeDocument = await BridgeToken.findOne({ token }).select('user')
|
|
const userId = bridgeDocument?.user?.toString() ?? null
|
|
|
|
if (!userId) {
|
|
return {
|
|
connected: false,
|
|
lastTelemetryAt: null,
|
|
telemetry: null,
|
|
commandResults: [],
|
|
}
|
|
}
|
|
|
|
const telemetry = flightlabTelemetryStore.get(userId)
|
|
const timestamp = telemetry && typeof telemetry.timestamp === 'number'
|
|
? new Date(telemetry.timestamp).toISOString()
|
|
: null
|
|
|
|
return {
|
|
connected: true,
|
|
lastTelemetryAt: timestamp,
|
|
telemetry,
|
|
// frequency-sim-control (design §4): terminal command results the client
|
|
// hasn't seen yet, so it can speak a confirmation/failure over TTS.
|
|
commandResults: simControlQueue.drainResultsForClient(token),
|
|
}
|
|
})
|