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.
- package/Package.swift +43 -0
- package/README.md +186 -0
- package/Seven365Zyprinter.podspec +27 -0
- package/android/build.gradle +58 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/mycompany/plugins/example/Example.java +342 -0
- package/android/src/main/java/com/mycompany/plugins/example/ExamplePlugin.java +161 -0
- package/android/src/main/res/.gitkeep +0 -0
- package/dist/docs.json +229 -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 +49 -0
- package/dist/esm/web.js +40 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +54 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +57 -0
- package/dist/plugin.js.map +1 -0
- package/ios/Seven365Zyprinter.podspec +28 -0
- package/ios/Sources/Plugin/ZyprintPlugin.swift +161 -0
- package/ios/Sources/Plugin/ZywellSDK.swift +358 -0
- package/ios/Sources/Seven365Zyprinter-Umbrella.h +16 -0
- package/ios/Sources/module.modulemap +12 -0
- package/ios/Sources/sources/BLEManager.h +658 -0
- package/ios/Sources/sources/BLEManager.m +2842 -0
- package/ios/Sources/sources/GCD/Documentation.html +47 -0
- package/ios/Sources/sources/GCD/GCDAsyncSocket.h +1226 -0
- package/ios/Sources/sources/GCD/GCDAsyncSocket.m +8560 -0
- package/ios/Sources/sources/GCD/GCDAsyncUdpSocket.h +1036 -0
- package/ios/Sources/sources/GCD/GCDAsyncUdpSocket.m +5632 -0
- package/ios/Sources/sources/GCD/PrinterManager.h +91 -0
- package/ios/Sources/sources/GCD/PrinterManager.m +513 -0
- package/ios/Sources/sources/GCD/WifiManager.h +91 -0
- package/ios/Sources/sources/GCD/WifiManager.m +510 -0
- package/ios/Sources/sources/ImageTranster.h +38 -0
- package/ios/Sources/sources/ImageTranster.m +389 -0
- package/ios/Sources/sources/POSBLEManager.h +759 -0
- package/ios/Sources/sources/POSBLEManager.m +834 -0
- package/ios/Sources/sources/POSSDK.h +93 -0
- package/ios/Sources/sources/POSWIFIManager.h +116 -0
- package/ios/Sources/sources/POSWIFIManager.m +260 -0
- package/ios/Sources/sources/POSWIFIManagerAsync.h +745 -0
- package/ios/Sources/sources/POSWIFIManagerAsync.m +1847 -0
- package/ios/Sources/sources/PosCommand.h +633 -0
- package/ios/Sources/sources/PosCommand.m +1019 -0
- package/ios/Sources/sources/TscCommand.h +723 -0
- package/ios/Sources/sources/TscCommand.m +566 -0
- package/ios/Tests/ExamplePluginTests/ExamplePluginTests.swift +15 -0
- package/package.json +339 -0
package/Package.swift
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// swift-tools-version: 5.9
|
|
2
|
+
import PackageDescription
|
|
3
|
+
|
|
4
|
+
let package = Package(
|
|
5
|
+
name: "Seven365Zyprinter",
|
|
6
|
+
platforms: [.iOS(.v14)],
|
|
7
|
+
products: [
|
|
8
|
+
.library(
|
|
9
|
+
name: "Seven365Zyprinter",
|
|
10
|
+
targets: ["Seven365ZyprinterPlugin"])
|
|
11
|
+
],
|
|
12
|
+
dependencies: [
|
|
13
|
+
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
|
14
|
+
],
|
|
15
|
+
targets: [
|
|
16
|
+
.target(
|
|
17
|
+
name: "Seven365ZyprinterPlugin",
|
|
18
|
+
dependencies: [
|
|
19
|
+
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
|
20
|
+
.product(name: "Cordova", package: "capacitor-swift-pm")
|
|
21
|
+
],
|
|
22
|
+
path: "ios/Sources",
|
|
23
|
+
exclude: [
|
|
24
|
+
"sources/GCD/Documentation.html"
|
|
25
|
+
],
|
|
26
|
+
sources: [
|
|
27
|
+
"Plugin/ZyprintPlugin.swift",
|
|
28
|
+
"Plugin/ZywellSDK.swift",
|
|
29
|
+
"sources"
|
|
30
|
+
],
|
|
31
|
+
publicHeadersPath: "Plugin",
|
|
32
|
+
cSettings: [
|
|
33
|
+
.headerSearchPath("sources"),
|
|
34
|
+
.headerSearchPath("sources/GCD"),
|
|
35
|
+
.headerSearchPath("Plugin")
|
|
36
|
+
]
|
|
37
|
+
),
|
|
38
|
+
.testTarget(
|
|
39
|
+
name: "Seven365ZyprinterPluginTests",
|
|
40
|
+
dependencies: ["Seven365ZyprinterPlugin"],
|
|
41
|
+
path: "ios/Tests/ExamplePluginTests")
|
|
42
|
+
]
|
|
43
|
+
)
|
package/README.md
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# seven365-zyprinter
|
|
2
|
+
|
|
3
|
+
plugin for integration of zyprinter
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install seven365-zyprinter
|
|
9
|
+
npx cap sync
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## API
|
|
13
|
+
|
|
14
|
+
<docgen-index>
|
|
15
|
+
|
|
16
|
+
* [`echo(...)`](#echo)
|
|
17
|
+
* [`discoverPrinters()`](#discoverprinters)
|
|
18
|
+
* [`discoverBluetoothPrinters()`](#discoverbluetoothprinters)
|
|
19
|
+
* [`discoverWiFiPrinters(...)`](#discoverwifiprinters)
|
|
20
|
+
* [`connectToPrinter(...)`](#connecttoprinter)
|
|
21
|
+
* [`disconnectFromPrinter(...)`](#disconnectfromprinter)
|
|
22
|
+
* [`printText(...)`](#printtext)
|
|
23
|
+
* [`printReceipt(...)`](#printreceipt)
|
|
24
|
+
* [`getPrinterStatus(...)`](#getprinterstatus)
|
|
25
|
+
* [Interfaces](#interfaces)
|
|
26
|
+
* [Type Aliases](#type-aliases)
|
|
27
|
+
|
|
28
|
+
</docgen-index>
|
|
29
|
+
|
|
30
|
+
<docgen-api>
|
|
31
|
+
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
|
32
|
+
|
|
33
|
+
### echo(...)
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
echo(options: { value: string; }) => Promise<{ value: string; }>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
| Param | Type |
|
|
40
|
+
| ------------- | ------------------------------- |
|
|
41
|
+
| **`options`** | <code>{ value: string; }</code> |
|
|
42
|
+
|
|
43
|
+
**Returns:** <code>Promise<{ value: string; }></code>
|
|
44
|
+
|
|
45
|
+
--------------------
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
### discoverPrinters()
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
discoverPrinters() => Promise<{ printers: ZyPrinter[]; }>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Returns:** <code>Promise<{ printers: ZyPrinter[]; }></code>
|
|
55
|
+
|
|
56
|
+
--------------------
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### discoverBluetoothPrinters()
|
|
60
|
+
|
|
61
|
+
```typescript
|
|
62
|
+
discoverBluetoothPrinters() => Promise<{ printers: ZyPrinter[]; }>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Returns:** <code>Promise<{ printers: ZyPrinter[]; }></code>
|
|
66
|
+
|
|
67
|
+
--------------------
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
### discoverWiFiPrinters(...)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
discoverWiFiPrinters(options?: { networkRange?: string | undefined; } | undefined) => Promise<{ printers: ZyPrinter[]; }>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
| Param | Type |
|
|
77
|
+
| ------------- | --------------------------------------- |
|
|
78
|
+
| **`options`** | <code>{ networkRange?: string; }</code> |
|
|
79
|
+
|
|
80
|
+
**Returns:** <code>Promise<{ printers: ZyPrinter[]; }></code>
|
|
81
|
+
|
|
82
|
+
--------------------
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
### connectToPrinter(...)
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
connectToPrinter(options: { identifier: string; }) => Promise<{ connected: boolean; }>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
| Param | Type |
|
|
92
|
+
| ------------- | ------------------------------------ |
|
|
93
|
+
| **`options`** | <code>{ identifier: string; }</code> |
|
|
94
|
+
|
|
95
|
+
**Returns:** <code>Promise<{ connected: boolean; }></code>
|
|
96
|
+
|
|
97
|
+
--------------------
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
### disconnectFromPrinter(...)
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
disconnectFromPrinter(options: { identifier: string; }) => Promise<{ disconnected: boolean; }>
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
| Param | Type |
|
|
107
|
+
| ------------- | ------------------------------------ |
|
|
108
|
+
| **`options`** | <code>{ identifier: string; }</code> |
|
|
109
|
+
|
|
110
|
+
**Returns:** <code>Promise<{ disconnected: boolean; }></code>
|
|
111
|
+
|
|
112
|
+
--------------------
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
### printText(...)
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
printText(options: { text: string; identifier: string; }) => Promise<{ success: boolean; }>
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
| Param | Type |
|
|
122
|
+
| ------------- | -------------------------------------------------- |
|
|
123
|
+
| **`options`** | <code>{ text: string; identifier: string; }</code> |
|
|
124
|
+
|
|
125
|
+
**Returns:** <code>Promise<{ success: boolean; }></code>
|
|
126
|
+
|
|
127
|
+
--------------------
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
### printReceipt(...)
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
printReceipt(options: { template: Record<string, any>; identifier: string; }) => Promise<{ success: boolean; }>
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
| Param | Type |
|
|
137
|
+
| ------------- | ----------------------------------------------------------------------------------------------- |
|
|
138
|
+
| **`options`** | <code>{ template: <a href="#record">Record</a><string, any>; identifier: string; }</code> |
|
|
139
|
+
|
|
140
|
+
**Returns:** <code>Promise<{ success: boolean; }></code>
|
|
141
|
+
|
|
142
|
+
--------------------
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
### getPrinterStatus(...)
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
getPrinterStatus(options: { identifier: string; }) => Promise<{ status: string; paperStatus: string; connected: boolean; }>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
| Param | Type |
|
|
152
|
+
| ------------- | ------------------------------------ |
|
|
153
|
+
| **`options`** | <code>{ identifier: string; }</code> |
|
|
154
|
+
|
|
155
|
+
**Returns:** <code>Promise<{ status: string; paperStatus: string; connected: boolean; }></code>
|
|
156
|
+
|
|
157
|
+
--------------------
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
### Interfaces
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
#### ZyPrinter
|
|
164
|
+
|
|
165
|
+
| Prop | Type |
|
|
166
|
+
| -------------------- | ------------------------------------------- |
|
|
167
|
+
| **`identifier`** | <code>string</code> |
|
|
168
|
+
| **`model`** | <code>string</code> |
|
|
169
|
+
| **`status`** | <code>string</code> |
|
|
170
|
+
| **`connectionType`** | <code>'bluetooth' \| 'wifi' \| 'usb'</code> |
|
|
171
|
+
| **`ipAddress`** | <code>string</code> |
|
|
172
|
+
| **`port`** | <code>number</code> |
|
|
173
|
+
| **`rssi`** | <code>number</code> |
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
### Type Aliases
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
#### Record
|
|
180
|
+
|
|
181
|
+
Construct a type with a set of properties K of type T
|
|
182
|
+
|
|
183
|
+
<code>{
|
|
184
|
[P in K]: T;
|
|
1
185
|
}</code>
|
|
186
|
+
|
|
187
|
+
</docgen-api>
|
|
188
|
+
# seven365-zyprinter-sdk
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
Pod::Spec.new do |s|
|
|
2
|
+
s.name = 'Seven365Zyprinter'
|
|
3
|
+
s.version = '0.0.1'
|
|
4
|
+
s.summary = 'Capacitor plugin for Zywell/Zyprint thermal printer integration'
|
|
5
|
+
s.license = 'MIT'
|
|
6
|
+
s.homepage = 'https://github.com/Seven365-Pte-Ltd/plateful-pos-mobile'
|
|
7
|
+
s.author = 'joelralph'
|
|
8
|
+
s.source = { :git => 'https://github.com/Seven365-Pte-Ltd/plateful-pos-mobile', :tag => s.version.to_s }
|
|
9
|
+
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
|
10
|
+
s.exclude_files = 'ios/Sources/sources/POSWIFIManagerAsync.{h,m}'
|
|
11
|
+
s.ios.deployment_target = '14.0'
|
|
12
|
+
s.dependency 'Capacitor'
|
|
13
|
+
s.swift_version = '5.1'
|
|
14
|
+
|
|
15
|
+
# Framework dependencies
|
|
16
|
+
s.frameworks = 'CoreBluetooth', 'SystemConfiguration', 'CFNetwork'
|
|
17
|
+
|
|
18
|
+
# Public headers for Objective-C SDK - expose to Swift
|
|
19
|
+
s.public_header_files = 'ios/Sources/sources/**/*.h'
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# Explicitly disable bridging header (not supported in frameworks)
|
|
23
|
+
s.pod_target_xcconfig = {
|
|
24
|
+
'SWIFT_OBJC_BRIDGING_HEADER' => '',
|
|
25
|
+
'DEFINES_MODULE' => 'YES'
|
|
26
|
+
}
|
|
27
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
buildscript {
|
|
9
|
+
repositories {
|
|
10
|
+
google()
|
|
11
|
+
mavenCentral()
|
|
12
|
+
}
|
|
13
|
+
dependencies {
|
|
14
|
+
classpath 'com.android.tools.build:gradle:8.7.2'
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
apply plugin: 'com.android.library'
|
|
19
|
+
|
|
20
|
+
android {
|
|
21
|
+
namespace "com.mycompany.plugins.example"
|
|
22
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
23
|
+
defaultConfig {
|
|
24
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
25
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
26
|
+
versionCode 1
|
|
27
|
+
versionName "1.0"
|
|
28
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
29
|
+
}
|
|
30
|
+
buildTypes {
|
|
31
|
+
release {
|
|
32
|
+
minifyEnabled false
|
|
33
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
lintOptions {
|
|
37
|
+
abortOnError false
|
|
38
|
+
}
|
|
39
|
+
compileOptions {
|
|
40
|
+
sourceCompatibility JavaVersion.VERSION_21
|
|
41
|
+
targetCompatibility JavaVersion.VERSION_21
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
repositories {
|
|
46
|
+
google()
|
|
47
|
+
mavenCentral()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
dependencies {
|
|
52
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
53
|
+
implementation project(':capacitor-android')
|
|
54
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
55
|
+
testImplementation "junit:junit:$junitVersion"
|
|
56
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
57
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
58
|
+
}
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
package com.mycompany.plugins.example;
|
|
2
|
+
|
|
3
|
+
import android.bluetooth.BluetoothAdapter;
|
|
4
|
+
import android.bluetooth.BluetoothDevice;
|
|
5
|
+
import android.bluetooth.BluetoothSocket;
|
|
6
|
+
import android.content.Context;
|
|
7
|
+
import android.util.Log;
|
|
8
|
+
import android.os.Handler;
|
|
9
|
+
import android.os.Looper;
|
|
10
|
+
|
|
11
|
+
import com.getcapacitor.JSArray;
|
|
12
|
+
import com.getcapacitor.JSObject;
|
|
13
|
+
|
|
14
|
+
import java.io.IOException;
|
|
15
|
+
import java.io.OutputStream;
|
|
16
|
+
import java.net.Socket;
|
|
17
|
+
import java.util.HashMap;
|
|
18
|
+
import java.util.Map;
|
|
19
|
+
import java.util.Set;
|
|
20
|
+
import java.util.UUID;
|
|
21
|
+
|
|
22
|
+
public class Zyprint {
|
|
23
|
+
|
|
24
|
+
private static final String TAG = "Zyprint";
|
|
25
|
+
private Map<String, PrinterConnection> connectedPrinters = new HashMap<>();
|
|
26
|
+
private Handler mainHandler = new Handler(Looper.getMainLooper());
|
|
27
|
+
|
|
28
|
+
// Callback interfaces
|
|
29
|
+
public interface PrinterDiscoveryCallback {
|
|
30
|
+
void onPrintersFound(JSArray printers);
|
|
31
|
+
void onError(String error);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
public interface ConnectionCallback {
|
|
35
|
+
void onConnected();
|
|
36
|
+
void onError(String error);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public interface DisconnectionCallback {
|
|
40
|
+
void onDisconnected();
|
|
41
|
+
void onError(String error);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
public interface PrintCallback {
|
|
45
|
+
void onSuccess();
|
|
46
|
+
void onError(String error);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
public interface StatusCallback {
|
|
50
|
+
void onStatus(String status, String paperStatus, boolean connected);
|
|
51
|
+
void onError(String error);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public String echo(String value) {
|
|
55
|
+
Log.i(TAG, "Echo: " + value);
|
|
56
|
+
return value;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public void discoverPrinters(PrinterDiscoveryCallback callback) {
|
|
60
|
+
new Thread(() -> {
|
|
61
|
+
try {
|
|
62
|
+
JSArray printers = new JSArray();
|
|
63
|
+
|
|
64
|
+
// Discover Bluetooth printers
|
|
65
|
+
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
66
|
+
if (bluetoothAdapter != null && bluetoothAdapter.isEnabled()) {
|
|
67
|
+
Set<BluetoothDevice> pairedDevices = bluetoothAdapter.getBondedDevices();
|
|
68
|
+
|
|
69
|
+
for (BluetoothDevice device : pairedDevices) {
|
|
70
|
+
// Filter for printer devices (you may need to adjust this based on Zywell printer naming)
|
|
71
|
+
if (device.getName() != null &&
|
|
72
|
+
(device.getName().toLowerCase().contains("zywell") ||
|
|
73
|
+
device.getName().toLowerCase().contains("zyprint") ||
|
|
74
|
+
device.getName().toLowerCase().contains("printer"))) {
|
|
75
|
+
|
|
76
|
+
JSObject printer = new JSObject();
|
|
77
|
+
printer.put("identifier", device.getAddress());
|
|
78
|
+
printer.put("model", device.getName());
|
|
79
|
+
printer.put("status", device.getBondState() == BluetoothDevice.BOND_BONDED ? "ready" : "offline");
|
|
80
|
+
printers.put(printer);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
mainHandler.post(() -> callback.onPrintersFound(printers));
|
|
86
|
+
|
|
87
|
+
} catch (Exception e) {
|
|
88
|
+
Log.e(TAG, "Error discovering printers", e);
|
|
89
|
+
mainHandler.post(() -> callback.onError("Discovery failed: " + e.getMessage()));
|
|
90
|
+
}
|
|
91
|
+
}).start();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public void connectToPrinter(String identifier, ConnectionCallback callback) {
|
|
95
|
+
new Thread(() -> {
|
|
96
|
+
try {
|
|
97
|
+
PrinterConnection connection = new PrinterConnection();
|
|
98
|
+
|
|
99
|
+
// Try to connect via Bluetooth
|
|
100
|
+
BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
|
|
101
|
+
if (bluetoothAdapter != null) {
|
|
102
|
+
BluetoothDevice device = bluetoothAdapter.getRemoteDevice(identifier);
|
|
103
|
+
|
|
104
|
+
if (connection.connectBluetooth(device)) {
|
|
105
|
+
connectedPrinters.put(identifier, connection);
|
|
106
|
+
mainHandler.post(callback::onConnected);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// If Bluetooth fails, try WiFi (if identifier is an IP address)
|
|
112
|
+
if (identifier.matches("\\d+\\.\\d+\\.\\d+\\.\\d+")) {
|
|
113
|
+
if (connection.connectWiFi(identifier, 9100)) {
|
|
114
|
+
connectedPrinters.put(identifier, connection);
|
|
115
|
+
mainHandler.post(callback::onConnected);
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
mainHandler.post(() -> callback.onError("Connection failed"));
|
|
121
|
+
|
|
122
|
+
} catch (Exception e) {
|
|
123
|
+
Log.e(TAG, "Error connecting to printer", e);
|
|
124
|
+
mainHandler.post(() -> callback.onError("Connection failed: " + e.getMessage()));
|
|
125
|
+
}
|
|
126
|
+
}).start();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
public void disconnectFromPrinter(String identifier, DisconnectionCallback callback) {
|
|
130
|
+
PrinterConnection connection = connectedPrinters.get(identifier);
|
|
131
|
+
if (connection != null) {
|
|
132
|
+
connection.disconnect();
|
|
133
|
+
connectedPrinters.remove(identifier);
|
|
134
|
+
callback.onDisconnected();
|
|
135
|
+
} else {
|
|
136
|
+
callback.onError("Printer not connected");
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public void printText(String text, String identifier, PrintCallback callback) {
|
|
141
|
+
PrinterConnection connection = connectedPrinters.get(identifier);
|
|
142
|
+
if (connection == null) {
|
|
143
|
+
callback.onError("Printer not connected");
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
new Thread(() -> {
|
|
148
|
+
try {
|
|
149
|
+
byte[] data = formatTextForPrinter(text);
|
|
150
|
+
if (connection.sendData(data)) {
|
|
151
|
+
mainHandler.post(callback::onSuccess);
|
|
152
|
+
} else {
|
|
153
|
+
mainHandler.post(() -> callback.onError("Print failed"));
|
|
154
|
+
}
|
|
155
|
+
} catch (Exception e) {
|
|
156
|
+
Log.e(TAG, "Error printing text", e);
|
|
157
|
+
mainHandler.post(() -> callback.onError("Print failed: " + e.getMessage()));
|
|
158
|
+
}
|
|
159
|
+
}).start();
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public void printReceipt(JSObject template, String identifier, PrintCallback callback) {
|
|
163
|
+
PrinterConnection connection = connectedPrinters.get(identifier);
|
|
164
|
+
if (connection == null) {
|
|
165
|
+
callback.onError("Printer not connected");
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
new Thread(() -> {
|
|
170
|
+
try {
|
|
171
|
+
byte[] data = formatReceiptForPrinter(template);
|
|
172
|
+
if (connection.sendData(data)) {
|
|
173
|
+
mainHandler.post(callback::onSuccess);
|
|
174
|
+
} else {
|
|
175
|
+
mainHandler.post(() -> callback.onError("Print failed"));
|
|
176
|
+
}
|
|
177
|
+
} catch (Exception e) {
|
|
178
|
+
Log.e(TAG, "Error printing receipt", e);
|
|
179
|
+
mainHandler.post(() -> callback.onError("Print failed: " + e.getMessage()));
|
|
180
|
+
}
|
|
181
|
+
}).start();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
public void getPrinterStatus(String identifier, StatusCallback callback) {
|
|
185
|
+
PrinterConnection connection = connectedPrinters.get(identifier);
|
|
186
|
+
if (connection == null) {
|
|
187
|
+
callback.onStatus("offline", "unknown", false);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
new Thread(() -> {
|
|
192
|
+
try {
|
|
193
|
+
// Send status command (this would be specific to Zywell protocol)
|
|
194
|
+
byte[] statusCommand = {0x10, 0x04, 0x01}; // Example status command
|
|
195
|
+
|
|
196
|
+
if (connection.sendData(statusCommand)) {
|
|
197
|
+
// In a real implementation, you'd read the response and parse it
|
|
198
|
+
mainHandler.post(() -> callback.onStatus("ready", "ok", true));
|
|
199
|
+
} else {
|
|
200
|
+
mainHandler.post(() -> callback.onStatus("error", "unknown", true));
|
|
201
|
+
}
|
|
202
|
+
} catch (Exception e) {
|
|
203
|
+
Log.e(TAG, "Error getting printer status", e);
|
|
204
|
+
mainHandler.post(() -> callback.onError("Status check failed: " + e.getMessage()));
|
|
205
|
+
}
|
|
206
|
+
}).start();
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private byte[] formatTextForPrinter(String text) {
|
|
210
|
+
try {
|
|
211
|
+
// ESC/POS commands for text printing
|
|
212
|
+
byte[] initPrinter = {0x1B, 0x40}; // ESC @
|
|
213
|
+
byte[] textBytes = text.getBytes("UTF-8");
|
|
214
|
+
byte[] lineFeed = {0x0A, 0x0A, 0x0A}; // Line feeds
|
|
215
|
+
byte[] cutPaper = {0x1D, 0x56, 0x41, 0x10}; // Cut command
|
|
216
|
+
|
|
217
|
+
byte[] result = new byte[initPrinter.length + textBytes.length + lineFeed.length + cutPaper.length];
|
|
218
|
+
int offset = 0;
|
|
219
|
+
|
|
220
|
+
System.arraycopy(initPrinter, 0, result, offset, initPrinter.length);
|
|
221
|
+
offset += initPrinter.length;
|
|
222
|
+
|
|
223
|
+
System.arraycopy(textBytes, 0, result, offset, textBytes.length);
|
|
224
|
+
offset += textBytes.length;
|
|
225
|
+
|
|
226
|
+
System.arraycopy(lineFeed, 0, result, offset, lineFeed.length);
|
|
227
|
+
offset += lineFeed.length;
|
|
228
|
+
|
|
229
|
+
System.arraycopy(cutPaper, 0, result, offset, cutPaper.length);
|
|
230
|
+
|
|
231
|
+
return result;
|
|
232
|
+
} catch (Exception e) {
|
|
233
|
+
Log.e(TAG, "Error formatting text", e);
|
|
234
|
+
return new byte[0];
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
private byte[] formatReceiptForPrinter(JSObject template) {
|
|
239
|
+
try {
|
|
240
|
+
StringBuilder receiptText = new StringBuilder();
|
|
241
|
+
|
|
242
|
+
// Initialize printer
|
|
243
|
+
receiptText.append("\u001B@"); // ESC @
|
|
244
|
+
|
|
245
|
+
// Center align
|
|
246
|
+
receiptText.append("\u001B\u0061\u0001"); // ESC a 1
|
|
247
|
+
|
|
248
|
+
// Header
|
|
249
|
+
if (template.has("header")) {
|
|
250
|
+
receiptText.append(template.getString("header")).append("\n\n");
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Left align for items
|
|
254
|
+
receiptText.append("\u001B\u0061\u0000"); // ESC a 0
|
|
255
|
+
|
|
256
|
+
// Items
|
|
257
|
+
if (template.has("items")) {
|
|
258
|
+
JSArray items = template.getJSArray("items");
|
|
259
|
+
for (int i = 0; i < items.length(); i++) {
|
|
260
|
+
JSObject item = items.getJSObject(i);
|
|
261
|
+
String name = item.optString("name", "");
|
|
262
|
+
String price = item.optString("price", "");
|
|
263
|
+
receiptText.append(name).append("\t").append(price).append("\n");
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// Total
|
|
268
|
+
if (template.has("total")) {
|
|
269
|
+
receiptText.append("\nTotal: ").append(template.getString("total")).append("\n");
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Line feeds and cut
|
|
273
|
+
receiptText.append("\n\n\n");
|
|
274
|
+
receiptText.append("\u001D\u0056\u0041\u0010"); // Cut command
|
|
275
|
+
|
|
276
|
+
return receiptText.toString().getBytes("UTF-8");
|
|
277
|
+
} catch (Exception e) {
|
|
278
|
+
Log.e(TAG, "Error formatting receipt", e);
|
|
279
|
+
return new byte[0];
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
private static class PrinterConnection {
|
|
284
|
+
private BluetoothSocket bluetoothSocket;
|
|
285
|
+
private Socket wifiSocket;
|
|
286
|
+
private OutputStream outputStream;
|
|
287
|
+
|
|
288
|
+
public boolean connectBluetooth(BluetoothDevice device) {
|
|
289
|
+
try {
|
|
290
|
+
// UUID for printer service (this might need to be specific to Zywell)
|
|
291
|
+
UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
|
|
292
|
+
bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
|
|
293
|
+
bluetoothSocket.connect();
|
|
294
|
+
outputStream = bluetoothSocket.getOutputStream();
|
|
295
|
+
return true;
|
|
296
|
+
} catch (Exception e) {
|
|
297
|
+
Log.e(TAG, "Bluetooth connection failed", e);
|
|
298
|
+
return false;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
public boolean connectWiFi(String ipAddress, int port) {
|
|
303
|
+
try {
|
|
304
|
+
wifiSocket = new Socket(ipAddress, port);
|
|
305
|
+
outputStream = wifiSocket.getOutputStream();
|
|
306
|
+
return true;
|
|
307
|
+
} catch (Exception e) {
|
|
308
|
+
Log.e(TAG, "WiFi connection failed", e);
|
|
309
|
+
return false;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
public boolean sendData(byte[] data) {
|
|
314
|
+
try {
|
|
315
|
+
if (outputStream != null) {
|
|
316
|
+
outputStream.write(data);
|
|
317
|
+
outputStream.flush();
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
} catch (IOException e) {
|
|
321
|
+
Log.e(TAG, "Error sending data", e);
|
|
322
|
+
}
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
public void disconnect() {
|
|
327
|
+
try {
|
|
328
|
+
if (outputStream != null) {
|
|
329
|
+
outputStream.close();
|
|
330
|
+
}
|
|
331
|
+
if (bluetoothSocket != null) {
|
|
332
|
+
bluetoothSocket.close();
|
|
333
|
+
}
|
|
334
|
+
if (wifiSocket != null) {
|
|
335
|
+
wifiSocket.close();
|
|
336
|
+
}
|
|
337
|
+
} catch (IOException e) {
|
|
338
|
+
Log.e(TAG, "Error disconnecting", e);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|