expo-bluetooth-thermal-printer
v1.0.1
Published
Expo native module for Bluetooth Classic thermal receipt printer (ESC/POS). Supports 58mm and 80mm paper. Android only.
Maintainers
Readme
expo-bluetooth-thermal-printer
Expo native module for Bluetooth Classic thermal receipt printers (ESC/POS). Supports 58mm and 80mm paper width. Android only.
Works with common thermal printers like RPP02N, POS-5802, and similar 58mm/80mm Bluetooth receipt printers that use the SPP (Serial Port Profile) protocol.
Features
- Bluetooth Classic (RFCOMM/SPP) — not BLE
- Multiple connection methods — tries secure, insecure, and reflection-based RFCOMM as fallback
- ESC/POS commands — alignment, bold, underline, text size, separator, cut
- High-level Printer class — chainable methods for easy receipt building
- Low-level access — send raw bytes or text directly
- Expo Modules API — compatible with Expo SDK 51+ and React Native 0.74+
- New Architecture compatible — uses JSI, not Bridge
Requirements
- Expo SDK 51+
- React Native 0.74+
- Android only (no iOS support — iOS requires MFi for Bluetooth Classic)
- Printer must be paired in Android Bluetooth Settings first
Installation
npx expo install expo-bluetooth-thermal-printerOr for local development:
npm install expo-bluetooth-thermal-printerAndroid Permissions
Add to your app.json:
{
"expo": {
"android": {
"permissions": [
"android.permission.BLUETOOTH",
"android.permission.BLUETOOTH_ADMIN",
"android.permission.BLUETOOTH_CONNECT",
"android.permission.BLUETOOTH_SCAN",
"android.permission.ACCESS_FINE_LOCATION"
]
}
}
}Request permissions at runtime (Android 12+):
import { PermissionsAndroid } from 'react-native';
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
]);Quick Start
import { Printer, getBondedDevices, isBluetoothEnabled } from 'expo-bluetooth-thermal-printer';
// Check Bluetooth
if (!isBluetoothEnabled()) {
console.log('Please enable Bluetooth');
return;
}
// Get paired devices
const devices = getBondedDevices();
console.log('Paired devices:', devices);
// Create printer instance (58mm paper)
const printer = new Printer('58mm');
// Connect to printer
await printer.connect(devices[0].address);
// Print receipt
await printer.initialize();
await printer.alignCenter();
await printer.bold(true);
await printer.println('MY STORE');
await printer.bold(false);
await printer.separator();
await printer.alignLeft();
await printer.row('Coffee', '25.000');
await printer.row('Tea', '15.000');
await printer.separator();
await printer.bold(true);
await printer.row('TOTAL', '40.000');
await printer.bold(false);
await printer.feed(4);
// Disconnect
printer.disconnect();API Reference
Core Functions
| Function | Returns | Description |
|----------|---------|-------------|
| isBluetoothEnabled() | boolean | Check if Bluetooth is on |
| getBondedDevices() | BluetoothDevice[] | Get paired devices |
| connect(address) | Promise<BluetoothDevice> | Connect to device |
| disconnect() | boolean | Disconnect |
| isConnected() | boolean | Check connection |
| getConnectedDevice() | BluetoothDevice \| null | Get connected device info |
Low-level Write
| Function | Description |
|----------|-------------|
| writeText(text) | Send text string (ISO-8859-1) |
| writeBytes(bytes) | Send byte array (ESC/POS commands) |
| writeRaw(base64) | Send raw base64-encoded data |
Printer Class
const printer = new Printer('58mm'); // or '80mm'| Method | Description |
|--------|-------------|
| connect(address) | Connect to printer |
| disconnect() | Disconnect |
| initialize() | Reset printer (ESC @) |
| alignLeft() / alignCenter() / alignRight() | Set alignment |
| bold(on) | Enable/disable bold |
| underline(on) | Enable/disable underline |
| setSize(size) | 'normal' | 'doubleHeight' | 'doubleWidth' | 'double' |
| println(text) | Print text + newline |
| print(text) | Print text without newline |
| newline() | Print empty line |
| feed(lines) | Feed paper |
| separator(char) | Print full-width separator (default: -) |
| doubleSeparator() | Print = separator |
| row(left, right) | Print left-right aligned row |
| centerText(text) | Print centered text |
| boldText(text, align) | Print bold text with alignment |
| cut() | Full cut (if cutter available) |
| partialCut() | Partial cut |
| raw(bytes) | Send raw ESC/POS bytes |
ESC/POS Commands
import { Commands } from 'expo-bluetooth-thermal-printer';
// Available commands:
Commands.INIT // Initialize printer
Commands.ALIGN_LEFT // Left alignment
Commands.ALIGN_CENTER // Center alignment
Commands.ALIGN_RIGHT // Right alignment
Commands.BOLD_ON // Bold on
Commands.BOLD_OFF // Bold off
Commands.UNDERLINE_ON // Underline on
Commands.UNDERLINE_OFF // Underline off
Commands.SIZE_NORMAL // Normal size
Commands.SIZE_DOUBLE_HEIGHT
Commands.SIZE_DOUBLE_WIDTH
Commands.SIZE_DOUBLE // Double width + height
Commands.LF // Line feed
Commands.CUT // Full cut
Commands.CUT_PARTIAL // Partial cutPaper Width
| Width | Characters per line | |-------|-------------------| | 58mm | 32 | | 80mm | 48 |
Connection Methods
The library tries 4 connection methods in order (fallback):
- Secure RFCOMM —
createRfcommSocketToServiceRecord(SPP_UUID) - Insecure RFCOMM —
createInsecureRfcommSocketToServiceRecord(SPP_UUID) - Reflection port 1 —
createRfcommSocket(1)via reflection - Reflection port 2 —
createRfcommSocket(2)via reflection
This ensures maximum compatibility with different printer models.
Troubleshooting
Printer not found in getBondedDevices()
- Go to Android Settings > Bluetooth
- Make sure printer is powered ON
- Tap the printer to pair (PIN is usually
1234or0000)
Connection failed
- Make sure no other app is connected to the printer
- Turn printer off and on again
- Remove and re-pair the printer in Bluetooth settings
- Make sure you've granted Bluetooth permissions
Print comes out garbled
- Make sure you're using the correct paper width (
58mmor80mm) - Call
initialize()before printing to reset printer state - Don't send text longer than
charsPerLineon one line
Tested Printers
- RPP02N (58mm)
- POS-5802 (58mm)
- Generic 58mm Bluetooth thermal printers
License
MIT
