seven365-zyprinter 0.0.1 → 0.0.3

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.
@@ -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
- // Discover Bluetooth
36
- group.enter()
37
- discoverBluetoothPrinters { btPrinters, error in
38
- if error == nil {
39
- allPrinters.append(contentsOf: btPrinters)
40
- }
41
- group.leave()
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
- bleManager = POSBLEManager.sharedInstance()
60
- bleManager?.delegate = self
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
- // Store completion for delegate callback
63
- self.discoveryCompletion = completion
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
- // Start scanning
66
- bleManager?.poSstartScan()
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
- // Auto-stop after 5 seconds
69
- DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { [weak self] in
70
- self?.bleManager?.poSstopScan()
122
+ var hasCompleted = false
123
+
124
+ connection.stateUpdateHandler = { state in
125
+ if hasCompleted { return }
71
126
 
72
- guard let printers = self?.discoveredPeripherals,
73
- let rssis = self?.peripheralRSSIs else {
74
- completion([], nil)
75
- return
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
- var printerList: [[String: Any]] = []
79
- for (index, peripheral) in printers.enumerated() {
80
- let rssi = rssis.count > index ? rssis[index].intValue : 0
81
-
82
- printerList.append([
83
- "identifier": peripheral.identifier.uuidString,
84
- "model": peripheral.name ?? "Unknown Printer",
85
- "status": "ready",
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
- @objc public func discoverWiFiPrinters(networkRange: String?, completion: @escaping ([[String: Any]], String?) -> Void) {
96
- // For WiFi discovery, we would need to implement network scanning
97
- // This is a placeholder - WiFi printers typically need manual IP entry
98
- // or use mDNS/Bonjour discovery which requires additional implementation
152
+ // Helper to get IP address
153
+ private func getWiFiAddress() -> String? {
154
+ var address: String?
155
+ var ifaddr: UnsafeMutablePointer<ifaddrs>?
99
156
 
100
- // Return empty for now - users will connect via IP address
101
- completion([], nil)
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
- completion(isConnected, isConnected ? nil : "Connection failed")
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 poSdidConnect(_ peripheral: CBPeripheral!) {
309
- connectionCompletion?(true, nil)
310
- connectionCompletion = nil
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 poSdidFail(toConnect peripheral: CBPeripheral!, error: Error!) {
394
+ public func poSdidFailToConnectPeripheral(_ peripheral: CBPeripheral!, error: Error!) {
314
395
  let errorMsg = error?.localizedDescription ?? "Connection failed"
315
- connectionCompletion?(false, errorMsg)
316
- connectionCompletion = nil
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
- if let error = error {
325
- printCompletion?(false, error.localizedDescription)
326
- } else {
327
- printCompletion?(true, nil)
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
- connectionCompletion?(true, nil)
339
- connectionCompletion = nil
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
- printCompletion?(true, nil)
348
- printCompletion = nil
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, didRead data: Data, tag: Int) {
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.1",
3
+ "version": "0.0.3",
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",