Explorar el Código

feat: 集成 TSC 打印机 DLL 支持标签打印
- 添加 JNA 库 (jna-5.13.0.jar) 用于调用原生 DLL
- 添加 TSCLIB.dll 驱动库
- 实现 TSCLIB.java 接口封装 TSC 打印机 DLL 函数
- 实现 TscPrinter.java 标签打印逻辑
* 根据 SN 前缀自动识别产品型号 (T09/T68)
* 绘制公司名、产品名、型号、批次号、日期、流水号
* 支持二维码和条码打印
- 添加 TestTscPrint.java 交互式测试程序
- 更新配置文件支持 TSC TTP-244 PRO 打印机

技术方案: TSC Windows DLL + JNA (方案4)
不依赖: BarTender 软件、.btw 模板

wangxichen hace 2 días
padre
commit
ae06f6c880

BIN
TSCLIB.dll


+ 1 - 1
config/print.properties

@@ -1,4 +1,4 @@
 printer.type=hp
-printer.name=HP-3004dn
+printer.name=TSC TTP-244 PRO
 # 纸张:A4 或 A5,默认 A5(流转卡模板就是 A5 设计)
 printer.paper=A5

BIN
lib/jna-5.13.0.jar


+ 0 - 128
src/com/mes/print/bartender/BarTenderFilePrinter.java

@@ -1,128 +0,0 @@
-package com.mes.print.bartender;
-
-import com.jacob.activeX.ActiveXComponent;
-import com.jacob.com.Dispatch;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.nio.charset.StandardCharsets;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-/**
- * BarTender 打印 - 通过文本文件数据源
- */
-public class BarTenderFilePrinter {
-    
-    private static final String DATA_FILE = "C:\\Users\\jcxa\\Desktop\\dydriver\\BtMsg1.txt";
-    
-    /**
-     * 打印标签
-     * @param sn 批次号(如 +KB60IS3031T81L000401)
-     * @param printIndex 打印序号(如 4)
-     */
-    public void printLabel(String sn, int printIndex) {
-        try {
-            // 1. 生成数据文件
-            generateDataFile(sn, printIndex);
-            
-            // 2. 确定模板文件
-            String templatePath = getTemplatePath(sn);
-            
-            // 3. 调用 BarTender 打印
-            printWithBarTender(templatePath);
-            
-        } catch (Exception e) {
-            throw new RuntimeException("打印失败", e);
-        }
-    }
-    
-    /**
-     * 生成数据文件
-     */
-    private void generateDataFile(String sn, int printIndex) throws Exception {
-        // 根据 SN 前缀判断产品型号
-        String productModel = getProductModel(sn);
-        
-        // 生成日期
-        String date = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
-        
-        // 生成流水号(7位补零)
-        String serialNo = String.format("%07d", printIndex);
-        
-        // 写入文件(制表符分隔)
-        try (OutputStreamWriter writer = new OutputStreamWriter(
-                new FileOutputStream(DATA_FILE), StandardCharsets.UTF_8)) {
-            
-            writer.write("广西巨石\t");
-            writer.write("新能源科技有限公司\t");
-            writer.write("高压电池下壳体总成\t");
-            writer.write(productModel + "\t");
-            writer.write(sn + "\t");
-            writer.write(date + "\t");
-            writer.write(serialNo);
-        }
-    }
-    
-    /**
-     * 根据 SN 前缀获取模板路径
-     */
-    private String getTemplatePath(String sn) {
-        if (sn.startsWith("+KB60")) {
-            return "C:\\Users\\jcxa\\Desktop\\dydriver\\T09.btw";
-        } else if (sn.startsWith("+KB87")) {
-            return "C:\\Users\\jcxa\\Desktop\\dydriver\\T68.btw";
-        } else {
-            throw new RuntimeException("未知的 SN 前缀: " + sn);
-        }
-    }
-    
-    /**
-     * 根据 SN 前缀获取产品型号
-     */
-    private String getProductModel(String sn) {
-        if (sn.startsWith("+KB60")) {
-            return "2510094CDE2200";  // T09
-        } else if (sn.startsWith("+KB87")) {
-            return "2510094ANB0900";  // T68
-        } else {
-            return "UNKNOWN";
-        }
-    }
-    
-    /**
-     * 调用 BarTender 打印
-     */
-    private void printWithBarTender(String templatePath) {
-        ActiveXComponent btApp = null;
-        Dispatch btFormat = null;
-        
-        try {
-            // 创建 BarTender Application
-            btApp = new ActiveXComponent("BarTender.Application");
-            
-            // 打开模板(带密码)
-            Dispatch btFormats = btApp.getProperty("Formats").toDispatch();
-            btFormat = Dispatch.call(btFormats, "Open", templatePath, false, "123654").toDispatch();
-            
-            // 打印(不显示对话框)
-            Dispatch.call(btFormat, "PrintOut", false, false);
-            
-        } finally {
-            // 关闭
-            if (btFormat != null) {
-                try {
-                    Dispatch.call(btFormat, "Close", 2); // btDoNotSaveChanges
-                } catch (Exception e) {
-                    // 忽略
-                }
-            }
-            if (btApp != null) {
-                try {
-                    btApp.invoke("Quit", 2);
-                } catch (Exception e) {
-                    // 忽略
-                }
-            }
-        }
-    }
-}

+ 75 - 0
src/com/mes/print/bartender/BarTenderLabelPrinter.java

@@ -0,0 +1,75 @@
+package com.mes.print.bartender;
+
+import com.mes.print.config.PrinterConfig;
+import com.mes.print.model.LabelData;
+import com.mes.print.impl.TscPrinter;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * BarTender 标签打印适配器
+ * 使用 TSPL 指令直接打印,不依赖 BarTender 软件和 .btw 模板
+ */
+public class BarTenderLabelPrinter {
+
+    private TscPrinter tscPrinter = new TscPrinter();
+
+    /**
+     * 打印标签
+     * @param sn 批次号(如 +KB60IS3031T81L000401)
+     * @param printIndex 打印序号(如 4)
+     */
+    public void printLabel(String sn, int printIndex) {
+        try {
+            // 根据 SN 前缀判断产品型号
+            String productModel = getProductModel(sn);
+
+            // 生成日期和流水号
+            String date = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
+            String serialNo = String.format("%07d", printIndex);
+
+            // 构建标签数据
+            LabelData data = new LabelData();
+
+            // 组装标题(多行信息用空格或换行符分隔,TSPL 会处理)
+            String title = "GXJS-NEV Battery Shell";
+            data.setTitle(title);
+
+            // SN 作为条码内容
+            data.setBarcode(sn);
+
+            // 二维码也使用 SN
+            data.setQrcode(sn);
+
+            // 设置打印份数
+            data.setCopies(1);
+
+            System.out.println("开始打印标签...");
+            System.out.println("  批次号: " + sn);
+            System.out.println("  产品型号: " + productModel);
+            System.out.println("  日期: " + date);
+            System.out.println("  流水号: " + serialNo);
+
+            // 调用 TSC 打印机打印
+            tscPrinter.printLabel(data);
+
+            System.out.println("打印成功");
+
+        } catch (Exception e) {
+            throw new RuntimeException("打印失败: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 根据 SN 前缀获取产品型号
+     */
+    private String getProductModel(String sn) {
+        if (sn.startsWith("+KB60")) {
+            return "2510094CDE2200";  // T09
+        } else if (sn.startsWith("+KB87")) {
+            return "2510094ANB0900";  // T68
+        } else {
+            return "UNKNOWN";
+        }
+    }
+}

+ 9 - 10
src/com/mes/print/test/TestBarTenderFilePrint.java

@@ -1,21 +1,21 @@
 package com.mes.print.test;
 
-import com.mes.print.bartender.BarTenderFilePrinter;
+import com.mes.print.bartender.BarTenderLabelPrinter;
 import java.util.Scanner;
 
 /**
- * 测试 BarTender 文件方式打印
+ * BarTender 标签打印测试(TSPL 方案)
  */
-public class TestBarTenderFilePrint {
+public class TestBarTenderLabelPrint {
 
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
 
         try {
-            System.out.println("===== BarTender 标签打印测试 =====");
+            System.out.println("===== BarTender 标签打印测试(TSPL) =====");
             System.out.println("支持的 SN 前缀:");
-            System.out.println("  +KB60* → T09 模板 (2510094CDE2200)");
-            System.out.println("  +KB87* → T68 模板 (2510094ANB0900)");
+            System.out.println("  +KB60* → T09 (2510094CDE2200)");
+            System.out.println("  +KB87* → T68 (2510094ANB0900)");
             System.out.println();
 
             // 输入批次号
@@ -53,14 +53,13 @@ public class TestBarTenderFilePrint {
                 return;
             }
 
-            System.out.println("\n开始打印...");
+            System.out.println();
 
             // 执行打印
-            BarTenderFilePrinter printer = new BarTenderFilePrinter();
+            BarTenderLabelPrinter printer = new BarTenderLabelPrinter();
             printer.printLabel(sn, printIndex);
 
-            System.out.println("✓ 打印成功!");
-            System.out.println("\n数据文件位置: C:\\Users\\jcxa\\Desktop\\dydriver\\BtMsg1.txt");
+            System.out.println("\n✓ 打印完成!");
 
         } catch (Exception e) {
             System.err.println("\n✗ 打印失败: " + e.getMessage());

+ 8 - 9
src/com/mes/print/test/TestBarTenderFilePrint.java

@@ -1,21 +1,21 @@
 package com.mes.print.test;
 
-import com.mes.print.bartender.BarTenderFilePrinter;
+import com.mes.print.tsc.TscPrinter;
 import java.util.Scanner;
 
 /**
- * 测试 BarTender 文件方式打印
+ * TSC DLL 打印测试
  */
-public class TestBarTenderFilePrint {
+public class TestTscPrint {
 
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
 
         try {
-            System.out.println("===== BarTender 标签打印测试 =====");
+            System.out.println("===== TSC DLL 打印测试 =====");
             System.out.println("支持的 SN 前缀:");
-            System.out.println("  +KB60* → T09 模板 (2510094CDE2200)");
-            System.out.println("  +KB87* → T68 模板 (2510094ANB0900)");
+            System.out.println("  +KB60* → 产品型号 2510094CDE2200");
+            System.out.println("  +KB87* → 产品型号 2510094ANB0900");
             System.out.println();
 
             // 输入批次号
@@ -56,11 +56,10 @@ public class TestBarTenderFilePrint {
             System.out.println("\n开始打印...");
 
             // 执行打印
-            BarTenderFilePrinter printer = new BarTenderFilePrinter();
+            TscPrinter printer = new TscPrinter();
             printer.printLabel(sn, printIndex);
 
-            System.out.println("✓ 打印成功!");
-            System.out.println("\n数据文件位置: C:\\Users\\jcxa\\Desktop\\dydriver\\BtMsg1.txt");
+            System.out.println("✓ 打印完成!");
 
         } catch (Exception e) {
             System.err.println("\n✗ 打印失败: " + e.getMessage());

+ 104 - 0
src/com/mes/print/tsc/TSCLIB.java

@@ -0,0 +1,104 @@
+package com.mes.print.tsc;
+
+import com.sun.jna.Library;
+import com.sun.jna.Native;
+
+/**
+ * TSC 打印机 DLL 接口
+ * 基于 TSCLIB.dll 的 JNA 封装
+ */
+public interface TSCLIB extends Library {
+
+    // 加载 DLL
+    TSCLIB INSTANCE = (TSCLIB) Native.load("TSCLIB", TSCLIB.class);
+
+    // ========== 基本控制函数 ==========
+
+    /**
+     * 打开打印机端口
+     * @param pirnterName 打印机名称(如 "TSC TTP-244 PRO")
+     * @return 成功返回 1,失败返回 0
+     */
+    int openport(String pirnterName);
+
+    /**
+     * 关闭打印机端口
+     */
+    int closeport();
+
+    /**
+     * 设置打印机参数
+     * @param width 标签宽度(单位:mm)
+     * @param height 标签高度(单位:mm)
+     * @param speed 打印速度(1-15)
+     * @param density 打印浓度(0-15)
+     * @param sensor 传感器类型(0=垂直间距传感器, 1=间隙传感器)
+     * @param vertical 垂直间距高度(单位:mm,仅 sensor=0 时有效)
+     * @param offset 标签偏移量(单位:mm)
+     */
+    int setup(String width, String height, String speed, String density,
+              String sensor, String vertical, String offset);
+
+    /**
+     * 清除打印缓冲区
+     */
+    int clearbuffer();
+
+    /**
+     * 打印标签
+     * @param sets 打印份数
+     * @param copys 每份打印的标签数
+     */
+    int printlabel(String sets, String copys);
+
+    // ========== 文本函数 ==========
+
+    /**
+     * 打印文本
+     * @param x X坐标(单位:dot)
+     * @param y Y坐标(单位:dot)
+     * @param font 字体名称(如 "TSS24.BF2", "1", "2"...)
+     * @param rotation 旋转角度(0, 90, 180, 270)
+     * @param x_multiplication X方向放大倍数(1-10)
+     * @param y_multiplication Y方向放大倍数(1-10)
+     * @param text 文本内容
+     */
+    int windowsfont(int x, int y, int fontheight, int rotation,
+                    int fontstyle, int fontunderline, String szFaceName, String content);
+
+    /**
+     * 打印条形码(简化版)
+     */
+    int barcode(String x, String y, String type, String height,
+                String readable, String rotation, String narrow, String wide, String code);
+
+    // ========== 条码/二维码函数 ==========
+
+    /**
+     * 打印一维条码
+     * @param x X坐标
+     * @param y Y坐标
+     * @param type 条码类型("128", "EAN13", "CODE39"等)
+     * @param height 条码高度(单位:dot)
+     * @param readable 是否显示可读文字(0=不显示, 1=显示)
+     * @param rotation 旋转角度(0, 90, 180, 270)
+     * @param narrow 窄条宽度(单位:dot)
+     * @param wide 宽条宽度(单位:dot)
+     * @param code 条码内容
+     */
+    int barcode128(String x, String y, String height, String readable,
+                   String rotation, String narrow, String code);
+
+    /**
+     * 打印 QR Code 二维码
+     * @param x X坐标
+     * @param y Y坐标
+     * @param eccLevel 纠错等级("L", "M", "Q", "H")
+     * @param cellWidth 单元宽度(1-10)
+     * @param mode 模式("A"=自动, "M"=手动)
+     * @param rotation 旋转角度(0, 90, 180, 270)
+     * @param code 二维码内容
+     */
+    int qrcode(String x, String y, String eccLevel, String cellWidth,
+               String mode, String rotation, String code);
+}

+ 100 - 0
src/com/mes/print/tsc/TscPrinter.java

@@ -0,0 +1,100 @@
+package com.mes.print.tsc;
+
+import com.mes.print.config.PrinterConfig;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * TSC 打印机 - 通过 DLL 直接控制
+ * 不需要 BarTender,不使用 .btw 模板
+ */
+public class TscPrinter {
+
+    private TSCLIB tsc = TSCLIB.INSTANCE;
+
+    /**
+     * 打印标签
+     * @param sn 批次号
+     * @param printIndex 打印序号
+     */
+    public void printLabel(String sn, int printIndex) {
+        try {
+            // 1. 打开打印机
+            String printerName = PrinterConfig.get("printer.name", "TSC TTP-244 PRO");
+            int result = tsc.openport(printerName);
+            if (result != 1) {
+                throw new RuntimeException("打开打印机失败: " + printerName);
+            }
+
+            // 2. 设置标签参数
+            // 标签尺寸:100mm x 60mm,速度4,浓度10,间隙传感器
+            tsc.setup("100", "60", "4", "10", "1", "0", "0");
+
+            // 3. 清除缓冲区
+            tsc.clearbuffer();
+
+            // 4. 绘制标签内容
+            drawLabel(sn, printIndex);
+
+            // 5. 打印
+            tsc.printlabel("1", "1");  // 打印1份,每份1张
+
+            // 6. 关闭打印机
+            tsc.closeport();
+
+            System.out.println("打印成功");
+
+        } catch (Exception e) {
+            throw new RuntimeException("打印失败: " + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 绘制标签内容(根据你的 T09 模板布局)
+     */
+    private void drawLabel(String sn, int printIndex) {
+        // 根据 SN 前缀判断产品型号
+        String productModel = getProductModel(sn);
+
+        // 生成日期和流水号
+        String date = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
+        String serialNo = String.format("%07d", printIndex);
+
+        // 坐标单位:dot(1mm ≈ 8 dot,根据打印机分辨率)
+        // 以下坐标需要根据实际标签布局调整
+
+        // 公司名第1行:广西巨石
+        tsc.windowsfont(50, 50, 32, 0, 0, 0, "SimSun", "广西巨石");
+
+        // 公司名第2行:新能源科技有限公司
+        tsc.windowsfont(50, 90, 24, 0, 0, 0, "SimSun", "新能源科技有限公司");
+
+        // 产品名:高压电池下壳体总成
+        tsc.windowsfont(400, 50, 28, 0, 0, 0, "SimSun", "高压电池下壳体总成");
+
+        // 产品型号
+        tsc.windowsfont(400, 90, 24, 0, 0, 0, "Arial", productModel);
+
+        // 二维码(批次号)
+        tsc.qrcode("50", "150", "M", "5", "A", "0", sn);
+
+        // 日期和流水号
+        tsc.windowsfont(400, 300, 24, 0, 0, 0, "Arial", date + "  NO:" + serialNo);
+
+        // 批次号文本
+        tsc.windowsfont(400, 350, 20, 0, 0, 0, "Arial", sn);
+    }
+
+    /**
+     * 根据 SN 前缀获取产品型号
+     */
+    private String getProductModel(String sn) {
+        if (sn.startsWith("+KB60")) {
+            return "2510094CDE2200";  // T09
+        } else if (sn.startsWith("+KB87")) {
+            return "2510094ANB0900";  // T68
+        } else {
+            return "UNKNOWN";
+        }
+    }
+}