import { Printer } from "@node-escpos/core"; import USB from "@node-escpos/usb-adapter"; import { Task, Step, Printer as PrinterInterface } from '@shared/index'; import { steps } from '../db'; import { Knex } from 'knex'; import logger from '../logger'; export class SerialPrinter implements PrinterInterface { private device: USB | null = null; private printer: Printer<[]> | null = null; constructor() { this.initializePrinter(); } private async initializePrinter() { try { this.device = new USB(); await new Promise((resolve, reject) => { this.device?.open((err) => { if (err) { logger.error('Failed to open printer:', err); reject(err); return; } resolve(); }); }); const options = { encoding: "CP437" }; this.printer = new Printer(this.device, options); logger.info('Printer initialized successfully'); } catch (error) { logger.error('Failed to initialize printer:', error); } } async getTaskSteps(db: Knex, task: Task): Promise { return await steps(db).where('task_id', task.id).orderBy('order').select('*'); } async printTask(task: Task, db: Knex): Promise { if (!this.printer || !this.device) { throw new Error('Printer not initialized'); } const taskSteps = await this.getTaskSteps(db, task); try { // Print header with task ID as barcode await this.printer .font('a') .align('ct') .style('b') .size(1, 1) // Normal size (0.08 x 2.13 mm) .text(`Task: ${task.name}`) .text('='.repeat(32)) .text('') .align('lt'); // Print task ID as barcode await this.printer .barcode(task.id.toString(), 'CODE128', { width: 2, height: 50 }) .text('') .text(''); // Print steps for (let i = 0; i < taskSteps.length; i++) { const step = taskSteps[i]; await this.printer .size(1, 1) // Normal size for step header .text(`Step ${i + 1}: ${step.name}`) .text('-'.repeat(32)) .size(0, 0) // Smaller size for instructions (0.08 x 2.13 mm) .text(step.instructions) .text(''); // Print step ID as barcode await this.printer .barcode(step.id.toString(), 'CODE128', { width: 2, height: 50 }) .text(''); } await this.printer .text('') .text('') .cut() .close(); logger.info(`Printed task ${task.id}`); } catch (error) { logger.error('Failed to print task:', error); throw error; } } async printStep(step: Step, db: Knex): Promise { if (!this.printer || !this.device) { throw new Error('Printer not initialized'); } try { await this.printer .font('a') .align('ct') .style('b') .size(1, 1) // Normal size (0.08 x 2.13 mm) .text(`Step: ${step.name}`) .text('='.repeat(32)) .text('') .align('lt') .size(0, 0) // Smaller size for instructions .text(step.instructions) .text('') .text(''); // Print step ID as barcode await this.printer .barcode(step.id.toString(), 'CODE128', { width: 2, height: 50 }) .text('') .text('') .cut() .close(); logger.info(`Printed step ${step.id}`); } catch (error) { logger.error('Failed to print step:', error); throw error; } } }