Browse Source

rfid成功获取TID、写入epc并打印,但是98mm*28mm标签获取的第二张纸的TID

master
han\hanst 5 months ago
parent
commit
c3a2f7b544
  1. 149
      src/main/java/com/gaotao/modules/base/service/Impl/ReportLabelListServiceImpl.java

149
src/main/java/com/gaotao/modules/base/service/Impl/ReportLabelListServiceImpl.java

@ -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;
}
/**
* 清空输入流缓冲区
*/

Loading…
Cancel
Save