@thermal-print/escpos 0.1.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/LICENSE +21 -0
- package/README.md +193 -0
- package/dist/command-adapters/escbematech-adapter.d.ts +30 -0
- package/dist/command-adapters/escbematech-adapter.d.ts.map +1 -0
- package/dist/command-adapters/escbematech-adapter.js +175 -0
- package/dist/command-adapters/escpos-adapter.d.ts +25 -0
- package/dist/command-adapters/escpos-adapter.d.ts.map +1 -0
- package/dist/command-adapters/escpos-adapter.js +144 -0
- package/dist/command-adapters/index.d.ts +11 -0
- package/dist/command-adapters/index.d.ts.map +1 -0
- package/dist/command-adapters/index.js +14 -0
- package/dist/command-adapters/types.d.ts +78 -0
- package/dist/command-adapters/types.d.ts.map +1 -0
- package/dist/command-adapters/types.js +8 -0
- package/dist/commands/escbematech.d.ts +867 -0
- package/dist/commands/escbematech.d.ts.map +1 -0
- package/dist/commands/escbematech.js +1387 -0
- package/dist/commands/escpos.d.ts +582 -0
- package/dist/commands/escpos.d.ts.map +1 -0
- package/dist/commands/escpos.js +1048 -0
- package/dist/converter.d.ts +47 -0
- package/dist/converter.d.ts.map +1 -0
- package/dist/converter.js +92 -0
- package/dist/encodings/cp860.d.ts +25 -0
- package/dist/encodings/cp860.d.ts.map +1 -0
- package/dist/encodings/cp860.js +187 -0
- package/dist/generator.d.ts +118 -0
- package/dist/generator.d.ts.map +1 -0
- package/dist/generator.js +383 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/styles.d.ts +72 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +210 -0
- package/dist/traverser.d.ts +60 -0
- package/dist/traverser.d.ts.map +1 -0
- package/dist/traverser.js +285 -0
- package/dist/types.d.ts +21 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/package.json +31 -0
|
@@ -0,0 +1,1387 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ESC/Bematech Command Set
|
|
4
|
+
*
|
|
5
|
+
* Command bytes for Bematech MP-4200 TH thermal printer using ESC/Bematech protocol.
|
|
6
|
+
* Reference: Bematech MP-4200 TH Programmer's Manual - Revision 1.0, Chapter 3
|
|
7
|
+
*
|
|
8
|
+
* This file contains all documented ESC/Bematech commands organized by category.
|
|
9
|
+
* Commands follow the Bematech-specific implementation which differs from standard ESC/POS.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.PrinterLanguage = exports.setPrintingIntensityAlt = exports.setPrintingIntensity = exports.setPrinterMode = exports.PrinterMode = exports.selectDrawerSensor = exports.selectPaperSensor = exports.disablePaperNearEndSensor = exports.enablePaperNearEndSensor = exports.setPaperWidth = exports.PaperWidth = exports.printUnicodeSet = exports.PRINT_UNICODE_SETS = exports.setInternationalCharset = exports.setIdeogramMode = exports.setDefaultCodePage = exports.setCodePage = exports.CodePage = exports.GET_CURRENT_MODE = exports.returnToPreviousMode = exports.selectESCPOSModeTemp = exports.selectESCBemaModeTemp = exports.selectESCPOSMode = exports.selectESCBemaMode = exports.INIT = exports.DEL = exports.GS = exports.FS = exports.ESC = exports.CAN = exports.ETB = exports.SYN = exports.NAK = exports.DC4 = exports.DC2 = exports.SI = exports.SO = exports.CR = exports.FF = exports.LF = exports.HT = exports.BS = exports.BEL = exports.ACK = exports.ENQ = exports.EOT = exports.ETX = exports.STX = exports.SOH = exports.NUL = void 0;
|
|
13
|
+
exports.DOUBLE_HEIGHT_ONLINE = exports.DOUBLE_HEIGHT_OFF = exports.DOUBLE_HEIGHT_ON = exports.calculatePrintMode = exports.SCRIPT_OFF = exports.SUBSCRIPT_ON = exports.SUPERSCRIPT_ON = exports.UPSIDE_DOWN_OFF = exports.UPSIDE_DOWN_ON = exports.ITALIC_OFF = exports.ITALIC_ON = exports.UNDERLINE_OFF = exports.UNDERLINE_ON = exports.BOLD_OFF = exports.BOLD_ON = exports.ALIGN_RIGHT = exports.ALIGN_CENTER = exports.ALIGN_LEFT = exports.CLEAR_TABS = exports.setTabPositions = exports.TAB = exports.setLeftMargin = exports.setRightMargin = exports.disableAutoLineFeed = exports.enableAutoLineFeed = exports.setPageSizeMM = exports.setPageSizeLines = exports.horizontalSkip = exports.verticalSkip = exports.setLineSpacing = exports.SET_LINE_HEIGHT_DEFAULT = exports.feedPaper = exports.fineFeed = exports.FEED_PAGE = exports.FEED_LINE = exports.activateBuzzer = exports.disableBuzzerOnCut = exports.setBuzzerOnCut = exports.CUT_FULL_ALT = exports.CUT_FULL = exports.activateDrawer2 = exports.activateDrawer1 = exports.ENABLE_DUMP_MODE = exports.disablePanelKeys = exports.enablePanelKeys = exports.RESET_PRINTER = exports.PRINT_CONFIG = exports.LOAD_DEFAULT_CONFIG = exports.getPrinterInfo = exports.setPrinterLanguage = void 0;
|
|
14
|
+
exports.CLEAR_BUFFER = exports.EXTENDED_STATUS = exports.STATUS_ENQUIRY = exports.printBarcodePLESSEYAlt = exports.printBarcodePLESSEY = exports.printBarcodeMSIAlt = exports.printBarcodeMSI = exports.printBarcodeISBN = exports.printBarcodePDF417 = exports.printBarcodeCODE128 = exports.printBarcodeCODE93 = exports.printBarcodeCODABARAlt = exports.printBarcodeCODABAR = exports.printBarcodeITFAlt = exports.printBarcodeITF = exports.printBarcodeCODE39Alt = exports.printBarcodeCODE39 = exports.printBarcodeEAN8Alt = exports.printBarcodeEAN8 = exports.printBarcodeEAN13Alt = exports.printBarcodeEAN13 = exports.printBarcodeUPCEAlt = exports.printBarcodeUPCE = exports.printBarcodeUPCAAlt = exports.printBarcodeUPCA = exports.setBarcodeLeftMargin = exports.setBarcodeHRIFont = exports.setBarcodeHRI = exports.BarcodeHRIPosition = exports.setBarcodeWidth = exports.setBarcodeHeight = exports.printNVBitImage = exports.defineNVBitImage = exports.printDownloadedBitImage = exports.defineDownloadedBitImage = exports.printRasterBitmap = exports.RasterMode = exports.print8BitGraphics = exports.print24BitGraphics = exports.fillBlankColumns = exports.CONDENSED_OFF_DC2 = exports.CONDENSED_OFF_ALT = exports.CONDENSED_OFF = exports.CONDENSED_ON_ALT = exports.CONDENSED_ON = exports.EXPANDED_OFF = exports.EXPANDED_ONLINE_ALT = exports.EXPANDED_ONLINE = exports.DOUBLE_WIDTH_OFF = exports.DOUBLE_WIDTH_ON = void 0;
|
|
15
|
+
exports.validateBarcodeData = exports.encodeText = exports.setWiFi = exports.setSNMP = exports.disableDHCP = exports.enableDHCP = exports.setGateway = exports.setIPAddress = exports.CANCEL_CHAR = exports.CANCEL_LINE = exports.END_BUFFER = void 0;
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// CONTROL CHARACTERS
|
|
18
|
+
// ============================================================================
|
|
19
|
+
exports.NUL = 0x00; // Null
|
|
20
|
+
exports.SOH = 0x01; // Start of Heading
|
|
21
|
+
exports.STX = 0x02; // Start of Text - Clear buffer
|
|
22
|
+
exports.ETX = 0x03; // End of Text - End buffer
|
|
23
|
+
exports.EOT = 0x04; // End of Transmission
|
|
24
|
+
exports.ENQ = 0x05; // Enquiry - Printer status
|
|
25
|
+
exports.ACK = 0x06; // Acknowledge
|
|
26
|
+
exports.BEL = 0x07; // Bell
|
|
27
|
+
exports.BS = 0x08; // Backspace
|
|
28
|
+
exports.HT = 0x09; // Horizontal Tab
|
|
29
|
+
exports.LF = 0x0a; // Line Feed
|
|
30
|
+
exports.FF = 0x0c; // Form Feed
|
|
31
|
+
exports.CR = 0x0d; // Carriage Return
|
|
32
|
+
exports.SO = 0x0e; // Shift Out - Enable on-line expanded mode
|
|
33
|
+
exports.SI = 0x0f; // Shift In - Enable condensed mode
|
|
34
|
+
exports.DC2 = 0x12; // Device Control 2 - Disable condensed mode
|
|
35
|
+
exports.DC4 = 0x14; // Device Control 4 - Disable on-line expanded print
|
|
36
|
+
exports.NAK = 0x15; // Negative Acknowledge
|
|
37
|
+
exports.SYN = 0x16; // Synchronous Idle
|
|
38
|
+
exports.ETB = 0x17; // End of Transmission Block
|
|
39
|
+
exports.CAN = 0x18; // Cancel - Cancel last line
|
|
40
|
+
exports.ESC = 0x1b; // Escape
|
|
41
|
+
exports.FS = 0x1c; // File Separator
|
|
42
|
+
exports.GS = 0x1d; // Group Separator
|
|
43
|
+
exports.DEL = 0x7f; // Delete - Cancel last character
|
|
44
|
+
// ============================================================================
|
|
45
|
+
// INITIALIZATION & CONFIGURATION
|
|
46
|
+
// ============================================================================
|
|
47
|
+
/**
|
|
48
|
+
* ESC @ - Initialize printer to default settings
|
|
49
|
+
* Hexadecimal: 1B 40
|
|
50
|
+
* Decimal: 27 64
|
|
51
|
+
*
|
|
52
|
+
* Cancels all printer settings including character font, line spacing,
|
|
53
|
+
* margins, and returns printer to initial state.
|
|
54
|
+
*/
|
|
55
|
+
exports.INIT = [exports.ESC, 0x40];
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// MODE SELECTION
|
|
58
|
+
// ============================================================================
|
|
59
|
+
/**
|
|
60
|
+
* GS F9h 5 n - Select printer operating mode (permanent)
|
|
61
|
+
* Saves to non-volatile memory
|
|
62
|
+
* n = 0 or 48: ESC/Bema mode
|
|
63
|
+
* n = 1 or 49: ESC/POS mode
|
|
64
|
+
*/
|
|
65
|
+
const selectESCBemaMode = () => [exports.GS, 0xF9, 0x35, 0x00];
|
|
66
|
+
exports.selectESCBemaMode = selectESCBemaMode;
|
|
67
|
+
const selectESCPOSMode = () => [exports.GS, 0xF9, 0x35, 0x01];
|
|
68
|
+
exports.selectESCPOSMode = selectESCPOSMode;
|
|
69
|
+
/**
|
|
70
|
+
* GS F9h SP n - Select printer operating mode temporarily
|
|
71
|
+
* Does NOT save to memory
|
|
72
|
+
* n = 0 or 48: ESC/Bema mode
|
|
73
|
+
* n = 1 or 49: ESC/POS mode
|
|
74
|
+
*/
|
|
75
|
+
const selectESCBemaModeTemp = () => [exports.GS, 0xF9, 0x20, 0x00];
|
|
76
|
+
exports.selectESCBemaModeTemp = selectESCBemaModeTemp;
|
|
77
|
+
const selectESCPOSModeTemp = () => [exports.GS, 0xF9, 0x20, 0x01];
|
|
78
|
+
exports.selectESCPOSModeTemp = selectESCPOSModeTemp;
|
|
79
|
+
/**
|
|
80
|
+
* GS F9h 1Fh 1 - Return to previously set mode
|
|
81
|
+
* Hexadecimal: 1D F9 1F 31
|
|
82
|
+
*/
|
|
83
|
+
const returnToPreviousMode = () => [exports.GS, 0xF9, 0x1F, 0x31];
|
|
84
|
+
exports.returnToPreviousMode = returnToPreviousMode;
|
|
85
|
+
/**
|
|
86
|
+
* GS F9h C 00h - Get printer current command set
|
|
87
|
+
* Returns: 0 = ESC/Bema, 1 = ESC/POS
|
|
88
|
+
*/
|
|
89
|
+
exports.GET_CURRENT_MODE = [exports.GS, 0xF9, 0x43, 0x00];
|
|
90
|
+
// ============================================================================
|
|
91
|
+
// CODE PAGES & CHARACTER ENCODING
|
|
92
|
+
// ============================================================================
|
|
93
|
+
/**
|
|
94
|
+
* Code page identifiers
|
|
95
|
+
*/
|
|
96
|
+
var CodePage;
|
|
97
|
+
(function (CodePage) {
|
|
98
|
+
CodePage[CodePage["CP850"] = 2] = "CP850";
|
|
99
|
+
CodePage[CodePage["CP437"] = 3] = "CP437";
|
|
100
|
+
CodePage[CodePage["CP860"] = 4] = "CP860";
|
|
101
|
+
CodePage[CodePage["CP858"] = 5] = "CP858";
|
|
102
|
+
CodePage[CodePage["CP866"] = 6] = "CP866";
|
|
103
|
+
CodePage[CodePage["CP864"] = 7] = "CP864";
|
|
104
|
+
CodePage[CodePage["UTF8"] = 8] = "UTF8";
|
|
105
|
+
CodePage[CodePage["BIG5E"] = 9] = "BIG5E";
|
|
106
|
+
CodePage[CodePage["JIS"] = 10] = "JIS";
|
|
107
|
+
CodePage[CodePage["SHIFT_JIS"] = 11] = "SHIFT_JIS";
|
|
108
|
+
CodePage[CodePage["GB2312"] = 12] = "GB2312";
|
|
109
|
+
CodePage[CodePage["EUC_CN"] = 14] = "EUC_CN";
|
|
110
|
+
CodePage[CodePage["CP862"] = 21] = "CP862"; // CODEPAGE 862 (15h)
|
|
111
|
+
})(CodePage || (exports.CodePage = CodePage = {}));
|
|
112
|
+
/**
|
|
113
|
+
* ESC t n - Select code page
|
|
114
|
+
* Hexadecimal: 1B 74 n
|
|
115
|
+
* Default: CP850
|
|
116
|
+
*/
|
|
117
|
+
const setCodePage = (codePage) => [exports.ESC, 0x74, codePage];
|
|
118
|
+
exports.setCodePage = setCodePage;
|
|
119
|
+
/**
|
|
120
|
+
* GS F9h 7 n - Set and save printer default code page
|
|
121
|
+
* Saves to non-volatile memory
|
|
122
|
+
*/
|
|
123
|
+
const setDefaultCodePage = (codePage) => [exports.GS, 0xF9, 0x37, codePage];
|
|
124
|
+
exports.setDefaultCodePage = setDefaultCodePage;
|
|
125
|
+
/**
|
|
126
|
+
* GS F9h 8 n - Set and save ESC/POS ideogram mode
|
|
127
|
+
* n = 0: UTF8 (Unicode)
|
|
128
|
+
* n = 1: ESC/POS Japanese
|
|
129
|
+
* n = 2: ESC/POS Simplified Chinese
|
|
130
|
+
* n = 3: ESC/POS Traditional Chinese
|
|
131
|
+
*/
|
|
132
|
+
const setIdeogramMode = (mode) => [exports.GS, 0xF9, 0x38, mode];
|
|
133
|
+
exports.setIdeogramMode = setIdeogramMode;
|
|
134
|
+
/**
|
|
135
|
+
* ESC R n - Select international character set
|
|
136
|
+
* n = 0: CODEPAGE 437
|
|
137
|
+
* n = 1-11: CODEPAGE 858
|
|
138
|
+
* n = 12: CODEPAGE 850 (default)
|
|
139
|
+
*/
|
|
140
|
+
const setInternationalCharset = (n) => {
|
|
141
|
+
if (n < 0 || n > 12)
|
|
142
|
+
n = 12;
|
|
143
|
+
return [exports.ESC, 0x52, n];
|
|
144
|
+
};
|
|
145
|
+
exports.setInternationalCharset = setInternationalCharset;
|
|
146
|
+
/**
|
|
147
|
+
* ESC Z - Print supported Unicode sets
|
|
148
|
+
* Prints a chart showing all supported Unicode character sets
|
|
149
|
+
*/
|
|
150
|
+
exports.PRINT_UNICODE_SETS = [exports.ESC, 0x5A];
|
|
151
|
+
/**
|
|
152
|
+
* ESC [ n - Print specific Unicode set
|
|
153
|
+
* Range: 0 ≤ n ≤ 255
|
|
154
|
+
*/
|
|
155
|
+
const printUnicodeSet = (n) => [exports.ESC, 0x5B, Math.max(0, Math.min(255, n))];
|
|
156
|
+
exports.printUnicodeSet = printUnicodeSet;
|
|
157
|
+
// ============================================================================
|
|
158
|
+
// PAPER CONFIGURATION
|
|
159
|
+
// ============================================================================
|
|
160
|
+
/**
|
|
161
|
+
* Paper width presets (ESC/Bema mode only)
|
|
162
|
+
* Format: [paper width in mm, printing width in mm]
|
|
163
|
+
*/
|
|
164
|
+
var PaperWidth;
|
|
165
|
+
(function (PaperWidth) {
|
|
166
|
+
PaperWidth[PaperWidth["WIDTH_58_48"] = 0] = "WIDTH_58_48";
|
|
167
|
+
PaperWidth[PaperWidth["WIDTH_76_72"] = 1] = "WIDTH_76_72";
|
|
168
|
+
PaperWidth[PaperWidth["WIDTH_80_72"] = 2] = "WIDTH_80_72";
|
|
169
|
+
PaperWidth[PaperWidth["WIDTH_80_76"] = 3] = "WIDTH_80_76";
|
|
170
|
+
PaperWidth[PaperWidth["WIDTH_82_72"] = 4] = "WIDTH_82_72";
|
|
171
|
+
PaperWidth[PaperWidth["WIDTH_82_76"] = 5] = "WIDTH_82_76";
|
|
172
|
+
PaperWidth[PaperWidth["WIDTH_82_80"] = 6] = "WIDTH_82_80"; // 82.5mm paper, 80mm print width
|
|
173
|
+
})(PaperWidth || (exports.PaperWidth = PaperWidth = {}));
|
|
174
|
+
/**
|
|
175
|
+
* GS F9h ! n - Set and save paper width
|
|
176
|
+
* Only effective in ESC/Bema mode
|
|
177
|
+
* In ESC/POS mode, paper width is always 80mm/73.5mm
|
|
178
|
+
*/
|
|
179
|
+
const setPaperWidth = (width) => [exports.GS, 0xF9, 0x21, width];
|
|
180
|
+
exports.setPaperWidth = setPaperWidth;
|
|
181
|
+
/**
|
|
182
|
+
* GS F9h , n - Enable/disable paper near-end sensor (PNES)
|
|
183
|
+
* n = 0 or 48: Disable PNES
|
|
184
|
+
* n = 1 or 49: Enable PNES (default)
|
|
185
|
+
* Saves to non-volatile memory
|
|
186
|
+
*/
|
|
187
|
+
const enablePaperNearEndSensor = () => [exports.GS, 0xF9, 0x2C, 0x01];
|
|
188
|
+
exports.enablePaperNearEndSensor = enablePaperNearEndSensor;
|
|
189
|
+
const disablePaperNearEndSensor = () => [exports.GS, 0xF9, 0x2C, 0x00];
|
|
190
|
+
exports.disablePaperNearEndSensor = disablePaperNearEndSensor;
|
|
191
|
+
/**
|
|
192
|
+
* ESC b n - Select paper sensor to output paper-end signal
|
|
193
|
+
* n = 0 or 48: PE reflects paper sensor (default)
|
|
194
|
+
* n = 1 or 49: PE reflects drawer sensor
|
|
195
|
+
*/
|
|
196
|
+
const selectPaperSensor = () => [exports.ESC, 0x62, 0x00];
|
|
197
|
+
exports.selectPaperSensor = selectPaperSensor;
|
|
198
|
+
const selectDrawerSensor = () => [exports.ESC, 0x62, 0x01];
|
|
199
|
+
exports.selectDrawerSensor = selectDrawerSensor;
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// PRINTER QUALITY & MODE
|
|
202
|
+
// ============================================================================
|
|
203
|
+
/**
|
|
204
|
+
* Printer quality modes
|
|
205
|
+
*/
|
|
206
|
+
var PrinterMode;
|
|
207
|
+
(function (PrinterMode) {
|
|
208
|
+
PrinterMode[PrinterMode["NORMAL"] = 0] = "NORMAL";
|
|
209
|
+
PrinterMode[PrinterMode["HIGH_QUALITY"] = 1] = "HIGH_QUALITY";
|
|
210
|
+
PrinterMode[PrinterMode["HIGH_SPEED"] = 2] = "HIGH_SPEED"; // High speed mode
|
|
211
|
+
})(PrinterMode || (exports.PrinterMode = PrinterMode = {}));
|
|
212
|
+
/**
|
|
213
|
+
* GS F9h - n - Set and save printer mode
|
|
214
|
+
* Sets printing priority to high quality or high speed
|
|
215
|
+
*/
|
|
216
|
+
const setPrinterMode = (mode) => [exports.GS, 0xF9, 0x2D, mode];
|
|
217
|
+
exports.setPrinterMode = setPrinterMode;
|
|
218
|
+
/**
|
|
219
|
+
* ESC N n - Select printing intensity (OBSOLETE)
|
|
220
|
+
* Kept for compatibility with earlier Bematech products
|
|
221
|
+
* Command is ignored by MP-4200 TH
|
|
222
|
+
*/
|
|
223
|
+
const setPrintingIntensity = (n) => [exports.ESC, 0x4E, Math.max(0, Math.min(4, n))];
|
|
224
|
+
exports.setPrintingIntensity = setPrintingIntensity;
|
|
225
|
+
/**
|
|
226
|
+
* GS F9h + n - Set and save printing intensity (OBSOLETE)
|
|
227
|
+
* Kept for compatibility with earlier Bematech products
|
|
228
|
+
* Command is ignored by MP-4200 TH
|
|
229
|
+
*/
|
|
230
|
+
const setPrintingIntensityAlt = (n) => [exports.GS, 0xF9, 0x2B, n];
|
|
231
|
+
exports.setPrintingIntensityAlt = setPrintingIntensityAlt;
|
|
232
|
+
// ============================================================================
|
|
233
|
+
// PRINTER LANGUAGE
|
|
234
|
+
// ============================================================================
|
|
235
|
+
/**
|
|
236
|
+
* GS FAh n - Set and save printer language
|
|
237
|
+
* n = 0 or 48: English
|
|
238
|
+
* n = 1 or 49: Portuguese
|
|
239
|
+
* n = 2 or 50: Spanish
|
|
240
|
+
* n = 3 or 51: German
|
|
241
|
+
*/
|
|
242
|
+
var PrinterLanguage;
|
|
243
|
+
(function (PrinterLanguage) {
|
|
244
|
+
PrinterLanguage[PrinterLanguage["ENGLISH"] = 0] = "ENGLISH";
|
|
245
|
+
PrinterLanguage[PrinterLanguage["PORTUGUESE"] = 1] = "PORTUGUESE";
|
|
246
|
+
PrinterLanguage[PrinterLanguage["SPANISH"] = 2] = "SPANISH";
|
|
247
|
+
PrinterLanguage[PrinterLanguage["GERMAN"] = 3] = "GERMAN";
|
|
248
|
+
})(PrinterLanguage || (exports.PrinterLanguage = PrinterLanguage = {}));
|
|
249
|
+
const setPrinterLanguage = (lang) => [exports.GS, 0xFA, lang];
|
|
250
|
+
exports.setPrinterLanguage = setPrinterLanguage;
|
|
251
|
+
// ============================================================================
|
|
252
|
+
// PRINTER INFORMATION & CONFIGURATION
|
|
253
|
+
// ============================================================================
|
|
254
|
+
/**
|
|
255
|
+
* GS F9h ' n - Get printer information
|
|
256
|
+
* Returns different information based on n value:
|
|
257
|
+
* n = 0 or 48: Product code (10 bytes)
|
|
258
|
+
* n = 1 or 49: Serial number (20 bytes)
|
|
259
|
+
* n = 2 or 50: Manufacturing date (4 bytes)
|
|
260
|
+
* n = 3 or 51: Firmware version (3 bytes)
|
|
261
|
+
* n = 5 or 53: Manufacturing timestamp (17 bytes, "dd/mm/yy hh:mm:ss")
|
|
262
|
+
* n = 8 or 56: Interface type (1 byte: 0=None, 1=Serial DB-9, 2=Serial DB-25, 3=Ethernet, -1=Unknown)
|
|
263
|
+
*/
|
|
264
|
+
const getPrinterInfo = (infoType) => [exports.GS, 0xF9, 0x27, infoType];
|
|
265
|
+
exports.getPrinterInfo = getPrinterInfo;
|
|
266
|
+
/**
|
|
267
|
+
* GS F9h ( 0 - Load default user configuration
|
|
268
|
+
* Reloads all configurations from non-volatile memory and dipswitches
|
|
269
|
+
*/
|
|
270
|
+
exports.LOAD_DEFAULT_CONFIG = [exports.GS, 0xF9, 0x28, 0x30];
|
|
271
|
+
/**
|
|
272
|
+
* GS F9h ) 0 - Print user configuration
|
|
273
|
+
* Prints current user configuration on paper
|
|
274
|
+
*/
|
|
275
|
+
exports.PRINT_CONFIG = [exports.GS, 0xF9, 0x29, 0x30];
|
|
276
|
+
/**
|
|
277
|
+
* GS F8h F - Printer reset
|
|
278
|
+
* Forces a hardware reset
|
|
279
|
+
*/
|
|
280
|
+
exports.RESET_PRINTER = [exports.GS, 0xF8, 0x46];
|
|
281
|
+
// ============================================================================
|
|
282
|
+
// PANEL CONTROL
|
|
283
|
+
// ============================================================================
|
|
284
|
+
/**
|
|
285
|
+
* ESC y n - Enable/disable panel keys
|
|
286
|
+
* n = 0 or 48: Disable panel keys
|
|
287
|
+
* n = 1 or 49: Enable panel keys (default)
|
|
288
|
+
*/
|
|
289
|
+
const enablePanelKeys = () => [exports.ESC, 0x79, 0x01];
|
|
290
|
+
exports.enablePanelKeys = enablePanelKeys;
|
|
291
|
+
const disablePanelKeys = () => [exports.ESC, 0x79, 0x00];
|
|
292
|
+
exports.disablePanelKeys = disablePanelKeys;
|
|
293
|
+
/**
|
|
294
|
+
* ESC x - Enable dump mode
|
|
295
|
+
* Prints data in hexadecimal for debugging
|
|
296
|
+
* WARNING: Only way to exit dump mode is to turn off printer
|
|
297
|
+
*/
|
|
298
|
+
exports.ENABLE_DUMP_MODE = [exports.ESC, 0x78];
|
|
299
|
+
// ============================================================================
|
|
300
|
+
// DRAWER CONTROL
|
|
301
|
+
// ============================================================================
|
|
302
|
+
/**
|
|
303
|
+
* ESC v n - Activate drawer #1 for n milliseconds
|
|
304
|
+
* Range: 50 ≤ n ≤ 250 (actual: 50ms ≤ n ≤ 200ms)
|
|
305
|
+
*/
|
|
306
|
+
const activateDrawer1 = (milliseconds) => {
|
|
307
|
+
const n = Math.max(50, Math.min(250, milliseconds));
|
|
308
|
+
return [exports.ESC, 0x76, n];
|
|
309
|
+
};
|
|
310
|
+
exports.activateDrawer1 = activateDrawer1;
|
|
311
|
+
/**
|
|
312
|
+
* ESC 80h n - Activate drawer #2 for n milliseconds
|
|
313
|
+
* Range: 50 ≤ n ≤ 250 (actual: 50ms ≤ n ≤ 200ms)
|
|
314
|
+
*/
|
|
315
|
+
const activateDrawer2 = (milliseconds) => {
|
|
316
|
+
const n = Math.max(50, Math.min(250, milliseconds));
|
|
317
|
+
return [exports.ESC, 0x80, n];
|
|
318
|
+
};
|
|
319
|
+
exports.activateDrawer2 = activateDrawer2;
|
|
320
|
+
// ============================================================================
|
|
321
|
+
// PAPER CUTTING
|
|
322
|
+
// ============================================================================
|
|
323
|
+
/**
|
|
324
|
+
* ESC i - Perform full paper cut
|
|
325
|
+
* Hexadecimal: 1B 69
|
|
326
|
+
*/
|
|
327
|
+
exports.CUT_FULL = [exports.ESC, 0x69];
|
|
328
|
+
/**
|
|
329
|
+
* ESC w - Perform full paper cut (alternate command)
|
|
330
|
+
* Hexadecimal: 1B 77
|
|
331
|
+
*/
|
|
332
|
+
exports.CUT_FULL_ALT = [exports.ESC, 0x77];
|
|
333
|
+
/**
|
|
334
|
+
* GS F9h D m n - Activate buzzer on cut
|
|
335
|
+
* m: Buzzer selection (0=none, 1=internal, 2=external)
|
|
336
|
+
* n: Activation time (n × 100ms)
|
|
337
|
+
* Default: m=0, n=200
|
|
338
|
+
*/
|
|
339
|
+
const setBuzzerOnCut = (buzzer, time) => {
|
|
340
|
+
const n = Math.max(0, Math.min(255, time));
|
|
341
|
+
return [exports.GS, 0xF9, 0x44, buzzer, n];
|
|
342
|
+
};
|
|
343
|
+
exports.setBuzzerOnCut = setBuzzerOnCut;
|
|
344
|
+
const disableBuzzerOnCut = () => [exports.GS, 0xF9, 0x44, 0x00, 0x00];
|
|
345
|
+
exports.disableBuzzerOnCut = disableBuzzerOnCut;
|
|
346
|
+
// ============================================================================
|
|
347
|
+
// BUZZER CONTROL
|
|
348
|
+
// ============================================================================
|
|
349
|
+
/**
|
|
350
|
+
* ESC ( A pL pH fn n1 n2 vol - Activate/deactivate buzzer
|
|
351
|
+
* pL + pH × 256 = 4 (always: pL=4, pH=0)
|
|
352
|
+
* fn = 1 or 49: Activate buzzer
|
|
353
|
+
* fn = 0 or 48: Deactivate buzzer (deprecated)
|
|
354
|
+
* n = (n1 + n2 × 256): Time in milliseconds
|
|
355
|
+
* vol = 0, 1, 48, or 49: Volume (unused)
|
|
356
|
+
*/
|
|
357
|
+
const activateBuzzer = (milliseconds) => {
|
|
358
|
+
const n1 = milliseconds & 0xFF;
|
|
359
|
+
const n2 = (milliseconds >> 8) & 0xFF;
|
|
360
|
+
return [exports.ESC, 0x28, 0x41, 0x04, 0x00, 0x01, n1, n2, 0x00];
|
|
361
|
+
};
|
|
362
|
+
exports.activateBuzzer = activateBuzzer;
|
|
363
|
+
// ============================================================================
|
|
364
|
+
// PAPER FEEDING
|
|
365
|
+
// ============================================================================
|
|
366
|
+
/**
|
|
367
|
+
* LF - Feed one line
|
|
368
|
+
* Prints buffer contents and feeds one line according to default line spacing
|
|
369
|
+
*/
|
|
370
|
+
exports.FEED_LINE = [exports.LF];
|
|
371
|
+
/**
|
|
372
|
+
* FF - Feed one page
|
|
373
|
+
* Moves from current position to top of next page
|
|
374
|
+
* Can be disabled by setting page size to zero
|
|
375
|
+
*/
|
|
376
|
+
exports.FEED_PAGE = [exports.FF];
|
|
377
|
+
/**
|
|
378
|
+
* ESC J n - Perform fine line feed
|
|
379
|
+
* Range: 48 ≤ n ≤ 255
|
|
380
|
+
* Feed: (n - 48) × 0.125mm
|
|
381
|
+
* Widely used for graphics printing
|
|
382
|
+
*/
|
|
383
|
+
const fineFeed = (n) => {
|
|
384
|
+
const value = Math.max(48, Math.min(255, n));
|
|
385
|
+
return [exports.ESC, 0x4A, value];
|
|
386
|
+
};
|
|
387
|
+
exports.fineFeed = fineFeed;
|
|
388
|
+
/**
|
|
389
|
+
* ESC A n - Feed paper by [n × 0.375]mm
|
|
390
|
+
* Range: 0 ≤ n ≤ 255
|
|
391
|
+
* Notes: n < 17 → 0mm, n > 85 → 32mm, else n × 0.375mm
|
|
392
|
+
*/
|
|
393
|
+
const feedPaper = (n) => {
|
|
394
|
+
const value = Math.max(0, Math.min(255, n));
|
|
395
|
+
return [exports.ESC, 0x41, value];
|
|
396
|
+
};
|
|
397
|
+
exports.feedPaper = feedPaper;
|
|
398
|
+
/**
|
|
399
|
+
* ESC 2 - Set text line height to 1/6 inches (default)
|
|
400
|
+
* Hexadecimal: 1B 32
|
|
401
|
+
*/
|
|
402
|
+
exports.SET_LINE_HEIGHT_DEFAULT = [exports.ESC, 0x32];
|
|
403
|
+
/**
|
|
404
|
+
* ESC 3 n - Set line feed to n/144 inches
|
|
405
|
+
* Range: 18 ≤ n ≤ 255
|
|
406
|
+
* Takes effect immediately
|
|
407
|
+
*/
|
|
408
|
+
const setLineSpacing = (n) => {
|
|
409
|
+
const value = Math.max(18, Math.min(255, n));
|
|
410
|
+
return [exports.ESC, 0x33, value];
|
|
411
|
+
};
|
|
412
|
+
exports.setLineSpacing = setLineSpacing;
|
|
413
|
+
/**
|
|
414
|
+
* ESC f 1 n - Vertical skipping
|
|
415
|
+
* Range: 0 ≤ n ≤ 255
|
|
416
|
+
* Performs vertical skipping of n characters
|
|
417
|
+
* Alternate: 1B 66 01 n (same effect)
|
|
418
|
+
*/
|
|
419
|
+
const verticalSkip = (n) => {
|
|
420
|
+
const value = Math.max(0, Math.min(255, n));
|
|
421
|
+
return [exports.ESC, 0x66, 0x31, value];
|
|
422
|
+
};
|
|
423
|
+
exports.verticalSkip = verticalSkip;
|
|
424
|
+
/**
|
|
425
|
+
* ESC f 0 n - Horizontal skipping
|
|
426
|
+
* Range: 0 ≤ n ≤ 255
|
|
427
|
+
* Performs horizontal skipping of n characters
|
|
428
|
+
* Alternate: 1B 66 00 n (same effect)
|
|
429
|
+
*/
|
|
430
|
+
const horizontalSkip = (n) => {
|
|
431
|
+
const value = Math.max(0, Math.min(255, n));
|
|
432
|
+
return [exports.ESC, 0x66, 0x30, value];
|
|
433
|
+
};
|
|
434
|
+
exports.horizontalSkip = horizontalSkip;
|
|
435
|
+
// ============================================================================
|
|
436
|
+
// PAGE CONFIGURATION
|
|
437
|
+
// ============================================================================
|
|
438
|
+
/**
|
|
439
|
+
* ESC C n - Set page size in lines
|
|
440
|
+
* Range: 0 < n < 256
|
|
441
|
+
* Default: n = 12
|
|
442
|
+
* n represents number of single-height lines
|
|
443
|
+
*/
|
|
444
|
+
const setPageSizeLines = (lines) => {
|
|
445
|
+
const n = Math.max(1, Math.min(255, lines));
|
|
446
|
+
return [exports.ESC, 0x43, n];
|
|
447
|
+
};
|
|
448
|
+
exports.setPageSizeLines = setPageSizeLines;
|
|
449
|
+
/**
|
|
450
|
+
* ESC c n1 n2 - Set page size in millimeters
|
|
451
|
+
* Range: 0 ≤ n1 ≤ 255, 0 ≤ n2 ≤ 255
|
|
452
|
+
* Page size = 0.125mm × [n1 + (256 × n2)]
|
|
453
|
+
*/
|
|
454
|
+
const setPageSizeMM = (n1, n2) => {
|
|
455
|
+
const v1 = Math.max(0, Math.min(255, n1));
|
|
456
|
+
const v2 = Math.max(0, Math.min(255, n2));
|
|
457
|
+
return [exports.ESC, 0x63, v1, v2];
|
|
458
|
+
};
|
|
459
|
+
exports.setPageSizeMM = setPageSizeMM;
|
|
460
|
+
// ============================================================================
|
|
461
|
+
// AUTOMATIC LINE FEED
|
|
462
|
+
// ============================================================================
|
|
463
|
+
/**
|
|
464
|
+
* ESC z n - Enable/disable automatic line feed
|
|
465
|
+
* n = 0 or 48: Disable (default)
|
|
466
|
+
* n = 1 or 49: Enable
|
|
467
|
+
* When enabled, printer performs LF after receiving CR
|
|
468
|
+
*/
|
|
469
|
+
const enableAutoLineFeed = () => [exports.ESC, 0x7A, 0x01];
|
|
470
|
+
exports.enableAutoLineFeed = enableAutoLineFeed;
|
|
471
|
+
const disableAutoLineFeed = () => [exports.ESC, 0x7A, 0x00];
|
|
472
|
+
exports.disableAutoLineFeed = disableAutoLineFeed;
|
|
473
|
+
// ============================================================================
|
|
474
|
+
// MARGINS & TABS
|
|
475
|
+
// ============================================================================
|
|
476
|
+
/**
|
|
477
|
+
* ESC Q n - Set right margin
|
|
478
|
+
* Range: 0 ≤ n ≤ 255
|
|
479
|
+
* Sets right margin in number of characters from default left margin
|
|
480
|
+
* New margin becomes valid only on next line if on right side of current position
|
|
481
|
+
*/
|
|
482
|
+
const setRightMargin = (chars) => {
|
|
483
|
+
const n = Math.max(0, Math.min(255, chars));
|
|
484
|
+
return [exports.ESC, 0x51, n];
|
|
485
|
+
};
|
|
486
|
+
exports.setRightMargin = setRightMargin;
|
|
487
|
+
/**
|
|
488
|
+
* ESC l n - Set left margin
|
|
489
|
+
* Range: 0 ≤ n ≤ 255
|
|
490
|
+
* Sets left margin in number of characters from default left margin
|
|
491
|
+
* New margin becomes valid only on next line if on left side of current position
|
|
492
|
+
*/
|
|
493
|
+
const setLeftMargin = (chars) => {
|
|
494
|
+
const n = Math.max(0, Math.min(255, chars));
|
|
495
|
+
return [exports.ESC, 0x6C, n];
|
|
496
|
+
};
|
|
497
|
+
exports.setLeftMargin = setLeftMargin;
|
|
498
|
+
/**
|
|
499
|
+
* HT - Horizontal tab
|
|
500
|
+
* Moves print position to next tab mark
|
|
501
|
+
* Default: tabs at every 8 character columns (9, 17, 25, ...)
|
|
502
|
+
*/
|
|
503
|
+
exports.TAB = [exports.HT];
|
|
504
|
+
/**
|
|
505
|
+
* ESC D n1 ... nk NUL - Set horizontal tab marks
|
|
506
|
+
* Range: 1 ≤ n ≤ 255, 0 ≤ k ≤ 32
|
|
507
|
+
* Default: intervals of 8 characters for font 12x24
|
|
508
|
+
*
|
|
509
|
+
* Example: setTabPositions([8, 16, 24]) sets tabs at columns 9, 17, 25
|
|
510
|
+
* Must be in ascending order and terminated with NUL
|
|
511
|
+
*/
|
|
512
|
+
const setTabPositions = (positions) => {
|
|
513
|
+
const validPositions = positions
|
|
514
|
+
.filter(p => p >= 1 && p <= 255)
|
|
515
|
+
.slice(0, 32)
|
|
516
|
+
.sort((a, b) => a - b);
|
|
517
|
+
return [exports.ESC, 0x44, ...validPositions, exports.NUL];
|
|
518
|
+
};
|
|
519
|
+
exports.setTabPositions = setTabPositions;
|
|
520
|
+
/**
|
|
521
|
+
* ESC D NUL - Cancel all horizontal tab marks
|
|
522
|
+
*/
|
|
523
|
+
exports.CLEAR_TABS = [exports.ESC, 0x44, exports.NUL];
|
|
524
|
+
// ============================================================================
|
|
525
|
+
// TEXT ALIGNMENT
|
|
526
|
+
// ============================================================================
|
|
527
|
+
/**
|
|
528
|
+
* ESC a n - Character alignment
|
|
529
|
+
* n = 0 or 48: Left justified (default)
|
|
530
|
+
* n = 1 or 49: Center justified
|
|
531
|
+
* n = 2 or 50: Right justified
|
|
532
|
+
*/
|
|
533
|
+
exports.ALIGN_LEFT = [exports.ESC, 0x61, 0x00];
|
|
534
|
+
exports.ALIGN_CENTER = [exports.ESC, 0x61, 0x01];
|
|
535
|
+
exports.ALIGN_RIGHT = [exports.ESC, 0x61, 0x02];
|
|
536
|
+
// ============================================================================
|
|
537
|
+
// TEXT FORMATTING - BOLD/EMPHASIZED
|
|
538
|
+
// ============================================================================
|
|
539
|
+
/**
|
|
540
|
+
* ESC E - Enable emphasized print mode (bold)
|
|
541
|
+
* Hexadecimal: 1B 45
|
|
542
|
+
* Emphasized mode is bolder than normal print
|
|
543
|
+
*/
|
|
544
|
+
exports.BOLD_ON = [exports.ESC, 0x45];
|
|
545
|
+
/**
|
|
546
|
+
* ESC F - Disable emphasized print mode (bold)
|
|
547
|
+
* Hexadecimal: 1B 46
|
|
548
|
+
*/
|
|
549
|
+
exports.BOLD_OFF = [exports.ESC, 0x46];
|
|
550
|
+
// ============================================================================
|
|
551
|
+
// TEXT FORMATTING - UNDERLINE
|
|
552
|
+
// ============================================================================
|
|
553
|
+
/**
|
|
554
|
+
* ESC - n - Enable/disable underline print mode
|
|
555
|
+
* n = 0 or 48: Disable (default)
|
|
556
|
+
* n = 1 or 49: Enable
|
|
557
|
+
* Underlines every character and space
|
|
558
|
+
*/
|
|
559
|
+
exports.UNDERLINE_ON = [exports.ESC, 0x2D, 0x01];
|
|
560
|
+
exports.UNDERLINE_OFF = [exports.ESC, 0x2D, 0x00];
|
|
561
|
+
// ============================================================================
|
|
562
|
+
// TEXT FORMATTING - ITALIC
|
|
563
|
+
// ============================================================================
|
|
564
|
+
/**
|
|
565
|
+
* ESC 4 - Enable italic print mode
|
|
566
|
+
* Hexadecimal: 1B 34
|
|
567
|
+
* Available in all other print modes
|
|
568
|
+
*/
|
|
569
|
+
exports.ITALIC_ON = [exports.ESC, 0x34];
|
|
570
|
+
/**
|
|
571
|
+
* ESC 5 - Disable italic print mode
|
|
572
|
+
* Hexadecimal: 1B 35
|
|
573
|
+
*/
|
|
574
|
+
exports.ITALIC_OFF = [exports.ESC, 0x35];
|
|
575
|
+
// ============================================================================
|
|
576
|
+
// TEXT FORMATTING - UPSIDE DOWN
|
|
577
|
+
// ============================================================================
|
|
578
|
+
/**
|
|
579
|
+
* ESC } n - Turn upside-down printing mode on/off
|
|
580
|
+
* n = 0 or 48: Disable (default)
|
|
581
|
+
* n = 1 or 49: Enable
|
|
582
|
+
*/
|
|
583
|
+
exports.UPSIDE_DOWN_ON = [exports.ESC, 0x7D, 0x01];
|
|
584
|
+
exports.UPSIDE_DOWN_OFF = [exports.ESC, 0x7D, 0x00];
|
|
585
|
+
// ============================================================================
|
|
586
|
+
// TEXT FORMATTING - SUPERSCRIPT/SUBSCRIPT
|
|
587
|
+
// ============================================================================
|
|
588
|
+
/**
|
|
589
|
+
* ESC S n - Enable superscript or subscript print mode
|
|
590
|
+
* n = 0 or 48: Superscript (print on upper side of line)
|
|
591
|
+
* n = 1 or 49: Subscript (print on bottom side of line)
|
|
592
|
+
*/
|
|
593
|
+
exports.SUPERSCRIPT_ON = [exports.ESC, 0x53, 0x00];
|
|
594
|
+
exports.SUBSCRIPT_ON = [exports.ESC, 0x53, 0x01];
|
|
595
|
+
/**
|
|
596
|
+
* ESC T - Disable superscript and subscript print modes
|
|
597
|
+
* Hexadecimal: 1B 54
|
|
598
|
+
*/
|
|
599
|
+
exports.SCRIPT_OFF = [exports.ESC, 0x54];
|
|
600
|
+
// ============================================================================
|
|
601
|
+
// TEXT FORMATTING - COMBINED MODE (ESC !)
|
|
602
|
+
// ============================================================================
|
|
603
|
+
/**
|
|
604
|
+
* ESC ! n - Select print mode (combined control)
|
|
605
|
+
* Bits:
|
|
606
|
+
* 0: Font selection (0=Font A, 1=Font B) - Not documented but works
|
|
607
|
+
* 1-2: Undefined
|
|
608
|
+
* 3: Emphasized (0=clear, 1=set)
|
|
609
|
+
* 4: Double height (0=clear, 1=set)
|
|
610
|
+
* 5: Double width (0=clear, 1=set)
|
|
611
|
+
* 6: Undefined
|
|
612
|
+
* 7: Underline (0=clear, 1=set)
|
|
613
|
+
*/
|
|
614
|
+
const calculatePrintMode = (options) => {
|
|
615
|
+
// Use Font B (narrower, 9×17 dots) for consistency with ESC/POS
|
|
616
|
+
// Font B fits more characters per line (better for 48-char receipts)
|
|
617
|
+
let n = 0x01; // Bit 0 - Font B
|
|
618
|
+
if (options.emphasized)
|
|
619
|
+
n |= 0x08; // Bit 3
|
|
620
|
+
if (options.doubleHeight)
|
|
621
|
+
n |= 0x10; // Bit 4
|
|
622
|
+
if (options.doubleWidth)
|
|
623
|
+
n |= 0x20; // Bit 5
|
|
624
|
+
if (options.underline)
|
|
625
|
+
n |= 0x80; // Bit 7
|
|
626
|
+
return [exports.ESC, 0x21, n];
|
|
627
|
+
};
|
|
628
|
+
exports.calculatePrintMode = calculatePrintMode;
|
|
629
|
+
// ============================================================================
|
|
630
|
+
// CHARACTER SIZING - DOUBLE HEIGHT
|
|
631
|
+
// ============================================================================
|
|
632
|
+
/**
|
|
633
|
+
* ESC d n - Enable/disable double height print mode
|
|
634
|
+
* n = 0 or 48: Disable (default)
|
|
635
|
+
* n = 1 or 49: Enable
|
|
636
|
+
*
|
|
637
|
+
* IMPORTANT: This is different from ESC/POS where ESC d is used for line feed
|
|
638
|
+
*/
|
|
639
|
+
exports.DOUBLE_HEIGHT_ON = [exports.ESC, 0x64, 0x01];
|
|
640
|
+
exports.DOUBLE_HEIGHT_OFF = [exports.ESC, 0x64, 0x00];
|
|
641
|
+
/**
|
|
642
|
+
* ESC V - Enable on-line double height mode
|
|
643
|
+
* If received at beginning of line: valid for whole line
|
|
644
|
+
* Otherwise: valid only for next incoming characters
|
|
645
|
+
* Returns to normal mode on next line
|
|
646
|
+
*/
|
|
647
|
+
exports.DOUBLE_HEIGHT_ONLINE = [exports.ESC, 0x56];
|
|
648
|
+
// ============================================================================
|
|
649
|
+
// CHARACTER SIZING - DOUBLE WIDTH (EXPANDED)
|
|
650
|
+
// ============================================================================
|
|
651
|
+
/**
|
|
652
|
+
* ESC W n - Enable/disable expanded mode (double width)
|
|
653
|
+
* n = 0 or 48: Disable (default)
|
|
654
|
+
* n = 1 or 49: Enable
|
|
655
|
+
* Takes effect immediately
|
|
656
|
+
*/
|
|
657
|
+
exports.DOUBLE_WIDTH_ON = [exports.ESC, 0x57, 0x01];
|
|
658
|
+
exports.DOUBLE_WIDTH_OFF = [exports.ESC, 0x57, 0x00];
|
|
659
|
+
/**
|
|
660
|
+
* ESC SO - Enable on-line expanded mode
|
|
661
|
+
* Hexadecimal: 1B 0E
|
|
662
|
+
* If received at beginning of line: valid for whole line
|
|
663
|
+
* Otherwise: valid only for next incoming characters
|
|
664
|
+
* Returns to normal mode on next line
|
|
665
|
+
*/
|
|
666
|
+
exports.EXPANDED_ONLINE = [exports.ESC, exports.SO];
|
|
667
|
+
/**
|
|
668
|
+
* SO - Enable on-line expanded mode (alternate)
|
|
669
|
+
* Hexadecimal: 0E
|
|
670
|
+
* Same as ESC SO
|
|
671
|
+
*/
|
|
672
|
+
exports.EXPANDED_ONLINE_ALT = [exports.SO];
|
|
673
|
+
/**
|
|
674
|
+
* DC4 - Disable on-line expanded print
|
|
675
|
+
* Hexadecimal: 14
|
|
676
|
+
* Disables expanded mode if previously set by ESC SO or SO
|
|
677
|
+
*/
|
|
678
|
+
exports.EXPANDED_OFF = [exports.DC4];
|
|
679
|
+
// ============================================================================
|
|
680
|
+
// CHARACTER SIZING - CONDENSED
|
|
681
|
+
// ============================================================================
|
|
682
|
+
/**
|
|
683
|
+
* ESC SI - Enable condensed mode
|
|
684
|
+
* Hexadecimal: 1B 0F
|
|
685
|
+
*/
|
|
686
|
+
exports.CONDENSED_ON = [exports.ESC, exports.SI];
|
|
687
|
+
/**
|
|
688
|
+
* SI - Enable condensed mode (alternate)
|
|
689
|
+
* Hexadecimal: 0F
|
|
690
|
+
* Same as ESC SI
|
|
691
|
+
*/
|
|
692
|
+
exports.CONDENSED_ON_ALT = [exports.SI];
|
|
693
|
+
/**
|
|
694
|
+
* ESC H - Disable condensed mode
|
|
695
|
+
* Hexadecimal: 1B 48
|
|
696
|
+
* Same as DC2 or ESC P
|
|
697
|
+
*/
|
|
698
|
+
exports.CONDENSED_OFF = [exports.ESC, 0x48];
|
|
699
|
+
/**
|
|
700
|
+
* ESC P - Disable condensed mode (alternate)
|
|
701
|
+
* Hexadecimal: 1B 50
|
|
702
|
+
* Same as DC2 or ESC H
|
|
703
|
+
*/
|
|
704
|
+
exports.CONDENSED_OFF_ALT = [exports.ESC, 0x50];
|
|
705
|
+
/**
|
|
706
|
+
* DC2 - Disable condensed mode (alternate)
|
|
707
|
+
* Hexadecimal: 12
|
|
708
|
+
* Same as ESC H or ESC P
|
|
709
|
+
*/
|
|
710
|
+
exports.CONDENSED_OFF_DC2 = [exports.DC2];
|
|
711
|
+
// ============================================================================
|
|
712
|
+
// GRAPHICS - BIT IMAGES
|
|
713
|
+
// ============================================================================
|
|
714
|
+
/**
|
|
715
|
+
* ESC $ n1 n2 - Fill in blank bit columns
|
|
716
|
+
* Fills blank bit columns from current column to column (n1 + n2 × 256)
|
|
717
|
+
* Must be ≤ printing width N
|
|
718
|
+
*/
|
|
719
|
+
const fillBlankColumns = (columns) => {
|
|
720
|
+
const n1 = columns & 0xFF;
|
|
721
|
+
const n2 = (columns >> 8) & 0xFF;
|
|
722
|
+
return [exports.ESC, 0x24, n1, n2];
|
|
723
|
+
};
|
|
724
|
+
exports.fillBlankColumns = fillBlankColumns;
|
|
725
|
+
/**
|
|
726
|
+
* ESC * ! n1 n2 b1 ... bn - 24-bit graphics
|
|
727
|
+
* Hexadecimal: 1B 2A 21 n1 n2 b1 ... bn
|
|
728
|
+
* Downloads 24-bit image with (n1 + n2 × 256) columns
|
|
729
|
+
* Each column = 3 bytes (24 bits height)
|
|
730
|
+
* Total bytes needed = columns × 3
|
|
731
|
+
*/
|
|
732
|
+
const print24BitGraphics = (columns, data) => {
|
|
733
|
+
const n1 = columns & 0xFF;
|
|
734
|
+
const n2 = (columns >> 8) & 0xFF;
|
|
735
|
+
return [exports.ESC, 0x2A, 0x21, n1, n2, ...data];
|
|
736
|
+
};
|
|
737
|
+
exports.print24BitGraphics = print24BitGraphics;
|
|
738
|
+
/**
|
|
739
|
+
* ESC K n1 n2 b1 ... bn - 8-bit graphics
|
|
740
|
+
* Hexadecimal: 1B 4B n1 n2 b1 ... bn
|
|
741
|
+
* Select "8 pin" bit image (compatible with dot-matrix printers)
|
|
742
|
+
* Columns = n1 + (n2 × 256), each column = 1 byte
|
|
743
|
+
* Low resolution (expanded to 3 bytes internally)
|
|
744
|
+
*/
|
|
745
|
+
const print8BitGraphics = (columns, data) => {
|
|
746
|
+
const n1 = columns & 0xFF;
|
|
747
|
+
const n2 = (columns >> 8) & 0xFF;
|
|
748
|
+
return [exports.ESC, 0x4B, n1, n2, ...data];
|
|
749
|
+
};
|
|
750
|
+
exports.print8BitGraphics = print8BitGraphics;
|
|
751
|
+
// ============================================================================
|
|
752
|
+
// GRAPHICS - RASTER BITMAP
|
|
753
|
+
// ============================================================================
|
|
754
|
+
/**
|
|
755
|
+
* Raster bitmap print modes
|
|
756
|
+
*/
|
|
757
|
+
var RasterMode;
|
|
758
|
+
(function (RasterMode) {
|
|
759
|
+
RasterMode[RasterMode["NORMAL"] = 0] = "NORMAL";
|
|
760
|
+
RasterMode[RasterMode["DOUBLE_WIDTH"] = 1] = "DOUBLE_WIDTH";
|
|
761
|
+
RasterMode[RasterMode["DOUBLE_HEIGHT"] = 2] = "DOUBLE_HEIGHT";
|
|
762
|
+
RasterMode[RasterMode["QUADRUPLE"] = 3] = "QUADRUPLE"; // 101 dpi × 101 dpi
|
|
763
|
+
})(RasterMode || (exports.RasterMode = RasterMode = {}));
|
|
764
|
+
/**
|
|
765
|
+
* GS v 0 m xL xH yL yH d1 ... dk - Print raster bitmap
|
|
766
|
+
* m: Mode (0-3 or 48-51)
|
|
767
|
+
* xL, xH: Horizontal bytes = xL + xH × 256
|
|
768
|
+
* yL, yH: Vertical bytes = yL + yH × 256
|
|
769
|
+
* k = (xL + xH × 256) × (yL + yH × 256)
|
|
770
|
+
*
|
|
771
|
+
* Data outside printing area is discarded
|
|
772
|
+
* Affected by HT, ESC $, ESC \, GS L, and ESC a
|
|
773
|
+
*/
|
|
774
|
+
const printRasterBitmap = (mode, width, height, data) => {
|
|
775
|
+
const xL = width & 0xFF;
|
|
776
|
+
const xH = (width >> 8) & 0xFF;
|
|
777
|
+
const yL = height & 0xFF;
|
|
778
|
+
const yH = (height >> 8) & 0xFF;
|
|
779
|
+
return [exports.GS, 0x76, 0x30, mode, xL, xH, yL, yH, ...data];
|
|
780
|
+
};
|
|
781
|
+
exports.printRasterBitmap = printRasterBitmap;
|
|
782
|
+
// ============================================================================
|
|
783
|
+
// GRAPHICS - DOWNLOADED BIT IMAGE
|
|
784
|
+
// ============================================================================
|
|
785
|
+
/**
|
|
786
|
+
* GS * x y d1 ... d(x×y×8) - Define downloaded bit image
|
|
787
|
+
* Range: 1 ≤ x ≤ 255, 1 ≤ y ≤ 64
|
|
788
|
+
* Horizontal dots: x × 8
|
|
789
|
+
* Vertical dots: y × 8
|
|
790
|
+
*
|
|
791
|
+
* Cleared by: ESC @, FS q, printer restart, or power cycle
|
|
792
|
+
*/
|
|
793
|
+
const defineDownloadedBitImage = (x, y, data) => {
|
|
794
|
+
const xVal = Math.max(1, Math.min(255, x));
|
|
795
|
+
const yVal = Math.max(1, Math.min(64, y));
|
|
796
|
+
return [exports.GS, 0x2A, xVal, yVal, ...data];
|
|
797
|
+
};
|
|
798
|
+
exports.defineDownloadedBitImage = defineDownloadedBitImage;
|
|
799
|
+
/**
|
|
800
|
+
* GS / m - Print downloaded bit image
|
|
801
|
+
* m: Mode (0-3 or 48-51) - same as RasterMode
|
|
802
|
+
* No effect if downloaded image not defined
|
|
803
|
+
*/
|
|
804
|
+
const printDownloadedBitImage = (mode) => [exports.GS, 0x2F, mode];
|
|
805
|
+
exports.printDownloadedBitImage = printDownloadedBitImage;
|
|
806
|
+
// ============================================================================
|
|
807
|
+
// GRAPHICS - NON-VOLATILE (NV) BIT IMAGE
|
|
808
|
+
// ============================================================================
|
|
809
|
+
/**
|
|
810
|
+
* FS q n [xL xH yL yH d1 ... dn]1 ... [xL xH yL yH d1 ... dn]n
|
|
811
|
+
* Define NV bit images (stored in non-volatile memory)
|
|
812
|
+
*
|
|
813
|
+
* n: Number of NV bit images (1 ≤ n ≤ 255)
|
|
814
|
+
* xL, xH: Horizontal = (xL + xH × 256) × 8 dots (max 1023 × 8)
|
|
815
|
+
* yL, yH: Vertical = (yL + yH × 256) × 8 dots (max 288 × 8)
|
|
816
|
+
*
|
|
817
|
+
* Erases all previously defined NV images
|
|
818
|
+
*/
|
|
819
|
+
const defineNVBitImage = (images) => {
|
|
820
|
+
const result = [exports.FS, 0x71, images.length];
|
|
821
|
+
for (const img of images) {
|
|
822
|
+
const xL = img.width & 0xFF;
|
|
823
|
+
const xH = (img.width >> 8) & 0xFF;
|
|
824
|
+
const yL = img.height & 0xFF;
|
|
825
|
+
const yH = (img.height >> 8) & 0xFF;
|
|
826
|
+
result.push(xL, xH, yL, yH, ...img.data);
|
|
827
|
+
}
|
|
828
|
+
return result;
|
|
829
|
+
};
|
|
830
|
+
exports.defineNVBitImage = defineNVBitImage;
|
|
831
|
+
/**
|
|
832
|
+
* FS p n m - Print non-volatile (NV) bit image
|
|
833
|
+
* n: NV bit image number (as defined by FS q)
|
|
834
|
+
* m: Mode (0-3 or 48-51) - same as RasterMode
|
|
835
|
+
* No effect if n-th NV image not defined
|
|
836
|
+
*/
|
|
837
|
+
const printNVBitImage = (imageNumber, mode) => [exports.FS, 0x70, imageNumber, mode];
|
|
838
|
+
exports.printNVBitImage = printNVBitImage;
|
|
839
|
+
// ============================================================================
|
|
840
|
+
// BARCODES - CONFIGURATION
|
|
841
|
+
// ============================================================================
|
|
842
|
+
/**
|
|
843
|
+
* GS h n - Set barcode height
|
|
844
|
+
* Range: 1 ≤ n ≤ 255
|
|
845
|
+
* Default: n = 162
|
|
846
|
+
* Height = n × 0.125mm
|
|
847
|
+
*/
|
|
848
|
+
const setBarcodeHeight = (n) => {
|
|
849
|
+
const height = Math.max(1, Math.min(255, n));
|
|
850
|
+
return [exports.GS, 0x68, height];
|
|
851
|
+
};
|
|
852
|
+
exports.setBarcodeHeight = setBarcodeHeight;
|
|
853
|
+
/**
|
|
854
|
+
* GS w n - Set barcode width
|
|
855
|
+
* Range: 2 ≤ n ≤ 4
|
|
856
|
+
* Default: n = 3
|
|
857
|
+
* n = 2: Normal width
|
|
858
|
+
* n = 3: Double width
|
|
859
|
+
* n = 4: Quadruple width
|
|
860
|
+
*/
|
|
861
|
+
const setBarcodeWidth = (width) => [exports.GS, 0x77, width];
|
|
862
|
+
exports.setBarcodeWidth = setBarcodeWidth;
|
|
863
|
+
/**
|
|
864
|
+
* Human Readable Information (HRI) position
|
|
865
|
+
*/
|
|
866
|
+
var BarcodeHRIPosition;
|
|
867
|
+
(function (BarcodeHRIPosition) {
|
|
868
|
+
BarcodeHRIPosition[BarcodeHRIPosition["NONE"] = 0] = "NONE";
|
|
869
|
+
BarcodeHRIPosition[BarcodeHRIPosition["TOP"] = 1] = "TOP";
|
|
870
|
+
BarcodeHRIPosition[BarcodeHRIPosition["BOTTOM"] = 2] = "BOTTOM";
|
|
871
|
+
BarcodeHRIPosition[BarcodeHRIPosition["BOTH"] = 3] = "BOTH"; // HRI on both top and bottom
|
|
872
|
+
})(BarcodeHRIPosition || (exports.BarcodeHRIPosition = BarcodeHRIPosition = {}));
|
|
873
|
+
/**
|
|
874
|
+
* GS H n - Choose HRI position in barcode
|
|
875
|
+
* Range: 0 ≤ n ≤ 3
|
|
876
|
+
* Default: n = 1 (top)
|
|
877
|
+
*/
|
|
878
|
+
const setBarcodeHRI = (position) => [exports.GS, 0x48, position];
|
|
879
|
+
exports.setBarcodeHRI = setBarcodeHRI;
|
|
880
|
+
/**
|
|
881
|
+
* GS f n - Set HRI font
|
|
882
|
+
* n = 0 or 48: Normal font (default)
|
|
883
|
+
* n = 1 or 49: Condensed font
|
|
884
|
+
*/
|
|
885
|
+
const setBarcodeHRIFont = (condensed) => [exports.GS, 0x66, condensed ? 0x01 : 0x00];
|
|
886
|
+
exports.setBarcodeHRIFont = setBarcodeHRIFont;
|
|
887
|
+
/**
|
|
888
|
+
* GS k 84h n1 n2 - Program barcode left margin
|
|
889
|
+
* Margin position = n1 + n2 × 256
|
|
890
|
+
*/
|
|
891
|
+
const setBarcodeLeftMargin = (position) => {
|
|
892
|
+
const n1 = position & 0xFF;
|
|
893
|
+
const n2 = (position >> 8) & 0xFF;
|
|
894
|
+
return [exports.GS, 0x6B, 0x84, n1, n2];
|
|
895
|
+
};
|
|
896
|
+
exports.setBarcodeLeftMargin = setBarcodeLeftMargin;
|
|
897
|
+
// ============================================================================
|
|
898
|
+
// BARCODES - UPC-A
|
|
899
|
+
// ============================================================================
|
|
900
|
+
/**
|
|
901
|
+
* GS k NUL d1 ... d11 NUL - Print UPC-A barcode
|
|
902
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
903
|
+
* Requires exactly 11 digits, checksum generated automatically
|
|
904
|
+
*/
|
|
905
|
+
const printBarcodeUPCA = (data) => {
|
|
906
|
+
if (data.length !== 11 || !/^\d{11}$/.test(data)) {
|
|
907
|
+
throw new Error('UPC-A requires exactly 11 digits');
|
|
908
|
+
}
|
|
909
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
910
|
+
return [exports.GS, 0x6B, exports.NUL, ...bytes, exports.NUL];
|
|
911
|
+
};
|
|
912
|
+
exports.printBarcodeUPCA = printBarcodeUPCA;
|
|
913
|
+
/**
|
|
914
|
+
* GS k A VT d1 ... d11 - Print UPC-A barcode (alternate)
|
|
915
|
+
* Same as GS k NUL variant
|
|
916
|
+
*/
|
|
917
|
+
const printBarcodeUPCAAlt = (data) => {
|
|
918
|
+
if (data.length !== 11 || !/^\d{11}$/.test(data)) {
|
|
919
|
+
throw new Error('UPC-A requires exactly 11 digits');
|
|
920
|
+
}
|
|
921
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
922
|
+
return [exports.GS, 0x6B, 0x41, 0x0B, ...bytes];
|
|
923
|
+
};
|
|
924
|
+
exports.printBarcodeUPCAAlt = printBarcodeUPCAAlt;
|
|
925
|
+
// ============================================================================
|
|
926
|
+
// BARCODES - UPC-E
|
|
927
|
+
// ============================================================================
|
|
928
|
+
/**
|
|
929
|
+
* GS k SOH d1 ... d6 NUL - Print UPC-E barcode
|
|
930
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
931
|
+
* Requires exactly 6 digits, checksum generated automatically
|
|
932
|
+
*/
|
|
933
|
+
const printBarcodeUPCE = (data) => {
|
|
934
|
+
if (data.length !== 6 || !/^\d{6}$/.test(data)) {
|
|
935
|
+
throw new Error('UPC-E requires exactly 6 digits');
|
|
936
|
+
}
|
|
937
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
938
|
+
return [exports.GS, 0x6B, exports.SOH, ...bytes, exports.NUL];
|
|
939
|
+
};
|
|
940
|
+
exports.printBarcodeUPCE = printBarcodeUPCE;
|
|
941
|
+
/**
|
|
942
|
+
* GS k B ACK d1 ... d6 - Print UPC-E barcode (alternate)
|
|
943
|
+
*/
|
|
944
|
+
const printBarcodeUPCEAlt = (data) => {
|
|
945
|
+
if (data.length !== 6 || !/^\d{6}$/.test(data)) {
|
|
946
|
+
throw new Error('UPC-E requires exactly 6 digits');
|
|
947
|
+
}
|
|
948
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
949
|
+
return [exports.GS, 0x6B, 0x42, 0x06, ...bytes];
|
|
950
|
+
};
|
|
951
|
+
exports.printBarcodeUPCEAlt = printBarcodeUPCEAlt;
|
|
952
|
+
// ============================================================================
|
|
953
|
+
// BARCODES - EAN-13
|
|
954
|
+
// ============================================================================
|
|
955
|
+
/**
|
|
956
|
+
* GS k STX d1 ... d12 NUL - Print EAN-13 barcode
|
|
957
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
958
|
+
* Requires exactly 12 digits, 13th digit generated automatically
|
|
959
|
+
*/
|
|
960
|
+
const printBarcodeEAN13 = (data) => {
|
|
961
|
+
if (data.length !== 12 || !/^\d{12}$/.test(data)) {
|
|
962
|
+
throw new Error('EAN-13 requires exactly 12 digits');
|
|
963
|
+
}
|
|
964
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
965
|
+
return [exports.GS, 0x6B, exports.STX, ...bytes, exports.NUL];
|
|
966
|
+
};
|
|
967
|
+
exports.printBarcodeEAN13 = printBarcodeEAN13;
|
|
968
|
+
/**
|
|
969
|
+
* GS k C FF d1 ... d12 - Print EAN-13 barcode (alternate)
|
|
970
|
+
*/
|
|
971
|
+
const printBarcodeEAN13Alt = (data) => {
|
|
972
|
+
if (data.length !== 12 || !/^\d{12}$/.test(data)) {
|
|
973
|
+
throw new Error('EAN-13 requires exactly 12 digits');
|
|
974
|
+
}
|
|
975
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
976
|
+
return [exports.GS, 0x6B, 0x43, 0x0C, ...bytes];
|
|
977
|
+
};
|
|
978
|
+
exports.printBarcodeEAN13Alt = printBarcodeEAN13Alt;
|
|
979
|
+
// ============================================================================
|
|
980
|
+
// BARCODES - EAN-8
|
|
981
|
+
// ============================================================================
|
|
982
|
+
/**
|
|
983
|
+
* GS k ETX d1 ... d7 NUL - Print EAN-8 barcode
|
|
984
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
985
|
+
* Requires exactly 7 digits, 8th digit generated automatically
|
|
986
|
+
*/
|
|
987
|
+
const printBarcodeEAN8 = (data) => {
|
|
988
|
+
if (data.length !== 7 || !/^\d{7}$/.test(data)) {
|
|
989
|
+
throw new Error('EAN-8 requires exactly 7 digits');
|
|
990
|
+
}
|
|
991
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
992
|
+
return [exports.GS, 0x6B, exports.ETX, ...bytes, exports.NUL];
|
|
993
|
+
};
|
|
994
|
+
exports.printBarcodeEAN8 = printBarcodeEAN8;
|
|
995
|
+
/**
|
|
996
|
+
* GS k D BEL d1 ... d7 - Print EAN-8 barcode (alternate)
|
|
997
|
+
*/
|
|
998
|
+
const printBarcodeEAN8Alt = (data) => {
|
|
999
|
+
if (data.length !== 7 || !/^\d{7}$/.test(data)) {
|
|
1000
|
+
throw new Error('EAN-8 requires exactly 7 digits');
|
|
1001
|
+
}
|
|
1002
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1003
|
+
return [exports.GS, 0x6B, 0x44, 0x07, ...bytes];
|
|
1004
|
+
};
|
|
1005
|
+
exports.printBarcodeEAN8Alt = printBarcodeEAN8Alt;
|
|
1006
|
+
// ============================================================================
|
|
1007
|
+
// BARCODES - CODE 39
|
|
1008
|
+
// ============================================================================
|
|
1009
|
+
/**
|
|
1010
|
+
* GS k EOT d1 ... dn NUL - Print CODE 39 barcode
|
|
1011
|
+
* Valid characters: 32 (space), 36 ($), 37 (%), 42 (*), 43 (+), 45-57 (-, ., /, 0-9), 65-90 (A-Z)
|
|
1012
|
+
* Checksum generated automatically
|
|
1013
|
+
* Length limited by physical print width and barcode width setting
|
|
1014
|
+
*/
|
|
1015
|
+
const printBarcodeCODE39 = (data) => {
|
|
1016
|
+
if (!/^[ $%*+\-./0-9A-Z]+$/.test(data)) {
|
|
1017
|
+
throw new Error('CODE 39 supports: space, $%*+-./, 0-9, A-Z');
|
|
1018
|
+
}
|
|
1019
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1020
|
+
return [exports.GS, 0x6B, exports.EOT, ...bytes, exports.NUL];
|
|
1021
|
+
};
|
|
1022
|
+
exports.printBarcodeCODE39 = printBarcodeCODE39;
|
|
1023
|
+
/**
|
|
1024
|
+
* GS k E n d1 ... dn - Print CODE 39 barcode (alternate)
|
|
1025
|
+
*/
|
|
1026
|
+
const printBarcodeCODE39Alt = (data) => {
|
|
1027
|
+
if (!/^[ $%*+\-./0-9A-Z]+$/.test(data)) {
|
|
1028
|
+
throw new Error('CODE 39 supports: space, $%*+-./, 0-9, A-Z');
|
|
1029
|
+
}
|
|
1030
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1031
|
+
return [exports.GS, 0x6B, 0x45, bytes.length, ...bytes];
|
|
1032
|
+
};
|
|
1033
|
+
exports.printBarcodeCODE39Alt = printBarcodeCODE39Alt;
|
|
1034
|
+
// ============================================================================
|
|
1035
|
+
// BARCODES - ITF (Interleaved 2 of 5)
|
|
1036
|
+
// ============================================================================
|
|
1037
|
+
/**
|
|
1038
|
+
* GS k ENQ d1 ... dn NUL - Print ITF barcode
|
|
1039
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
1040
|
+
* Length limited by physical print width and barcode width setting
|
|
1041
|
+
*/
|
|
1042
|
+
const printBarcodeITF = (data) => {
|
|
1043
|
+
if (!/^\d+$/.test(data)) {
|
|
1044
|
+
throw new Error('ITF requires only digits 0-9');
|
|
1045
|
+
}
|
|
1046
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1047
|
+
return [exports.GS, 0x6B, exports.ENQ, ...bytes, exports.NUL];
|
|
1048
|
+
};
|
|
1049
|
+
exports.printBarcodeITF = printBarcodeITF;
|
|
1050
|
+
/**
|
|
1051
|
+
* GS k F n d1 ... dn - Print ITF barcode (alternate)
|
|
1052
|
+
*/
|
|
1053
|
+
const printBarcodeITFAlt = (data) => {
|
|
1054
|
+
if (!/^\d+$/.test(data)) {
|
|
1055
|
+
throw new Error('ITF requires only digits 0-9');
|
|
1056
|
+
}
|
|
1057
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1058
|
+
return [exports.GS, 0x6B, 0x46, bytes.length, ...bytes];
|
|
1059
|
+
};
|
|
1060
|
+
exports.printBarcodeITFAlt = printBarcodeITFAlt;
|
|
1061
|
+
// ============================================================================
|
|
1062
|
+
// BARCODES - CODABAR
|
|
1063
|
+
// ============================================================================
|
|
1064
|
+
/**
|
|
1065
|
+
* GS k ACK d1 ... dn NUL - Print CODABAR barcode
|
|
1066
|
+
* Valid: 36 ($), 43 (+), 45-57 (-, ., /, 0-9), 65-68 (A-D uppercase), 97-100 (a-d lowercase)
|
|
1067
|
+
* Cannot mix uppercase and lowercase letters
|
|
1068
|
+
* If d1 is letter, dn must also be letter
|
|
1069
|
+
*/
|
|
1070
|
+
const printBarcodeCODABAR = (data) => {
|
|
1071
|
+
if (!/^[$+\-./0-9A-D]+$/.test(data) && !/^[$+\-./0-9a-d]+$/.test(data)) {
|
|
1072
|
+
throw new Error('CODABAR supports: $+-./, 0-9, A-D (or a-d, not mixed)');
|
|
1073
|
+
}
|
|
1074
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1075
|
+
return [exports.GS, 0x6B, exports.ACK, ...bytes, exports.NUL];
|
|
1076
|
+
};
|
|
1077
|
+
exports.printBarcodeCODABAR = printBarcodeCODABAR;
|
|
1078
|
+
/**
|
|
1079
|
+
* GS k G n d1 ... dn - Print CODABAR barcode (alternate)
|
|
1080
|
+
*/
|
|
1081
|
+
const printBarcodeCODABARAlt = (data) => {
|
|
1082
|
+
if (!/^[$+\-./0-9A-D]+$/.test(data) && !/^[$+\-./0-9a-d]+$/.test(data)) {
|
|
1083
|
+
throw new Error('CODABAR supports: $+-./, 0-9, A-D (or a-d, not mixed)');
|
|
1084
|
+
}
|
|
1085
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1086
|
+
return [exports.GS, 0x6B, 0x47, bytes.length, ...bytes];
|
|
1087
|
+
};
|
|
1088
|
+
exports.printBarcodeCODABARAlt = printBarcodeCODABARAlt;
|
|
1089
|
+
// ============================================================================
|
|
1090
|
+
// BARCODES - CODE 93
|
|
1091
|
+
// ============================================================================
|
|
1092
|
+
/**
|
|
1093
|
+
* GS k H n d1 ... dn - Print CODE 93 barcode
|
|
1094
|
+
* Range: 0 ≤ dn ≤ 127 (all ASCII characters)
|
|
1095
|
+
* Checksum generated automatically
|
|
1096
|
+
*/
|
|
1097
|
+
const printBarcodeCODE93 = (data) => {
|
|
1098
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1099
|
+
if (bytes.some(b => b > 127)) {
|
|
1100
|
+
throw new Error('CODE 93 supports ASCII 0-127');
|
|
1101
|
+
}
|
|
1102
|
+
return [exports.GS, 0x6B, 0x48, bytes.length, ...bytes];
|
|
1103
|
+
};
|
|
1104
|
+
exports.printBarcodeCODE93 = printBarcodeCODE93;
|
|
1105
|
+
// ============================================================================
|
|
1106
|
+
// BARCODES - CODE 128
|
|
1107
|
+
// ============================================================================
|
|
1108
|
+
/**
|
|
1109
|
+
* GS k I n d1 ... dn - Print CODE 128 barcode
|
|
1110
|
+
* Range: 0 ≤ dn ≤ 127 (all ASCII characters)
|
|
1111
|
+
* Checksum generated automatically
|
|
1112
|
+
*/
|
|
1113
|
+
const printBarcodeCODE128 = (data) => {
|
|
1114
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1115
|
+
if (bytes.some(b => b > 127)) {
|
|
1116
|
+
throw new Error('CODE 128 supports ASCII 0-127');
|
|
1117
|
+
}
|
|
1118
|
+
return [exports.GS, 0x6B, 0x49, bytes.length, ...bytes];
|
|
1119
|
+
};
|
|
1120
|
+
exports.printBarcodeCODE128 = printBarcodeCODE128;
|
|
1121
|
+
// ============================================================================
|
|
1122
|
+
// BARCODES - PDF-417
|
|
1123
|
+
// ============================================================================
|
|
1124
|
+
/**
|
|
1125
|
+
* GS k 80h n1 n2 n3 n4 n5 n6 d1 ... dn - Print PDF-417 barcode
|
|
1126
|
+
* n1: ECC level (0-8)
|
|
1127
|
+
* n2: Pitch height (n2 × 0.125mm)
|
|
1128
|
+
* n3: Pitch width (n3 × 0.125mm, range 1-4)
|
|
1129
|
+
* n4: Codewords per row (0 = max for pitch width)
|
|
1130
|
+
* n5, n6: Byte count (n5 + n6 × 256, must be < 900)
|
|
1131
|
+
*/
|
|
1132
|
+
const printBarcodePDF417 = (eccLevel, pitchHeight, pitchWidth, codewordsPerRow, data) => {
|
|
1133
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1134
|
+
const totalBytes = bytes.length;
|
|
1135
|
+
if (totalBytes >= 900) {
|
|
1136
|
+
throw new Error('PDF-417 data must be less than 900 bytes');
|
|
1137
|
+
}
|
|
1138
|
+
const n1 = Math.max(0, Math.min(8, eccLevel));
|
|
1139
|
+
const n2 = Math.max(1, Math.min(8, pitchHeight));
|
|
1140
|
+
const n3 = Math.max(1, Math.min(4, pitchWidth));
|
|
1141
|
+
const n4 = Math.max(0, Math.min(255, codewordsPerRow));
|
|
1142
|
+
const n5 = totalBytes & 0xFF;
|
|
1143
|
+
const n6 = (totalBytes >> 8) & 0xFF;
|
|
1144
|
+
return [exports.GS, 0x6B, 0x80, n1, n2, n3, n4, n5, n6, ...bytes];
|
|
1145
|
+
};
|
|
1146
|
+
exports.printBarcodePDF417 = printBarcodePDF417;
|
|
1147
|
+
// ============================================================================
|
|
1148
|
+
// BARCODES - ISBN
|
|
1149
|
+
// ============================================================================
|
|
1150
|
+
/**
|
|
1151
|
+
* GS k NAK d1 ... d9 NUL - Print ISBN barcode
|
|
1152
|
+
* Format: X-XXXXX-XXX-X [XXXXX] (hyphens optional in data)
|
|
1153
|
+
* Last char before space: 'X' (88) or digit
|
|
1154
|
+
* After hyphen+X/digit: optional space + 5 more digits
|
|
1155
|
+
*/
|
|
1156
|
+
const printBarcodeISBN = (data) => {
|
|
1157
|
+
// Remove hyphens for validation
|
|
1158
|
+
const clean = data.replace(/-/g, '');
|
|
1159
|
+
if (!/^[\dX][\d ]+$/.test(clean)) {
|
|
1160
|
+
throw new Error('ISBN format: digits, optional X, optional space + 5 digits');
|
|
1161
|
+
}
|
|
1162
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1163
|
+
return [exports.GS, 0x6B, exports.NAK, ...bytes, exports.NUL];
|
|
1164
|
+
};
|
|
1165
|
+
exports.printBarcodeISBN = printBarcodeISBN;
|
|
1166
|
+
// ============================================================================
|
|
1167
|
+
// BARCODES - MSI
|
|
1168
|
+
// ============================================================================
|
|
1169
|
+
/**
|
|
1170
|
+
* GS k SYN d1 ... dn NUL - Print MSI barcode
|
|
1171
|
+
* Range: 48 ≤ dn ≤ 57 (ASCII digits '0'-'9')
|
|
1172
|
+
* Checksum generated automatically
|
|
1173
|
+
*/
|
|
1174
|
+
const printBarcodeMSI = (data) => {
|
|
1175
|
+
if (!/^\d+$/.test(data)) {
|
|
1176
|
+
throw new Error('MSI requires only digits 0-9');
|
|
1177
|
+
}
|
|
1178
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1179
|
+
return [exports.GS, 0x6B, exports.SYN, ...bytes, exports.NUL];
|
|
1180
|
+
};
|
|
1181
|
+
exports.printBarcodeMSI = printBarcodeMSI;
|
|
1182
|
+
/**
|
|
1183
|
+
* GS k 82h n d1 ... dn - Print MSI barcode (alternate)
|
|
1184
|
+
*/
|
|
1185
|
+
const printBarcodeMSIAlt = (data) => {
|
|
1186
|
+
if (!/^\d+$/.test(data)) {
|
|
1187
|
+
throw new Error('MSI requires only digits 0-9');
|
|
1188
|
+
}
|
|
1189
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1190
|
+
return [exports.GS, 0x6B, 0x82, bytes.length, ...bytes];
|
|
1191
|
+
};
|
|
1192
|
+
exports.printBarcodeMSIAlt = printBarcodeMSIAlt;
|
|
1193
|
+
// ============================================================================
|
|
1194
|
+
// BARCODES - PLESSEY
|
|
1195
|
+
// ============================================================================
|
|
1196
|
+
/**
|
|
1197
|
+
* GS k ETB d1 ... dn NUL - Print PLESSEY barcode
|
|
1198
|
+
* Valid: 48-57 (0-9), 65-70 (A-F uppercase), 97-102 (a-f lowercase)
|
|
1199
|
+
* Cannot mix uppercase and lowercase letters
|
|
1200
|
+
* Checksum generated automatically
|
|
1201
|
+
*/
|
|
1202
|
+
const printBarcodePLESSEY = (data) => {
|
|
1203
|
+
if (!/^[0-9A-F]+$/.test(data) && !/^[0-9a-f]+$/.test(data)) {
|
|
1204
|
+
throw new Error('PLESSEY supports: 0-9, A-F (or a-f, not mixed)');
|
|
1205
|
+
}
|
|
1206
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1207
|
+
return [exports.GS, 0x6B, exports.ETB, ...bytes, exports.NUL];
|
|
1208
|
+
};
|
|
1209
|
+
exports.printBarcodePLESSEY = printBarcodePLESSEY;
|
|
1210
|
+
/**
|
|
1211
|
+
* GS k 83h n d1 ... dn - Print PLESSEY barcode (alternate)
|
|
1212
|
+
*/
|
|
1213
|
+
const printBarcodePLESSEYAlt = (data) => {
|
|
1214
|
+
if (!/^[0-9A-F]+$/.test(data) && !/^[0-9a-f]+$/.test(data)) {
|
|
1215
|
+
throw new Error('PLESSEY supports: 0-9, A-F (or a-f, not mixed)');
|
|
1216
|
+
}
|
|
1217
|
+
const bytes = data.split('').map(c => c.charCodeAt(0));
|
|
1218
|
+
return [exports.GS, 0x6B, 0x83, bytes.length, ...bytes];
|
|
1219
|
+
};
|
|
1220
|
+
exports.printBarcodePLESSEYAlt = printBarcodePLESSEYAlt;
|
|
1221
|
+
// ============================================================================
|
|
1222
|
+
// STATUS QUERIES
|
|
1223
|
+
// ============================================================================
|
|
1224
|
+
/**
|
|
1225
|
+
* ENQ - Printer status enquiry
|
|
1226
|
+
* Returns 1 byte with status bits:
|
|
1227
|
+
* Bit 0: 0=offline, 1=online
|
|
1228
|
+
* Bit 1: 0=paper present, 1=paper out
|
|
1229
|
+
* Bit 2: Drawer/paper status (depends on ESC b setting)
|
|
1230
|
+
* Bit 3: 0=print head raised, 1=print head down
|
|
1231
|
+
* Bit 4: 0=paper full, 1=paper near end
|
|
1232
|
+
* Bit 5: 0=command not executed, 1=command executed
|
|
1233
|
+
* Bits 6-7: Unused (always 0)
|
|
1234
|
+
*/
|
|
1235
|
+
exports.STATUS_ENQUIRY = [exports.ENQ];
|
|
1236
|
+
/**
|
|
1237
|
+
* GS F8h 1 - Printer extended status enquiry
|
|
1238
|
+
* Returns 5 status bytes with detailed printer information
|
|
1239
|
+
*/
|
|
1240
|
+
exports.EXTENDED_STATUS = [exports.GS, 0xF8, 0x31];
|
|
1241
|
+
// ============================================================================
|
|
1242
|
+
// BUFFER CONTROL
|
|
1243
|
+
// ============================================================================
|
|
1244
|
+
/**
|
|
1245
|
+
* STX - Clear buffer
|
|
1246
|
+
* Clears print buffer without restoring default printer conditions
|
|
1247
|
+
*/
|
|
1248
|
+
exports.CLEAR_BUFFER = [exports.STX];
|
|
1249
|
+
/**
|
|
1250
|
+
* ETX - End buffer
|
|
1251
|
+
* Printer remains in BUSY state until print buffer becomes empty
|
|
1252
|
+
* DTR (RTS) remains deactivated while printing on serial interfaces
|
|
1253
|
+
*/
|
|
1254
|
+
exports.END_BUFFER = [exports.ETX];
|
|
1255
|
+
/**
|
|
1256
|
+
* CAN - Cancel last line
|
|
1257
|
+
* Clears last line sent to printer
|
|
1258
|
+
* No action if data already dispatched to print head
|
|
1259
|
+
*/
|
|
1260
|
+
exports.CANCEL_LINE = [exports.CAN];
|
|
1261
|
+
/**
|
|
1262
|
+
* DEL - Cancel last character
|
|
1263
|
+
* Clears last character sent to printer
|
|
1264
|
+
* No action if already dispatched to print head
|
|
1265
|
+
*/
|
|
1266
|
+
exports.CANCEL_CHAR = [exports.DEL];
|
|
1267
|
+
// ============================================================================
|
|
1268
|
+
// NETWORK CONFIGURATION - IP ADDRESS
|
|
1269
|
+
// ============================================================================
|
|
1270
|
+
/**
|
|
1271
|
+
* GS F7h BS NUL " i1 i2 i3 i4 s1 s2 s3 s4 - Set IP address and subnet mask
|
|
1272
|
+
* i1-i4: IP address octets
|
|
1273
|
+
* s1-s4: Subnet mask octets
|
|
1274
|
+
*
|
|
1275
|
+
* Example: IP 10.10.1.2, Mask 255.255.0.0
|
|
1276
|
+
* Command: 1D F7 08 00 22 0A 0A 01 02 FF FF 00 00
|
|
1277
|
+
*
|
|
1278
|
+
* Valid only for ethernet or wi-fi interface
|
|
1279
|
+
*/
|
|
1280
|
+
const setIPAddress = (ip, subnet) => {
|
|
1281
|
+
return [exports.GS, 0xF7, 0x08, 0x00, 0x22, ...ip, ...subnet];
|
|
1282
|
+
};
|
|
1283
|
+
exports.setIPAddress = setIPAddress;
|
|
1284
|
+
/**
|
|
1285
|
+
* GS F7h EOT NUL ' g1 g2 g3 g4 - Set default gateway IP address
|
|
1286
|
+
* g1-g4: Gateway IP address octets
|
|
1287
|
+
* Default: 0.0.0.0
|
|
1288
|
+
*
|
|
1289
|
+
* Example: Gateway 192.168.1.2
|
|
1290
|
+
* Command: 1D F7 04 00 27 C0 A8 01 02
|
|
1291
|
+
*/
|
|
1292
|
+
const setGateway = (gateway) => {
|
|
1293
|
+
return [exports.GS, 0xF7, 0x04, 0x00, 0x27, ...gateway];
|
|
1294
|
+
};
|
|
1295
|
+
exports.setGateway = setGateway;
|
|
1296
|
+
// ============================================================================
|
|
1297
|
+
// NETWORK CONFIGURATION - DHCP
|
|
1298
|
+
// ============================================================================
|
|
1299
|
+
/**
|
|
1300
|
+
* GS F9h E n - Set DHCP usage
|
|
1301
|
+
* LSB of n: 0 = DHCP disabled (default), 1 = DHCP enabled
|
|
1302
|
+
* Saves to non-volatile memory
|
|
1303
|
+
* Valid only for ethernet or wi-fi interface
|
|
1304
|
+
*/
|
|
1305
|
+
const enableDHCP = () => [exports.GS, 0xF9, 0x45, 0x01];
|
|
1306
|
+
exports.enableDHCP = enableDHCP;
|
|
1307
|
+
const disableDHCP = () => [exports.GS, 0xF9, 0x45, 0x00];
|
|
1308
|
+
exports.disableDHCP = disableDHCP;
|
|
1309
|
+
// ============================================================================
|
|
1310
|
+
// NETWORK CONFIGURATION - SNMP
|
|
1311
|
+
// ============================================================================
|
|
1312
|
+
/**
|
|
1313
|
+
* GS F9h S m ip1 ip2 ip3 ip4 n c1 ... cn - Set SNMP settings
|
|
1314
|
+
* m: 0 = disabled, non-zero = enabled
|
|
1315
|
+
* ip1-ip4: SNMP trap IP address
|
|
1316
|
+
* n: Community name length (0-64)
|
|
1317
|
+
* c1-cn: Community name bytes
|
|
1318
|
+
*
|
|
1319
|
+
* Valid only for ethernet or wi-fi interface
|
|
1320
|
+
*/
|
|
1321
|
+
const setSNMP = (enabled, ip, community) => {
|
|
1322
|
+
const communityBytes = community.split('').map(c => c.charCodeAt(0)).slice(0, 64);
|
|
1323
|
+
return [exports.GS, 0xF9, 0x53, enabled ? 0x01 : 0x00, ...ip, communityBytes.length, ...communityBytes];
|
|
1324
|
+
};
|
|
1325
|
+
exports.setSNMP = setSNMP;
|
|
1326
|
+
// ============================================================================
|
|
1327
|
+
// NETWORK CONFIGURATION - WI-FI
|
|
1328
|
+
// ============================================================================
|
|
1329
|
+
/**
|
|
1330
|
+
* GS F9h W a s c m n e1...em p1...pn - Set Wi-Fi settings
|
|
1331
|
+
* a: Access mode (0=Access Point, 1=Ad-hoc)
|
|
1332
|
+
* s: Security mode (0=None, 1=WEP 64-bit, 2=WEP 128-bit, 3=WPA-TKIP, 4=WPA2-AES)
|
|
1333
|
+
* c: Channel (0-13, use 0 when a=0)
|
|
1334
|
+
* m: ESSID size (0-32)
|
|
1335
|
+
* n: Passphrase size (0-63)
|
|
1336
|
+
* e1-em: ESSID bytes
|
|
1337
|
+
* p1-pn: Passphrase bytes
|
|
1338
|
+
*
|
|
1339
|
+
* Valid only for wi-fi interface
|
|
1340
|
+
*/
|
|
1341
|
+
const setWiFi = (accessMode, securityMode, channel, essid, passphrase) => {
|
|
1342
|
+
const essidBytes = essid.split('').map(c => c.charCodeAt(0)).slice(0, 32);
|
|
1343
|
+
const passphraseBytes = passphrase.split('').map(c => c.charCodeAt(0)).slice(0, 63);
|
|
1344
|
+
const c = Math.max(0, Math.min(13, channel));
|
|
1345
|
+
return [
|
|
1346
|
+
exports.GS, 0xF9, 0x57,
|
|
1347
|
+
accessMode,
|
|
1348
|
+
securityMode,
|
|
1349
|
+
c,
|
|
1350
|
+
essidBytes.length,
|
|
1351
|
+
passphraseBytes.length,
|
|
1352
|
+
...essidBytes,
|
|
1353
|
+
...passphraseBytes
|
|
1354
|
+
];
|
|
1355
|
+
};
|
|
1356
|
+
exports.setWiFi = setWiFi;
|
|
1357
|
+
// ============================================================================
|
|
1358
|
+
// UTILITY FUNCTIONS
|
|
1359
|
+
// ============================================================================
|
|
1360
|
+
/**
|
|
1361
|
+
* Convert string to code page bytes
|
|
1362
|
+
* Uses CP860 encoding by default (Portuguese)
|
|
1363
|
+
*/
|
|
1364
|
+
const encodeText = (text, codePage = CodePage.CP860) => {
|
|
1365
|
+
// Basic ASCII conversion - full implementation would require proper code page mapping
|
|
1366
|
+
return text.split('').map(c => {
|
|
1367
|
+
const code = c.charCodeAt(0);
|
|
1368
|
+
return code <= 127 ? code : 0x3F; // Replace non-ASCII with '?'
|
|
1369
|
+
});
|
|
1370
|
+
};
|
|
1371
|
+
exports.encodeText = encodeText;
|
|
1372
|
+
/**
|
|
1373
|
+
* Validate barcode data
|
|
1374
|
+
*/
|
|
1375
|
+
const validateBarcodeData = (data, type) => {
|
|
1376
|
+
switch (type) {
|
|
1377
|
+
case 'numeric':
|
|
1378
|
+
return /^\d+$/.test(data);
|
|
1379
|
+
case 'alphanumeric':
|
|
1380
|
+
return /^[A-Z0-9\-. $%+/]+$/.test(data);
|
|
1381
|
+
case 'all':
|
|
1382
|
+
return data.split('').every(c => c.charCodeAt(0) <= 127);
|
|
1383
|
+
default:
|
|
1384
|
+
return false;
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
exports.validateBarcodeData = validateBarcodeData;
|