@munchi_oy/react-native-epson-printer
v1.0.7
Published
Munchi Printer SDK Bridge
Readme
@munchi_oy/react-native-epson-printer
Epson printer SDK bridge for React Native (iOS + Android).
Installation (version-pinned recommended)
Use an explicit version instead of latest to keep production builds predictable.
npm install @munchi_oy/[email protected]
# or
pnpm add @munchi_oy/[email protected]
# or
yarn add @munchi_oy/[email protected]Recommended policy:
- Pin to an exact version in production.
- Upgrade intentionally after validating printers on staging.
Overview
This package provides:
- Epson discovery (
discoverPrinters) - Epson connection lifecycle (
connect,disconnect, connection events) - Serialized print queue with retry + recovery behavior
- Receipt printing via generic
PrintJobcommands - Embedded payload printing (
printEmbedded) - Cash drawer pulse (
openDrawer)
This package does not include Star or Sunmi drivers.
Behavior Support (implemented)
| Behavior | Status | Details |
| :--- | :--- | :--- |
| Session-isolated instances | Implemented | Each getPrinter(...) instance owns a native sessionId; events are routed by session. |
| Target conflict protection | Implemented | Concurrent active usage of the same target returns TARGET_IN_USE. |
| Serialized job queue | Implemented | connect, print, and disconnect are queued to avoid race conditions per instance. |
| Hardware-error pause/resume | Implemented | Hardware failures pause queue; queue resumes when recovery is detected via status events and polling. |
| Retry for transient busy/timeout states | Implemented | Native operations retry for retryable states (BUSY, IN_USE, timeout-family errors). |
| Print receive timeout guard | Implemented | Native print call fails with PRINT_TIMEOUT if printer callback does not return within 30s. |
| iOS stale-session recovery | Implemented | One-shot session recovery + reconnect + retry for stale/busy/offline connection scenarios. |
| Post-print auto-disconnect | Implemented | JS driver schedules disconnect after 5s idle after print completion. |
| Android warm reconnect cache | Implemented | Native Android keeps a short-lived connection cache (up to 120s) for faster reconnect. |
| Discovery cleanup/filtering | Implemented | Duplicate targets are deduped and Epson sub-devices such as [local_display] are filtered out. |
Multi-instance (one tablet -> many printers)
Yes, this is supported.
- Create one printer instance per physical target.
- Run them in parallel if needed.
- Do not connect two active instances to the same target at the same time (
TARGET_IN_USE).
import { EpsonModel, getPrinter } from '@munchi_oy/react-native-epson-printer';
const kitchenPrinter = getPrinter({
target: 'BT:00:01:90:7B:5A:11',
model: EpsonModel.TM_M30III,
});
const receiptPrinter = getPrinter({
target: 'TCP:192.168.1.50',
model: EpsonModel.TM_M30III,
});
await Promise.all([
kitchenPrinter.connect(),
receiptPrinter.connect(),
]);
await Promise.all([
kitchenPrinter.print({ commands: [{ type: 'text', text: 'Kitchen ticket\n' }, { type: 'cut' }] }),
receiptPrinter.print({ commands: [{ type: 'text', text: 'Customer receipt\n' }, { type: 'cut' }] }),
]);
await Promise.all([
kitchenPrinter.disconnect(),
receiptPrinter.disconnect(),
]);iOS Setup
- Install the package.
- Run CocoaPods install:
cd ios && pod install- Configure
Info.plistpermissions based on your connection method (Bluetooth/TCP).
Android Setup
- Install the package and sync Gradle.
- Request runtime permissions before discovery/connection:
- Android 12+ (
API 31+):BLUETOOTH_SCAN,BLUETOOTH_CONNECT - Android 11 and below:
ACCESS_FINE_LOCATION(Bluetooth discovery)
- Rebuild the app.
Quick Start
import { EpsonModel, getPrinter } from '@munchi_oy/react-native-epson-printer';
const printer = getPrinter({
target: 'BT:00:01:90:7B:5A:11',
model: EpsonModel.TM_M30III,
});
await printer.connect();
await printer.print({
commands: [
{ type: 'text', text: 'Hello\n', align: 'center', bold: true },
{ type: 'feed', lines: 2 },
{ type: 'cut' },
],
});
await printer.disconnect();Config
getPrinter(config) requires EpsonPrinterConfig.
| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| model | EpsonModel | Yes | Epson printer series passed to native init |
| target | string | No | Default target used by connect() when no target is passed |
| lang | Epos2Lang | No | Language enum for native printer object |
| logger | PrinterLogger | No | Per-instance logger (error, optional info) |
Discovery
Use discovery as a standalone API:
import { discoverPrinters } from '@munchi_oy/react-native-epson-printer';
const printers = await discoverPrinters({
timeout: 5000,
connectionType: 'bluetooth',
});Supported connectionType filters:
bluetooth->BT:tcp->TCP:,TCPS:usb->USB:
Connection Lifecycle
connect(target?, timeout?)disconnect()onConnectionChange(callback)onStatusChange(callback)
Example:
await printer.connect(); // uses config.target
await printer.connect('TCP:192.168.1.50', 7000); // override target
const off = printer.onConnectionChange((status) => {
console.log('connection', status);
});Printing
Generic PrintJob
await printer.print({
commands: [
{ type: 'align', align: 'left' },
{ type: 'text', text: 'Order #123\n' },
{ type: 'separator' },
{ type: 'cut' },
],
});Embedded payload
await printer.printEmbedded({
id: 'Ord-123',
ts: '12:00 PM',
lines: [{ t: '1x Burger' }],
});Cash drawer
await printer.openDrawer();Logging
You can set a global logger:
import { setGlobalLogger } from '@munchi_oy/react-native-epson-printer';
setGlobalLogger({
info: (message) => console.log(message),
error: (message, error) => console.error(message, error),
});React Helpers
The package exports:
PrinterProviderusePrinter()usePrinterStatus({ enabled?: boolean })
usePrinterStatus handles connect/disconnect behavior based on enabled, subscribes to connection + hardware status events, and exposes error state.
Supported Epson Models
The following printer series are natively supported by the underlying Epson ePOS SDK and can be passed to the model configuration using the EpsonModel enum:
- TM-M Series: TM-m10, TM-m30, TM-m30II, TM-m30III, TM-m50, TM-m50II, TM-m55
- TM-P Series: TM-P20, TM-P20II, TM-P60, TM-P60II, TM-P80, TM-P80II
- TM-T Series: TM-T20, TM-T60, TM-T70, TM-T81, TM-T82, TM-T83, TM-T83III, TM-T88, TM-T88VII, TM-T90, TM-T90KP, TM-T100
- TM-U Series: TM-U220, TM-U220II, TM-U330
- TM-L Series: TM-L90, TM-L90LFC, TM-L100
- TM-H Series: TM-H6000
- Others: TS-100, SB-H50, SB-M30
Vendor and Platform Support
| Vendor | Support | | :--- | :--- | | Epson | Yes | | Star | No | | Sunmi | No |
| Platform | Status | | :--- | :--- | | iOS | Supported | | Android | Supported |
Known Limitations
- Epson-only scope.
modelmust be known atgetPrinter(...)creation time.- Model/language are immutable per instance; create a new instance to change them.
- Underlying behavior is constrained by Epson ePOS2 SDK.
Troubleshooting
Native module not found
- iOS: reinstall pods and rebuild.
- Android: clean/sync Gradle and rebuild.
Printer target is required
- Pass
targetin config orconnect(target).
TARGET_IN_USE
- Another active session is using the same target. Disconnect old owner first.
- Busy/timeouts during peak usage
- Keep one active owner per target and avoid overlapping connect/print flows from different instances.
Migration Notes (already shipped)
If upgrading from older adapter-based versions:
- Epson-only scope
- Removed Star/Sunmi and
PrinterTypefactory behavior.
- Config updates
modelis required ingetPrinter({ ... }).
- Connect signature
- Before:
connect(target, timeout, model, lang) - Now:
connect(target?, timeout?)(model/lang come from instance config).
