seven365-zyprinter 0.0.1 → 0.0.4
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/ios/Sources/Plugin/ZywellSDK.swift +147 -58
- package/package.json +2 -1
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
|
|
8
8
|
import Foundation
|
|
9
9
|
import CoreBluetooth
|
|
10
|
+
import Network
|
|
11
|
+
|
|
10
12
|
|
|
11
13
|
@objc public class ZywellSDK: NSObject {
|
|
12
14
|
|
|
@@ -19,6 +21,13 @@ import CoreBluetooth
|
|
|
19
21
|
super.init()
|
|
20
22
|
}
|
|
21
23
|
|
|
24
|
+
deinit {
|
|
25
|
+
bleManager?.delegate = nil
|
|
26
|
+
for (_, manager) in wifiManagers {
|
|
27
|
+
manager.delegate = nil
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
22
31
|
// MARK: - Echo Test
|
|
23
32
|
|
|
24
33
|
@objc public func echo(_ value: String) -> String {
|
|
@@ -32,14 +41,14 @@ import CoreBluetooth
|
|
|
32
41
|
var allPrinters: [[String: Any]] = []
|
|
33
42
|
let group = DispatchGroup()
|
|
34
43
|
|
|
35
|
-
//
|
|
36
|
-
group.enter()
|
|
37
|
-
discoverBluetoothPrinters { btPrinters, error in
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
44
|
+
// Bluetooth discovery disabled
|
|
45
|
+
// group.enter()
|
|
46
|
+
// discoverBluetoothPrinters { btPrinters, error in
|
|
47
|
+
// if error == nil {
|
|
48
|
+
// allPrinters.append(contentsOf: btPrinters)
|
|
49
|
+
// }
|
|
50
|
+
// group.leave()
|
|
51
|
+
// }
|
|
43
52
|
|
|
44
53
|
// Discover WiFi
|
|
45
54
|
group.enter()
|
|
@@ -56,49 +65,117 @@ import CoreBluetooth
|
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
@objc public func discoverBluetoothPrinters(completion: @escaping ([[String: Any]], String?) -> Void) {
|
|
59
|
-
|
|
60
|
-
|
|
68
|
+
// Bluetooth discovery disabled
|
|
69
|
+
completion([], nil)
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
@objc public func discoverWiFiPrinters(networkRange: String?, completion: @escaping ([[String: Any]], String?) -> Void) {
|
|
73
|
+
guard let ipAddress = getWiFiAddress() else {
|
|
74
|
+
completion([], "Could not determine device IP address")
|
|
75
|
+
return
|
|
76
|
+
}
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
78
|
+
let prefix = ipAddress.components(separatedBy: ".").dropLast().joined(separator: ".") + "."
|
|
79
|
+
scanSubnet(prefix: prefix, completion: completion)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private func scanSubnet(prefix: String, completion: @escaping ([[String: Any]], String?) -> Void) {
|
|
83
|
+
let group = DispatchGroup()
|
|
84
|
+
let queue = DispatchQueue(label: "com.seven365.printer.scan", attributes: .concurrent)
|
|
85
|
+
var foundPrinters: [[String: Any]] = []
|
|
86
|
+
let lock = NSLock()
|
|
87
|
+
|
|
88
|
+
// Scan range 1-254
|
|
89
|
+
for i in 1...254 {
|
|
90
|
+
let host = "\(prefix)\(i)"
|
|
91
|
+
group.enter()
|
|
92
|
+
|
|
93
|
+
queue.async {
|
|
94
|
+
self.checkPort(host: host, port: 9100, timeout: 0.5) { isOpen in
|
|
95
|
+
if isOpen {
|
|
96
|
+
lock.lock()
|
|
97
|
+
foundPrinters.append([
|
|
98
|
+
"identifier": host,
|
|
99
|
+
"model": "WiFi Printer (\(host))",
|
|
100
|
+
"status": "ready",
|
|
101
|
+
"connectionType": "wifi",
|
|
102
|
+
"ip": host
|
|
103
|
+
])
|
|
104
|
+
lock.unlock()
|
|
105
|
+
}
|
|
106
|
+
group.leave()
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
64
110
|
|
|
65
|
-
|
|
66
|
-
|
|
111
|
+
group.notify(queue: .main) {
|
|
112
|
+
completion(foundPrinters, nil)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
private func checkPort(host: String, port: UInt16, timeout: TimeInterval, completion: @escaping (Bool) -> Void) {
|
|
117
|
+
let hostEndpoint = NWEndpoint.Host(host)
|
|
118
|
+
let portEndpoint = NWEndpoint.Port(integerLiteral: port)
|
|
119
|
+
|
|
120
|
+
let connection = NWConnection(host: hostEndpoint, port: portEndpoint, using: .tcp)
|
|
67
121
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
122
|
+
var hasCompleted = false
|
|
123
|
+
|
|
124
|
+
connection.stateUpdateHandler = { state in
|
|
125
|
+
if hasCompleted { return }
|
|
71
126
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
127
|
+
switch state {
|
|
128
|
+
case .ready:
|
|
129
|
+
hasCompleted = true
|
|
130
|
+
connection.cancel()
|
|
131
|
+
completion(true)
|
|
132
|
+
case .failed(_), .cancelled:
|
|
133
|
+
hasCompleted = true
|
|
134
|
+
connection.cancel()
|
|
135
|
+
completion(false)
|
|
136
|
+
default:
|
|
137
|
+
break
|
|
76
138
|
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
"connectionType": "bluetooth",
|
|
87
|
-
"rssi": rssi
|
|
88
|
-
])
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
connection.start(queue: .global())
|
|
142
|
+
|
|
143
|
+
DispatchQueue.global().asyncAfter(deadline: .now() + timeout) {
|
|
144
|
+
if !hasCompleted {
|
|
145
|
+
hasCompleted = true
|
|
146
|
+
connection.cancel()
|
|
147
|
+
completion(false)
|
|
89
148
|
}
|
|
90
|
-
|
|
91
|
-
completion(printerList, nil)
|
|
92
149
|
}
|
|
93
150
|
}
|
|
94
151
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
152
|
+
// Helper to get IP address
|
|
153
|
+
private func getWiFiAddress() -> String? {
|
|
154
|
+
var address: String?
|
|
155
|
+
var ifaddr: UnsafeMutablePointer<ifaddrs>?
|
|
99
156
|
|
|
100
|
-
|
|
101
|
-
|
|
157
|
+
if getifaddrs(&ifaddr) == 0 {
|
|
158
|
+
var ptr = ifaddr
|
|
159
|
+
while ptr != nil {
|
|
160
|
+
defer { ptr = ptr?.pointee.ifa_next }
|
|
161
|
+
|
|
162
|
+
guard let interface = ptr?.pointee else { continue }
|
|
163
|
+
let addrFamily = interface.ifa_addr.pointee.sa_family
|
|
164
|
+
|
|
165
|
+
if addrFamily == UInt8(AF_INET) { // IPv4 only
|
|
166
|
+
let name = String(cString: interface.ifa_name)
|
|
167
|
+
if name == "en0" { // WiFi interface
|
|
168
|
+
var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
|
|
169
|
+
getnameinfo(interface.ifa_addr, socklen_t(interface.ifa_addr.pointee.sa_len),
|
|
170
|
+
&hostname, socklen_t(hostname.count),
|
|
171
|
+
nil, socklen_t(0), NI_NUMERICHOST)
|
|
172
|
+
address = String(cString: hostname)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
freeifaddrs(ifaddr)
|
|
177
|
+
}
|
|
178
|
+
return address
|
|
102
179
|
}
|
|
103
180
|
|
|
104
181
|
// MARK: - Connection Management
|
|
@@ -144,7 +221,9 @@ import CoreBluetooth
|
|
|
144
221
|
self.connectionCompletion = completion
|
|
145
222
|
|
|
146
223
|
wifiManager.posConnect(withHost: ipAddress, port: port) { [weak self] isConnected in
|
|
147
|
-
|
|
224
|
+
DispatchQueue.main.async {
|
|
225
|
+
completion(isConnected, isConnected ? nil : "Connection failed")
|
|
226
|
+
}
|
|
148
227
|
}
|
|
149
228
|
}
|
|
150
229
|
|
|
@@ -305,15 +384,19 @@ extension ZywellSDK: POSBLEManagerDelegate {
|
|
|
305
384
|
self.peripheralRSSIs = rssis
|
|
306
385
|
}
|
|
307
386
|
|
|
308
|
-
public func
|
|
309
|
-
|
|
310
|
-
|
|
387
|
+
public func poSdidConnectPeripheral(_ peripheral: CBPeripheral!) {
|
|
388
|
+
DispatchQueue.main.async { [weak self] in
|
|
389
|
+
self?.connectionCompletion?(true, nil)
|
|
390
|
+
self?.connectionCompletion = nil
|
|
391
|
+
}
|
|
311
392
|
}
|
|
312
393
|
|
|
313
|
-
public func
|
|
394
|
+
public func poSdidFailToConnectPeripheral(_ peripheral: CBPeripheral!, error: Error!) {
|
|
314
395
|
let errorMsg = error?.localizedDescription ?? "Connection failed"
|
|
315
|
-
|
|
316
|
-
|
|
396
|
+
DispatchQueue.main.async { [weak self] in
|
|
397
|
+
self?.connectionCompletion?(false, errorMsg)
|
|
398
|
+
self?.connectionCompletion = nil
|
|
399
|
+
}
|
|
317
400
|
}
|
|
318
401
|
|
|
319
402
|
public func poSdidDisconnectPeripheral(_ peripheral: CBPeripheral!, isAutoDisconnect: Bool) {
|
|
@@ -321,12 +404,14 @@ extension ZywellSDK: POSBLEManagerDelegate {
|
|
|
321
404
|
}
|
|
322
405
|
|
|
323
406
|
public func poSdidWriteValue(for character: CBCharacteristic!, error: Error!) {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
407
|
+
DispatchQueue.main.async { [weak self] in
|
|
408
|
+
if let error = error {
|
|
409
|
+
self?.printCompletion?(false, error.localizedDescription)
|
|
410
|
+
} else {
|
|
411
|
+
self?.printCompletion?(true, nil)
|
|
412
|
+
}
|
|
413
|
+
self?.printCompletion = nil
|
|
328
414
|
}
|
|
329
|
-
printCompletion = nil
|
|
330
415
|
}
|
|
331
416
|
}
|
|
332
417
|
|
|
@@ -335,8 +420,10 @@ extension ZywellSDK: POSBLEManagerDelegate {
|
|
|
335
420
|
extension ZywellSDK: POSWIFIManagerDelegate {
|
|
336
421
|
|
|
337
422
|
public func poswifiManager(_ manager: POSWIFIManager!, didConnectedToHost host: String!, port: UInt16) {
|
|
338
|
-
|
|
339
|
-
|
|
423
|
+
DispatchQueue.main.async { [weak self] in
|
|
424
|
+
self?.connectionCompletion?(true, nil)
|
|
425
|
+
self?.connectionCompletion = nil
|
|
426
|
+
}
|
|
340
427
|
}
|
|
341
428
|
|
|
342
429
|
public func poswifiManager(_ manager: POSWIFIManager, willDisconnectWithError error: Error?) {
|
|
@@ -344,11 +431,13 @@ extension ZywellSDK: POSWIFIManagerDelegate {
|
|
|
344
431
|
}
|
|
345
432
|
|
|
346
433
|
public func poswifiManager(_ manager: POSWIFIManager!, didWriteDataWithTag tag: Int) {
|
|
347
|
-
|
|
348
|
-
|
|
434
|
+
DispatchQueue.main.async { [weak self] in
|
|
435
|
+
self?.printCompletion?(true, nil)
|
|
436
|
+
self?.printCompletion = nil
|
|
437
|
+
}
|
|
349
438
|
}
|
|
350
439
|
|
|
351
|
-
public func poswifiManager(_ manager: POSWIFIManager,
|
|
440
|
+
public func poswifiManager(_ manager: POSWIFIManager, didReadData data: Data, tag: Int) {
|
|
352
441
|
// Handle data reading if needed
|
|
353
442
|
}
|
|
354
443
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "seven365-zyprinter",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Capacitor plugin for Zywell/Zyprint thermal printer integration with Bluetooth and WiFi support",
|
|
5
5
|
"main": "dist/plugin.cjs.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@capacitor/android": "^7.0.0",
|
|
57
|
+
"@capacitor/cli": "^7.4.4",
|
|
57
58
|
"@capacitor/core": "^7.0.0",
|
|
58
59
|
"@capacitor/docgen": "^0.3.0",
|
|
59
60
|
"@capacitor/ios": "^7.0.0",
|