@hoangnh0099/react-native-sunmi-printer 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,73 +5,81 @@ import android.util.Base64
5
5
  import com.facebook.react.bridge.Promise
6
6
  import com.facebook.react.bridge.ReactApplicationContext
7
7
  import com.facebook.react.bridge.ReadableArray
8
- import com.sunmi.peripheral.printer.InnerLcdCallback
9
- import com.sunmi.peripheral.printer.InnerPrinterCallback
10
- import com.sunmi.peripheral.printer.InnerPrinterManager
11
- import com.sunmi.peripheral.printer.InnerResultCallback
12
- import com.sunmi.peripheral.printer.SunmiPrinterService
8
+ import com.sunmi.printerx.PrinterSdk
9
+ import com.sunmi.printerx.PrinterSdk.Printer
10
+ import com.sunmi.printerx.api.PrintResult
11
+ import com.sunmi.printerx.enums.Align
12
+ import com.sunmi.printerx.enums.Command
13
+ import com.sunmi.printerx.enums.DividingLine
14
+ import com.sunmi.printerx.enums.ErrorLevel
15
+ import com.sunmi.printerx.enums.HumanReadable
16
+ import com.sunmi.printerx.enums.ImageAlgorithm
17
+ import com.sunmi.printerx.enums.PrinterInfo
18
+ import com.sunmi.printerx.enums.PrinterType
19
+ import com.sunmi.printerx.style.BaseStyle
20
+ import com.sunmi.printerx.style.BarcodeStyle
21
+ import com.sunmi.printerx.style.BitmapStyle
22
+ import com.sunmi.printerx.style.QrStyle
23
+ import com.sunmi.printerx.style.LabelStyle
24
+ import com.sunmi.printerx.style.TextStyle
13
25
 
14
26
  class SunmiPrinterModule(reactContext: ReactApplicationContext) :
15
27
  NativeSunmiPrinterSpec(reactContext) {
16
28
 
17
- private var printerService: SunmiPrinterService? = null
18
-
19
- private val printerCallback = object : InnerPrinterCallback() {
20
- override fun onConnected(service: SunmiPrinterService) {
21
- printerService = service
22
- }
23
-
24
- override fun onDisconnected() {
25
- printerService = null
26
- }
29
+ private var printer: Printer? = null
30
+ private var isTransMode = false
31
+
32
+ // Formatting state
33
+ private var currentAlignment: Align = Align.LEFT
34
+ private var currentFontSize: Int = 24
35
+ private var currentFontName: String? = null
36
+ private var currentBold: Boolean = false
37
+ private var currentUnderline: Boolean = false
38
+ private var currentItalic: Boolean = false
39
+ private var currentStrikethrough: Boolean = false
40
+ private var currentAntiWhite: Boolean = false
41
+ private var currentInvert: Boolean = false
42
+ private var currentDoubleWidth: Boolean = false
43
+ private var currentDoubleHeight: Boolean = false
44
+ private var currentTextSpace: Int = 0
45
+ private var currentLineSpacing: Int = -1
46
+
47
+ // WoyouConsts keys
48
+ companion object {
49
+ const val NAME = NativeSunmiPrinterSpec.NAME
50
+ private const val ENABLE_BOLD = 0
51
+ private const val ENABLE_UNDERLINE = 1
52
+ private const val ENABLE_ANTI_WHITE = 2
53
+ private const val ENABLE_STRIKETHROUGH = 3
54
+ private const val ENABLE_ITALIC = 4
55
+ private const val ENABLE_INVERT = 5
56
+ private const val SET_TEXT_RIGHT_SPACING = 6
57
+ private const val SET_LINE_SPACING = 9
58
+ private const val ENABLE_DOUBLE_WIDTH = 14
59
+ private const val ENABLE_DOUBLE_HEIGHT = 15
27
60
  }
28
61
 
29
62
  init {
30
- InnerPrinterManager.getInstance().bindService(reactContext, printerCallback)
31
- }
32
-
33
- private fun getService(promise: Promise): SunmiPrinterService? {
34
- return printerService ?: run {
35
- promise.reject("SERVICE_NOT_CONNECTED", "Printer service is not connected")
63
+ PrinterSdk.getInstance().getPrinter(reactContext, object : PrinterSdk.PrinterListen {
64
+ override fun onDefPrinter(printer: Printer?) {
65
+ this@SunmiPrinterModule.printer = printer
66
+ }
67
+
68
+ override fun onPrinters(printers: MutableList<Printer>?) {
69
+ if (this@SunmiPrinterModule.printer == null && !printers.isNullOrEmpty()) {
70
+ this@SunmiPrinterModule.printer = printers[0]
71
+ }
72
+ }
73
+ })
74
+ }
75
+
76
+ private fun getPrinter(promise: Promise): Printer? {
77
+ return printer ?: run {
78
+ promise.reject("PRINTER_NOT_FOUND", "No printer found")
36
79
  null
37
80
  }
38
81
  }
39
82
 
40
- private fun resultCallback(promise: Promise) = object : InnerResultCallback() {
41
- override fun onRunResult(isSuccess: Boolean) {
42
- if (isSuccess) promise.resolve(null)
43
- else promise.reject("PRINTER_ERROR", "Operation failed")
44
- }
45
-
46
- override fun onReturnString(result: String?) {}
47
-
48
- override fun onRaiseException(code: Int, msg: String?) {
49
- promise.reject("PRINTER_EXCEPTION", msg ?: "Printer exception (code: $code)")
50
- }
51
-
52
- override fun onPrintResult(code: Int, msg: String?) {}
53
- }
54
-
55
- private fun stringResultCallback(promise: Promise) = object : InnerResultCallback() {
56
- override fun onRunResult(isSuccess: Boolean) {}
57
-
58
- override fun onReturnString(result: String?) {
59
- promise.resolve(result)
60
- }
61
-
62
- override fun onRaiseException(code: Int, msg: String?) {
63
- promise.reject("PRINTER_EXCEPTION", msg ?: "Printer exception (code: $code)")
64
- }
65
-
66
- override fun onPrintResult(code: Int, msg: String?) {}
67
- }
68
-
69
- private fun lcdCallback(promise: Promise) = object : InnerLcdCallback() {
70
- override fun onRunResult(show: Boolean) {
71
- promise.resolve(null)
72
- }
73
- }
74
-
75
83
  private fun decodeBitmap(base64: String, promise: Promise): android.graphics.Bitmap? {
76
84
  val bytes = Base64.decode(base64, Base64.DEFAULT)
77
85
  return BitmapFactory.decodeByteArray(bytes, 0, bytes.size) ?: run {
@@ -80,93 +88,128 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
80
88
  }
81
89
  }
82
90
 
91
+ private fun toAlign(value: Int): Align = when (value) {
92
+ 0 -> Align.LEFT
93
+ 1 -> Align.CENTER
94
+ 2 -> Align.RIGHT
95
+ else -> Align.LEFT
96
+ }
97
+
98
+ private fun buildTextStyle(): TextStyle {
99
+ return TextStyle.getStyle().apply {
100
+ setTextSize(currentFontSize)
101
+ enableBold(currentBold)
102
+ enableUnderline(currentUnderline)
103
+ enableStrikethrough(currentStrikethrough)
104
+ enableItalics(currentItalic)
105
+ enableAntiColor(currentAntiWhite)
106
+ enableInvert(currentInvert)
107
+ if (currentDoubleWidth) setTextWidthRatio(2) else setTextWidthRatio(1)
108
+ if (currentDoubleHeight) setTextHeightRatio(2) else setTextHeightRatio(1)
109
+ if (currentTextSpace > 0) setTextSpace(currentTextSpace)
110
+ currentFontName?.let { if (it.isNotEmpty()) setFont(it) }
111
+ }
112
+ }
113
+
83
114
  // region Printer Info
84
115
 
85
116
  override fun getPrinterSerialNo(promise: Promise) {
86
- val service = getService(promise) ?: return
117
+ val p = getPrinter(promise) ?: return
87
118
  try {
88
- promise.resolve(service.printerSerialNo)
119
+ promise.resolve(p.queryApi().getInfo(PrinterInfo.ID))
89
120
  } catch (e: Exception) {
90
121
  promise.reject("PRINTER_ERROR", e.message, e)
91
122
  }
92
123
  }
93
124
 
94
125
  override fun getPrinterVersion(promise: Promise) {
95
- val service = getService(promise) ?: return
126
+ val p = getPrinter(promise) ?: return
96
127
  try {
97
- promise.resolve(service.printerVersion)
128
+ promise.resolve(p.queryApi().getInfo(PrinterInfo.VERSION))
98
129
  } catch (e: Exception) {
99
130
  promise.reject("PRINTER_ERROR", e.message, e)
100
131
  }
101
132
  }
102
133
 
103
134
  override fun getPrinterModal(promise: Promise) {
104
- val service = getService(promise) ?: return
135
+ val p = getPrinter(promise) ?: return
105
136
  try {
106
- promise.resolve(service.printerModal)
137
+ promise.resolve(p.queryApi().getInfo(PrinterInfo.NAME))
107
138
  } catch (e: Exception) {
108
139
  promise.reject("PRINTER_ERROR", e.message, e)
109
140
  }
110
141
  }
111
142
 
112
143
  override fun getPrinterPaper(promise: Promise) {
113
- val service = getService(promise) ?: return
144
+ val p = getPrinter(promise) ?: return
114
145
  try {
115
- promise.resolve(service.printerPaper)
146
+ val paper = p.queryApi().getInfo(PrinterInfo.PAPER)
147
+ val paperWidth = paper?.replace("mm", "")?.trim()?.toIntOrNull() ?: 0
148
+ promise.resolve(paperWidth)
116
149
  } catch (e: Exception) {
117
150
  promise.reject("PRINTER_ERROR", e.message, e)
118
151
  }
119
152
  }
120
153
 
121
154
  override fun getPrinterMode(promise: Promise) {
122
- val service = getService(promise) ?: return
155
+ val p = getPrinter(promise) ?: return
123
156
  try {
124
- promise.resolve(service.printerMode)
157
+ val type = p.queryApi().getInfo(PrinterInfo.TYPE)
158
+ val mode = when (type) {
159
+ PrinterType.THERMAL.toString() -> 0
160
+ PrinterType.BLACK_LABEL.toString() -> 1
161
+ PrinterType.LABEL.toString() -> 2
162
+ else -> 0
163
+ }
164
+ promise.resolve(mode)
125
165
  } catch (e: Exception) {
126
166
  promise.reject("PRINTER_ERROR", e.message, e)
127
167
  }
128
168
  }
129
169
 
130
170
  override fun getServiceVersion(promise: Promise) {
131
- val service = getService(promise) ?: return
171
+ val p = getPrinter(promise) ?: return
132
172
  try {
133
- promise.resolve(service.serviceVersion)
173
+ promise.resolve(p.queryApi().getInfo(PrinterInfo.VERSION))
134
174
  } catch (e: Exception) {
135
175
  promise.reject("PRINTER_ERROR", e.message, e)
136
176
  }
137
177
  }
138
178
 
139
179
  override fun getFirmwareStatus(promise: Promise) {
140
- val service = getService(promise) ?: return
180
+ val p = getPrinter(promise) ?: return
141
181
  try {
142
- promise.resolve(service.firmwareStatus)
182
+ // PrinterX SDK does not expose firmware update status directly.
183
+ // Returns 0 (unknown). Use updatePrinterState() for operational status.
184
+ promise.resolve(0)
143
185
  } catch (e: Exception) {
144
186
  promise.reject("PRINTER_ERROR", e.message, e)
145
187
  }
146
188
  }
147
189
 
148
190
  override fun updatePrinterState(promise: Promise) {
149
- val service = getService(promise) ?: return
191
+ val p = getPrinter(promise) ?: return
150
192
  try {
151
- promise.resolve(service.updatePrinterState())
193
+ promise.resolve(p.queryApi().status.ordinal)
152
194
  } catch (e: Exception) {
153
195
  promise.reject("PRINTER_ERROR", e.message, e)
154
196
  }
155
197
  }
156
198
 
157
199
  override fun getPrintedLength(promise: Promise) {
158
- val service = getService(promise) ?: return
200
+ val p = getPrinter(promise) ?: return
159
201
  try {
160
- service.getPrintedLength(stringResultCallback(promise))
202
+ val distance = p.queryApi().getInfo(PrinterInfo.DISTANCE)
203
+ promise.resolve(distance ?: "0")
161
204
  } catch (e: Exception) {
162
205
  promise.reject("PRINTER_ERROR", e.message, e)
163
206
  }
164
207
  }
165
208
 
166
209
  override fun getPrinterFactory(promise: Promise) {
167
- val service = getService(promise) ?: return
210
+ val p = getPrinter(promise) ?: return
168
211
  try {
169
- service.getPrinterFactory(stringResultCallback(promise))
212
+ promise.resolve("SUNMI")
170
213
  } catch (e: Exception) {
171
214
  promise.reject("PRINTER_ERROR", e.message, e)
172
215
  }
@@ -177,18 +220,37 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
177
220
  // region Initialization
178
221
 
179
222
  override fun printerInit(promise: Promise) {
180
- val service = getService(promise) ?: return
181
- try {
182
- service.printerInit(resultCallback(promise))
223
+ val p = getPrinter(promise) ?: return
224
+ try {
225
+ currentAlignment = Align.LEFT
226
+ currentFontSize = 24
227
+ currentFontName = null
228
+ currentBold = false
229
+ currentUnderline = false
230
+ currentItalic = false
231
+ currentStrikethrough = false
232
+ currentAntiWhite = false
233
+ currentInvert = false
234
+ currentDoubleWidth = false
235
+ currentDoubleHeight = false
236
+ currentTextSpace = 0
237
+ currentLineSpacing = -1
238
+ p.lineApi()?.initLine(BaseStyle.getStyle())
239
+ promise.resolve(null)
183
240
  } catch (e: Exception) {
184
241
  promise.reject("PRINTER_ERROR", e.message, e)
185
242
  }
186
243
  }
187
244
 
188
245
  override fun printerSelfChecking(promise: Promise) {
189
- val service = getService(promise) ?: return
246
+ val p = getPrinter(promise) ?: return
190
247
  try {
191
- service.printerSelfChecking(resultCallback(promise))
248
+ p.lineApi()?.run {
249
+ initLine(BaseStyle.getStyle().setAlign(Align.CENTER))
250
+ printText("Printer Self Check OK", TextStyle.getStyle())
251
+ autoOut()
252
+ }
253
+ promise.resolve(null)
192
254
  } catch (e: Exception) {
193
255
  promise.reject("PRINTER_ERROR", e.message, e)
194
256
  }
@@ -199,36 +261,49 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
199
261
  // region Formatting
200
262
 
201
263
  override fun setAlignment(alignment: Double, promise: Promise) {
202
- val service = getService(promise) ?: return
203
264
  try {
204
- service.setAlignment(alignment.toInt(), resultCallback(promise))
265
+ currentAlignment = toAlign(alignment.toInt())
266
+ promise.resolve(null)
205
267
  } catch (e: Exception) {
206
268
  promise.reject("PRINTER_ERROR", e.message, e)
207
269
  }
208
270
  }
209
271
 
210
272
  override fun setFontName(typeface: String, promise: Promise) {
211
- val service = getService(promise) ?: return
212
273
  try {
213
- service.setFontName(typeface, resultCallback(promise))
274
+ currentFontName = typeface
275
+ promise.resolve(null)
214
276
  } catch (e: Exception) {
215
277
  promise.reject("PRINTER_ERROR", e.message, e)
216
278
  }
217
279
  }
218
280
 
219
281
  override fun setFontSize(fontsize: Double, promise: Promise) {
220
- val service = getService(promise) ?: return
221
282
  try {
222
- service.setFontSize(fontsize.toFloat(), resultCallback(promise))
283
+ currentFontSize = fontsize.toInt()
284
+ promise.resolve(null)
223
285
  } catch (e: Exception) {
224
286
  promise.reject("PRINTER_ERROR", e.message, e)
225
287
  }
226
288
  }
227
289
 
228
290
  override fun setPrinterStyle(key: Double, value: Double, promise: Promise) {
229
- val service = getService(promise) ?: return
230
291
  try {
231
- service.setPrinterStyle(key.toInt(), value.toInt())
292
+ val k = key.toInt()
293
+ val v = value.toInt()
294
+ val enabled = v == 1
295
+ when (k) {
296
+ ENABLE_BOLD -> currentBold = enabled
297
+ ENABLE_UNDERLINE -> currentUnderline = enabled
298
+ ENABLE_ANTI_WHITE -> currentAntiWhite = enabled
299
+ ENABLE_STRIKETHROUGH -> currentStrikethrough = enabled
300
+ ENABLE_ITALIC -> currentItalic = enabled
301
+ ENABLE_INVERT -> currentInvert = enabled
302
+ SET_TEXT_RIGHT_SPACING -> currentTextSpace = v
303
+ SET_LINE_SPACING -> currentLineSpacing = v
304
+ ENABLE_DOUBLE_WIDTH -> currentDoubleWidth = enabled
305
+ ENABLE_DOUBLE_HEIGHT -> currentDoubleHeight = enabled
306
+ }
232
307
  promise.resolve(null)
233
308
  } catch (e: Exception) {
234
309
  promise.reject("PRINTER_ERROR", e.message, e)
@@ -240,27 +315,40 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
240
315
  // region Text
241
316
 
242
317
  override fun printText(text: String, promise: Promise) {
243
- val service = getService(promise) ?: return
318
+ val p = getPrinter(promise) ?: return
244
319
  try {
245
- service.printText(text, resultCallback(promise))
320
+ p.lineApi()?.run {
321
+ initLine(BaseStyle.getStyle().setAlign(currentAlignment))
322
+ printText(text, buildTextStyle())
323
+ if (!isTransMode) autoOut()
324
+ }
325
+ promise.resolve(null)
246
326
  } catch (e: Exception) {
247
327
  promise.reject("PRINTER_ERROR", e.message, e)
248
328
  }
249
329
  }
250
330
 
251
331
  override fun printTextWithFont(text: String, typeface: String, fontsize: Double, promise: Promise) {
252
- val service = getService(promise) ?: return
253
- try {
254
- service.printTextWithFont(text, typeface, fontsize.toFloat(), resultCallback(promise))
332
+ val p = getPrinter(promise) ?: return
333
+ try {
334
+ val style = buildTextStyle().setTextSize(fontsize.toInt())
335
+ if (typeface.isNotEmpty()) style.setFont(typeface)
336
+ p.lineApi()?.run {
337
+ initLine(BaseStyle.getStyle().setAlign(currentAlignment))
338
+ printText(text, style)
339
+ if (!isTransMode) autoOut()
340
+ }
341
+ promise.resolve(null)
255
342
  } catch (e: Exception) {
256
343
  promise.reject("PRINTER_ERROR", e.message, e)
257
344
  }
258
345
  }
259
346
 
260
347
  override fun printOriginalText(text: String, promise: Promise) {
261
- val service = getService(promise) ?: return
348
+ val p = getPrinter(promise) ?: return
262
349
  try {
263
- service.printOriginalText(text, resultCallback(promise))
350
+ p.commandApi()?.sendEscCommand(text.toByteArray(Charsets.UTF_8))
351
+ promise.resolve(null)
264
352
  } catch (e: Exception) {
265
353
  promise.reject("PRINTER_ERROR", e.message, e)
266
354
  }
@@ -271,20 +359,101 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
271
359
  // region Image
272
360
 
273
361
  override fun printImage(base64: String, promise: Promise) {
274
- val service = getService(promise) ?: return
362
+ val p = getPrinter(promise) ?: return
275
363
  try {
276
364
  val bitmap = decodeBitmap(base64, promise) ?: return
277
- service.printBitmap(bitmap, resultCallback(promise))
365
+ p.lineApi()?.run {
366
+ printBitmap(bitmap, BitmapStyle.getStyle().setAlign(currentAlignment))
367
+ if (!isTransMode) autoOut()
368
+ }
369
+ promise.resolve(null)
278
370
  } catch (e: Exception) {
279
371
  promise.reject("PRINTER_ERROR", e.message, e)
280
372
  }
281
373
  }
282
374
 
283
375
  override fun printBitmapCustom(base64: String, type: Double, promise: Promise) {
284
- val service = getService(promise) ?: return
376
+ val p = getPrinter(promise) ?: return
285
377
  try {
286
378
  val bitmap = decodeBitmap(base64, promise) ?: return
287
- service.printBitmapCustom(bitmap, type.toInt(), resultCallback(promise))
379
+ val algorithm = when (type.toInt()) {
380
+ 0 -> ImageAlgorithm.BINARIZATION
381
+ 1 -> ImageAlgorithm.DITHERING
382
+ else -> ImageAlgorithm.BINARIZATION
383
+ }
384
+ p.lineApi()?.run {
385
+ printBitmap(bitmap, BitmapStyle.getStyle().setAlign(currentAlignment).setAlgorithm(algorithm))
386
+ if (!isTransMode) autoOut()
387
+ }
388
+ promise.resolve(null)
389
+ } catch (e: Exception) {
390
+ promise.reject("PRINTER_ERROR", e.message, e)
391
+ }
392
+ }
393
+
394
+ // endregion
395
+
396
+ // region Print Style Query
397
+
398
+ override fun getForcedDouble(promise: Promise) {
399
+ try {
400
+ val value = when {
401
+ currentDoubleWidth && currentDoubleHeight -> 3
402
+ currentDoubleHeight -> 2
403
+ currentDoubleWidth -> 1
404
+ else -> 0
405
+ }
406
+ promise.resolve(value)
407
+ } catch (e: Exception) {
408
+ promise.reject("PRINTER_ERROR", e.message, e)
409
+ }
410
+ }
411
+
412
+ override fun isForcedBold(promise: Promise) {
413
+ try {
414
+ promise.resolve(currentBold)
415
+ } catch (e: Exception) {
416
+ promise.reject("PRINTER_ERROR", e.message, e)
417
+ }
418
+ }
419
+
420
+ override fun isForcedUnderline(promise: Promise) {
421
+ try {
422
+ promise.resolve(currentUnderline)
423
+ } catch (e: Exception) {
424
+ promise.reject("PRINTER_ERROR", e.message, e)
425
+ }
426
+ }
427
+
428
+ override fun isForcedAntiWhite(promise: Promise) {
429
+ try {
430
+ promise.resolve(currentAntiWhite)
431
+ } catch (e: Exception) {
432
+ promise.reject("PRINTER_ERROR", e.message, e)
433
+ }
434
+ }
435
+
436
+ override fun getPrinterDensity(promise: Promise) {
437
+ val p = getPrinter(promise) ?: return
438
+ try {
439
+ val density = p.queryApi().getInfo(PrinterInfo.DENSITY)
440
+ promise.resolve(density?.toIntOrNull() ?: 0)
441
+ } catch (e: Exception) {
442
+ promise.reject("PRINTER_ERROR", e.message, e)
443
+ }
444
+ }
445
+
446
+ override fun getForcedRowHeight(promise: Promise) {
447
+ try {
448
+ promise.resolve(currentLineSpacing)
449
+ } catch (e: Exception) {
450
+ promise.reject("PRINTER_ERROR", e.message, e)
451
+ }
452
+ }
453
+
454
+ override fun getCurrentFontName(promise: Promise) {
455
+ try {
456
+ promise.resolve(currentFontName ?: "")
288
457
  } catch (e: Exception) {
289
458
  promise.reject("PRINTER_ERROR", e.message, e)
290
459
  }
@@ -302,25 +471,107 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
302
471
  textposition: Double,
303
472
  promise: Promise
304
473
  ) {
305
- val service = getService(promise) ?: return
306
- try {
307
- service.printBarCode(
308
- data,
309
- symbology.toInt(),
310
- height.toInt(),
311
- width.toInt(),
312
- textposition.toInt(),
313
- resultCallback(promise)
314
- )
474
+ val p = getPrinter(promise) ?: return
475
+ try {
476
+ val readable = when (textposition.toInt()) {
477
+ 0 -> HumanReadable.HIDE
478
+ 1 -> HumanReadable.POS_ONE
479
+ 2 -> HumanReadable.POS_TWO
480
+ 3 -> HumanReadable.POS_THREE
481
+ else -> HumanReadable.POS_TWO
482
+ }
483
+ p.lineApi()?.run {
484
+ initLine(BaseStyle.getStyle().setAlign(currentAlignment))
485
+ printBarCode(data, BarcodeStyle.getStyle()
486
+ .setAlign(currentAlignment)
487
+ .setBarHeight(height.toInt())
488
+ .setDotWidth(width.toInt())
489
+ .setReadable(readable))
490
+ if (!isTransMode) autoOut()
491
+ }
492
+ promise.resolve(null)
315
493
  } catch (e: Exception) {
316
494
  promise.reject("PRINTER_ERROR", e.message, e)
317
495
  }
318
496
  }
319
497
 
320
498
  override fun printQRCode(data: String, modulesize: Double, errorlevel: Double, promise: Promise) {
321
- val service = getService(promise) ?: return
322
- try {
323
- service.printQRCode(data, modulesize.toInt(), errorlevel.toInt(), resultCallback(promise))
499
+ val p = getPrinter(promise) ?: return
500
+ try {
501
+ val level = when (errorlevel.toInt()) {
502
+ 0 -> ErrorLevel.L
503
+ 1 -> ErrorLevel.M
504
+ 2 -> ErrorLevel.Q
505
+ 3 -> ErrorLevel.H
506
+ else -> ErrorLevel.L
507
+ }
508
+ p.lineApi()?.run {
509
+ initLine(BaseStyle.getStyle().setAlign(currentAlignment))
510
+ printQrCode(data, QrStyle.getStyle()
511
+ .setAlign(currentAlignment)
512
+ .setDot(modulesize.toInt())
513
+ .setErrorLevel(level))
514
+ if (!isTransMode) autoOut()
515
+ }
516
+ promise.resolve(null)
517
+ } catch (e: Exception) {
518
+ promise.reject("PRINTER_ERROR", e.message, e)
519
+ }
520
+ }
521
+
522
+ override fun print2DCode(data: String, symbology: Double, modulesize: Double, errorlevel: Double, promise: Promise) {
523
+ val p = getPrinter(promise) ?: return
524
+ try {
525
+ when (symbology.toInt()) {
526
+ 1 -> {
527
+ // QR Code - delegate to printQrCode
528
+ val level = when (errorlevel.toInt()) {
529
+ 0 -> ErrorLevel.L
530
+ 1 -> ErrorLevel.M
531
+ 2 -> ErrorLevel.Q
532
+ 3 -> ErrorLevel.H
533
+ else -> ErrorLevel.L
534
+ }
535
+ p.lineApi()?.run {
536
+ initLine(BaseStyle.getStyle().setAlign(currentAlignment))
537
+ printQrCode(data, QrStyle.getStyle()
538
+ .setAlign(currentAlignment)
539
+ .setDot(modulesize.toInt())
540
+ .setErrorLevel(level))
541
+ if (!isTransMode) autoOut()
542
+ }
543
+ }
544
+ 2 -> {
545
+ // PDF417 via ESC/POS GS ( k commands
546
+ val dataBytes = data.toByteArray(Charsets.UTF_8)
547
+ val storeLen = dataBytes.size + 3
548
+ val pL = (storeLen and 0xFF).toByte()
549
+ val pH = ((storeLen shr 8) and 0xFF).toByte()
550
+ val cmd = byteArrayOf(
551
+ 0x1D, 0x28, 0x6B, 0x03, 0x00, 0x30, 0x43, modulesize.toInt().toByte(),
552
+ 0x1D, 0x28, 0x6B, 0x04, 0x00, 0x30, 0x45, 0x30, errorlevel.toInt().toByte()
553
+ ) + byteArrayOf(0x1D, 0x28, 0x6B, pL, pH, 0x30, 0x50, 0x30) + dataBytes +
554
+ byteArrayOf(0x1D, 0x28, 0x6B, 0x03, 0x00, 0x30, 0x51, 0x30)
555
+ p.commandApi()?.sendEscCommand(cmd)
556
+ }
557
+ 3 -> {
558
+ // DataMatrix via ESC/POS GS ( k commands
559
+ val dataBytes = data.toByteArray(Charsets.UTF_8)
560
+ val storeLen = dataBytes.size + 3
561
+ val pL = (storeLen and 0xFF).toByte()
562
+ val pH = ((storeLen shr 8) and 0xFF).toByte()
563
+ val cmd = byteArrayOf(
564
+ 0x1D, 0x28, 0x6B, 0x03, 0x00, 0x36, 0x43, modulesize.toInt().toByte()
565
+ ) + byteArrayOf(0x1D, 0x28, 0x6B, pL, pH, 0x36, 0x50, 0x30) + dataBytes +
566
+ byteArrayOf(0x1D, 0x28, 0x6B, 0x03, 0x00, 0x36, 0x51, 0x30)
567
+ p.commandApi()?.sendEscCommand(cmd)
568
+ }
569
+ else -> {
570
+ promise.reject("PRINTER_ERROR", "Unsupported 2D symbology: ${symbology.toInt()}")
571
+ return
572
+ }
573
+ }
574
+ promise.resolve(null)
324
575
  } catch (e: Exception) {
325
576
  promise.reject("PRINTER_ERROR", e.message, e)
326
577
  }
@@ -331,27 +582,25 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
331
582
  // region Table
332
583
 
333
584
  override fun printColumnsText(texts: ReadableArray, widths: ReadableArray, aligns: ReadableArray, promise: Promise) {
334
- val service = getService(promise) ?: return
585
+ val p = getPrinter(promise) ?: return
335
586
  try {
336
- val textsArr = Array(texts.size()) { texts.getString(it) }
587
+ val textsArr = Array(texts.size()) { texts.getString(it) ?: "" }
337
588
  val widthsArr = IntArray(widths.size()) { widths.getInt(it) }
338
- val alignsArr = IntArray(aligns.size()) { aligns.getInt(it) }
339
- service.printColumnsText(textsArr, widthsArr, alignsArr, resultCallback(promise))
589
+ val stylesArr = Array(aligns.size()) {
590
+ TextStyle.getStyle().setAlign(toAlign(aligns.getInt(it)))
591
+ }
592
+ p.lineApi()?.run {
593
+ printTexts(textsArr, widthsArr, stylesArr)
594
+ if (!isTransMode) autoOut()
595
+ }
596
+ promise.resolve(null)
340
597
  } catch (e: Exception) {
341
598
  promise.reject("PRINTER_ERROR", e.message, e)
342
599
  }
343
600
  }
344
601
 
345
602
  override fun printColumnsString(texts: ReadableArray, widths: ReadableArray, aligns: ReadableArray, promise: Promise) {
346
- val service = getService(promise) ?: return
347
- try {
348
- val textsArr = Array(texts.size()) { texts.getString(it) }
349
- val widthsArr = IntArray(widths.size()) { widths.getInt(it) }
350
- val alignsArr = IntArray(aligns.size()) { aligns.getInt(it) }
351
- service.printColumnsString(textsArr, widthsArr, alignsArr, resultCallback(promise))
352
- } catch (e: Exception) {
353
- promise.reject("PRINTER_ERROR", e.message, e)
354
- }
603
+ printColumnsText(texts, widths, aligns, promise)
355
604
  }
356
605
 
357
606
  // endregion
@@ -359,10 +608,11 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
359
608
  // region Raw
360
609
 
361
610
  override fun sendRAWData(data: ReadableArray, promise: Promise) {
362
- val service = getService(promise) ?: return
611
+ val p = getPrinter(promise) ?: return
363
612
  try {
364
613
  val bytes = ByteArray(data.size()) { data.getInt(it).toByte() }
365
- service.sendRAWData(bytes, resultCallback(promise))
614
+ p.commandApi()?.sendEscCommand(bytes)
615
+ promise.resolve(null)
366
616
  } catch (e: Exception) {
367
617
  promise.reject("PRINTER_ERROR", e.message, e)
368
618
  }
@@ -373,27 +623,34 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
373
623
  // region Paper
374
624
 
375
625
  override fun lineWrap(lines: Double, promise: Promise) {
376
- val service = getService(promise) ?: return
626
+ val p = getPrinter(promise) ?: return
377
627
  try {
378
- service.lineWrap(lines.toInt(), resultCallback(promise))
628
+ p.lineApi()?.run {
629
+ printDividingLine(DividingLine.EMPTY, lines.toInt() * 30)
630
+ if (!isTransMode) autoOut()
631
+ }
632
+ promise.resolve(null)
379
633
  } catch (e: Exception) {
380
634
  promise.reject("PRINTER_ERROR", e.message, e)
381
635
  }
382
636
  }
383
637
 
384
638
  override fun cutPaper(promise: Promise) {
385
- val service = getService(promise) ?: return
639
+ val p = getPrinter(promise) ?: return
386
640
  try {
387
- service.cutPaper(resultCallback(promise))
641
+ // ESC/POS cut command: GS V 1
642
+ p.commandApi()?.sendEscCommand(byteArrayOf(0x1d, 0x56, 0x01))
643
+ promise.resolve(null)
388
644
  } catch (e: Exception) {
389
645
  promise.reject("PRINTER_ERROR", e.message, e)
390
646
  }
391
647
  }
392
648
 
393
649
  override fun autoOutPaper(promise: Promise) {
394
- val service = getService(promise) ?: return
650
+ val p = getPrinter(promise) ?: return
395
651
  try {
396
- service.autoOutPaper(resultCallback(promise))
652
+ p.lineApi()?.autoOut()
653
+ promise.resolve(null)
397
654
  } catch (e: Exception) {
398
655
  promise.reject("PRINTER_ERROR", e.message, e)
399
656
  }
@@ -404,9 +661,54 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
404
661
  // region Cash Drawer
405
662
 
406
663
  override fun openDrawer(promise: Promise) {
407
- val service = getService(promise) ?: return
664
+ val p = getPrinter(promise) ?: return
665
+ try {
666
+ p.cashDrawerApi()?.open(null)
667
+ promise.resolve(null)
668
+ } catch (e: Exception) {
669
+ promise.reject("PRINTER_ERROR", e.message, e)
670
+ }
671
+ }
672
+
673
+ override fun getDrawerStatus(promise: Promise) {
674
+ val p = getPrinter(promise) ?: return
675
+ try {
676
+ val isOpen = p.cashDrawerApi()?.isOpen() ?: false
677
+ promise.resolve(if (isOpen) 1 else 0)
678
+ } catch (e: Exception) {
679
+ promise.reject("PRINTER_ERROR", e.message, e)
680
+ }
681
+ }
682
+
683
+ override fun getOpenDrawerTimes(promise: Promise) {
684
+ val p = getPrinter(promise) ?: return
685
+ try {
686
+ // PrinterX SDK does not track drawer open count. Returns 0.
687
+ promise.resolve(0)
688
+ } catch (e: Exception) {
689
+ promise.reject("PRINTER_ERROR", e.message, e)
690
+ }
691
+ }
692
+
693
+ // endregion
694
+
695
+ // region Cut Paper Info
696
+
697
+ override fun getCutPaperTimes(promise: Promise) {
698
+ val p = getPrinter(promise) ?: return
408
699
  try {
409
- service.openDrawer(resultCallback(promise))
700
+ val cutter = p.queryApi().getInfo(PrinterInfo.CUTTER)
701
+ promise.resolve(cutter?.toIntOrNull() ?: 0)
702
+ } catch (e: Exception) {
703
+ promise.reject("PRINTER_ERROR", e.message, e)
704
+ }
705
+ }
706
+
707
+ override fun getPrinterBBMDistance(promise: Promise) {
708
+ val p = getPrinter(promise) ?: return
709
+ try {
710
+ val distance = p.queryApi().getInfo(PrinterInfo.DISTANCE)
711
+ promise.resolve(distance?.toIntOrNull() ?: 0)
410
712
  } catch (e: Exception) {
411
713
  promise.reject("PRINTER_ERROR", e.message, e)
412
714
  }
@@ -417,9 +719,9 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
417
719
  // region Label
418
720
 
419
721
  override fun labelLocate(promise: Promise) {
420
- val service = getService(promise) ?: return
722
+ val p = getPrinter(promise) ?: return
421
723
  try {
422
- service.labelLocate()
724
+ p.lineApi()?.initLine(LabelStyle.getStyle().setAlign(currentAlignment))
423
725
  promise.resolve(null)
424
726
  } catch (e: Exception) {
425
727
  promise.reject("PRINTER_ERROR", e.message, e)
@@ -427,9 +729,9 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
427
729
  }
428
730
 
429
731
  override fun labelOutput(promise: Promise) {
430
- val service = getService(promise) ?: return
732
+ val p = getPrinter(promise) ?: return
431
733
  try {
432
- service.labelOutput()
734
+ p.lineApi()?.autoOut()
433
735
  promise.resolve(null)
434
736
  } catch (e: Exception) {
435
737
  promise.reject("PRINTER_ERROR", e.message, e)
@@ -441,9 +743,36 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
441
743
  // region LCD
442
744
 
443
745
  override fun sendLCDCommand(flag: Double, promise: Promise) {
444
- val service = getService(promise) ?: return
746
+ val p = getPrinter(promise) ?: return
747
+ try {
748
+ val command = when (flag.toInt()) {
749
+ 1 -> Command.INIT
750
+ 2 -> Command.WAKE
751
+ 3 -> Command.SLEEP
752
+ 4 -> Command.CLEAR
753
+ else -> Command.INIT
754
+ }
755
+ p.lcdApi()?.config(command)
756
+ promise.resolve(null)
757
+ } catch (e: Exception) {
758
+ promise.reject("PRINTER_ERROR", e.message, e)
759
+ }
760
+ }
761
+
762
+ override fun sendLCDString(text: String, promise: Promise) {
763
+ val p = getPrinter(promise) ?: return
764
+ try {
765
+ p.lcdApi()?.showText(text, 0, false)
766
+ promise.resolve(null)
767
+ } catch (e: Exception) {
768
+ promise.reject("PRINTER_ERROR", e.message, e)
769
+ }
770
+ }
771
+
772
+ override fun sendLCDDoubleString(topText: String, bottomText: String, promise: Promise) {
773
+ val p = getPrinter(promise) ?: return
445
774
  try {
446
- service.sendLCDCommand(flag.toInt())
775
+ p.lcdApi()?.showTexts(arrayOf(topText, bottomText), intArrayOf(1, 1))
447
776
  promise.resolve(null)
448
777
  } catch (e: Exception) {
449
778
  promise.reject("PRINTER_ERROR", e.message, e)
@@ -451,30 +780,33 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
451
780
  }
452
781
 
453
782
  override fun sendLCDFillString(text: String, size: Double, fill: Boolean, promise: Promise) {
454
- val service = getService(promise) ?: return
783
+ val p = getPrinter(promise) ?: return
455
784
  try {
456
- service.sendLCDFillString(text, size.toInt(), fill, lcdCallback(promise))
785
+ p.lcdApi()?.showText(text, size.toInt(), fill)
786
+ promise.resolve(null)
457
787
  } catch (e: Exception) {
458
788
  promise.reject("PRINTER_ERROR", e.message, e)
459
789
  }
460
790
  }
461
791
 
462
792
  override fun sendLCDMultiString(texts: ReadableArray, align: ReadableArray, promise: Promise) {
463
- val service = getService(promise) ?: return
793
+ val p = getPrinter(promise) ?: return
464
794
  try {
465
- val textsArr = Array(texts.size()) { texts.getString(it) }
795
+ val textsArr = Array(texts.size()) { texts.getString(it) ?: "" }
466
796
  val alignArr = IntArray(align.size()) { align.getInt(it) }
467
- service.sendLCDMultiString(textsArr, alignArr, lcdCallback(promise))
797
+ p.lcdApi()?.showTexts(textsArr, alignArr)
798
+ promise.resolve(null)
468
799
  } catch (e: Exception) {
469
800
  promise.reject("PRINTER_ERROR", e.message, e)
470
801
  }
471
802
  }
472
803
 
473
804
  override fun sendLCDBitmap(base64: String, promise: Promise) {
474
- val service = getService(promise) ?: return
805
+ val p = getPrinter(promise) ?: return
475
806
  try {
476
807
  val bitmap = decodeBitmap(base64, promise) ?: return
477
- service.sendLCDBitmap(bitmap, lcdCallback(promise))
808
+ p.lcdApi()?.showBitmap(bitmap)
809
+ promise.resolve(null)
478
810
  } catch (e: Exception) {
479
811
  promise.reject("PRINTER_ERROR", e.message, e)
480
812
  }
@@ -485,9 +817,13 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
485
817
  // region Transaction
486
818
 
487
819
  override fun enterPrinterBuffer(clean: Boolean, promise: Promise) {
488
- val service = getService(promise) ?: return
820
+ val p = getPrinter(promise) ?: return
489
821
  try {
490
- service.enterPrinterBuffer(clean)
822
+ isTransMode = true
823
+ p.lineApi()?.enableTransMode(true)
824
+ if (clean) {
825
+ p.lineApi()?.initLine(BaseStyle.getStyle())
826
+ }
491
827
  promise.resolve(null)
492
828
  } catch (e: Exception) {
493
829
  promise.reject("PRINTER_ERROR", e.message, e)
@@ -495,32 +831,56 @@ class SunmiPrinterModule(reactContext: ReactApplicationContext) :
495
831
  }
496
832
 
497
833
  override fun exitPrinterBuffer(commit: Boolean, promise: Promise) {
498
- val service = getService(promise) ?: return
834
+ val p = getPrinter(promise) ?: return
499
835
  try {
500
- service.exitPrinterBufferWithCallback(commit, resultCallback(promise))
836
+ if (commit) {
837
+ p.lineApi()?.autoOut()
838
+ p.lineApi()?.printTrans(object : PrintResult() {
839
+ override fun onResult(resultCode: Int, message: String?) {
840
+ isTransMode = false
841
+ p.lineApi()?.enableTransMode(false)
842
+ if (resultCode == 0) promise.resolve(null)
843
+ else promise.reject("PRINTER_ERROR", message ?: "Print failed")
844
+ }
845
+ })
846
+ } else {
847
+ isTransMode = false
848
+ p.lineApi()?.enableTransMode(false)
849
+ promise.resolve(null)
850
+ }
501
851
  } catch (e: Exception) {
502
852
  promise.reject("PRINTER_ERROR", e.message, e)
503
853
  }
504
854
  }
505
855
 
506
856
  override fun commitPrinterBuffer(promise: Promise) {
507
- val service = getService(promise) ?: return
857
+ val p = getPrinter(promise) ?: return
508
858
  try {
509
- service.commitPrinterBufferWithCallback(resultCallback(promise))
859
+ p.lineApi()?.autoOut()
860
+ p.lineApi()?.printTrans(object : PrintResult() {
861
+ override fun onResult(resultCode: Int, message: String?) {
862
+ if (resultCode == 0) promise.resolve(null)
863
+ else promise.reject("PRINTER_ERROR", message ?: "Print failed")
864
+ }
865
+ })
510
866
  } catch (e: Exception) {
511
867
  promise.reject("PRINTER_ERROR", e.message, e)
512
868
  }
513
869
  }
514
870
 
871
+ override fun commitPrinterBufferWithCallback(promise: Promise) {
872
+ commitPrinterBuffer(promise)
873
+ }
874
+
875
+ override fun exitPrinterBufferWithCallback(commit: Boolean, promise: Promise) {
876
+ exitPrinterBuffer(commit, promise)
877
+ }
878
+
515
879
  // endregion
516
880
 
517
881
  override fun invalidate() {
518
882
  super.invalidate()
519
- InnerPrinterManager.getInstance().unBindService(reactApplicationContext, printerCallback)
520
- printerService = null
521
- }
522
-
523
- companion object {
524
- const val NAME = NativeSunmiPrinterSpec.NAME
883
+ PrinterSdk.getInstance().destroy()
884
+ printer = null
525
885
  }
526
886
  }