escpos 0.8.2

ESC/POS printer driver
Documentation
# ESC/POS Rust implementation

[![Build status](https://github.com/fabienbellanger/escpos-rs/actions/workflows/CI.yml/badge.svg?branch=main)](https://github.com/fabienbellanger/escpos-rs/actions/workflows/CI.yml)
[![Crates.io](https://img.shields.io/crates/v/escpos)](https://crates.io/crates/escpos)
[![Documentation](https://docs.rs/escpos/badge.svg)](https://docs.rs/escpos)

This crate implements a subset of Epson's ESC/POS protocol for thermal receipt printers.
It allows you to generate and print documents with basic text formatting, cutting, barcodes, QR codes and raster images
on a compatible printer.

![Ticket](resources/documentation/ticket.jpg) ![Receipt](resources/documentation/receipt.jpg)  
_Printed on Aures ODP 333_

This project is strongly inspired by [recibo](https://github.com/jamhall/recibo/tree/main) _(Rust)_,
[escposify](https://github.com/local-group/rust-escposify) _(Rust)_
and [escpos](https://github.com/hennedo/escpos) _(Go)_.

## Installation

For standard functionalities (e.g. printing text), no additional dependencies are required:

```toml
[dependencies]
escpos = "0.8.2"
```

If you need all [features](#Features-list), you can use the `full` feature:

```toml
[dependencies]
escpos = { version = "0.8.2", features = ["full"] }
```

Or you can use `cargo add` command:

```bash
cargo add escpos
cargo add escpos -F full
```

## Features list

| Name          | Description                                                            | Default |
|---------------|------------------------------------------------------------------------|:-------:|
| `barcodes`    | Print barcodes (UPC-A, UPC-E, EAN8, EAN13, CODE39, ITF or CODABAR)     ||
| `codes_2d`    | Print 2D codes (QR Code, PDF417, GS1 DataBar, DataMatrix, Aztec, etc.) ||
| `graphics`    | Print raster images                                                    ||
| `usb`         | Enable USB feature                                                     ||
| `hidapi`      | Enable HidApi feature                                                  ||
| `serial_port` | Enable Serial port feature                                             ||
| `full`        | Enable all features                                                    ||

## Examples

The `examples` folder contains various examples of how to use `escpos`.
The [docs](https://docs.rs/escpos) (will) also provide lots of code snippets and examples.

To launch an example, use the following command:

```shell
RUST_LOG=debug cargo run --example full --features "full"
RUST_LOG=debug cargo run --example receipt -F full
RUST_LOG=debug cargo run --example codes
RUST_LOG=debug cargo run --example debug
RUST_LOG=debug cargo run --example page_codes
RUST_LOG=debug cargo run --example usb --features "usb"
RUST_LOG=debug cargo run --example hidapi --features "hidapi"
RUST_LOG=debug cargo run --example serial_port --features "serial_port"
```

### Simple text formatting

```rust
use escpos::printer::Printer;
use escpos::utils::*;
use escpos::{driver::*, errors::Result};

fn main() -> Result<()> {
    env_logger::init();

    let driver = NetworkDriver::open("192.168.1.248", 9100)?;
    Printer::new(driver, Protocol::default(), None)
        .debug_mode(Some(DebugMode::Dec))
        .init()?
        .smoothing(true)?
        .bold(true)?
        .underline(UnderlineMode::Single)?
        .writeln("Bold underline")?
        .justify(JustifyMode::CENTER)?
        .reverse(true)?
        .bold(false)?
        .writeln("Hello world - Reverse")?
        .feed()?
        .justify(JustifyMode::RIGHT)?
        .reverse(false)?
        .underline(UnderlineMode::None)?
        .size(2, 3)?
        .writeln("Hello world - Normal")?
        .print_cut()?;

    Ok(())
}
```

### EAN13

```rust
use escpos::printer::Printer;
use escpos::utils::*;
use escpos::{driver::*, errors::Result};

fn main() -> Result<()> {
    env_logger::init();

    let driver = ConsoleDriver::open(true);
    Printer::new(driver, Protocol::default(), None)
        .debug_mode(Some(DebugMode::Hex))
        .init()?
        .ean13_option(
            "1234567890265",
            BarcodeOption::new(
                BarcodeWidth::M,
                BarcodeHeight::S,
                BarcodeFont::A,
                BarcodePosition::Below,
            )
        )?
        .feed()?
        .print_cut()?;

    Ok(())
}
```

### QR Code

```rust
use escpos::printer::Printer;
use escpos::utils::*;
use escpos::{driver::*, errors::Result};

fn main() -> Result<()> {
    env_logger::init();

    let driver = ConsoleDriver::open(true);
    Printer::new(driver, Protocol::default(), None)
        .debug_mode(Some(DebugMode::Hex))
        .init()?
        .qrcode_option(
            "https://www.google.com",
            QRCodeOption::new(QRCodeModel::Model1, 6, QRCodeCorrectionLevel::M),
        )?
        .feed()?
        .print_cut()?;

    Ok(())
}
```

### Bit image (with `graphics` feature enabled)

```rust
use escpos::printer::Printer;
use escpos::utils::*;
use escpos::{driver::*, errors::Result};

fn main() -> Result<()> {
    env_logger::init();

    let driver = ConsoleDriver::open(true);
    let mut printer = Printer::new(driver, Protocol::default(), None);
    printer.debug_mode(Some(DebugMode::Hex))
        .init()?
        .bit_image_option(
            "./resources/images/rust-logo-small.png",
            BitImageOption::new(Some(128), None, BitImageSize::Normal)?,
        )?
        .feed()?
        .print_cut()?;

    Ok(())
}
```

## Commands list

| Status | Command                         | Description                                           | Feature    |
|:------:|---------------------------------|-------------------------------------------------------|------------|
|| `init()`                        | Initialize printer (`ESC @`)                          |            |
|| `print()`                       | Print document                                        |            |
|| `reset()`                       | Hardware reset (`ESC ? LF 0`)                         |            |
|| `cut()`                         | Paper cut (`GS V A 0`)                                |            |
|| `partial_cut()`                 | Partial paper cut (`GS V A 1`)                        |            |
|| `print_cut()`                   | Print and paper cut                                   |            |
|| `page_code()`                   | Select character code table (`ESC t`)                 |            |
|| `character_set()`               | Select an international character set (`ESC R`)       |            |
|| `bold()`                        | Text bold (`ESC E`)                                   |            |
|| `underline()`                   | Text underline (`ESC -`)                              |            |
|| `double_strike()`               | Text double strike (`ESC G`)                          |            |
|| `font()`                        | Text font (`ESC M`)                                   |            |
|| `flip()`                        | Text flip (`ESC V`)                                   |            |
|| `justify()`                     | Text justify (`ESC a`)                                |            |
|| `reserve()`                     | Text reserve color (`GS B`)                           |            |
|| `size()`                        | Text size (`GS !`)                                    |            |
|| `reset_size()`                  | Reset text size (`GS !`)                              |            |
|| `smoothing()`                   | Smoothing mode (`GS b`)                               |            |
|| `feed()`                        | Line feed (`ESC d`)                                   |            |
|| `feeds()`                       | Multiple lines feed (`ESC d`)                         |            |
|| `line_spacing()`                | Line spacing (`ESC 3`)                                |            |
|| `reset_line_spacing()`          | Reset line spacing (`ESC 2`)                          |            |
|| `upside_down()`                 | Upside-down mode (`ESC {`)                            |            |
|| `cash_drawer()`                 | Generate pulse (`ESC p`)                              |            |
|| `write()`                       | Write text                                            |            |
|| `writeln()`                     | Write text and line feed                              |            |
|| `custom()`                      | Custom command                                        |            |
|| `custom_with_page_code()`       | Custom command with page code                         |            |
|| `motion_units()`                | Set horizontal and vertical motion units (`GS P`)     |            |
|| `ean13()`                       | Print EAN13 with default option                       | `barcode`  |
|| `ean13_option()`                | Print EAN13 with custom option                        | `barcode`  |
|| `ean8()`                        | Print EAN8 with default option                        | `barcode`  |
|| `ean8_option()`                 | Print EAN8 with custom option                         | `barcode`  |
|| `upca()`                        | Print UPC-A with default option                       | `barcode`  |
|| `upca_option()`                 | Print UPC-A with custom option                        | `barcode`  |
|| `upce()`                        | Print UPC-E with default option                       | `barcode`  |
|| `upce_option()`                 | Print UPC-E with custom option                        | `barcode`  |
|| `code39()`                      | Print CODE 39 with default option                     | `barcode`  |
|| `code39_option()`               | Print CODE 39 with custom option                      | `barcode`  |
|| `codabar()`                     | Print CODABAR with default option                     | `barcode`  |
|| `codabar_option()`              | Print CODABAR with custom option                      | `barcode`  |
|| `itf()`                         | Print ITF with default option                         | `barcode`  |
|| `itf_option()`                  | Print ITF with custom option                          | `barcode`  |
|| `qrcode()`                      | Print QR code with default option                     | `codes_2d` |
|| `qrcode_option()`               | Print QR code with custom option                      | `codes_2d` |
|| `bit_image()`                   | Print raster bit image with default option            | `graphics` |
|| `bit_image_option()`            | Print raster bit image with custom option             | `graphics` |
|| `bit_image_from_bytes()`        | Print raster bit image from bytes with default option | `graphics` |
|| `bit_image_from_bytes_option()` | Print raster bit image from bytes with custom option  | `graphics` |
|| `gs1_databar_2d`                | Print 2D GS1 DataBar with default option              | `codes_2d` |
|| `gs1_databar_2d_option`         | Print 2D GS1 DataBar with custom option               | `codes_2d` |
|| `pdf417`                        | Print PDF417 with default option                      | `codes_2d` |
|| `pdf417_option`                 | Print PDF417 with custom option                       | `codes_2d` |
|| `maxi_code`                     | Print MaxiCode with default option                    | `codes_2d` |
|| `maxi_code_option`              | Print MaxiCode with custom option                     | `codes_2d` |
|| `data_matrix`                   | Print DataMatrix with default option                  | `codes_2d` |
|| `data_matrix_option`            | Print DataMatrix with custom option                   | `codes_2d` |
|| `aztec`                         | Print Aztec code with default option                  | `codes_2d` |
|| `aztec_option`                  | Print Aztec code with custom option                   | `codes_2d` |
|   🚧   | `graphic()`                     | Print raster graphic with default option              | `graphics` |
|   🚧   | `graphic_option()`              | Print raster graphic with custom option               | `graphics` |

- ✅ Done
- 🚧 In progress
- ❌ To do

## Page codes list

| Code       | Implemented? |
|:-----------|:------------:|
| PC437      ||
| Katakana   ||
| PC850      ||
| PC860      ||
| PC863      ||
| PC865      ||
| Hiragana   ||
| PC851      ||
| PC853      ||
| PC857      ||
| PC737      ||
| ISO8859_7  ||
| WPC1252    ||
| PC866      ||
| PC852      ||
| PC858      ||
| PC720      ||
| WPC775     ||
| PC855      ||
| PC861      ||
| PC862      ||
| PC864      ||
| PC869      ||
| ISO8859_2  ||
| ISO8859_15 ||
| PC1098     ||
| PC1118     ||
| PC1119     ||
| PC1125     ||
| WPC1250    ||
| WPC1251    ||
| WPC1253    ||
| WPC1254    ||
| WPC1255    ||
| WPC1256    ||
| WPC1257    ||
| WPC1258    ||
| KZ1048     ||

## External resources

- [Epson documentation]https://download4.epson.biz/sec_pubs/pos/reference_en/escpos/ref_escpos_en/introduction.html

## Todo

- [ ] Implement all pages codes
- [ ] Add more commands:
    - [ ] Graphic (Ex.: `GS 8 L` or `GS ( L`)