Files
FEDEO/frontend/stores/labelPrinter.ts
2026-01-06 12:09:31 +01:00

191 lines
6.3 KiB
TypeScript

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()
}
}
}
})