seven365-zyprinter 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.
Files changed (53) hide show
  1. package/Package.swift +43 -0
  2. package/README.md +186 -0
  3. package/Seven365Zyprinter.podspec +27 -0
  4. package/android/build.gradle +58 -0
  5. package/android/src/main/AndroidManifest.xml +2 -0
  6. package/android/src/main/java/com/mycompany/plugins/example/Example.java +342 -0
  7. package/android/src/main/java/com/mycompany/plugins/example/ExamplePlugin.java +161 -0
  8. package/android/src/main/res/.gitkeep +0 -0
  9. package/dist/docs.json +229 -0
  10. package/dist/esm/definitions.d.ts +56 -0
  11. package/dist/esm/definitions.js +2 -0
  12. package/dist/esm/definitions.js.map +1 -0
  13. package/dist/esm/index.d.ts +4 -0
  14. package/dist/esm/index.js +7 -0
  15. package/dist/esm/index.js.map +1 -0
  16. package/dist/esm/web.d.ts +49 -0
  17. package/dist/esm/web.js +40 -0
  18. package/dist/esm/web.js.map +1 -0
  19. package/dist/plugin.cjs.js +54 -0
  20. package/dist/plugin.cjs.js.map +1 -0
  21. package/dist/plugin.js +57 -0
  22. package/dist/plugin.js.map +1 -0
  23. package/ios/Seven365Zyprinter.podspec +28 -0
  24. package/ios/Sources/Plugin/ZyprintPlugin.swift +161 -0
  25. package/ios/Sources/Plugin/ZywellSDK.swift +358 -0
  26. package/ios/Sources/Seven365Zyprinter-Umbrella.h +16 -0
  27. package/ios/Sources/module.modulemap +12 -0
  28. package/ios/Sources/sources/BLEManager.h +658 -0
  29. package/ios/Sources/sources/BLEManager.m +2842 -0
  30. package/ios/Sources/sources/GCD/Documentation.html +47 -0
  31. package/ios/Sources/sources/GCD/GCDAsyncSocket.h +1226 -0
  32. package/ios/Sources/sources/GCD/GCDAsyncSocket.m +8560 -0
  33. package/ios/Sources/sources/GCD/GCDAsyncUdpSocket.h +1036 -0
  34. package/ios/Sources/sources/GCD/GCDAsyncUdpSocket.m +5632 -0
  35. package/ios/Sources/sources/GCD/PrinterManager.h +91 -0
  36. package/ios/Sources/sources/GCD/PrinterManager.m +513 -0
  37. package/ios/Sources/sources/GCD/WifiManager.h +91 -0
  38. package/ios/Sources/sources/GCD/WifiManager.m +510 -0
  39. package/ios/Sources/sources/ImageTranster.h +38 -0
  40. package/ios/Sources/sources/ImageTranster.m +389 -0
  41. package/ios/Sources/sources/POSBLEManager.h +759 -0
  42. package/ios/Sources/sources/POSBLEManager.m +834 -0
  43. package/ios/Sources/sources/POSSDK.h +93 -0
  44. package/ios/Sources/sources/POSWIFIManager.h +116 -0
  45. package/ios/Sources/sources/POSWIFIManager.m +260 -0
  46. package/ios/Sources/sources/POSWIFIManagerAsync.h +745 -0
  47. package/ios/Sources/sources/POSWIFIManagerAsync.m +1847 -0
  48. package/ios/Sources/sources/PosCommand.h +633 -0
  49. package/ios/Sources/sources/PosCommand.m +1019 -0
  50. package/ios/Sources/sources/TscCommand.h +723 -0
  51. package/ios/Sources/sources/TscCommand.m +566 -0
  52. package/ios/Tests/ExamplePluginTests/ExamplePluginTests.swift +15 -0
  53. package/package.json +339 -0
package/dist/plugin.js ADDED
@@ -0,0 +1,57 @@
1
+ var capacitorExample = (function (exports, core) {
2
+ 'use strict';
3
+
4
+ const Zyprint = core.registerPlugin('Zyprint', {
5
+ web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.ZyprintWeb()),
6
+ });
7
+
8
+ class ZyprintWeb extends core.WebPlugin {
9
+ async echo(options) {
10
+ console.log('ECHO', options);
11
+ return options;
12
+ }
13
+ async discoverPrinters() {
14
+ console.warn('Zyprint discovery is not available on web platform');
15
+ return { printers: [] };
16
+ }
17
+ async discoverBluetoothPrinters() {
18
+ console.warn('Zyprint Bluetooth discovery is not available on web platform');
19
+ return { printers: [] };
20
+ }
21
+ async discoverWiFiPrinters(_options) {
22
+ console.warn('Zyprint WiFi discovery is not available on web platform');
23
+ return { printers: [] };
24
+ }
25
+ async connectToPrinter(_options) {
26
+ console.warn('Zyprint connection is not available on web platform');
27
+ return { connected: false };
28
+ }
29
+ async disconnectFromPrinter(_options) {
30
+ console.warn('Zyprint disconnection is not available on web platform');
31
+ return { disconnected: false };
32
+ }
33
+ async printText(_options) {
34
+ console.warn('Zyprint printing is not available on web platform');
35
+ return { success: false };
36
+ }
37
+ async printReceipt(_options) {
38
+ console.warn('Zyprint receipt printing is not available on web platform');
39
+ return { success: false };
40
+ }
41
+ async getPrinterStatus(_options) {
42
+ console.warn('Zyprint status check is not available on web platform');
43
+ return { status: 'unknown', paperStatus: 'unknown', connected: false };
44
+ }
45
+ }
46
+
47
+ var web = /*#__PURE__*/Object.freeze({
48
+ __proto__: null,
49
+ ZyprintWeb: ZyprintWeb
50
+ });
51
+
52
+ exports.Zyprint = Zyprint;
53
+
54
+ return exports;
55
+
56
+ })({}, capacitorExports);
57
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst Zyprint = registerPlugin('Zyprint', {\n web: () => import('./web').then((m) => new m.ZyprintWeb()),\n});\nexport * from './definitions';\nexport { Zyprint };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ZyprintWeb extends WebPlugin {\n async echo(options) {\n console.log('ECHO', options);\n return options;\n }\n async discoverPrinters() {\n console.warn('Zyprint discovery is not available on web platform');\n return { printers: [] };\n }\n async discoverBluetoothPrinters() {\n console.warn('Zyprint Bluetooth discovery is not available on web platform');\n return { printers: [] };\n }\n async discoverWiFiPrinters(_options) {\n console.warn('Zyprint WiFi discovery is not available on web platform');\n return { printers: [] };\n }\n async connectToPrinter(_options) {\n console.warn('Zyprint connection is not available on web platform');\n return { connected: false };\n }\n async disconnectFromPrinter(_options) {\n console.warn('Zyprint disconnection is not available on web platform');\n return { disconnected: false };\n }\n async printText(_options) {\n console.warn('Zyprint printing is not available on web platform');\n return { success: false };\n }\n async printReceipt(_options) {\n console.warn('Zyprint receipt printing is not available on web platform');\n return { success: false };\n }\n async getPrinterStatus(_options) {\n console.warn('Zyprint status check is not available on web platform');\n return { status: 'unknown', paperStatus: 'unknown', connected: false };\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["registerPlugin","WebPlugin"],"mappings":";;;AACK,UAAC,OAAO,GAAGA,mBAAc,CAAC,SAAS,EAAE;IAC1C,IAAI,GAAG,EAAE,MAAM,mDAAe,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC;IAC9D,CAAC;;ICFM,MAAM,UAAU,SAASC,cAAS,CAAC;IAC1C,IAAI,MAAM,IAAI,CAAC,OAAO,EAAE;IACxB,QAAQ,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC;IACpC,QAAQ,OAAO,OAAO;IACtB,IAAI;IACJ,IAAI,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,OAAO,CAAC,IAAI,CAAC,oDAAoD,CAAC;IAC1E,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC/B,IAAI;IACJ,IAAI,MAAM,yBAAyB,GAAG;IACtC,QAAQ,OAAO,CAAC,IAAI,CAAC,8DAA8D,CAAC;IACpF,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC/B,IAAI;IACJ,IAAI,MAAM,oBAAoB,CAAC,QAAQ,EAAE;IACzC,QAAQ,OAAO,CAAC,IAAI,CAAC,yDAAyD,CAAC;IAC/E,QAAQ,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IAC/B,IAAI;IACJ,IAAI,MAAM,gBAAgB,CAAC,QAAQ,EAAE;IACrC,QAAQ,OAAO,CAAC,IAAI,CAAC,qDAAqD,CAAC;IAC3E,QAAQ,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE;IACnC,IAAI;IACJ,IAAI,MAAM,qBAAqB,CAAC,QAAQ,EAAE;IAC1C,QAAQ,OAAO,CAAC,IAAI,CAAC,wDAAwD,CAAC;IAC9E,QAAQ,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE;IACtC,IAAI;IACJ,IAAI,MAAM,SAAS,CAAC,QAAQ,EAAE;IAC9B,QAAQ,OAAO,CAAC,IAAI,CAAC,mDAAmD,CAAC;IACzE,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,YAAY,CAAC,QAAQ,EAAE;IACjC,QAAQ,OAAO,CAAC,IAAI,CAAC,2DAA2D,CAAC;IACjF,QAAQ,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE;IACjC,IAAI;IACJ,IAAI,MAAM,gBAAgB,CAAC,QAAQ,EAAE;IACrC,QAAQ,OAAO,CAAC,IAAI,CAAC,uDAAuD,CAAC;IAC7E,QAAQ,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE;IAC9E,IAAI;IACJ;;;;;;;;;;;;;;;"}
@@ -0,0 +1,28 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'Seven365Zyprinter'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.license = package['license']
10
+ s.homepage = package['repository']['url']
11
+ s.author = package['author']
12
+ s.source = { :git => package['repository']['url'], :tag => s.version.to_s }
13
+ # Source files include Swift and Objective-C source from ios/Sources
14
+ s.source_files = 'ios/Sources/**/*.{swift,h,m,mm,c,cc,cpp}'
15
+ s.ios.deployment_target = '14.0'
16
+ s.dependency 'Capacitor'
17
+ s.swift_version = '5.1'
18
+
19
+ # iOS system frameworks required for Zyprint functionality
20
+ # CoreBluetooth for BLE, SystemConfiguration/CFNetwork for networking
21
+ s.frameworks = 'CoreBluetooth', 'SystemConfiguration', 'CFNetwork'
22
+
23
+ # Expose Zywell SDK public headers so consumers can import Objective-C APIs
24
+ s.public_header_files = 'ios/Sources/zywell/ZywellSDK/**/*.h'
25
+
26
+ # Uncomment when you add the Zywell SDK framework:
27
+ # s.vendored_frameworks = 'Frameworks/ZywellPrinter.xcframework'
28
+ end
@@ -0,0 +1,161 @@
1
+ //
2
+ // ZyprintPlugin.swift
3
+ // Seven365Zyprinter
4
+ //
5
+ // Capacitor plugin for Zywell thermal printer integration
6
+ //
7
+
8
+ import Foundation
9
+ import Capacitor
10
+
11
+ @objc(ZyprintPlugin)
12
+ public class ZyprintPlugin: CAPPlugin, CAPBridgedPlugin {
13
+ public let identifier = "ZyprintPlugin"
14
+ public let jsName = "Zyprint"
15
+ public let pluginMethods: [CAPPluginMethod] = [
16
+ CAPPluginMethod(name: "echo", returnType: CAPPluginReturnPromise),
17
+ CAPPluginMethod(name: "discoverPrinters", returnType: CAPPluginReturnPromise),
18
+ CAPPluginMethod(name: "discoverBluetoothPrinters", returnType: CAPPluginReturnPromise),
19
+ CAPPluginMethod(name: "discoverWiFiPrinters", returnType: CAPPluginReturnPromise),
20
+ CAPPluginMethod(name: "connectToPrinter", returnType: CAPPluginReturnPromise),
21
+ CAPPluginMethod(name: "disconnectFromPrinter", returnType: CAPPluginReturnPromise),
22
+ CAPPluginMethod(name: "printText", returnType: CAPPluginReturnPromise),
23
+ CAPPluginMethod(name: "printReceipt", returnType: CAPPluginReturnPromise),
24
+ CAPPluginMethod(name: "getPrinterStatus", returnType: CAPPluginReturnPromise)
25
+ ]
26
+
27
+ private let implementation = ZywellSDK()
28
+
29
+ @objc func echo(_ call: CAPPluginCall) {
30
+ let value = call.getString("value") ?? ""
31
+ call.resolve([
32
+ "value": implementation.echo(value)
33
+ ])
34
+ }
35
+
36
+ @objc func discoverPrinters(_ call: CAPPluginCall) {
37
+ implementation.discoverPrinters { printers, error in
38
+ if let error = error {
39
+ call.reject(error)
40
+ } else {
41
+ call.resolve([
42
+ "printers": printers
43
+ ])
44
+ }
45
+ }
46
+ }
47
+
48
+ @objc func discoverBluetoothPrinters(_ call: CAPPluginCall) {
49
+ implementation.discoverBluetoothPrinters { printers, error in
50
+ if let error = error {
51
+ call.reject(error)
52
+ } else {
53
+ call.resolve([
54
+ "printers": printers
55
+ ])
56
+ }
57
+ }
58
+ }
59
+
60
+ @objc func discoverWiFiPrinters(_ call: CAPPluginCall) {
61
+ let networkRange = call.getString("networkRange")
62
+ implementation.discoverWiFiPrinters(networkRange: networkRange) { printers, error in
63
+ if let error = error {
64
+ call.reject(error)
65
+ } else {
66
+ call.resolve([
67
+ "printers": printers
68
+ ])
69
+ }
70
+ }
71
+ }
72
+
73
+ @objc func connectToPrinter(_ call: CAPPluginCall) {
74
+ guard let identifier = call.getString("identifier") else {
75
+ call.reject("Missing identifier parameter")
76
+ return
77
+ }
78
+
79
+ implementation.connectToPrinter(identifier: identifier) { success, error in
80
+ if let error = error {
81
+ call.reject(error)
82
+ } else {
83
+ call.resolve([
84
+ "connected": success
85
+ ])
86
+ }
87
+ }
88
+ }
89
+
90
+ @objc func disconnectFromPrinter(_ call: CAPPluginCall) {
91
+ guard let identifier = call.getString("identifier") else {
92
+ call.reject("Missing identifier parameter")
93
+ return
94
+ }
95
+
96
+ implementation.disconnectFromPrinter(identifier: identifier) { success, error in
97
+ if let error = error {
98
+ call.reject(error)
99
+ } else {
100
+ call.resolve([
101
+ "disconnected": success
102
+ ])
103
+ }
104
+ }
105
+ }
106
+
107
+ @objc func printText(_ call: CAPPluginCall) {
108
+ guard let text = call.getString("text"),
109
+ let identifier = call.getString("identifier") else {
110
+ call.reject("Missing required parameters")
111
+ return
112
+ }
113
+
114
+ implementation.printText(text: text, identifier: identifier) { success, error in
115
+ if let error = error {
116
+ call.reject(error)
117
+ } else {
118
+ call.resolve([
119
+ "success": success
120
+ ])
121
+ }
122
+ }
123
+ }
124
+
125
+ @objc func printReceipt(_ call: CAPPluginCall) {
126
+ guard let template = call.getObject("template"),
127
+ let identifier = call.getString("identifier") else {
128
+ call.reject("Missing required parameters")
129
+ return
130
+ }
131
+
132
+ implementation.printReceipt(template: template, identifier: identifier) { success, error in
133
+ if let error = error {
134
+ call.reject(error)
135
+ } else {
136
+ call.resolve([
137
+ "success": success
138
+ ])
139
+ }
140
+ }
141
+ }
142
+
143
+ @objc func getPrinterStatus(_ call: CAPPluginCall) {
144
+ guard let identifier = call.getString("identifier") else {
145
+ call.reject("Missing identifier parameter")
146
+ return
147
+ }
148
+
149
+ implementation.getPrinterStatus(identifier: identifier) { status, paperStatus, connected, error in
150
+ if let error = error {
151
+ call.reject(error)
152
+ } else {
153
+ call.resolve([
154
+ "status": status,
155
+ "paperStatus": paperStatus,
156
+ "connected": connected
157
+ ])
158
+ }
159
+ }
160
+ }
161
+ }
@@ -0,0 +1,358 @@
1
+ //
2
+ // ZywellSDK.swift
3
+ // Seven365Zyprinter
4
+ //
5
+ // Swift wrapper for the Zywell Objective-C SDK
6
+ //
7
+
8
+ import Foundation
9
+ import CoreBluetooth
10
+
11
+ @objc public class ZywellSDK: NSObject {
12
+
13
+ private var bleManager: POSBLEManager?
14
+ private var wifiManagers: [String: POSWIFIManager] = [:]
15
+ private var discoveredPeripherals: [CBPeripheral] = []
16
+ private var peripheralRSSIs: [NSNumber] = []
17
+
18
+ public override init() {
19
+ super.init()
20
+ }
21
+
22
+ // MARK: - Echo Test
23
+
24
+ @objc public func echo(_ value: String) -> String {
25
+ return value
26
+ }
27
+
28
+ // MARK: - Printer Discovery
29
+
30
+ @objc public func discoverPrinters(completion: @escaping ([[String: Any]], String?) -> Void) {
31
+ // Discover both Bluetooth and WiFi printers
32
+ var allPrinters: [[String: Any]] = []
33
+ let group = DispatchGroup()
34
+
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
+ }
43
+
44
+ // Discover WiFi
45
+ group.enter()
46
+ discoverWiFiPrinters(networkRange: nil) { wifiPrinters, error in
47
+ if error == nil {
48
+ allPrinters.append(contentsOf: wifiPrinters)
49
+ }
50
+ group.leave()
51
+ }
52
+
53
+ group.notify(queue: .main) {
54
+ completion(allPrinters, nil)
55
+ }
56
+ }
57
+
58
+ @objc public func discoverBluetoothPrinters(completion: @escaping ([[String: Any]], String?) -> Void) {
59
+ bleManager = POSBLEManager.sharedInstance()
60
+ bleManager?.delegate = self
61
+
62
+ // Store completion for delegate callback
63
+ self.discoveryCompletion = completion
64
+
65
+ // Start scanning
66
+ bleManager?.poSstartScan()
67
+
68
+ // Auto-stop after 5 seconds
69
+ DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) { [weak self] in
70
+ self?.bleManager?.poSstopScan()
71
+
72
+ guard let printers = self?.discoveredPeripherals,
73
+ let rssis = self?.peripheralRSSIs else {
74
+ completion([], nil)
75
+ return
76
+ }
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
+ ])
89
+ }
90
+
91
+ completion(printerList, nil)
92
+ }
93
+ }
94
+
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
99
+
100
+ // Return empty for now - users will connect via IP address
101
+ completion([], nil)
102
+ }
103
+
104
+ // MARK: - Connection Management
105
+
106
+ @objc public func connectToPrinter(identifier: String, completion: @escaping (Bool, String?) -> Void) {
107
+ // Check if it's a Bluetooth connection (UUID format)
108
+ if let uuid = UUID(uuidString: identifier) {
109
+ connectBluetoothPrinter(uuid: uuid, completion: completion)
110
+ } else {
111
+ // Assume it's an IP address for WiFi
112
+ connectWiFiPrinter(ipAddress: identifier, completion: completion)
113
+ }
114
+ }
115
+
116
+ private func connectBluetoothPrinter(uuid: UUID, completion: @escaping (Bool, String?) -> Void) {
117
+ if bleManager == nil {
118
+ bleManager = POSBLEManager.sharedInstance()
119
+ bleManager?.delegate = self
120
+ }
121
+
122
+ guard let manager = bleManager else {
123
+ completion(false, "Failed to initialize BLE manager")
124
+ return
125
+ }
126
+
127
+ // Find the peripheral
128
+ guard let peripheral = discoveredPeripherals.first(where: { $0.identifier == uuid }) else {
129
+ completion(false, "Printer not found")
130
+ return
131
+ }
132
+
133
+ self.connectionCompletion = completion
134
+ manager.poSconnectDevice(peripheral)
135
+ }
136
+
137
+ private func connectWiFiPrinter(ipAddress: String, completion: @escaping (Bool, String?) -> Void) {
138
+ let port: UInt16 = 9100 // Standard printer port
139
+
140
+ let wifiManager = POSWIFIManager()
141
+ wifiManager.delegate = self
142
+ wifiManagers[ipAddress] = wifiManager
143
+
144
+ self.connectionCompletion = completion
145
+
146
+ wifiManager.posConnect(withHost: ipAddress, port: port) { [weak self] isConnected in
147
+ completion(isConnected, isConnected ? nil : "Connection failed")
148
+ }
149
+ }
150
+
151
+ @objc public func disconnectFromPrinter(identifier: String, completion: @escaping (Bool, String?) -> Void) {
152
+ // Check if it's WiFi connection
153
+ if let wifiManager = wifiManagers[identifier] {
154
+ wifiManager.posDisConnect()
155
+ wifiManagers.removeValue(forKey: identifier)
156
+ completion(true, nil)
157
+ } else {
158
+ // Bluetooth disconnection
159
+ bleManager?.poSdisconnectRootPeripheral()
160
+ completion(true, nil)
161
+ }
162
+ }
163
+
164
+ // MARK: - Printing Methods
165
+
166
+ @objc public func printText(text: String, identifier: String, completion: @escaping (Bool, String?) -> Void) {
167
+ guard let data = formatTextForPrinter(text: text) else {
168
+ completion(false, "Failed to format text")
169
+ return
170
+ }
171
+
172
+ sendDataToPrinter(data: data, identifier: identifier, completion: completion)
173
+ }
174
+
175
+ @objc public func printReceipt(template: [String: Any], identifier: String, completion: @escaping (Bool, String?) -> Void) {
176
+ guard let data = formatReceiptForPrinter(template: template) else {
177
+ completion(false, "Failed to format receipt")
178
+ return
179
+ }
180
+
181
+ sendDataToPrinter(data: data, identifier: identifier, completion: completion)
182
+ }
183
+
184
+ private func sendDataToPrinter(data: Data, identifier: String, completion: @escaping (Bool, String?) -> Void) {
185
+ // Check if WiFi connection
186
+ if let wifiManager = wifiManagers[identifier] {
187
+ self.printCompletion = completion
188
+ wifiManager.posWriteCommand(with: data)
189
+ } else {
190
+ // Bluetooth connection
191
+ self.printCompletion = completion
192
+ bleManager?.posWriteCommand(with: data)
193
+ }
194
+ }
195
+
196
+ // MARK: - Printer Status
197
+
198
+ @objc public func getPrinterStatus(identifier: String, completion: @escaping (String, String, Bool, String?) -> Void) {
199
+ // Send status request command
200
+ let statusCommand = Data([0x10, 0x04, 0x01]) // DLE EOT n
201
+
202
+ if let wifiManager = wifiManagers[identifier] {
203
+ if wifiManager.isConnected {
204
+ completion("ready", "ok", true, nil)
205
+ } else {
206
+ completion("offline", "unknown", false, nil)
207
+ }
208
+ } else if let bleManager = bleManager, bleManager.connectOK {
209
+ completion("ready", "ok", true, nil)
210
+ } else {
211
+ completion("offline", "unknown", false, nil)
212
+ }
213
+ }
214
+
215
+ // MARK: - Data Formatting
216
+
217
+ private func formatTextForPrinter(text: String) -> Data? {
218
+ var printData = Data()
219
+
220
+ // Initialize printer (ESC @)
221
+ printData.append(Data([0x1B, 0x40]))
222
+
223
+ // Add text
224
+ if let textData = text.data(using: .utf8) {
225
+ printData.append(textData)
226
+ }
227
+
228
+ // Line feeds
229
+ printData.append(Data([0x0A, 0x0A, 0x0A]))
230
+
231
+ // Cut paper (GS V m)
232
+ printData.append(Data([0x1D, 0x56, 0x41, 0x10]))
233
+
234
+ return printData
235
+ }
236
+
237
+ private func formatReceiptForPrinter(template: [String: Any]) -> Data? {
238
+ var printData = Data()
239
+
240
+ // Initialize printer
241
+ printData.append(Data([0x1B, 0x40]))
242
+
243
+ // Center align (ESC a 1)
244
+ printData.append(Data([0x1B, 0x61, 0x01]))
245
+
246
+ // Header
247
+ if let header = template["header"] as? String,
248
+ let headerData = (header + "\n\n").data(using: .utf8) {
249
+ printData.append(headerData)
250
+ }
251
+
252
+ // Left align (ESC a 0)
253
+ printData.append(Data([0x1B, 0x61, 0x00]))
254
+
255
+ // Items
256
+ if let items = template["items"] as? [[String: Any]] {
257
+ for item in items {
258
+ if let name = item["name"] as? String,
259
+ let price = item["price"] as? String {
260
+ let line = String(format: "%@\t%@\n", name, price)
261
+ if let lineData = line.data(using: .utf8) {
262
+ printData.append(lineData)
263
+ }
264
+ }
265
+ }
266
+ }
267
+
268
+ // Total
269
+ if let total = template["total"] as? String,
270
+ let totalData = ("\nTotal: " + total + "\n").data(using: .utf8) {
271
+ printData.append(totalData)
272
+ }
273
+
274
+ // Footer
275
+ if let footer = template["footer"] as? String,
276
+ let footerData = (footer + "\n").data(using: .utf8) {
277
+ printData.append(footerData)
278
+ }
279
+
280
+ // Line feeds
281
+ printData.append(Data([0x0A, 0x0A, 0x0A]))
282
+
283
+ // Cut paper
284
+ printData.append(Data([0x1D, 0x56, 0x41, 0x10]))
285
+
286
+ return printData
287
+ }
288
+
289
+ // MARK: - Callback Storage
290
+
291
+ private var discoveryCompletion: (([[String: Any]], String?) -> Void)?
292
+ private var connectionCompletion: ((Bool, String?) -> Void)?
293
+ private var printCompletion: ((Bool, String?) -> Void)?
294
+ }
295
+
296
+ // MARK: - POSBLEManagerDelegate
297
+
298
+ extension ZywellSDK: POSBLEManagerDelegate {
299
+
300
+ public func poSdidUpdatePeripheralList(_ peripherals: [Any]!, rssiList: [Any]!) {
301
+ guard let peripherals = peripherals as? [CBPeripheral],
302
+ let rssis = rssiList as? [NSNumber] else { return }
303
+
304
+ self.discoveredPeripherals = peripherals
305
+ self.peripheralRSSIs = rssis
306
+ }
307
+
308
+ public func poSdidConnect(_ peripheral: CBPeripheral!) {
309
+ connectionCompletion?(true, nil)
310
+ connectionCompletion = nil
311
+ }
312
+
313
+ public func poSdidFail(toConnect peripheral: CBPeripheral!, error: Error!) {
314
+ let errorMsg = error?.localizedDescription ?? "Connection failed"
315
+ connectionCompletion?(false, errorMsg)
316
+ connectionCompletion = nil
317
+ }
318
+
319
+ public func poSdidDisconnectPeripheral(_ peripheral: CBPeripheral!, isAutoDisconnect: Bool) {
320
+ // Handle disconnection
321
+ }
322
+
323
+ public func poSdidWriteValue(for character: CBCharacteristic!, error: Error!) {
324
+ if let error = error {
325
+ printCompletion?(false, error.localizedDescription)
326
+ } else {
327
+ printCompletion?(true, nil)
328
+ }
329
+ printCompletion = nil
330
+ }
331
+ }
332
+
333
+ // MARK: - POSWIFIManagerDelegate
334
+
335
+ extension ZywellSDK: POSWIFIManagerDelegate {
336
+
337
+ public func poswifiManager(_ manager: POSWIFIManager!, didConnectedToHost host: String!, port: UInt16) {
338
+ connectionCompletion?(true, nil)
339
+ connectionCompletion = nil
340
+ }
341
+
342
+ public func poswifiManager(_ manager: POSWIFIManager, willDisconnectWithError error: Error?) {
343
+ // Handle disconnection warning
344
+ }
345
+
346
+ public func poswifiManager(_ manager: POSWIFIManager!, didWriteDataWithTag tag: Int) {
347
+ printCompletion?(true, nil)
348
+ printCompletion = nil
349
+ }
350
+
351
+ public func poswifiManager(_ manager: POSWIFIManager, didRead data: Data, tag: Int) {
352
+ // Handle data reading if needed
353
+ }
354
+
355
+ public func poswifiManagerDidDisconnected(_ manager: POSWIFIManager!) {
356
+ // Handle disconnection
357
+ }
358
+ }
@@ -0,0 +1,16 @@
1
+ //
2
+ // Seven365Zyprinter-Umbrella.h
3
+ // Seven365Zyprinter
4
+ //
5
+ // Umbrella header for Zywell SDK Objective-C headers
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ // Zywell SDK Headers
11
+ #import "POSSDK.h"
12
+ #import "POSBLEManager.h"
13
+ #import "POSWIFIManager.h"
14
+ #import "PosCommand.h"
15
+ #import "TscCommand.h"
16
+ #import "ImageTranster.h"
@@ -0,0 +1,12 @@
1
+ module Seven365Zyprinter {
2
+ header "sources/POSSDK.h"
3
+ header "sources/POSBLEManager.h"
4
+ header "sources/POSWIFIManager.h"
5
+ header "sources/PosCommand.h"
6
+ header "sources/TscCommand.h"
7
+ header "sources/ImageTranster.h"
8
+
9
+ export *
10
+ module * { export * }
11
+ }
12
+