@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 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>