Files
2026-09-30 10:22:42 +02:00

118 lines
5.3 KiB
Markdown

# Emulador de impresora térmica ESC/POS
Impresora térmica virtual para probar la librería sin papel ni ruido. Recibe
bytes ESC/POS por **LAN** (TCP RAW, puerto 9100) y por **USB** (dispositivo
USB real exportado por USB/IP), dibuja el papel que saldría y responde a los
comandos de estado como una impresora de verdad.
## Compilar y ejecutar
```sh
cd emulator
go build -o escpos-emu.exe .
./escpos-emu.exe # perfil 80 mm, LAN :9100, USB/IP :3240
./escpos-emu.exe -perfil 58mm # clon barato: sin cuchilla, sin QR, GS I limitado
./escpos-emu.exe -nogui # sin ventana: registro por consola, tickets a ./tickets/*.png
```
| Opción | Por defecto | Significado |
|-------------|-------------|-------------------------------------------------------|
| `-lan` | `:9100` | Puerto TCP RAW. Vacío (`-lan ""`) lo desactiva |
| `-usbip` | `:3240` | Servidor USB/IP. Vacío lo desactiva |
| `-perfil` | `80mm` | `80mm` o `58mm` |
| `-nogui` | no | Modo consola |
| `-tickets` | — | Carpeta donde guardar cada ticket cortado como PNG |
La primera vez, el firewall de Windows preguntará si permite las conexiones:
acéptalo en redes privadas si vas a conectar desde WSL u otra máquina.
## La ventana
- **Centro**: el papel. Arriba, los tickets ya cortados; abajo, el papel que
sigue dentro de la impresora. La línea roja es la cuchilla.
- **Derecha**: cada comando recibido con sus bytes en hexadecimal y su
significado. Verde: texto. Azul: respuestas al host. Naranja: avisos.
- **Izquierda**: interruptores de estado físico (tapa, papel, cuchilla,
offline), cajón, captura de bytes a `.bin` y reinicio.
## LAN
Cualquier cliente TCP sirve. Abre una conexión a `IP:9100`, escribe los bytes
y, si has enviado un comando de estado, lee la respuesta por el mismo socket.
Desde WSL con NAT, la IP de Windows es la puerta de enlace:
`ip route show default | awk '{print $3}'`.
## USB (USB/IP)
El emulador actúa como servidor USB/IP y publica un dispositivo `1209:0001`
de clase impresora (07/01/02, bidireccional) con endpoint bulk OUT 0x01 y bulk
IN 0x82, de 64 bytes. El sistema operativo lo ve como una impresora USB
enchufada físicamente y carga su driver habitual.
**Fedora / Debian (WSL o nativo)**
```sh
sudo dnf install usbip # Debian: sudo apt install usbip
sudo modprobe vhci-hcd
usbip list -r <IP-de-Windows>
sudo usbip attach -r <IP-de-Windows> -b 1-1
lsusb # 1209:0001 EMULADOR ESCPOS-EMU-80
ls /dev/usb/lp* # el driver usblp crea /dev/usb/lp0
sudo usbip detach -p 0
```
**Windows**
Instala el cliente [usbip-win2](https://github.com/vadimgrn/usbip-win2) (lee
en su README los requisitos de firma del driver). Después:
```bat
usbip attach -r 127.0.0.1 -b 1-1
usbip port
usbip detach -p <puerto>
```
Windows carga `usbprint.sys` y crea un puerto `USB001`, igual que con una
impresora real. Para acceder con WinUSB o libusb hay que cambiarle el driver
(por ejemplo con Zadig), como con cualquier dispositivo USB.
Si `usbipd-win` ya ocupa el puerto 3240, usa `-usbip :3241` y en el cliente
indica el puerto (`usbip --tcp-port 3241 ...` en Linux).
## Respuestas de estado
| Comando | Respuesta (1 byte salvo indicación) |
|---------------|-------------------------------------------------------------------------|
| `DLE EOT 1` | `0x12` + bit 2 cajón abierto + bit 3 offline |
| `DLE EOT 2` | `0x12` + bit 2 tapa abierta + bit 5 sin papel + bit 6 error |
| `DLE EOT 3` | `0x12` + bit 3 error de cuchilla |
| `DLE EOT 4` | `0x12` + bits 2-3 papel casi agotado + bits 5-6 sin papel |
| `GS r 1` | bits 0-1 casi agotado, bits 2-3 sin papel |
| `GS I 1/2/3` | ID de modelo / tipo / versión |
| `GS I 65..69` | `0x5F` + texto + `0x00` (solo perfil 80mm; el 58mm no responde) |
| `GS a n` | activa el estado automático (4 bytes en cada cambio) |
Con la tapa abierta, sin papel, con error de cuchilla u offline, la impresora
**deja de imprimir** y guarda los datos en el buffer; `DLE EOT` y `DLE DC4 1`
se siguen atendiendo al momento. Al resolver el problema se imprime lo
pendiente.
## Comportamientos reales que conviene conocer
- **La cuchilla está 12 mm por encima del cabezal.** `GS V 0` corta donde
está la cuchilla, así que las últimas líneas quedan en el siguiente ticket.
`GS V 65 n` avanza hasta la cuchilla y `n` puntos más antes de cortar.
- **`ESC a` solo se aplica al principio de una línea.** Si llega a mitad de
línea, se aplica en la siguiente.
- **Los comandos pueden llegar partidos** entre paquetes TCP o transferencias
USB. El emulador espera a tener el comando completo, como el firmware.
- **Ancho imprimible**: 576 puntos en 80 mm y 384 en 58 mm (8 puntos/mm).
## Qué no emula
Modo página, códigos de barras (`GS k` dibuja un recuadro con los datos),
PDF417 y otros símbolos 2D distintos de QR, caracteres definidos por el
usuario, imágenes NV/descargables, impresión boca abajo, y control de flujo
(el buffer no se llena nunca).