@amitkhare/capacitor-cat-printer 0.5.0 → 0.5.2

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 CHANGED
@@ -1,323 +1,306 @@
1
- # Capacitor Cat Printer Plugin
1
+ # Capacitor Cat Printer
2
2
 
3
- A Capacitor plugin for printing to Cat thermal printers (and compatible devices) via Bluetooth Low Energy (BLE).
3
+ A Capacitor plugin for thermal printers (Cat printers and compatibles) over Bluetooth LE.
4
4
 
5
5
  ## Features
6
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
7
+ - BLE scanning and connection management
8
+ - Text printing with full styling (bold, italic, underline, strikethrough)
9
+ - Rich text with mixed formatting in a single print
10
+ - Image printing with dithering, brightness/contrast adjustments
11
+ - QR codes and barcodes (CODE128, EAN13, UPC, etc.)
12
+ - Table/receipt layout printing
13
+ - Custom font support (TTF/OTF)
14
+ - RTL text support
15
+ - Printer status (battery, paper, charging)
16
+ - Auto-reconnect
17
+ - Dry-run mode for testing
18
+ - 58mm and 80mm paper widths
19
+
20
+ ## Install
16
21
 
17
22
  ```bash
18
23
  npm install capacitor-cat-printer
19
24
  npx cap sync android
20
25
  ```
21
26
 
22
- For local development:
23
- ```bash
24
- npm install file:../path/to/capacitor-cat-printer
25
- npx cap sync android
26
- ```
27
+ ## Android Permissions
27
28
 
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`:
29
+ Add to `AndroidManifest.xml` before `<application>`:
33
30
 
34
31
  ```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">
32
+ <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
33
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
34
+ <uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
35
+ <uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
36
+ <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
37
+ <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
38
+ <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
39
+ ```
38
40
 
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" />
41
+ ## Quick Start
42
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" />
43
+ ```typescript
44
+ import { CatPrinter } from 'capacitor-cat-printer';
46
45
 
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" />
46
+ // Scan
47
+ const { devices } = await CatPrinter.scan({ duration: 5000 });
50
48
 
51
- <!-- Declare BLE feature -->
52
- <uses-feature android:name="android.hardware.bluetooth_le" android:required="true" />
49
+ // Connect
50
+ await CatPrinter.connect({ address: devices[0].address });
53
51
 
54
- <application>
55
- <!-- ... -->
56
- </application>
57
- </manifest>
58
- ```
52
+ // Print
53
+ await CatPrinter.printText({ text: 'Hello World!' });
59
54
 
60
- **Important:** The `tools:remove="android:maxSdkVersion"` attribute is required to ensure location permissions work on Android 12+.
55
+ // Disconnect
56
+ await CatPrinter.disconnect();
57
+ ```
61
58
 
62
- ## Usage
59
+ ## API
63
60
 
64
- ### Import
61
+ ### Connection
65
62
 
66
63
  ```typescript
67
- import { CatPrinter, PaperWidth } from 'capacitor-cat-printer';
68
- ```
64
+ // Scan for printers
65
+ const { devices } = await CatPrinter.scan({ duration: 5000 });
66
+ // devices: [{ name, address, rssi }]
69
67
 
70
- ### Scan for Printers
68
+ // Stop scan early
69
+ await CatPrinter.stopScan();
71
70
 
72
- ```typescript
73
- // Scan for 5 seconds
74
- const result = await CatPrinter.scan({ duration: 5000 });
75
- console.log('Found devices:', result.devices);
71
+ // Connect
72
+ await CatPrinter.connect({
73
+ address: 'AA:BB:CC:DD:EE:FF',
74
+ paperWidth: 384, // 384 = 58mm, 576 = 80mm
75
+ timeout: 10000,
76
+ dryRun: false, // true = simulate without printing
77
+ autoReconnect: false
78
+ });
79
+
80
+ // Check status
81
+ const { connected, address, paperWidth } = await CatPrinter.isConnected();
76
82
 
77
- // Each device has: { name: string, address: string, rssi: number }
83
+ // Disconnect
84
+ await CatPrinter.disconnect();
78
85
  ```
79
86
 
80
- ### Connect to a Printer
87
+ ### Print Text
81
88
 
82
89
  ```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
90
+ await CatPrinter.printText({
91
+ text: 'Hello World!',
92
+ fontSize: 24,
93
+ align: 'center', // 'left' | 'center' | 'right'
94
+ bold: true,
95
+ italic: false,
96
+ underline: false,
97
+ strikethrough: false,
98
+ lineSpacing: 1.2,
99
+ wordWrap: true, // break at word boundaries
100
+ rtl: false, // right-to-left
101
+ fontPath: '/path/to/font.ttf', // custom font
102
+ energy: 0.6, // 0.0-1.0 darkness
103
+ quality: 3, // 1-4
104
+ feedAfter: 100
86
105
  });
87
106
  ```
88
107
 
89
- ### Check Connection Status
108
+ ### Rich Text (Mixed Formatting)
90
109
 
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
110
+ Print text with different styles in the same line:
100
111
 
101
112
  ```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)
113
+ await CatPrinter.printRichText({
114
+ segments: [
115
+ { text: 'Normal ' },
116
+ { text: 'Bold', bold: true },
117
+ { text: ' and ' },
118
+ { text: 'Italic', italic: true },
119
+ { text: ' Big', fontSize: 32 } // per-segment font size
120
+ ],
121
+ fontSize: 24,
122
+ align: 'left',
123
+ lineSpacing: 1.2,
124
+ rtl: false,
125
+ fontPath: '/path/to/font.ttf',
126
+ energy: 0.6,
127
+ quality: 3,
128
+ feedAfter: 100
111
129
  });
112
130
  ```
113
131
 
114
132
  ### Print Image
115
133
 
116
134
  ```typescript
117
- // Image must be base64 encoded (PNG or JPEG)
118
135
  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)
136
+ imageBase64: '...', // base64 PNG/JPEG (no data: prefix)
137
+ threshold: 127, // 0-255 for B/W conversion
138
+ dither: true, // Floyd-Steinberg dithering
139
+ brightness: 0, // -100 to 100
140
+ contrast: 0, // -100 to 100
141
+ invert: false,
142
+ flipHorizontal: false,
143
+ flipVertical: false,
144
+ compress: false, // for newer printers (GB03+)
145
+ energy: 0.6,
146
+ quality: 3,
147
+ feedAfter: 100
125
148
  });
126
149
  ```
127
150
 
128
- ### Feed Paper
151
+ ### QR Code
129
152
 
130
153
  ```typescript
131
- await CatPrinter.feedPaper({ pixels: 100 });
154
+ await CatPrinter.printQRCode({
155
+ data: 'https://example.com',
156
+ size: 200,
157
+ errorCorrection: 'M', // 'L' | 'M' | 'Q' | 'H'
158
+ align: 'center',
159
+ energy: 0.6,
160
+ feedAfter: 100
161
+ });
132
162
  ```
133
163
 
134
- ### Disconnect
164
+ ### Barcode
135
165
 
136
166
  ```typescript
137
- await CatPrinter.disconnect();
167
+ await CatPrinter.printBarcode({
168
+ data: '123456789',
169
+ type: 'CODE128', // CODE128, CODE39, EAN13, EAN8, UPC_A, UPC_E, ITF, CODABAR
170
+ height: 80,
171
+ showText: true,
172
+ align: 'center',
173
+ energy: 0.6,
174
+ feedAfter: 100
175
+ });
138
176
  ```
139
177
 
140
- ## Event Listeners
141
-
142
- ### Scan Results (Real-time)
178
+ ### Table / Receipt
143
179
 
144
180
  ```typescript
145
- const listener = await CatPrinter.addListener('scanResult', (device) => {
146
- console.log('Found device:', device.name, device.address, device.rssi);
181
+ await CatPrinter.printTable({
182
+ rows: [
183
+ { columns: [{ text: 'RECEIPT', align: 'center' }], bold: true, fontSize: 28 },
184
+ { columns: [{ text: '─'.repeat(16), align: 'center' }] },
185
+ {
186
+ columns: [
187
+ { text: 'Item', width: 60 }, // width as percentage
188
+ { text: 'Price', width: 40, align: 'right' }
189
+ ],
190
+ bold: true
191
+ },
192
+ { columns: [{ text: 'Coffee' }, { text: '$4.00', align: 'right' }] },
193
+ { columns: [{ text: 'Muffin' }, { text: '$3.50', align: 'right' }] },
194
+ { columns: [{ text: '─'.repeat(16), align: 'center' }] },
195
+ { columns: [{ text: 'Total' }, { text: '$7.50', align: 'right' }], bold: true }
196
+ ],
197
+ fontSize: 22,
198
+ showLines: false, // horizontal lines between rows
199
+ lineChar: '-', // character for lines
200
+ energy: 0.6,
201
+ feedAfter: 100
147
202
  });
148
-
149
- // Remove listener when done
150
- listener.remove();
151
203
  ```
152
204
 
153
- ### Connection State Changes
205
+ ### Paper Control
154
206
 
155
207
  ```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
- });
208
+ await CatPrinter.feedPaper({ pixels: 100 });
209
+ await CatPrinter.retractPaper({ pixels: 50 });
210
+ await CatPrinter.cancelPrint();
163
211
  ```
164
212
 
165
- ### Print Progress
213
+ ### Auto-Reconnect
166
214
 
167
215
  ```typescript
168
- await CatPrinter.addListener('printProgress', (progress) => {
169
- console.log(`${progress.percent}% - ${progress.status}: ${progress.message}`);
170
- // status: 'processing' | 'printing' | 'feeding' | 'done' | 'error'
216
+ await CatPrinter.setAutoReconnect({
217
+ enabled: true,
218
+ maxAttempts: 3,
219
+ delayMs: 2000
171
220
  });
172
221
  ```
173
222
 
174
- ### Remove All Listeners
223
+ ### Printer Info
175
224
 
176
225
  ```typescript
177
- await CatPrinter.removeAllListeners();
178
- ```
226
+ // Get printer model
227
+ const model = await CatPrinter.getPrinterModel();
228
+ // { model: 'GB03', isNewKind: true, hasFeedingProblems: false, paperWidth: 384, deviceName: '...' }
179
229
 
180
- ## API Reference
230
+ // Get printer status
231
+ const status = await CatPrinter.getPrinterStatus();
232
+ // { connected, batteryLevel, isCharging, hasPaper, firmwareVersion, paperWidth }
181
233
 
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 |
234
+ // Get raw device info
235
+ const info = await CatPrinter.getDeviceInfo();
236
+ ```
194
237
 
195
- ### Interfaces
238
+ ### Preview (Without Printing)
196
239
 
197
240
  ```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
- }
241
+ const preview = await CatPrinter.getPreview({
242
+ type: 'text',
243
+ options: { text: 'Preview this', fontSize: 24 }
244
+ });
245
+ // { imageBase64, width, height }
230
246
  ```
231
247
 
232
- ### Constants
248
+ ### Events
233
249
 
234
250
  ```typescript
235
- const PaperWidth = {
236
- MM_58: 384, // 58mm paper width
237
- MM_80: 576 // 80mm paper width
238
- };
251
+ // Device found during scan
252
+ CatPrinter.addListener('scanResult', (device) => {
253
+ console.log('Found:', device.name, device.address);
254
+ });
255
+
256
+ // Connection state changed
257
+ CatPrinter.addListener('connectionState', (state) => {
258
+ console.log('Connected:', state.connected);
259
+ });
260
+
261
+ // Print progress
262
+ CatPrinter.addListener('printProgress', (progress) => {
263
+ console.log(`${progress.percent}% - ${progress.status}`);
264
+ // status: 'processing' | 'printing' | 'feeding' | 'done' | 'error'
265
+ });
266
+
267
+ // Remove all listeners
268
+ await CatPrinter.removeAllListeners();
239
269
  ```
240
270
 
241
- ## Complete Example
271
+ ## Constants
242
272
 
243
273
  ```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
- ```
274
+ import { PaperWidth, BarcodeType, PrinterModels } from 'capacitor-cat-printer';
294
275
 
295
- ## Supported Printers
276
+ PaperWidth.MM_58 // 384
277
+ PaperWidth.MM_80 // 576
278
+
279
+ BarcodeType.CODE128
280
+ BarcodeType.EAN13
281
+ // etc.
296
282
 
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`
283
+ PrinterModels.GB01
284
+ PrinterModels.GB03
285
+ PrinterModels.MX05
286
+ // etc.
287
+ ```
300
288
 
301
- Many generic thermal printers from AliExpress/Amazon use this protocol.
289
+ ## Supported Printers
302
290
 
303
- ## Troubleshooting
291
+ Works with Cat thermal printers and compatibles using BLE characteristics:
292
+ - TX: `0000ae01-0000-1000-8000-00805f9b34fb`
293
+ - RX: `0000ae02-0000-1000-8000-00805f9b34fb`
304
294
 
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
295
+ Known models: GB01, GB02, GB03, GT01, MX05, MX06, MX08, MX09, MX10, MX11, YT01
310
296
 
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
297
+ ## Tips
315
298
 
316
- ### Print quality issues
317
- - Increase `energy` for darker prints (0.6-0.8 recommended)
318
- - Use `quality: 4` for best quality (slower)
299
+ - Enable Location Services for BLE scanning on Android
300
+ - Use `energy: 0.6-0.8` for darker prints
319
301
  - Enable `dither: true` for images with gradients
320
- - Adjust `threshold` for black/white conversion (lower = more black)
302
+ - Use `quality: 4` for best quality (slower)
303
+ - Lower `threshold` = more black pixels in images
321
304
 
322
305
  ## License
323
306
 
@@ -38,6 +38,10 @@ dependencies {
38
38
  implementation fileTree(dir: 'libs', include: ['*.jar'])
39
39
  implementation project(':capacitor-android')
40
40
  implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
41
+
42
+ // ZXing for barcode/QR code generation
43
+ implementation 'com.google.zxing:core:3.5.2'
44
+
41
45
  testImplementation "junit:junit:$junitVersion"
42
46
  androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
43
47
  androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"