@delicity/capacitor-thermal-printer 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DelicityThermalPrinter.podspec +28 -0
- package/LICENSE +21 -0
- package/README.md +649 -0
- package/android/build.gradle +122 -0
- package/android/src/main/AndroidManifest.xml +38 -0
- package/android/src/main/java/com/delicity/thermalprinter/Logger.kt +50 -0
- package/android/src/main/java/com/delicity/thermalprinter/ThermalPrinterEngine.kt +528 -0
- package/android/src/main/java/com/delicity/thermalprinter/ThermalPrinterPlugin.kt +334 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/BleAdapter.kt +125 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/BrotherAdapter.kt +206 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/EpsonAdapter.kt +384 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/EscPosAdapter.kt +160 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/EscPosCommands.kt +42 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/EscPosTextEncoder.kt +138 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/PrinterAdapter.kt +95 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/RawTcpAdapter.kt +96 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/SdkContract.kt +158 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/SdkReflect.kt +104 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/StarAdapter.kt +322 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/UsbAdapter.kt +248 -0
- package/android/src/main/java/com/delicity/thermalprinter/adapters/ZebraAdapter.kt +207 -0
- package/android/src/main/java/com/delicity/thermalprinter/discovery/AdapterPriority.kt +39 -0
- package/android/src/main/java/com/delicity/thermalprinter/discovery/BleScanner.kt +70 -0
- package/android/src/main/java/com/delicity/thermalprinter/discovery/BluetoothClassicScanner.kt +112 -0
- package/android/src/main/java/com/delicity/thermalprinter/discovery/DiscoveryManager.kt +136 -0
- package/android/src/main/java/com/delicity/thermalprinter/discovery/TcpScanner.kt +96 -0
- package/android/src/main/java/com/delicity/thermalprinter/image/ImageCache.kt +88 -0
- package/android/src/main/java/com/delicity/thermalprinter/image/ImageProcessor.kt +220 -0
- package/android/src/main/java/com/delicity/thermalprinter/image/TextRasterizer.kt +99 -0
- package/android/src/main/java/com/delicity/thermalprinter/model/Models.kt +206 -0
- package/android/src/main/java/com/delicity/thermalprinter/model/PrintItem.kt +100 -0
- package/android/src/main/java/com/delicity/thermalprinter/store/PrinterStore.kt +71 -0
- package/android/src/main/java/com/delicity/thermalprinter/transport/BleGattClient.kt +201 -0
- package/android/src/main/java/com/delicity/thermalprinter/transport/BluetoothSppTransport.kt +110 -0
- package/android/src/main/java/com/delicity/thermalprinter/transport/ByteTransport.kt +18 -0
- package/android/src/main/java/com/delicity/thermalprinter/transport/TcpTransport.kt +83 -0
- package/dist/esm/adapters/dedup.d.ts +26 -0
- package/dist/esm/adapters/dedup.js +66 -0
- package/dist/esm/adapters/dedup.js.map +1 -0
- package/dist/esm/adapters/priority.d.ts +29 -0
- package/dist/esm/adapters/priority.js +55 -0
- package/dist/esm/adapters/priority.js.map +1 -0
- package/dist/esm/core/enums.d.ts +61 -0
- package/dist/esm/core/enums.js +25 -0
- package/dist/esm/core/enums.js.map +1 -0
- package/dist/esm/core/errors.d.ts +16 -0
- package/dist/esm/core/errors.js +53 -0
- package/dist/esm/core/errors.js.map +1 -0
- package/dist/esm/core/escpos-text.d.ts +33 -0
- package/dist/esm/core/escpos-text.js +239 -0
- package/dist/esm/core/escpos-text.js.map +1 -0
- package/dist/esm/core/imaging.d.ts +91 -0
- package/dist/esm/core/imaging.js +184 -0
- package/dist/esm/core/imaging.js.map +1 -0
- package/dist/esm/core/models.d.ts +131 -0
- package/dist/esm/core/models.js +2 -0
- package/dist/esm/core/models.js.map +1 -0
- package/dist/esm/core/options.d.ts +154 -0
- package/dist/esm/core/options.js +2 -0
- package/dist/esm/core/options.js.map +1 -0
- package/dist/esm/core/text.d.ts +138 -0
- package/dist/esm/core/text.js +14 -0
- package/dist/esm/core/text.js.map +1 -0
- package/dist/esm/definitions.d.ts +155 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +15 -0
- package/dist/esm/index.js +18 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +63 -0
- package/dist/esm/web.js +112 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +224 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +227 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Plugin/Adapters/BrotherAdapter.swift +139 -0
- package/ios/Plugin/Adapters/EpsonAdapter.swift +131 -0
- package/ios/Plugin/Adapters/EscPosAdapter.swift +106 -0
- package/ios/Plugin/Adapters/EscPosCommands.swift +32 -0
- package/ios/Plugin/Adapters/EscPosTextEncoder.swift +115 -0
- package/ios/Plugin/Adapters/PrinterAdapter.swift +44 -0
- package/ios/Plugin/Adapters/RawTcpAdapter.swift +70 -0
- package/ios/Plugin/Adapters/StarAdapter.swift +305 -0
- package/ios/Plugin/Adapters/ZebraAdapter.swift +119 -0
- package/ios/Plugin/Discovery/AdapterPriority.swift +21 -0
- package/ios/Plugin/Discovery/BonjourScanner.swift +51 -0
- package/ios/Plugin/Discovery/DiscoveryManager.swift +86 -0
- package/ios/Plugin/Image/ImageCache.swift +73 -0
- package/ios/Plugin/Image/ImageProcessor.swift +168 -0
- package/ios/Plugin/Image/TextRasterizer.swift +81 -0
- package/ios/Plugin/Logger.swift +33 -0
- package/ios/Plugin/Model/Models.swift +174 -0
- package/ios/Plugin/Model/PrintItem.swift +111 -0
- package/ios/Plugin/Store/PrinterStore.swift +51 -0
- package/ios/Plugin/ThermalPrinterEngine.swift +395 -0
- package/ios/Plugin/ThermalPrinterPlugin.m +22 -0
- package/ios/Plugin/ThermalPrinterPlugin.swift +258 -0
- package/ios/Plugin/Transport/TcpTransport.swift +89 -0
- package/package.json +96 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
package com.delicity.thermalprinter
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.os.Build
|
|
5
|
+
import com.getcapacitor.JSArray
|
|
6
|
+
import com.getcapacitor.JSObject
|
|
7
|
+
import com.getcapacitor.Plugin
|
|
8
|
+
import com.getcapacitor.PluginCall
|
|
9
|
+
import com.getcapacitor.PluginMethod
|
|
10
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
11
|
+
import com.getcapacitor.annotation.Permission
|
|
12
|
+
import com.getcapacitor.annotation.PermissionCallback
|
|
13
|
+
import com.delicity.thermalprinter.discovery.DiscoveryManager
|
|
14
|
+
import com.delicity.thermalprinter.model.PrinterException
|
|
15
|
+
import com.delicity.thermalprinter.model.RenderOptions
|
|
16
|
+
import kotlinx.coroutines.CoroutineScope
|
|
17
|
+
import kotlinx.coroutines.Dispatchers
|
|
18
|
+
import kotlinx.coroutines.SupervisorJob
|
|
19
|
+
import kotlinx.coroutines.launch
|
|
20
|
+
import kotlinx.coroutines.withContext
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Pont Capacitor (bridge JS <-> natif). Mappe l'API publique ThermalPrinterPlugin
|
|
24
|
+
* (definitions.ts) vers le ThermalPrinterEngine.
|
|
25
|
+
*
|
|
26
|
+
* Toutes les opérations longues s'exécutent sur Dispatchers.IO ; les erreurs
|
|
27
|
+
* PrinterException sont converties en rejets Capacitor avec le code normalisé.
|
|
28
|
+
*/
|
|
29
|
+
@CapacitorPlugin(
|
|
30
|
+
name = "ThermalPrinter",
|
|
31
|
+
permissions = [
|
|
32
|
+
Permission(alias = "bluetoothScan", strings = [Manifest.permission.BLUETOOTH_SCAN]),
|
|
33
|
+
Permission(alias = "bluetoothConnect", strings = [Manifest.permission.BLUETOOTH_CONNECT]),
|
|
34
|
+
Permission(alias = "location", strings = [Manifest.permission.ACCESS_FINE_LOCATION]),
|
|
35
|
+
],
|
|
36
|
+
)
|
|
37
|
+
class ThermalPrinterPlugin : Plugin() {
|
|
38
|
+
|
|
39
|
+
private lateinit var engine: ThermalPrinterEngine
|
|
40
|
+
private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
|
|
41
|
+
|
|
42
|
+
override fun load() {
|
|
43
|
+
engine = ThermalPrinterEngine(context)
|
|
44
|
+
// Relaye les états de job vers le JS (event printJobStatus).
|
|
45
|
+
engine.onJobUpdate = { u ->
|
|
46
|
+
val job = JSObject()
|
|
47
|
+
.put("jobId", u.jobId)
|
|
48
|
+
.put("printerId", u.printerId)
|
|
49
|
+
.put("state", u.state)
|
|
50
|
+
.put("updatedAt", System.currentTimeMillis())
|
|
51
|
+
u.holdReason?.let { job.put("holdReason", it) }
|
|
52
|
+
u.progress?.let { job.put("progress", it) }
|
|
53
|
+
u.errorCode?.let { job.put("errorCode", it.name) }
|
|
54
|
+
u.message?.let { job.put("message", it) }
|
|
55
|
+
notifyListeners("printJobStatus", JSObject().put("job", job))
|
|
56
|
+
}
|
|
57
|
+
// Relaye les changements de statut vers le JS (event statusChange).
|
|
58
|
+
engine.onStatusChange = { status ->
|
|
59
|
+
notifyListeners("statusChange", JSObject().put("status", status.toJson()))
|
|
60
|
+
}
|
|
61
|
+
Logger.log("plugin", "loaded")
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ---------------------------------------------------------------------
|
|
65
|
+
// Permissions
|
|
66
|
+
// ---------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
@PluginMethod
|
|
69
|
+
override fun checkPermissions(call: PluginCall) {
|
|
70
|
+
call.resolve(buildPermissionStatus())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@PluginMethod
|
|
74
|
+
override fun requestPermissions(call: PluginCall) {
|
|
75
|
+
// Sur API < 31, les permissions BT runtime n'existent pas -> rien à demander.
|
|
76
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
|
77
|
+
call.resolve(buildPermissionStatus())
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
requestPermissionForAliases(arrayOf("bluetoothScan", "bluetoothConnect"), call, "permsCallback")
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@PermissionCallback
|
|
84
|
+
private fun permsCallback(call: PluginCall) {
|
|
85
|
+
call.resolve(buildPermissionStatus())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
private fun buildPermissionStatus(): JSObject {
|
|
89
|
+
fun state(alias: String): String =
|
|
90
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S && alias.startsWith("bluetooth")) "granted"
|
|
91
|
+
else getPermissionState(alias)?.toString() ?: "prompt"
|
|
92
|
+
return JSObject().apply {
|
|
93
|
+
put("bluetooth", state("bluetoothConnect"))
|
|
94
|
+
put("bluetoothScan", state("bluetoothScan"))
|
|
95
|
+
put("bluetoothConnect", state("bluetoothConnect"))
|
|
96
|
+
put("location", state("location"))
|
|
97
|
+
put("localNetwork", "granted") // pas de permission runtime réseau sur Android
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------
|
|
102
|
+
// Découverte
|
|
103
|
+
// ---------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
@PluginMethod
|
|
106
|
+
fun discoverPrinters(call: PluginCall) = exec(call) {
|
|
107
|
+
val sources = call.getArray("sources", null)?.let { arr ->
|
|
108
|
+
(0 until arr.length()).map { arr.getString(it) }.toSet()
|
|
109
|
+
}
|
|
110
|
+
val options = DiscoveryManager.Options(
|
|
111
|
+
sources = sources,
|
|
112
|
+
timeoutMs = (call.getInt("timeoutMs")?.toLong()) ?: 8000L,
|
|
113
|
+
includePaired = call.getBoolean("includePaired", true) ?: true,
|
|
114
|
+
networkCidr = call.getString("networkCidr"),
|
|
115
|
+
tcpPorts = call.getArray("tcpPorts", null)?.let { arr ->
|
|
116
|
+
(0 until arr.length()).mapNotNull { arr.optInt(it) }
|
|
117
|
+
} ?: listOf(9100),
|
|
118
|
+
)
|
|
119
|
+
val emitPartial = call.getBoolean("emitPartialResults", true) ?: true
|
|
120
|
+
|
|
121
|
+
val (printers, failed) = engine.discover(options) { p ->
|
|
122
|
+
if (emitPartial) notifyListeners("printerFound", JSObject().put("printer", p.toJson()))
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
val arr = JSArray()
|
|
126
|
+
printers.forEach { arr.put(it.toJson()) }
|
|
127
|
+
val failedArr = JSArray()
|
|
128
|
+
failed.forEach { failedArr.put(it) }
|
|
129
|
+
val result = JSObject().put("printers", arr)
|
|
130
|
+
|
|
131
|
+
// Event de fin de découverte.
|
|
132
|
+
notifyListeners(
|
|
133
|
+
"discoveryComplete",
|
|
134
|
+
JSObject().put("printers", arr).put("failedSources", failedArr),
|
|
135
|
+
)
|
|
136
|
+
result
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ---------------------------------------------------------------------
|
|
140
|
+
// Connexion
|
|
141
|
+
// ---------------------------------------------------------------------
|
|
142
|
+
|
|
143
|
+
@PluginMethod
|
|
144
|
+
fun connectPrinter(call: PluginCall) = exec(call) {
|
|
145
|
+
val printerId = call.getString("printerId")
|
|
146
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.PRINTER_NOT_FOUND, "printerId requis")
|
|
147
|
+
val timeout = (call.getInt("timeoutMs")?.toLong()) ?: 10000L
|
|
148
|
+
val force = call.getString("forceAdapter")?.let { com.delicity.thermalprinter.model.AdapterId.from(it) }
|
|
149
|
+
val setAsDefault = call.getBoolean("setAsDefault", false) ?: false
|
|
150
|
+
val connected = engine.connect(printerId, timeout, force, setAsDefault)
|
|
151
|
+
JSObject().put("connected", connected)
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
@PluginMethod
|
|
155
|
+
fun disconnectPrinter(call: PluginCall) = exec(call) {
|
|
156
|
+
engine.disconnect(call.getString("printerId") ?: "")
|
|
157
|
+
JSObject()
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// ---------------------------------------------------------------------
|
|
161
|
+
// Profils / défaut
|
|
162
|
+
// ---------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
@PluginMethod
|
|
165
|
+
fun setDefaultPrinter(call: PluginCall) = exec(call) {
|
|
166
|
+
val id = call.getString("printerId")
|
|
167
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.PRINTER_NOT_FOUND, "printerId requis")
|
|
168
|
+
val profile = engine.setDefault(id)
|
|
169
|
+
JSObject().put("profile", profile.toJson())
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
@PluginMethod
|
|
173
|
+
fun getDefaultPrinter(call: PluginCall) = exec(call) {
|
|
174
|
+
val profile = engine.defaultProfile()
|
|
175
|
+
JSObject().put("profile", profile?.toJson() ?: JSObject.NULL)
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
@PluginMethod
|
|
179
|
+
fun getSavedPrinters(call: PluginCall) = exec(call) {
|
|
180
|
+
val arr = JSArray()
|
|
181
|
+
engine.savedProfiles().forEach { arr.put(it.toJson()) }
|
|
182
|
+
JSObject().put("profiles", arr)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@PluginMethod
|
|
186
|
+
fun removePrinter(call: PluginCall) = exec(call) {
|
|
187
|
+
engine.removeProfile(call.getString("printerId") ?: "")
|
|
188
|
+
JSObject()
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// ---------------------------------------------------------------------
|
|
192
|
+
// Impression / statut
|
|
193
|
+
// ---------------------------------------------------------------------
|
|
194
|
+
|
|
195
|
+
@PluginMethod
|
|
196
|
+
fun printImage(call: PluginCall) = exec(call) {
|
|
197
|
+
val image = call.getObject("image")
|
|
198
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.IMAGE_INVALID, "image requise")
|
|
199
|
+
val render = call.getObject("render")?.let { r ->
|
|
200
|
+
RenderOptions(
|
|
201
|
+
widthDots = r.optInt("widthDots", 0),
|
|
202
|
+
resize = r.optBoolean("resize", true),
|
|
203
|
+
grayscale = r.optBoolean("grayscale", true),
|
|
204
|
+
threshold = r.optInt("threshold", 128),
|
|
205
|
+
dithering = r.optString("dithering", "floyd_steinberg"),
|
|
206
|
+
align = r.optString("align", "center"),
|
|
207
|
+
invert = r.optBoolean("invert", false),
|
|
208
|
+
cut = r.optBoolean("cut", true),
|
|
209
|
+
feedLines = r.optInt("feedLines", 3),
|
|
210
|
+
openCashDrawer = r.optBoolean("openCashDrawer", false),
|
|
211
|
+
copies = r.optInt("copies", 1),
|
|
212
|
+
)
|
|
213
|
+
}
|
|
214
|
+
val req = ThermalPrinterEngine.PrintRequest(
|
|
215
|
+
printerId = call.getString("printerId"),
|
|
216
|
+
filePath = image.optString("filePath", null),
|
|
217
|
+
url = image.optString("url", null),
|
|
218
|
+
base64 = image.optString("base64", null),
|
|
219
|
+
render = render,
|
|
220
|
+
timeoutMs = (call.getInt("timeoutMs")?.toLong()) ?: 15000L,
|
|
221
|
+
autoReconnect = call.getBoolean("autoReconnect", true) ?: true,
|
|
222
|
+
)
|
|
223
|
+
val out = engine.printImage(req)
|
|
224
|
+
printResultJson(out)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@PluginMethod
|
|
228
|
+
fun printText(call: PluginCall) = exec(call) {
|
|
229
|
+
val itemsArr = call.getArray("items")
|
|
230
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.IMAGE_INVALID, "items requis")
|
|
231
|
+
val items = com.delicity.thermalprinter.model.PrintItem.parseList(itemsArr)
|
|
232
|
+
val req = ThermalPrinterEngine.PrintTextRequest(
|
|
233
|
+
printerId = call.getString("printerId"),
|
|
234
|
+
items = items,
|
|
235
|
+
defaultCodePage = call.getString("defaultCodePage") ?: "WPC1252",
|
|
236
|
+
cut = call.getBoolean("cut", false) ?: false,
|
|
237
|
+
feedLines = call.getInt("feedLines") ?: 3,
|
|
238
|
+
timeoutMs = (call.getInt("timeoutMs")?.toLong()) ?: 15000L,
|
|
239
|
+
autoReconnect = call.getBoolean("autoReconnect", true) ?: true,
|
|
240
|
+
)
|
|
241
|
+
val out = engine.printText(req)
|
|
242
|
+
printResultJson(out)
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private fun printResultJson(out: ThermalPrinterEngine.PrintOutcome): JSObject = JSObject().apply {
|
|
246
|
+
put("success", out.state == "completed")
|
|
247
|
+
put("printerId", out.printerId)
|
|
248
|
+
put("adapter", out.adapter.value)
|
|
249
|
+
put("jobId", out.jobId)
|
|
250
|
+
put("state", out.state)
|
|
251
|
+
put("bytesSent", out.bytesSent)
|
|
252
|
+
put("durationMs", out.durationMs)
|
|
253
|
+
out.status?.let { put("status", it.toJson()) }
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
@PluginMethod
|
|
257
|
+
fun getPrinterStatus(call: PluginCall) = exec(call) {
|
|
258
|
+
engine.getStatus(call.getString("printerId")).toJson()
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// ---------------------------------------------------------------------
|
|
262
|
+
// Monitoring (Phase 6) — stubs branchés à compléter
|
|
263
|
+
// ---------------------------------------------------------------------
|
|
264
|
+
|
|
265
|
+
@PluginMethod
|
|
266
|
+
fun startStatusMonitor(call: PluginCall) = exec(call) {
|
|
267
|
+
val printerId = call.getString("printerId")
|
|
268
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.PRINTER_NOT_FOUND, "printerId requis")
|
|
269
|
+
val interval = (call.getInt("intervalMs")?.toLong()) ?: 5000L
|
|
270
|
+
engine.startStatusMonitor(printerId, interval)
|
|
271
|
+
JSObject()
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
@PluginMethod
|
|
275
|
+
fun stopStatusMonitor(call: PluginCall) = exec(call) {
|
|
276
|
+
val printerId = call.getString("printerId")
|
|
277
|
+
?: throw PrinterException(com.delicity.thermalprinter.model.ErrorCode.PRINTER_NOT_FOUND, "printerId requis")
|
|
278
|
+
engine.stopStatusMonitor(printerId)
|
|
279
|
+
JSObject()
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
@PluginMethod
|
|
283
|
+
fun getActiveSdks(call: PluginCall) = exec(call) {
|
|
284
|
+
val arr = JSArray()
|
|
285
|
+
engine.activeSdks().forEach { s ->
|
|
286
|
+
val transports = JSArray()
|
|
287
|
+
s.transports.forEach { transports.put(it) }
|
|
288
|
+
arr.put(
|
|
289
|
+
JSObject()
|
|
290
|
+
.put("adapter", s.adapter)
|
|
291
|
+
.put("label", s.label)
|
|
292
|
+
.put("available", s.available)
|
|
293
|
+
.put("requiresSdk", s.requiresSdk)
|
|
294
|
+
.put("transports", transports),
|
|
295
|
+
)
|
|
296
|
+
}
|
|
297
|
+
JSObject().put("sdks", arr)
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
@PluginMethod
|
|
301
|
+
fun getDebugLog(call: PluginCall) {
|
|
302
|
+
call.resolve(JSObject().put("log", engine.debugLog()))
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
// ---------------------------------------------------------------------
|
|
306
|
+
// Plomberie : exécution async + normalisation d'erreurs
|
|
307
|
+
// ---------------------------------------------------------------------
|
|
308
|
+
|
|
309
|
+
private fun exec(call: PluginCall, block: suspend () -> JSObject) {
|
|
310
|
+
scope.launch {
|
|
311
|
+
try {
|
|
312
|
+
val result = block()
|
|
313
|
+
withContext(Dispatchers.Main) { call.resolve(result) }
|
|
314
|
+
} catch (e: PrinterException) {
|
|
315
|
+
Logger.error("plugin", "${e.code}: ${e.message}", e)
|
|
316
|
+
withContext(Dispatchers.Main) {
|
|
317
|
+
val data = JSObject().put("code", e.code.name).put("detail", e.detail).put("retryable", e.retryable)
|
|
318
|
+
call.reject(e.message, e.code.name, e, data)
|
|
319
|
+
}
|
|
320
|
+
} catch (e: Exception) {
|
|
321
|
+
Logger.error("plugin", "UNKNOWN: ${e.message}", e)
|
|
322
|
+
withContext(Dispatchers.Main) {
|
|
323
|
+
call.reject(e.message ?: "Erreur inconnue", "UNKNOWN", e)
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
override fun handleOnDestroy() {
|
|
330
|
+
super.handleOnDestroy()
|
|
331
|
+
engine.stopAllMonitors()
|
|
332
|
+
scope.coroutineContext[kotlinx.coroutines.Job]?.cancel()
|
|
333
|
+
}
|
|
334
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
package com.delicity.thermalprinter.adapters
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothManager
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.Bitmap
|
|
6
|
+
import com.delicity.thermalprinter.image.ImageProcessor
|
|
7
|
+
import com.delicity.thermalprinter.model.AdapterId
|
|
8
|
+
import com.delicity.thermalprinter.model.DiscoveredPrinter
|
|
9
|
+
import com.delicity.thermalprinter.model.ErrorCode
|
|
10
|
+
import com.delicity.thermalprinter.model.PrinterException
|
|
11
|
+
import com.delicity.thermalprinter.model.PrinterProfile
|
|
12
|
+
import com.delicity.thermalprinter.model.PrinterStatus
|
|
13
|
+
import com.delicity.thermalprinter.model.RenderOptions
|
|
14
|
+
import com.delicity.thermalprinter.model.Transport
|
|
15
|
+
import com.delicity.thermalprinter.transport.BleGattClient
|
|
16
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Adapter BLE (Bluetooth Low Energy) générique pour imprimantes ESC/POS exposant
|
|
20
|
+
* un service GATT d'écriture "série".
|
|
21
|
+
*
|
|
22
|
+
* La connexion GATT + l'écriture par paquets sont déléguées à [BleGattClient]
|
|
23
|
+
* (négociation MTU, allowlist d'UUID, fallback characteristic inscriptible). Le
|
|
24
|
+
* scan BLE concret est fait par BleScanner (DiscoveryManager).
|
|
25
|
+
*
|
|
26
|
+
* Recommandation : valider chaque modèle (allowlist d'UUID dans BleGattClient).
|
|
27
|
+
* Pour le BT classique ESC/POS générique sur Android, préférer SPP (EscPosAdapter).
|
|
28
|
+
*/
|
|
29
|
+
class BleAdapter(private val context: Context) : PrinterAdapter {
|
|
30
|
+
|
|
31
|
+
override val id = AdapterId.ESCPOS // BLE transporte de l'ESC/POS dans la majorité des cas
|
|
32
|
+
|
|
33
|
+
private val connections = ConcurrentHashMap<String, BleGattClient>()
|
|
34
|
+
|
|
35
|
+
private val btAdapter by lazy {
|
|
36
|
+
(context.getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager)?.adapter
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
override fun isAvailable(): Boolean =
|
|
40
|
+
context.packageManager.hasSystemFeature(android.content.pm.PackageManager.FEATURE_BLUETOOTH_LE)
|
|
41
|
+
|
|
42
|
+
override fun supportsTextItems(): Boolean = true
|
|
43
|
+
|
|
44
|
+
override suspend fun discover(timeoutMs: Long, onFound: (DiscoveredPrinter) -> Unit) {
|
|
45
|
+
// Délégué à BleScanner (DiscoveryManager).
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
override fun canHandle(profile: PrinterProfile): Boolean = profile.transport == Transport.BLE
|
|
49
|
+
|
|
50
|
+
override suspend fun connect(profile: PrinterProfile, timeoutMs: Long) {
|
|
51
|
+
ensureBle()
|
|
52
|
+
if (isConnected(profile.id)) return
|
|
53
|
+
val adapter = btAdapter ?: throw PrinterException(ErrorCode.BLUETOOTH_DISABLED, "Bluetooth indisponible")
|
|
54
|
+
val device = try {
|
|
55
|
+
adapter.getRemoteDevice(profile.address)
|
|
56
|
+
} catch (e: IllegalArgumentException) {
|
|
57
|
+
throw PrinterException(ErrorCode.PRINTER_NOT_FOUND, "Adresse BLE invalide: ${profile.address}")
|
|
58
|
+
}
|
|
59
|
+
val client = BleGattClient(context, device)
|
|
60
|
+
client.open(timeoutMs)
|
|
61
|
+
connections[profile.id] = client
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun isConnected(printerId: String): Boolean = connections[printerId]?.isOpen == true
|
|
65
|
+
|
|
66
|
+
override suspend fun disconnect(printerId: String) {
|
|
67
|
+
connections.remove(printerId)?.close()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
override suspend fun printBitmap(profile: PrinterProfile, bitmap: Bitmap, options: RenderOptions): Int {
|
|
71
|
+
val client = requireClient(profile)
|
|
72
|
+
val mono = ImageProcessor.toMono(bitmap, options)
|
|
73
|
+
val raster = ImageProcessor.encodeEscPosRaster(mono)
|
|
74
|
+
val job = EscPosCommands.buildJob(
|
|
75
|
+
rasterData = raster,
|
|
76
|
+
align = options.align,
|
|
77
|
+
feedLines = options.feedLines,
|
|
78
|
+
cut = options.cut && profile.capabilities.supportsCut,
|
|
79
|
+
openDrawer = options.openCashDrawer && profile.capabilities.supportsCashDrawer,
|
|
80
|
+
)
|
|
81
|
+
var sent = 0
|
|
82
|
+
repeat(options.copies.coerceAtLeast(1)) {
|
|
83
|
+
client.write(job)
|
|
84
|
+
sent += job.size
|
|
85
|
+
}
|
|
86
|
+
return sent
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
override suspend fun printItems(
|
|
90
|
+
profile: PrinterProfile,
|
|
91
|
+
items: List<com.delicity.thermalprinter.model.PrintItem>,
|
|
92
|
+
defaultCodePage: String,
|
|
93
|
+
cut: Boolean,
|
|
94
|
+
feedLines: Int,
|
|
95
|
+
): Int {
|
|
96
|
+
val client = requireClient(profile)
|
|
97
|
+
val columns = if (profile.capabilities.printableDots <= 420) 32 else 48
|
|
98
|
+
val encoded = EscPosTextEncoder.encode(items, defaultCodePage, columns)
|
|
99
|
+
val out = java.io.ByteArrayOutputStream()
|
|
100
|
+
out.write(encoded.bytes)
|
|
101
|
+
if (feedLines > 0) out.write(EscPosCommands.feed(feedLines))
|
|
102
|
+
if (cut && profile.capabilities.supportsCut) out.write(EscPosCommands.CUT_PARTIAL)
|
|
103
|
+
val job = out.toByteArray()
|
|
104
|
+
client.write(job)
|
|
105
|
+
return job.size
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override suspend fun getStatus(profile: PrinterProfile): PrinterStatus {
|
|
109
|
+
val open = isConnected(profile.id)
|
|
110
|
+
return PrinterStatus(
|
|
111
|
+
id = profile.id,
|
|
112
|
+
connection = if (open) "connected" else "disconnected",
|
|
113
|
+
online = open,
|
|
114
|
+
paper = "unknown",
|
|
115
|
+
rawStatus = "BLE: statut temps réel non lu (notify spécifique au modèle)",
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private fun requireClient(profile: PrinterProfile): BleGattClient =
|
|
120
|
+
connections[profile.id] ?: throw PrinterException(ErrorCode.CONNECTION_FAILED, "BLE non connecté: ${profile.id}")
|
|
121
|
+
|
|
122
|
+
private fun ensureBle() {
|
|
123
|
+
if (!isAvailable()) throw PrinterException(ErrorCode.UNSUPPORTED_TRANSPORT, "BLE indisponible sur cet appareil")
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
package com.delicity.thermalprinter.adapters
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothManager
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.graphics.Bitmap
|
|
6
|
+
import com.delicity.thermalprinter.model.AdapterId
|
|
7
|
+
import com.delicity.thermalprinter.model.DiscoveredPrinter
|
|
8
|
+
import com.delicity.thermalprinter.model.ErrorCode
|
|
9
|
+
import com.delicity.thermalprinter.model.PrinterException
|
|
10
|
+
import com.delicity.thermalprinter.model.PrinterProfile
|
|
11
|
+
import com.delicity.thermalprinter.model.PrinterStatus
|
|
12
|
+
import com.delicity.thermalprinter.model.RenderOptions
|
|
13
|
+
import com.delicity.thermalprinter.model.Transport
|
|
14
|
+
import java.util.concurrent.ConcurrentHashMap
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Adapter Brother basé sur le Brother Print SDK v4 (`com.brother.sdk.lmprinter`),
|
|
18
|
+
* piloté par RÉFLEXION.
|
|
19
|
+
*
|
|
20
|
+
* Brother est orienté étiquettes (QL / TD / RJ / PJ / PT) : les réglages d'impression
|
|
21
|
+
* (`*PrintSettings`) dépendent du MODÈLE. L'adapter dérive un `PrinterModel` depuis
|
|
22
|
+
* `profile.model` (ex "RJ-3150" -> PrinterModel.RJ_3150). Si le modèle est inconnu,
|
|
23
|
+
* une erreur explicite invite à le préciser.
|
|
24
|
+
*
|
|
25
|
+
* Le SDK n'est pas redistribuable (licence Brother) : déposer
|
|
26
|
+
* `BrotherPrintLibrary.aar` (portail Brother). Voir docs/SDK_INTEGRATION.md (§ Brother).
|
|
27
|
+
*
|
|
28
|
+
* ⚠️ API model-dépendante : à vérifier sur device avec le binaire réel.
|
|
29
|
+
*/
|
|
30
|
+
class BrotherAdapter(private val context: Context) : PrinterAdapter {
|
|
31
|
+
|
|
32
|
+
override val id = AdapterId.BROTHER
|
|
33
|
+
|
|
34
|
+
private val cache = ConcurrentHashMap<String, Any>() // printerId -> PrinterDriver
|
|
35
|
+
|
|
36
|
+
private val btAdapter by lazy {
|
|
37
|
+
(context.getSystemService(Context.BLUETOOTH_SERVICE) as? BluetoothManager)?.adapter
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override fun isAvailable(): Boolean = EpsonAdapter.classExists(DRIVER_GENERATOR)
|
|
41
|
+
|
|
42
|
+
// -------------------------------------------------------------------------
|
|
43
|
+
// Découverte (BRLMPrinterSearcher — réseau)
|
|
44
|
+
// -------------------------------------------------------------------------
|
|
45
|
+
|
|
46
|
+
override suspend fun discover(timeoutMs: Long, onFound: (DiscoveredPrinter) -> Unit) {
|
|
47
|
+
if (!isAvailable()) return
|
|
48
|
+
// L'API de recherche Brother varie selon la version ; on tente la recherche
|
|
49
|
+
// réseau si disponible, sinon on s'appuie sur le scan TCP générique.
|
|
50
|
+
runCatching {
|
|
51
|
+
val option = SdkReflect.newInstance(NET_SEARCH_OPTION, emptyArray(), emptyArray())
|
|
52
|
+
runCatching {
|
|
53
|
+
SdkReflect.call(option, "setSearchDuration", arrayOf(Int::class.javaPrimitiveType!!), arrayOf((timeoutMs / 1000).toInt()))
|
|
54
|
+
}
|
|
55
|
+
val callback = SdkReflect.proxy(SEARCH_RESULT_CALLBACK, mapOf(
|
|
56
|
+
"onChannelInfo" to { args -> handleChannel(args.getOrNull(0), onFound); null },
|
|
57
|
+
"onSearchResult" to { null },
|
|
58
|
+
))
|
|
59
|
+
SdkReflect.callStatic(
|
|
60
|
+
SEARCHER, "startNetworkSearch",
|
|
61
|
+
arrayOf(Context::class.java, SdkReflect.classOrNull(NET_SEARCH_OPTION)!!, SdkReflect.classOrNull(SEARCH_RESULT_CALLBACK)!!),
|
|
62
|
+
arrayOf(context, option, callback),
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
private fun handleChannel(channel: Any?, onFound: (DiscoveredPrinter) -> Unit) {
|
|
68
|
+
if (channel == null) return
|
|
69
|
+
val address = (SdkReflect.call(channel, "getChannelInfo") as? String)
|
|
70
|
+
?: (SdkReflect.field(channel, "channelInfo") as? String) ?: return
|
|
71
|
+
val name = (SdkReflect.call(channel, "getExtraInfo") as? String) ?: "Brother"
|
|
72
|
+
onFound(
|
|
73
|
+
DiscoveredPrinter(
|
|
74
|
+
id = "brother:$address",
|
|
75
|
+
name = name,
|
|
76
|
+
brand = "Brother",
|
|
77
|
+
transport = Transport.WIFI,
|
|
78
|
+
adapter = AdapterId.BROTHER,
|
|
79
|
+
address = address,
|
|
80
|
+
discoveredBy = mutableSetOf(AdapterId.BROTHER),
|
|
81
|
+
),
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
override fun canHandle(profile: PrinterProfile): Boolean =
|
|
86
|
+
isAvailable() && profile.adapter == AdapterId.BROTHER
|
|
87
|
+
|
|
88
|
+
// -------------------------------------------------------------------------
|
|
89
|
+
// Connexion (openChannel -> PrinterDriver)
|
|
90
|
+
// -------------------------------------------------------------------------
|
|
91
|
+
|
|
92
|
+
override suspend fun connect(profile: PrinterProfile, timeoutMs: Long) {
|
|
93
|
+
ensureSdk()
|
|
94
|
+
if (isConnected(profile.id)) return
|
|
95
|
+
val channel = buildChannel(profile)
|
|
96
|
+
val result = SdkReflect.callStatic(
|
|
97
|
+
DRIVER_GENERATOR, "openChannel",
|
|
98
|
+
arrayOf(SdkReflect.classOrNull(CHANNEL)!!), arrayOf(channel),
|
|
99
|
+
) ?: throw PrinterException(ErrorCode.CONNECTION_FAILED, "openChannel Brother null")
|
|
100
|
+
|
|
101
|
+
val driver = SdkReflect.call(result, "getDriver")
|
|
102
|
+
if (driver == null) {
|
|
103
|
+
val err = runCatching { SdkReflect.call(result, "getError")?.let { SdkReflect.call(it, "getCode") } }.getOrNull()
|
|
104
|
+
throw PrinterException(ErrorCode.CONNECTION_FAILED, "Connexion Brother échouée (${err ?: "openChannel"})", retryable = true)
|
|
105
|
+
}
|
|
106
|
+
cache[profile.id] = driver
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
override fun isConnected(printerId: String): Boolean = cache.containsKey(printerId)
|
|
110
|
+
|
|
111
|
+
override suspend fun disconnect(printerId: String) {
|
|
112
|
+
cache.remove(printerId)?.let { runCatching { SdkReflect.call(it, "closeChannel") } }
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// -------------------------------------------------------------------------
|
|
116
|
+
// Impression image
|
|
117
|
+
// -------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
override suspend fun printBitmap(profile: PrinterProfile, bitmap: Bitmap, options: RenderOptions): Int {
|
|
120
|
+
val driver = cache[profile.id]
|
|
121
|
+
?: throw PrinterException(ErrorCode.CONNECTION_FAILED, "Brother non connecté: ${profile.id}")
|
|
122
|
+
val settings = buildPrintSettings(profile)
|
|
123
|
+
try {
|
|
124
|
+
repeat(options.copies.coerceAtLeast(1)) {
|
|
125
|
+
SdkReflect.call(
|
|
126
|
+
driver, "printImage",
|
|
127
|
+
arrayOf(Bitmap::class.java, SdkReflect.classOrNull(PRINT_IMAGE_SETTINGS)!!),
|
|
128
|
+
arrayOf(bitmap, settings),
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
} catch (e: Throwable) {
|
|
132
|
+
throw PrinterException(ErrorCode.PRINT_FAILED, "Impression Brother échouée", e.message, retryable = true)
|
|
133
|
+
}
|
|
134
|
+
return bitmap.width * bitmap.height / 8
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// -------------------------------------------------------------------------
|
|
138
|
+
// Statut
|
|
139
|
+
// -------------------------------------------------------------------------
|
|
140
|
+
|
|
141
|
+
override suspend fun getStatus(profile: PrinterProfile): PrinterStatus {
|
|
142
|
+
val driver = cache[profile.id]
|
|
143
|
+
?: return PrinterStatus(profile.id, "disconnected", online = false, paper = "unknown")
|
|
144
|
+
return try {
|
|
145
|
+
val result = SdkReflect.call(driver, "getPrinterStatus")
|
|
146
|
+
val online = result != null
|
|
147
|
+
PrinterStatus(profile.id, if (online) "connected" else "disconnected", online = online, paper = "unknown", rawStatus = result?.toString())
|
|
148
|
+
} catch (e: Throwable) {
|
|
149
|
+
PrinterStatus(profile.id, "connected", online = true, paper = "unknown", rawStatus = e.message)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// -------------------------------------------------------------------------
|
|
154
|
+
// Helpers
|
|
155
|
+
// -------------------------------------------------------------------------
|
|
156
|
+
|
|
157
|
+
private fun buildChannel(profile: PrinterProfile): Any = when (profile.transport) {
|
|
158
|
+
Transport.WIFI, Transport.ETHERNET -> SdkReflect.callStatic(
|
|
159
|
+
CHANNEL, "newWifiChannel", arrayOf(String::class.java), arrayOf(profile.address.substringBefore(":")),
|
|
160
|
+
) ?: error("newWifiChannel null")
|
|
161
|
+
Transport.BLUETOOTH -> SdkReflect.callStatic(
|
|
162
|
+
CHANNEL, "newBluetoothChannel",
|
|
163
|
+
arrayOf(String::class.java, android.bluetooth.BluetoothAdapter::class.java),
|
|
164
|
+
arrayOf(profile.address, btAdapter),
|
|
165
|
+
) ?: error("newBluetoothChannel null")
|
|
166
|
+
Transport.BLE -> SdkReflect.callStatic(
|
|
167
|
+
CHANNEL, "newBluetoothLowEnergyChannel",
|
|
168
|
+
arrayOf(String::class.java, Context::class.java, android.bluetooth.BluetoothAdapter::class.java),
|
|
169
|
+
arrayOf(profile.address, context, btAdapter),
|
|
170
|
+
) ?: error("newBluetoothLowEnergyChannel null")
|
|
171
|
+
else -> throw PrinterException(ErrorCode.UNSUPPORTED_TRANSPORT, "Transport Brother non supporté: ${profile.transport.value}")
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Construit les *PrintSettings selon la famille du modèle (QL/PJ/RJ/TD/PT).
|
|
176
|
+
* `PrinterModel` est dérivé du nom (ex "RJ-3150" -> RJ_3150).
|
|
177
|
+
*/
|
|
178
|
+
private fun buildPrintSettings(profile: PrinterProfile): Any {
|
|
179
|
+
val model = profile.model
|
|
180
|
+
?: throw PrinterException(ErrorCode.UNSUPPORTED_PRINTER, "Modèle Brother requis (ex 'RJ-3150') pour les réglages d'impression")
|
|
181
|
+
val enumName = model.uppercase().replace("-", "_").replace(" ", "_")
|
|
182
|
+
val family = Regex("^(QL|PJ|RJ|TD|PT)").find(enumName)?.value
|
|
183
|
+
?: throw PrinterException(ErrorCode.UNSUPPORTED_PRINTER, "Famille Brother inconnue pour '$model'")
|
|
184
|
+
val printerModel = SdkReflect.enumValue(PRINTER_MODEL, enumName)
|
|
185
|
+
?: throw PrinterException(ErrorCode.UNSUPPORTED_PRINTER, "PrinterModel Brother inconnu: $enumName")
|
|
186
|
+
val settingsClass = "$SETTING_PKG.${family}PrintSettings"
|
|
187
|
+
return SdkReflect.newInstance(
|
|
188
|
+
settingsClass, arrayOf(SdkReflect.classOrNull(PRINTER_MODEL)!!), arrayOf(printerModel),
|
|
189
|
+
)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
private fun ensureSdk() {
|
|
193
|
+
if (!isAvailable()) throw PrinterException(ErrorCode.SDK_NOT_AVAILABLE, "SDK Brother absent")
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
companion object {
|
|
197
|
+
private const val DRIVER_GENERATOR = "com.brother.sdk.lmprinter.PrinterDriverGenerator"
|
|
198
|
+
private const val CHANNEL = "com.brother.sdk.lmprinter.Channel"
|
|
199
|
+
private const val SEARCHER = "com.brother.sdk.lmprinter.PrinterSearcher"
|
|
200
|
+
private const val NET_SEARCH_OPTION = "com.brother.sdk.lmprinter.NetworkSearchOption"
|
|
201
|
+
private const val SEARCH_RESULT_CALLBACK = "com.brother.sdk.lmprinter.PrinterSearcher\$SearchResultCallback"
|
|
202
|
+
private const val SETTING_PKG = "com.brother.sdk.lmprinter.setting"
|
|
203
|
+
private const val PRINT_IMAGE_SETTINGS = "com.brother.sdk.lmprinter.setting.PrintImageSettings"
|
|
204
|
+
private const val PRINTER_MODEL = "com.brother.sdk.lmprinter.setting.PrinterModel"
|
|
205
|
+
}
|
|
206
|
+
}
|