@amitkhare/capacitor-cat-printer 0.5.0
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/LICENSE +21 -0
- package/README.md +324 -0
- package/android/build.gradle +44 -0
- package/android/src/main/AndroidManifest.xml +21 -0
- package/android/src/main/java/khare/catprinter/plugin/CatPrinterCore.java +661 -0
- package/android/src/main/java/khare/catprinter/plugin/CatPrinterPlugin.java +348 -0
- package/android/src/main/java/khare/catprinter/plugin/ImageProcessor.java +213 -0
- package/android/src/main/java/khare/catprinter/plugin/PrinterProtocol.java +243 -0
- package/dist/esm/definitions.d.ts +189 -0
- package/dist/esm/definitions.d.ts.map +1 -0
- package/dist/esm/definitions.js +8 -0
- package/dist/esm/definitions.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/web.d.ts +13 -0
- package/dist/esm/web.d.ts.map +1 -0
- package/dist/esm/web.js +28 -0
- package/dist/esm/web.js.map +1 -0
- package/dist/plugin.cjs.js +51 -0
- package/dist/plugin.cjs.js.map +1 -0
- package/dist/plugin.js +54 -0
- package/dist/plugin.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Amit Kumar Khare
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
# Capacitor Cat Printer Plugin
|
|
2
|
+
|
|
3
|
+
A Capacitor plugin for printing to Cat thermal printers (and compatible devices) via Bluetooth Low Energy (BLE).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Scan for BLE printers
|
|
8
|
+
- Connect/disconnect to printers
|
|
9
|
+
- Print text with customizable font, alignment, and styling
|
|
10
|
+
- Print images with dithering support for better quality
|
|
11
|
+
- Paper feed control
|
|
12
|
+
- Support for 58mm (384px) and 80mm (576px) paper widths
|
|
13
|
+
- Real-time print progress events
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install capacitor-cat-printer
|
|
19
|
+
npx cap sync android
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For local development:
|
|
23
|
+
```bash
|
|
24
|
+
npm install file:../path/to/capacitor-cat-printer
|
|
25
|
+
npx cap sync android
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Android Setup
|
|
29
|
+
|
|
30
|
+
### 1. Add Permissions to AndroidManifest.xml
|
|
31
|
+
|
|
32
|
+
Add these permissions **before** the `<application>` tag in `android/app/src/main/AndroidManifest.xml`:
|
|
33
|
+
|
|
34
|
+
```xml
|
|
35
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
36
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
37
|
+
xmlns:tools="http://schemas.android.com/tools">
|
|
38
|
+
|
|
39
|
+
<!-- Bluetooth permissions for Android 11 and below -->
|
|
40
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
41
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
42
|
+
|
|
43
|
+
<!-- Bluetooth permissions for Android 12+ -->
|
|
44
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
45
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
46
|
+
|
|
47
|
+
<!-- Location permission required for BLE scanning -->
|
|
48
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" tools:remove="android:maxSdkVersion" />
|
|
49
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" tools:remove="android:maxSdkVersion" />
|
|
50
|
+
|
|
51
|
+
<!-- Declare BLE feature -->
|
|
52
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
53
|
+
|
|
54
|
+
<application>
|
|
55
|
+
<!-- ... -->
|
|
56
|
+
</application>
|
|
57
|
+
</manifest>
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Important:** The `tools:remove="android:maxSdkVersion"` attribute is required to ensure location permissions work on Android 12+.
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
### Import
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { CatPrinter, PaperWidth } from 'capacitor-cat-printer';
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Scan for Printers
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// Scan for 5 seconds
|
|
74
|
+
const result = await CatPrinter.scan({ duration: 5000 });
|
|
75
|
+
console.log('Found devices:', result.devices);
|
|
76
|
+
|
|
77
|
+
// Each device has: { name: string, address: string, rssi: number }
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Connect to a Printer
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
await CatPrinter.connect({
|
|
84
|
+
address: 'AA:BB:CC:DD:EE:FF', // Bluetooth MAC address
|
|
85
|
+
paperWidth: PaperWidth.MM_58 // 384px for 58mm, 576px for 80mm
|
|
86
|
+
});
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Check Connection Status
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
const status = await CatPrinter.isConnected();
|
|
93
|
+
if (status.connected) {
|
|
94
|
+
console.log('Connected to:', status.address);
|
|
95
|
+
console.log('Paper width:', status.paperWidth);
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Print Text
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
await CatPrinter.printText({
|
|
103
|
+
text: 'Hello World!\n\nThis is a test receipt.',
|
|
104
|
+
fontSize: 24, // Font size in pixels (default: 24)
|
|
105
|
+
align: 'center', // 'left', 'center', 'right' (default: 'left')
|
|
106
|
+
bold: false, // Bold text (default: false)
|
|
107
|
+
lineSpacing: 1.2, // Line spacing multiplier (default: 1.2)
|
|
108
|
+
energy: 0.6, // Print darkness 0.0-1.0 (default: 0.6)
|
|
109
|
+
quality: 3, // Print quality 1-4 (default: 3)
|
|
110
|
+
feedAfter: 100 // Paper feed after printing in pixels (default: 100)
|
|
111
|
+
});
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Print Image
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
// Image must be base64 encoded (PNG or JPEG)
|
|
118
|
+
await CatPrinter.printImage({
|
|
119
|
+
imageBase64: 'iVBORw0KGgoAAAANSUhEUgAA...', // Base64 image data (without data URL prefix)
|
|
120
|
+
energy: 0.65, // Print darkness 0.0-1.0 (default: 0.5)
|
|
121
|
+
quality: 4, // Print quality 1-4 (default: 3)
|
|
122
|
+
feedAfter: 100, // Paper feed after printing in pixels (default: 100)
|
|
123
|
+
threshold: 127, // Black/white threshold 0-255 (default: 127)
|
|
124
|
+
dither: true // Use Floyd-Steinberg dithering (default: true)
|
|
125
|
+
});
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Feed Paper
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
await CatPrinter.feedPaper({ pixels: 100 });
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Disconnect
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
await CatPrinter.disconnect();
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Event Listeners
|
|
141
|
+
|
|
142
|
+
### Scan Results (Real-time)
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const listener = await CatPrinter.addListener('scanResult', (device) => {
|
|
146
|
+
console.log('Found device:', device.name, device.address, device.rssi);
|
|
147
|
+
});
|
|
148
|
+
|
|
149
|
+
// Remove listener when done
|
|
150
|
+
listener.remove();
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Connection State Changes
|
|
154
|
+
|
|
155
|
+
```typescript
|
|
156
|
+
await CatPrinter.addListener('connectionState', (state) => {
|
|
157
|
+
if (state.connected) {
|
|
158
|
+
console.log('Connected to:', state.address);
|
|
159
|
+
} else {
|
|
160
|
+
console.log('Disconnected');
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Print Progress
|
|
166
|
+
|
|
167
|
+
```typescript
|
|
168
|
+
await CatPrinter.addListener('printProgress', (progress) => {
|
|
169
|
+
console.log(`${progress.percent}% - ${progress.status}: ${progress.message}`);
|
|
170
|
+
// status: 'processing' | 'printing' | 'feeding' | 'done' | 'error'
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Remove All Listeners
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
await CatPrinter.removeAllListeners();
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## API Reference
|
|
181
|
+
|
|
182
|
+
### Methods
|
|
183
|
+
|
|
184
|
+
| Method | Description |
|
|
185
|
+
|--------|-------------|
|
|
186
|
+
| `scan(options?)` | Scan for BLE devices |
|
|
187
|
+
| `stopScan()` | Stop ongoing scan |
|
|
188
|
+
| `connect(options)` | Connect to a printer |
|
|
189
|
+
| `disconnect()` | Disconnect from printer |
|
|
190
|
+
| `isConnected()` | Check connection status |
|
|
191
|
+
| `printText(options)` | Print text |
|
|
192
|
+
| `printImage(options)` | Print image |
|
|
193
|
+
| `feedPaper(options?)` | Feed paper |
|
|
194
|
+
|
|
195
|
+
### Interfaces
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface ScanOptions {
|
|
199
|
+
duration?: number; // Scan duration in ms (default: 4000)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface ConnectOptions {
|
|
203
|
+
address: string; // Bluetooth MAC address
|
|
204
|
+
paperWidth?: number; // Paper width in pixels (default: 384)
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface PrintTextOptions {
|
|
208
|
+
text: string;
|
|
209
|
+
fontSize?: number; // default: 24
|
|
210
|
+
align?: 'left' | 'center' | 'right'; // default: 'left'
|
|
211
|
+
bold?: boolean; // default: false
|
|
212
|
+
lineSpacing?: number; // default: 1.2
|
|
213
|
+
energy?: number; // 0.0-1.0, default: 0.6
|
|
214
|
+
quality?: number; // 1-4, default: 3
|
|
215
|
+
feedAfter?: number; // default: 100
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
interface PrintImageOptions {
|
|
219
|
+
imageBase64: string;
|
|
220
|
+
energy?: number; // 0.0-1.0, default: 0.5
|
|
221
|
+
quality?: number; // 1-4, default: 3
|
|
222
|
+
feedAfter?: number; // default: 100
|
|
223
|
+
threshold?: number; // 0-255, default: 127
|
|
224
|
+
dither?: boolean; // default: true
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
interface FeedOptions {
|
|
228
|
+
pixels?: number; // default: 100
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Constants
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
const PaperWidth = {
|
|
236
|
+
MM_58: 384, // 58mm paper width
|
|
237
|
+
MM_80: 576 // 80mm paper width
|
|
238
|
+
};
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Complete Example
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
import { CatPrinter, PaperWidth } from 'capacitor-cat-printer';
|
|
245
|
+
|
|
246
|
+
async function printReceipt() {
|
|
247
|
+
try {
|
|
248
|
+
// Setup listeners
|
|
249
|
+
CatPrinter.addListener('printProgress', (p) => {
|
|
250
|
+
console.log(`Printing: ${p.percent}%`);
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
// Scan for printers
|
|
254
|
+
const { devices } = await CatPrinter.scan({ duration: 5000 });
|
|
255
|
+
|
|
256
|
+
if (devices.length === 0) {
|
|
257
|
+
console.log('No printers found');
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// Connect to first printer
|
|
262
|
+
await CatPrinter.connect({
|
|
263
|
+
address: devices[0].address,
|
|
264
|
+
paperWidth: PaperWidth.MM_58
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Print receipt
|
|
268
|
+
await CatPrinter.printText({
|
|
269
|
+
text: `
|
|
270
|
+
RECEIPT
|
|
271
|
+
================
|
|
272
|
+
Item 1 $10.00
|
|
273
|
+
Item 2 $15.00
|
|
274
|
+
----------------
|
|
275
|
+
Total $25.00
|
|
276
|
+
================
|
|
277
|
+
Thank you!
|
|
278
|
+
`,
|
|
279
|
+
fontSize: 24,
|
|
280
|
+
align: 'left',
|
|
281
|
+
energy: 0.6,
|
|
282
|
+
quality: 3
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Disconnect
|
|
286
|
+
await CatPrinter.disconnect();
|
|
287
|
+
|
|
288
|
+
console.log('Print complete!');
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error('Print error:', error);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Supported Printers
|
|
296
|
+
|
|
297
|
+
This plugin works with Cat thermal printers and compatible devices that use the same BLE protocol:
|
|
298
|
+
- TX Characteristic: `0000ae01-0000-1000-8000-00805f9b34fb`
|
|
299
|
+
- RX Characteristic: `0000ae02-0000-1000-8000-00805f9b34fb`
|
|
300
|
+
|
|
301
|
+
Many generic thermal printers from AliExpress/Amazon use this protocol.
|
|
302
|
+
|
|
303
|
+
## Troubleshooting
|
|
304
|
+
|
|
305
|
+
### No devices found during scan
|
|
306
|
+
1. Ensure Bluetooth is enabled
|
|
307
|
+
2. Ensure Location Services are enabled (required for BLE scanning)
|
|
308
|
+
3. Grant both Bluetooth and Location permissions when prompted
|
|
309
|
+
4. Make sure the printer is powered on and in pairing mode
|
|
310
|
+
|
|
311
|
+
### Permission errors
|
|
312
|
+
- On Android 12+, the app needs "Nearby devices" permission
|
|
313
|
+
- On Android 6-11, the app needs Location permission for BLE scanning
|
|
314
|
+
- Check app permissions in Settings > Apps > Your App > Permissions
|
|
315
|
+
|
|
316
|
+
### Print quality issues
|
|
317
|
+
- Increase `energy` for darker prints (0.6-0.8 recommended)
|
|
318
|
+
- Use `quality: 4` for best quality (slower)
|
|
319
|
+
- Enable `dither: true` for images with gradients
|
|
320
|
+
- Adjust `threshold` for black/white conversion (lower = more black)
|
|
321
|
+
|
|
322
|
+
## License
|
|
323
|
+
|
|
324
|
+
MIT
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
ext {
|
|
2
|
+
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
|
3
|
+
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.6.1'
|
|
4
|
+
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.1.5'
|
|
5
|
+
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.5.1'
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
apply plugin: 'com.android.library'
|
|
9
|
+
|
|
10
|
+
android {
|
|
11
|
+
namespace "khare.catprinter.plugin"
|
|
12
|
+
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
|
13
|
+
defaultConfig {
|
|
14
|
+
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
|
15
|
+
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
|
16
|
+
versionCode 1
|
|
17
|
+
versionName "1.0"
|
|
18
|
+
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
19
|
+
}
|
|
20
|
+
buildTypes {
|
|
21
|
+
release {
|
|
22
|
+
minifyEnabled false
|
|
23
|
+
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
compileOptions {
|
|
27
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
28
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
repositories {
|
|
33
|
+
google()
|
|
34
|
+
mavenCentral()
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
dependencies {
|
|
38
|
+
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
|
39
|
+
implementation project(':capacitor-android')
|
|
40
|
+
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
|
41
|
+
testImplementation "junit:junit:$junitVersion"
|
|
42
|
+
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
|
43
|
+
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
|
44
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
3
|
+
|
|
4
|
+
<!-- Bluetooth permissions for Android 11 and below -->
|
|
5
|
+
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
|
|
6
|
+
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
|
|
7
|
+
|
|
8
|
+
<!-- Bluetooth permissions for Android 12+ -->
|
|
9
|
+
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
|
10
|
+
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
|
11
|
+
|
|
12
|
+
<!-- Location permission required for BLE scanning on Android 6-11 -->
|
|
13
|
+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
|
|
14
|
+
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
|
15
|
+
|
|
16
|
+
<!-- Declare BLE feature -->
|
|
17
|
+
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
|
|
18
|
+
<uses-feature android:name="android.hardware.location.gps" android:required="false"/>
|
|
19
|
+
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
|
|
20
|
+
|
|
21
|
+
</manifest>
|