diff --git a/src/api/client.ts b/src/api/client.ts index cb8551c..6be2756 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -28,6 +28,7 @@ import type { TrackSummary, BuildTrackModelRequest, CarProfile, + GameInfo, } from '@/types' const api = axios.create({ @@ -45,6 +46,11 @@ export async function getLiveTelemetry(): Promise { return res.data } +export async function getGameInfo(): Promise { + const res = await api.get('/game-info') + return res.data +} + // ── Recordings ── export async function listRecordings(): Promise { diff --git a/src/stores/telemetry.ts b/src/stores/telemetry.ts index 3897ad1..b7f1b05 100644 --- a/src/stores/telemetry.ts +++ b/src/stores/telemetry.ts @@ -15,17 +15,19 @@ // along with this program. If not, see . import { defineStore } from 'pinia' import { ref, computed } from 'vue' -import type { LiveTelemetryResponse, LiveFeedSnapshot } from '@/types' -import { getLiveTelemetry } from '@/api/client' +import type { LiveTelemetryResponse, LiveFeedSnapshot, GameInfo } from '@/types' +import { getLiveTelemetry, getGameInfo } from '@/api/client' export const useTelemetryStore = defineStore('telemetry', () => { const feeds = ref([]) const activeRecording = ref(null) + const gameInfo = ref({}) const connected = ref(false) const error = ref(null) const lastUpdate = ref(null) let pollTimer: ReturnType | null = null + let gameInfoCounter = 0 const anyFeedAlive = computed(() => feeds.value.some((f) => f.health === 'alive')) const anyFeedStale = computed(() => feeds.value.some((f) => f.health === 'stale')) @@ -65,6 +67,12 @@ export const useTelemetryStore = defineStore('telemetry', () => { connected.value = true error.value = null lastUpdate.value = new Date() + gameInfoCounter++ + if (gameInfoCounter % 8 === 0) { + try { + gameInfo.value = await getGameInfo() + } catch { /* non-critical */ } + } } catch (e: unknown) { connected.value = false error.value = e instanceof Error ? e.message : 'Connection failed' @@ -87,6 +95,7 @@ export const useTelemetryStore = defineStore('telemetry', () => { return { feeds, activeRecording, + gameInfo, connected, error, lastUpdate, diff --git a/src/types/index.ts b/src/types/index.ts index c8a4b13..e113895 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -118,6 +118,8 @@ export interface UseCaseSession { analysis: AnalysisResult | null guidance: string | null recording_id: string | null + car_name?: string | null + track_name?: string | null } export interface CreateSessionRequest { @@ -139,6 +141,14 @@ export interface UseCaseInfo { guidance: string } +// ── Game Info (from KSUDP handshake) ── + +export interface GameInfo { + car_name?: string | null + track_name?: string | null + driver_name?: string | null +} + // ── Analysis Results ── // Shift Point Analysis (use_case = "shift_points") diff --git a/src/views/DashboardView.vue b/src/views/DashboardView.vue index baed79f..a4e61de 100644 --- a/src/views/DashboardView.vue +++ b/src/views/DashboardView.vue @@ -114,6 +114,10 @@ const aliveCount = computed(() => telemetry.feeds.filter((f) => f.health === 'al {{ aliveCount }} feed(s) receiving data · {{ telemetry.totalPackets.toLocaleString() }} packets total +