escpos-mc 1.0.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/index.js ADDED
@@ -0,0 +1,967 @@
1
+ 'use strict';
2
+ const util = require('util');
3
+ const qr = require('qr-image');
4
+ const iconv = require('iconv-lite');
5
+ const getPixels = require('get-pixels');
6
+ const { MutableBuffer } = require('mutable-buffer');
7
+ const EventEmitter = require('events');
8
+ const Image = require('./image');
9
+ const utils = require('./utils');
10
+ const _ = require('./commands');
11
+ const Promiseify = require('./promisify');
12
+ const statuses = require('./statuses');
13
+ const {PrinterStatus,OfflineCauseStatus,ErrorCauseStatus,RollPaperSensorStatus} = statuses;
14
+
15
+ /**
16
+ * [function ESC/POS Printer]
17
+ * @param {[Adapter]} adapter [eg: usb, network, or serialport]
18
+ * @return {[Printer]} printer [the escpos printer instance]
19
+ */
20
+ function Printer(adapter, options) {
21
+ if (!(this instanceof Printer)) {
22
+ return new Printer(adapter);
23
+ }
24
+ var self = this;
25
+ EventEmitter.call(this);
26
+ this.adapter = adapter;
27
+ this.options = options;
28
+ this.buffer = new MutableBuffer();
29
+ this.encoding = options && options.encoding || 'GB18030';
30
+ this.width = options && options.width || 48;
31
+ this._model = null;
32
+ };
33
+
34
+ Printer.create = function (device) {
35
+ const printer = new Printer(device);
36
+ return Promise.resolve(Promiseify(printer))
37
+ };
38
+
39
+ /**
40
+ * Printer extends EventEmitter
41
+ */
42
+ util.inherits(Printer, EventEmitter);
43
+
44
+ /**
45
+ * Set printer model to recognize model-specific commands.
46
+ * Supported models: [ null, 'qsprinter' ]
47
+ *
48
+ * For generic printers, set model to null
49
+ *
50
+ * [function set printer model]
51
+ * @param {[String]} model [mandatory]
52
+ * @return {[Printer]} printer [the escpos printer instance]
53
+ */
54
+ Printer.prototype.model = function (_model) {
55
+ this._model = _model;
56
+ return this;
57
+ };
58
+
59
+ /**
60
+ * Set character code table
61
+ * @param {[Number]} codeTable
62
+ * @return {[Printer]} printer [the escpos printer instance]
63
+ */
64
+ Printer.prototype.setCharacterCodeTable = function (codeTable) {
65
+ this.buffer.write(_.ESC);
66
+ this.buffer.write(_.TAB);
67
+ this.buffer.writeUInt8(codeTable);
68
+ return this;
69
+ };
70
+
71
+ /**
72
+ * Fix bottom margin
73
+ * @param {[String]} size
74
+ * @return {[Printer]} printer [the escpos printer instance]
75
+ */
76
+ Printer.prototype.marginBottom = function (size) {
77
+ this.buffer.write(_.MARGINS.BOTTOM);
78
+ this.buffer.writeUInt8(size);
79
+ return this;
80
+ };
81
+
82
+ /**
83
+ * Fix left margin
84
+ * @param {[String]} size
85
+ * @return {[Printer]} printer [the escpos printer instance]
86
+ */
87
+ Printer.prototype.marginLeft = function (size) {
88
+ this.buffer.write(_.MARGINS.LEFT);
89
+ this.buffer.writeUInt8(size);
90
+ return this;
91
+ };
92
+
93
+ /**
94
+ * Fix right margin
95
+ * @param {[String]} size
96
+ * @return {[Printer]} printer [the escpos printer instance]
97
+ */
98
+ Printer.prototype.marginRight = function (size) {
99
+ this.buffer.write(_.MARGINS.RIGHT);
100
+ this.buffer.writeUInt8(size);
101
+ return this;
102
+ };
103
+
104
+ /**
105
+ * [function print]
106
+ * @param {[String]} content [mandatory]
107
+ * @return {[Printer]} printer [the escpos printer instance]
108
+ */
109
+ Printer.prototype.print = function (content) {
110
+ this.buffer.write(content);
111
+ return this;
112
+ };
113
+ /**
114
+ * [function print pure content with End Of Line]
115
+ * @param {[String]} content [mandatory]
116
+ * @return {[Printer]} printer [the escpos printer instance]
117
+ */
118
+ Printer.prototype.println = function (content) {
119
+ return this.print(content + _.EOL);
120
+ };
121
+
122
+ /**
123
+ * [function print pure content with End Of Line]
124
+ * @param {[String]} content [mandatory]
125
+ * @return {[Printer]} printer [the escpos printer instance]
126
+ */
127
+ Printer.prototype.newLine = function () {
128
+ return this.print(_.EOL);
129
+ };
130
+
131
+ /**
132
+ * [function Print encoded alpha-numeric text with End Of Line]
133
+ * @param {[String]} content [mandatory]
134
+ * @param {[String]} encoding [optional]
135
+ * @return {[Printer]} printer [the escpos printer instance]
136
+ */
137
+ Printer.prototype.text = function (content, encoding) {
138
+ return this.print(iconv.encode(content + _.EOL, encoding || this.encoding));
139
+ };
140
+
141
+
142
+ /**
143
+ * [function Print draw line End Of Line]
144
+ * @param {[String]} character [optional]
145
+ * @return {[Printer]} printer [the escpos printer instance]
146
+ */
147
+ Printer.prototype.drawLine = function (character) {
148
+ if (!character) character = '-';
149
+
150
+ for (var i = 0; i < this.width; i++) {
151
+ this.buffer.write(Buffer.from(character));
152
+ }
153
+ this.newLine();
154
+
155
+ return this;
156
+ };
157
+
158
+
159
+
160
+ /**
161
+ * [function Print table with End Of Line]
162
+ * @param {[List]} data [mandatory]
163
+ * @param {[String]} encoding [optional]
164
+ * @return {[Printer]} printer [the escpos printer instance]
165
+ */
166
+ Printer.prototype.table = function (data, encoding) {
167
+
168
+
169
+ var cellWidth = this.width / data.length;
170
+ var lineTxt = "";
171
+
172
+ for (var i = 0; i < data.length; i++) {
173
+
174
+ lineTxt += data[i].toString();
175
+
176
+ var spaces = cellWidth - data[i].toString().length;
177
+ for (var j = 0; j < spaces; j++) {
178
+ lineTxt += " ";
179
+
180
+ }
181
+
182
+ }
183
+ this.buffer.write(iconv.encode(lineTxt + _.EOL, encoding || this.encoding));
184
+
185
+ return this;
186
+
187
+
188
+
189
+ };
190
+
191
+ /**
192
+ * [function Print custom table with End Of Line]
193
+ * @param {[List]} data [mandatory]
194
+ * @param {[String]} encoding [optional]
195
+ * @param {[Array]} size [optional]
196
+ * @return {[Printer]} printer [the escpos printer instance]
197
+ */
198
+ Printer.prototype.tableCustom = function (data, options = {}) {
199
+ options = options || { size: [], encoding: this.encoding }
200
+ let [width = 1, height = 1] = options.size || []
201
+ let baseWidth = Math.floor(this.width / width)
202
+ let cellWidth = Math.floor(baseWidth / data.length)
203
+ let leftoverSpace = baseWidth - cellWidth * data.length // by only data[].width
204
+ let lineStr = ''
205
+ let secondLineEnabled = false
206
+ let secondLine = []
207
+
208
+ for (let i = 0; i < data.length; i++) {
209
+ let obj = data[i]
210
+ let align = (obj.align || '').toUpperCase()
211
+ let tooLong = false
212
+
213
+ obj.text = obj.text.toString()
214
+ let textLength = utils.textLength(obj.text);
215
+
216
+ if (obj.width) {
217
+ cellWidth = baseWidth * obj.width
218
+ } else if (obj.cols) {
219
+ cellWidth = obj.cols / width
220
+ leftoverSpace = 0;
221
+ }
222
+
223
+ if (cellWidth < textLength) {
224
+ tooLong = true
225
+ obj.originalText = obj.text
226
+ obj.text = utils.textSubstring(obj.text, 0, cellWidth)
227
+ }
228
+
229
+ if (align === 'CENTER') {
230
+ let spaces = (cellWidth - textLength) / 2
231
+ for (let s = 0; s < spaces; s++) {
232
+ lineStr += ' '
233
+ }
234
+
235
+ if (obj.text !== '') {
236
+ if (obj.style) {
237
+ lineStr += (
238
+ this._getStyle(obj.style) +
239
+ obj.text +
240
+ this._getStyle("NORMAL")
241
+ )
242
+ } else {
243
+ lineStr += obj.text
244
+ }
245
+ }
246
+
247
+ for (let s = 0; s < spaces - 1; s++) {
248
+ lineStr += ' '
249
+ }
250
+ } else if (align === 'RIGHT') {
251
+ let spaces = cellWidth - textLength
252
+ if (leftoverSpace > 0) {
253
+ spaces += leftoverSpace
254
+ leftoverSpace = 0
255
+ }
256
+
257
+ for (let s = 0; s < spaces; s++) {
258
+ lineStr += ' '
259
+ }
260
+
261
+ if (obj.text !== '') {
262
+ if (obj.style) {
263
+ lineStr += (
264
+ this._getStyle(obj.style) +
265
+ obj.text +
266
+ this._getStyle("NORMAL")
267
+ )
268
+ } else {
269
+ lineStr += obj.text
270
+ }
271
+ }
272
+ } else {
273
+ if (obj.text !== '') {
274
+ if (obj.style) {
275
+ lineStr += (
276
+ this._getStyle(obj.style) +
277
+ obj.text +
278
+ this._getStyle("NORMAL")
279
+ )
280
+ } else {
281
+ lineStr += obj.text
282
+ }
283
+ }
284
+
285
+ let spaces = Math.floor(cellWidth - textLength)
286
+ if (leftoverSpace > 0) {
287
+ spaces += leftoverSpace
288
+ leftoverSpace = 0
289
+ }
290
+
291
+ for (let s = 0; s < spaces; s++) {
292
+ lineStr += ' '
293
+ }
294
+ }
295
+
296
+ if (tooLong) {
297
+ secondLineEnabled = true
298
+ obj.text = utils.textSubstring(obj.originalText, cellWidth)
299
+ secondLine.push(obj)
300
+ } else {
301
+ obj.text = ''
302
+ secondLine.push(obj)
303
+ }
304
+ }
305
+
306
+ // Set size to line
307
+ if (width > 1 || height > 1) {
308
+ lineStr = (
309
+ _.TEXT_FORMAT.TXT_CUSTOM_SIZE(width, height) +
310
+ lineStr +
311
+ _.TEXT_FORMAT.TXT_NORMAL
312
+ )
313
+ }
314
+
315
+ // Write the line
316
+ this.buffer.write(
317
+ iconv.encode(lineStr + _.EOL, options.encoding || this.encoding)
318
+ )
319
+
320
+ if (secondLineEnabled) {
321
+ // Writes second line if has
322
+ return this.tableCustom(secondLine, options)
323
+ } else {
324
+ return this
325
+ }
326
+ }
327
+
328
+
329
+ /**
330
+ * [function Print encoded alpha-numeric text without End Of Line]
331
+ * @param {[String]} content [mandatory]
332
+ * @param {[String]} encoding [optional]
333
+ * @return {[Printer]} printer [the escpos printer instance]
334
+ */
335
+ Printer.prototype.pureText = function (content, encoding) {
336
+ return this.print(iconv.encode(content, encoding || this.encoding));
337
+ };
338
+
339
+ /**
340
+ * [function encode text]
341
+ * @param {[String]} encoding [mandatory]
342
+ * @return {[Printer]} printer [the escpos printer instance]
343
+ */
344
+ Printer.prototype.encode = function (encoding) {
345
+ this.encoding = encoding;
346
+ return this;
347
+ }
348
+
349
+ /**
350
+ * [line feed]
351
+ * @param {[type]} lines [description]
352
+ * @return {[Printer]} printer [the escpos printer instance]
353
+ */
354
+ Printer.prototype.feed = function (n) {
355
+ this.buffer.write(new Array(n || 1).fill(_.EOL).join(''));
356
+ return this;
357
+ };
358
+
359
+ /**
360
+ * [feed control sequences]
361
+ * @param {[type]} ctrl [description]
362
+ * @return {[Printer]} printer [the escpos printer instance]
363
+ */
364
+ Printer.prototype.control = function (ctrl) {
365
+ this.buffer.write(_.FEED_CONTROL_SEQUENCES[
366
+ 'CTL_' + ctrl.toUpperCase()
367
+ ]);
368
+ return this;
369
+ };
370
+ /**
371
+ * [text align]
372
+ * @param {[type]} align [description]
373
+ * @return {[Printer]} printer [the escpos printer instance]
374
+ */
375
+ Printer.prototype.align = function (align) {
376
+ this.buffer.write(_.TEXT_FORMAT[
377
+ 'TXT_ALIGN_' + align.toUpperCase()
378
+ ]);
379
+ return this;
380
+ };
381
+ /**
382
+ * [font family]
383
+ * @param {[type]} family [description]
384
+ * @return {[Printer]} printer [the escpos printer instance]
385
+ */
386
+ Printer.prototype.font = function (family) {
387
+ this.buffer.write(_.TEXT_FORMAT[
388
+ 'TXT_FONT_' + family.toUpperCase()
389
+ ]);
390
+ if (family.toUpperCase() === 'A')
391
+ this.width = this.options && this.options.width || 42;
392
+ else
393
+ this.width = this.options && this.options.width || 56;
394
+ return this;
395
+ };
396
+
397
+ /**
398
+ * [font style]
399
+ * @param {[type]} type [description]
400
+ * @return {[Printer]} printer [the escpos printer instance]
401
+ */
402
+ Printer.prototype._getStyle = function (type) {
403
+ let styled = ''
404
+ switch (type.toUpperCase()) {
405
+ case 'B':
406
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
407
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
408
+ styled += _.TEXT_FORMAT.TXT_UNDERL_OFF
409
+ break
410
+ case 'I':
411
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
412
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
413
+ styled += _.TEXT_FORMAT.TXT_UNDERL_OFF
414
+ break
415
+ case 'U':
416
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
417
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
418
+ styled += _.TEXT_FORMAT.TXT_UNDERL_ON
419
+ break
420
+ case 'U2':
421
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
422
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
423
+ styled += _.TEXT_FORMAT.TXT_UNDERL2_ON
424
+ break
425
+
426
+ case 'BI':
427
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
428
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
429
+ styled += _.TEXT_FORMAT.TXT_UNDERL_OFF
430
+ break
431
+ case 'BIU':
432
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
433
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
434
+ styled += _.TEXT_FORMAT.TXT_UNDERL_ON
435
+ break
436
+ case 'BIU2':
437
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
438
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
439
+ styled += _.TEXT_FORMAT.TXT_UNDERL2_ON
440
+ break
441
+ case 'BU':
442
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
443
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
444
+ styled += _.TEXT_FORMAT.TXT_UNDERL_ON
445
+ break
446
+ case 'BU2':
447
+ styled += _.TEXT_FORMAT.TXT_BOLD_ON
448
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
449
+ styled += _.TEXT_FORMAT.TXT_UNDERL2_ON
450
+ break
451
+ case 'IU':
452
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
453
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
454
+ styled += _.TEXT_FORMAT.TXT_UNDERL_ON
455
+ break
456
+ case 'IU2':
457
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
458
+ styled += _.TEXT_FORMAT.TXT_ITALIC_ON
459
+ styled += _.TEXT_FORMAT.TXT_UNDERL2_ON
460
+ break
461
+
462
+ case 'NORMAL':
463
+ default:
464
+ styled += _.TEXT_FORMAT.TXT_BOLD_OFF
465
+ styled += _.TEXT_FORMAT.TXT_ITALIC_OFF
466
+ styled += _.TEXT_FORMAT.TXT_UNDERL_OFF
467
+ break
468
+ }
469
+ return styled
470
+ }
471
+
472
+ /**
473
+ * [font style]
474
+ * @param {[type]} type [description]
475
+ * @return {[Printer]} printer [the escpos printer instance]
476
+ */
477
+ Printer.prototype.style = function (type) {
478
+ this.buffer.write(this._getStyle(type));
479
+ return this;
480
+ };
481
+
482
+ /**
483
+ * [font size]
484
+ * @param {[String]} width [description]
485
+ * @param {[String]} height [description]
486
+ * @return {[Printer]} printer [the escpos printer instance]
487
+ */
488
+ Printer.prototype.size = function (width, height) {
489
+
490
+ this.buffer.write(_.TEXT_FORMAT.TXT_CUSTOM_SIZE(width, height));
491
+
492
+ return this;
493
+ };
494
+
495
+ /**
496
+ * [set character spacing]
497
+ * @param {[type]} n [description]
498
+ * @return {[Printer]} printer [the escpos printer instance]
499
+ */
500
+ Printer.prototype.spacing = function (n) {
501
+ if (n === undefined || n === null) {
502
+ this.buffer.write(_.CHARACTER_SPACING.CS_DEFAULT);
503
+ } else {
504
+ this.buffer.write(_.CHARACTER_SPACING.CS_SET);
505
+ this.buffer.writeUInt8(n);
506
+ }
507
+ return this;
508
+ }
509
+
510
+ /**
511
+ * [set line spacing]
512
+ * @param {[type]} n [description]
513
+ * @return {[Printer]} printer [the escpos printer instance]
514
+ */
515
+ Printer.prototype.lineSpace = function (n) {
516
+ if (n === undefined || n === null) {
517
+ this.buffer.write(_.LINE_SPACING.LS_DEFAULT);
518
+ } else {
519
+ this.buffer.write(_.LINE_SPACING.LS_SET);
520
+ this.buffer.writeUInt8(n);
521
+ }
522
+ return this;
523
+ };
524
+
525
+ /**
526
+ * [hardware]
527
+ * @param {[type]} hw [description]
528
+ * @return {[Printer]} printer [the escpos printer instance]
529
+ */
530
+ Printer.prototype.hardware = function (hw) {
531
+ this.buffer.write(_.HARDWARE['HW_' + hw.toUpperCase()]);
532
+ return this;
533
+ };
534
+ /**
535
+ * [barcode]
536
+ * @param {[type]} code [description]
537
+ * @param {[type]} type [description]
538
+ * @param {[type]} options [description]
539
+ * @return {[Printer]} printer [the escpos printer instance]
540
+ */
541
+ Printer.prototype.barcode = function (code, type, options) {
542
+ options = options || {};
543
+ var width, height, position, font, includeParity;
544
+ // Backward compatibility
545
+ width = arguments[2];
546
+ if (typeof width === 'string' || typeof width === 'number') {
547
+ width = arguments[2];
548
+ height = arguments[3];
549
+ position = arguments[4];
550
+ font = arguments[5];
551
+ } else {
552
+ width = options.width;
553
+ height = options.height;
554
+ position = options.position;
555
+ font = options.font;
556
+ includeParity = options.includeParity !== false; // true by default
557
+ }
558
+
559
+ type = type || 'EAN13'; // default type is EAN13, may a good choice ?
560
+ var convertCode = String(code), parityBit = '', codeLength = '';
561
+ if (typeof type === 'undefined' || type === null) {
562
+ throw new TypeError('barcode type is required');
563
+ }
564
+ if (type === 'EAN13' && convertCode.length !== 12) {
565
+ throw new Error('EAN13 Barcode type requires code length 12');
566
+ }
567
+ if (type === 'EAN8' && convertCode.length !== 7) {
568
+ throw new Error('EAN8 Barcode type requires code length 7');
569
+ }
570
+ if (this._model === 'qsprinter') {
571
+ this.buffer.write(_.MODEL.QSPRINTER.BARCODE_MODE.ON);
572
+ }
573
+ if (this._model === 'qsprinter') {
574
+ // qsprinter has no BARCODE_WIDTH command (as of v7.5)
575
+ } else if (width >= 1 && width <= 5) {
576
+ this.buffer.write(_.BARCODE_FORMAT.BARCODE_WIDTH[width]);
577
+ } else {
578
+ this.buffer.write(_.BARCODE_FORMAT.BARCODE_WIDTH_DEFAULT);
579
+ }
580
+ if (height >= 1 && height <= 255) {
581
+ this.buffer.write(_.BARCODE_FORMAT.BARCODE_HEIGHT(height));
582
+ } else {
583
+ if (this._model === 'qsprinter') {
584
+ this.buffer.write(_.MODEL.QSPRINTER.BARCODE_HEIGHT_DEFAULT);
585
+ } else {
586
+ this.buffer.write(_.BARCODE_FORMAT.BARCODE_HEIGHT_DEFAULT);
587
+ }
588
+ }
589
+ if (this._model === 'qsprinter') {
590
+ // Qsprinter has no barcode font
591
+ } else {
592
+ this.buffer.write(_.BARCODE_FORMAT[
593
+ 'BARCODE_FONT_' + (font || 'A').toUpperCase()
594
+ ]);
595
+ }
596
+ this.buffer.write(_.BARCODE_FORMAT[
597
+ 'BARCODE_TXT_' + (position || 'BLW').toUpperCase()
598
+ ]);
599
+ this.buffer.write(_.BARCODE_FORMAT[
600
+ 'BARCODE_' + ((type || 'EAN13').replace('-', '_').toUpperCase())
601
+ ]);
602
+ if (includeParity) {
603
+ if (type === 'EAN13' || type === 'EAN8') {
604
+ parityBit = utils.getParityBit(code);
605
+ }
606
+ }
607
+ if (type == 'CODE128' || type == 'CODE93') {
608
+ codeLength = utils.codeLength(code);
609
+ }
610
+ this.buffer.write(codeLength + code + (includeParity ? parityBit : '') + '\x00'); // Allow to skip the parity byte
611
+ if (this._model === 'qsprinter') {
612
+ this.buffer.write(_.MODEL.QSPRINTER.BARCODE_MODE.OFF);
613
+ }
614
+ return this;
615
+ };
616
+
617
+ /**
618
+ * [print qrcode]
619
+ * @param {[type]} code [description]
620
+ * @param {[type]} version [description]
621
+ * @param {[type]} level [description]
622
+ * @param {[type]} size [description]
623
+ * @return {[Printer]} printer [the escpos printer instance]
624
+ */
625
+ Printer.prototype.qrcode = function (code, version, level, size) {
626
+ if (this._model !== 'qsprinter') {
627
+ this.buffer.write(_.CODE2D_FORMAT.TYPE_QR);
628
+ this.buffer.write(_.CODE2D_FORMAT.CODE2D);
629
+ this.buffer.writeUInt8(version || 3);
630
+ this.buffer.write(_.CODE2D_FORMAT[
631
+ 'QR_LEVEL_' + (level || 'L').toUpperCase()
632
+ ]);
633
+ this.buffer.writeUInt8(size || 6);
634
+ this.buffer.writeUInt16LE(code.length);
635
+ this.buffer.write(code);
636
+ } else {
637
+ const dataRaw = iconv.encode(code, 'utf8');
638
+ if (dataRaw.length < 1 && dataRaw.length > 2710) {
639
+ throw new Error('Invalid code length in byte. Must be between 1 and 2710');
640
+ }
641
+
642
+ // Set pixel size
643
+ if (!size || (size && typeof size !== 'number'))
644
+ size = _.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.DEFAULT;
645
+ else if (size && size < _.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.MIN)
646
+ size = _.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.MIN;
647
+ else if (size && size > _.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.MAX)
648
+ size = _.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.MAX;
649
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.PIXEL_SIZE.CMD);
650
+ this.buffer.writeUInt8(size);
651
+
652
+ // Set version
653
+ if (!version || (version && typeof version !== 'number'))
654
+ version = _.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.DEFAULT;
655
+ else if (version && version < _.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.MIN)
656
+ version = _.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.MIN;
657
+ else if (version && version > _.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.MAX)
658
+ version = _.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.MAX;
659
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.VERSION.CMD);
660
+ this.buffer.writeUInt8(version);
661
+
662
+ // Set level
663
+ if (!level || (level && typeof level !== 'string'))
664
+ level = _.CODE2D_FORMAT.QR_LEVEL_L;
665
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.LEVEL.CMD);
666
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.LEVEL.OPTIONS[level.toUpperCase()]);
667
+
668
+ // Transfer data(code) to buffer
669
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.SAVEBUF.CMD_P1);
670
+ this.buffer.writeUInt16LE(dataRaw.length + _.MODEL.QSPRINTER.CODE2D_FORMAT.LEN_OFFSET);
671
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.SAVEBUF.CMD_P2);
672
+ this.buffer.write(dataRaw);
673
+
674
+ // Print from buffer
675
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.PRINTBUF.CMD_P1);
676
+ this.buffer.writeUInt16LE(dataRaw.length + _.MODEL.QSPRINTER.CODE2D_FORMAT.LEN_OFFSET);
677
+ this.buffer.write(_.MODEL.QSPRINTER.CODE2D_FORMAT.PRINTBUF.CMD_P2);
678
+ }
679
+ return this;
680
+ };
681
+
682
+ /**
683
+ * [print qrcode image]
684
+ * @param {[type]} content [description]
685
+ * @param {[type]} options [description]
686
+ * @param {[Function]} callback [description]
687
+ * @return {[Printer]} printer [the escpos printer instance]
688
+ */
689
+ Printer.prototype.qrimage = function (content, options, callback) {
690
+ var self = this;
691
+ if (typeof options == 'function') {
692
+ callback = options;
693
+ options = null;
694
+ }
695
+ options = options || { type: 'png', mode: 'dhdw' };
696
+ var buffer = qr.imageSync(content, options);
697
+ var type = ['image', options.type].join('/');
698
+ getPixels(buffer, type, function (err, pixels) {
699
+ if (err) return callback && callback(err);
700
+ self.raster(new Image(pixels), options.mode);
701
+ callback && callback.call(self, null, self);
702
+ });
703
+ return this;
704
+ };
705
+
706
+ /**
707
+ * [image description]
708
+ * @param {[type]} image [description]
709
+ * @param {[type]} density [description]
710
+ * @return {[Printer]} printer [the escpos printer instance]
711
+ */
712
+ Printer.prototype.image = async function (image, density) {
713
+ if (!(image instanceof Image))
714
+ throw new TypeError('Only escpos.Image supported');
715
+ density = density || 'd24';
716
+ var n = !!~['d8', 's8'].indexOf(density) ? 1 : 3;
717
+ var header = _.BITMAP_FORMAT['BITMAP_' + density.toUpperCase()];
718
+ var bitmap = image.toBitmap(n * 8);
719
+ var self = this;
720
+
721
+ // added a delay so the printer can process the graphical data
722
+ // when connected via slower connection ( e.g.: Serial)
723
+ this.lineSpace(0); // set line spacing to 0
724
+ bitmap.data.forEach(async (line) => {
725
+ self.buffer.write(header);
726
+ self.buffer.writeUInt16LE(line.length / n);
727
+ self.buffer.write(line);
728
+ self.buffer.write(_.EOL);
729
+ await new Promise((resolve, reject) => {
730
+ setTimeout(() => { resolve(true) }, 200);
731
+ });
732
+ });
733
+ return this.lineSpace();
734
+ };
735
+
736
+ /**
737
+ * [raster description]
738
+ * @param {[type]} image [description]
739
+ * @param {[type]} mode [description]
740
+ * @return {[Printer]} printer [the escpos printer instance]
741
+ */
742
+ Printer.prototype.raster = function (image, mode) {
743
+ if (!(image instanceof Image))
744
+ throw new TypeError('Only escpos.Image supported');
745
+ mode = mode || 'normal';
746
+ if (mode === 'dhdw' ||
747
+ mode === 'dwh' ||
748
+ mode === 'dhw') mode = 'dwdh';
749
+ var raster = image.toRaster();
750
+ var header = _.GSV0_FORMAT['GSV0_' + mode.toUpperCase()];
751
+ this.buffer.write(header);
752
+ this.buffer.writeUInt16LE(raster.width);
753
+ this.buffer.writeUInt16LE(raster.height);
754
+ this.buffer.write(raster.data);
755
+ return this;
756
+ };
757
+
758
+ /**
759
+ * [function Send pulse to kick the cash drawer]
760
+ * @param {[type]} pin [description]
761
+ * @return {[Printer]} printer [the escpos printer instance]
762
+ */
763
+ Printer.prototype.cashdraw = function (pin) {
764
+ this.buffer.write(_.CASH_DRAWER[
765
+ 'CD_KICK_' + (pin || 2)
766
+ ]);
767
+ return this;
768
+ };
769
+
770
+ /**
771
+ * Printer Buzzer (Beep sound)
772
+ * @param {[Number]} n Refers to the number of buzzer times
773
+ * @param {[Number]} t Refers to the buzzer sound length in (t * 100) milliseconds.
774
+ */
775
+ Printer.prototype.beep = function (n, t) {
776
+ this.buffer.write(_.BEEP);
777
+ this.buffer.writeUInt8(n);
778
+ this.buffer.writeUInt8(t);
779
+ return this;
780
+ };
781
+
782
+ /**
783
+ * Send data to hardware and flush buffer
784
+ * @param {Function} callback
785
+ * @return {[Printer]} printer [the escpos printer instance]
786
+ */
787
+ Printer.prototype.flush = function (callback) {
788
+ var buf = this.buffer.flush();
789
+ this.adapter.write(buf, callback);
790
+ return this;
791
+ };
792
+
793
+ /**
794
+ * [function Cut paper]
795
+ * @param {[type]} part [description]
796
+ * @return {[Printer]} printer [the escpos printer instance]
797
+ */
798
+ Printer.prototype.cut = function (part, feed) {
799
+ this.feed(feed || 3);
800
+ this.buffer.write(_.PAPER[
801
+ part ? 'PAPER_PART_CUT' : 'PAPER_FULL_CUT'
802
+ ]);
803
+ return this;
804
+ };
805
+
806
+ /**
807
+ * [close description]
808
+ * @param {Function} callback [description]
809
+ * @param {[type]} options [description]
810
+ * @return {[type]} [description]
811
+ */
812
+ Printer.prototype.close = function (callback, options) {
813
+ var self = this;
814
+ return this.flush(function () {
815
+ self.adapter.close(callback, options);
816
+ });
817
+ };
818
+
819
+ /**
820
+ * [color select between two print color modes, if your printer supports it]
821
+ * @param {Number} color - 0 for primary color (black) 1 for secondary color (red)
822
+ * @return {[Printer]} printer [the escpos printer instance]
823
+ */
824
+ Printer.prototype.color = function (color) {
825
+ this.buffer.write(_.COLOR[
826
+ color === 0 || color === 1 ? color : 0
827
+ ]);
828
+ return this;
829
+ };
830
+
831
+ /**
832
+ * [reverse colors, if your printer supports it]
833
+ * @param {Boolean} bool - True for reverse, false otherwise
834
+ * @return {[Printer]} printer [the escpos printer instance]
835
+ */
836
+ Printer.prototype.setReverseColors = function (bool) {
837
+ this.buffer.write(bool ? _.COLOR.REVERSE : _.COLOR.UNREVERSE);
838
+ return this;
839
+ };
840
+
841
+
842
+ /**
843
+ * [writes a low level command to the printer buffer]
844
+ *
845
+ * @usage
846
+ * 1) raw('1d:77:06:1d:6b:02:32:32:30:30:30:30:32:30:30:30:35:30:35:00:0a')
847
+ * 2) raw('1d 77 06 1d 6b 02 32 32 30 30 30 30 32 30 30 30 35 30 35 00 0a')
848
+ * 3) raw(Buffer.from('1d77061d6b0232323030303032303030353035000a','hex'))
849
+ *
850
+ * @param data {Buffer|string}
851
+ * @returns {Printer}
852
+ */
853
+ Printer.prototype.raw = function raw(data) {
854
+ if (Buffer.isBuffer(data)) {
855
+ this.buffer.write(data);
856
+ } else if (typeof data === 'string') {
857
+ data = data.toLowerCase();
858
+ this.buffer.write(Buffer.from(data.replace(/(\s|:)/g, ''), 'hex'));
859
+ }
860
+ return this;
861
+ };
862
+
863
+
864
+ /**
865
+ * get one specific status from the printer
866
+ * @param {string} statusClassName
867
+ * @param {Function} callback
868
+ * @return {Printer}
869
+ */
870
+ Printer.prototype.getStatus = function(statusClassName, callback) {
871
+ this.adapter.read(data => {
872
+ let byte;
873
+ try {
874
+ byte = data.readInt8(0);
875
+ } catch (error) {
876
+ //console.log("XSSSSS ", error)
877
+ this.adapter.close();
878
+ }
879
+ if (byte) {
880
+ const status = new statuses[statusClassName](byte);
881
+
882
+ callback(status);
883
+ } else {
884
+ const status = null;
885
+ callback(status)
886
+ }
887
+ })
888
+
889
+ statuses[statusClassName].commands().forEach((c) => {
890
+ this.buffer.write(c);
891
+ });
892
+
893
+ return this;
894
+ }
895
+
896
+ /**
897
+ * get statuses from the printer
898
+ * @param {Function} callback
899
+ * @return {Printer}
900
+ */
901
+ Printer.prototype.getStatuses = function(callback) {
902
+ let buffer = [];
903
+ this.adapter.read(data => {
904
+ for (let i = 0; i < data.byteLength; i++) {
905
+ buffer.push(data.readInt8(i));
906
+ }
907
+
908
+ if (buffer.length < 4) {
909
+ return;
910
+ }
911
+
912
+ let statuses = [];
913
+ for (let i = 0; i < buffer.length; i++) {
914
+ let byte = buffer[i];
915
+ switch (i) {
916
+ case 0:
917
+ statuses.push(new PrinterStatus(byte));
918
+ break;
919
+ case 1:
920
+ statuses.push(new RollPaperSensorStatus(byte));
921
+ break;
922
+ case 2:
923
+ statuses.push(new OfflineCauseStatus(byte));
924
+ break;
925
+ case 3 :
926
+ statuses.push(new ErrorCauseStatus(byte));
927
+ break;
928
+ }
929
+ }
930
+
931
+ buffer = [];
932
+ callback(statuses);
933
+ })
934
+
935
+ PrinterStatus.commands().forEach((c) => {
936
+ this.adapter.write(c);
937
+ });
938
+
939
+ RollPaperSensorStatus.commands().forEach((c) => {
940
+ this.adapter.write(c);
941
+ });
942
+
943
+ OfflineCauseStatus.commands().forEach((c) => {
944
+ this.adapter.write(c);
945
+ });
946
+
947
+ ErrorCauseStatus.commands().forEach((c) => {
948
+ this.adapter.write(c);
949
+ });
950
+
951
+ return this;
952
+ }
953
+
954
+
955
+ /**
956
+ * Printer Supports
957
+ */
958
+ Printer.Printer = Printer;
959
+ Printer.Image = require('./image');
960
+ Printer.command = require('./commands');
961
+ Printer.Printer2 = require('./promisify');
962
+
963
+ /**
964
+ * [exports description]
965
+ * @type {[type]}
966
+ */
967
+ module.exports = Printer;