package com.zy.service; import com.zy.core.model.RFIDSlave; import com.zy.core.properties.SlaveProperties; import com.rfid.uhf288.RFIDTemplate; import com.rfid.uhf288.RFIDTemplate.TagInfo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import javax.annotation.PostConstruct; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; /** * RFID自动连接和监控服务 * 支持多个RFID设备独立管理,每个设备独立的连接线程和检测线程 * 每个设备的autoConnect配置独立控制 * * @author Created on 2026/01/10 */ @Slf4j @Service public class RFIDAutoConnectService { @Autowired private SlaveProperties slaveProperties; @Value("${wcs-slave.rfid-config.reconnectInterval:5}") private Integer globalReconnectInterval; @Value("${wcs-slave.rfid-config.tagScanInterval:500}") private Integer globalTagScanInterval; @Value("${wcs-slave.rfid-config.tagScanTime:10}") private Integer globalTagScanTime; // 存储每个设备的连接和线程信息 private final Map deviceManagers = new ConcurrentHashMap<>(); /** * 设备管理器 - 管理单个RFID设备的连接和检测 */ private static class DeviceManager { final RFIDSlave config; final RFIDTemplate template; final AtomicBoolean running = new AtomicBoolean(false); final AtomicBoolean connected = new AtomicBoolean(false); Thread connectThread; Thread scanThread; final int reconnectInterval; final long tagScanInterval; final int tagScanTime; int reconfigCounter = 0; volatile List latestTags = new ArrayList<>(); // 最新检测到的标签 DeviceManager(RFIDSlave config, Integer reconnectInterval, Integer tagScanInterval, Integer tagScanTime) { this.config = config; this.template = new RFIDTemplate(); this.reconnectInterval = reconnectInterval != null ? reconnectInterval : 5; this.tagScanInterval = tagScanInterval != null ? tagScanInterval : 500; this.tagScanTime = tagScanTime != null ? tagScanTime : 10; } void start() { if (running.get()) { return; } running.set(true); // 启动连接线程 // 注意:设置为非守护线程,确保应用运行期间线程一直运行 connectThread = new Thread(this::connectLoop, String.format("RFID-Connect-%d-%s", config.getId(), config.getIp())); connectThread.setDaemon(false); // 改为非守护线程,确保应用运行期间一直运行 connectThread.start(); // 启动标签检测线程 scanThread = new Thread(this::scanLoop, String.format("RFID-Scan-%d-%s", config.getId(), config.getIp())); scanThread.setDaemon(false); // 改为非守护线程,确保应用运行期间一直运行 scanThread.start(); } void stop() { running.set(false); connected.set(false); if (connectThread != null) { connectThread.interrupt(); } if (scanThread != null) { scanThread.interrupt(); } try { if (connectThread != null) { connectThread.join(2000); } if (scanThread != null) { scanThread.join(2000); } } catch (InterruptedException e) { Thread.currentThread().interrupt(); } if (template != null && template.isConnected()) { try { template.disconnect(); } catch (Exception e) { log.error("RFID设备[{}]断开连接异常", config.getId(), e); } } } /** * 连接循环 - 负责连接和重连 * 特别处理UnsatisfiedLinkError,确保DLL方法链接失败时也会定期重连 */ private void connectLoop() { log.info("RFID设备[{}]连接线程启动 - IP: {}, Port: {}", config.getId(), config.getIp(), config.getPort()); while (running.get()) { try { if (!connected.get()) { log.info("========== RFID设备[{}]尝试连接 ==========", config.getId()); log.info("IP: {}, Port: {}", config.getIp(), config.getPort()); // 尝试连接 boolean success = false; try { success = template.connectNetwork(config.getIp(), config.getPort()); } catch (UnsatisfiedLinkError e) { // DLL方法链接失败,记录错误但继续重连 log.error("RFID设备[{}] DLL方法链接失败 - UnsatisfiedLinkError", config.getId()); log.error("错误信息: {}", e.getMessage()); log.error("可能原因:1. DLL版本不匹配 2. 方法签名不匹配 3. DLL未正确加载"); log.warn("将在{}秒后重试连接", reconnectInterval); success = false; } if (success) { connected.set(true); log.info("✓ RFID设备[{}]连接成功!IP: {}, Port: {}", config.getId(), config.getIp(), config.getPort()); } else { log.warn("✗ RFID设备[{}]连接失败,{}秒后重试", config.getId(), reconnectInterval); Thread.sleep(reconnectInterval * 1000L); } } else { // 已连接,检查连接状态 if (!template.isConnected()) { log.warn("RFID设备[{}]连接已断开,准备重连", config.getId()); connected.set(false); } else { // 连接正常,定期重新配置天线(处理天线插拔情况) // 每5次循环(约50秒)重新配置一次天线,确保插拔后能自动检测 reconfigCounter++; if (reconfigCounter >= 5) { reconfigCounter = 0; log.debug("RFID设备[{}]定期重新配置天线(处理天线插拔)", config.getId()); boolean reconfigured = template.reconfigureAntenna(); if (reconfigured) { // log.info("RFID设备[{}]天线重新配置成功,所有天线已启用", config.getId()); } } // 等待一段时间后再次检查 Thread.sleep(reconnectInterval * 1000L); } } } catch (InterruptedException e) { log.info("RFID设备[{}]连接线程被中断", config.getId()); Thread.currentThread().interrupt(); break; } catch (UnsatisfiedLinkError e) { // DLL方法链接失败,记录错误并继续重连 log.error("RFID设备[{}]连接线程 - DLL方法链接失败", config.getId()); log.error("错误信息: {}", e.getMessage()); log.error("可能原因:1. DLL版本不匹配 2. 方法签名不匹配 3. DLL未正确加载"); log.warn("将在{}秒后重试连接", reconnectInterval); connected.set(false); try { Thread.sleep(reconnectInterval * 1000L); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } catch (Exception e) { log.error("RFID设备[{}]连接线程异常", config.getId(), e); connected.set(false); try { Thread.sleep(reconnectInterval * 1000L); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } log.info("RFID设备[{}]连接线程已停止", config.getId()); } /** * 标签检测循环 - 持续检测并打印标签 * 特别处理UnsatisfiedLinkError,确保DLL方法链接失败时不影响重连 */ private void scanLoop() { log.info("RFID设备[{}]标签检测线程启动 - IP: {}", config.getId(), config.getIp()); while (running.get()) { try { if (connected.get() && template.isConnected()) { try { List tags = template.readTags(4, 0, tagScanTime); latestTags = tags != null ? new ArrayList<>(tags) : new ArrayList<>(); if (tags != null && !tags.isEmpty()) { printTags(tags); } } catch (UnsatisfiedLinkError e) { // DLL方法链接失败,标记为未连接,让连接线程重连 log.error("RFID设备[{}]标签检测 - DLL方法链接失败", config.getId()); log.error("错误信息: {}", e.getMessage()); log.warn("连接状态已标记为断开,连接线程将尝试重连"); connected.set(false); // 等待一段时间后继续 Thread.sleep(reconnectInterval * 1000L); continue; } } else { // 未连接,等待一段时间 Thread.sleep(1000); } // 等待指定间隔 Thread.sleep(tagScanInterval); } catch (InterruptedException e) { log.info("RFID设备[{}]标签检测线程被中断", config.getId()); Thread.currentThread().interrupt(); break; } catch (UnsatisfiedLinkError e) { // DLL方法链接失败,标记为未连接 log.error("RFID设备[{}]标签检测线程 - DLL方法链接失败", config.getId()); log.error("错误信息: {}", e.getMessage()); connected.set(false); try { Thread.sleep(reconnectInterval * 1000L); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } catch (Exception e) { log.error("RFID设备[{}]标签检测线程异常", config.getId(), e); try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } log.info("RFID设备[{}]标签检测线程已停止", config.getId()); } private void printTags(List tags) { if (tags == null || tags.isEmpty()) { return; } for (TagInfo tag : tags) { log.info("RFID设备[{}]检测到标签: EPC={}, RSSI={}dBm, 天线={}", config.getId(), tag.epc, tag.rssi, tag.antenna); } } } /** * 系统启动时初始化所有配置了autoConnect=true的设备 */ @PostConstruct public void init() { log.info("========== RFID自动连接服务启动 =========="); if (slaveProperties.getRfid() == null || slaveProperties.getRfid().isEmpty()) { log.info("未配置RFID设备"); return; } log.info("RFID全局配置 - 重连间隔: {}秒, 检测间隔: {}毫秒, 扫描时间: {} * 100ms", globalReconnectInterval, globalTagScanInterval, globalTagScanTime); // 遍历所有RFID设备配置 for (RFIDSlave rfidConfigItem : slaveProperties.getRfid()) { if (rfidConfigItem == null) { continue; } // 检查是否启用自动连接 Boolean autoConnect = rfidConfigItem.getAutoConnect(); if (autoConnect == null || !autoConnect) { log.info("RFID设备[{}] - IP: {}, Port: {} - 未启用自动连接", rfidConfigItem.getId(), rfidConfigItem.getIp(), rfidConfigItem.getPort()); continue; } // 验证配置 if (rfidConfigItem.getIp() == null || rfidConfigItem.getPort() == null) { log.warn("RFID设备[{}]配置不完整,跳过自动连接", rfidConfigItem.getId()); continue; } // 创建设备管理器并启动 DeviceManager manager = new DeviceManager(rfidConfigItem, globalReconnectInterval, globalTagScanInterval, globalTagScanTime); deviceManagers.put(rfidConfigItem.getId(), manager); manager.start(); log.info("RFID设备[{}]自动连接已启动 - IP: {}, Port: {}", rfidConfigItem.getId(), rfidConfigItem.getIp(), rfidConfigItem.getPort()); } log.info("RFID自动连接服务已启动,共 {} 个设备启用自动连接", deviceManagers.size()); } /** * 手动停止所有RFID设备连接(通过API调用) * 注意:移除了@PreDestroy,服务不会自动关闭,只能通过API手动关闭 */ public void stopAll() { log.info("========== RFID自动连接服务手动关闭 =========="); // 停止所有设备管理器 for (Map.Entry entry : deviceManagers.entrySet()) { try { log.info("停止RFID设备[{}]自动连接", entry.getKey()); entry.getValue().stop(); } catch (Exception e) { log.error("停止RFID设备[{}]自动连接异常", entry.getKey(), e); } } deviceManagers.clear(); log.info("RFID自动连接服务已关闭"); } /** * 手动停止指定RFID设备连接(通过API调用) */ public boolean stopDevice(Integer deviceId) { DeviceManager manager = deviceManagers.get(deviceId); if (manager == null) { log.warn("RFID设备[{}]未启用自动连接或不存在", deviceId); return false; } try { log.info("手动停止RFID设备[{}]自动连接", deviceId); manager.stop(); deviceManagers.remove(deviceId); return true; } catch (Exception e) { log.error("停止RFID设备[{}]自动连接异常", deviceId, e); return false; } } /** * 手动启动指定RFID设备连接(通过API调用) */ public boolean startDevice(Integer deviceId) { // 检查设备是否已经在运行 if (deviceManagers.containsKey(deviceId)) { DeviceManager manager = deviceManagers.get(deviceId); if (manager.running.get()) { log.warn("RFID设备[{}]已经在运行", deviceId); return false; } } // 查找配置 RFIDSlave config = null; for (RFIDSlave rfidConfigItem : slaveProperties.getRfid()) { if (rfidConfigItem != null && rfidConfigItem.getId().equals(deviceId)) { config = rfidConfigItem; break; } } if (config == null) { log.warn("RFID设备[{}]配置不存在", deviceId); return false; } // 验证配置 if (config.getIp() == null || config.getPort() == null) { log.warn("RFID设备[{}]配置不完整", deviceId); return false; } // 创建设备管理器并启动 DeviceManager manager = new DeviceManager(config, globalReconnectInterval, globalTagScanInterval, globalTagScanTime); deviceManagers.put(deviceId, manager); manager.start(); log.info("RFID设备[{}]手动启动成功 - IP: {}, Port: {}", deviceId, config.getIp(), config.getPort()); return true; } /** * 获取设备连接状态 */ public Map getDeviceStatus(Integer deviceId) { Map result = new java.util.HashMap<>(); DeviceManager manager = deviceManagers.get(deviceId); if (manager == null) { result.put("exists", false); result.put("message", "设备未启用自动连接"); return result; } result.put("exists", true); result.put("connected", manager.connected.get()); result.put("running", manager.running.get()); result.put("ip", manager.config.getIp()); result.put("port", manager.config.getPort()); result.put("templateConnected", manager.template.isConnected()); return result; } /** * 获取所有设备状态 */ public List> getAllDeviceStatus() { List> result = new ArrayList<>(); for (Map.Entry entry : deviceManagers.entrySet()) { Map status = getDeviceStatus(entry.getKey()); status.put("deviceId", entry.getKey()); result.add(status); } return result; } /** * 重新配置指定设备的天线(用于天线插拔后重新配置) */ public boolean reconfigureAntenna(Integer deviceId) { DeviceManager manager = deviceManagers.get(deviceId); if (manager == null) { log.warn("RFID设备[{}]未启用自动连接或不存在", deviceId); return false; } if (!manager.template.isConnected()) { log.warn("RFID设备[{}]未连接,无法配置天线", deviceId); return false; } log.info("手动重新配置RFID设备[{}]天线", deviceId); return manager.template.reconfigureAntenna(); } public List> getDeviceTags(Integer deviceId, String ip, Integer antenna) { List> result = new ArrayList<>(); DeviceManager manager = null; if (ip != null && !ip.isEmpty()) { for (DeviceManager m : deviceManagers.values()) { if (ip.equals(m.config.getIp())) { manager = m; break; } } } else if (deviceId != null) { manager = deviceManagers.get(deviceId); } if (manager == null || !manager.connected.get() || !manager.template.isConnected()) { return result; } List tags = manager.latestTags; if (tags == null || tags.isEmpty()) { return result; } for (TagInfo tag : tags) { if (antenna != null && tag.antenna != antenna) { continue; } Map tagMap = new java.util.HashMap<>(); tagMap.put("epc", tag.epc); tagMap.put("rssi", tag.rssi); tagMap.put("antenna", tag.antenna); tagMap.put("timestamp", tag.timestamp); tagMap.put("deviceId", manager.config.getId()); tagMap.put("deviceIp", manager.config.getIp()); result.add(tagMap); } return result; } public List> queryDeviceTags(Integer deviceId, String ip, Integer antenna) { List> result = new ArrayList<>(); DeviceManager manager = null; if (ip != null && !ip.isEmpty()) { for (DeviceManager m : deviceManagers.values()) { if (ip.equals(m.config.getIp())) { manager = m; break; } } } else if (deviceId != null) { manager = deviceManagers.get(deviceId); } if (manager == null || !manager.connected.get() || !manager.template.isConnected()) { return result; } try { List tags = manager.template.readTags(4, 0, manager.tagScanTime); if (tags != null && !tags.isEmpty()) { for (TagInfo tag : tags) { if (antenna != null && tag.antenna != antenna) { continue; } Map tagMap = new java.util.HashMap<>(); tagMap.put("epc", tag.epc); tagMap.put("rssi", tag.rssi); tagMap.put("antenna", tag.antenna); tagMap.put("timestamp", tag.timestamp); tagMap.put("deviceId", manager.config.getId()); tagMap.put("deviceIp", manager.config.getIp()); result.add(tagMap); } } } catch (Exception e) { log.error("查询RFID设备[{}]标签异常", deviceId != null ? deviceId : ip, e); } return result; } }