package com.reactnativethermalprint import android.annotation.SuppressLint import android.graphics.Bitmap import android.util.Log import com.bumptech.glide.Glide import com.reactnativethermalprint.escposprinter.connection.DeviceConnection import com.reactnativethermalprint.escposprinter.connection.bluetooth.BluetoothConnection import com.reactnativethermalprint.escposprinter.connection.tcp.TcpConnection import com.reactnativethermalprint.escposprinter.textparser.PrinterTextParserImg import com.facebook.react.bridge.* import com.reactnativethermalprint.async.* import com.reactnativethermalprint.bluetooth.BluetoothPrintersConnections import java.util.regex.Matcher import java.util.regex.Pattern class ThermalPrintModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) { private var selectedDevice: BluetoothConnection? = null private var currentBluetooth: Boolean = false private var currentTcp: Boolean = false override fun getName(): String { return "ReactNativeThermalPrint" } private fun _printTcp(configs: Configs, callbacksPrint: CallbackPrint){ if(!currentTcp){ currentTcp = true val connection = TcpConnection(configs.address, configs.port, configs.timeout) val params = getAsyncEscPosPrinter(configs.text, connection, configs) val qrText = if (configs.textQr.length > 1) getAsyncEscPosPrinter(configs.textQr, TcpConnection(configs.address, configs.port, configs.timeout), configs) else null val callbacks = object : CallbackPrint { override fun resolve() { callbacksPrint.resolve() currentTcp = false } override fun rejected(params: WritableMap?) { callbacksPrint.rejected(params) currentTcp = false } } AsyncTcpEscPosPrint(currentActivity, reactApplicationContext, configs, callbacks).execute(params, qrText) } } private fun _printBluetooth(configs: Configs, callbacksPrint: CallbackPrint){ connectBluetooth(configs.address) if(!currentBluetooth){ currentBluetooth = true val paramsText = getAsyncEscPosPrinter(configs.text, selectedDevice!!, configs) val paramsQr = if (configs.textQr.length > 1) getAsyncEscPosPrinter(configs.textQr, selectedDevice!!, configs) else null val callbacks = object : CallbackPrint { override fun resolve() { callbacksPrint.resolve() currentBluetooth = false } override fun rejected(params: WritableMap?) { callbacksPrint.rejected(params) currentBluetooth = false } } AsyncBluetoothEscPosPrint(currentActivity, reactApplicationContext, configs, callbacks).execute(paramsText, paramsQr) } } private fun _printUsb(configs: Configs, callbacksPrint: CallbackPrint){ // TODO: impementar } @ReactMethod fun printTcp(configsMap: ReadableMap, promiseResolve: Callback, promiseReject: Callback) { try { val configs = Configs(configsMap) val callbacks = object : CallbackPrint { override fun resolve() { promiseResolve.invoke() } override fun rejected(params: WritableMap?) { promiseReject.invoke(params) } } _printTcp(configs, callbacks) } catch (e: Error) { val map = Arguments.createMap() map.putString("message", e.message) map.putInt("code", e.hashCode()) promiseReject.invoke(map) } } @ReactMethod fun printBluetooth(configsMap: ReadableMap, promiseResolve: Callback, promiseReject: Callback) { try { val configs = Configs(configsMap) val callbacks = object : CallbackPrint { override fun resolve() { promiseResolve.invoke() } override fun rejected(params: WritableMap?) { promiseReject.invoke(params) } } _printBluetooth(configs, callbacks) } catch (e: Error) { val map = Arguments.createMap() map.putString("message", e.message) map.putInt("code", e.hashCode()) promiseReject.invoke(map) } } @ReactMethod fun printUsb(configsMap: ReadableMap, promiseResolve: Callback, promiseReject: Callback) { try { val configs = Configs(configsMap) val callbacks = object : CallbackPrint { override fun resolve() { promiseResolve.invoke() } override fun rejected(params: WritableMap?) { promiseReject.invoke(params) } } _printUsb(configs, callbacks) } catch (e: Error) { val map = Arguments.createMap() map.putString("message", e.message) map.putInt("code", e.hashCode()) promiseReject.invoke(map) } } @ReactMethod fun print(configsMap: ReadableMap, promiseResolve: Callback, promiseReject: Callback) { try { val configs = Configs(configsMap) val callbacks = object : CallbackPrint { override fun resolve() { promiseResolve.invoke() } override fun rejected(params: WritableMap?) { promiseReject.invoke(params) } } if(configs.type === Configs.BLT){ _printBluetooth(configs, callbacks) } else if(configs.type === Configs.TCP){ _printTcp(configs, callbacks) } else if(configs.type === Configs.USB){ _printUsb(configs, callbacks) } else{ val map = Arguments.createMap() map.putString("message", "Configuración inválida") map.putInt("code", 500) promiseReject.invoke(map) } } catch (e: Error) { val map = Arguments.createMap() map.putString("message", e.message) map.putInt("code", e.hashCode()) promiseReject.invoke(map) } } @ReactMethod fun getDevicesBluetooth(successCallback: Callback, errorCallback: Callback) { try { val bluetoothDevicesList = BluetoothPrintersConnections().list if (bluetoothDevicesList != null) { val items = Arguments.createArray() for (device in bluetoothDevicesList) { val objectTrack = Arguments.createMap() objectTrack.putString("name", device.device.name) objectTrack.putString("address", device.device.address) items.pushMap(objectTrack) } successCallback.invoke(items) }else{ errorCallback.invoke("No Device Found") } } catch (e: NumberFormatException) { errorCallback.invoke("Error") } } @SuppressLint("SimpleDateFormat") fun getAsyncEscPosPrinter(text: String, printerConnection: DeviceConnection, configs: Configs): AsyncEscPosPrinter? { val printer = AsyncEscPosPrinter(printerConnection, configs.printerDpi, configs.printerWidthMM, configs.printerNbrCharactersPerLine) val newText = preprocessorImageTagFile(printer, text, configs.imageMaxHeight) return printer.setTextToPrint(newText.trimIndent()) } private fun getBitmapFromPath(path: String): Bitmap? { Log.i("path", path) return try { Glide .with(currentActivity!!) .asBitmap() .load(path) .submit() .get() } catch (e: Exception) { e.printStackTrace() null } } private fun connectBluetooth(address: String){ val bluetoothDevicesList = BluetoothPrintersConnections().list selectedDevice = null if(bluetoothDevicesList != null){ for (device in bluetoothDevicesList){ Log.i("BLT",device.device.address ) Log.i("BLT", address) if(device.device.address == address){ selectedDevice = device break } } if(selectedDevice == null){ throw Error("No hay dispositivos con esa dirección") } }else{ throw Error("No hay dispositivos conectado") } } private fun preprocessorImageTagFile(printer: AsyncEscPosPrinter, text: String, imageMaxHeight: Int): String { val p: Pattern = Pattern.compile("(?<=\\)(.*)(?=\\<\\/img\\>)") val m: Matcher = p.matcher(text) val sb = StringBuffer() while (m.find()) { val firstGroup = m.group(1) val bitmap = getBitmapFromPath(firstGroup) if(imageMaxHeight !== 0){ m.appendReplacement(sb, PrinterTextParserImg.bitmapToHexadecimalString(printer, bitmap, imageMaxHeight)) } else { m.appendReplacement(sb, PrinterTextParserImg.bitmapToHexadecimalString(printer, bitmap)) } } m.appendTail(sb) return sb.toString() } }