En este post vamos a ver cómo comunicar Java con una impresora térmica para imprimir imágenes, códigos QR, códigos de barra, texto, texto con acentos y darle estilo a los tickets desde ese lenguaje de programación.
Al final podrás usar NetBeans, IntelliJ IDEA, VSCode o cualquier editor en donde programes en Java para imprimir tickets en una impresora térmica.
Con el código mostrado aquí vas a ser capaz de imprimir recibos en una impresora térmica con Java ya sea desde la terminal, con Swing, en SpringBoot o cualquier cosa que programes con Java.
Prueba el nuevo diseñador
En estos días he creado un nuevo diseñador web para impresoras térmicas. El diseñador te guiará en el proceso de instalar tu impresora, compartirla e instalar lo necesario para imprimir tus diseños. Pruébalo en:
https://parzibyte.me/apps/ticket-designer/#/first-steps
Una vez que tengas tus diseños vas a poder imprimirlos desde cualquier lenguaje de programación, incluyendo Java.
Imprimir en impresora térmica con Java
Ahora sí vamos a lo que vinimos: la impresión de un ticket con Java. Comenzamos creando la lista de operaciones. En el siguiente ejemplo estamos iniciando la impresora, escribiendo un hola mundo, avanzando el papel 2 líneas e imprimiendo una imagen de internet.
// Lista completa: https://parzibyte.me/http-esc-pos-desktop-docs/es/
ArrayList<OperacionHttpEscPos> operaciones = new ArrayList<>();
operaciones.add(new OperacionHttpEscPos("Iniciar", new Object[]{}));
operaciones.add(new OperacionHttpEscPos("EscribirTexto", new Object[]{"Hola\nMundo\n"}));
operaciones.add(new OperacionHttpEscPos("Feed", new Object[]{2}));
operaciones.add(new OperacionHttpEscPos("DescargarImagenDeInternetEImprimir", new Object[]{"https://github.com/parzibyte.png", 380, 0, true}));
Debemos crear un ArrayList
de tipo OperacionHttpEscPos
y luego invocar a operaciones.add(new OperacionHttpEscPos("NombreDeLaOperacion", new Object[]{/*Argumentos*/}));
Puedes invocar a add
cuantas veces sea necesario para agregar todas las operaciones con las que vas a diseñar tu ticket. La lista completa de operaciones está en la documentación.
Por ejemplo, la operación que permite descargar una imagen de internet para imprimirla recibe, en orden: la URL de la imagen, el ancho máximo, el algoritmo y una bandera indicando si se debería aplicar dithering. Por ello es que la definimos así:
operaciones.add(new OperacionHttpEscPos("DescargarImagenDeInternetEImprimir", new Object[]{"https://github.com/parzibyte.png", 380, 0, true}));
Una vez que tienes tu lista de operaciones definida, procedemos a crear la carga útil que se va a enviar. Aquí indicamos el nombre de la impresora:
String nombreImpresora = "Termica";
String serial = "";
ImpresionConNombre impresionConNombre = new ImpresionConNombre(operaciones, nombreImpresora, serial);
Ya tenemos el objeto creado, ahora solo falta codificarlo y enviarlo a la API HTTP local del plugin:
String postEndpoint = "http://localhost:8000/imprimir";
try {
String inputJson = JSON.std.asString(impresionConNombre);
var request = HttpRequest
.newBuilder()
.uri(URI.create(postEndpoint))
.POST(HttpRequest.BodyPublishers.ofString(inputJson))
.build();
var client = HttpClient.newHttpClient();
var respuestaHttp = client.send(request, HttpResponse.BodyHandlers.ofString());
if (respuestaHttp.statusCode() != 200) {
throw new Exception("código de respuesta distinto a 200. Verifique que el plugin se está ejecutando");
}
RespuestaHttpEscPos respuesta = JSON.std.beanFrom(RespuestaHttpEscPos.class, respuestaHttp.body());
if (respuesta.isOk()) {
System.out.println("Impreso correctamente");
} else {
System.out.println("Petición correcta, pero error en el plugin: " + respuesta.getMessage() + " . Documentación: https://parzibyte.me/http-esc-pos-desktop-docs/es/");
}
} catch (Exception e) {
System.out.println(e);
}
Puede verse complicado al inicio, pero en realidad solo estamos consumiendo una API HTTP REST local con Java usando JSON. La API está documentada en el siguiente enlace y puedes usar cualquier lenguaje de programación para consumirla:
https://parzibyte.me/http-esc-pos-desktop-docs/es/
Sigue leyendo para revisar los detalles sobre las clases de Java.
Clases necesarias y dependencias
Vamos a necesitar algunas clases programadas por mí para la interacción con el plugin de impresión térmica (servidor HTTP a ESC POS) y comandos ESC POS. La primera indica las operaciones ESC POS que se pueden hacer:
public class OperacionHttpEscPos {
public String nombre;
public Object[] argumentos;
public OperacionHttpEscPos(String nombre, Object[] argumentos) {
this.nombre = nombre;
this.argumentos = argumentos;
}
}
La segunda clase es la que contiene la lista de operaciones y el nombre de la impresora. Más adelante vamos a codificar esta clase y enviarla a la API:
public class ImpresionConNombre {
public ArrayList<OperacionHttpEscPos> operaciones;
public String nombreImpresora;
public String serial;
public ImpresionConNombre(ArrayList<OperacionHttpEscPos> operaciones, String nombreImpresora, String serial) {
this.operaciones = operaciones;
this.nombreImpresora = nombreImpresora;
this.serial = serial;
}
}
Finalmente debemos manejar la respuesta al imprimir para saber si la impresión ESC POS fue exitosa:
public class RespuestaHttpEscPos {
private String message;
private boolean ok;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public boolean isOk() {
return ok;
}
public void setOk(boolean ok) {
this.ok = ok;
}
}
Como Java es un lenguaje fuertemente tipado debemos definir correctamente todos los datos que se van a manejar, indicando claramente las propiedades de cada clase. En mi caso cada clase está en su respectivo archivo llamado ImpresionConNombre.java
, OperacionHttpEscPos.java
y RespuestaHttpEscPos.java
.
Dependencias de Java
El servidor local que convierte peticiones HTTP con JSON a operaciones ESC POS para impresoras térmicas se comunica con JSON, así que necesitamos convertir nuestras clases a JSON.
No encontré alguna manera nativa, así que agregué la dependencia jackson-jr que sirve para convertir a JSON desde Java.
La inclusión depende de tu IDE y entorno, pero yo he usado Maven con NetBeans y solo ha sido cuestión de agregar la siguiente dependencia a mi archivo pom.xml
:
<dependency>
<groupId>com.fasterxml.jackson.jr</groupId>
<artifactId>jackson-jr-objects</artifactId>
<version>2.13.0</version>
</dependency>
Solo como referencia, mi archivo pom.xml
completo se ve así:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.parzibyte</groupId>
<artifactId>mavenproject1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.release>17</maven.compiler.release>
<exec.mainClass>me.parzibyte.mavenproject1.Mavenproject1</exec.mainClass>
</properties>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson.jr</groupId>
<artifactId>jackson-jr-objects</artifactId>
<version>2.13.0</version>
</dependency>
</dependencies>
</project>
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/
Vídeo de apoyo
Código completo
El código completo para comunicar Java con una impresora térmica es el siguiente, excluyendo las 3 clases que mencioné previamente:
package me.parzibyte.mavenproject1;
import com.fasterxml.jackson.jr.ob.JSON;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.ArrayList;
/**
*
* @author parzibyte
*/
public class Mavenproject1 {
public static void main(String[] args) {
// Lista completa: https://parzibyte.me/http-esc-pos-desktop-docs/es/
ArrayList<OperacionHttpEscPos> operaciones = new ArrayList<>();
operaciones.add(new OperacionHttpEscPos("Iniciar", new Object[]{}));
operaciones.add(new OperacionHttpEscPos("EscribirTexto", new Object[]{"Hola\nMundo\n"}));
operaciones.add(new OperacionHttpEscPos("Feed", new Object[]{2}));
operaciones.add(new OperacionHttpEscPos("DescargarImagenDeInternetEImprimir", new Object[]{"https://github.com/parzibyte.png", 380, 0, true}));
String nombreImpresora = "Termica";
String serial = "";
ImpresionConNombre impresionConNombre = new ImpresionConNombre(operaciones, nombreImpresora, serial);
String postEndpoint = "http://localhost:8000/imprimir";
try {
String inputJson = JSON.std.asString(impresionConNombre);
var request = HttpRequest
.newBuilder()
.uri(URI.create(postEndpoint))
.POST(HttpRequest.BodyPublishers.ofString(inputJson))
.build();
var client = HttpClient.newHttpClient();
var respuestaHttp = client.send(request, HttpResponse.BodyHandlers.ofString());
if (respuestaHttp.statusCode() != 200) {
throw new Exception("código de respuesta distinto a 200. Verifique que el plugin se está ejecutando");
}
RespuestaHttpEscPos respuesta = JSON.std.beanFrom(RespuestaHttpEscPos.class, respuestaHttp.body());
if (respuesta.isOk()) {
System.out.println("Impreso correctamente");
} else {
System.out.println("Petición correcta, pero error en el plugin: " + respuesta.getMessage() + " . Documentación: https://parzibyte.me/http-esc-pos-desktop-docs/es/");
}
} catch (Exception e) {
System.out.println(e);
}
System.out.println(operaciones);
}
}
Siguientes pasos
Ahora ya puedes enviar recibos a impresoras térmicas desde Java de una manera muy fácil.
En resumen debes importar las clases y agregar la dependencia de jackson-jr para después crear una instancia del conector e imprimir.
Y la documentación así como los detalles del plugin, incluyendo conectores y más métodos (que te animo y casi obligo a leer) están en: https://parzibyte.me/http-esc-pos-desktop-docs/es/
Buenas, excelente tu trabajo. Cuanto cuesta eliminar el pie de la impresion? Saludos
Hola. Gracias por sus comentarios. Los detalles de la licencia están en: https://parzibyte.me/blog/2022/10/02/contratar-licencia-para-plugin-impresora-termica-v3/