@autorunify/capacitor-bleprinter 0.0.1
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/AutorunifyCapacitorBleprinter.podspec +17 -0
- package/Package.swift +28 -0
- package/README.md +342 -0
- package/android/build.gradle +67 -0
- package/android/libs/LPAPI-2024-10-21-R.jar +0 -0
- package/android/src/main/AndroidManifest.xml +21 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/AsyncManager.kt +118 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/BleDevice.kt +45 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/BleManager.kt +214 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/BlePrinter.kt +29 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/BlePrinterPlugin.kt +272 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/DotHanTechPrinter.kt +120 -0
- package/android/src/main/java/com/autorunify/capacitor/bleprinter/FormatManager.kt +13 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +1320 -0
- package/dist/esm/definitions.d.ts +56 -0
- package/dist/esm/definitions.js +2 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +4 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +14 -0
- package/dist/esm/web.js +14 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +28 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +31 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Sources/BlePrinterPlugin/BlePrinter.swift +8 -0
- package/ios/Sources/BlePrinterPlugin/BlePrinterPlugin.swift +23 -0
- package/ios/Tests/BlePrinterPluginTests/BlePrinterTests.swift +15 -0
- package/package.json +81 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
package com.autorunify.capacitor.bleprinter
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.bluetooth.BluetoothAdapter
|
|
5
|
+
import android.bluetooth.BluetoothDevice
|
|
6
|
+
import android.bluetooth.BluetoothManager
|
|
7
|
+
import android.content.BroadcastReceiver
|
|
8
|
+
import android.content.Context
|
|
9
|
+
import android.content.Intent
|
|
10
|
+
import android.content.IntentFilter
|
|
11
|
+
import android.content.pm.PackageManager
|
|
12
|
+
import androidx.lifecycle.MutableLiveData
|
|
13
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_STATE_CONNECTED
|
|
14
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_STATE_DISCONNECTED
|
|
15
|
+
import com.getcapacitor.JSObject
|
|
16
|
+
import com.getcapacitor.PluginCall
|
|
17
|
+
import no.nordicsemi.android.support.v18.scanner.BluetoothLeScannerCompat
|
|
18
|
+
import no.nordicsemi.android.support.v18.scanner.ScanCallback
|
|
19
|
+
import no.nordicsemi.android.support.v18.scanner.ScanFilter
|
|
20
|
+
import no.nordicsemi.android.support.v18.scanner.ScanResult
|
|
21
|
+
import no.nordicsemi.android.support.v18.scanner.ScanSettings
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class BleManager {
|
|
25
|
+
private class StateReceiver : BroadcastReceiver {
|
|
26
|
+
private val ble: BleManager
|
|
27
|
+
|
|
28
|
+
constructor(bleManager: BleManager) {
|
|
29
|
+
this.ble = bleManager
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
override fun onReceive(context: Context, intent: Intent) {
|
|
33
|
+
val eventName = "state"
|
|
34
|
+
val state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)
|
|
35
|
+
|
|
36
|
+
when (state) {
|
|
37
|
+
BluetoothAdapter.STATE_ON -> {
|
|
38
|
+
ble.notify.notifyListeners(eventName, JSObject().apply {
|
|
39
|
+
ble.isConnected.postValue(false)
|
|
40
|
+
put("action", "enabled")
|
|
41
|
+
put("state", true)
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
BluetoothAdapter.STATE_OFF -> {
|
|
46
|
+
ble.notify.notifyListeners(eventName, JSObject().apply {
|
|
47
|
+
ble.isConnected.postValue(false)
|
|
48
|
+
put("action", "enabled")
|
|
49
|
+
put("state", false)
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
when (intent.action) {
|
|
55
|
+
BluetoothDevice.ACTION_ACL_CONNECTED -> {
|
|
56
|
+
ble.isConnected.postValue(true)
|
|
57
|
+
ble.notify.notifyListeners(eventName, JSObject().apply {
|
|
58
|
+
put("action", "connected")
|
|
59
|
+
put("state", true)
|
|
60
|
+
})
|
|
61
|
+
|
|
62
|
+
ble.async.emit(JSObject(), PRINTER_STATE_CONNECTED)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
BluetoothDevice.ACTION_ACL_DISCONNECTED -> {
|
|
66
|
+
ble.isConnected.postValue(false)
|
|
67
|
+
ble.notify.notifyListeners(eventName, JSObject().apply {
|
|
68
|
+
put("action", "connected")
|
|
69
|
+
put("state", false)
|
|
70
|
+
})
|
|
71
|
+
ble.async.emit(JSObject(), PRINTER_STATE_DISCONNECTED)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private class ScanReceiver : ScanCallback {
|
|
78
|
+
private val ble: BleManager
|
|
79
|
+
|
|
80
|
+
constructor(bleManager: BleManager) {
|
|
81
|
+
this.ble = bleManager
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
override fun onScanResult(callbackType: Int, result: ScanResult) {
|
|
85
|
+
val device = BleDevice(result)
|
|
86
|
+
synchronized(ble.devices) {
|
|
87
|
+
if (!ble.devices.contains(device)) {
|
|
88
|
+
ble.devices.add(device)
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
override fun onScanFailed(errorCode: Int) {
|
|
94
|
+
ble.scan(false)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
val notify: BlePrinterPlugin
|
|
99
|
+
val async: AsyncManager
|
|
100
|
+
|
|
101
|
+
private lateinit var context: Context
|
|
102
|
+
private lateinit var adapter: BluetoothAdapter
|
|
103
|
+
private lateinit var stateReceiver: StateReceiver
|
|
104
|
+
private lateinit var scanReceiver: ScanReceiver
|
|
105
|
+
|
|
106
|
+
private var isSupported: Boolean = false
|
|
107
|
+
private var isScanning: Boolean = false
|
|
108
|
+
|
|
109
|
+
var filters: MutableList<ScanFilter> = mutableListOf()
|
|
110
|
+
val devices: MutableList<BleDevice> = mutableListOf()
|
|
111
|
+
val isConnected = MutableLiveData<Boolean>(false)
|
|
112
|
+
|
|
113
|
+
constructor(notify: BlePrinterPlugin, asyncManager: AsyncManager) {
|
|
114
|
+
this.notify = notify
|
|
115
|
+
this.async = asyncManager
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
fun load(activity: Activity, context: Context) {
|
|
119
|
+
this.isSupported =
|
|
120
|
+
activity.packageManager.hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)
|
|
121
|
+
if (!this.isSupported) return
|
|
122
|
+
|
|
123
|
+
val manager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
|
|
124
|
+
this.adapter = manager.adapter
|
|
125
|
+
this.context = context
|
|
126
|
+
|
|
127
|
+
this.stateReceiver = StateReceiver(this)
|
|
128
|
+
this.scanReceiver = ScanReceiver(this)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
fun init() {
|
|
132
|
+
isConnected.postValue(false)
|
|
133
|
+
try {
|
|
134
|
+
val filter = IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)
|
|
135
|
+
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED)
|
|
136
|
+
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED)
|
|
137
|
+
context.registerReceiver(this.stateReceiver, filter)
|
|
138
|
+
} catch (ex: Exception) {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
fun kill() {
|
|
143
|
+
isConnected.postValue(false)
|
|
144
|
+
try {
|
|
145
|
+
context.unregisterReceiver(this.stateReceiver)
|
|
146
|
+
} catch (ex: Exception) {
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
fun assertFeature(call: PluginCall): Boolean {
|
|
151
|
+
if (!isSupported) {
|
|
152
|
+
call.reject("BLE is not supported.")
|
|
153
|
+
return false
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
fun assertAdapter(call: PluginCall): Boolean {
|
|
160
|
+
if (adapter == null) {
|
|
161
|
+
call.reject("BLE is not available.")
|
|
162
|
+
return false
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return true
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
fun assertEnabled(call: PluginCall): Boolean {
|
|
169
|
+
if (adapter != null && adapter.isEnabled) {
|
|
170
|
+
return true
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
call.reject("BLE is not enabled")
|
|
174
|
+
return false
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
fun assertConnected(call: PluginCall): Boolean {
|
|
178
|
+
if (isConnected.value == true) return true
|
|
179
|
+
|
|
180
|
+
call.reject("BLE is not connected")
|
|
181
|
+
return false
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
fun isEnabled(): Boolean {
|
|
185
|
+
if (adapter != null) return adapter.isEnabled
|
|
186
|
+
return false
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
fun scan(startScan: Boolean) {
|
|
190
|
+
if (startScan) {
|
|
191
|
+
val settings = ScanSettings.Builder()
|
|
192
|
+
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
|
|
193
|
+
.setUseHardwareFilteringIfSupported(false)
|
|
194
|
+
.setReportDelay(0)
|
|
195
|
+
.build()
|
|
196
|
+
|
|
197
|
+
synchronized(this) {
|
|
198
|
+
if (isScanning) return
|
|
199
|
+
isScanning = true
|
|
200
|
+
|
|
201
|
+
val scanner = BluetoothLeScannerCompat.getScanner()
|
|
202
|
+
scanner.startScan(filters, settings, scanReceiver)
|
|
203
|
+
}
|
|
204
|
+
} else {
|
|
205
|
+
synchronized(this) {
|
|
206
|
+
if (!isScanning) return
|
|
207
|
+
isScanning = false
|
|
208
|
+
|
|
209
|
+
val scanner = BluetoothLeScannerCompat.getScanner()
|
|
210
|
+
scanner.stopScan(scanReceiver)
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
package com.autorunify.capacitor.bleprinter
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
|
|
5
|
+
abstract class BlePrinter {
|
|
6
|
+
protected val scaner: BleManager
|
|
7
|
+
|
|
8
|
+
constructor(scanner: BleManager) {
|
|
9
|
+
this.scaner = scanner
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
protected fun px2mm(px: Double, dpi: Int): Double {
|
|
13
|
+
return (px * 25.4) / dpi
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
protected fun mm2px(mm: Double, dpi: Int): Double {
|
|
17
|
+
return (mm * dpi) / 25.4
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
abstract fun init()
|
|
21
|
+
abstract fun kill()
|
|
22
|
+
|
|
23
|
+
abstract suspend fun devices(timeout: Int): MutableList<BleDevice>
|
|
24
|
+
|
|
25
|
+
abstract fun connect(address: String)
|
|
26
|
+
abstract fun disconnect()
|
|
27
|
+
|
|
28
|
+
abstract fun printImage(bitmap: Bitmap, width: Int, height: Int)
|
|
29
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
package com.autorunify.capacitor.bleprinter
|
|
2
|
+
|
|
3
|
+
import android.content.pm.PackageManager
|
|
4
|
+
import android.graphics.Bitmap
|
|
5
|
+
import androidx.core.app.ActivityCompat
|
|
6
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_PRINT_FINISHED
|
|
7
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_STATE_CONNECTED
|
|
8
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_STATE_DISCONNECTED
|
|
9
|
+
import com.getcapacitor.JSArray
|
|
10
|
+
import com.getcapacitor.JSObject
|
|
11
|
+
import com.getcapacitor.PermissionState
|
|
12
|
+
import com.getcapacitor.Plugin
|
|
13
|
+
import com.getcapacitor.PluginCall
|
|
14
|
+
import com.getcapacitor.PluginMethod
|
|
15
|
+
import com.getcapacitor.annotation.CapacitorPlugin
|
|
16
|
+
import com.getcapacitor.annotation.Permission
|
|
17
|
+
import com.getcapacitor.annotation.PermissionCallback
|
|
18
|
+
import kotlinx.coroutines.CoroutineScope
|
|
19
|
+
import kotlinx.coroutines.Dispatchers
|
|
20
|
+
import kotlinx.coroutines.launch
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@CapacitorPlugin(
|
|
24
|
+
name = "BlePrinter",
|
|
25
|
+
permissions = [
|
|
26
|
+
Permission(
|
|
27
|
+
strings = [
|
|
28
|
+
"android.permission.BLUETOOTH",
|
|
29
|
+
"android.permission.BLUETOOTH_ADMIN",
|
|
30
|
+
"android.permission.ACCESS_COARSE_LOCATION",
|
|
31
|
+
"android.permission.ACCESS_FINE_LOCATION",
|
|
32
|
+
], alias = "ANDROID_R"
|
|
33
|
+
),
|
|
34
|
+
Permission(
|
|
35
|
+
strings = [
|
|
36
|
+
"android.permission.BLUETOOTH_SCAN",
|
|
37
|
+
"android.permission.BLUETOOTH_CONNECT",
|
|
38
|
+
], alias = "ANDROID_S"
|
|
39
|
+
)]
|
|
40
|
+
)
|
|
41
|
+
class BlePrinterPlugin : Plugin {
|
|
42
|
+
private var alias: String = "ANDROID_R"
|
|
43
|
+
private val defaultTimeout = 20
|
|
44
|
+
private var printer: BlePrinter? = null
|
|
45
|
+
private val formatter = FormatManager()
|
|
46
|
+
private val async = AsyncManager()
|
|
47
|
+
private val ble = BleManager(this, async)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
constructor() {
|
|
51
|
+
if (android.os.Build.VERSION.SDK_INT > android.os.Build.VERSION_CODES.R) {
|
|
52
|
+
this.alias = "ANDROID_S"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
@PermissionCallback
|
|
57
|
+
@PluginMethod
|
|
58
|
+
override fun checkPermissions(call: PluginCall) {
|
|
59
|
+
|
|
60
|
+
val permissions = super.handle.pluginAnnotation.permissions
|
|
61
|
+
|
|
62
|
+
call.resolve(JSObject().apply {
|
|
63
|
+
permissions.forEach { permission ->
|
|
64
|
+
if (permission.alias == alias) {
|
|
65
|
+
permission.strings.forEach { key ->
|
|
66
|
+
val status = ActivityCompat.checkSelfPermission(context, key)
|
|
67
|
+
val state = if (status == PackageManager.PERMISSION_DENIED) {
|
|
68
|
+
PermissionState.DENIED
|
|
69
|
+
} else {
|
|
70
|
+
PermissionState.GRANTED
|
|
71
|
+
}
|
|
72
|
+
put(key, state)
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@PluginMethod
|
|
80
|
+
override fun requestPermissions(call: PluginCall) {
|
|
81
|
+
super.requestPermissionForAlias(this.alias, call, "checkPermissions")
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
@PluginMethod
|
|
85
|
+
fun isBluetoothEnabled(call: PluginCall) {
|
|
86
|
+
call.resolve(JSObject().apply {
|
|
87
|
+
put("enabled", ble.isEnabled())
|
|
88
|
+
})
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
public override fun notifyListeners(eventName: String?, data: JSObject?) {
|
|
92
|
+
super.notifyListeners(eventName, data)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
override fun load() {
|
|
96
|
+
super.load()
|
|
97
|
+
ble.load(activity, context)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
fun assertPrinter(call: PluginCall): Boolean {
|
|
101
|
+
if (printer == null) {
|
|
102
|
+
call.reject("printer is not init.")
|
|
103
|
+
return false
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
return true
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@PluginMethod
|
|
110
|
+
fun init(call: PluginCall) {
|
|
111
|
+
if (!this.ble.assertFeature(call)) return
|
|
112
|
+
if (!this.ble.assertAdapter(call)) return
|
|
113
|
+
if (!this.ble.assertEnabled(call)) return
|
|
114
|
+
|
|
115
|
+
if (printer != null) return call.resolve()
|
|
116
|
+
|
|
117
|
+
val manufacturer = call.getString("manufacturer")
|
|
118
|
+
?: return call.reject("manufacturer is required")
|
|
119
|
+
|
|
120
|
+
try {
|
|
121
|
+
when (manufacturer) {
|
|
122
|
+
"DotHanTech" -> printer = DotHanTechPrinter(ble)
|
|
123
|
+
else -> return call.reject("manufacturer is not supported $manufacturer")
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
ble.init()
|
|
127
|
+
printer!!.init()
|
|
128
|
+
|
|
129
|
+
call.resolve()
|
|
130
|
+
} catch (ex: Exception) {
|
|
131
|
+
call.reject(ex.message)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
@PluginMethod
|
|
136
|
+
fun kill(call: PluginCall) {
|
|
137
|
+
if (!this.ble.assertFeature(call)) return
|
|
138
|
+
if (!this.ble.assertAdapter(call)) return
|
|
139
|
+
if (!this.ble.assertEnabled(call)) return
|
|
140
|
+
|
|
141
|
+
if (printer == null) return call.resolve()
|
|
142
|
+
|
|
143
|
+
ble.kill()
|
|
144
|
+
printer!!.kill()
|
|
145
|
+
printer = null
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
@PluginMethod
|
|
149
|
+
fun devices(call: PluginCall) {
|
|
150
|
+
if (!this.ble.assertFeature(call)) return
|
|
151
|
+
if (!this.ble.assertAdapter(call)) return
|
|
152
|
+
if (!this.ble.assertEnabled(call)) return
|
|
153
|
+
if (!this.assertPrinter(call)) return
|
|
154
|
+
|
|
155
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
156
|
+
try {
|
|
157
|
+
val timeout = call.getInt("timeout", 5000)
|
|
158
|
+
val devices = printer!!.devices(timeout!!)
|
|
159
|
+
|
|
160
|
+
call.resolve(JSObject().apply {
|
|
161
|
+
put("devices", JSArray().apply {
|
|
162
|
+
devices.forEach { device ->
|
|
163
|
+
put(formatter.toJSON(device))
|
|
164
|
+
}
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
} catch (ex: Exception) {
|
|
168
|
+
call.reject(ex.message)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
@PluginMethod
|
|
174
|
+
fun isConnected(call: PluginCall) {
|
|
175
|
+
if (!this.ble.assertFeature(call)) return
|
|
176
|
+
if (!this.ble.assertAdapter(call)) return
|
|
177
|
+
if (!this.ble.assertEnabled(call)) return
|
|
178
|
+
if (!this.assertPrinter(call)) return
|
|
179
|
+
|
|
180
|
+
call.resolve(JSObject().apply {
|
|
181
|
+
put("connected", ble.isConnected.value)
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
@PluginMethod
|
|
186
|
+
fun connect(call: PluginCall) {
|
|
187
|
+
if (!this.ble.assertFeature(call)) return
|
|
188
|
+
if (!this.ble.assertAdapter(call)) return
|
|
189
|
+
if (!this.ble.assertEnabled(call)) return
|
|
190
|
+
if (!this.assertPrinter(call)) return
|
|
191
|
+
|
|
192
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
193
|
+
try {
|
|
194
|
+
val timeout = call.getInt("timeout", defaultTimeout)
|
|
195
|
+
val address = call.getString("address")
|
|
196
|
+
?: return@launch call.reject("address is required")
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
async.on(call, PRINTER_STATE_CONNECTED).timeout(timeout!!)
|
|
200
|
+
printer?.connect(address)
|
|
201
|
+
} catch (ex: Exception) {
|
|
202
|
+
call.reject(ex.message)
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@PluginMethod
|
|
208
|
+
fun disconnect(call: PluginCall) {
|
|
209
|
+
if (!this.ble.assertFeature(call)) return
|
|
210
|
+
if (!this.ble.assertAdapter(call)) return
|
|
211
|
+
if (!this.ble.assertEnabled(call)) return
|
|
212
|
+
if (!this.assertPrinter(call)) return
|
|
213
|
+
if (!this.ble.assertConnected(call)) return
|
|
214
|
+
|
|
215
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
216
|
+
try {
|
|
217
|
+
val timeout = call.getInt("timeout", defaultTimeout)
|
|
218
|
+
|
|
219
|
+
async.on(call, PRINTER_STATE_DISCONNECTED).timeout(timeout!!)
|
|
220
|
+
printer?.disconnect()
|
|
221
|
+
} catch (ex: Exception) {
|
|
222
|
+
call.reject(ex.message)
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@PluginMethod
|
|
228
|
+
fun printImage(call: PluginCall) {
|
|
229
|
+
if (!this.ble.assertFeature(call)) return
|
|
230
|
+
if (!this.ble.assertAdapter(call)) return
|
|
231
|
+
if (!this.ble.assertEnabled(call)) return
|
|
232
|
+
if (!this.assertPrinter(call)) return
|
|
233
|
+
if (!this.ble.assertConnected(call)) return
|
|
234
|
+
|
|
235
|
+
CoroutineScope(Dispatchers.IO).launch {
|
|
236
|
+
try {
|
|
237
|
+
val width = call.getInt("width")
|
|
238
|
+
?: return@launch call.reject("width is required")
|
|
239
|
+
val height = call.getInt("height")
|
|
240
|
+
?: return@launch call.reject("height is required")
|
|
241
|
+
val imageData = call.getObject("imageData")
|
|
242
|
+
?: return@launch call.reject("imageData is required")
|
|
243
|
+
|
|
244
|
+
val colors = IntArray(imageData.length() / 4)
|
|
245
|
+
|
|
246
|
+
for (i in 0..<colors.size) {
|
|
247
|
+
val R = imageData.getInt((i * 4 + 0).toString())
|
|
248
|
+
val G = imageData.getInt((i * 4 + 1).toString())
|
|
249
|
+
val B = imageData.getInt((i * 4 + 2).toString())
|
|
250
|
+
val A = imageData.getInt((i * 4 + 3).toString())
|
|
251
|
+
|
|
252
|
+
var color = 0
|
|
253
|
+
color += ((A and 0xff) shl 24)
|
|
254
|
+
color += ((G and 0xff) shl 16)
|
|
255
|
+
color += ((B and 0xff) shl 8)
|
|
256
|
+
color += ((R and 0xff) shl 0)
|
|
257
|
+
|
|
258
|
+
colors[i] = color
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async.on(call,PRINTER_PRINT_FINISHED)
|
|
262
|
+
printer!!.printImage(
|
|
263
|
+
Bitmap.createBitmap(colors, width, height, Bitmap.Config.ARGB_8888),
|
|
264
|
+
width,
|
|
265
|
+
height
|
|
266
|
+
)
|
|
267
|
+
} catch (ex: Exception) {
|
|
268
|
+
call.reject(ex.message)
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
package com.autorunify.capacitor.bleprinter
|
|
2
|
+
|
|
3
|
+
import android.graphics.Bitmap
|
|
4
|
+
import android.os.ParcelUuid
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.autorunify.capacitor.bleprinter.SystemAsyncCall.Companion.PRINTER_PRINT_FINISHED
|
|
7
|
+
import com.dothantech.lpapi.LPAPI
|
|
8
|
+
import com.dothantech.printer.IDzPrinter
|
|
9
|
+
import com.getcapacitor.JSObject
|
|
10
|
+
import kotlinx.coroutines.delay
|
|
11
|
+
import no.nordicsemi.android.support.v18.scanner.ScanFilter
|
|
12
|
+
import java.util.UUID
|
|
13
|
+
|
|
14
|
+
class DotHanTechPrinter : BlePrinter {
|
|
15
|
+
private class DotHanTechReceiver : LPAPI.Callback {
|
|
16
|
+
private val printer: DotHanTechPrinter
|
|
17
|
+
|
|
18
|
+
constructor(blePrinter: DotHanTechPrinter) {
|
|
19
|
+
this.printer = blePrinter
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
override fun onProgressInfo(p0: IDzPrinter.ProgressInfo?, p1: Any?) {
|
|
23
|
+
Log.w("BlePrinter", "onProgressInfo: ${p0?.name}")
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
override fun onStateChange(p0: IDzPrinter.PrinterAddress?, p1: IDzPrinter.PrinterState?) {
|
|
27
|
+
Log.w("BlePrinter", "onStateChange: ${p0?.shownName} ${p1?.name}")
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
override fun onPrintProgress(
|
|
31
|
+
p0: IDzPrinter.PrinterAddress?,
|
|
32
|
+
p1: IDzPrinter.PrintData?,
|
|
33
|
+
p2: IDzPrinter.PrintProgress?,
|
|
34
|
+
p3: Any?
|
|
35
|
+
) {
|
|
36
|
+
Log.w("BlePrinter", "onPrintProgress: ${p0?.shownName} ${p2?.name}")
|
|
37
|
+
if (p2 == IDzPrinter.PrintProgress.Success) {
|
|
38
|
+
printer.async.emit(JSObject().apply {
|
|
39
|
+
put("state", "success")
|
|
40
|
+
}, PRINTER_PRINT_FINISHED)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (p2 == IDzPrinter.PrintProgress.Failed) {
|
|
44
|
+
printer.async.emit(JSObject().apply {
|
|
45
|
+
put("state", "failed")
|
|
46
|
+
}, PRINTER_PRINT_FINISHED)
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
override fun onPrinterDiscovery(p0: IDzPrinter.PrinterAddress?, p1: Any?) {
|
|
51
|
+
Log.w("BlePrinter", "onPrinterDiscovery: ${p0?.shownName}")
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private val async: AsyncManager
|
|
56
|
+
private val receiver: DotHanTechReceiver = DotHanTechReceiver(this)
|
|
57
|
+
private lateinit var adapter: LPAPI
|
|
58
|
+
private val DPI = 300
|
|
59
|
+
|
|
60
|
+
constructor(scanner: BleManager) : super(scanner) {
|
|
61
|
+
this.async = scanner.async
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
override fun init() {
|
|
65
|
+
this.adapter = LPAPI.Factory.createInstance(receiver)
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
override fun kill() {
|
|
69
|
+
this.adapter.closePrinter()
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
override suspend fun devices(timeout: Int): MutableList<BleDevice> {
|
|
73
|
+
this.scaner.scan(false)
|
|
74
|
+
this.scaner.filters = mutableListOf<ScanFilter>()
|
|
75
|
+
this.scaner.filters.add(
|
|
76
|
+
ScanFilter.Builder()
|
|
77
|
+
.setServiceUuid(ParcelUuid(UUID.fromString("000018f0-0000-1000-8000-00805f9b34fb")))
|
|
78
|
+
.build()
|
|
79
|
+
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
this.scaner.devices.clear()
|
|
83
|
+
this.scaner.scan(true);
|
|
84
|
+
delay(timeout.toLong())
|
|
85
|
+
|
|
86
|
+
this.scaner.scan(false)
|
|
87
|
+
val _devices: MutableList<BleDevice> = mutableListOf()
|
|
88
|
+
|
|
89
|
+
synchronized(scaner.devices) {
|
|
90
|
+
scaner.devices.forEach { device ->
|
|
91
|
+
_devices.add(device)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return _devices
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
override fun connect(address: String) {
|
|
98
|
+
val _device = scaner.devices.firstOrNull { device -> device.address == address }
|
|
99
|
+
if (_device == null) return
|
|
100
|
+
|
|
101
|
+
val address = IDzPrinter.PrinterAddress(_device.address, IDzPrinter.AddressType.BLE)
|
|
102
|
+
this.adapter.openPrinterByAddressSync(address)
|
|
103
|
+
this.adapter.setPrintPageGapType(0)
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
override fun disconnect() {
|
|
107
|
+
if (this.adapter.isPrinterOpened) {
|
|
108
|
+
this.adapter.closePrinter()
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
override fun printImage(bitmap: Bitmap, width: Int, height: Int) {
|
|
113
|
+
val widthMm = px2mm(width.toDouble(), DPI)
|
|
114
|
+
val heightMm = px2mm(height.toDouble(), DPI) + 10
|
|
115
|
+
|
|
116
|
+
if (!adapter.startJob(widthMm, heightMm, 0)) return
|
|
117
|
+
if (!adapter.drawBitmapWithThreshold(bitmap, 0.0, 0.0, 0.0, 0.0, 256)) return
|
|
118
|
+
adapter.commitJob()
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.autorunify.capacitor.bleprinter
|
|
2
|
+
|
|
3
|
+
import com.getcapacitor.JSObject
|
|
4
|
+
|
|
5
|
+
class FormatManager {
|
|
6
|
+
fun toJSON(device: BleDevice): JSObject {
|
|
7
|
+
return JSObject().apply {
|
|
8
|
+
put("address", device.address)
|
|
9
|
+
put("name", device.name)
|
|
10
|
+
put("rssi", device.rssi)
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
File without changes
|