Incredible Flutter Library to allows to Print Receipts using a Bluetooth printer
Contents
Introduction
A library is a collection of subprograms that are utilized in the development of software. Libraries contain supplementary code and data that provide stand-alone program services, allowing for modular code and data sharing and modification.
A collection of procedures is referred to as a library in a programming language (set of programming instructions). Dart comes with a collection of built-in libraries for storing frequently used functions. Classes, constants, functions, typedefs, properties, and exceptions are all part of a Dart library.
esc_pos_bluetooth
The library allows to print receipts using a Bluetooth printer. For WiFi/Ethernet printers, use esc_pos_printer library.
Tested Printers
Here are some printers tested with this library. Please add the models you have tested to maintain and improve this library and help others to choose the right printer.
Generate a Ticket
1. Simple Ticket with Styles:
Ticket testTicket() { final Ticket ticket = Ticket(PaperSize.mm80); ticket.text( 'Regular: aA bB cC dD eE fF gG hH iI jJ kK lL mM nN oO pP qQ rR sS tT uU vV wW xX yY zZ'); ticket.text('Special 1: àÀ èÈ éÉ ûÛ üÜ çÇ ôÔ', styles: PosStyles(codeTable: PosCodeTable.westEur)); ticket.text('Special 2: blåbærgrød', styles: PosStyles(codeTable: PosCodeTable.westEur)); ticket.text('Bold text', styles: PosStyles(bold: true)); ticket.text('Reverse text', styles: PosStyles(reverse: true)); ticket.text('Underlined text', styles: PosStyles(underline: true), linesAfter: 1); ticket.text('Align left', styles: PosStyles(align: PosAlign.left)); ticket.text('Align center', styles: PosStyles(align: PosAlign.center)); ticket.text('Align right', styles: PosStyles(align: PosAlign.right), linesAfter: 1); ticket.text('Text size 200%', styles: PosStyles( height: PosTextSize.size2, width: PosTextSize.size2, )); ticket.feed(2); ticket.cut(); return ticket; }
1.1 Simple ticket with styles:
List<int> testTicket() { final List<int> bytes = []; // Using default profile final profile = await CapabilityProfile.load(); final generator = Generator(PaperSize.mm80, profile); List<int> bytes = []; bytes += generator.text( 'Regular: aA bB cC dD eE fF gG hH iI jJ kK lL mM nN oO pP qQ rR sS tT uU vV wW xX yY zZ'); bytes += generator.text('Special 1: àÀ èÈ éÉ ûÛ üÜ çÇ ôÔ', styles: PosStyles(codeTable: PosCodeTable.westEur)); bytes += generator.text('Special 2: blåbærgrød', styles: PosStyles(codeTable: PosCodeTable.westEur)); bytes += generator.text('Bold text', styles: PosStyles(bold: true)); bytes += generator.text('Reverse text', styles: PosStyles(reverse: true)); bytes += generator.text('Underlined text', styles: PosStyles(underline: true), linesAfter: 1); bytes += generator.text('Align left', styles: PosStyles(align: PosAlign.left)); bytes += generator.text('Align center', styles: PosStyles(align: PosAlign.center)); bytes += generator.text('Align right', styles: PosStyles(align: PosAlign.right), linesAfter: 1); bytes += generator.text('Text size 200%', styles: PosStyles( height: PosTextSize.size2, width: PosTextSize.size2, )); bytes += generator.feed(2); bytes += generator.cut(); return bytes; }
Print a table row:
generator.row([ PosColumn( text: 'col3', width: 3, styles: PosStyles(align: PosAlign.center, underline: true), ), PosColumn( text: 'col6', width: 6, styles: PosStyles(align: PosAlign.center, underline: true), ), PosColumn( text: 'col3', width: 3, styles: PosStyles(align: PosAlign.center, underline: true), ), ]);
Print an image:
This package implements 3 ESC/POS functions:
ESC *
– print in column formatGS v 0
– print in bit raster format (obsolete)GS ( L
– print in bit raster format
Note that your printer may support only some of the above functions.
import 'dart:io'; import 'package:image/image.dart'; final ByteData data = await rootBundle.load('assets/logo.png'); final Uint8List bytes = data.buffer.asUint8List(); final Image image = decodeImage(bytes); // Using `ESC *` generator.image(image); // Using `GS v 0` (obsolete) generator.imageRaster(image); // Using `GS ( L` generator.imageRaster(image, imageFn: PosImageFn.graphics);
Print a Barcode:
final List<int> barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4]; generator.barcode(Barcode.upcA(barData));
Print a QR Code:
Using native ESC/POS commands:
generator.qrcode('example.com');
To print a QR Code as an image (if your printer doesn’t support native commands), add qr_flutter and path_provider as a dependency in your pubspec.yaml
file.
String qrData = "google.com"; const double qrSize = 200; try { final uiImg = await QrPainter( data: qrData, version: QrVersions.auto, gapless: false, ).toImageData(qrSize); final dir = await getTemporaryDirectory(); final pathName = '${dir.path}/qr_tmp.png'; final qrFile = File(pathName); final imgFile = await qrFile.writeAsBytes(uiImg.buffer.asUint8List()); final img = decodeImage(imgFile.readAsBytesSync()); generator.image(img); } catch (e) { print(e); }
Using Code Tables
Different printers support different sets of code tables. Some printer models are defined in CapabilityProfile
class. So, if you want to change the default code table, it’s important to choose the right profile:
// Xprinter XP-N160I final profile = await CapabilityProfile.load('XP-N160I'); final generator = Generator(PaperSize.mm80, profile); bytes += generator.setGlobalCodeTable('CP1252');
All available profiles can be retrieved by calling :
final profiles = await CapabilityProfile.getAvailableProfiles();
Print a Ticket
PrinterBluetoothManager printerManager = PrinterBluetoothManager(); printerManager.scanResults.listen((printers) async { // store found printers }); printerManager.startScan(Duration(seconds: 4)); // ... printerManager.selectPrinter(printer); final PosPrintResult res = await printerManager.printTicket(testTicket()); print('Print result: ${res.msg}');
For a complete example, check the demo project example/blue.
Troubleshooting
- If your printer prints only 5%-10% of an image and then stops, or it can’t print more than 1 image on the same ticket, or it can’t print long tickets, try to ajust
queueSleepTimeMs
of thePrinterBluetoothManager.printTicket
(try 50 or 100ms):printerManager.printTicket(await demoReceipt(paper), queueSleepTimeMs: 50);
Test Print (Demo)
TODO (PRs are welcomed!)
- Split byte data into chunks: issue
- Print QR Codes using the
GS ( k
command (printing QR code from an image already supported) - PDF-417 Barcodes using the
GS ( k
command - Line spacing using the
ESC 3 <n>
command
How to Help
- Test your printer and add it in the table: Wifi/Network printer or Bluetooth printer
- Test and report bugs
- Share your ideas about what could be improved (code optimization, new features…)
- PRs are welcomed!
- Add a CapabilityProfile to support your printer’s model. A new profile should be added to
lib/resources/capabilities.json
file - Test your printer and add it in the table: Wifi/Network printer or Bluetooth printer
- Test and report bugs
- Share your ideas about what could be improved (code optimization, new features…)
GitHub
Soruce Code: esc_pos_bluetooth and esc_pos_utils.