/** Pure K1 telemetry and phase vocabulary, shared by direct and onboard views. */ export type AcquisitionState = | "preparing" | "prepared" | "awaiting_external_start" | "starting" | "acquiring" | "awaiting_external_stop" | "stopping" | "finalizing" | "completed" | "failed" | "aborted" | "interrupted"; export interface XgridsK1Metrics { pcl_frames?: number | null; pose_frames?: number | null; mqtt_to_decode_ms?: number | null; decode_ms?: number | null; publish_ms?: number | null; pipeline_ms?: number | null; end_to_end_ms?: number | null; frame_rate?: number | null; frame_rate_hz?: number | null; point_count?: number | null; dropped_preview_frames?: number | null; ai_end_to_end_ms?: number | null; ai_end_to_end_p95_ms?: number | null; ai_frame_rate_hz?: number | null; ai_dropped_frames?: number | null; ai_stale_ms?: number | null; device_elapsed_seconds?: number | null; device_route_distance_meters?: number | null; device_speed_meters_per_second?: number | null; device_speed_mps?: number | null; elapsed_seconds?: number | null; route_distance_meters?: number | null; speed_meters_per_second?: number | null; [key: string]: number | null | undefined; } export function finiteMetric(value: number | null | undefined): number | null { return typeof value === "number" && Number.isFinite(value) ? value : null; } function nonNegativeMetric(value: number | null | undefined): number | null { const finite = finiteMetric(value); return finite !== null && finite >= 0 ? finite : null; } export interface K1DeviceTelemetry { elapsedSeconds: number | null; routeDistanceMeters: number | null; speedMetersPerSecond: number | null; } export function deviceTelemetry( metrics: XgridsK1Metrics | null | undefined, ): K1DeviceTelemetry { return { elapsedSeconds: nonNegativeMetric( metrics?.device_elapsed_seconds ?? metrics?.elapsed_seconds, ), routeDistanceMeters: nonNegativeMetric( metrics?.device_route_distance_meters ?? metrics?.route_distance_meters, ), speedMetersPerSecond: nonNegativeMetric( metrics?.device_speed_meters_per_second ?? metrics?.device_speed_mps ?? metrics?.speed_meters_per_second, ), }; } export function formatNumber(value: number | null, digits = 1): string { if (value === null) return "—"; return value.toLocaleString("ru-RU", { maximumFractionDigits: digits, minimumFractionDigits: digits, }); }