@posx/capacitor-usb-printer 0.0.5 → 0.0.7
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/README.md +1 -0
- package/android/src/main/java/ai/posx/capacitor/usbprinter/UsbPrinter.java +37 -5
- package/android/src/main/java/ai/posx/capacitor/usbprinter/UsbPrinterPlugin.java +4 -1
- package/dist/docs.json +7 -0
- package/dist/esm/definitions.d.ts +1 -0
- package/dist/esm/definitions.js.map +1 -1
- package/package.json +63 -63
package/README.md
CHANGED
|
@@ -153,6 +153,7 @@ addListener(eventName: 'deviceDetached', listenerFunc: (device: UsbDevice) => vo
|
|
|
153
153
|
| **`vendorId`** | <code>number</code> |
|
|
154
154
|
| **`productId`** | <code>number</code> |
|
|
155
155
|
| **`deviceName`** | <code>string</code> |
|
|
156
|
+
| **`portPath`** | <code>string</code> |
|
|
156
157
|
| **`manufacturerName`** | <code>string</code> |
|
|
157
158
|
| **`productName`** | <code>string</code> |
|
|
158
159
|
| **`serialNumber`** | <code>string</code> |
|
|
@@ -9,9 +9,12 @@ import android.hardware.usb.*;
|
|
|
9
9
|
import android.os.Build;
|
|
10
10
|
import android.util.Log;
|
|
11
11
|
|
|
12
|
+
import java.io.File;
|
|
12
13
|
import java.util.ArrayList;
|
|
14
|
+
import java.util.Collections;
|
|
13
15
|
import java.util.List;
|
|
14
16
|
import java.util.Map;
|
|
17
|
+
import java.util.Scanner;
|
|
15
18
|
import java.util.concurrent.ConcurrentHashMap;
|
|
16
19
|
|
|
17
20
|
public class UsbPrinter {
|
|
@@ -24,12 +27,30 @@ public class UsbPrinter {
|
|
|
24
27
|
|
|
25
28
|
public UsbPrinter(Context context) {
|
|
26
29
|
usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
|
|
30
|
+
if (usbManager == null) Log.e(TAG, "USB service unavailable on this device");
|
|
27
31
|
}
|
|
28
32
|
|
|
29
33
|
public List<UsbDevice> listDevices() {
|
|
34
|
+
if (usbManager == null) return Collections.emptyList();
|
|
30
35
|
return new ArrayList<>(usbManager.getDeviceList().values());
|
|
31
36
|
}
|
|
32
37
|
|
|
38
|
+
public String getPortPath(UsbDevice device) {
|
|
39
|
+
String[] parts = device.getDeviceName().split("/");
|
|
40
|
+
try {
|
|
41
|
+
int busNum = Integer.parseInt(parts[parts.length - 2]);
|
|
42
|
+
int devNum = Integer.parseInt(parts[parts.length - 1]);
|
|
43
|
+
for (File f : new File("/sys/bus/usb/devices").listFiles()) {
|
|
44
|
+
File bf = new File(f, "busnum"), df = new File(f, "devnum");
|
|
45
|
+
if (!bf.exists()) continue;
|
|
46
|
+
if (Integer.parseInt(new Scanner(bf).nextLine()) == busNum &&
|
|
47
|
+
Integer.parseInt(new Scanner(df).nextLine()) == devNum)
|
|
48
|
+
return f.getName();
|
|
49
|
+
}
|
|
50
|
+
} catch (Exception ignored) {}
|
|
51
|
+
return "";
|
|
52
|
+
}
|
|
53
|
+
|
|
33
54
|
public String getSerialNumber(UsbDevice device) {
|
|
34
55
|
try {
|
|
35
56
|
return device.getSerialNumber() != null ? device.getSerialNumber() : "";
|
|
@@ -39,6 +60,7 @@ public class UsbPrinter {
|
|
|
39
60
|
}
|
|
40
61
|
|
|
41
62
|
public void requestPermission(Context context, UsbDevice device, PermissionCallback callback) {
|
|
63
|
+
if (usbManager == null) { callback.onResult(false); return; }
|
|
42
64
|
if (usbManager.hasPermission(device)) {
|
|
43
65
|
callback.onResult(true);
|
|
44
66
|
return;
|
|
@@ -70,6 +92,7 @@ public class UsbPrinter {
|
|
|
70
92
|
}
|
|
71
93
|
|
|
72
94
|
public boolean connect(UsbDevice device) {
|
|
95
|
+
if (usbManager == null) return false;
|
|
73
96
|
int id = device.getDeviceId();
|
|
74
97
|
if (connections.containsKey(id)) return true;
|
|
75
98
|
|
|
@@ -101,7 +124,11 @@ public class UsbPrinter {
|
|
|
101
124
|
}
|
|
102
125
|
|
|
103
126
|
try {
|
|
104
|
-
conn.claimInterface(usbInterface, true)
|
|
127
|
+
if (!conn.claimInterface(usbInterface, true)) {
|
|
128
|
+
conn.close();
|
|
129
|
+
Log.e(TAG, "Failed to claim interface for device " + id);
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
105
132
|
String name = device.getProductName() != null ? device.getProductName() : device.getDeviceName();
|
|
106
133
|
String serial = getSerialNumber(device);
|
|
107
134
|
connections.put(id, new DeviceConnection(conn, bulkOut, usbInterface, name, serial));
|
|
@@ -129,8 +156,8 @@ public class UsbPrinter {
|
|
|
129
156
|
DeviceConnection dc = connections.get(deviceId);
|
|
130
157
|
if (dc == null) return false;
|
|
131
158
|
int result = dc.connection.bulkTransfer(dc.bulkOut, data, data.length, 10000);
|
|
132
|
-
if (result
|
|
133
|
-
return result
|
|
159
|
+
if (result <= 0) Log.e(TAG, "Transfer failed for device " + deviceId + ": " + result);
|
|
160
|
+
return result > 0;
|
|
134
161
|
}
|
|
135
162
|
|
|
136
163
|
public DeviceConnection getConnection(int deviceId) {
|
|
@@ -138,6 +165,7 @@ public class UsbPrinter {
|
|
|
138
165
|
}
|
|
139
166
|
|
|
140
167
|
public UsbDevice findDevice(int deviceId) {
|
|
168
|
+
if (usbManager == null) return null;
|
|
141
169
|
for (UsbDevice device : usbManager.getDeviceList().values()) {
|
|
142
170
|
if (device.getDeviceId() == deviceId) return device;
|
|
143
171
|
}
|
|
@@ -148,8 +176,12 @@ public class UsbPrinter {
|
|
|
148
176
|
if (hex.length() % 2 != 0) throw new IllegalArgumentException("Hex string length must be even");
|
|
149
177
|
int len = hex.length();
|
|
150
178
|
byte[] data = new byte[len / 2];
|
|
151
|
-
for (int i = 0; i < len; i += 2)
|
|
152
|
-
|
|
179
|
+
for (int i = 0; i < len; i += 2) {
|
|
180
|
+
int hi = Character.digit(hex.charAt(i), 16);
|
|
181
|
+
int lo = Character.digit(hex.charAt(i + 1), 16);
|
|
182
|
+
if (hi < 0 || lo < 0) throw new IllegalArgumentException("Invalid hex char at position " + i);
|
|
183
|
+
data[i / 2] = (byte) ((hi << 4) + lo);
|
|
184
|
+
}
|
|
153
185
|
return data;
|
|
154
186
|
}
|
|
155
187
|
|
|
@@ -39,7 +39,7 @@ public class UsbPrinterPlugin extends Plugin {
|
|
|
39
39
|
notifyListeners("deviceDetached", data);
|
|
40
40
|
} else {
|
|
41
41
|
// request permission first so serialNumber is readable
|
|
42
|
-
implementation.requestPermission(
|
|
42
|
+
implementation.requestPermission(getContext(), device, granted -> {
|
|
43
43
|
data.put("serialNumber", implementation.getSerialNumber(device));
|
|
44
44
|
notifyListeners("deviceAttached", data);
|
|
45
45
|
});
|
|
@@ -85,6 +85,7 @@ public class UsbPrinterPlugin extends Plugin {
|
|
|
85
85
|
d.put("vendorId", device.getVendorId());
|
|
86
86
|
d.put("productId", device.getProductId());
|
|
87
87
|
d.put("deviceName", device.getDeviceName());
|
|
88
|
+
d.put("portPath", implementation.getPortPath(device));
|
|
88
89
|
d.put("manufacturerName", device.getManufacturerName() != null ? device.getManufacturerName() : "");
|
|
89
90
|
d.put("productName", device.getProductName() != null ? device.getProductName() : "");
|
|
90
91
|
return d;
|
|
@@ -173,6 +174,8 @@ public class UsbPrinterPlugin extends Plugin {
|
|
|
173
174
|
boolean success = implementation.print(deviceId, bytes);
|
|
174
175
|
if (success) call.resolve();
|
|
175
176
|
else call.reject("Not connected or transfer failed");
|
|
177
|
+
} catch (IllegalArgumentException e) {
|
|
178
|
+
call.reject("Invalid hex data: " + e.getMessage());
|
|
176
179
|
} catch (Exception e) {
|
|
177
180
|
call.reject("Failed to print", e);
|
|
178
181
|
}
|
package/dist/docs.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\r\n\r\nexport interface UsbDevice {\r\n deviceId: number;\r\n vendorId: number;\r\n productId: number;\r\n deviceName: string;\r\n manufacturerName: string;\r\n productName: string;\r\n serialNumber: string;\r\n}\r\n\r\nexport interface UsbPrinterPlugin {\r\n listDevices(): Promise<{ devices: UsbDevice[] }>;\r\n requestPermission(options: { deviceId: number }): Promise<{ granted: boolean }>;\r\n connect(options: { deviceId: number }): Promise<{ connected: boolean }>;\r\n disconnect(options: { deviceId: number }): Promise<void>;\r\n print(options: { deviceId: number; data: string }): Promise<void>;\r\n getStatus(options: { deviceId: number }): Promise<{ connected: boolean; deviceName: string; serialNumber: string }>;\r\n addListener(eventName: 'deviceAttached', listenerFunc: (device: UsbDevice) => void): Promise<PluginListenerHandle>;\r\n addListener(eventName: 'deviceDetached', listenerFunc: (device: UsbDevice) => void): Promise<PluginListenerHandle>;\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PluginListenerHandle } from '@capacitor/core';\r\n\r\nexport interface UsbDevice {\r\n deviceId: number;\r\n vendorId: number;\r\n productId: number;\r\n deviceName: string;\r\n portPath: string;\r\n manufacturerName: string;\r\n productName: string;\r\n serialNumber: string;\r\n}\r\n\r\nexport interface UsbPrinterPlugin {\r\n listDevices(): Promise<{ devices: UsbDevice[] }>;\r\n requestPermission(options: { deviceId: number }): Promise<{ granted: boolean }>;\r\n connect(options: { deviceId: number }): Promise<{ connected: boolean }>;\r\n disconnect(options: { deviceId: number }): Promise<void>;\r\n print(options: { deviceId: number; data: string }): Promise<void>;\r\n getStatus(options: { deviceId: number }): Promise<{ connected: boolean; deviceName: string; serialNumber: string }>;\r\n addListener(eventName: 'deviceAttached', listenerFunc: (device: UsbDevice) => void): Promise<PluginListenerHandle>;\r\n addListener(eventName: 'deviceDetached', listenerFunc: (device: UsbDevice) => void): Promise<PluginListenerHandle>;\r\n}\r\n"]}
|
package/package.json
CHANGED
|
@@ -1,63 +1,63 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@posx/capacitor-usb-printer",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Capacitor plugin for USB ESC/POS thermal printer via Android USB Host API",
|
|
5
|
-
"main": "dist/plugin.cjs.js",
|
|
6
|
-
"module": "dist/esm/index.js",
|
|
7
|
-
"types": "dist/esm/index.d.ts",
|
|
8
|
-
"unpkg": "dist/plugin.js",
|
|
9
|
-
"files": [
|
|
10
|
-
"android/src/main/",
|
|
11
|
-
"android/build.gradle",
|
|
12
|
-
"dist/"
|
|
13
|
-
],
|
|
14
|
-
"author": "posx team",
|
|
15
|
-
"license": "MIT",
|
|
16
|
-
"keywords": [
|
|
17
|
-
"capacitor",
|
|
18
|
-
"plugin",
|
|
19
|
-
"native"
|
|
20
|
-
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"verify": "npm run verify:android && npm run verify:web",
|
|
23
|
-
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
24
|
-
"verify:web": "npm run build",
|
|
25
|
-
"lint": "npm run eslint && npm run prettier -- --check",
|
|
26
|
-
"fmt": "npm run eslint -- --fix && npm run prettier -- --write",
|
|
27
|
-
"eslint": "eslint . --ext ts",
|
|
28
|
-
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
29
|
-
"docgen": "docgen --api UsbPrinterPlugin --output-readme README.md --output-json dist/docs.json",
|
|
30
|
-
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
31
|
-
"clean": "rimraf ./dist",
|
|
32
|
-
"p": "npm run build && npm publish",
|
|
33
|
-
"bump": "bumpp patch --commit --tag --push --yes",
|
|
34
|
-
"watch": "tsc --watch",
|
|
35
|
-
"prepublishOnly": "npm run build"
|
|
36
|
-
},
|
|
37
|
-
"devDependencies": {
|
|
38
|
-
"@capacitor/android": "^5.7.8",
|
|
39
|
-
"@capacitor/core": "^5.7.8",
|
|
40
|
-
"@capacitor/docgen": "^0.3.1",
|
|
41
|
-
"@ionic/eslint-config": "^0.4.0",
|
|
42
|
-
"@ionic/prettier-config": "^4.0.0",
|
|
43
|
-
"bumpp": "10.4.1",
|
|
44
|
-
"eslint": "^8.57.1",
|
|
45
|
-
"prettier": "^3.6.2",
|
|
46
|
-
"prettier-plugin-java": "^2.7.7",
|
|
47
|
-
"rimraf": "^6.1.0",
|
|
48
|
-
"rollup": "^4.53.2",
|
|
49
|
-
"typescript": "^5.9.3"
|
|
50
|
-
},
|
|
51
|
-
"peerDependencies": {
|
|
52
|
-
"@capacitor/core": ">=5.0.0"
|
|
53
|
-
},
|
|
54
|
-
"prettier": "@ionic/prettier-config",
|
|
55
|
-
"eslintConfig": {
|
|
56
|
-
"extends": "@ionic/eslint-config/recommended"
|
|
57
|
-
},
|
|
58
|
-
"capacitor": {
|
|
59
|
-
"android": {
|
|
60
|
-
"src": "android"
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@posx/capacitor-usb-printer",
|
|
3
|
+
"version": "0.0.7",
|
|
4
|
+
"description": "Capacitor plugin for USB ESC/POS thermal printer via Android USB Host API",
|
|
5
|
+
"main": "dist/plugin.cjs.js",
|
|
6
|
+
"module": "dist/esm/index.js",
|
|
7
|
+
"types": "dist/esm/index.d.ts",
|
|
8
|
+
"unpkg": "dist/plugin.js",
|
|
9
|
+
"files": [
|
|
10
|
+
"android/src/main/",
|
|
11
|
+
"android/build.gradle",
|
|
12
|
+
"dist/"
|
|
13
|
+
],
|
|
14
|
+
"author": "posx team",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"capacitor",
|
|
18
|
+
"plugin",
|
|
19
|
+
"native"
|
|
20
|
+
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"verify": "npm run verify:android && npm run verify:web",
|
|
23
|
+
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
|
24
|
+
"verify:web": "npm run build",
|
|
25
|
+
"lint": "npm run eslint && npm run prettier -- --check",
|
|
26
|
+
"fmt": "npm run eslint -- --fix && npm run prettier -- --write",
|
|
27
|
+
"eslint": "eslint . --ext ts",
|
|
28
|
+
"prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
|
|
29
|
+
"docgen": "docgen --api UsbPrinterPlugin --output-readme README.md --output-json dist/docs.json",
|
|
30
|
+
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
|
31
|
+
"clean": "rimraf ./dist",
|
|
32
|
+
"p": "npm run build && npm publish",
|
|
33
|
+
"bump": "bumpp patch --commit --tag --push --yes",
|
|
34
|
+
"watch": "tsc --watch",
|
|
35
|
+
"prepublishOnly": "npm run build"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@capacitor/android": "^5.7.8",
|
|
39
|
+
"@capacitor/core": "^5.7.8",
|
|
40
|
+
"@capacitor/docgen": "^0.3.1",
|
|
41
|
+
"@ionic/eslint-config": "^0.4.0",
|
|
42
|
+
"@ionic/prettier-config": "^4.0.0",
|
|
43
|
+
"bumpp": "10.4.1",
|
|
44
|
+
"eslint": "^8.57.1",
|
|
45
|
+
"prettier": "^3.6.2",
|
|
46
|
+
"prettier-plugin-java": "^2.7.7",
|
|
47
|
+
"rimraf": "^6.1.0",
|
|
48
|
+
"rollup": "^4.53.2",
|
|
49
|
+
"typescript": "^5.9.3"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"@capacitor/core": ">=5.0.0"
|
|
53
|
+
},
|
|
54
|
+
"prettier": "@ionic/prettier-config",
|
|
55
|
+
"eslintConfig": {
|
|
56
|
+
"extends": "@ionic/eslint-config/recommended"
|
|
57
|
+
},
|
|
58
|
+
"capacitor": {
|
|
59
|
+
"android": {
|
|
60
|
+
"src": "android"
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|