feat: add printer connector with job queue
This commit is contained in:
parent
400b716623
commit
002f6dc8f3
134
src/printer/connector.ts
Normal file
134
src/printer/connector.ts
Normal file
@ -0,0 +1,134 @@
|
||||
interface PrinterConfig {
|
||||
ip: string;
|
||||
port: number;
|
||||
timeout?: number;
|
||||
}
|
||||
|
||||
interface PrintJob {
|
||||
id: string;
|
||||
data: Uint8Array;
|
||||
status: 'pending' | 'printing' | 'completed' | 'failed';
|
||||
createdAt: Date;
|
||||
startedAt?: Date;
|
||||
completedAt?: Date;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export class PrinterConnector {
|
||||
private config: PrinterConfig;
|
||||
private queueItems: PrintJob[] = [];
|
||||
private currentJob: PrintJob | null = null;
|
||||
private connected = false;
|
||||
private processing = false;
|
||||
|
||||
constructor(config: PrinterConfig) {
|
||||
this.config = {
|
||||
timeout: 5000,
|
||||
...config
|
||||
};
|
||||
}
|
||||
|
||||
isConnected(): boolean {
|
||||
return this.connected;
|
||||
}
|
||||
|
||||
getQueueLength(): number {
|
||||
return this.queueItems.length + (this.currentJob ? 1 : 0);
|
||||
}
|
||||
|
||||
queue(data: Uint8Array): string {
|
||||
const job: PrintJob = {
|
||||
id: `job_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
||||
data,
|
||||
status: 'pending',
|
||||
createdAt: new Date()
|
||||
};
|
||||
|
||||
this.queueItems.push(job);
|
||||
this.processQueue();
|
||||
|
||||
return job.id;
|
||||
}
|
||||
|
||||
getJob(jobId: string): PrintJob | undefined {
|
||||
if (this.currentJob?.id === jobId) return this.currentJob;
|
||||
return this.queueItems.find(j => j.id === jobId);
|
||||
}
|
||||
|
||||
getAllJobs(): PrintJob[] {
|
||||
return this.currentJob
|
||||
? [this.currentJob, ...this.queueItems]
|
||||
: [...this.queueItems];
|
||||
}
|
||||
|
||||
cancelJob(jobId: string): boolean {
|
||||
const index = this.queueItems.findIndex(j => j.id === jobId);
|
||||
if (index >= 0 && this.queueItems[index].status === 'pending') {
|
||||
this.queueItems[index].status = 'cancelled' as any;
|
||||
this.queueItems.splice(index, 1);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
async processQueue(): Promise<void> {
|
||||
if (this.processing || this.queueItems.length === 0) return;
|
||||
|
||||
this.processing = true;
|
||||
|
||||
while (this.queueItems.length > 0) {
|
||||
const job = this.queueItems.shift()!;
|
||||
this.currentJob = job;
|
||||
job.status = 'printing';
|
||||
job.startedAt = new Date();
|
||||
|
||||
try {
|
||||
await this.sendToPrinter(job.data);
|
||||
job.status = 'completed';
|
||||
job.completedAt = new Date();
|
||||
} catch (error) {
|
||||
job.status = 'failed';
|
||||
job.error = String(error);
|
||||
console.error(`Print job ${job.id} failed:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
this.currentJob = null;
|
||||
this.processing = false;
|
||||
}
|
||||
|
||||
private async sendToPrinter(data: Uint8Array): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const socket = new (Bun as any).connect({
|
||||
hostname: this.config.ip,
|
||||
port: this.config.port,
|
||||
});
|
||||
|
||||
socket.then((conn: any) => {
|
||||
this.connected = true;
|
||||
conn.write(data);
|
||||
conn.end();
|
||||
setTimeout(() => {
|
||||
this.connected = false;
|
||||
resolve();
|
||||
}, 1000);
|
||||
}).catch((err: any) => {
|
||||
this.connected = false;
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async getStatus(): Promise<{ online: boolean; paperStatus: string }> {
|
||||
try {
|
||||
const socket = await (Bun as any).connect({
|
||||
hostname: this.config.ip,
|
||||
port: this.config.port,
|
||||
});
|
||||
socket.end();
|
||||
return { online: true, paperStatus: 'ok' };
|
||||
} catch {
|
||||
return { online: false, paperStatus: 'unknown' };
|
||||
}
|
||||
}
|
||||
}
|
||||
25
tests/connector.test.ts
Normal file
25
tests/connector.test.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { describe, it, expect } from 'bun:test';
|
||||
import { PrinterConnector } from '../src/printer/connector';
|
||||
|
||||
describe('Printer Connector', () => {
|
||||
it('should create connector with config', () => {
|
||||
const connector = new PrinterConnector({
|
||||
ip: '192.168.1.100',
|
||||
port: 9100
|
||||
});
|
||||
expect(connector).toBeDefined();
|
||||
expect(connector.isConnected()).toBe(false);
|
||||
});
|
||||
|
||||
it('should queue print jobs', () => {
|
||||
const connector = new PrinterConnector({
|
||||
ip: '192.168.1.100',
|
||||
port: 9100
|
||||
});
|
||||
|
||||
const data = new Uint8Array([0x1B, 0x40]);
|
||||
const jobId = connector.queue(data);
|
||||
expect(jobId).toMatch(/^job_/);
|
||||
expect(connector.getQueueLength()).toBe(1);
|
||||
});
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user