thermal_printer_billbay 1.0.6 copy "thermal_printer_billbay: ^1.0.6" to clipboard
thermal_printer_billbay: ^1.0.6 copied to clipboard

A comprehensive Flutter plugin for ESC/POS thermal printers via Bluetooth Classic (SPP). Supports Arabic shaping, multiple code pages, receipt templates, images, QR codes, barcodes, and all standard E [...]

thermal_printer_billbay #

A comprehensive Flutter plugin for ESC/POS thermal printers via Bluetooth Classic (SPP).

Supports Android (Bluetooth Classic) and iOS (MFi via ExternalAccessory).

Features #

  • Bluetooth Classic (SPP) connection — scan, pair, connect, send
  • Full ESC/POS command set — text, bold, underline, reverse, font sizes, alignment
  • Arabic text shaping — automatic joining forms, Lam-Alef ligatures, bidi reversal
  • Multiple code pages — Win-1256, CP864, CP720, UTF-8, or any custom number
  • Paper sizes — 58mm, 72mm, 80mm, 110mm, and custom
  • Multi-column rows — grid-based column layout for receipts
  • Receipt templates — ready-made invoice builder with items, tax, QR, footer
  • Images — print PNG/JPEG/BMP with auto monochrome conversion
  • QR codes — native ESC/POS QR commands
  • Barcodes — UPC-A, UPC-E, EAN-13, EAN-8, Code 39, ITF, Codabar, Code 93, Code 128
  • Horizontal lines — solid, dashed, dotted, double, star, equals
  • Paper cut, cash drawer, beep
  • Raw bytes pass-through for custom commands

Table of Contents #

  1. Installation
  2. Android Setup
  3. iOS Setup
  4. Quick Start
  5. Finding Your Printer's Code Page
  6. Printing Text
  7. Text Styles
  8. Arabic Text
  9. Multi-Column Rows
  10. Horizontal Lines
  11. QR Codes
  12. Barcodes
  13. Images
  14. Receipt Templates
  15. Paper Cut, Cash Drawer & Beep
  16. Full API Reference
  17. Distribution Guide

1. Installation #

Option A: Local Path (for development / private use) #

Put the thermal_printer_billbay folder next to your app folder:

my_projects/
  thermal_printer_billbay/    ← this plugin
  my_app/             ← your Flutter app

In your app's pubspec.yaml:

dependencies:
  thermal_printer_billbay:
    path: ../thermal_printer_billbay

Option B: Git Repository (for sharing with team) #

Push thermal_printer_billbay to a Git repo (GitHub, GitLab, Bitbucket), then:

dependencies:
  thermal_printer_billbay:
    git:
      url: https://github.com/YOUR_USERNAME/thermal_printer_billbay.git
      ref: main  # or a specific tag like v1.0.0

Option C: Publish to pub.dev (for public distribution) #

See Section 17: Distribution Guide.

After adding the dependency #

Run in your app folder:

flutter pub get

No additional permission packages needed — the plugin handles Bluetooth permissions internally.


2. Android Setup #

2.1 Permissions #

Add these to your app's android/app/src/main/AndroidManifest.xml (inside the <manifest> tag, before <application>):

<!-- Bluetooth Classic permissions -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>

<!-- Android 12+ Bluetooth permissions -->
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

<!-- Location (required for Bluetooth scanning on Android) -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

2.2 Request Permissions at Runtime #

The plugin handles runtime permission requests automatically. Just call:

final printer = ThermalPrinterManager();

// Option A: One-call setup (handles permissions + Bluetooth enable)
final ready = await printer.ensureReady();
if (!ready) return; // permissions denied or Bluetooth off

// Option B: Step by step
final granted = await printer.requestPermissions();
if (!granted) return;

if (!await printer.isBluetoothEnabled()) {
  await printer.enableBluetooth();
}

2.3 Min SDK #

Make sure your android/app/build.gradle has minSdk at least 21:

android {
    defaultConfig {
        minSdk = 21
    }
}

3. iOS Setup #

3.1 Info.plist #

Add these to ios/Runner/Info.plist:

<key>NSBluetoothAlwaysUsageDescription</key>
<string>This app needs Bluetooth to connect to thermal printers</string>

<key>UISupportedExternalAccessoryProtocols</key>
<array>
    <string>com.yourprinter.protocol</string>
</array>

Replace com.yourprinter.protocol with your printer's MFi protocol string (check your printer's documentation).

3.2 Set Protocol in Code #

final printer = ThermalPrinterManager();
await printer.setProtocol('com.yourprinter.protocol');

3.3 Important #

iOS only supports MFi-certified printers via the ExternalAccessory framework. Regular Bluetooth printers that are not MFi certified will not work on iOS.


4. Quick Start #

Here is the simplest possible example — setup, connect, print "Hello World", cut paper:

import 'package:thermal_printer_billbay/thermal_printer_billbay.dart';

// 1. Create the printer manager
final printer = ThermalPrinterManager();

// 2. Ensure permissions + Bluetooth are ready
final ready = await printer.ensureReady();
if (!ready) return;

// 3. Get already-paired devices
final devices = await printer.getBondedDevices();
print('Found ${devices.length} paired devices');

// 4. Connect to the first printer (with auto-retry)
final connected = await printer.connectWithRetry(devices.first.address);
if (!connected) {
  print('Failed to connect');
  return;
}

// 4. Build ESC/POS commands
final cmd = EscPosCommands(PaperSize.mm80);
cmd.initialize();
cmd.textLn('Hello World!', useLatin: true);
cmd.feed(3);
cmd.cut();

// 5. Send to printer
await printer.sendBytes(cmd.getBytes());

// 6. Disconnect when done
await printer.disconnect();
printer.dispose();

Scanning for New Devices #

final printer = ThermalPrinterManager();

// Listen for discovered devices
printer.scanResults.listen((device) {
  print('Found: ${device.name} (${device.address})');
});

// Listen for connection changes
printer.connectionState.listen((connected) {
  print('Connected: $connected');
});

// Start scanning (also discovers nearby unpaired devices)
await printer.startScan();

// Stop after 10 seconds
Future.delayed(Duration(seconds: 10), () {
  printer.stopScan();
});

5. Finding Your Printer's Code Page #

This is the most important step for Arabic/special characters.

Every thermal printer has a list of code pages, but the numbers are different for every brand. The same encoding (e.g., Windows-1256 Arabic) might be number 46 on one printer and number 60 on another.

How to Find Your Code Page Number #

  1. Print a self-test page: Turn off your printer, then hold the FEED button and turn it on. It will print a page showing all supported code pages with their numbers.

  2. Look for Arabic code pages: Find entries like:

    • 46: WPC1256 or 46: Win-1256 (Windows-1256 Arabic)
    • 22: PC864 (IBM Arabic)
    • 41: PC864 (same encoding, different number!)
    • 60: PC1001 (another Arabic page)
  3. Use the number from YOUR printer's self-test:

    // If your printer shows "46: Win-1256"
    cmd.setCodePage(CodePage.win1256); // sends ESC t 46
    
    // If your printer shows Arabic at number 41
    cmd.setCodePageRaw(41); // sends ESC t 41
    
    // For UTF-8 mode (Chinese-brand printers often support this)
    cmd.setCodePage(CodePage.utf8); // sends FS .
    

Built-in Code Page Presets #

Preset Code Page Number Best For
CodePage.utf8 PC10001 (UTF-8) FS . Chinese-brand printers, full Unicode
CodePage.win1256 Win-1256 46 Arabic (Epson standard)
CodePage.cp864 CP864 22 Arabic (IBM standard)
CodePage.cp720 CP720 32 Arabic DOS
CodePage.pc437 PC437 0 USA/Western Europe
CodePage.win1252 WPC1252 16 Western European
CodePage.pc850 PC850 2 Multilingual Latin

Custom Code Page #

If your printer uses a different number:

// Your printer has Arabic at position 60
cmd.setCodePageRaw(60);

// Or create a reusable CodePage object
final myCodePage = CodePage.customArabic(60);
cmd.setCodePage(myCodePage);

// Parse from user input (number or name)
cmd.setCodePageFromString('60');      // sends ESC t 60
cmd.setCodePageFromString('PC10001'); // sends FS . (UTF-8)

6. Printing Text #

Basic Text #

final cmd = EscPosCommands(PaperSize.mm80);
cmd.initialize();
cmd.setCodePage(CodePage.win1256);

// Print a line (adds line feed at end)
cmd.textLn('Hello World!', useLatin: true);

// Print text without line feed
cmd.text('Same line... ', useLatin: true);
cmd.textLn('continues here', useLatin: true);

// Print a blank line
cmd.newLine();

// Print Arabic text
cmd.textLn('مرحبا بالعالم');

cmd.feed(3);
await printer.sendBytes(cmd.getBytes());

The useLatin Parameter #

  • useLatin: true — Use for English, numbers, symbols. Sends raw ASCII bytes (fast, always works).
  • useLatin: false (default) — Use for Arabic or mixed text. Applies Arabic shaping and encodes using the selected code page.

7. Text Styles #

textStyled() applies styles, prints the text, then automatically resets styles back to normal:

cmd.initialize();

// Bold centered title
cmd.textStyled('MY STORE',
    PosStyles(align: PrintAlign.center, bold: true, width: 2, height: 2),
    useLatin: true);

// Underlined text
cmd.textStyled('Underlined', PosStyles(underline: true), useLatin: true);

// Double underline
cmd.textStyled('Double underline', PosStyles(doubleUnderline: true), useLatin: true);

// Reverse (white text on black background)
cmd.textStyled('Reversed!', PosStyles(reverse: true), useLatin: true);

// Font B (smaller font, more characters per line)
cmd.textStyled('Small font', PosStyles(fontType: FontType.fontB), useLatin: true);

// Wide text (2x width)
cmd.textStyled('Wide', PosStyles(width: 2), useLatin: true);

// Tall text (2x height)
cmd.textStyled('Tall', PosStyles(height: 2), useLatin: true);

// Combine multiple styles
cmd.textStyled('BIG BOLD',
    PosStyles(bold: true, width: 2, height: 2, align: PrintAlign.center),
    useLatin: true);

Using Manual Style Commands #

For more control, set styles individually:

cmd.setBold(true);
cmd.setFontSize(2, 2);       // width=2, height=2
cmd.setAlign(PrintAlign.center);
cmd.textLn('Custom styled', useLatin: true);

// Reset everything back to normal
cmd.resetStyles();

All Available Styles #

Style PosStyles Property Values
Alignment align PrintAlign.left, .center, .right
Bold bold true / false
Underline underline true / false
Double underline doubleUnderline true / false
Reverse reverse true / false
Font fontType FontType.fontA, .fontB
Width width 1 to 8 (multiplier)
Height height 1 to 8 (multiplier)
Upside down upsideDown true / false

8. Arabic Text #

Basic Arabic Printing #

cmd.initialize();
cmd.setCodePage(CodePage.win1256); // Use the code page that works for YOUR printer

cmd.textLn('مرحبا بالعالم');             // Hello World
cmd.textLn('اختبار الطباعة العربية');     // Arabic printing test

How Arabic Works #

  1. Code page tells the printer which character encoding to use
  2. Arabic shaping converts letters to their correct joined forms (initial, medial, final, isolated)
  3. Bidi reversal flips the text so it prints right-to-left

The plugin handles steps 2 and 3 automatically when you use textLn() without useLatin: true.

Arabic with UTF-8 Mode #

If your printer supports UTF-8 (FS . command), Arabic shaping uses Unicode Presentation Forms (U+FE70-U+FEFF) which gives the best results:

cmd.setCodePage(CodePage.utf8);
cmd.textLn('مرحبا بالعالم');  // Shaped + UTF-8 encoded

Arabic with Win-1256 #

If your printer uses Windows-1256 (common for Epson-compatible printers), the plugin encodes Arabic using a Win-1256 lookup table:

cmd.setCodePage(CodePage.win1256);
cmd.textLn('مرحبا بالعالم');  // Encoded as Win-1256 bytes

Mixed Arabic and English #

cmd.textLn('الفاتورة Invoice');  // Mixed text
cmd.textLn('Hello مرحبا World');

9. Multi-Column Rows #

Use row() to print tabular data. Column widths are proportional (like a 12-column grid):

// Header row
cmd.row([
  PosColumn(text: 'Item', width: 6),
  PosColumn(text: 'Qty', width: 2, align: PrintAlign.center),
  PosColumn(text: 'Price', width: 4, align: PrintAlign.right),
], useLatin: true);

// Data rows
cmd.row([
  PosColumn(text: 'Coffee', width: 6),
  PosColumn(text: '2', width: 2, align: PrintAlign.center),
  PosColumn(text: '5.00', width: 4, align: PrintAlign.right),
], useLatin: true);

Left-Right Alignment #

For simple label-value pairs:

cmd.leftRight('Subtotal:', '45.00', useLatin: true);
cmd.leftRight('Tax (15%):', '6.75', useLatin: true);
cmd.leftRight('TOTAL:', '51.75', useLatin: true);

10. Horizontal Lines #

cmd.hr();                                // ------------------------------------------------
cmd.hr(style: LineStyle.solid);          // ------------------------------------------------
cmd.hr(style: LineStyle.dashed);         // - - - - - - - - - - - - - - - - - - - - - - - -
cmd.hr(style: LineStyle.dotted);         // ................................................
cmd.hr(style: LineStyle.doubleLine);     // ================================================
cmd.hr(style: LineStyle.star);           // ************************************************
cmd.hr(style: LineStyle.equals);         // ================================================

// Custom character
cmd.hr(customChar: '~');                 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The line width is automatically calculated based on your paper size (48 chars for 80mm, 32 for 58mm, etc.).


11. QR Codes #

cmd.printQrCode(
  'https://example.com',
  size: 6,                           // Module size: 1-16 (default: 6)
  errorLevel: QrErrorLevel.medium,   // L, M, Q, H (default: M)
  align: PrintAlign.center,          // Alignment (default: center)
);

QR Error Correction Levels #

Level Recovery Best For
QrErrorLevel.low ~7% Short URLs, clean environment
QrErrorLevel.medium ~15% General use (default)
QrErrorLevel.quartile ~25% Receipts that may get crumpled
QrErrorLevel.high ~30% Harsh environments

12. Barcodes #

cmd.printBarcode(
  '1234567890128',
  BarcodeType.ean13,
  height: 80,          // Barcode height in dots (default: 80)
  width: 2,            // Bar width: 2-6 (default: 2)
  textPosition: 2,     // 0=none, 1=above, 2=below, 3=both
  align: PrintAlign.center,
);

Supported Barcode Types #

Type Data Format
BarcodeType.upcA 11-12 digits
BarcodeType.upcE 6-8 digits
BarcodeType.ean13 12-13 digits
BarcodeType.ean8 7-8 digits
BarcodeType.code39 A-Z, 0-9, space, $%+-./
BarcodeType.itf Even number of digits
BarcodeType.codabar 0-9, A-D, $+-./:
BarcodeType.code93 ASCII 0-127
BarcodeType.code128 ASCII 0-127 (most flexible)

13. Images #

Print any image (PNG, JPEG, BMP). It's automatically converted to monochrome and scaled to fit the paper width:

import 'dart:io';

// Load image from file
final imageBytes = await File('path/to/logo.png').readAsBytes();

cmd.printImage(
  imageBytes,
  maxWidth: 384,           // Max width in dots (optional, defaults to paper width)
  threshold: 127,          // Black/white threshold: 0-255 (default: 127)
  align: PrintAlign.center,
);

From Flutter Assets #

import 'package:flutter/services.dart';

final data = await rootBundle.load('assets/logo.png');
final imageBytes = data.buffer.asUint8List();
cmd.printImage(imageBytes);

14. Receipt Templates #

Full Receipt #

final cmd = EscPosCommands(PaperSize.mm80);
cmd.setCodePage(CodePage.win1256);

final receipt = ReceiptTemplate(
  cmd: cmd,
  storeName: 'MY STORE',
  storeAddress: '123 Main Street',
  storePhone: '555-1234',
  storeEmail: 'info@mystore.com',
  currency: '\$',  // Currency symbol before prices
);

receipt.build(
  items: [
    ReceiptItem(name: 'Coffee', quantity: 2, price: 5.00),
    ReceiptItem(name: 'Sandwich', quantity: 1, price: 8.50),
    ReceiptItem(name: 'Cookie', quantity: 3, price: 2.00, discount: 1.00),
  ],
  taxRate: 0.15,              // 15% tax
  discount: 2.0,              // Overall discount amount
  receiptNumber: '001234',
  cashierName: 'Ahmad',
  customerName: 'John',
  footerText: 'Thank you for your purchase!',
  footerTextArabic: 'شكرا لزيارتكم',
  qrData: 'https://mystore.com/receipt/001234',
  barcodeData: '001234',
  cutAfter: true,             // Auto cut paper after receipt
);

await printer.sendBytes(cmd.getBytes());

This prints:

       MY STORE
    123 Main Street
      Tel: 555-1234
    info@mystore.com
------------------------------------------------
Receipt #:               001234
Date:          2026-02-07 14:30
Cashier:                 Ahmad
Customer:                 John
------------------------------------------------
Item       Qty  Price   Total
- - - - - - - - - - - - - - -
Coffee      2    5.00   10.00
Sandwich    1    8.50    8.50
Cookie      3    2.00    5.00
  Disc: -1.00
- - - - - - - - - - - - - - -
Subtotal:                23.50
Discount:                -2.00
Tax (15%):                3.23
- - - - - - - - - - - - - - -
TOTAL:                   24.73
------------------------------------------------
  Thank you for your purchase!
        شكرا لزيارتكم

        [QR CODE]

       ||||| BARCODE |||||
         001234

Simple Receipt (minimal) #

For a quick receipt without store info:

final cmd = EscPosCommands(PaperSize.mm80);
cmd.initialize();

SimpleReceipt.print(
  cmd,
  title: 'RECEIPT',
  items: [
    ReceiptItem(name: 'Item A', quantity: 2, price: 10.0),
    ReceiptItem(name: 'Item B', quantity: 1, price: 25.0),
  ],
  cutAfter: true,
);

await printer.sendBytes(cmd.getBytes());

Custom Receipt (build your own) #

You can build any layout using the low-level commands:

final cmd = EscPosCommands(PaperSize.mm80);
cmd.initialize();
cmd.setCodePage(CodePage.win1256);

// Header
cmd.textStyled('INVOICE',
    PosStyles(align: PrintAlign.center, bold: true, width: 2, height: 2),
    useLatin: true);
cmd.textStyled('My Company LLC',
    PosStyles(align: PrintAlign.center),
    useLatin: true);
cmd.hr(style: LineStyle.doubleLine);

// Items
cmd.row([
  PosColumn(text: 'Description', width: 6),
  PosColumn(text: 'Qty', width: 2, align: PrintAlign.center),
  PosColumn(text: 'Amount', width: 4, align: PrintAlign.right),
], useLatin: true);
cmd.hr(style: LineStyle.dashed);

cmd.row([
  PosColumn(text: 'Laptop', width: 6),
  PosColumn(text: '1', width: 2, align: PrintAlign.center),
  PosColumn(text: '999.00', width: 4, align: PrintAlign.right),
], useLatin: true);

cmd.hr(style: LineStyle.doubleLine);

// Total
cmd.setBold(true);
cmd.setFontSize(2, 1);
cmd.leftRight('TOTAL:', '\$999.00', useLatin: true);
cmd.resetStyles();

// Arabic footer
cmd.setAlign(PrintAlign.center);
cmd.textLn('شكرا لك');
cmd.setAlign(PrintAlign.left);

// QR code
cmd.printQrCode('https://mycompany.com/inv/12345', size: 5);

cmd.feedAndCut();
await printer.sendBytes(cmd.getBytes());

15. Paper Cut, Cash Drawer & Beep #

Paper Cut #

cmd.cut();                            // Full cut
cmd.cut(mode: CutMode.partial);      // Partial cut (leaves a small strip)
cmd.feedAndCut();                     // Feed 3 lines + full cut
cmd.feedAndCut(lines: 5, mode: CutMode.partial);  // Custom

Cash Drawer #

cmd.openDrawer();                      // Open via pin 2 (default)
cmd.openDrawer(pin: DrawerPin.pin5);   // Open via pin 5

Beep #

cmd.beep();                            // Single beep
cmd.beep(count: 3, duration: 5);       // 3 beeps, each 5 units long

Paper Feed #

cmd.feed(1);     // Feed 1 line
cmd.feed(5);     // Feed 5 lines
cmd.newLine();   // Single line feed

16. Full API Reference #

ThermalPrinterManager #

Method Description
ensureReady() One-call setup: permissions + Bluetooth enable
requestPermissions() Request Bluetooth permissions (shows system dialog)
checkPermissions() Check which permissions are granted
isBluetoothEnabled() Check if Bluetooth is turned on
enableBluetooth() Show system dialog to enable Bluetooth
getBondedDevices() Get list of already-paired Bluetooth devices
startScan() Start discovering nearby Bluetooth devices
stopScan() Stop scanning
connect(address) Connect to a printer by MAC address
connectWithRetry(address) Connect with automatic retry on failure
disconnect() Disconnect from current printer
sendBytes(Uint8List) Send raw bytes to the printer
checkConnected() Check if still connected
setProtocol(String) Set MFi protocol string (iOS only)
scanResults Stream of discovered devices
connectionState Stream of connection state changes
isConnected Current connection status
dispose() Release resources

EscPosCommands #

Method Description
initialize() Reset printer to defaults (ESC @)
resetStyles() Reset text formatting only
setCodePage(CodePage) Set code page from preset
setCodePageRaw(int) Set code page by raw number
setCodePageFromString(String) Parse code page from string
setCharSet(CharSet) Set international character set
setBold(bool) Bold on/off
setUnderline(int) 0=off, 1=single, 2=double
setFontSize(w, h) Size multiplier 1-8
setAlign(PrintAlign) Left, center, right
setFont(FontType) Font A or B
setReverse(bool) White on black
setUpsideDown(bool) Upside down text
setLineSpacing(int) Line spacing in dots
resetLineSpacing() Reset to default spacing
setCharSpacing(int) Character spacing in dots
setDensity(int) Print darkness 0-15
text(String) Print text (no line feed)
textLn(String) Print text + line feed
textStyled(String, PosStyles) Print with styles (auto-resets)
newLine() Print blank line
writeRaw(String) Write raw code units
rawBytes(Uint8List) Write raw bytes
row(List<PosColumn>) Multi-column row
leftRight(left, right) Left-right aligned text
hr() Horizontal line
feed(int) Feed n lines
cut() Cut paper
feedAndCut() Feed + cut
openDrawer() Open cash drawer
beep() Buzzer beep
printImage(Uint8List) Print image
printRasterImage(...) Print pre-processed image
printQrCode(String) Print QR code
printBarcode(String, BarcodeType) Print barcode
getBytes() Get buffered bytes + clear
peekBytes() Get bytes without clearing
clear() Clear buffer

PaperSize #

Size Font A Chars Font B Chars Max Dot Width
PaperSize.mm58 32 42 384
PaperSize.mm72 42 56 512
PaperSize.mm80 48 64 576
PaperSize.mm110 66 88 832

17. Distribution Guide #

How to Share This Package #

Option 1: Share the Folder (simplest)

  1. Copy the thermal_printer_billbay/ folder to anyone who needs it
  2. They put it next to their app folder
  3. They add to their pubspec.yaml:
    dependencies:
      thermal_printer_billbay:
        path: ../thermal_printer_billbay
    
  4. Run flutter pub get

Step 1: Create a GitHub repo

  1. Go to https://github.com/new
  2. Name it thermal_printer_billbay
  3. Set it to Public or Private
  4. Do NOT add a README (we already have one)

Step 2: Push your code

Open a terminal in the thermal_printer_billbay/ folder:

cd thermal_printer_billbay
git init
git add .
git commit -m "Initial release v1.0.0"
git branch -M main
git remote add origin https://github.com/YOUR_USERNAME/thermal_printer_billbay.git
git push -u origin main

Step 3: Create a version tag (optional but recommended)

git tag v1.0.0
git push origin v1.0.0

Step 4: Others can now use it

# In their pubspec.yaml
dependencies:
  thermal_printer_billbay:
    git:
      url: https://github.com/YOUR_USERNAME/thermal_printer_billbay.git
      ref: v1.0.0  # or 'main' for latest

Option 3: Publish to pub.dev (public packages)

Step 1: Prepare the package

  1. Open thermal_printer_billbay/pubspec.yaml
  2. Remove or change the publish_to: 'none' line
  3. Make sure name, description, and version are set
  4. Make sure this README.md exists and is complete

Step 2: Check the package

cd thermal_printer_billbay
dart pub publish --dry-run

Fix any issues it reports.

Step 3: Create a Google account (if you don't have one)

You need a Google account to publish to pub.dev.

Step 4: Publish

dart pub publish

This will open a browser for Google sign-in, then upload the package.

Step 5: Others can now use it

# In their pubspec.yaml
dependencies:
  thermal_printer_billbay: ^1.0.0

Troubleshooting #

"Arabic prints as Chinese/garbage characters" #

Your printer is using the wrong code page. Print a self-test page (hold FEED button while powering on) and find the Arabic code page number. Then use that number:

cmd.setCodePageRaw(YOUR_NUMBER_HERE);

"Cannot find printer" #

  • Make sure Bluetooth is turned on
  • Make sure the printer is powered on and in pairing mode
  • On Android, grant all Bluetooth and Location permissions
  • Try pairing the printer first in your phone's Bluetooth settings

"Connection failed" #

  • Make sure no other app is connected to the printer
  • Turn the printer off and on
  • Remove the pairing and re-pair in Bluetooth settings

"Arabic letters are not joined" #

The plugin automatically shapes Arabic text. Make sure you're NOT using useLatin: true for Arabic text:

// WRONG — Arabic won't be shaped
cmd.textLn('مرحبا', useLatin: true);

// CORRECT — Arabic will be shaped automatically
cmd.textLn('مرحبا');

"Image is too dark/light" #

Adjust the threshold value (0=all black, 255=all white):

cmd.printImage(imageBytes, threshold: 100); // Darker
cmd.printImage(imageBytes, threshold: 180); // Lighter

License #

This package is provided as-is for free use. Modify and distribute as needed.

1
likes
0
points
112
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter plugin for ESC/POS thermal printers via Bluetooth Classic (SPP). Supports Arabic shaping, multiple code pages, receipt templates, images, QR codes, barcodes, and all standard ESC/POS commands.

Repository (GitLab)
View/report issues

Topics

#printer #bluetooth #thermal-printer #escpos

License

unknown (license)

Dependencies

flutter, image

More

Packages that depend on thermal_printer_billbay

Packages that implement thermal_printer_billbay