@sincpro/printer-expo 0.1.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 +917 -0
- package/android/build.gradle +52 -0
- package/android/libs/BixolonLabelPrinterLibrary_V2.0.9.jar +0 -0
- package/android/libs/jniLibs/arm64-v8a/libbxl_common.so +0 -0
- package/android/libs/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
- package/android/libs/jniLibs/x86/libbxl_common.so +0 -0
- package/android/libs/jniLibs/x86_64/libbxl_common.so +0 -0
- package/android/libs/libcommon_V1.4.0.jar +0 -0
- package/android/libs/pdf/Bixolon_pdf.aar +0 -0
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/expo/sincpro/ExpoBixolonModule.kt +271 -0
- package/android/src/main/java/expo/sincpro/bixolon/BixolonQRPrinter.kt +423 -0
- package/android/src/main/java/expo/sincpro/managers/BluetoothManager.kt +139 -0
- package/android/src/main/java/expo/sincpro/managers/ConnectionManager.kt +124 -0
- package/android/src/main/java/expo/sincpro/managers/PermissionManager.kt +122 -0
- package/android/src/main/java/expo/sincpro/managers/PrinterManager.kt +396 -0
- package/android/src/main/jniLibs/arm64-v8a/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/armeabi-v7a/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/x86/libbxl_common.so +0 -0
- package/android/src/main/jniLibs/x86_64/libbxl_common.so +0 -0
- package/build/BixolonPrinter.d.ts +4 -0
- package/build/BixolonPrinter.d.ts.map +1 -0
- package/build/BixolonPrinter.js +12 -0
- package/build/BixolonPrinter.js.map +1 -0
- package/build/ExpoBixolon.types.d.ts +45 -0
- package/build/ExpoBixolon.types.d.ts.map +1 -0
- package/build/ExpoBixolon.types.js +2 -0
- package/build/ExpoBixolon.types.js.map +1 -0
- package/build/ExpoBixolonModule.d.ts +24 -0
- package/build/ExpoBixolonModule.d.ts.map +1 -0
- package/build/ExpoBixolonModule.js +3 -0
- package/build/ExpoBixolonModule.js.map +1 -0
- package/build/QrCodePrinter.d.ts +45 -0
- package/build/QrCodePrinter.d.ts.map +1 -0
- package/build/QrCodePrinter.js +118 -0
- package/build/QrCodePrinter.js.map +1 -0
- package/build/index.d.ts +4 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/expo-module.config.json +9 -0
- package/ios/ExpoBixolon.podspec +29 -0
- package/ios/ExpoBixolonModule.swift +33 -0
- package/ios/ExpoBixolonView.swift +36 -0
- package/package.json +63 -0
- package/src/BixolonPrinter.ts +16 -0
- package/src/ExpoBixolon.types.ts +60 -0
- package/src/ExpoBixolonModule.ts +38 -0
- package/src/QrCodePrinter.ts +201 -0
- package/src/index.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,917 @@
|
|
|
1
|
+
# Expo Bixolon Module
|
|
2
|
+
|
|
3
|
+
[](https://badge.fury.io/js/expo-bixolon)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://expo.dev)
|
|
6
|
+
|
|
7
|
+
A powerful React Native module for controlling Bixolon thermal printers in Expo applications. This module provides comprehensive Bluetooth connectivity, advanced printing functionality, and seamless integration with Bixolon's official SDK.
|
|
8
|
+
|
|
9
|
+
## ✨ Features
|
|
10
|
+
|
|
11
|
+
- 🔗 **Bluetooth Connectivity**: Full Bluetooth device discovery and connection management
|
|
12
|
+
- 📱 **Permission Management**: Automatic handling of Bluetooth and location permissions
|
|
13
|
+
- 🖨️ **Advanced Printing**: Text, invoices, and formatted document printing
|
|
14
|
+
- 📋 **QR Code Printing**: Multiple QR code formats (URL, Contact, WiFi, Payment)
|
|
15
|
+
- 🔌 **Multiple Interfaces**: Support for Bluetooth, WiFi, and USB connections
|
|
16
|
+
- 📚 **Official SDK**: Integration with BixolonLabelPrinter library
|
|
17
|
+
- 📝 **TypeScript**: Complete TypeScript definitions and type safety
|
|
18
|
+
- 🔄 **Event-Driven**: Real-time events for device discovery and connection status
|
|
19
|
+
- 🛠️ **Easy Setup**: Simple installation and configuration
|
|
20
|
+
- 📱 **Cross-Platform**: Works on both Android and iOS (Android focus)
|
|
21
|
+
|
|
22
|
+
## 📦 Installation
|
|
23
|
+
|
|
24
|
+
### Method 1: Install from NPM (when published)
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install expo-bixolon
|
|
28
|
+
# or
|
|
29
|
+
yarn add expo-bixolon
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Method 2: Install from Local Tarball
|
|
33
|
+
|
|
34
|
+
If you have the module locally or want to use a specific version:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# First, create a tarball from the module directory
|
|
38
|
+
cd /path/to/expo-bixolon
|
|
39
|
+
npm pack
|
|
40
|
+
|
|
41
|
+
# Then install in your app
|
|
42
|
+
cd /path/to/your-app
|
|
43
|
+
npm install /path/to/expo-bixolon-0.1.0.tgz
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Method 3: Install as Local Development Dependency
|
|
47
|
+
|
|
48
|
+
For development or testing purposes:
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
# In your app directory
|
|
52
|
+
npm install /absolute/path/to/expo-bixolon
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Post-Installation Setup
|
|
56
|
+
|
|
57
|
+
After installation, run these commands in your app directory:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
# Install native dependencies
|
|
61
|
+
npx expo install
|
|
62
|
+
|
|
63
|
+
# Generate native code
|
|
64
|
+
npx expo prebuild
|
|
65
|
+
|
|
66
|
+
# For development builds
|
|
67
|
+
npx expo run:android
|
|
68
|
+
# or
|
|
69
|
+
npx expo run:ios
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## ⚙️ Configuration
|
|
73
|
+
|
|
74
|
+
### 1. Add Plugin to app.json
|
|
75
|
+
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"expo": {
|
|
79
|
+
"plugins": [
|
|
80
|
+
[
|
|
81
|
+
"expo-bixolon",
|
|
82
|
+
{
|
|
83
|
+
"bluetoothPermissions": [
|
|
84
|
+
"android.permission.BLUETOOTH",
|
|
85
|
+
"android.permission.BLUETOOTH_ADMIN",
|
|
86
|
+
"android.permission.BLUETOOTH_SCAN",
|
|
87
|
+
"android.permission.BLUETOOTH_CONNECT",
|
|
88
|
+
"android.permission.ACCESS_FINE_LOCATION",
|
|
89
|
+
"android.permission.ACCESS_COARSE_LOCATION"
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### 2. Android Permissions (app.json)
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"expo": {
|
|
103
|
+
"android": {
|
|
104
|
+
"permissions": [
|
|
105
|
+
"android.permission.BLUETOOTH",
|
|
106
|
+
"android.permission.BLUETOOTH_ADMIN",
|
|
107
|
+
"android.permission.BLUETOOTH_SCAN",
|
|
108
|
+
"android.permission.BLUETOOTH_CONNECT",
|
|
109
|
+
"android.permission.ACCESS_FINE_LOCATION",
|
|
110
|
+
"android.permission.ACCESS_COARSE_LOCATION"
|
|
111
|
+
]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## 🚀 Quick Start
|
|
118
|
+
|
|
119
|
+
### Basic Setup
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import BixolonPrinter, { BluetoothDevice } from 'expo-bixolon';
|
|
123
|
+
|
|
124
|
+
// Initialize the printer
|
|
125
|
+
const initializePrinter = async () => {
|
|
126
|
+
try {
|
|
127
|
+
const success = await BixolonPrinter.initializePrinter();
|
|
128
|
+
if (success) {
|
|
129
|
+
console.log('✅ Printer initialized successfully');
|
|
130
|
+
}
|
|
131
|
+
} catch (error) {
|
|
132
|
+
console.error('❌ Error initializing printer:', error);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Complete Example
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
import React, { useState, useEffect } from 'react';
|
|
141
|
+
import { View, Button, Alert } from 'react-native';
|
|
142
|
+
import BixolonPrinter, { BluetoothDevice } from 'expo-bixolon';
|
|
143
|
+
|
|
144
|
+
export default function PrinterApp() {
|
|
145
|
+
const [devices, setDevices] = useState<BluetoothDevice[]>([]);
|
|
146
|
+
const [isConnected, setIsConnected] = useState(false);
|
|
147
|
+
|
|
148
|
+
useEffect(() => {
|
|
149
|
+
initializePrinter();
|
|
150
|
+
checkPermissions();
|
|
151
|
+
}, []);
|
|
152
|
+
|
|
153
|
+
const initializePrinter = async () => {
|
|
154
|
+
try {
|
|
155
|
+
await BixolonPrinter.initializePrinter();
|
|
156
|
+
console.log('Printer initialized');
|
|
157
|
+
} catch (error) {
|
|
158
|
+
console.error('Initialization failed:', error);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
const checkPermissions = async () => {
|
|
163
|
+
const permissions = await BixolonPrinter.checkBluetoothPermissions();
|
|
164
|
+
console.log('Permissions:', permissions);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const discoverDevices = async () => {
|
|
168
|
+
try {
|
|
169
|
+
const foundDevices = await BixolonPrinter.discoverBluetoothDevices();
|
|
170
|
+
setDevices(foundDevices);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
Alert.alert('Error', 'Failed to discover devices');
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
const connectToDevice = async (device: BluetoothDevice) => {
|
|
177
|
+
try {
|
|
178
|
+
const success = await BixolonPrinter.connectPrinter('BLUETOOTH', device.address, 1);
|
|
179
|
+
if (success) {
|
|
180
|
+
setIsConnected(true);
|
|
181
|
+
Alert.alert('Success', 'Connected to printer');
|
|
182
|
+
}
|
|
183
|
+
} catch (error) {
|
|
184
|
+
Alert.alert('Error', 'Connection failed');
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
|
|
188
|
+
const printTest = async () => {
|
|
189
|
+
try {
|
|
190
|
+
const success = await BixolonPrinter.testPlainText('Hello from Expo!');
|
|
191
|
+
if (success) {
|
|
192
|
+
Alert.alert('Success', 'Text printed successfully');
|
|
193
|
+
}
|
|
194
|
+
} catch (error) {
|
|
195
|
+
Alert.alert('Error', 'Print failed');
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
return (
|
|
200
|
+
<View style={{ padding: 20 }}>
|
|
201
|
+
<Button title="Discover Devices" onPress={discoverDevices} />
|
|
202
|
+
<Button title="Print Test" onPress={printTest} disabled={!isConnected} />
|
|
203
|
+
{/* Render device list */}
|
|
204
|
+
</View>
|
|
205
|
+
);
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## 📱 Detailed Usage
|
|
210
|
+
|
|
211
|
+
### Bluetooth Device Discovery
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
// Check Bluetooth permissions
|
|
215
|
+
const checkPermissions = async () => {
|
|
216
|
+
const permissions = await BixolonPrinter.checkBluetoothPermissions();
|
|
217
|
+
console.log('Permissions:', permissions);
|
|
218
|
+
|
|
219
|
+
// Check if all required permissions are granted
|
|
220
|
+
const allGranted = Object.values(permissions).every((granted) => granted);
|
|
221
|
+
if (!allGranted) {
|
|
222
|
+
await requestPermissions();
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
// Request permissions if needed
|
|
227
|
+
const requestPermissions = async () => {
|
|
228
|
+
try {
|
|
229
|
+
const granted = await BixolonPrinter.requestBluetoothPermissions();
|
|
230
|
+
if (granted) {
|
|
231
|
+
console.log('✅ All permissions granted');
|
|
232
|
+
} else {
|
|
233
|
+
console.log('❌ Some permissions were denied');
|
|
234
|
+
}
|
|
235
|
+
} catch (error) {
|
|
236
|
+
console.error('Permission request failed:', error);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
// Discover Bluetooth devices
|
|
241
|
+
const discoverDevices = async () => {
|
|
242
|
+
try {
|
|
243
|
+
// Check if Bluetooth is enabled
|
|
244
|
+
const isEnabled = await BixolonPrinter.isBluetoothEnabled();
|
|
245
|
+
if (!isEnabled) {
|
|
246
|
+
Alert.alert('Error', 'Please enable Bluetooth first');
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Start discovery
|
|
251
|
+
await BixolonPrinter.startBluetoothDiscovery();
|
|
252
|
+
|
|
253
|
+
// Get paired devices
|
|
254
|
+
const devices = await BixolonPrinter.discoverBluetoothDevices();
|
|
255
|
+
console.log('Found devices:', devices);
|
|
256
|
+
|
|
257
|
+
// Filter for printer devices
|
|
258
|
+
const printers = devices.filter((device) => device.isPrinter);
|
|
259
|
+
console.log('Printer devices:', printers);
|
|
260
|
+
} catch (error) {
|
|
261
|
+
console.error('Device discovery failed:', error);
|
|
262
|
+
} finally {
|
|
263
|
+
// Stop discovery
|
|
264
|
+
await BixolonPrinter.stopBluetoothDiscovery();
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Connecting to a Printer
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
// Connect to a Bluetooth device
|
|
273
|
+
const connectToDevice = async (device: BluetoothDevice) => {
|
|
274
|
+
try {
|
|
275
|
+
console.log(`Connecting to ${device.name} (${device.address})...`);
|
|
276
|
+
|
|
277
|
+
const success = await BixolonPrinter.connectPrinter(
|
|
278
|
+
'BLUETOOTH', // Interface type
|
|
279
|
+
device.address, // Device MAC address
|
|
280
|
+
1 // Port (usually 1 for Bluetooth)
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
if (success) {
|
|
284
|
+
console.log('✅ Connected to printer successfully');
|
|
285
|
+
setIsConnected(true);
|
|
286
|
+
} else {
|
|
287
|
+
console.log('❌ Connection failed');
|
|
288
|
+
}
|
|
289
|
+
} catch (error) {
|
|
290
|
+
console.error('Connection error:', error);
|
|
291
|
+
Alert.alert('Connection Failed', error.message);
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
// Connect via WiFi (if supported)
|
|
296
|
+
const connectViaWiFi = async (ipAddress: string, port: number = 9100) => {
|
|
297
|
+
try {
|
|
298
|
+
const success = await BixolonPrinter.connectPrinter('WIFI', ipAddress, port);
|
|
299
|
+
|
|
300
|
+
if (success) {
|
|
301
|
+
console.log('✅ Connected via WiFi');
|
|
302
|
+
}
|
|
303
|
+
} catch (error) {
|
|
304
|
+
console.error('WiFi connection failed:', error);
|
|
305
|
+
}
|
|
306
|
+
};
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Advanced Printing
|
|
310
|
+
|
|
311
|
+
```typescript
|
|
312
|
+
// Print formatted text with custom formatting
|
|
313
|
+
const printFormattedText = async () => {
|
|
314
|
+
try {
|
|
315
|
+
const text = `COMPANY NAME
|
|
316
|
+
123 Main Street
|
|
317
|
+
City, State 12345
|
|
318
|
+
|
|
319
|
+
Invoice #: INV-001
|
|
320
|
+
Date: ${new Date().toLocaleDateString()}
|
|
321
|
+
Customer: John Doe
|
|
322
|
+
|
|
323
|
+
Items:
|
|
324
|
+
- Product A $10.00
|
|
325
|
+
- Product B $15.00
|
|
326
|
+
- Product C $25.00
|
|
327
|
+
|
|
328
|
+
Total: $50.00
|
|
329
|
+
|
|
330
|
+
Thank you for your business!`;
|
|
331
|
+
|
|
332
|
+
const success = await BixolonPrinter.printFormattedText(text, 10);
|
|
333
|
+
if (success) {
|
|
334
|
+
console.log('✅ Formatted text printed');
|
|
335
|
+
}
|
|
336
|
+
} catch (error) {
|
|
337
|
+
console.error('Print error:', error);
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Print text in pages (for long content)
|
|
342
|
+
const printLongText = async () => {
|
|
343
|
+
try {
|
|
344
|
+
const longText = `This is a very long text that will be split into multiple pages for better printing on thermal printers...`;
|
|
345
|
+
|
|
346
|
+
const success = await BixolonPrinter.printTextInPages(longText);
|
|
347
|
+
if (success) {
|
|
348
|
+
console.log('✅ Long text printed in pages');
|
|
349
|
+
}
|
|
350
|
+
} catch (error) {
|
|
351
|
+
console.error('Page printing error:', error);
|
|
352
|
+
}
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Print a complete invoice
|
|
356
|
+
const printInvoice = async () => {
|
|
357
|
+
try {
|
|
358
|
+
const items = [
|
|
359
|
+
{ description: 'Premium Coffee', quantity: 2, price: 4.5 },
|
|
360
|
+
{ description: 'Chocolate Croissant', quantity: 1, price: 3.25 },
|
|
361
|
+
{ description: 'Fresh Orange Juice', quantity: 1, price: 2.75 },
|
|
362
|
+
];
|
|
363
|
+
|
|
364
|
+
const success = await BixolonPrinter.printInvoice(
|
|
365
|
+
'Jane Smith', // Customer name
|
|
366
|
+
items, // Items array
|
|
367
|
+
15.0 // Total amount
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
if (success) {
|
|
371
|
+
console.log('✅ Invoice printed successfully');
|
|
372
|
+
}
|
|
373
|
+
} catch (error) {
|
|
374
|
+
console.error('Invoice printing error:', error);
|
|
375
|
+
}
|
|
376
|
+
};
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### Disconnecting and Cleanup
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
// Disconnect from printer
|
|
383
|
+
const disconnect = async () => {
|
|
384
|
+
try {
|
|
385
|
+
const success = await BixolonPrinter.disconnectPrinter();
|
|
386
|
+
if (success) {
|
|
387
|
+
console.log('✅ Disconnected from printer');
|
|
388
|
+
setIsConnected(false);
|
|
389
|
+
}
|
|
390
|
+
} catch (error) {
|
|
391
|
+
console.error('Disconnection error:', error);
|
|
392
|
+
}
|
|
393
|
+
};
|
|
394
|
+
|
|
395
|
+
// Cleanup on component unmount
|
|
396
|
+
useEffect(() => {
|
|
397
|
+
return () => {
|
|
398
|
+
if (isConnected) {
|
|
399
|
+
disconnect();
|
|
400
|
+
}
|
|
401
|
+
};
|
|
402
|
+
}, [isConnected]);
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
## 📋 Local Installation Guide
|
|
406
|
+
|
|
407
|
+
### Creating a Local Package
|
|
408
|
+
|
|
409
|
+
If you want to distribute the module locally without publishing to NPM:
|
|
410
|
+
|
|
411
|
+
```bash
|
|
412
|
+
# 1. Build the module
|
|
413
|
+
cd /path/to/expo-bixolon
|
|
414
|
+
npm run build
|
|
415
|
+
|
|
416
|
+
# 2. Create a tarball
|
|
417
|
+
npm pack
|
|
418
|
+
|
|
419
|
+
# This creates: expo-bixolon-0.1.0.tgz
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
### Installing in Another Project
|
|
423
|
+
|
|
424
|
+
```bash
|
|
425
|
+
# Method 1: Direct tarball installation
|
|
426
|
+
cd /path/to/your-app
|
|
427
|
+
npm install /path/to/expo-bixolon-0.1.0.tgz
|
|
428
|
+
|
|
429
|
+
# Method 2: Using file path
|
|
430
|
+
npm install /absolute/path/to/expo-bixolon
|
|
431
|
+
|
|
432
|
+
# Method 3: Using yarn
|
|
433
|
+
yarn add /path/to/expo-bixolon-0.1.0.tgz
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
### Post-Installation Steps
|
|
437
|
+
|
|
438
|
+
```bash
|
|
439
|
+
# Install native dependencies
|
|
440
|
+
npx expo install
|
|
441
|
+
|
|
442
|
+
# Generate native code
|
|
443
|
+
npx expo prebuild
|
|
444
|
+
|
|
445
|
+
# Run the app
|
|
446
|
+
npx expo run:android
|
|
447
|
+
# or
|
|
448
|
+
npx expo run:ios
|
|
449
|
+
```
|
|
450
|
+
|
|
451
|
+
## 📚 API Reference
|
|
452
|
+
|
|
453
|
+
### Core Methods
|
|
454
|
+
|
|
455
|
+
#### `initializePrinter(): Promise<boolean>`
|
|
456
|
+
|
|
457
|
+
Initializes the printer module. Must be called before any other operations.
|
|
458
|
+
|
|
459
|
+
**Returns:** `Promise<boolean>` - `true` if initialization successful
|
|
460
|
+
|
|
461
|
+
**Example:**
|
|
462
|
+
|
|
463
|
+
```typescript
|
|
464
|
+
const success = await BixolonPrinter.initializePrinter();
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
#### `connectPrinter(interfaceType: string, address: string, port: number): Promise<boolean>`
|
|
468
|
+
|
|
469
|
+
Connects to a printer using the specified interface type, address, and port.
|
|
470
|
+
|
|
471
|
+
**Parameters:**
|
|
472
|
+
|
|
473
|
+
- `interfaceType`: `'BLUETOOTH' | 'WIFI' | 'USB'`
|
|
474
|
+
- `address`: Device MAC address (Bluetooth) or IP address (WiFi)
|
|
475
|
+
- `port`: Port number (usually 1 for Bluetooth, 9100 for WiFi)
|
|
476
|
+
|
|
477
|
+
**Returns:** `Promise<boolean>` - `true` if connection successful
|
|
478
|
+
|
|
479
|
+
**Example:**
|
|
480
|
+
|
|
481
|
+
```typescript
|
|
482
|
+
const success = await BixolonPrinter.connectPrinter('BLUETOOTH', '00:11:22:33:44:55', 1);
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### `disconnectPrinter(): Promise<boolean>`
|
|
486
|
+
|
|
487
|
+
Disconnects from the currently connected printer.
|
|
488
|
+
|
|
489
|
+
**Returns:** `Promise<boolean>` - `true` if disconnection successful
|
|
490
|
+
|
|
491
|
+
#### `executeCommand(command: string): Promise<boolean>`
|
|
492
|
+
|
|
493
|
+
Executes a raw command on the printer.
|
|
494
|
+
|
|
495
|
+
**Parameters:**
|
|
496
|
+
|
|
497
|
+
- `command`: Raw command string to send to printer
|
|
498
|
+
|
|
499
|
+
### Printing Methods
|
|
500
|
+
|
|
501
|
+
#### `testPlainText(text: string): Promise<boolean>`
|
|
502
|
+
|
|
503
|
+
Prints plain text to the connected printer.
|
|
504
|
+
|
|
505
|
+
**Parameters:**
|
|
506
|
+
|
|
507
|
+
- `text`: Text content to print
|
|
508
|
+
|
|
509
|
+
#### `printFormattedText(text: string, fontSize?: number): Promise<boolean>`
|
|
510
|
+
|
|
511
|
+
Prints formatted text with optional font size.
|
|
512
|
+
|
|
513
|
+
**Parameters:**
|
|
514
|
+
|
|
515
|
+
- `text`: Formatted text content
|
|
516
|
+
- `fontSize`: Optional font size (default: 10)
|
|
517
|
+
|
|
518
|
+
#### `printTextSimple(text: string): Promise<boolean>`
|
|
519
|
+
|
|
520
|
+
Prints text using simple formatting (line-by-line).
|
|
521
|
+
|
|
522
|
+
#### `printTextInPages(text: string): Promise<boolean>`
|
|
523
|
+
|
|
524
|
+
Prints long text split into multiple pages.
|
|
525
|
+
|
|
526
|
+
#### `printInvoice(invoiceText: string): Promise<boolean>`
|
|
527
|
+
|
|
528
|
+
Prints a complete invoice from formatted text.
|
|
529
|
+
|
|
530
|
+
**Parameters:**
|
|
531
|
+
|
|
532
|
+
- `invoiceText`: Complete invoice text with formatting
|
|
533
|
+
|
|
534
|
+
### Bluetooth Methods
|
|
535
|
+
|
|
536
|
+
#### `requestBluetoothPermissions(): Promise<boolean>`
|
|
537
|
+
|
|
538
|
+
Requests necessary Bluetooth and location permissions.
|
|
539
|
+
|
|
540
|
+
**Returns:** `Promise<boolean>` - `true` if permissions granted
|
|
541
|
+
|
|
542
|
+
#### `checkBluetoothPermissions(): Promise<BluetoothPermissions>`
|
|
543
|
+
|
|
544
|
+
Returns the current status of Bluetooth and location permissions.
|
|
545
|
+
|
|
546
|
+
**Returns:** `Promise<BluetoothPermissions>` - Object with permission status
|
|
547
|
+
|
|
548
|
+
#### `discoverBluetoothDevices(): Promise<BluetoothDevice[]>`
|
|
549
|
+
|
|
550
|
+
Discovers available Bluetooth devices.
|
|
551
|
+
|
|
552
|
+
**Returns:** `Promise<BluetoothDevice[]>` - Array of discovered devices
|
|
553
|
+
|
|
554
|
+
#### `startBluetoothDiscovery(): Promise<boolean>`
|
|
555
|
+
|
|
556
|
+
Starts the Bluetooth device discovery process.
|
|
557
|
+
|
|
558
|
+
#### `stopBluetoothDiscovery(): Promise<boolean>`
|
|
559
|
+
|
|
560
|
+
Stops the Bluetooth device discovery process.
|
|
561
|
+
|
|
562
|
+
#### `isBluetoothEnabled(): Promise<boolean>`
|
|
563
|
+
|
|
564
|
+
Checks if Bluetooth is enabled on the device.
|
|
565
|
+
|
|
566
|
+
## Types
|
|
567
|
+
|
|
568
|
+
### BluetoothDevice
|
|
569
|
+
|
|
570
|
+
```typescript
|
|
571
|
+
interface BluetoothDevice {
|
|
572
|
+
name: string;
|
|
573
|
+
address: string;
|
|
574
|
+
type: 'CLASSIC' | 'LE' | 'DUAL' | 'UNKNOWN';
|
|
575
|
+
isPrinter: boolean;
|
|
576
|
+
}
|
|
577
|
+
```
|
|
578
|
+
|
|
579
|
+
### BluetoothPermissions
|
|
580
|
+
|
|
581
|
+
```typescript
|
|
582
|
+
interface BluetoothPermissions {
|
|
583
|
+
ACCESS_FINE_LOCATION: boolean;
|
|
584
|
+
ACCESS_COARSE_LOCATION: boolean;
|
|
585
|
+
BLUETOOTH_SCAN?: boolean;
|
|
586
|
+
BLUETOOTH_CONNECT?: boolean;
|
|
587
|
+
}
|
|
588
|
+
```
|
|
589
|
+
|
|
590
|
+
### InvoiceItem
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
interface InvoiceItem {
|
|
594
|
+
description: string;
|
|
595
|
+
quantity: number;
|
|
596
|
+
price: number;
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
## QR Code Printing
|
|
601
|
+
|
|
602
|
+
The module now includes comprehensive QR code printing functionality using the official Bixolon libraries.
|
|
603
|
+
|
|
604
|
+
### Basic QR Code Printing
|
|
605
|
+
|
|
606
|
+
```typescript
|
|
607
|
+
import QrCodePrinter from 'expo-bixolon/src/QrCodePrinter';
|
|
608
|
+
|
|
609
|
+
// Get the QR printer instance
|
|
610
|
+
const qrPrinter = QrCodePrinter.getInstance();
|
|
611
|
+
|
|
612
|
+
// Print a simple QR code
|
|
613
|
+
await qrPrinter.printSimpleQRCode('Hello World!', 9);
|
|
614
|
+
```
|
|
615
|
+
|
|
616
|
+
### Advanced QR Code Options
|
|
617
|
+
|
|
618
|
+
```typescript
|
|
619
|
+
import { QRCodeOptions } from 'expo-bixolon/src/QrCodePrinter';
|
|
620
|
+
|
|
621
|
+
const options: QRCodeOptions = {
|
|
622
|
+
data: 'https://www.example.com',
|
|
623
|
+
horizontalPosition: 200,
|
|
624
|
+
verticalPosition: 100,
|
|
625
|
+
model: 'MODEL2',
|
|
626
|
+
eccLevel: 'ECC_LEVEL_15',
|
|
627
|
+
size: 9,
|
|
628
|
+
rotation: 'NONE',
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
await qrPrinter.printQRCode(options);
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
### Specialized QR Code Types
|
|
635
|
+
|
|
636
|
+
#### URL QR Code
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
await qrPrinter.printURLQRCode('www.example.com', 9);
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
#### Contact QR Code (vCard)
|
|
643
|
+
|
|
644
|
+
```typescript
|
|
645
|
+
const contact = {
|
|
646
|
+
name: 'John Doe',
|
|
647
|
+
phone: '+1234567890',
|
|
648
|
+
email: 'john.doe@example.com',
|
|
649
|
+
company: 'Example Corp',
|
|
650
|
+
title: 'Software Engineer',
|
|
651
|
+
};
|
|
652
|
+
|
|
653
|
+
await qrPrinter.printContactQRCode(contact, 9);
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
#### WiFi QR Code
|
|
657
|
+
|
|
658
|
+
```typescript
|
|
659
|
+
await qrPrinter.printWiFiQRCode('MyWiFiNetwork', 'password123', 'WPA', 9);
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
#### Payment QR Code
|
|
663
|
+
|
|
664
|
+
```typescript
|
|
665
|
+
const paymentData = {
|
|
666
|
+
amount: 99.99,
|
|
667
|
+
currency: 'USD',
|
|
668
|
+
description: 'Product purchase',
|
|
669
|
+
merchantName: 'Example Store',
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
await qrPrinter.printPaymentQRCode(paymentData, 9);
|
|
673
|
+
```
|
|
674
|
+
|
|
675
|
+
### QR Code Configuration
|
|
676
|
+
|
|
677
|
+
- **Models**: MODEL1 (original) or MODEL2 (enhanced, recommended)
|
|
678
|
+
- **Error Correction**: ECC_LEVEL_7, ECC_LEVEL_15, ECC_LEVEL_25, ECC_LEVEL_30
|
|
679
|
+
- **Size**: 1-10 (recommended: 7-9)
|
|
680
|
+
- **Rotation**: NONE, ROTATION_90_DEGREES, ROTATION_180_DEGREES, ROTATION_270_DEGREES
|
|
681
|
+
|
|
682
|
+
For detailed QR code printing documentation, see [QR_PRINTING_README.md](./QR_PRINTING_README.md).
|
|
683
|
+
|
|
684
|
+
## Events
|
|
685
|
+
|
|
686
|
+
The module emits the following events:
|
|
687
|
+
|
|
688
|
+
- `onBluetoothDeviceDiscovered`: Fired when a new Bluetooth device is discovered
|
|
689
|
+
- `onBluetoothDiscoveryStarted`: Fired when Bluetooth discovery starts
|
|
690
|
+
- `onBluetoothDiscoveryStopped`: Fired when Bluetooth discovery stops
|
|
691
|
+
- `onPrinterConnected`: Fired when successfully connected to a printer
|
|
692
|
+
- `onPrinterDisconnected`: Fired when disconnected from a printer
|
|
693
|
+
- `onPrintComplete`: Fired when a print operation completes
|
|
694
|
+
|
|
695
|
+
## Example
|
|
696
|
+
|
|
697
|
+
See the `example` directory for a complete working example that demonstrates:
|
|
698
|
+
|
|
699
|
+
- Bluetooth device discovery
|
|
700
|
+
- Permission management
|
|
701
|
+
- Printer connection
|
|
702
|
+
- Text and invoice printing
|
|
703
|
+
- Event handling
|
|
704
|
+
|
|
705
|
+
## 🔧 Requirements
|
|
706
|
+
|
|
707
|
+
- **React Native**: 0.79+
|
|
708
|
+
- **Expo SDK**: 53+
|
|
709
|
+
- **Android**: API level 21+ (Android 5.0+)
|
|
710
|
+
- **iOS**: 13+ (limited support)
|
|
711
|
+
- **Node.js**: 18+
|
|
712
|
+
- **TypeScript**: 4.9+ (optional but recommended)
|
|
713
|
+
|
|
714
|
+
## 🖨️ Supported Printers
|
|
715
|
+
|
|
716
|
+
### Bixolon Thermal Printers
|
|
717
|
+
|
|
718
|
+
- **SPP-L310** ✅ (Primary target)
|
|
719
|
+
- **SPP-R200III** ✅
|
|
720
|
+
- **SPP-R300** ✅
|
|
721
|
+
- **SPP-R400** ✅
|
|
722
|
+
- **SPP-L410** ✅
|
|
723
|
+
- **SPP-L420** ✅
|
|
724
|
+
|
|
725
|
+
### Connection Types
|
|
726
|
+
|
|
727
|
+
- **Bluetooth** ✅ (Primary)
|
|
728
|
+
- **WiFi** ✅ (Limited support)
|
|
729
|
+
- **USB** ⚠️ (Experimental)
|
|
730
|
+
|
|
731
|
+
## 🐛 Troubleshooting
|
|
732
|
+
|
|
733
|
+
### Common Issues
|
|
734
|
+
|
|
735
|
+
#### 1. Bluetooth Permissions Not Granted
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
// Always check permissions first
|
|
739
|
+
const permissions = await BixolonPrinter.checkBluetoothPermissions();
|
|
740
|
+
console.log('Permissions:', permissions);
|
|
741
|
+
|
|
742
|
+
// Request if needed
|
|
743
|
+
if (!permissions.ACCESS_FINE_LOCATION) {
|
|
744
|
+
await BixolonPrinter.requestBluetoothPermissions();
|
|
745
|
+
}
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
#### 2. Device Not Found
|
|
749
|
+
|
|
750
|
+
- Ensure Bluetooth is enabled on both devices
|
|
751
|
+
- Make sure the printer is in pairing mode
|
|
752
|
+
- Check if the device is already paired in system settings
|
|
753
|
+
- Try restarting Bluetooth discovery
|
|
754
|
+
|
|
755
|
+
#### 3. Connection Fails
|
|
756
|
+
|
|
757
|
+
- Verify the device MAC address is correct
|
|
758
|
+
- Ensure the printer is compatible with the module
|
|
759
|
+
- Check if another app is connected to the printer
|
|
760
|
+
- Try disconnecting and reconnecting
|
|
761
|
+
|
|
762
|
+
#### 4. Print Jobs Not Completing
|
|
763
|
+
|
|
764
|
+
- Check if the printer has paper
|
|
765
|
+
- Verify the printer is not in error state
|
|
766
|
+
- Try printing a simple test first
|
|
767
|
+
- Check printer logs for error messages
|
|
768
|
+
|
|
769
|
+
#### 5. Module Not Found Error
|
|
770
|
+
|
|
771
|
+
```bash
|
|
772
|
+
# Make sure to run prebuild after installation
|
|
773
|
+
npx expo prebuild
|
|
774
|
+
|
|
775
|
+
# Clear cache if needed
|
|
776
|
+
npx expo start --clear
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
### Debug Mode
|
|
780
|
+
|
|
781
|
+
Enable debug logging for detailed information:
|
|
782
|
+
|
|
783
|
+
```bash
|
|
784
|
+
# Set environment variable
|
|
785
|
+
export EXPO_DEBUG=true
|
|
786
|
+
|
|
787
|
+
# Or in your app
|
|
788
|
+
process.env.EXPO_DEBUG = 'true';
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
### Performance Tips
|
|
792
|
+
|
|
793
|
+
1. **Initialize once**: Call `initializePrinter()` only once per app session
|
|
794
|
+
2. **Reuse connections**: Keep connections alive when possible
|
|
795
|
+
3. **Batch operations**: Group multiple print operations together
|
|
796
|
+
4. **Error handling**: Always wrap print operations in try-catch blocks
|
|
797
|
+
|
|
798
|
+
### Getting Help
|
|
799
|
+
|
|
800
|
+
If you encounter issues:
|
|
801
|
+
|
|
802
|
+
1. Check the [example app](./example) for working code
|
|
803
|
+
2. Enable debug mode and check logs
|
|
804
|
+
3. Verify your printer model is supported
|
|
805
|
+
4. Test with a simple print operation first
|
|
806
|
+
|
|
807
|
+
## 🤝 Contributing
|
|
808
|
+
|
|
809
|
+
We welcome contributions! Here's how you can help:
|
|
810
|
+
|
|
811
|
+
### Development Setup
|
|
812
|
+
|
|
813
|
+
```bash
|
|
814
|
+
# Clone the repository
|
|
815
|
+
git clone https://github.com/your-username/expo-bixolon.git
|
|
816
|
+
cd expo-bixolon
|
|
817
|
+
|
|
818
|
+
# Install dependencies
|
|
819
|
+
npm install
|
|
820
|
+
|
|
821
|
+
# Build the module
|
|
822
|
+
npm run build
|
|
823
|
+
|
|
824
|
+
# Run the example app
|
|
825
|
+
cd example
|
|
826
|
+
npm install
|
|
827
|
+
npx expo run:android
|
|
828
|
+
```
|
|
829
|
+
|
|
830
|
+
### Making Changes
|
|
831
|
+
|
|
832
|
+
1. **Fork the repository**
|
|
833
|
+
2. **Create a feature branch**: `git checkout -b feature/amazing-feature`
|
|
834
|
+
3. **Make your changes** and test thoroughly
|
|
835
|
+
4. **Add tests** if applicable
|
|
836
|
+
5. **Update documentation** as needed
|
|
837
|
+
6. **Submit a pull request**
|
|
838
|
+
|
|
839
|
+
### Publishing to NPM
|
|
840
|
+
|
|
841
|
+
El paquete se publica automáticamente a NPM cuando se crea un release en GitHub:
|
|
842
|
+
|
|
843
|
+
1. **Update version**: `make update-version VERSION=x.y.z`
|
|
844
|
+
2. **Commit**: `git add . && git commit -m "chore: bump version to x.y.z"`
|
|
845
|
+
3. **Push**: `git push origin main`
|
|
846
|
+
4. **Create GitHub Release**: El CI/CD publicará automáticamente a NPM
|
|
847
|
+
- Requiere secret `NPM_TOKEN` configurado en GitHub
|
|
848
|
+
|
|
849
|
+
**Comandos de desarrollo**:
|
|
850
|
+
|
|
851
|
+
- `make build` - Construye el módulo
|
|
852
|
+
- `make test` - Ejecuta tests
|
|
853
|
+
- `make format` - Formatea código
|
|
854
|
+
- `make verify-format` - Verifica formato (usado en CI)
|
|
855
|
+
- `make publish-dry-run` - Simula publicación
|
|
856
|
+
- `make publish` - Publica manualmente (requiere `npm login`)
|
|
857
|
+
|
|
858
|
+
### Code Style
|
|
859
|
+
|
|
860
|
+
- Use TypeScript for all new code
|
|
861
|
+
- Follow existing code patterns
|
|
862
|
+
- Add proper error handling
|
|
863
|
+
- Include JSDoc comments for public APIs
|
|
864
|
+
- Test on real Bixolon printers when possible
|
|
865
|
+
|
|
866
|
+
## 📄 License
|
|
867
|
+
|
|
868
|
+
MIT License - see [LICENSE](./LICENSE) file for details.
|
|
869
|
+
|
|
870
|
+
## 🆘 Support
|
|
871
|
+
|
|
872
|
+
### Getting Help
|
|
873
|
+
|
|
874
|
+
- 📖 **Documentation**: Check this README and the example app
|
|
875
|
+
- 🐛 **Bug Reports**: Open an issue with detailed information
|
|
876
|
+
- 💡 **Feature Requests**: Open an issue with use case description
|
|
877
|
+
- 💬 **Discussions**: Use GitHub Discussions for questions
|
|
878
|
+
|
|
879
|
+
### Issue Template
|
|
880
|
+
|
|
881
|
+
When reporting issues, please include:
|
|
882
|
+
|
|
883
|
+
```markdown
|
|
884
|
+
**Printer Model**: SPP-L310
|
|
885
|
+
**Android Version**: 12
|
|
886
|
+
**Expo SDK Version**: 53
|
|
887
|
+
**Steps to Reproduce**:
|
|
888
|
+
|
|
889
|
+
1. Initialize printer
|
|
890
|
+
2. Connect to device
|
|
891
|
+
3. Print text
|
|
892
|
+
**Expected Behavior**: Text should print
|
|
893
|
+
**Actual Behavior**: Connection fails
|
|
894
|
+
**Logs**: [Include relevant logs]
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
## 🎯 Roadmap
|
|
898
|
+
|
|
899
|
+
### Planned Features
|
|
900
|
+
|
|
901
|
+
- [ ] **Enhanced WiFi Support**: Full WiFi printing capabilities
|
|
902
|
+
- [ ] **Image Printing**: Support for printing images and logos
|
|
903
|
+
- [ ] **Barcode Printing**: Various barcode formats
|
|
904
|
+
- [ ] **iOS Support**: Full iOS implementation
|
|
905
|
+
- [ ] **Web Support**: Web-based printing interface
|
|
906
|
+
- [ ] **Cloud Printing**: Remote printing capabilities
|
|
907
|
+
|
|
908
|
+
### Recent Updates
|
|
909
|
+
|
|
910
|
+
- ✅ **v0.1.0**: Initial release with Bluetooth support
|
|
911
|
+
- ✅ **QR Code Printing**: Advanced QR code functionality
|
|
912
|
+
- ✅ **TypeScript Support**: Complete type definitions
|
|
913
|
+
- ✅ **Local Installation**: Support for local package distribution
|
|
914
|
+
|
|
915
|
+
---
|
|
916
|
+
|
|
917
|
+
**Made with ❤️ for the Expo and Bixolon communities**
|