El día de hoy vamos a ver cómo imprimir tickets, recibos o facturas en una impresora térmica desde Angular usando el lenguaje de programación TypeScript y el lenguaje ESC POS para la impresora.
Básicamente vamos a ver cómo comunicar Angular con una thermal printer, pos printer o impresora POS (Epson, Xprinter, etcétera) e imprimir texto, darle formato, imprimir códigos QR, códigos de barras, imágenes, acentos y varias cosas que permitirán crear tickets desde Angular.
Vamos a usar un plugin gratuito y un conector en TypeScript que acabo de crear. Por cierto, el plugin también nos permitirá cortar el papel, abrir el cajón de dinero, definir caracteres personalizados e imprimir en red.
Nota: esto funciona en Windows, Linux, Raspberry Pi y con otro plugin podría incluso funcionar en Android con impresoras Bluetooth.
Imprimir ticket en impresora térmica desde Angular
Necesitamos crear una lista de operaciones que serán realizadas en la impresora térmica. Podemos usar un simple arreglo de TypeScript (que al final es un array de JS):
// Lista de operaciones disponibles: https://parzibyte.me/http-esc-pos-desktop-docs/es/
const operaciones = [
{
nombre: "Iniciar",
argumentos: [],
},
{
nombre: "EstablecerAlineacion",
argumentos: [1],
},
{
nombre: "EscribirTexto",
argumentos: ["Hola Angular desde parzibyte.me"],
},
{
nombre: "Feed",
argumentos: [1],
},
{
nombre: "EscribirTexto",
argumentos: [this.mensaje],
},
{
nombre: "Feed",
argumentos: [1],
},
{
nombre: "DescargarImagenDeInternetEImprimir",
argumentos: ["https://github.com/parzibyte.png", 380, 0, true],
},
];
El ticket será impreso en la impresora térmica haciendo cada operación indicada en el arreglo. No es obligatorio que definas todas las operaciones en el arreglo, ya que también puedes usar operaciones.push
para agregar una operación.
Eres libre de ver la documentación para ver todas las operaciones disponibles. Después de definir la lista de operaciones debemos definir la carga útil donde indicamos el nombre de la impresora, y enviamos esa carga útil al servidor local usando fetch.
La función completa para imprimir en una impresora térmica desde Angular queda así:
async probarImpresion() {
if (!this.impresoraSeleccionada) {
return alert("Seleccione una impresora");
}
if (!this.mensaje) {
return alert("Escribe un mensaje");
}
// Lista de operaciones disponibles: https://parzibyte.me/http-esc-pos-desktop-docs/es/
const operaciones = [
{
nombre: "Iniciar",
argumentos: [],
},
{
nombre: "EstablecerAlineacion",
argumentos: [1],
},
{
nombre: "EscribirTexto",
argumentos: ["Hola Angular desde parzibyte.me"],
},
{
nombre: "Feed",
argumentos: [1],
},
{
nombre: "EscribirTexto",
argumentos: [this.mensaje],
},
{
nombre: "Feed",
argumentos: [1],
},
{
nombre: "DescargarImagenDeInternetEImprimir",
argumentos: ["https://github.com/parzibyte.png", 380, 0, true],
},
];
// https://parzibyte.me/http-esc-pos-desktop-docs/es/api/imprimir.html
const cargaUtil = {
nombreImpresora: this.impresoraSeleccionada,
serial: "",
operaciones: operaciones,
};
const respuestaHttp = await fetch("http://localhost:8000/imprimir", {
method: "POST",
body: JSON.stringify(cargaUtil),
})
const respuesta = await respuestaHttp.json();
if (respuesta.ok) {
console.log("Impreso correctamente");
} else {
console.error("Petición realizada pero error en el plugin: " + respuesta.message);
}
}
Cuando ese código se ejecute, se imprimirá un recibo parecido al de la imagen del post. Toma en cuenta que estoy pasando el this.mensaje
en la lista de operaciones, así como el this.impresoraSeleccionada
en la carga útil. Esos valores podrían venir de cualquier otro lugar.
Lista de impresoras
Para proporcionar al usuario una lista de impresoras disponibles se hace una petición al plugin:
async ngOnInit() {
// https://parzibyte.me/http-esc-pos-desktop-docs/es/api/obtener-impresoras.html
const respuestaHttp = await fetch("http://localhost:8000/impresoras");
const impresoras = await respuestaHttp.json();
this.impresoras = impresoras;
}
Vídeo de ayuda
He grabado un vídeo para explicar el funcionamiento del plugin para imprimir en impresora térmica con Angular. Es un complemento de este post:
Configurar impresora y descargar servidor HTTP a ESC POS
Para que el código funcione necesitas el servidor local de la API ESC POS ejecutándose y que tu impresora esté compartida. Por favor, sigue los pasos que aparecen en la página previamente enlazada, ya que ahí está la API unificada.
La documentación completa está en: https://parzibyte.me/http-esc-pos-desktop-docs/es/
En resumen
- Configura tu impresora y compártela
- Descarga el plugin y asegúrate de que se está ejecutando en segundo plano
- Crea la lista de operaciones y envíala al plugin que convertirá el JSON a ESC POS
Próximos pasos
Ahora que has conectado una impresora térmica con tus apps de Angular puedes hacer más como imprimir códigos de barras, imágenes, códigos QR, imprimir texto con tildes y varias cosas con una impresora térmica sin importar el sistema operativo.
Recomiendo visitar el área de pruebas en donde se usa JavaScript, mismo que es compatible con TypeScript.
También recuerda que puedes crear tu propio conector en cualquier otro lenguaje de programación revisando la documentación de la API, y que, aunque todavía no escribo el post para Angular, existe un plugin para impresoras térmicas en Android con Bluetooth.
El código completo del ejemplo te lo dejo en GitHub. Eres libre de explorarlo: https://github.com/parzibyte/thermal-printer-angular/
Buen video, tengo una duda, como seria en el caso de android?
es decir si tengo el proyecto usando mi movil android, para la impresion como seria el procedimiento?
Usar esto: https://parzibyte.me/blog/2022/09/30/comunicar-javascript-impresora-termica-usando-plugin-v3/
Muchas gracias por los tutoriales sobre las impresoras. Estoy teniendo el siguiente error al darle al botón de imprimir:
“Error: Error en el servidor: open \\xxxxxx\ZDesigner ZQ520 (ZPL): The network name cannot be found.”
La impresora no existe, no está compartida o no sigue los parámetros del nombre. Por favor vuelva a leer: https://parzibyte.me/blog/2017/12/11/instalar-impresora-termica-generica/
¿Es necesario compartirla? Ya la instalé como genérica como indicas e imprimí la pagina de pruebas. Y me aparece en la lista de impresora de la aplicación, pero me sigue saliendo el mismo mensaje. Muchas gracias de nuevo por estos tutoriales.
Sí, es necesario compartirla como se indica en el tutorial que cité anteriormente. Por otro lado, veo que su impresora se llama
ZDesigner ZQ520 (ZPL)
Citando el tutorial que le recomendé que lea de nuevo, dice: