Commit 49cbee0b authored by Andrey's avatar Andrey

Removed PosString class. Added PosStyles class. Added PosColumn class. Updated examples and readme.

parent c318078c
...@@ -2,13 +2,15 @@ ...@@ -2,13 +2,15 @@
The library allows to print receipts using a ESC/POS (usually thermal) network printer. The library allows to print receipts using a ESC/POS (usually thermal) network printer.
It can be used in [Flutter](https://flutter.dev/) or [Dart](https://dart.dev/) projects. In Flutter, both Android and iOS are supported.
[[pub.dev page]](https://pub.dev/packages/esc_pos_printer) [[pub.dev page]](https://pub.dev/packages/esc_pos_printer)
| [[Documentation]](https://pub.dev/documentation/esc_pos_printer/latest/) | [[Documentation]](https://pub.dev/documentation/esc_pos_printer/latest/)
It can be used in [Flutter](https://flutter.dev/) or [Dart](https://dart.dev/) projects. In Flutter, both Android and iOS are supported.
To discover existing printers in your subnet, consider using [ping_discover_network](https://pub.dev/packages/ping_discover_network) package. Note that most of ESC/POS printers by default listen on port 9100. To discover existing printers in your subnet, consider using [ping_discover_network](https://pub.dev/packages/ping_discover_network) package. Note that most of ESC/POS printers by default listen on port 9100.
USB and Bluetooth printers support will be added later.
## Features ## Features
* Connect to Wi-Fi printers * Connect to Wi-Fi printers
...@@ -20,39 +22,64 @@ To discover existing printers in your subnet, consider using [ping_discover_netw ...@@ -20,39 +22,64 @@ To discover existing printers in your subnet, consider using [ping_discover_netw
* Beeping (with different duration) * Beeping (with different duration)
* Paper feed, reverse feed * Paper feed, reverse feed
**Note**: Your printer may not support some of the presented features (especially for underline styles, partial/full paper cutting, reverse feed, ...). **Note**: Your printer may not support some of presented features (especially for underline styles, partial/full paper cutting, reverse feed, ...).
## Getting Started ## Getting Started
```dart ```dart
import 'package:esc_pos_printer/esc_pos_printer.dart'; import 'package:esc_pos_printer/esc_pos_printer.dart';
Printer.connect('192.168.0.123').then((printer) { Printer.connect('192.168.0.123', port: 9100).then((printer) {
printer.println(PosString('Normal text')); printer.println('Normal text');
printer.println(PosString('Bold text', bold: true)); printer.println('Bold text', styles: PosStyles(bold: true));
printer.println(PosString('Reverse text', reverse: true)); printer.println('Reverse text', styles: PosStyles(reverse: true));
printer.println(PosString('Underlined text', underline: true)); printer.println('Underlined text',
printer.println(PosString('Align center', align: PosTextAlign.center)); styles: PosStyles(underline: true), linesAfter: 1);
printer.printRow([3, 6, 3], printer.println('Align left', styles: PosStyles(align: PosTextAlign.left));
[ printer.println('Align center',
PosString('col3'), styles: PosStyles(align: PosTextAlign.center));
PosString('col6'), printer.println('Align right',
PosString('col3', underline: true) styles: PosStyles(align: PosTextAlign.right), linesAfter: 1);
],
); printer.println('Text size 200%',
printer.println(PosString('Text size 200%', styles: PosStyles(
height: PosTextSize.size2, width: PosTextSize.size2)); height: PosTextSize.size2,
width: PosTextSize.size2,
));
printer.cut(); printer.cut();
printer.disconnect(); printer.disconnect();
}); });
``` ```
Print table:
```dart
printer.printRow([
PosColumn(
text: 'col3',
width: 3,
styles: PosStyles(align: PosTextAlign.center, underline: true),
),
PosColumn(
text: 'col6',
width: 6,
styles: PosStyles(align: PosTextAlign.center, underline: true),
),
PosColumn(
text: 'col3',
width: 3,
styles: PosStyles(align: PosTextAlign.center, underline: true),
),
]);
```
## TODO ## TODO
* Add raw print function * Add raw print function
* Print images * Print images
* Print barcodes * Print barcodes
* Print QR codes * Print QR codes
* Example project for Flutter (print a receipt template)
* Turn 90° clockwise rotation mode on/off * Turn 90° clockwise rotation mode on/off
* Discover active Wi-Fi printers * Flutter example: print a demo receipt
\ No newline at end of file * Flutter example: discover active Wi-Fi printers
* USB, Bluetooth printers support
\ No newline at end of file
import 'package:esc_pos_printer/esc_pos_printer.dart'; import 'package:esc_pos_printer/esc_pos_printer.dart';
import 'package:esc_pos_printer/src/pos_column.dart';
void main() { void main() {
Printer.connect('192.168.0.123').then((printer) { // To discover existing printers in your subnet, consider using
printer.println(PosString('Normal text')); // ping_discover_network package (https://pub.dev/packages/ping_discover_network).
printer.println(PosString('Bold text', bold: true)); // Note that most of ESC/POS printers by default listen on port 9100.
printer.println(PosString('Reverse text', reverse: true)); Printer.connect('192.168.0.123', port: 9100).then((printer) {
printer.println(PosString('Underlined text', underline: true), printer.println('Normal text');
linesAfter: 1); printer.println('Bold text', styles: PosStyles(bold: true));
printer.println(PosString('Align left', align: PosTextAlign.left)); printer.println('Reverse text', styles: PosStyles(reverse: true));
printer.println(PosString('Align center', align: PosTextAlign.center)); printer.println('Underlined text',
printer.println(PosString('Align right', align: PosTextAlign.right), styles: PosStyles(underline: true), linesAfter: 1);
linesAfter: 1); printer.println('Align left', styles: PosStyles(align: PosTextAlign.left));
printer.printRow( printer.println('Align center',
[3, 6, 3], styles: PosStyles(align: PosTextAlign.center));
[ printer.println('Align right',
PosString('col3', align: PosTextAlign.center, underline: true), styles: PosStyles(align: PosTextAlign.right), linesAfter: 1);
PosString('col6', align: PosTextAlign.center, underline: true), printer.printRow([
PosString('col3', align: PosTextAlign.center, underline: true) PosColumn(
], text: 'col3',
); width: 3,
printer.println(PosString('Text size 200%', styles: PosStyles(align: PosTextAlign.center, underline: true),
height: PosTextSize.size2, width: PosTextSize.size2)); ),
PosColumn(
text: 'col6',
width: 6,
styles: PosStyles(align: PosTextAlign.center, underline: true),
),
PosColumn(
text: 'col3',
width: 3,
styles: PosStyles(align: PosTextAlign.center, underline: true),
),
]);
printer.println('Text size 200%',
styles: PosStyles(
height: PosTextSize.size2,
width: PosTextSize.size2,
));
printer.cut(); printer.cut();
printer.disconnect(); printer.disconnect();
......
...@@ -8,5 +8,5 @@ library esc_pos_printer; ...@@ -8,5 +8,5 @@ library esc_pos_printer;
export './src/enums.dart'; export './src/enums.dart';
export './src/exceptions.dart'; export './src/exceptions.dart';
export './src/pos_string.dart'; export './src/pos_styles.dart';
export './src/printer.dart'; export './src/printer.dart';
/*
* esc_pos_printer
* Created by Andrey Ushakov
*
* Copyright (c) 2019. All rights reserved.
* See LICENSE for distribution and usage details.
*/
import 'pos_styles.dart';
/// Column contains text, styles and width (an integer in 1..12 range)
class PosColumn {
PosColumn({
this.text = '',
this.width = 2,
this.styles = const PosStyles(),
}) : assert(width >= 1 && width <= 12);
String text;
int width;
PosStyles styles;
}
...@@ -8,10 +8,9 @@ ...@@ -8,10 +8,9 @@
import 'enums.dart'; import 'enums.dart';
/// A string with styles /// Text styles
class PosString { class PosStyles {
PosString( const PosStyles({
this.text, {
this.bold = false, this.bold = false,
this.reverse = false, this.reverse = false,
this.underline = false, this.underline = false,
...@@ -21,17 +20,11 @@ class PosString { ...@@ -21,17 +20,11 @@ class PosString {
this.fontType = PosFontType.fontA, this.fontType = PosFontType.fontA,
}); });
String text; final bool bold;
bool bold = false; final bool reverse;
bool reverse = false; final bool underline;
bool underline = false; final PosTextAlign align;
PosTextAlign align = PosTextAlign.left; final PosTextSize height;
PosTextSize height = PosTextSize.size1; final PosTextSize width;
PosTextSize width = PosTextSize.size1; final PosFontType fontType;
PosFontType fontType = PosFontType.fontA;
@override
String toString() {
return text;
}
} }
...@@ -8,11 +8,14 @@ ...@@ -8,11 +8,14 @@
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
// import 'package:esc_pos_printer/esc_pos_printer.dart';
import 'package:hex/hex.dart'; import 'package:hex/hex.dart';
import 'commands.dart'; import 'commands.dart';
import 'enums.dart'; import 'enums.dart';
import 'exceptions.dart'; import 'exceptions.dart';
import 'pos_string.dart'; import 'pos_column.dart';
import 'pos_styles.dart';
/// Network printer /// Network printer
class Printer { class Printer {
...@@ -26,8 +29,11 @@ class Printer { ...@@ -26,8 +29,11 @@ class Printer {
/// ///
/// The argument [timeout] is used to specify the maximum allowed time to wait /// The argument [timeout] is used to specify the maximum allowed time to wait
/// for a connection to be established. /// for a connection to be established.
static Future<Printer> connect(String host, static Future<Printer> connect(
{int port = 9100, Duration timeout}) { String host, {
int port = 9100,
Duration timeout,
}) {
return Socket.connect(host, port, timeout: timeout).then((socket) { return Socket.connect(host, port, timeout: timeout).then((socket) {
return Printer._internal(socket); return Printer._internal(socket);
}); });
...@@ -41,24 +47,29 @@ class Printer { ...@@ -41,24 +47,29 @@ class Printer {
/// Generic print for internal use /// Generic print for internal use
/// ///
/// [colInd] range: 0..11 /// [colInd] range: 0..11
void _print(PosString data, {int colInd = 0, int linesAfter = 0}) { void _print(
String text, {
PosStyles styles,
int colInd = 0,
int linesAfter = 0,
}) {
final int pos = colInd == 0 ? 0 : (512 * colInd / 11 - 1).round(); final int pos = colInd == 0 ? 0 : (512 * colInd / 11 - 1).round();
final hexStr = pos.toRadixString(16).padLeft(3, '0'); final hexStr = pos.toRadixString(16).padLeft(3, '0');
final hexPair = HEX.decode(hexStr); final hexPair = HEX.decode(hexStr);
// print('dec: $pos \t hex: $hexStr \t pair $hexPair'); // print('dec: $pos \t hex: $hexStr \t pair $hexPair');
_socket.write(data.bold ? cBoldOn : cBoldOff); _socket.write(styles.bold ? cBoldOn : cBoldOff);
_socket.write(data.reverse ? cReverseOn : cReverseOff); _socket.write(styles.reverse ? cReverseOn : cReverseOff);
_socket.write(data.underline ? cUnderline1dot : cUnderlineOff); _socket.write(styles.underline ? cUnderline1dot : cUnderlineOff);
_socket.write(data.align == PosTextAlign.left _socket.write(styles.align == PosTextAlign.left
? cAlignLeft ? cAlignLeft
: (data.align == PosTextAlign.center ? cAlignCenter : cAlignRight)); : (styles.align == PosTextAlign.center ? cAlignCenter : cAlignRight));
_socket.write(data.fontType == PosFontType.fontA ? cFontA : cFontB); _socket.write(styles.fontType == PosFontType.fontA ? cFontA : cFontB);
// Text size // Text size
_socket.add( _socket.add(
Uint8List.fromList( Uint8List.fromList(
List.from(cSizeGSn.codeUnits) List.from(cSizeGSn.codeUnits)
..add(PosTextSize.decSize(data.height, data.width)), ..add(PosTextSize.decSize(styles.height, styles.width)),
), ),
); );
// Position // Position
...@@ -68,12 +79,12 @@ class Printer { ...@@ -68,12 +79,12 @@ class Printer {
), ),
); );
_socket.write(data.text); _socket.write(text);
} }
/// Prints one line of styled text /// Prints one line of styled text
void println(PosString data, {int linesAfter = 0}) { void println(String text, {PosStyles styles, int linesAfter = 0}) {
_print(data, linesAfter: linesAfter); _print(text, styles: styles, linesAfter: linesAfter);
_socket.writeln(); _socket.writeln();
emptyLines(linesAfter); emptyLines(linesAfter);
reset(); reset();
...@@ -83,35 +94,16 @@ class Printer { ...@@ -83,35 +94,16 @@ class Printer {
/// ///
/// A row contains up to 12 columns. A column has a width between 1 and 12. /// A row contains up to 12 columns. A column has a width between 1 and 12.
/// Total width of columns in one row must be equal 12. /// Total width of columns in one row must be equal 12.
/// void printRow(List<PosColumn> cols) {
/// [cols] parameter is used to define the row structure (each integer value is one column width). final validSum = cols.fold(0, (int sum, col) => sum + col.width) == 12;
/// [data] parameter is used to define the column data (text, align inside of the column and styles).
/// Column data is represented by [PosString] class.
///
/// ```dart
/// printer.printRow(
/// [3, 6, 3],
/// [ PosString('col3'),
/// PosString('col6'),
/// PosString('col3') ],
/// );
/// ```
void printRow(List<int> cols, List<PosString> data) {
final validRange = cols.every((val) => val >= 1 && val <= 12);
if (!validRange) {
throw PosRowException('Column width should be between 1..12');
}
final validSum = cols.fold(0, (int sum, cur) => sum + cur) == 12;
if (!validSum) { if (!validSum) {
throw PosRowException('Total columns width must be equal 12'); throw PosRowException('Total columns width must be equal to 12');
}
if (cols.length != data.length) {
throw PosRowException("Columns number doesn't equal to data number");
} }
for (int i = 0; i < cols.length; ++i) { for (int i = 0; i < cols.length; ++i) {
final colInd = cols.sublist(0, i).fold(0, (int sum, cur) => sum + cur); final colInd =
_print(data[i], colInd: colInd); cols.sublist(0, i).fold(0, (int sum, col) => sum + col.width);
_print(cols[i].text, colInd: colInd);
} }
_socket.writeln(); _socket.writeln();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment