|
|
|
@ -194,7 +194,7 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
sendZplToPrinter(printerIP, printRequest.getZplCode(), requestedCopies,rfidFlag); |
|
|
|
|
|
|
|
// 5. 记录打印日志 |
|
|
|
log.info("RFID标签打印任务执行成功,请求参数: {}", printRequest); |
|
|
|
//log.info("RFID标签打印任务执行成功,请求参数: {}", printRequest); |
|
|
|
} catch (Exception e) { |
|
|
|
System.err.println("RFID标签打印失败: " + e.getMessage()); |
|
|
|
throw new RuntimeException("RFID标签打印失败: " + e.getMessage()); |
|
|
|
@ -202,57 +202,103 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 发送ZPL代码到打印机(支持RFID标签处理) |
|
|
|
* 修复:每次打印请求只处理一张标签,避免重复打印 |
|
|
|
* 发送ZPL代码到打印机(支持RFID标签处理和多份打印) |
|
|
|
*/ |
|
|
|
private void sendZplToPrinter(String printerIP, String zplCode, Integer copies, String rfidFlag) { |
|
|
|
try { |
|
|
|
// 注意:这里的copies参数实际上应该在ZPL代码中处理,而不是在这里循环 |
|
|
|
// 每次打印请求只处理一张RFID标签 |
|
|
|
log.info("开始处理RFID标签打印: {}, 请求份数: {}", printerIP, copies); |
|
|
|
RfidProcessResult result = processRfidLabel(printerIP, zplCode, copies,rfidFlag); |
|
|
|
if (result.isSuccess()) { |
|
|
|
log.info("RFID标签处理成功: {}", printerIP); |
|
|
|
log.info("开始处理标签打印: {}, 请求份数: {}, RFID标志: {}", printerIP, copies, rfidFlag); |
|
|
|
|
|
|
|
if ("Y".equals(rfidFlag)) { |
|
|
|
// RFID模式:需要特殊处理多份打印 |
|
|
|
handleRfidMultiplePrint(printerIP, zplCode, copies); |
|
|
|
} else { |
|
|
|
throw new RuntimeException("RFID标签处理失败: " + result.getErrorMessage()); |
|
|
|
// 普通模式:直接处理 |
|
|
|
RfidProcessResult result = processRfidLabel(printerIP, zplCode, copies, rfidFlag); |
|
|
|
if (!result.isSuccess()) { |
|
|
|
throw new RuntimeException("普通标签打印失败: " + result.getErrorMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.info("标签打印任务完成,总份数: {}", copies); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
throw new RuntimeException("无法连接到打印机 " + printerIP + ": " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 处理单张RFID标签:读取TID -> 写入EPC -> 打印标签 |
|
|
|
* 处理RFID标签的多份打印 |
|
|
|
* 由于RFID标签的特殊性,需要逐张处理,并在每张之间留有足够的间隔 |
|
|
|
*/ |
|
|
|
private void handleRfidMultiplePrint(String printerIP, String zplCode, Integer copies) { |
|
|
|
log.info("开始处理RFID多份打印,份数: {}", copies); |
|
|
|
|
|
|
|
for (int i = 1; i <= copies; i++) { |
|
|
|
try { |
|
|
|
log.info("开始处理第{}张RFID标签", i); |
|
|
|
|
|
|
|
// 每张标签之间留有间隔,避免RFID模块冲突 |
|
|
|
if (i > 1) { |
|
|
|
Thread.sleep(2000); // 2秒间隔 |
|
|
|
log.info("等待间隔完成,开始处理第{}张标签", i); |
|
|
|
} |
|
|
|
|
|
|
|
RfidProcessResult result = processRfidLabel(printerIP, zplCode, i, "Y"); |
|
|
|
if (!result.isSuccess()) { |
|
|
|
throw new RuntimeException("第" + i + "张RFID标签处理失败: " + result.getErrorMessage()); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("第{}张RFID标签处理成功", i); |
|
|
|
|
|
|
|
} catch (Exception e) { |
|
|
|
log.error("第{}张RFID标签处理失败: {}", i, e.getMessage()); |
|
|
|
throw new RuntimeException("第" + i + "张RFID标签处理失败: " + e.getMessage()); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
log.info("RFID多份打印完成,总计{}张", copies); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 处理标签打印:支持RFID和普通标签 |
|
|
|
*/ |
|
|
|
private RfidProcessResult processRfidLabel(String printerIP, String originalZplCode, int labelIndex, String rfidFlag) { |
|
|
|
RfidProcessResult result = new RfidProcessResult(labelIndex); |
|
|
|
private RfidProcessResult processRfidLabel(String printerIP, String originalZplCode, int copiesOrIndex, String rfidFlag) { |
|
|
|
RfidProcessResult result = new RfidProcessResult(copiesOrIndex); |
|
|
|
java.net.Socket socket = null; |
|
|
|
try { |
|
|
|
if (rfidFlag==null || "N".equals(rfidFlag)) { |
|
|
|
if (rfidFlag == null || "N".equals(rfidFlag)) { |
|
|
|
// 普通标签模式:可以直接设置打印份数 |
|
|
|
socket = new java.net.Socket(printerIP, 9100); |
|
|
|
socket.setSoTimeout(10000); |
|
|
|
OutputStream outputStream = socket.getOutputStream(); |
|
|
|
// 清理原始ZPL代码,确保只打印1张 |
|
|
|
String cleanedZpl = cleanZplForSinglePrint(originalZplCode); |
|
|
|
String singlePrintZpl = "^XA\n^PQ1\n" + cleanedZpl.substring(3); |
|
|
|
log.info("发送清理后的ZPL(跳过RFID): {}", singlePrintZpl); |
|
|
|
printLabel(outputStream, singlePrintZpl); |
|
|
|
result.markCompleted(true, "调试模式:跳过RFID,已打印普通标签"); |
|
|
|
log.info("第{}张标签 - 调试模式:跳过RFID,已打印普通标签", labelIndex); |
|
|
|
|
|
|
|
// 清理原始ZPL代码,设置正确的打印份数 |
|
|
|
String cleanedZpl = cleanZplForMultiplePrint(originalZplCode, copiesOrIndex); |
|
|
|
|
|
|
|
log.info("发送普通标签ZPL,份数: {}", copiesOrIndex); |
|
|
|
printLabel(outputStream, cleanedZpl); |
|
|
|
result.markCompleted(true, "普通标签打印完成,份数: " + copiesOrIndex); |
|
|
|
log.info("普通标签打印完成,份数: {}", copiesOrIndex); |
|
|
|
return result; |
|
|
|
} |
|
|
|
// RFID标签模式:单张处理 |
|
|
|
socket = new java.net.Socket(printerIP, 9100); |
|
|
|
socket.setSoTimeout(10000); |
|
|
|
socket.setSoTimeout(15000); // 增加超时时间 |
|
|
|
OutputStream outputStream = socket.getOutputStream(); |
|
|
|
InputStream inputStream = socket.getInputStream(); |
|
|
|
|
|
|
|
// 步骤1: 读取RFID标签的TID |
|
|
|
String tid = readRfidTid(outputStream, inputStream,originalZplCode); |
|
|
|
String tid = readRfidTid(outputStream, inputStream, originalZplCode); |
|
|
|
result.setTid(tid); |
|
|
|
log.info("第{}张标签 - 读取到TID: {}", labelIndex, tid); |
|
|
|
log.info("第{}张RFID标签 - 读取到TID: {}", copiesOrIndex, tid); |
|
|
|
result.markCompleted(true, null); |
|
|
|
} catch (Exception e) { |
|
|
|
String errorMsg = "第" + labelIndex + "张标签处理失败: " + e.getMessage(); |
|
|
|
String errorMsg; |
|
|
|
if ("Y".equals(rfidFlag)) { |
|
|
|
errorMsg = "第" + copiesOrIndex + "张RFID标签处理失败: " + e.getMessage(); |
|
|
|
} else { |
|
|
|
errorMsg = "普通标签打印失败(份数:" + copiesOrIndex + "): " + e.getMessage(); |
|
|
|
} |
|
|
|
System.err.println(errorMsg); |
|
|
|
result.markCompleted(false, e.getMessage()); |
|
|
|
throw new RuntimeException(errorMsg); |
|
|
|
@ -276,23 +322,23 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
// 清空输入流缓冲区,避免之前的数据干扰 |
|
|
|
clearInputStreamBuffer(inputStream); |
|
|
|
// 生成有效的EPC数据 - 确保格式正确,避免写入失败 |
|
|
|
String epc = generateValidEpc(); |
|
|
|
String epc = "1234567890AB1234567890AB"; // 示例EPC数据,实际应用中应生成或获取有效的EPC |
|
|
|
// 处理原始ZPL代码,移除可能的打印份数指令,确保只打印1张 |
|
|
|
String cleanedZplCode = cleanZplForSinglePrint(originalZplCode.substring(3)); |
|
|
|
// 组装 ZPL - 优化RFID指令,确保EPC写入成功 |
|
|
|
String readTidZpl = "^XA\n" + |
|
|
|
"^PQ1\n" + // 首先设置打印份数为1 |
|
|
|
"^RS8\n" + // 设置RFID参数 |
|
|
|
"^RFR,H,2,12,1^FN1^FS\n" + // 读取 TID |
|
|
|
"^RFW,H,2,6,1^FD" + epc + "^FS\n" + // 写入 EPC - 重新启用 |
|
|
|
"^RFR,H,0,12,2^FN1^FS\n" + // 读取 TID |
|
|
|
"^HV1^FN1^FS\n" + // 打印 TID |
|
|
|
"^RFW,H,2,6,6^FD" + epc + "^FS\n" + // 写入 EPC - 重新启用 |
|
|
|
cleanedZplCode; |
|
|
|
log.info("发送完整ZPL指令: {}", readTidZpl); |
|
|
|
try { |
|
|
|
outputStream.write(readTidZpl.getBytes("UTF-8")); |
|
|
|
outputStream.flush(); |
|
|
|
log.info("ZPL指令发送成功,等待RFID操作完成..."); |
|
|
|
Thread.sleep(3000); // 增加等待时间,确保RFID操作完成 |
|
|
|
Thread.sleep(1000); // 增加等待时间,确保RFID操作完成 |
|
|
|
} catch (Exception e) { |
|
|
|
log.error("发送ZPL指令失败: {}", e.getMessage()); |
|
|
|
throw new RuntimeException("发送ZPL指令失败: " + e.getMessage()); |
|
|
|
@ -309,14 +355,6 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
if (bytesRead > 0) { |
|
|
|
String data = new String(buffer, 0, bytesRead, "UTF-8"); |
|
|
|
response.append(data); |
|
|
|
hasReceivedData = true; |
|
|
|
log.info("收到数据片段: {}", data.trim()); |
|
|
|
|
|
|
|
// 如果收到的数据看起来像TID数据,可以提前结束等待 |
|
|
|
if (data.trim().length() >= 12 && data.trim().matches("[0-9A-Fa-f]+")) { |
|
|
|
log.info("检测到TID格式数据,提前结束等待"); |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} else { |
|
|
|
Thread.sleep(200); // 增加等待间隔 |
|
|
|
@ -324,18 +362,14 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
} |
|
|
|
|
|
|
|
String responseStr = response.toString().trim(); |
|
|
|
log.info("完整响应数据: {}", responseStr); |
|
|
|
|
|
|
|
if (responseStr.isEmpty()) { |
|
|
|
throw new RuntimeException("未收到TID响应数据,请检查RFID标签是否正确放置"); |
|
|
|
} |
|
|
|
|
|
|
|
// 如果收到的是状态信息而不是TID数据 |
|
|
|
if (responseStr.length() > 200 || responseStr.contains("RFID READER") || |
|
|
|
responseStr.contains("FIRMWARE") || responseStr.contains("RESOLUTION")) { |
|
|
|
throw new RuntimeException("收到打印机状态信息而非TID数据,请检查标签是否为RFID标签"); |
|
|
|
} |
|
|
|
|
|
|
|
return responseStr; |
|
|
|
} |
|
|
|
|
|
|
|
@ -347,14 +381,12 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
// 生成基于时间戳的EPC,确保唯一性和有效性 |
|
|
|
long timestamp = System.currentTimeMillis(); |
|
|
|
String epc = String.format("%012X", timestamp & 0xFFFFFFFFFFFFL); |
|
|
|
|
|
|
|
// 确保EPC长度正确(12个字符) |
|
|
|
if (epc.length() > 12) { |
|
|
|
epc = epc.substring(epc.length() - 12); |
|
|
|
} else if (epc.length() < 12) { |
|
|
|
epc = String.format("%012s", epc).replace(' ', '0'); |
|
|
|
} |
|
|
|
|
|
|
|
log.info("生成EPC: {}", epc); |
|
|
|
return epc; |
|
|
|
} |
|
|
|
@ -366,9 +398,6 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
if (zplCode == null) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
|
|
|
|
log.info("开始清理ZPL代码,原始内容: {}", zplCode); |
|
|
|
|
|
|
|
// 移除所有可能导致多张打印的指令 |
|
|
|
String cleaned = zplCode |
|
|
|
.replaceAll("\\^PQ\\d+", "") // 移除 ^PQ 指令(打印份数) |
|
|
|
@ -383,12 +412,34 @@ public class ReportLabelListServiceImpl extends ServiceImpl<ReportLabelListMappe |
|
|
|
if (!cleaned.endsWith("^XZ")) { |
|
|
|
cleaned += "\n^XZ"; |
|
|
|
} |
|
|
|
|
|
|
|
log.info("ZPL清理完成 - 原始长度: {}, 清理后长度: {}, 清理后内容: {}", |
|
|
|
zplCode.length(), cleaned.length(), cleaned); |
|
|
|
return cleaned; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 清理ZPL代码并设置指定的打印份数 |
|
|
|
*/ |
|
|
|
private String cleanZplForMultiplePrint(String zplCode, int copies) { |
|
|
|
if (zplCode == null) { |
|
|
|
return ""; |
|
|
|
} |
|
|
|
// 移除所有可能导致冲突的打印指令 |
|
|
|
String cleaned = zplCode |
|
|
|
.replaceAll("\\^PQ\\d+", "") // 移除 ^PQ 指令(打印份数) |
|
|
|
.replaceAll("\\^PQ\\d+,\\d+", "") // 移除带参数的 ^PQ 指令 |
|
|
|
.replaceAll("\\^PQ\\d+,\\d+,\\d+", "") // 移除完整参数的 ^PQ 指令 |
|
|
|
.replaceAll("\\^XA", "") // 移除额外的 ^XA 开始符 |
|
|
|
.replaceAll("\\^XZ", "") // 移除所有 ^XZ 结束符,我们会在最后添加一个 |
|
|
|
.replaceAll("\\n\\s*\\n", "\n") // 清理多余的空行 |
|
|
|
.trim(); |
|
|
|
|
|
|
|
// 构建完整的ZPL代码 |
|
|
|
String finalZpl = "^XA\n" + |
|
|
|
"^PQ" + copies + "\n" + // 设置指定的打印份数 |
|
|
|
cleaned + "\n" + |
|
|
|
"^XZ"; |
|
|
|
return finalZpl; |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
* 清空输入流缓冲区 |
|
|
|
*/ |
|
|
|
|