npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

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

No 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
end

Then run:

cd ios && pod install

Troubleshooting:

  • 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

  1. Sử dụng print() thay vì connectNet() + printPic() riêng lẻ
  2. printConcurrent() cho nhiều máy in khác nhau
  3. printSequential() cho cùng 1 máy in hoặc cần thứ tự
  4. Gọi cleanup() định kỳ mỗi 30 phút để dọn dẹp connections
  5. Không cần gọi disconnect() sau mỗi lần in
  6. 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