taro-bluetooth-print 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +73 -195
- package/README.md +134 -386
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/types/config/PrinterConfigManager.d.ts +206 -0
- package/dist/types/config/index.d.ts +8 -0
- package/dist/types/core/BluetoothPrinter.d.ts +1 -1
- package/dist/types/core/EventEmitter.d.ts +6 -26
- package/dist/types/core/index.d.ts +6 -0
- package/dist/types/device/MultiPrinterManager.d.ts +164 -0
- package/dist/types/device/index.d.ts +2 -0
- package/dist/types/drivers/CpclDriver.d.ts +304 -0
- package/dist/types/drivers/GPrinterDriver.d.ts +63 -0
- package/dist/types/drivers/ZplDriver.d.ts +325 -0
- package/dist/types/drivers/index.d.ts +9 -0
- package/dist/types/encoding/gbk-lite.d.ts +8 -0
- package/dist/types/encoding/gbk-table.d.ts +8 -30
- package/dist/types/index.d.ts +12 -8
- package/dist/types/services/BatchPrintManager.d.ts +205 -0
- package/dist/types/services/ConnectionManager.d.ts +1 -1
- package/dist/types/services/PrintHistory.d.ts +142 -0
- package/dist/types/services/PrintJobManager.d.ts +28 -4
- package/dist/types/services/PrinterStatus.d.ts +97 -0
- package/dist/types/services/index.d.ts +11 -0
- package/package.json +25 -7
- package/src/adapters/AlipayAdapter.ts +1 -0
- package/src/adapters/BaiduAdapter.ts +1 -0
- package/src/adapters/BaseAdapter.ts +6 -8
- package/src/adapters/ByteDanceAdapter.ts +1 -0
- package/src/adapters/TaroAdapter.ts +1 -0
- package/src/adapters/WebBluetoothAdapter.ts +1 -1
- package/src/config/PrinterConfigManager.ts +519 -0
- package/src/config/index.ts +15 -0
- package/src/core/BluetoothPrinter.ts +15 -15
- package/src/core/EventEmitter.ts +15 -15
- package/src/core/index.ts +7 -0
- package/src/device/MultiPrinterManager.ts +470 -0
- package/src/device/index.ts +8 -0
- package/src/drivers/CpclDriver.ts +549 -0
- package/src/drivers/GPrinterDriver.ts +115 -0
- package/src/drivers/TsplDriver.ts +9 -21
- package/src/drivers/ZplDriver.ts +543 -0
- package/src/drivers/index.ts +37 -0
- package/src/encoding/gbk-lite.ts +113 -0
- package/src/encoding/gbk-table.ts +80 -58
- package/src/index.ts +40 -35
- package/src/plugins/PluginManager.ts +3 -1
- package/src/plugins/builtin/LoggingPlugin.ts +4 -2
- package/src/plugins/builtin/RetryPlugin.ts +8 -14
- package/src/services/BatchPrintManager.ts +500 -0
- package/src/services/ConnectionManager.ts +25 -22
- package/src/services/PrintHistory.ts +336 -0
- package/src/services/PrintJobManager.ts +69 -9
- package/src/services/PrinterStatus.ts +267 -0
- package/src/services/index.ts +22 -0
- package/src/template/TemplateEngine.ts +4 -1
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Printer Status Service
|
|
3
|
+
*
|
|
4
|
+
* Queries printer status including paper, battery, and error states.
|
|
5
|
+
* Works with ESC/POS printers that support status commands.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* const status = new PrinterStatus(printer);
|
|
10
|
+
* const paperStatus = await status.getPaperStatus();
|
|
11
|
+
* console.log('Paper:', paperStatus);
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { Logger } from '@/utils/logger';
|
|
16
|
+
import { BluetoothPrintError, ErrorCode } from '@/errors/BluetoothError';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Paper status
|
|
20
|
+
*/
|
|
21
|
+
export enum PaperStatus {
|
|
22
|
+
/** Paper is present and OK */
|
|
23
|
+
OK = 'ok',
|
|
24
|
+
/** Paper is low */
|
|
25
|
+
LOW = 'low',
|
|
26
|
+
/** Paper is out */
|
|
27
|
+
OUT = 'out',
|
|
28
|
+
/** Paper status unknown */
|
|
29
|
+
UNKNOWN = 'unknown',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Printer status
|
|
34
|
+
*/
|
|
35
|
+
export interface PrinterStatusInfo {
|
|
36
|
+
/** Paper status */
|
|
37
|
+
paper: PaperStatus;
|
|
38
|
+
/** Cover open (if supported) */
|
|
39
|
+
coverOpen?: boolean;
|
|
40
|
+
/** Cutter error (if supported) */
|
|
41
|
+
cutterError?: boolean;
|
|
42
|
+
/** Motor error (if supported) */
|
|
43
|
+
motorError?: boolean;
|
|
44
|
+
/** Temperature issue (if supported) */
|
|
45
|
+
overTemp?: boolean;
|
|
46
|
+
/** Battery level (0-100, if supported) */
|
|
47
|
+
batteryLevel?: number;
|
|
48
|
+
/** Timestamp of status check */
|
|
49
|
+
timestamp: number;
|
|
50
|
+
/** Raw status bytes */
|
|
51
|
+
rawStatus?: Uint8Array;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Status query options
|
|
56
|
+
*/
|
|
57
|
+
export interface StatusQueryOptions {
|
|
58
|
+
/** Timeout for status query in ms */
|
|
59
|
+
timeout?: number;
|
|
60
|
+
/** Include raw status bytes */
|
|
61
|
+
includeRaw?: boolean;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* ESC/POS Status Commands
|
|
66
|
+
*/
|
|
67
|
+
const ESCPOS_STATUS_CMD = 0x10; // DLE
|
|
68
|
+
const ESCPOS_STATUS_NUL = 0x04; // ENQ
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Status response bit masks for common printers
|
|
72
|
+
*/
|
|
73
|
+
const STATUS_BIT_PAPER_OUT = 0x20; // Bit 5: Paper out
|
|
74
|
+
const STATUS_BIT_PAPER_LOW = 0x40; // Bit 6: Paper low
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Printer Status Service
|
|
78
|
+
*/
|
|
79
|
+
export class PrinterStatus {
|
|
80
|
+
private readonly logger = Logger.scope('PrinterStatus');
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Creates a new PrinterStatus instance
|
|
84
|
+
*/
|
|
85
|
+
constructor() {}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Get printer status
|
|
89
|
+
*
|
|
90
|
+
* Sends ESC/POS status query command and parses the response.
|
|
91
|
+
*
|
|
92
|
+
* @param writeFunc - Function to write data to printer
|
|
93
|
+
* @param readFunc - Function to read response from printer
|
|
94
|
+
* @param options - Query options
|
|
95
|
+
* @returns Printer status info
|
|
96
|
+
*/
|
|
97
|
+
async getStatus(
|
|
98
|
+
writeFunc: (data: ArrayBuffer) => Promise<void>,
|
|
99
|
+
readFunc: () => Promise<ArrayBuffer>,
|
|
100
|
+
options: StatusQueryOptions = {}
|
|
101
|
+
): Promise<PrinterStatusInfo> {
|
|
102
|
+
const { timeout = 3000, includeRaw = false } = options;
|
|
103
|
+
|
|
104
|
+
try {
|
|
105
|
+
// Send status query: DLE ENQ
|
|
106
|
+
const queryCmd = new Uint8Array([ESCPOS_STATUS_CMD, ESCPOS_STATUS_NUL]);
|
|
107
|
+
await writeFunc(queryCmd.buffer);
|
|
108
|
+
|
|
109
|
+
// Set up timeout promise
|
|
110
|
+
const timeoutPromise = new Promise<ArrayBuffer>((_, reject) => {
|
|
111
|
+
setTimeout(() => {
|
|
112
|
+
reject(new BluetoothPrintError(
|
|
113
|
+
ErrorCode.CONNECTION_TIMEOUT,
|
|
114
|
+
'Status query timed out'
|
|
115
|
+
));
|
|
116
|
+
}, timeout);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Read response with timeout
|
|
120
|
+
const response = await Promise.race([
|
|
121
|
+
readFunc(),
|
|
122
|
+
timeoutPromise
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
return this.parseStatus(new Uint8Array(response), includeRaw);
|
|
126
|
+
} catch (error) {
|
|
127
|
+
this.logger.error('Failed to get printer status:', error);
|
|
128
|
+
|
|
129
|
+
// Return unknown status on error
|
|
130
|
+
return {
|
|
131
|
+
paper: PaperStatus.UNKNOWN,
|
|
132
|
+
timestamp: Date.now(),
|
|
133
|
+
...(includeRaw && { rawStatus: new Uint8Array(0) }),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Parse status bytes from printer
|
|
140
|
+
*
|
|
141
|
+
* Different printers return different status formats.
|
|
142
|
+
* This implementation handles common ESC/POS status responses.
|
|
143
|
+
*/
|
|
144
|
+
private parseStatus(statusBytes: Uint8Array, includeRaw: boolean): PrinterStatusInfo {
|
|
145
|
+
const result: PrinterStatusInfo = {
|
|
146
|
+
paper: PaperStatus.UNKNOWN,
|
|
147
|
+
timestamp: Date.now(),
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
if (includeRaw && statusBytes.length > 0) {
|
|
151
|
+
result.rawStatus = statusBytes;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (statusBytes.length === 0) {
|
|
155
|
+
this.logger.warn('Empty status response');
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// First byte typically contains printer status
|
|
160
|
+
const status = statusBytes[0] ?? 0;
|
|
161
|
+
|
|
162
|
+
// Check paper status
|
|
163
|
+
if ((status & STATUS_BIT_PAPER_OUT) !== 0) {
|
|
164
|
+
result.paper = PaperStatus.OUT;
|
|
165
|
+
} else if ((status & STATUS_BIT_PAPER_LOW) !== 0) {
|
|
166
|
+
result.paper = PaperStatus.LOW;
|
|
167
|
+
} else {
|
|
168
|
+
result.paper = PaperStatus.OK;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Check other status bits (printer-dependent)
|
|
172
|
+
// Bit 0: Drawer open/closed
|
|
173
|
+
// Bit 1: Offline
|
|
174
|
+
// Bit 2: Error
|
|
175
|
+
// Bit 3: Printer-specific status
|
|
176
|
+
|
|
177
|
+
if ((status & 0x01) !== 0) {
|
|
178
|
+
this.logger.debug('Drawer open detected');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if ((status & 0x02) !== 0) {
|
|
182
|
+
result.coverOpen = true;
|
|
183
|
+
this.logger.debug('Cover open detected');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
if ((status & 0x04) !== 0) {
|
|
187
|
+
result.cutterError = true;
|
|
188
|
+
this.logger.debug('Cutter error detected');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if ((status & 0x10) !== 0) {
|
|
192
|
+
result.overTemp = true;
|
|
193
|
+
this.logger.debug('Over temperature detected');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// Second byte often contains paper sensor status
|
|
197
|
+
if (statusBytes.length >= 2) {
|
|
198
|
+
const paperSensor = statusBytes[1] ?? 0;
|
|
199
|
+
|
|
200
|
+
// Paper out sensor
|
|
201
|
+
if ((paperSensor & 0x04) !== 0) {
|
|
202
|
+
result.paper = PaperStatus.OUT;
|
|
203
|
+
} else if ((paperSensor & 0x08) !== 0) {
|
|
204
|
+
result.paper = PaperStatus.LOW;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
this.logger.debug('Parsed status:', result);
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Check if paper is available
|
|
214
|
+
*/
|
|
215
|
+
async checkPaper(
|
|
216
|
+
writeFunc: (data: ArrayBuffer) => Promise<void>,
|
|
217
|
+
readFunc: () => Promise<ArrayBuffer>
|
|
218
|
+
): Promise<PaperStatus> {
|
|
219
|
+
const status = await this.getStatus(writeFunc, readFunc);
|
|
220
|
+
return status.paper;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Check if printer is ready
|
|
225
|
+
*/
|
|
226
|
+
async isReady(
|
|
227
|
+
writeFunc: (data: ArrayBuffer) => Promise<void>,
|
|
228
|
+
readFunc: () => Promise<ArrayBuffer>
|
|
229
|
+
): Promise<boolean> {
|
|
230
|
+
try {
|
|
231
|
+
const status = await this.getStatus(writeFunc, readFunc);
|
|
232
|
+
return status.paper !== PaperStatus.OUT && !status.cutterError && !status.motorError;
|
|
233
|
+
} catch {
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Get human-readable status string
|
|
240
|
+
*/
|
|
241
|
+
static toString(status: PrinterStatusInfo): string {
|
|
242
|
+
const parts: string[] = [];
|
|
243
|
+
|
|
244
|
+
parts.push(`Paper: ${status.paper}`);
|
|
245
|
+
|
|
246
|
+
if (status.coverOpen) {
|
|
247
|
+
parts.push('Cover Open');
|
|
248
|
+
}
|
|
249
|
+
if (status.cutterError) {
|
|
250
|
+
parts.push('Cutter Error');
|
|
251
|
+
}
|
|
252
|
+
if (status.motorError) {
|
|
253
|
+
parts.push('Motor Error');
|
|
254
|
+
}
|
|
255
|
+
if (status.overTemp) {
|
|
256
|
+
parts.push('Over Temperature');
|
|
257
|
+
}
|
|
258
|
+
if (status.batteryLevel !== undefined) {
|
|
259
|
+
parts.push(`Battery: ${status.batteryLevel}%`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return parts.join(', ');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Export singleton
|
|
267
|
+
export const printerStatus = new PrinterStatus();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Services Module
|
|
3
|
+
* 服务模块 - 提供连接管理、命令构建、任务管理等功能
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export {
|
|
7
|
+
ConnectionManager,
|
|
8
|
+
type ConnectionManagerConfig,
|
|
9
|
+
type ConnectionManagerEvents,
|
|
10
|
+
} from './ConnectionManager';
|
|
11
|
+
|
|
12
|
+
export { CommandBuilder } from './CommandBuilder';
|
|
13
|
+
|
|
14
|
+
export { PrintJobManager } from './PrintJobManager';
|
|
15
|
+
|
|
16
|
+
export { PrintHistory, printHistory, type PrintHistoryEntry, type PrintHistoryStats, type HistoryQueryOptions } from './PrintHistory';
|
|
17
|
+
|
|
18
|
+
export { PrinterStatus, printerStatus, type PrinterStatusInfo, type StatusQueryOptions, type PaperStatus } from './PrinterStatus';
|
|
19
|
+
|
|
20
|
+
export { BatchPrintManager, batchPrintManager, type BatchJob, type BatchConfig, type BatchStats, type BatchEvents } from './BatchPrintManager';
|
|
21
|
+
|
|
22
|
+
export * from './interfaces';
|
|
@@ -510,7 +510,10 @@ export class TemplateEngine implements ITemplateEngine {
|
|
|
510
510
|
private substituteVariables(template: string, data: Record<string, unknown>): string {
|
|
511
511
|
return template.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (_, key: string) => {
|
|
512
512
|
const value = this.getNestedValue(data, key);
|
|
513
|
-
|
|
513
|
+
if (value === undefined) return '';
|
|
514
|
+
if (typeof value === 'object') return JSON.stringify(value);
|
|
515
|
+
// eslint-disable-next-line @typescript-eslint/no-base-to-string
|
|
516
|
+
return String(value);
|
|
514
517
|
});
|
|
515
518
|
}
|
|
516
519
|
|