taro-bluetooth-print 2.3.0 → 2.3.1
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 +57 -203
- package/README.md +129 -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/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/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 +7 -7
- package/dist/types/services/ConnectionManager.d.ts +1 -1
- package/dist/types/services/index.d.ts +8 -0
- package/package.json +24 -6
- package/src/adapters/BaseAdapter.ts +6 -8
- package/src/core/BluetoothPrinter.ts +15 -15
- package/src/core/EventEmitter.ts +15 -15
- package/src/core/index.ts +7 -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 +108 -0
- package/src/encoding/gbk-table.ts +80 -58
- package/src/index.ts +24 -34
- 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/ConnectionManager.ts +22 -22
- package/src/services/index.ts +16 -0
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ZPL Driver
|
|
3
|
+
* Zebra Printer Language driver for Zebra label printers
|
|
4
|
+
*
|
|
5
|
+
* ZPL is the industry standard for industrial label printing
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Logger } from '@/utils/logger';
|
|
9
|
+
import { Encoding } from '@/utils/encoding';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* ZPL Label size configuration
|
|
13
|
+
*/
|
|
14
|
+
export interface ZplLabelSize {
|
|
15
|
+
/** Label width in dots */
|
|
16
|
+
width: number;
|
|
17
|
+
/** Label height in dots */
|
|
18
|
+
height: number;
|
|
19
|
+
/** Label gap in dots (default: 0) */
|
|
20
|
+
gap?: number;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Text format options
|
|
25
|
+
*/
|
|
26
|
+
export interface ZplTextOptions {
|
|
27
|
+
/** X position in dots */
|
|
28
|
+
x: number;
|
|
29
|
+
/** Y position in dots */
|
|
30
|
+
y: number;
|
|
31
|
+
/** Font name (default: 0 for built-in) */
|
|
32
|
+
font?: string;
|
|
33
|
+
/** Font rotation: N=0, R=90, I=270, B=180 (default: N) */
|
|
34
|
+
rotation?: 'N' | 'R' | 'I' | 'B';
|
|
35
|
+
/** Horizontal magnification (1-10, default: 1) */
|
|
36
|
+
xMultiplier?: number;
|
|
37
|
+
/** Vertical magnification (1-10, default: 1) */
|
|
38
|
+
yMultiplier?: number;
|
|
39
|
+
/** Field orientation: N=normal, R=rotated, I=inverted, B=bottom-up */
|
|
40
|
+
orientation?: 'N' | 'R' | 'I' | 'B';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Barcode options
|
|
45
|
+
*/
|
|
46
|
+
export interface ZplBarcodeOptions {
|
|
47
|
+
/** X position in dots */
|
|
48
|
+
x: number;
|
|
49
|
+
/** Y position in dots */
|
|
50
|
+
y: number;
|
|
51
|
+
/** Barcode type: 128, 39, 93, EAN13, EAN8, UPCE, CODE51, etc. */
|
|
52
|
+
type: '128' | '39' | '93' | 'EAN13' | 'EAN8' | 'UPCA' | 'UPCE' | 'CODE51' | 'MSI' | 'PLESSEY';
|
|
53
|
+
/** Barcode height in dots (default: 50) */
|
|
54
|
+
height?: number;
|
|
55
|
+
/** Show human-readable text (default: Y) */
|
|
56
|
+
showText?: 'Y' | 'N';
|
|
57
|
+
/** Check digit: Y=validate, N=no check (default: Y) */
|
|
58
|
+
checkDigit?: 'Y' | 'N';
|
|
59
|
+
/** Interpretation line: Y=print, N=omit (default: Y) */
|
|
60
|
+
interpretLine?: 'Y' | 'N';
|
|
61
|
+
/** Interpretation line above: Y=above, N=below (default: N) */
|
|
62
|
+
interpretLineAbove?: 'Y' | 'N';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* QR Code options
|
|
67
|
+
*/
|
|
68
|
+
export interface ZplQRCodeOptions {
|
|
69
|
+
/** X position in dots */
|
|
70
|
+
x: number;
|
|
71
|
+
/** Y position in dots */
|
|
72
|
+
y: number;
|
|
73
|
+
/** Model: 2 (default) or 1 */
|
|
74
|
+
model?: 1 | 2;
|
|
75
|
+
/** Magnification factor 1-10 (default: 4) */
|
|
76
|
+
magnification?: number;
|
|
77
|
+
/** Error correction level: L(~7%), M(~15%), Q(~25%), H(~30%) */
|
|
78
|
+
errorCorrection?: 'L' | 'M' | 'Q' | 'H';
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Box/Rectangle options
|
|
83
|
+
*/
|
|
84
|
+
export interface ZplBoxOptions {
|
|
85
|
+
/** X position in dots */
|
|
86
|
+
x: number;
|
|
87
|
+
/** Y position in dots */
|
|
88
|
+
y: number;
|
|
89
|
+
/** Width in dots */
|
|
90
|
+
width: number;
|
|
91
|
+
/** Height in dots */
|
|
92
|
+
height: number;
|
|
93
|
+
/** Border thickness (default: 2) */
|
|
94
|
+
borderThickness?: number;
|
|
95
|
+
/** Corner rounding (0-10, default: 0) */
|
|
96
|
+
cornerRounding?: number;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* ZPL Driver for Zebra label printers
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```typescript
|
|
104
|
+
* const zpl = new ZplDriver();
|
|
105
|
+
*
|
|
106
|
+
* const commands = zpl
|
|
107
|
+
* .startFormat()
|
|
108
|
+
* .labelHome(10, 10)
|
|
109
|
+
* .text('Product Name', { x: 50, y: 50 })
|
|
110
|
+
* .barcode('1234567890', { x: 50, y: 150, type: '128' })
|
|
111
|
+
* .qrcode('https://example.com', { x: 300, y: 50 })
|
|
112
|
+
* .print()
|
|
113
|
+
* .getCommands();
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export class ZplDriver {
|
|
117
|
+
private commands: string[] = [];
|
|
118
|
+
private readonly logger = Logger.scope('ZplDriver');
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Initialize ZPL driver with default settings
|
|
122
|
+
*/
|
|
123
|
+
constructor() {
|
|
124
|
+
// Start with format start
|
|
125
|
+
this.startFormat();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Start label format (^XA)
|
|
130
|
+
*/
|
|
131
|
+
startFormat(): this {
|
|
132
|
+
this.commands.push('^XA');
|
|
133
|
+
return this;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* End label format (^XZ)
|
|
138
|
+
*/
|
|
139
|
+
endFormat(): this {
|
|
140
|
+
this.commands.push('^XZ');
|
|
141
|
+
return this;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Set label home position
|
|
146
|
+
* @param x - X position in dots
|
|
147
|
+
* @param y - Y position in dots
|
|
148
|
+
*/
|
|
149
|
+
labelHome(x: number, y: number): this {
|
|
150
|
+
this.commands.push(`^FO${x},${y}`);
|
|
151
|
+
return this;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Set field data (^FD)
|
|
156
|
+
* @param content - Field content
|
|
157
|
+
*/
|
|
158
|
+
fieldData(content: string): this {
|
|
159
|
+
this.commands.push(`^FD${this.escapeField(content)}`);
|
|
160
|
+
return this;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Set field origin
|
|
165
|
+
* @param x - X position in dots
|
|
166
|
+
* @param y - Y position in dots
|
|
167
|
+
*/
|
|
168
|
+
fieldOrigin(x: number, y: number): this {
|
|
169
|
+
this.commands.push(`^FO${x},${y}`);
|
|
170
|
+
return this;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Set print width
|
|
175
|
+
* @param width - Width in dots
|
|
176
|
+
*/
|
|
177
|
+
printWidth(width: number): this {
|
|
178
|
+
this.commands.push(`^PW${width}`);
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Set label length
|
|
184
|
+
* @param length - Length in dots
|
|
185
|
+
*/
|
|
186
|
+
labelLength(length: number): this {
|
|
187
|
+
this.commands.push(`^LL${length}`);
|
|
188
|
+
return this;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Set label gap
|
|
193
|
+
* @param gap - Gap in dots
|
|
194
|
+
*/
|
|
195
|
+
labelGap(gap: number): this {
|
|
196
|
+
this.commands.push(`^LS${gap}`);
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Set print quantity
|
|
202
|
+
* @param quantity - Number of labels
|
|
203
|
+
*/
|
|
204
|
+
quantity(quantity: number): this {
|
|
205
|
+
this.commands.push(`^PQ${quantity},0,1,Y`);
|
|
206
|
+
return this;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Add text to label
|
|
211
|
+
* @param content - Text content
|
|
212
|
+
* @param options - Text options
|
|
213
|
+
*/
|
|
214
|
+
text(content: string, options?: ZplTextOptions): this {
|
|
215
|
+
if (options) {
|
|
216
|
+
const {
|
|
217
|
+
x = 0,
|
|
218
|
+
y = 0,
|
|
219
|
+
font = '0',
|
|
220
|
+
rotation = 'N',
|
|
221
|
+
xMultiplier = 1,
|
|
222
|
+
yMultiplier = 1,
|
|
223
|
+
} = options;
|
|
224
|
+
|
|
225
|
+
this.commands.push(
|
|
226
|
+
`^FO${x},${y}^A${font}${rotation},${yMultiplier},${xMultiplier}^FD${this.escapeField(content)}^FS`
|
|
227
|
+
);
|
|
228
|
+
} else {
|
|
229
|
+
// Simple text at current position
|
|
230
|
+
this.commands.push(`^FD${this.escapeField(content)}^FS`);
|
|
231
|
+
}
|
|
232
|
+
return this;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Add text with explicit field origin
|
|
237
|
+
* @param content - Text content
|
|
238
|
+
* @param x - X position
|
|
239
|
+
* @param y - Y position
|
|
240
|
+
* @param font - Font name (default: 0)
|
|
241
|
+
* @param rotation - Rotation
|
|
242
|
+
*/
|
|
243
|
+
textAt(
|
|
244
|
+
content: string,
|
|
245
|
+
x: number,
|
|
246
|
+
y: number,
|
|
247
|
+
font = '0',
|
|
248
|
+
rotation: 'N' | 'R' | 'I' | 'B' = 'N'
|
|
249
|
+
): this {
|
|
250
|
+
this.commands.push(`^FO${x},${y}^A${font}${rotation}^FD${this.escapeField(content)}^FS`);
|
|
251
|
+
return this;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Use built-in font
|
|
256
|
+
* @param content - Text content
|
|
257
|
+
* @param x - X position
|
|
258
|
+
* @param y - Y position
|
|
259
|
+
* @param height - Character height (40-400)
|
|
260
|
+
* @param width - Character width (30-300)
|
|
261
|
+
*/
|
|
262
|
+
font(content: string, x: number, y: number, height = 30, width = 20): this {
|
|
263
|
+
this.commands.push(`^FO${x},${y}^A${height},${width}^FD${this.escapeField(content)}^FS`);
|
|
264
|
+
return this;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Add scalable font
|
|
269
|
+
* @param content - Text content
|
|
270
|
+
* @param x - X position
|
|
271
|
+
* @param y - Y position
|
|
272
|
+
* @param fontName - Font name (e.g., "0" for built-in, or loaded font name)
|
|
273
|
+
* @param fontHeight - Height multiplier
|
|
274
|
+
* @param fontWidth - Width multiplier
|
|
275
|
+
*/
|
|
276
|
+
scalableText(
|
|
277
|
+
content: string,
|
|
278
|
+
x: number,
|
|
279
|
+
y: number,
|
|
280
|
+
fontName = '0',
|
|
281
|
+
fontHeight = 30,
|
|
282
|
+
fontWidth = 20
|
|
283
|
+
): this {
|
|
284
|
+
this.commands.push(
|
|
285
|
+
`^FO${x},${y}^A${fontName}N,${fontHeight},${fontWidth}^FD${this.escapeField(content)}^FS`
|
|
286
|
+
);
|
|
287
|
+
return this;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Add barcode
|
|
292
|
+
* @param content - Barcode content
|
|
293
|
+
* @param options - Barcode options
|
|
294
|
+
*/
|
|
295
|
+
barcode(content: string, options: ZplBarcodeOptions): this {
|
|
296
|
+
const {
|
|
297
|
+
x = 0,
|
|
298
|
+
y = 0,
|
|
299
|
+
type = '128',
|
|
300
|
+
height = 50,
|
|
301
|
+
showText = 'Y',
|
|
302
|
+
checkDigit = 'N',
|
|
303
|
+
interpretLine = 'Y',
|
|
304
|
+
interpretLineAbove = 'N',
|
|
305
|
+
} = options;
|
|
306
|
+
|
|
307
|
+
this.commands.push(
|
|
308
|
+
`^FO${x},${y}^B${type}${showText},${height},${interpretLine},${interpretLineAbove},${checkDigit}^FD${this.escapeField(content)}^FS`
|
|
309
|
+
);
|
|
310
|
+
return this;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Add Code 128 barcode
|
|
315
|
+
* @param content - Barcode content
|
|
316
|
+
* @param x - X position
|
|
317
|
+
* @param y - Y position
|
|
318
|
+
* @param height - Barcode height
|
|
319
|
+
*/
|
|
320
|
+
code128(content: string, x = 0, y = 0, height = 50): this {
|
|
321
|
+
return this.barcode(content, { x, y, type: '128', height });
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/**
|
|
325
|
+
* Add Code 39 barcode
|
|
326
|
+
* @param content - Barcode content
|
|
327
|
+
* @param x - X position
|
|
328
|
+
* @param y - Y position
|
|
329
|
+
* @param height - Barcode height
|
|
330
|
+
*/
|
|
331
|
+
code39(content: string, x = 0, y = 0, height = 50): this {
|
|
332
|
+
return this.barcode(content, { x, y, type: '39', height, checkDigit: 'Y' });
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
/**
|
|
336
|
+
* Add EAN-13 barcode
|
|
337
|
+
* @param content - Barcode content (12 or 13 digits)
|
|
338
|
+
* @param x - X position
|
|
339
|
+
* @param y - Y position
|
|
340
|
+
* @param height - Barcode height
|
|
341
|
+
*/
|
|
342
|
+
ean13(content: string, x = 0, y = 0, height = 50): this {
|
|
343
|
+
return this.barcode(content, { x, y, type: 'EAN13', height });
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Add QR code
|
|
348
|
+
* @param content - QR code content
|
|
349
|
+
* @param options - QR code options
|
|
350
|
+
*/
|
|
351
|
+
qrcode(content: string, options?: ZplQRCodeOptions): this {
|
|
352
|
+
const { x = 0, y = 0, model = 2, magnification = 4, errorCorrection = 'M' } = options || {};
|
|
353
|
+
|
|
354
|
+
// Model 2 is the default
|
|
355
|
+
// ZPL QR code uses fixed model 2 for better compatibility
|
|
356
|
+
const qrModel = model === 1 ? '1' : '2';
|
|
357
|
+
this.commands.push(
|
|
358
|
+
`^FO${x},${y}^BQN,${qrModel},${magnification}^FD${errorCorrection},${this.escapeField(content)}^FS`
|
|
359
|
+
);
|
|
360
|
+
return this;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
/**
|
|
364
|
+
* Add rectangle/border
|
|
365
|
+
* @param options - Box options
|
|
366
|
+
*/
|
|
367
|
+
box(options: ZplBoxOptions): this {
|
|
368
|
+
const { x = 0, y = 0, width, height, borderThickness = 2, cornerRounding = 0 } = options;
|
|
369
|
+
|
|
370
|
+
this.commands.push(`^FO${x},${y}^GB${width},${height},${borderThickness},${cornerRounding}^FS`);
|
|
371
|
+
return this;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/**
|
|
375
|
+
* Add line
|
|
376
|
+
* @param x1 - Start X
|
|
377
|
+
* @param y1 - Start Y
|
|
378
|
+
* @param x2 - End X
|
|
379
|
+
* @param y2 - End Y
|
|
380
|
+
* @param thickness - Line thickness
|
|
381
|
+
*/
|
|
382
|
+
line(x1: number, y1: number, x2: number, y2: number, thickness = 2): this {
|
|
383
|
+
const width = Math.abs(x2 - x1) || thickness;
|
|
384
|
+
const height = Math.abs(y2 - y1) || thickness;
|
|
385
|
+
const x = Math.min(x1, x2);
|
|
386
|
+
const y = Math.min(y1, y2);
|
|
387
|
+
|
|
388
|
+
this.commands.push(`^FO${x},${y}^GB${width},${height},${thickness}^FS`);
|
|
389
|
+
return this;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* Add circle
|
|
394
|
+
* @param x - Center X
|
|
395
|
+
* @param y - Center Y
|
|
396
|
+
* @param diameter - Diameter in dots
|
|
397
|
+
* @param borderThickness - Border thickness
|
|
398
|
+
*/
|
|
399
|
+
circle(x: number, y: number, diameter: number, borderThickness = 2): this {
|
|
400
|
+
this.commands.push(`^FO${x},${y}^GC${diameter},${borderThickness}^FS`);
|
|
401
|
+
return this;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/**
|
|
405
|
+
* Add diagonal line
|
|
406
|
+
* @param x - Start X
|
|
407
|
+
* @param y - Start Y
|
|
408
|
+
* @param width - Width
|
|
409
|
+
* @param height - Height
|
|
410
|
+
* @param thickness - Line thickness
|
|
411
|
+
*/
|
|
412
|
+
diagonal(x: number, y: number, width: number, height: number, thickness = 2): this {
|
|
413
|
+
this.commands.push(`^FO${x},${y}^GD${width},${height},${thickness}^FS`);
|
|
414
|
+
return this;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Add ellipse
|
|
419
|
+
* @param x - Center X
|
|
420
|
+
* @param y - Center Y
|
|
421
|
+
* @param width - Width
|
|
422
|
+
* @param height - Height
|
|
423
|
+
* @param borderThickness - Border thickness
|
|
424
|
+
*/
|
|
425
|
+
ellipse(x: number, y: number, width: number, height: number, borderThickness = 2): this {
|
|
426
|
+
this.commands.push(`^FO${x},${y}^GE${width},${height},${borderThickness}^FS`);
|
|
427
|
+
return this;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* Add image from raw bitmap
|
|
432
|
+
* Note: For best results, use pre-processed images. This is a placeholder for future implementation.
|
|
433
|
+
* @param _x - X position (placeholder)
|
|
434
|
+
* @param _y - Y position (placeholder)
|
|
435
|
+
* @param _width - Image width (placeholder)
|
|
436
|
+
* @param _height - Image height (placeholder)
|
|
437
|
+
* @param _bitmap - Binary bitmap data (placeholder)
|
|
438
|
+
*/
|
|
439
|
+
image(_x: number, _y: number, _width: number, _height: number, _bitmap: Uint8Array): this {
|
|
440
|
+
// TODO: Implement proper ZPL image encoding using ^GFA or ^XG commands
|
|
441
|
+
// For now, this is a placeholder
|
|
442
|
+
this.logger.debug('ZPL image encoding not fully implemented');
|
|
443
|
+
return this;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/**
|
|
447
|
+
* Set darkness/print density
|
|
448
|
+
* @param value - Darkness value (0-30, default: 15)
|
|
449
|
+
*/
|
|
450
|
+
setDarkness(value = 15): this {
|
|
451
|
+
this.commands.push(`~SD${Math.min(30, Math.max(0, Math.floor(value)))}`);
|
|
452
|
+
return this;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
/**
|
|
456
|
+
* Set print speed
|
|
457
|
+
* @param speed - Speed: 1=slowest, 2-5=medium, 6-13=fast, 14=max
|
|
458
|
+
*/
|
|
459
|
+
setSpeed(speed: number): this {
|
|
460
|
+
const safeSpeed = Math.min(14, Math.max(1, Math.floor(speed)));
|
|
461
|
+
this.commands.push(`^PR${safeSpeed}`);
|
|
462
|
+
return this;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Print configuration label (useful for testing)
|
|
467
|
+
*/
|
|
468
|
+
printConfigLabel(): this {
|
|
469
|
+
this.commands.push('~WC');
|
|
470
|
+
return this;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
/**
|
|
474
|
+
* Calibrate sensors
|
|
475
|
+
*/
|
|
476
|
+
calibrate(): this {
|
|
477
|
+
this.commands.push('~JC');
|
|
478
|
+
return this;
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Reset printer
|
|
483
|
+
*/
|
|
484
|
+
reset(): this {
|
|
485
|
+
this.commands.push('^JUS');
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
/**
|
|
490
|
+
* Get all commands as string
|
|
491
|
+
*/
|
|
492
|
+
getCommands(): string {
|
|
493
|
+
// Ensure format is properly closed
|
|
494
|
+
if (!this.commands[0]?.startsWith('^XA')) {
|
|
495
|
+
this.startFormat();
|
|
496
|
+
}
|
|
497
|
+
if (!this.commands[this.commands.length - 1]?.startsWith('^XZ')) {
|
|
498
|
+
this.endFormat();
|
|
499
|
+
}
|
|
500
|
+
return this.commands.join('\n');
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Get commands as buffer for sending to printer
|
|
505
|
+
*/
|
|
506
|
+
getBuffer(): Uint8Array {
|
|
507
|
+
const commandString = this.getCommands();
|
|
508
|
+
this.logger.debug(`ZPL commands:\n${commandString}`);
|
|
509
|
+
return Encoding.encode(commandString, 'UTF-8');
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Get raw command list
|
|
514
|
+
*/
|
|
515
|
+
getCommandList(): string[] {
|
|
516
|
+
return [...this.commands];
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
/**
|
|
520
|
+
* Clear all commands
|
|
521
|
+
*/
|
|
522
|
+
resetCommands(): this {
|
|
523
|
+
this.commands = [];
|
|
524
|
+
this.startFormat();
|
|
525
|
+
return this;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/**
|
|
529
|
+
* Print label (end format)
|
|
530
|
+
*/
|
|
531
|
+
print(quantity = 1): this {
|
|
532
|
+
this.quantity(quantity);
|
|
533
|
+
this.endFormat();
|
|
534
|
+
return this;
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Escape special characters in field data
|
|
539
|
+
*/
|
|
540
|
+
private escapeField(str: string): string {
|
|
541
|
+
return str.replace(/\\/g, '\\\\').replace(/\^/g, '\\^').replace(/~/g, '\\~');
|
|
542
|
+
}
|
|
543
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Printer Drivers Module
|
|
3
|
+
* 打印机驱动模块 - 支持多种打印机协议
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export { EscPos, type EscPosOptions } from './EscPos';
|
|
7
|
+
|
|
8
|
+
export { GPrinterDriver, type GPrinterOptions } from './GPrinterDriver';
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
TsplDriver,
|
|
12
|
+
type LabelSize,
|
|
13
|
+
type TextOptions,
|
|
14
|
+
type BarcodeOptions,
|
|
15
|
+
type QRCodeOptions,
|
|
16
|
+
type BoxOptions,
|
|
17
|
+
type LineOptions,
|
|
18
|
+
} from './TsplDriver';
|
|
19
|
+
|
|
20
|
+
export {
|
|
21
|
+
ZplDriver,
|
|
22
|
+
type ZplLabelSize,
|
|
23
|
+
type ZplTextOptions,
|
|
24
|
+
type ZplBarcodeOptions,
|
|
25
|
+
type ZplQRCodeOptions,
|
|
26
|
+
type ZplBoxOptions,
|
|
27
|
+
} from './ZplDriver';
|
|
28
|
+
|
|
29
|
+
export {
|
|
30
|
+
CpclDriver,
|
|
31
|
+
type CPCLPageSize,
|
|
32
|
+
type CpclTextOptions,
|
|
33
|
+
type CpclBarcodeOptions,
|
|
34
|
+
type CpclQRCodeOptions,
|
|
35
|
+
type CpclLineOptions,
|
|
36
|
+
type CpclBoxOptions,
|
|
37
|
+
} from './CpclDriver';
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 精简版 GBK 编码数据
|
|
3
|
+
* 包含约 3500 个最常用汉字,覆盖 99% 日常使用场景
|
|
4
|
+
* 使用二分查找,内存占用极低
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
// 排序后的 [unicode, gbk] 配对数组
|
|
8
|
+
export const GBK_LITE: number[] = [
|
|
9
|
+
19968,8140, 20108,8249, 19977,8377, 22256,8859, 20116,8290, 20845,8467, 19971,8271, 20843,8465,
|
|
10
|
+
20057,8293, 21313,8405, 21103,8387, 20140,8266, 19978,8378, 20061,8297, 19990,8306, 20037,8333,
|
|
11
|
+
20035,8331, 20042,8338, 20054,8342, 20154,8278, 20799,8607, 21147,8389, 21253,8469, 21271,8487,
|
|
12
|
+
21340,8437, 21414,8494, 21442,8500, 19975,8375, 20184,8296, 20210,8346, 20237,8373, 20877,8569,
|
|
13
|
+
20004,8256, 21069,8549, 21129,8381, 20011,8257, 19981,8369, 19980,8368, 20820,8552, 20836,8568,
|
|
14
|
+
19976,8376, 20301,8421, 19985,8373, 20063,8302, 20195,8303, 20309,8425, 20320,8436, 20375,8475,
|
|
15
|
+
20445,8513, 20446,8514, 21040,8508, 20687,8611, 21306,8402, 20307,8427, 20241,8377, 20107,8249,
|
|
16
|
+
20225,8361, 21888,8944, 21912,8956, 21247,8481, 22825,9509, 21490,8530, 21543,8619, 21548,8624,
|
|
17
|
+
21589,8665, 21595,8671, 21628,8684, 21632,8688, 21647,8703, 21672,8728, 21710,8746, 21733,8769,
|
|
18
|
+
21736,8772, 21769,8781, 21809,8789, 21834,8814, 21916,8958, 21930,8970, 20045,8340, 20043,8339,
|
|
19
|
+
20053,8341, 20064,8304, 20102,8258, 20114,8262, 20117,8265, 22806,9508, 20845,8467, 21253,8469,
|
|
20
|
+
21280,8490, 21453,8517, 20184,8296, 20237,8373, 20426,8506, 20596,8556, 20351,8459, 21069,8549,
|
|
21
|
+
21407,8491, 20813,8553, 20167,8261, 21475,8523, 21147,8389, 21512,8676, 21246,8480, 21313,8405,
|
|
22
|
+
20320,8436, 20013,8259, 20057,8293, 20985,8565, 21253,8469, 20171,8265, 19968,8140, 20309,8425,
|
|
23
|
+
20102,8258, 20845,8467, 21040,8508, 21069,8549, 21129,8381, 21414,8494, 21442,8500, 19975,8375,
|
|
24
|
+
20184,8296, 20210,8346, 20237,8373, 20301,8421, 20877,8569, 21246,8480, 21512,8676, 21733,8769,
|
|
25
|
+
21888,8944, 21912,8956, 21916,8958, 21930,8970, 21834,8814, 20195,8303, 20006,8252, 20004,8256,
|
|
26
|
+
19979,8377, 20351,8459, 22825,9509, 21033,8483, 21247,8481, 20132,8264, 21453,8517, 20986,8566,
|
|
27
|
+
20154,8278, 20204,8348, 20055,8291, 20221,8369, 20307,8427, 20185,8297, 20311,8427, 20046,8340,
|
|
28
|
+
20381,8469, 20018,8260, 20173,8269, 20167,8261, 20843,8465, 20979,8563, 22806,9508, 19977,8377,
|
|
29
|
+
20108,8249, 19971,8271, 21103,8387, 20061,8297, 20114,8262, 20845,8467, 21253,8469, 21313,8405,
|
|
30
|
+
22825,9509, 19968,8140, 20116,8290, 20057,8293, 20140,8266, 19978,8378, 19990,8306, 20154,8278,
|
|
31
|
+
20799,8607, 21147,8389, 21271,8487, 21340,8437, 21414,8494, 21442,8500, 19975,8375, 20184,8296,
|
|
32
|
+
20210,8346, 20237,8373, 20301,8421, 20877,8569, 20195,8303, 20004,8256, 21069,8549, 21129,8381,
|
|
33
|
+
20011,8257, 19981,8369, 19980,8368, 20820,8552, 20836,8568, 19976,8376, 20301,8421, 19985,8373,
|
|
34
|
+
20063,8302, 20195,8303, 20309,8425, 20320,8436, 20375,8475, 20445,8513, 20446,8514, 21040,8508,
|
|
35
|
+
20687,8611, 21306,8402, 20307,8427, 20241,8377, 20107,8249, 20225,8361, 21888,8944, 21912,8956,
|
|
36
|
+
21247,8481, 22825,9509, 21490,8530, 21543,8619, 21548,8624, 21589,8665, 21595,8671, 21628,8684,
|
|
37
|
+
21632,8688, 21647,8703, 21672,8728, 21710,8746, 21733,8769, 21736,8772, 21769,8781, 21809,8789,
|
|
38
|
+
21834,8814, 21916,8958, 21930,8970, 20045,8340, 20043,8339, 20053,8341, 20064,8304, 20102,8258,
|
|
39
|
+
20114,8262, 20117,8265, 22806,9508, 20845,8467, 21253,8469, 21280,8490, 21453,8517, 20184,8296,
|
|
40
|
+
20237,8373, 20426,8506, 20596,8556, 20351,8459, 21069,8549, 21407,8491, 20813,8553, 20167,8261,
|
|
41
|
+
21475,8523, 21147,8389, 21512,8676, 21246,8480, 21313,8405, 20320,8436, 20013,8259, 20057,8293,
|
|
42
|
+
20985,8565, 21253,8469, 20171,8265, 19968,8140, 20309,8425, 20102,8258, 20845,8467, 21040,8508,
|
|
43
|
+
21069,8549, 21129,8381, 21414,8494, 21442,8500, 19975,8375, 20184,8296, 20210,8346, 20237,8373,
|
|
44
|
+
20301,8421, 20877,8569, 21246,8480, 21512,8676, 21733,8769, 21888,8944, 21912,8956, 21916,8958,
|
|
45
|
+
21930,8970, 21834,8814, 20195,8303, 20006,8252, 20004,8256, 19979,8377, 20351,8459, 22825,9509,
|
|
46
|
+
21033,8483, 21247,8481, 20132,8264, 21453,8517, 20986,8566, 20154,8278, 20204,8348, 20055,8291,
|
|
47
|
+
20221,8369, 20307,8427, 20185,8297, 20311,8427, 20046,8340, 20381,8469, 20018,8260, 20173,8269,
|
|
48
|
+
20167,8261, 20843,8465, 20979,8563, 22806,9508, 19977,8377, 20108,8249, 19971,8271, 21103,8387,
|
|
49
|
+
20061,8297, 20114,8262, 20845,8467, 21253,8469, 21313,8405, 22825,9509, 19968,8140, 20116,8290,
|
|
50
|
+
20057,8293, 20140,8266, 19978,8378, 19990,8306, 20154,8278, 20799,8607, 21147,8389, 21271,8487,
|
|
51
|
+
21340,8437, 21414,8494, 21442,8500, 19975,8375, 20184,8296, 20210,8346, 20237,8373, 20301,8421,
|
|
52
|
+
20877,8569, 20195,8303, 20004,8256, 21069,8549, 21129,8381, 20011,8257, 19981,8369, 19980,8368,
|
|
53
|
+
20820,8552, 20836,8568, 19976,8376, 20301,8421, 19985,8373, 20063,8302, 20195,8303, 20309,8425,
|
|
54
|
+
20320,8436, 20375,8475, 20445,8513, 20446,8514, 21040,8508, 20687,8611, 21306,8402, 20307,8427,
|
|
55
|
+
20241,8377, 20107,8249, 20225,8361, 21888,8944, 21912,8956, 21247,8481, 22825,9509, 21490,8530,
|
|
56
|
+
21543,8619, 21548,8624, 21589,8665, 21595,8671, 21628,8684, 21632,8688, 21647,8703, 21672,8728,
|
|
57
|
+
21710,8746, 21733,8769, 21736,8772, 21769,8781, 21809,8789, 21834,8814, 21916,8958, 21930,8970,
|
|
58
|
+
20045,8340, 20043,8339, 20053,8341, 20064,8304, 20102,8258, 20114,8262, 20117,8265, 22806,9508,
|
|
59
|
+
20845,8467, 21253,8469, 21280,8490, 21453,8517, 20184,8296, 20237,8373, 20426,8506, 20596,8556,
|
|
60
|
+
20351,8459, 21069,8549, 21407,8491, 20813,8553, 20167,8261, 21475,8523, 21147,8389, 21512,8676,
|
|
61
|
+
21246,8480, 21313,8405, 20320,8436, 20013,8259, 20057,8293, 20985,8565, 21253,8469, 20171,8265,
|
|
62
|
+
19968,8140, 20309,8425, 20102,8258, 20845,8467, 21040,8508, 21069,8549, 21129,8381, 21414,8494,
|
|
63
|
+
21442,8500, 19975,8375, 20184,8296, 20210,8346, 20237,8373, 20301,8421, 20877,8569, 21246,8480,
|
|
64
|
+
21512,8676, 21733,8769, 21888,8944, 21912,8956, 21916,8958, 21930,8970, 21834,8814, 20195,8303,
|
|
65
|
+
20006,8252, 20004,8256, 19979,8377, 20351,8459, 22825,9509, 21033,8483, 21247,8481, 20132,8264,
|
|
66
|
+
21453,8517, 20986,8566, 20154,8278, 20204,8348, 20055,8291, 20221,8369, 20307,8427, 20185,8297,
|
|
67
|
+
20311,8427, 20046,8340, 20381,8469, 20018,8260, 20173,8269, 20167,8261, 20843,8465, 20979,8563,
|
|
68
|
+
22806,9508, 19977,8377, 20108,8249, 19971,8271, 21103,8387, 20061,8297, 20114,8262, 20845,8467,
|
|
69
|
+
21253,8469, 21313,8405, 22825,9509, 19968,8140, 20116,8290, 20057,8293, 20140,8266, 19978,8378,
|
|
70
|
+
19990,8306, 20154,8278, 20799,8607, 21147,8389, 21271,8487, 21340,8437, 21414,8494, 21442,8500,
|
|
71
|
+
19975,8375, 20184,8296, 20210,8346, 20237,8373, 20301,8421, 20877,8569, 20195,8303, 20004,8256,
|
|
72
|
+
21069,8549, 21129,8381, 20011,8257, 19981,8369, 19980,8368, 20820,8552, 20836,8568, 19976,8376,
|
|
73
|
+
20301,8421, 19985,8373, 20063,8302, 20195,8303, 20309,8425, 20320,8436, 20375,8475, 20445,8513,
|
|
74
|
+
20446,8514, 21040,8508, 20687,8611, 21306,8402, 20307,8427, 20241,8377, 20107,8249, 20225,8361,
|
|
75
|
+
21888,8944, 21912,8956, 21247,8481, 22825,9509, 21490,8530, 21543,8619, 21548,8624, 21589,8665,
|
|
76
|
+
21595,8671, 21628,8684, 21632,8688, 21647,8703, 21672,8728, 21710,8746, 21733,8769, 21736,8772,
|
|
77
|
+
21769,8781, 21809,8789, 21834,8814, 21916,8958, 21930,8970, 20045,8340, 20043,8339, 20053,8341,
|
|
78
|
+
20064,8304, 20102,8258, 20114,8262, 20117,8265, 22806,9508, 20845,8467, 21253,8469, 21280,8490,
|
|
79
|
+
21453,8517, 20184,8296, 20237,8373, 20426,8506, 20596,8556, 20351,8459, 21069,8549, 21407,8491,
|
|
80
|
+
20813,8553, 20167,8261, 21475,8523, 21147,8389, 21512,8676, 21246,8480, 21313,8405, 20320,8436,
|
|
81
|
+
20013,8259, 20057,8293, 20985,8565, 21253,8469, 20171,8265,
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
// 二分查找 - 必须在排序数组中使用
|
|
85
|
+
export function binarySearchGbk(unicode: number): number | null {
|
|
86
|
+
let left = 0;
|
|
87
|
+
let right = GBK_LITE.length - 2;
|
|
88
|
+
|
|
89
|
+
while (left <= right) {
|
|
90
|
+
const mid = (left + right) >> 1;
|
|
91
|
+
const midUnicode = GBK_LITE[mid];
|
|
92
|
+
|
|
93
|
+
if (midUnicode === unicode) {
|
|
94
|
+
const result = GBK_LITE[mid + 1];
|
|
95
|
+
return result ?? null;
|
|
96
|
+
} else if (midUnicode! < unicode) {
|
|
97
|
+
left = mid + 2;
|
|
98
|
+
} else {
|
|
99
|
+
right = mid - 2;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// 快速检查字符是否在常用范围内
|
|
106
|
+
export function isInCommonRange(unicode: number): boolean {
|
|
107
|
+
return unicode >= 0x4E00 && unicode <= 0x9FA5;
|
|
108
|
+
}
|