package com.zy.service;
|
|
import com.rfid.uhf288.RFIDTemplate;
|
import com.rfid.uhf288.RFIDTemplate.TagInfo;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
/**
|
* RFID服务类
|
* 提供RFID设备检测功能
|
* Created on 2026/01/10
|
*/
|
@Slf4j
|
@Service
|
public class RFIDService {
|
|
private RFIDTemplate rfidTemplate;
|
private String connectionType = ""; // "COM" 或 "NET"
|
|
/**
|
* 连接RFID设备(网络连接)
|
*
|
* @param ip IP地址
|
* @param port 端口号
|
* @return 连接结果
|
*/
|
public Map<String, Object> connectNetwork(String ip, Integer port) {
|
Map<String, Object> result = new HashMap<>();
|
|
try {
|
if (rfidTemplate == null) {
|
rfidTemplate = new RFIDTemplate();
|
}
|
|
if (rfidTemplate.isConnected()) {
|
result.put("success", false);
|
result.put("message", "设备已连接,请先断开连接");
|
return result;
|
}
|
|
int portNum = port != null ? port : 6000;
|
boolean connected = rfidTemplate.connectNetwork(ip, portNum);
|
|
if (connected) {
|
connectionType = "NET";
|
result.put("success", true);
|
result.put("message", "连接成功");
|
result.put("ip", ip);
|
result.put("port", portNum);
|
log.info("RFID设备网络连接成功 - IP: {}, Port: {}", ip, portNum);
|
} else {
|
result.put("success", false);
|
result.put("message", "连接失败,请检查IP和端口");
|
}
|
} catch (UnsatisfiedLinkError e) {
|
log.error("RFID设备DLL方法链接失败", e);
|
result.put("success", false);
|
result.put("message", "DLL方法链接失败: " + e.getMessage());
|
result.put("errorType", "UnsatisfiedLinkError");
|
result.put("suggestion", "请检查DLL文件是否正确,或尝试重启应用");
|
} catch (Exception e) {
|
log.error("RFID设备连接异常", e);
|
result.put("success", false);
|
result.put("message", "连接异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
|
/**
|
* 连接RFID设备(串口连接)
|
*
|
* @param port 串口号 (1=COM1, 2=COM2, 3=COM3...)
|
* @param baud 波特率 (0=9600, 1=19200, 2=38400, 3=57600, 4=115200, 5=230400, 6=460800, 7=921600)
|
* @return 连接结果
|
*/
|
public Map<String, Object> connectComPort(Integer port, Integer baud) {
|
Map<String, Object> result = new HashMap<>();
|
|
try {
|
if (rfidTemplate == null) {
|
rfidTemplate = new RFIDTemplate();
|
}
|
|
if (rfidTemplate.isConnected()) {
|
result.put("success", false);
|
result.put("message", "设备已连接,请先断开连接");
|
return result;
|
}
|
|
int portNum = port != null ? port : 3; // 默认COM3
|
boolean connected;
|
|
if (baud != null && baud >= 0 && baud <= 7) {
|
connected = rfidTemplate.connectComPort(portNum, baud.byteValue());
|
} else {
|
// 自动检测波特率
|
connected = rfidTemplate.connectComPortAuto(portNum, -1);
|
}
|
|
if (connected) {
|
connectionType = "COM";
|
result.put("success", true);
|
result.put("message", "连接成功");
|
result.put("port", "COM" + portNum);
|
log.info("RFID设备串口连接成功 - COM{}", portNum);
|
} else {
|
result.put("success", false);
|
result.put("message", "连接失败,请检查串口和波特率");
|
}
|
} catch (UnsatisfiedLinkError e) {
|
log.error("RFID设备DLL方法链接失败", e);
|
result.put("success", false);
|
result.put("message", "DLL方法链接失败: " + e.getMessage());
|
result.put("errorType", "UnsatisfiedLinkError");
|
result.put("suggestion", "请检查DLL文件是否正确,或尝试重启应用");
|
} catch (Exception e) {
|
log.error("RFID设备连接异常", e);
|
result.put("success", false);
|
result.put("message", "连接异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
|
/**
|
* 检测RFID标签(单次检测)
|
* 只在检测到标签时打印日志
|
*
|
* @param scanTime 扫描时间(单位: 100ms,默认5)
|
* @return 检测结果
|
*/
|
public Map<String, Object> detectTags(Integer scanTime) {
|
Map<String, Object> result = new HashMap<>();
|
List<Map<String, Object>> tagList = new ArrayList<>();
|
|
try {
|
if (rfidTemplate == null || !rfidTemplate.isConnected()) {
|
result.put("success", false);
|
result.put("message", "设备未连接,请先连接设备");
|
return result;
|
}
|
|
int scanTimeValue = scanTime != null ? scanTime : 5; // 默认5*100ms=500ms
|
List<TagInfo> tags = rfidTemplate.readTags(4, 0, scanTimeValue);
|
|
if (tags != null && !tags.isEmpty()) {
|
// 检测到标签时才打印日志
|
for (TagInfo tag : tags) {
|
Map<String, Object> tagMap = new HashMap<>();
|
tagMap.put("epc", tag.epc);
|
tagMap.put("rssi", tag.rssi);
|
tagMap.put("antenna", tag.antenna);
|
tagMap.put("timestamp", tag.timestamp);
|
tagList.add(tagMap);
|
|
// 打印检测到的标签信息
|
log.info(">>> 检测到RFID标签 - EPC: {}, RSSI: {}dBm, 天线: {}",
|
tag.epc, tag.rssi, tag.antenna);
|
}
|
|
result.put("success", true);
|
result.put("message", "检测到 " + tags.size() + " 个标签");
|
result.put("count", tags.size());
|
result.put("tags", tagList);
|
} else {
|
// 检测不到标签时不打印日志(只返回结果)
|
result.put("success", true);
|
result.put("message", "未检测到标签");
|
result.put("count", 0);
|
result.put("tags", tagList);
|
}
|
} catch (Exception e) {
|
log.error("RFID标签检测异常", e);
|
result.put("success", false);
|
result.put("message", "检测异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
|
/**
|
* 断开RFID设备连接
|
*
|
* @return 断开结果
|
*/
|
public Map<String, Object> disconnect() {
|
Map<String, Object> result = new HashMap<>();
|
|
try {
|
if (rfidTemplate != null && rfidTemplate.isConnected()) {
|
rfidTemplate.disconnect();
|
connectionType = "";
|
result.put("success", true);
|
result.put("message", "断开连接成功");
|
log.info("RFID设备连接已断开");
|
} else {
|
result.put("success", false);
|
result.put("message", "设备未连接");
|
}
|
} catch (Exception e) {
|
log.error("RFID设备断开连接异常", e);
|
result.put("success", false);
|
result.put("message", "断开连接异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
|
/**
|
* 获取连接状态
|
*
|
* @return 连接状态
|
*/
|
public Map<String, Object> getConnectionStatus() {
|
Map<String, Object> result = new HashMap<>();
|
|
try {
|
boolean connected = rfidTemplate != null && rfidTemplate.isConnected();
|
result.put("connected", connected);
|
result.put("connectionType", connected ? connectionType : "");
|
result.put("message", connected ? "设备已连接" : "设备未连接");
|
} catch (Exception e) {
|
log.error("获取RFID连接状态异常", e);
|
result.put("connected", false);
|
result.put("message", "获取状态异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
|
/**
|
* 诊断DLL加载状态
|
*
|
* @return 诊断信息
|
*/
|
public Map<String, Object> diagnoseDll() {
|
Map<String, Object> result = new HashMap<>();
|
|
try {
|
// 检查DLL文件是否存在(使用项目根目录的相对路径)
|
String projectBaseDir = System.getProperty("user.dir");
|
java.io.File dllFile1 = new java.io.File(projectBaseDir, "src/main/resources/lib/com_rfid_uhf288_Device.dll");
|
java.io.File dllFile2 = new java.io.File(projectBaseDir, "src/main/resources/lib/UHFReader288.dll");
|
|
// 也检查临时目录中的DLL文件
|
String tempDir = System.getProperty("java.io.tmpdir");
|
java.io.File tempDll1 = new java.io.File(tempDir + "rfid-lib/com_rfid_uhf288_Device.dll");
|
java.io.File tempDll2 = new java.io.File(tempDir + "rfid-lib/UHFReader288.dll");
|
|
Map<String, Object> dllInfo = new HashMap<>();
|
Map<String, Object> sourceDll1 = new HashMap<>();
|
sourceDll1.put("exists", dllFile1.exists());
|
sourceDll1.put("size", dllFile1.exists() ? dllFile1.length() : 0);
|
sourceDll1.put("path", dllFile1.getAbsolutePath());
|
sourceDll1.put("tempExists", tempDll1.exists());
|
sourceDll1.put("tempSize", tempDll1.exists() ? tempDll1.length() : 0);
|
sourceDll1.put("tempPath", tempDll1.getAbsolutePath());
|
if (dllFile1.exists() && tempDll1.exists()) {
|
sourceDll1.put("sizeMatch", dllFile1.length() == tempDll1.length());
|
}
|
dllInfo.put("com_rfid_uhf288_Device.dll", sourceDll1);
|
|
Map<String, Object> sourceDll2 = new HashMap<>();
|
sourceDll2.put("exists", dllFile2.exists());
|
sourceDll2.put("size", dllFile2.exists() ? dllFile2.length() : 0);
|
sourceDll2.put("path", dllFile2.getAbsolutePath());
|
sourceDll2.put("tempExists", tempDll2.exists());
|
sourceDll2.put("tempSize", tempDll2.exists() ? tempDll2.length() : 0);
|
sourceDll2.put("tempPath", tempDll2.getAbsolutePath());
|
if (dllFile2.exists() && tempDll2.exists()) {
|
sourceDll2.put("sizeMatch", dllFile2.length() == tempDll2.length());
|
}
|
dllInfo.put("UHFReader288.dll", sourceDll2);
|
result.put("dllFiles", dllInfo);
|
|
// 检查Device类是否可以实例化
|
boolean deviceCreated = false;
|
String deviceError = null;
|
try {
|
if (rfidTemplate == null) {
|
rfidTemplate = new RFIDTemplate();
|
}
|
deviceCreated = true;
|
} catch (Exception e) {
|
deviceError = e.getMessage();
|
}
|
|
result.put("deviceCreated", deviceCreated);
|
if (deviceError != null) {
|
result.put("deviceError", deviceError);
|
}
|
|
// 检查native方法是否可用(实际尝试调用验证)
|
boolean nativeMethodAvailable = false;
|
String nativeMethodError = null;
|
if (deviceCreated && rfidTemplate != null) {
|
try {
|
// 实际尝试调用native方法来验证(使用无效参数,只测试方法链接)
|
// 如果方法不存在或链接失败,会抛出UnsatisfiedLinkError
|
boolean wasConnected = rfidTemplate.isConnected();
|
if (!wasConnected) {
|
// 尝试连接一个无效的IP地址,只测试native方法是否可用
|
// 注意:这里会失败,但我们只关心方法是否链接成功
|
try {
|
// 调用connectNetwork,如果native方法链接失败会抛出UnsatisfiedLinkError
|
boolean connected = rfidTemplate.connectNetwork("127.0.0.1", 9999);
|
// 如果执行到这里,说明native方法链接成功(即使连接失败)
|
nativeMethodAvailable = true;
|
// 如果意外连接成功,断开连接
|
if (connected) {
|
rfidTemplate.disconnect();
|
}
|
} catch (UnsatisfiedLinkError e) {
|
// 如果抛出UnsatisfiedLinkError,说明native方法链接失败
|
nativeMethodError = "DLL native方法链接失败: " + e.getMessage();
|
nativeMethodAvailable = false;
|
} catch (Exception e) {
|
// 其他异常(如连接失败、网络错误等)是正常的,说明方法链接成功
|
// 检查异常类型,UnsatisfiedLinkError应该已经被上面的catch捕获
|
if (e.getCause() instanceof UnsatisfiedLinkError) {
|
nativeMethodError = "DLL native方法链接失败: " + e.getCause().getMessage();
|
nativeMethodAvailable = false;
|
} else {
|
// 其他异常说明方法链接成功,只是调用失败
|
nativeMethodAvailable = true;
|
}
|
}
|
} else {
|
// 如果已经连接,说明之前调用过native方法,方法应该是可用的
|
nativeMethodAvailable = true;
|
}
|
} catch (UnsatisfiedLinkError e) {
|
nativeMethodError = "DLL native方法链接失败: " + e.getMessage();
|
nativeMethodAvailable = false;
|
} catch (Exception e) {
|
// 其他异常不影响判断
|
if (nativeMethodError == null) {
|
nativeMethodError = "验证异常: " + e.getMessage();
|
}
|
}
|
}
|
|
result.put("nativeMethodAvailable", nativeMethodAvailable);
|
if (nativeMethodError != null) {
|
result.put("nativeMethodError", nativeMethodError);
|
}
|
|
// 提供建议
|
List<String> suggestions = new ArrayList<>();
|
if (!dllFile1.exists()) {
|
suggestions.add("DLL文件不存在: com_rfid_uhf288_Device.dll");
|
suggestions.add("请检查 src/main/resources/lib/ 目录");
|
} else {
|
suggestions.add("DLL文件存在: com_rfid_uhf288_Device.dll (大小: " + dllFile1.length() + " 字节)");
|
// 检查DLL文件是否可能是文本文件(被Maven过滤损坏)
|
if (dllFile1.length() < 1000) {
|
suggestions.add("警告:DLL文件大小异常小,可能被损坏");
|
}
|
}
|
|
if (!deviceCreated) {
|
suggestions.add("Device类实例化失败,请检查DLL文件是否存在");
|
} else if (!nativeMethodAvailable) {
|
suggestions.add("DLL已加载,但native方法不可用");
|
suggestions.add("错误信息: " + (nativeMethodError != null ? nativeMethodError : "未知错误"));
|
suggestions.add("可能原因:1. DLL版本不匹配 2. 方法签名不匹配 3. DLL文件损坏");
|
suggestions.add("解决方案:");
|
suggestions.add("1. 从demo项目(testdemo-jni)中复制DLL文件到当前项目");
|
suggestions.add("2. 确保DLL文件没有被Maven资源过滤处理");
|
suggestions.add("3. 检查DLL文件大小是否与demo项目中的一致");
|
suggestions.add("4. 尝试重新编译项目: mvn clean compile");
|
suggestions.add("5. 检查临时目录中的DLL文件: " + System.getProperty("java.io.tmpdir") + "rfid-lib");
|
} else {
|
suggestions.add("DLL加载正常,native方法可用");
|
}
|
|
result.put("suggestions", suggestions);
|
result.put("message", nativeMethodAvailable ? "DLL状态正常" : "DLL状态异常");
|
|
} catch (Exception e) {
|
log.error("RFID DLL诊断异常", e);
|
result.put("error", "诊断异常: " + e.getMessage());
|
}
|
|
return result;
|
}
|
}
|