|
@@ -0,0 +1,105 @@
|
|
|
|
|
+package com.mes.util;
|
|
|
|
|
+
|
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
|
+
|
|
|
|
|
+import javax.print.Doc;
|
|
|
|
|
+import javax.print.DocFlavor;
|
|
|
|
|
+import javax.print.DocPrintJob;
|
|
|
|
|
+import javax.print.PrintService;
|
|
|
|
|
+import javax.print.PrintServiceLookup;
|
|
|
|
|
+import javax.print.SimpleDoc;
|
|
|
|
|
+import java.nio.charset.Charset;
|
|
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
|
|
+import java.util.Arrays;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * TSC TTP-244 Pro 标签打印。
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 使用 TSPL 指令直打,配合打印机 Tear(撕纸)模式:打完送出标签,
|
|
|
|
|
+ * 下一张前回抽,并由 SIZE/GAP 保证回抽后仍对准缝隙。
|
|
|
|
|
+ * <p>
|
|
|
|
|
+ * 打印机 Post-Print Action 请保持为 Tear。
|
|
|
|
|
+ */
|
|
|
|
|
+public class PrintUtil {
|
|
|
|
|
+ public static final Logger log = LoggerFactory.getLogger(PrintUtil.class);
|
|
|
|
|
+
|
|
|
|
|
+ private static final float LABEL_WIDTH_MM = 35f;
|
|
|
|
|
+ private static final float LABEL_HEIGHT_MM = 25f;
|
|
|
|
|
+ /** 标签间隙 */
|
|
|
|
|
+ private static final float LABEL_GAP_MM = 2f;
|
|
|
|
|
+
|
|
|
|
|
+ public static void printLabel(String barCode) {
|
|
|
|
|
+ log.info("sn:" + barCode);
|
|
|
|
|
+ PrintService[] services = PrintServiceLookup.lookupPrintServices(null, null);
|
|
|
|
|
+ if (services.length == 0) {
|
|
|
|
|
+ log.info("No printers found.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ String printerName = "TTP-244 Pro";
|
|
|
|
|
+ PrintService selectedService = Arrays.stream(services)
|
|
|
|
|
+ .filter(s -> s.getName().equals(printerName))
|
|
|
|
|
+ .findFirst()
|
|
|
|
|
+ .orElse(null);
|
|
|
|
|
+ if (selectedService == null) {
|
|
|
|
|
+ log.info(printerName + ":Printer not found.");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ try {
|
|
|
|
|
+ byte[] tspl = buildTsplCommands(barCode).getBytes(Charset.forName("GB18030"));
|
|
|
|
|
+ DocFlavor flavor = DocFlavor.BYTE_ARRAY.AUTOSENSE;
|
|
|
|
|
+ if (!selectedService.isDocFlavorSupported(flavor)) {
|
|
|
|
|
+ flavor = DocFlavor.BYTE_ARRAY.TEXT_PLAIN_UTF_8;
|
|
|
|
|
+ tspl = buildTsplCommands(barCode).getBytes(StandardCharsets.UTF_8);
|
|
|
|
|
+ }
|
|
|
|
|
+ Doc doc = new SimpleDoc(tspl, flavor, null);
|
|
|
|
|
+ DocPrintJob job = selectedService.createPrintJob();
|
|
|
|
|
+ job.print(doc, null);
|
|
|
|
|
+ log.info("TSPL print submitted, bytes={}", tspl.length);
|
|
|
|
|
+ System.out.println("Printer finish.");
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ e.printStackTrace();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * TTP-244 Pro 为 203DPI:1mm ≈ 8 dots。
|
|
|
|
|
+ * 文字在上、二维码在下(两行)。
|
|
|
|
|
+ * 标签约 280x200 dots(35x25mm)。
|
|
|
|
|
+ */
|
|
|
|
|
+ private static String buildTsplCommands(String barCode) {
|
|
|
|
|
+ String data = sanitizeTsplText(barCode);
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ sb.append("SIZE ").append(fmt(LABEL_WIDTH_MM)).append(" mm,").append(fmt(LABEL_HEIGHT_MM)).append(" mm\r\n");
|
|
|
|
|
+ sb.append("GAP ").append(fmt(LABEL_GAP_MM)).append(" mm,0\r\n");
|
|
|
|
|
+ sb.append("DIRECTION 1\r\n");
|
|
|
|
|
+ sb.append("REFERENCE 0,0\r\n");
|
|
|
|
|
+ sb.append("OFFSET 0 mm\r\n");
|
|
|
|
|
+ sb.append("SET TEAR ON\r\n");
|
|
|
|
|
+ sb.append("CLS\r\n");
|
|
|
|
|
+ // 第一行:条码文字
|
|
|
|
|
+ sb.append("TEXT 36,36,\"2\",0,1,1,\"").append(data).append("\"\r\n");
|
|
|
|
|
+ // 第二行:二维码
|
|
|
|
|
+ sb.append("QRCODE 100,68,L,4,A,0,\"").append(data).append("\"\r\n");
|
|
|
|
|
+ sb.append("PRINT 1,1\r\n");
|
|
|
|
|
+ String cmd = sb.toString();
|
|
|
|
|
+ log.info("TSPL:\n{}", cmd);
|
|
|
|
|
+ return cmd;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static String sanitizeTsplText(String text) {
|
|
|
|
|
+ if (text == null) {
|
|
|
|
|
+ return "";
|
|
|
|
|
+ }
|
|
|
|
|
+ return text.replace("\"", "").replace("\r", "").replace("\n", "");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ private static String fmt(float mm) {
|
|
|
|
|
+ if (mm == (long) mm) {
|
|
|
|
|
+ return Long.toString((long) mm);
|
|
|
|
|
+ }
|
|
|
|
|
+ return Float.toString(mm);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|