import { defineStore } from "pinia"; export interface PrinterTelemetry { printerId: string; farmId: string; state: "idle" | "printing" | "paused" | "error" | "offline"; nozzleTempC: number; bedTempC: number; progressPct: number; updatedAt: string; } interface TelemetryState { socket: WebSocket | null; connected: boolean; printers: Record; } const RECONNECT_DELAY_MS = 3_000; export const useTelemetryStore = defineStore("telemetry", { state: (): TelemetryState => ({ socket: null, connected: false, printers: {}, }), getters: { printerList: (state) => Object.values(state.printers), }, actions: { connect() { if (this.socket) return; const config = useRuntimeConfig(); const client = useSupabaseClient(); client.auth.getSession().then(({ data }) => { const token = data.session?.access_token ?? ""; const url = `${config.public.wsBase}/ws/telemetry?token=${encodeURIComponent(token)}`; this.open(url); }); }, open(url: string) { const socket = new WebSocket(url); socket.onopen = () => { this.connected = true; }; socket.onmessage = (event) => { try { const payload = JSON.parse(event.data) as { type: string; data: PrinterTelemetry }; if (payload.type === "printer.telemetry") { this.printers[payload.data.printerId] = payload.data; } } catch { // Ignore malformed frames rather than crashing the UI. } }; socket.onclose = () => { this.connected = false; this.socket = null; setTimeout(() => this.connect(), RECONNECT_DELAY_MS); }; socket.onerror = () => { socket.close(); }; this.socket = socket; }, disconnect() { this.socket?.close(); this.socket = null; this.connected = false; }, }, });