Skip to content

thermal-label/escpos-core

Repository files navigation

@thermal-label/escpos-core

Driver-complete Epson ESC/POS protocol encoder for bitmap label printing. Bitmap in, printer code out — every directive needed to drive a bitmap-rasterised print job end-to-end on a spec-compliant Epson printer, anchored on Epson's published spec.

CI codecov npm core License: MIT

This package produces the byte streams that bitmap-mode ESC/POS printers consume. It is the pure-spec foundation; vendor packages add their own 1F 11 xx opcode families, multi-copy framing, compressed raster modes, and status-opcode tables on top.

Capabilities

Driver-complete bitmap-printing scope — every directive needed to drive a bitmap-rasterised print job end-to-end:

In scope Out of scope
Initialise (ESC @) Native text (ESC ! / GS ! / ESC E / ESC G / ESC - / ESC { / ESC a / ESC R / ESC t / ESC SP)
Bitmap raster — modern (GS v 0) and legacy (ESC * modes 0/1/32/33) Native barcodes (GS k, GS ( k, GS H / GS f / GS h / GS w)
Density (ESC N 7) Page mode (ESC L / ESC S / GS $ / GS \ / GS T / GS /)
Paper handling (ESC d / ESC J / ESC K / GS V full / partial / feed-then-cut) Cash-drawer kick (ESC p)
Print-area control (GS L / GS W / ESC c 5 / ESC 2 / ESC 3) Buzzer (ESC ( A / ESC B)
Status query (DLE EOT n / GS r n / GS a n) Kanji / double-byte modes (FS family)
Realtime-status reply parsing — paper / cover / drawer / autocutter / printer-status / error-info / offline-cause / Star-style Logo / NV image storage (GS ( L / GS * / FS p / FS q)
Uint8Array in, Uint8Array out Macros (GS : / GS ^); vendor 1F 11 xx opcode families

Design rule. Bitmap in, printer code out. Commands that exist solely to make the printer render content the host could have rendered (text, barcodes, scripting) are not in scope.

Install

pnpm add @thermal-label/escpos-core @mbtech-nl/bitmap

Quick example

import {
  encodeEscposJob,
  parseRealtimeStatus,
  type EscposEngine,
} from '@thermal-label/escpos-core';
import { createBitmap } from '@mbtech-nl/bitmap';

const engine: EscposEngine = { dpi: 203, headDots: 384 };
const bitmap = createBitmap(384, 100); // paint your bitmap here…
const bytes = encodeEscposJob(engine, { bitmap });

// `bytes` is now a complete ESC/POS print job:
//   1B 40                       ESC @
//   1D 76 30 00 30 00 64 00     GS v 0  m=0  width=48 bytes  height=100
//   <raster payload>            48 * 100 = 4800 bytes
// Hand it to your transport (USB, RFCOMM, TCP-9100, BLE, …).

// Realtime-status replies arrive opcode-framed; feed them to the parser:
const reply = parseRealtimeStatus(buffer);
if (reply.reply?.kind === 'paper' && reply.reply.paperOut) {
  // show "load paper" UI
}

API surface

// Directive byte builders
buildEscposReset(): Uint8Array                          // 1B 40
buildGsV0Raster(widthBytes, heightDots): Uint8Array     // 1D 76 30 00 + xL xH yL yH
buildEscStarRaster(mode, widthDots, heightDots)         // 1B 2A m xL xH (legacy)
buildEscposDensity(level): Uint8Array                   // 1B 4E 07 nn
buildFeedLines(n) / buildFeedDots(n) / buildReverseFeed(n)
buildCut(mode, feed?)                                   // 1D 56 …
buildPrintAndFeed(n?)
buildLeftMargin(dots) / buildPrintWidth(dots)           // 1D 4C / 1D 57
buildPanelButtons(state)                                // 1B 63 35 nn
buildLineSpacing(dots) / buildDefaultLineSpacing()      // 1B 33 / 1B 32
buildRealtimeStatusQuery(kind)                          // 10 04 nn
buildTransmitStatus(kind)                               // 1D 72 nn
buildAutoStatusBack(kind)                               // 1D 61 nn
concatBytes(...chunks): Uint8Array

// High-level encoder — single page, single copy
encodeEscposJob(engine, page): Uint8Array

// Realtime-status reply parser — paper / cover / drawer / autocutter /
// printer / error-info / offline-cause / printer-star / unknown
parseRealtimeStatus(bytes, offset?): ParseResult

Notes

  • Bit polarity is spec-aligned. Epson's GS v 0 defines bit 1 as a printed dot — same convention as LabelBitmap's 1 = dark. No flip needed.
  • Width must be a multiple of 8 dots. The GS v 0 wire format uses truncating row stride; pad upstream with padBitmap from @mbtech-nl/bitmap if your source isn't aligned.
  • No multi-copy framing at the protocol layer. Pure ESC/POS doesn't define one; write the same payload N times back-to-back at the transport layer, or use a vendor package.

Documentation

Full docs at https://thermal-label.github.io/escpos-core/.

License

MIT — see LICENSE.

See INTEROPERABILITY.md for the interoperability statement and legal posture.

About

Pure Epson ESC/POS encoder for bitmap label printing — ESC @ / GS v 0 / ESC * raster, paper handling, realtime status reply parsing. Driver-complete subset of the Epson spec; native text / barcodes / page mode out of scope by design.

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Sponsor this project

Packages

 
 
 

Contributors