import { defineStore } from "pinia" import { Utils, RequestCommandId, ResponseCommandId, NiimbotBluetoothClient, NiimbotSerialClient } from "@mmote/niimbluelib" import { useToast } from "#imports" export const useLabelPrinterStore = defineStore("labelPrinter", { state: () => ({ client: null as NiimbotBluetoothClient | NiimbotSerialClient | null, connected: false, connectLoading: false, transportLastUsed: "", printProgress: 0, info: {} as any }), actions: { /** Logging Helper */ logger(...args: any[]) { console.debug("[Printer]", ...args) }, /** --- Client erzeugen --- */ newClient(transport: "ble" | "serial" = "serial") { const toast = useToast() // alten Client trennen if (this.client) { try { this.client.disconnect() } catch {} } // neuen Client erzeugen this.client = transport === "ble" ? new NiimbotBluetoothClient() : new NiimbotSerialClient() /** Events registrieren */ this.client.on("printerinfofetched", (e) => { console.log("printerInfoFetched") console.log(e.info) this.info = e.info }) this.client.on("connect", () => { this.connected = true toast.add({ title: "Drucker verbunden" }) this.logger("connected") }) this.client.on("disconnect", () => { this.connected = false toast.add({ title: "Drucker getrennt" }) this.logger("disconnected") }) this.client.on("printprogress", (e) => { if (e.pagePrintProgress) this.printProgress = e.pagePrintProgress this.logger( `Page ${e.page}/${e.pagesTotal}, Page print ${e.pagePrintProgress}%, Page feed ${e.pageFeedProgress}%` ) }) return this.client }, /** --- Verbinden --- */ async connect(transport: "ble" | "serial" = "serial") { const toast = useToast() this.connectLoading = true this.newClient(transport) try { await this.client!.connect() this.transportLastUsed = transport this.connectLoading = false } catch (err) { console.error("[Printer] Connect failed:", err) toast.add({ title: "Verbindung fehlgeschlagen", color: "red" }) this.connectLoading = false } }, /** --- Trennen --- */ async disconnect({ forget = false } = {}) { const toast = useToast() this.logger("Disconnect requested…") if (!this.client) return try { // Timer stoppen try { if (this.client.heartbeatTimer) { clearInterval(this.client.heartbeatTimer) this.client.heartbeatTimer = null } if (this.client.abstraction?.statusPollTimer) { clearInterval(this.client.abstraction.statusPollTimer) this.client.abstraction.statusPollTimer = null } } catch {} await this.client.disconnect?.() // Serial-Port schließen const port = (this.client as any).port if (port) { try { if (port.readable) port.readable.cancel?.() if (port.writable) await port.writable.abort?.() await port.close?.() if (forget && navigator.serial?.forgetPort) { await navigator.serial.forgetPort(port) } } catch (err) { this.logger("Error closing port:", err) } } // BLE GATT if ( this.client instanceof NiimbotBluetoothClient && this.client.device?.gatt?.connected ) { try { this.client.device.gatt.disconnect() } catch {} } this.connected = false this.client = null toast.add({ title: "Drucker getrennt" }) } catch (err) { console.error("[Printer] Disconnect error", err) toast.add({ title: "Fehler beim Trennen", color: "red" }) } }, /** Hilfsfunktion: EncodedImage reparieren */ reviveEncodedImage(encoded: any) { if (!encoded?.rowsData) return encoded for (const row of encoded.rowsData) { if (row.rowData && !(row.rowData instanceof Uint8Array)) { row.rowData = new Uint8Array(Object.values(row.rowData)) } } return encoded }, /** --- Drucken --- */ async print(encoded: any, options?: { density?: number; pages?: number }) { const toast = useToast() if (!this.client) throw new Error("Kein Drucker verbunden") const fixed = this.reviveEncodedImage(encoded) const taskName = this.client.getPrintTaskType() ?? "B1" const task = this.client.abstraction.newPrintTask(taskName, { totalPages: options?.pages ?? 1, statusPollIntervalMs: 100, statusTimeoutMs: 8000, density: options?.density ?? 5 }) try { this.printProgress = 0 await task.printInit() await task.printPage(fixed, options?.pages ?? 1) await task.waitForFinished() toast.add({ title: "Druck abgeschlossen" }) } catch (e) { console.error("[Printer] print error", e) toast.add({ title: "Druckfehler", color: "red" }) } finally { await task.printEnd() } } } })