@finan-me/react-native-zywell-thermal-printer
v1.2.5
Published
Native bridge for Zywell Thermal printer
Readme
@finan-me/react-native-zywell-thermal-printer
Native bridge for Zywell Thermal printer với Connection Pool tự động quản lý kết nối
Installation
npm install @finan-me/react-native-zywell-thermal-printer⚡ Features
- 🖨️ Zywell Thermal Printer: In ảnh qua LAN/WiFi và Bluetooth
- 🚀 Connection Pool: Tự động quản lý và tái sử dụng kết nối
- 📶 Bluetooth Support: Hỗ trợ kết nối và in qua Bluetooth
- 📱 Cross Platform: Hỗ trợ iOS và Android
- 🔄 Auto Reconnect: Tự động kết nối lại khi cần thiết
🚀 Quick Start
In đơn giản (Khuyến nghị)
import { print } from "@finan-me/react-native-zywell-thermal-printer";
// Cách đơn giản nhất - chỉ 1 dòng!
const result = await print("192.168.1.100", "/path/to/receipt.png");
// Với config
const result = await print("192.168.1.100", "/path/to/receipt.png", {
size: 80,
width: 576,
cut_paper: true,
mode: "THERMAL",
});In nhiều máy đồng thời
import { printConcurrent } from "@finan-me/react-native-zywell-thermal-printer";
const jobs = [
{ ip: "192.168.1.100", imagePath: "/images/kitchen.png" },
{ ip: "192.168.1.101", imagePath: "/images/receipt.png" },
{ ip: "192.168.1.102", imagePath: "/images/label.png" },
];
const results = await printConcurrent(jobs);
results.forEach((r) => {
console.log(`${r.ip}: ${r.success ? "✅" : "❌"} ${r.error || ""}`);
});In tuần tự (cùng 1 máy)
import { printSequential } from "@finan-me/react-native-zywell-thermal-printer";
const jobs = [
{ ip: "192.168.1.100", imagePath: "/orders/order1.png" },
{ ip: "192.168.1.100", imagePath: "/orders/order2.png" },
{ ip: "192.168.1.100", imagePath: "/orders/order3.png" },
];
const results = await printSequential(jobs);📚 API Reference
Connection Methods
| Method | Description | Parameters | Returns |
| --------------------- | ---------------------------- | ----------------- | ----------------- |
| connectNet(ip) | Kết nối máy in qua mạng | ip: string | Promise<string> |
| connectBLE(address) | Kết nối máy in qua Bluetooth | address: string | Promise<string> |
Printing Methods
| Method | Description | Parameters | Returns |
| -------------------------------------------- | ------------------------------------ | ------------------------------------------------------------------------------------- | ------------------------ |
| print(address, imagePath, opts?, type?) | In với connection pool (khuyến nghị) | address: stringimagePath: stringopts?: PrinterConfigtype?: string | Promise<string> |
| printPic(address, imagePath, opts?, type?) | In ảnh (legacy) | Same as above | Promise<string> |
| printConcurrent(jobs) | In nhiều jobs đồng thời | jobs: Array<PrintJob> | Promise<Array<Result>> |
| printSequential(jobs) | In nhiều jobs tuần tự | jobs: Array<PrintJob> | Promise<Array<Result>> |
Disconnection Methods
| Method | Description | Parameters | Returns |
| ---------------------------- | ------------------- | ------------------------------------ | ------- |
| disconnect(address, type?) | Ngắt kết nối máy in | address: stringtype?: string | void |
Maintenance Methods
| Method | Description | Parameters | Returns |
| ---------------------------- | ---------------------------------------- | ----------------------------------- | ----------------- |
| clearBuffer(address, type) | Xóa buffer máy in | address: stringtype: string | void |
| cleanup() | Dọn dẹp connections cũ (gọi mỗi 30 phút) | None | Promise<string> |
Status Methods
| Method | Description | Parameters | Returns |
| ------------------------- | --------------------------- | ------------ | --------------------------- |
| getConnectionStatus(ip) | Lấy trạng thái kết nối | ip: string | Promise<ConnectionStatus> |
| pingConnection(ip) | Kiểm tra connection healthy | ip: string | Promise<boolean> |
🔧 Configuration
PrinterConfig Options
interface PrinterConfig {
size?: number; // 58 hoặc 80 (mặc định: 80)
width?: number; // Chiều rộng in pixels (mặc định: 576)
cut_paper?: boolean; // Cắt giấy sau khi in (mặc định: true)
mode?: string; // "THERMAL" hoặc "LABEL" (mặc định: "THERMAL")
paper_size?: number; // Kích thước giấy cho mode LABEL (mặc định: 50)
}Android Permissions
Add to android/src/main/AndroidManifest.xml:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.INTERNET" />iOS Permissions
Add to Info.plist:
<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs Bluetooth access to connect to thermal printers</string>
<key>NSBluetoothPeripheralUsageDescription</key>
<string>This app needs Bluetooth access to connect to thermal printers</string>iOS Setup
CocoaAsyncSocket Dependency
This library requires CocoaAsyncSocket for WiFi printing support. The dependency is automatically included in the podspec.
Standard Installation:
If you're using ONLY this library:
cd ios && pod installNo additional configuration needed!
Compatibility with react-native-thermal-receipt-printer:
If you're using BOTH this library AND react-native-thermal-receipt-printer, you may encounter duplicate symbols error because react-native-thermal-receipt-printer includes CocoaAsyncSocket in its libPrinterSDK.a file.
To fix this, add the following to your ios/Podfile inside the post_install block:
post_install do |installer|
# ... other post install code
# Fix duplicate symbols conflict between printer libraries
# react-native-thermal-receipt-printer includes CocoaAsyncSocket in libPrinterSDK.a
# react-native-zywell-thermal-printer needs CocoaAsyncSocket headers
# This removes the implementation files but keeps the headers
installer.pods_project.targets.each do |target|
if target.name == 'CocoaAsyncSocket'
source_files = target.source_build_phase.files
source_files.delete_if { |file|
['GCDAsyncSocket.m', 'GCDAsyncUdpSocket.m'].include?(file.file_ref.name)
}
end
end
endThen run:
cd ios && pod installTroubleshooting:
- Error: 'CocoaAsyncSocket/GCDAsyncSocket.h' file not found: Make sure you have the latest version and run
pod install - Error: 137 duplicate symbols: Apply the Podfile fix mentioned above if using both printer libraries
- Build fails after pod install: Try cleaning:
cd ios && rm -rf Pods Podfile.lock && pod install --repo-update
💡 Connection Pool Management
Library tự động quản lý connection pool với các tính năng:
- Auto Connect: Tự động kết nối khi cần in
- Connection Reuse: Tái sử dụng connection trong 5 phút
- Health Check: Kiểm tra connection trước khi in
- Stale Cleanup: Tự động cleanup connection không dùng > 10 phút (khi gọi
cleanup())
Cleanup Strategy
import { cleanup } from "@finan-me/react-native-zywell-thermal-printer";
// Gọi cleanup định kỳ mỗi 30 phút
setInterval(async () => {
const result = await cleanup();
console.log(result); // "Cleaned up 3 stale connections"
}, 30 * 60 * 1000);
// Hoặc gọi khi app về background
AppState.addEventListener("change", (state) => {
if (state === "background") {
cleanup();
}
});🔍 Advanced Usage
Health Check trước khi in batch
import {
pingConnection,
printConcurrent,
} from "@finan-me/react-native-zywell-thermal-printer";
// Kiểm tra máy in trước khi in batch
const printers = ["192.168.1.100", "192.168.1.101"];
const availablePrinters = [];
for (const ip of printers) {
if (await pingConnection(ip)) {
availablePrinters.push(ip);
}
}
// Chỉ in với máy sẵn sàng
const validJobs = jobs.filter((job) => availablePrinters.includes(job.ip));
const results = await printConcurrent(validJobs);Monitor Connection Status
import { getConnectionStatus } from "@finan-me/react-native-zywell-thermal-printer";
const status = await getConnectionStatus("192.168.1.100");
console.log(status);
// Output:
// {
// connected: true,
// lastUsed: 30, // seconds since last use
// ipAddress: "192.168.1.100"
// }🎯 Best Practices
- Sử dụng
print()thay vìconnectNet()+printPic()riêng lẻ printConcurrent()cho nhiều máy in khác nhauprintSequential()cho cùng 1 máy in hoặc cần thứ tự- Gọi
cleanup()định kỳ mỗi 30 phút để dọn dẹp connections - Không cần gọi
disconnect()sau mỗi lần in - Health check chỉ cần cho batch printing hoặc mission-critical apps
🆚 So sánh với cách cũ
| Feature | Cách cũ | Connection Pool | | -------------- | ----------- | -------------------- | | Connect | Mỗi lần in | Tự động, tái sử dụng | | Disconnect | Thủ công | Tự động cleanup | | Performance | ~3-5s/print | ~1-2s/print | | Code | 3-5 dòng | 1 dòng | | Error handling | Try-catch | Built-in retry |
Migration Example
// ❌ Cách cũ - chậm và phức tạp
await connectNet("192.168.1.100");
await printPic("192.168.1.100", "/image.png", {
is_disconnect: true,
});
// ✅ Cách mới - nhanh và đơn giản
await print("192.168.1.100", "/image.png");🐛 Troubleshooting
Connection issues
// Kiểm tra connection
const isHealthy = await pingConnection("192.168.1.100");
if (!isHealthy) {
// Force cleanup và thử lại
await cleanup();
await print("192.168.1.100", "/image.png");
}Memory management
// Cleanup khi app terminate
const onAppTerminate = async () => {
await cleanup();
};📝 License
MIT
