import 'dart:convert'; import 'dart:typed_data'; import 'package:charset_converter/charset_converter.dart'; import 'package:esc_pos_bluetooth/esc_pos_bluetooth.dart'; import 'package:esc_pos_utils/esc_pos_utils.dart'; import 'package:flutter/material.dart' hide Image; import 'package:image/image.dart' as Im; import 'package:flutter/services.dart'; import 'package:intl/intl.dart'; class PrinterSelectView extends StatefulWidget { PrinterSelectView({Key key, this.title}) : super(key: key); final String title; @override _PrinterSelectViewState createState() => _PrinterSelectViewState(); } class _PrinterSelectViewState extends State { PrinterBluetoothManager printerManager = PrinterBluetoothManager(); List _devices = []; @override void initState() { super.initState(); printerManager.scanResults.listen((devices) async { // print('UI: Devices found ${devices.length}'); setState(() { _devices = devices; }); }); } void _startScanDevices() { setState(() { _devices = []; }); printerManager.startScan(Duration(seconds: 4)); } void _stopScanDevices() { printerManager.stopScan(); } Future demoReceipt(PaperSize paper) async { final Ticket ticket = Ticket(paper, ); // Print image final ByteData data = await rootBundle.load('assets/images/aman_kassa_check.png'); final Uint8List bytes = data.buffer.asUint8List(); final Im.Image image = Im.decodeImage(bytes); Im.Image thumbnail = Im.copyResize(image, width: 270); // ticket.image(thumbnail, align: PosAlign.center); //ticket.imageRaster(image, align: PosAlign.center); ticket.text('AMAN-SATU', styles: PosStyles( align: PosAlign.center, height: PosTextSize.size2, width: PosTextSize.size2, ), linesAfter: 1); ticket.text('889 Watson Lane', styles: PosStyles(align: PosAlign.center)); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, codeTable: PosCodeTable.westEur), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontA), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, fontType: PosFontType.fontB), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, height: PosTextSize.size1), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size2), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size3), containsChinese: true); ticket.text('Русский язык', styles: PosStyles(align: PosAlign.center, width: PosTextSize.size4), containsChinese: true); ticket.text('Tel: 830-221-1234', styles: PosStyles(align: PosAlign.center)); ticket.text('Web: www.example.com', styles: PosStyles(align: PosAlign.center), linesAfter: 1); ticket.hr(); ticket.row([ PosColumn(text: 'Qty', width: 1), PosColumn(text: 'Item', width: 7), PosColumn( text: 'Price', width: 2, styles: PosStyles(align: PosAlign.right)), PosColumn( text: 'Total', width: 2, styles: PosStyles(align: PosAlign.right)), ]); ticket.row([ PosColumn(text: '2', width: 1), PosColumn(text: 'ONION RINGS', width: 7), PosColumn( text: '0.99', width: 2, styles: PosStyles(align: PosAlign.right)), PosColumn( text: '1.98', width: 2, styles: PosStyles(align: PosAlign.right)), ]); ticket.row([ PosColumn(text: '1', width: 1), PosColumn(text: 'PIZZA', width: 7), PosColumn( text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)), PosColumn( text: '3.45', width: 2, styles: PosStyles(align: PosAlign.right)), ]); ticket.row([ PosColumn(text: '1', width: 1), PosColumn(text: 'SPRING ROLLS', width: 7), PosColumn( text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)), PosColumn( text: '2.99', width: 2, styles: PosStyles(align: PosAlign.right)), ]); ticket.row([ PosColumn(text: '3', width: 1), PosColumn(text: 'CRUNCHY STICKS', width: 7), PosColumn( text: '0.85', width: 2, styles: PosStyles(align: PosAlign.right)), PosColumn( text: '2.55', width: 2, styles: PosStyles(align: PosAlign.right)), ]); ticket.hr(); ticket.row([ PosColumn( text: 'TOTAL', width: 6, styles: PosStyles( height: PosTextSize.size2, width: PosTextSize.size2, )), PosColumn( text: '\$10.97', width: 6, styles: PosStyles( align: PosAlign.right, height: PosTextSize.size2, width: PosTextSize.size2, )), ]); ticket.hr(ch: '=', linesAfter: 1); ticket.row([ PosColumn( text: 'Cash', width: 7, styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), PosColumn( text: '\$15.00', width: 5, styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), ]); ticket.row([ PosColumn( text: 'Change', width: 7, styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), PosColumn( text: '\$4.03', width: 5, styles: PosStyles(align: PosAlign.right, width: PosTextSize.size2)), ]); ticket.feed(2); ticket.text('Thank you!', styles: PosStyles(align: PosAlign.center, bold: true)); final now = DateTime.now(); final formatter = DateFormat('MM/dd/yyyy H:m'); final String timestamp = formatter.format(now); ticket.text(timestamp, styles: PosStyles(align: PosAlign.center), linesAfter: 2); // Print QR Code from image // try { // const String qrData = 'example.com'; // const double qrSize = 200; // 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()); // ticket.image(img); // } catch (e) { // print(e); // } // Print QR Code using native function // ticket.qrcode('example.com'); ticket.feed(2); ticket.cut(); return ticket; } Future testTicket(PaperSize paper) async { final Ticket ticket = Ticket(paper); Uint8List encTxt4 = await CharsetConverter.encode("cp866", "Russian: Привет Мир!"); ticket.textEncoded(encTxt4, styles: PosStyles(codeTable: PosCodeTable.pc866_2)); ticket.text('Kazakh: Сәлем Әлем!', styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true); // Uint8List encTxt1 = // await CharsetConverter.encode("utf-8", "Kazakh: Сәлем Әлем!"); // ticket.textEncoded(encTxt1, // styles: PosStyles(codeTable: PosCodeTable.pc866_2)); 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.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), ), ]); ticket.text('Text size 200%', styles: PosStyles( height: PosTextSize.size2, width: PosTextSize.size2, )); // Print image //final ByteData data = await rootBundle.load('assets/images/logo.png'); //final Uint8List bytes = data.buffer.asUint8List(); // Print image using alternative commands // ticket.imageRaster(image); // ticket.imageRaster(image, imageFn: PosImageFn.graphics); // Print barcode final List barData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 4]; ticket.barcode(Barcode.upcA(barData)); // Print mixed (chinese + latin) text. Only for printers supporting Kanji mode ticket.text( 'hello ! 中文字 # world @ éphémère &', styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true, ); ticket.text( 'hello ! Мир # world @ éphémère &', styles: PosStyles(codeTable: PosCodeTable.westEur), containsChinese: true, ); ticket.feed(2); ticket.cut(); return ticket; } void _testPrint(PrinterBluetooth printer) async { printerManager.selectPrinter(printer); // TODO Don't forget to choose printer's paper const PaperSize paper = PaperSize.mm58; // TEST PRINT // final PosPrintResult res = // await printerManager.printTicket(await testTicket(paper)); // DEMO RECEIPT final PosPrintResult res = await printerManager.printTicket(await testTicket(paper) , queueSleepTimeMs: 50); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: ListView.builder( itemCount: _devices.length, itemBuilder: (BuildContext context, int index) { return InkWell( onTap: () => _testPrint(_devices[index]), child: Column( children: [ Container( height: 60, padding: EdgeInsets.only(left: 10), alignment: Alignment.centerLeft, child: Row( children: [ Icon(Icons.print), SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text(_devices[index].name ?? ''), Text(_devices[index].address), Text( 'Click to print a test receipt', style: TextStyle(color: Colors.grey[700]), ), ], ), ) ], ), ), Divider(), ], ), ); }), floatingActionButton: StreamBuilder( stream: printerManager.isScanningStream, initialData: false, builder: (c, snapshot) { if (snapshot.data) { return FloatingActionButton( child: Icon(Icons.stop), onPressed: _stopScanDevices, backgroundColor: Colors.red, ); } else { return FloatingActionButton( child: Icon(Icons.search), onPressed: _startScanDevices, ); } }, ), ); } }