From 6b53373bf1cc50b18b0a5d17d8e7e25118068640 Mon Sep 17 00:00:00 2001
From: chen.llin <1442464845@qq.comm>
Date: 星期二, 13 一月 2026 14:23:52 +0800
Subject: [PATCH] rfid调试正常代码
---
src/main/java/com/zy/core/model/RFIDSlave.java | 20
src/main/resources/application-prod.yml | 33
src/main/resources/lib/UHFReader288.dll | 0
pom.xml | 18
src/main/java/com/zy/core/thread/RFIDThread.java | 322 ++++++
src/main/java/com/zy/rfid/RFIDTemplate.java | 506 ++++++++++
src/main/java/com/zy/core/ServerBootstrap.java | 19
src/main/resources/lib/com_rfid_uhf288_Device.dll | 0
src/main/java/com/rfid/uhf288/Device.java | 266 +++++
src/main/java/com/zy/service/RFIDService.java | 393 +++++++
src/main/java/com/zy/service/RFIDAutoConnectService.java | 557 +++++++++++
src/main/java/com/zy/core/enums/SlaveType.java | 3
src/main/java/com/zy/core/cache/OutputQueue.java | 2
src/main/resources/application-dev.yml | 33
src/main/java/com/rfid/uhf288/RFIDTemplate.java | 505 ++++++++++
src/main/java/com/zy/controller/RFIDController.java | 270 +++++
16 files changed, 2,944 insertions(+), 3 deletions(-)
diff --git a/pom.xml b/pom.xml
index 32da556..cfc062e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -195,6 +195,24 @@
<build>
<finalName>wcs</finalName>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>**/com_rfid_uhf288_Device.dll</exclude>
+ <exclude>**/UHFReader288.dll</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>**/com_rfid_uhf288_Device.dll</include>
+ <include>**/UHFReader288.dll</include>
+ </includes>
+ </resource>
+ </resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
diff --git a/src/main/java/com/rfid/uhf288/Device.java b/src/main/java/com/rfid/uhf288/Device.java
new file mode 100644
index 0000000..531c944
--- /dev/null
+++ b/src/main/java/com/rfid/uhf288/Device.java
@@ -0,0 +1,266 @@
+package com.rfid.uhf288;
+
+import java.io.File;
+
+/**
+ * RFID UHF288璁惧JNI鎺ュ彛
+ * 瀵瑰簲DLL: com_rfid_uhf288_Device.dll
+ *
+ * 鍙傝�僤emo椤圭洰鐨勫姞杞芥柟寮忥細鍦╯tatic浠g爜鍧椾腑鍔犺浇DLL
+ * 娉ㄦ剰锛欴LL鍙兘涓嶆敮鎸佸绾跨▼骞跺彂璁块棶锛岄渶瑕佸悓姝ヤ繚鎶�
+ */
+public class Device {
+
+ // DLL鍔犺浇鐘舵�佹爣蹇�
+ private static volatile boolean libraryLoaded = false;
+ // DLL鍔犺浇閿侊紝纭繚鍙姞杞戒竴娆�
+ private static final Object loadLock = new Object();
+
+ /**
+ * 闈欐�佷唬鐮佸潡锛氬姞杞紻LL搴�
+ * 鍙傝�僤emo椤圭洰鐨勬柟寮忥紝浼樺厛浣跨敤缁濆璺緞鍔犺浇锛屽鏋滃け璐ュ垯灏濊瘯浠庣郴缁烶ATH鍔犺浇
+ */
+ static {
+ loadLibrary();
+ }
+
+ /**
+ * 鍔犺浇DLL搴�
+ * 浼樺厛浣跨敤缁濆璺緞鐩存帴鍔犺浇锛屽鏋滃け璐ュ垯灏濊瘯浠庣郴缁烶ATH鍔犺浇锛堝弬鑰僤emo椤圭洰鐨勬柟寮忥級
+ * 浣跨敤鍚屾閿佺‘淇濈嚎绋嬪畨鍏紝閬垮厤澶氱嚎绋嬪悓鏃跺姞杞藉鑷村啿绐�
+ */
+ private static void loadLibrary() {
+ // 濡傛灉宸茬粡鍔犺浇锛岀洿鎺ヨ繑鍥�
+ if (libraryLoaded) {
+ return;
+ }
+
+ // 鍚屾鍔犺浇锛岀‘淇濆彧鍔犺浇涓�娆�
+ synchronized (loadLock) {
+ // 鍙岄噸妫�鏌ワ紝閬垮厤閲嶅鍔犺浇
+ if (libraryLoaded) {
+ return;
+ }
+
+ String mainDllName = "com_rfid_uhf288_Device.dll";
+ String depDllName = "UHFReader288.dll"; // 渚濊禆鐨凞LL
+
+ // 鏂规硶1: 浣跨敤缁濆璺緞鐩存帴鍔犺浇DLL
+ try {
+ // 浣跨敤鐪熷疄璺緞鍔犺浇DLL
+ String projectBaseDir = "D:\\work\\work-zy\\zy-wcs";
+ String mainDllPath = projectBaseDir + "\\src\\main\\resources\\lib\\" + mainDllName;
+ String depDllPath = projectBaseDir + "\\src\\main\\resources\\lib\\" + depDllName;
+
+ File mainDllFile = new File(mainDllPath);
+ File depDllFile = new File(depDllPath);
+
+ if (mainDllFile.exists() && mainDllFile.canRead()) {
+ // 鍏堝皾璇曞姞杞戒緷璧朌LL锛堝鏋滃瓨鍦級
+ if (depDllFile.exists() && depDllFile.canRead()) {
+ try {
+ System.load(depDllPath);
+ System.out.println("鎴愬姛鍔犺浇渚濊禆DLL: " + depDllName + " (璺緞: " + depDllPath + ")");
+ } catch (UnsatisfiedLinkError e) {
+ // 渚濊禆DLL鍙兘宸茬粡鍔犺浇杩囷紝鎴栬�呭姞杞藉け璐�
+ // 濡傛灉閿欒淇℃伅涓嶆槸"宸插姞杞�"锛屽垯鎵撳嵃璀﹀憡
+ if (e.getMessage() == null || !e.getMessage().contains("already loaded")) {
+ System.err.println("璀﹀憡: 渚濊禆DLL鍔犺浇澶辫触锛堢户缁皾璇曞姞杞戒富DLL锛�: " + depDllName);
+ System.err.println("閿欒淇℃伅: " + e.getMessage());
+ }
+ }
+ }
+
+ // 鍔犺浇涓籇LL
+ System.load(mainDllPath);
+ System.out.println("鎴愬姛浠庣粷瀵硅矾寰勫姞杞紻LL: " + mainDllName + " (璺緞: " + mainDllPath + ")");
+ System.out.println("DLL鏂囦欢澶у皬: " + mainDllFile.length() + " 瀛楄妭");
+ libraryLoaded = true;
+ return;
+ } else {
+ System.err.println("DLL鏂囦欢涓嶅瓨鍦ㄦ垨涓嶅彲璇�: " + mainDllPath);
+ }
+ } catch (UnsatisfiedLinkError e) {
+ // 濡傛灉鏄緷璧栧簱閿欒锛屾彁渚涙洿璇︾粏鐨勯敊璇俊鎭�
+ if (e.getMessage() != null && e.getMessage().contains("dependent libraries")) {
+ System.err.println("DLL渚濊禆搴撳姞杞藉け璐�: " + e.getMessage());
+ System.err.println("璇风‘淇濇墍鏈変緷璧朌LL鏂囦欢閮藉湪鍚屼竴鐩綍涓�");
+ }
+ System.err.println("浠庣粷瀵硅矾寰勫姞杞紻LL澶辫触: " + e.getMessage());
+ e.printStackTrace();
+ } catch (Exception e) {
+ System.err.println("浠庣粷瀵硅矾寰勫姞杞紻LL澶辫触: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ /* 鏂规硶2锛堝凡娉ㄩ噴锛�: 灏濊瘯浠巖esources鐩綍鎻愬彇鍒颁复鏃剁洰褰曞姞杞�
+ try {
+ // 鍒涘缓涓撻棬鐨勪复鏃剁洰褰曟潵瀛樻斁鎵�鏈塂LL锛堝彧鍒涘缓涓�娆★級
+ if (tempLibDir == null) {
+ tempLibDir = createTempLibDirectory();
+ }
+
+ if (tempLibDir != null && tempLibDir.exists()) {
+ // 鍏堟彁鍙栨墍鏈塂LL鍒板悓涓�鐩綍
+ File depDll = extractDllToDir("/lib/" + depDllName, depDllName, tempLibDir);
+ File mainDll = extractDllToDir("/lib/" + mainDllName, mainDllName, tempLibDir);
+
+ if (mainDll != null && mainDll.exists()) {
+ // 鍏堝皾璇曞姞杞戒緷璧朌LL锛堝鏋滃瓨鍦級
+ if (depDll != null && depDll.exists()) {
+ try {
+ System.load(depDll.getAbsolutePath());
+ System.out.println("鎴愬姛鍔犺浇渚濊禆DLL: " + depDllName + " (璺緞: " + depDll.getAbsolutePath() + ")");
+ } catch (UnsatisfiedLinkError e) {
+ if (e.getMessage() == null || !e.getMessage().contains("already loaded")) {
+ System.err.println("璀﹀憡: 渚濊禆DLL鍔犺浇澶辫触锛堢户缁皾璇曞姞杞戒富DLL锛�: " + depDllName);
+ System.err.println("閿欒淇℃伅: " + e.getMessage());
+ }
+ }
+ }
+
+ System.load(mainDll.getAbsolutePath());
+ System.out.println("鎴愬姛浠巖esources鐩綍鍔犺浇DLL: " + mainDllName + " (璺緞: " + mainDll.getAbsolutePath() + ")");
+ return;
+ }
+ }
+ } catch (Exception e) {
+ System.err.println("浠巖esources鐩綍鍔犺浇DLL澶辫触: " + e.getMessage());
+ e.printStackTrace();
+ }
+ */
+
+ // 鏂规硶3: 灏濊瘯浠庣郴缁烶ATH鎴杍ava.library.path鍔犺浇锛堝弬鑰僤emo椤圭洰鐨勬柟寮忥級
+ try {
+ System.loadLibrary("com_rfid_uhf288_Device");
+ System.out.println("鎴愬姛浠庣郴缁烶ATH鍔犺浇DLL: " + mainDllName);
+ System.out.println("娉ㄦ剰锛氬鏋滃悗缁璶ative鏂规硶璋冪敤澶辫触锛岃妫�鏌LL鐗堟湰鏄惁鍖归厤");
+ libraryLoaded = true;
+ return;
+ } catch (UnsatisfiedLinkError e) {
+ System.err.println("鏃犳硶浠庣郴缁烶ATH鍔犺浇RFID璁惧DLL搴�: " + mainDllName);
+ System.err.println("閿欒淇℃伅: " + e.getMessage());
+ System.err.println("璇风‘淇滵LL鏂囦欢鍦ㄧ郴缁烶ATH鎴栭」鐩甽ib鐩綍涓�");
+ e.printStackTrace();
+ }
+
+ // 濡傛灉鎵�鏈夋柟娉曢兘澶辫触锛岃褰曢敊璇�
+ if (!libraryLoaded) {
+ System.err.println("========================================");
+ System.err.println("RFID璁惧DLL鍔犺浇澶辫触锛�");
+ System.err.println("璇锋鏌ワ細");
+ System.err.println("1. DLL鏂囦欢鏄惁瀛樺湪: D:\\work\\work-zy\\zy-wcs\\src\\main\\resources\\lib\\com_rfid_uhf288_Device.dll");
+ System.err.println("2. DLL鏂囦欢鏄惁瀹屾暣");
+ System.err.println("3. DLL鏂囦欢鏄惁鍦ㄧ郴缁烶ATH涓�");
+ System.err.println("4. 浠巇emo椤圭洰涓鍒舵纭殑DLL鏂囦欢");
+ System.err.println("========================================");
+ }
+ }
+ }
+
+ /**
+ * @param args
+ */
+ public native int OpenComPort(int port,byte[]comAddr,byte baud,int[]PortHandle);
+ public native int CloseSpecComPort(int PortHandle);
+ public native int OpenNetPort(int Port,String IPaddr,byte[]comAddr,int[] PortHandle);
+ public native int CloseNetPort(int PortHandle);
+ public native int GetReaderInformation(byte[]comAddr,byte[]versionInfo,byte[]readerType,byte[]trType,byte[]dmaxfre,
+ byte[]dminfre,byte[]powerdBm,byte[]InventoryScanTime,byte[]Ant,byte[]BeepEn,
+ byte[]OutputRep,byte[]CheckAnt,int PortHandle);
+
+ public native int Inventory_G2(byte[]comAddr,byte QValue,byte Session,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,byte MaskFlag,byte AdrTID,byte LenTID,byte TIDFlag,byte Target,
+ byte InAnt,byte Scantime,byte FastFlag,byte[]pEPCList,byte[] Ant,int[]Totallen,
+ int[]CardNum,int PortHandle);
+
+ public native int InventoryMix_G2(byte[]comAddr,byte QValue,byte Session,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,byte MaskFlag,byte ReadMem,byte[]ReadAdr,byte ReadLen,byte[]Psd,
+ byte Target,byte InAnt,byte Scantime,byte FastFlag,byte[]pEPCList,byte[] Ant,
+ int[]Totallen,int[]CardNum,int PortHandle);
+
+ public native int ReadData_G2(byte[]comAddr,byte[] EPC,byte ENum,byte Mem,byte WordPtr,byte Num,byte[]Password,
+ byte MaskMem,byte[]MaskAdr,byte MaskLen,byte[]MaskData,byte[]Data,int[]Errorcode,
+ int PortHandle);
+
+ public native int WriteData_G2(byte[]comAddr,byte[] EPC,byte WNum,byte ENum,byte Mem,byte WordPtr,byte[] Wdt,
+ byte[]Password,byte MaskMem,byte[]MaskAdr,byte MaskLen,byte[]MaskData,int[]Errorcode,
+ int PortHandle);
+
+ public native int WriteEPC_G2(byte[]comAddr,byte[] Password,byte[] EPC,byte ENum,int[]Errorcode,int PortHandle);
+
+ public native int KillTag_G2(byte[]comAddr,byte[] EPC,byte ENum,byte[] Killpwd,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,int[]Errorcode,int PortHandle);
+ public native int Lock_G2(byte[]comAddr,byte[] EPC,byte ENum,byte selectid,byte setprotect,byte[] Password,byte MaskMem,
+ byte[]MaskAdr,byte MaskLen, byte[]MaskData,int[]Errorcode,int PortHandle);
+ public native int BlockErase_G2(byte[]comAddr,byte[] EPC,byte ENum,byte Mem,byte WordPtr,byte Num,byte[] Password,
+ byte MaskMem,byte[]MaskAdr,byte MaskLen, byte[]MaskData,int[]Errorcode,int PortHandle);
+ public native int SetRegion(byte[]comAddr, byte dmaxfre,byte dminfre,int PortHandle);
+ public native int SetAddress(byte[]comAddr, byte ComAdrData,int PortHandle);
+ public native int SetInventoryScanTime(byte[]comAddr, byte ScanTime,int PortHandle);
+ public native int SetBaudRate(byte[]comAddr, byte baud,int PortHandle);
+ public native int SetRfPower(byte[]comAddr, byte PowerDbm,int PortHandle);
+ public native int SetWorkMode(byte[]comAddr, byte Read_mode,int PortHandle);
+ public native int GetSystemParameter(byte[]comAddr,byte[]Read_mode,byte[]Accuracy,byte[]RepCondition,byte[]RepPauseTime,
+ byte[]ReadPauseTim,byte[]TagProtocol,byte[]MaskMem,byte[]MaskAdr,byte[]MaskLen,
+ byte[]MaskData, byte[]TriggerTime,byte[]AdrTID,byte[]LenTID,int PortHandle);
+ public native int SetAntennaMultiplexing(byte[]comAddr, byte Ant,int PortHandle);
+ public native int SetAntenna(byte[]comAddr, byte SetOnce,byte AntCfg1,byte AntCfg2,int PortHandle);
+ public native int WriteRfPower(byte[]comAddr, byte PowerDbm,int PortHandle);
+ public native int ReadRfPower(byte[]comAddr, byte[] PowerDbm,int PortHandle);
+ public native int RetryTimes(byte[]comAddr, byte[] Times,int PortHandle);
+ public native int SetReadMode(byte[]comAddr, byte ReadMode,int PortHandle);
+ public native int SetCheckAnt(byte[]comAddr, byte CheckAnt,int PortHandle);
+ public native int GetSeriaNo(byte[]comAddr, byte[] SeriaNo,int PortHandle);
+ public native int SetBeepNotification(byte[]comAddr, byte BeepEn,int PortHandle);
+ public native int SetReal_timeClock(byte[]comAddr, byte[] paramer,int PortHandle);
+ public native int GetTime(byte[]comAddr, byte[] paramer,int PortHandle);
+ public native int SetDRM(byte[]comAddr, byte DRM,int PortHandle);
+ public native int GetDRM(byte[]comAddr, byte[] DRM,int PortHandle);
+ public native int GetReaderTemperature(byte[]comAddr, byte[] PlusMinus,byte[]Temperature,int PortHandle);
+ public native int MeasureReturnLoss(byte[]comAddr, byte[] TestFreq,byte Ant,byte[]ReturnLoss,int PortHandle);
+ public native int SetGPIO(byte[] comAddr, byte OutputPin, int PortHandle);
+ public native int GetGPIOStatus(byte[] ComAdr, byte[] OutputPin, int PortHandle);
+ public native int ReadActiveModeData(byte[] ScanModeData, int[] ValidDatalength, int PortHandle);
+ public native int SetRelay(byte[] comAddr, byte RelayTime, int PortHandle);
+ public native int SwitchProtocol(byte[] comAddr, byte[] protocol, int PortHandle);
+
+ public native int Inventory_JB(byte[]comAddr,byte Algo,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,byte MaskFlag, byte InAnt,byte Scantime,byte FastFlag,byte[]pEPCList,byte[] Ant,int[]Totallen,
+ int[]CardNum,int PortHandle);
+
+ public native int InventoryMix_JB(byte[]comAddr,byte Algo,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,byte MaskFlag,byte ReadMem,byte[]ReadAdr,byte ReadLen,byte[]Psd,
+ byte InAnt,byte Scantime,byte FastFlag,byte[]pEPCList,byte[] Ant,
+ int[]Totallen,int[]CardNum,int PortHandle);
+
+ public native int ReadData_JB(byte[]comAddr,byte[] TagID,byte TNum,byte Mem,int WordPtr,byte WordNum,byte[]Password,
+ byte MaskMem,byte[]MaskAdr,byte MaskLen,byte[]MaskData,byte[]Data,int[]Errorcode,
+ int PortHandle);
+
+ public native int WriteData_JB(byte[]comAddr,byte[] TagID,byte WNum,byte TNum,byte Mem,int WordPtr,byte[] Wdt,
+ byte[]Password,byte MaskMem,byte[]MaskAdr,byte MaskLen,byte[]MaskData,int[]Errorcode,
+ int PortHandle);
+ public native int KillTag_JB(byte[]comAddr,byte[] TagID,byte TNum,byte[] Killpwd,byte MaskMem,byte[]MaskAdr,byte MaskLen,
+ byte[]MaskData,int[]Errorcode,int PortHandle);
+ public native int Lock_JB(byte[]comAddr,byte[] EPC,byte TNum,byte LockMem,byte Cfg,byte Action,byte[] Password,byte MaskMem,
+ byte[]MaskAdr,byte MaskLen, byte[]MaskData,int[]Errorcode,int PortHandle);
+ public native int BlockErase_JB(byte[]comAddr,byte[] EPC,byte TNum,byte Mem,int WordPtr,int Num,byte[] Password,
+ byte MaskMem,byte[]MaskAdr,byte MaskLen, byte[]MaskData,int[]Errorcode,int PortHandle);
+
+
+ public native int SetCfgParameter(byte[] comAddr, byte opt, byte cfgNum, byte[]data,int len, int FrmHandle);
+
+ public native int GetCfgParameter (byte[] comAddr, byte cfgNum,byte[] data, int[] len, int FrmHandle);
+
+ public native int SetProfile(byte[] comAddr, byte[] Profile, int FrmHandle);
+ public native int SetExtProfile(byte[] comAddr,byte Opt, int[] Profile, int FrmHandle);
+
+ public native int GetEx10Version(byte[] comAddr,byte[] Version, byte[] ex10Tpye, int FrmHandle);
+
+ public static void main(String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
diff --git a/src/main/java/com/rfid/uhf288/RFIDTemplate.java b/src/main/java/com/rfid/uhf288/RFIDTemplate.java
new file mode 100644
index 0000000..2ab6afb
--- /dev/null
+++ b/src/main/java/com/rfid/uhf288/RFIDTemplate.java
@@ -0,0 +1,505 @@
+package com.rfid.uhf288;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RFID璁惧鎿嶄綔妯℃澘 - 妯″潡鍖栬璁�
+ * 鍙傝�僤emo椤圭洰锛屼絾鍙寘鍚熀鏈鍙栧姛鑳斤紙绫讳技鍙傝�冮」鐩畓y-wcs-czbrwcs涓殑鍔熻兘锛�
+ * Created by chen.lin on 2026/01/10
+ *
+ * 鍔熻兘妯″潡锛�
+ * 1. 杩炴帴妯″潡 - 涓插彛杩炴帴 / 缃戠粶杩炴帴锛堢嫭绔嬶級
+ * 2. 璇诲彇妯″潡 - 鐩樼偣鏍囩锛堢嫭绔嬶級
+ *
+ * 浣跨敤鏂瑰紡锛�
+ * 1. 鍒涘缓瀹炰緥
+ * 2. 閫夋嫨杩炴帴鏂瑰紡锛堜覆鍙f垨缃戠粶锛�
+ * 3. 杩炴帴鎴愬姛鍚庯紝璋冪敤璇诲彇鍔熻兘
+ * 4. 浣跨敤瀹屾瘯鍚庡叧闂繛鎺�
+ */
+@Slf4j
+public class RFIDTemplate {
+
+ // ==================== 鍩虹缁勪欢 ====================
+ private Device reader;
+ private int portHandle = -1;
+ private byte[] comAddr = new byte[1];
+
+ // 杩炴帴鐘舵��
+ private boolean isConnected = false;
+ private String connectionType = ""; // "COM" 鎴� "NET"
+
+ // ==================== 鍒濆鍖� ====================
+
+ /**
+ * 鏋勯�犲嚱鏁� - 鍔犺浇DLL搴�
+ */
+ public RFIDTemplate() {
+ try {
+ reader = new Device();
+ comAddr[0] = (byte)255; // 榛樿鍦板潃
+ log.info("RFID妯℃澘鍒濆鍖栨垚鍔�");
+ } catch (Exception e) {
+ log.error("RFID妯℃澘鍒濆鍖栧け璐�", e);
+ }
+ }
+
+ // ==================== 妯″潡1: 杩炴帴妯″潡 ====================
+
+ /**
+ * 銆愪覆鍙h繛鎺ャ�戞墦寮�涓插彛杩炴帴
+ *
+ * @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 true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectComPort(int port, byte baud) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenComPort(port, comAddr, baud, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "COM";
+ log.info("========== 涓插彛杩炴帴鎴愬姛 ==========");
+ log.info("涓插彛鍙�: COM{}", port);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ }
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ }
+ }
+ } catch (Exception e) {
+ log.warn("閰嶇疆澶╃嚎寮傚父: {}", e.getMessage());
+ }
+ return true;
+ } else {
+ log.error("涓插彛杩炴帴澶辫触锛岄敊璇爜: 0x{} ({})", String.format("%02X", result & 0xFF), getErrorCodeMessage(result));
+ return false;
+ }
+ } catch (UnsatisfiedLinkError e) {
+ log.error("RFID璁惧DLL鏂规硶閾炬帴澶辫触 - OpenComPort", e);
+ log.error("閿欒淇℃伅: {}", e.getMessage());
+ log.error("鍙兘鍘熷洜锛�1. DLL鐗堟湰涓嶅尮閰� 2. 鏂规硶绛惧悕涓嶅尮閰� 3. DLL鏈纭姞杞�");
+ throw e; // 閲嶆柊鎶涘嚭寮傚父锛岃璋冪敤鑰呭鐞�
+ }
+ }
+
+ /**
+ * 銆愪覆鍙h繛鎺ャ�戣嚜鍔ㄥ皾璇曞涓尝鐗圭巼杩炴帴锛堟帹鑽愶級
+ *
+ * @param port 涓插彛鍙� (1=COM1, 2=COM2, 3=COM3...)
+ * @param preferredBaud 棣栭�夋尝鐗圭巼 (0-7)锛�-1琛ㄧず浣跨敤榛樿椤哄簭
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectComPortAuto(int port, int preferredBaud) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ // 娉㈢壒鐜囨槧灏�
+ byte[] baudRates = {(byte)0, (byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6, (byte)7};
+ String[] baudNames = {"9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"};
+
+ // 榛樿灏濊瘯椤哄簭锛�57600浼樺厛
+ byte[] tryBauds = {(byte)3, (byte)4, (byte)2, (byte)1, (byte)0, (byte)5, (byte)6, (byte)7};
+
+ // 濡傛灉鎸囧畾浜嗛閫夋尝鐗圭巼锛屽皢鍏舵斁鍦ㄦ渶鍓嶉潰
+ if (preferredBaud >= 0 && preferredBaud <= 7) {
+ byte[] newTryBauds = new byte[tryBauds.length];
+ newTryBauds[0] = (byte)preferredBaud;
+ int idx = 1;
+ for (byte b : tryBauds) {
+ if (b != preferredBaud) {
+ newTryBauds[idx++] = b;
+ }
+ }
+ tryBauds = newTryBauds;
+ }
+
+ log.info("========== 涓插彛杩炴帴 ==========");
+ log.info("涓插彛鍙�: COM{}", port);
+ log.info("姝e湪灏濊瘯杩炴帴...");
+
+ for (int i = 0; i < tryBauds.length; i++) {
+ byte baud = tryBauds[i];
+ String baudName = "";
+ for (int j = 0; j < baudRates.length; j++) {
+ if (baudRates[j] == baud) {
+ baudName = baudNames[j];
+ break;
+ }
+ }
+
+ log.info("灏濊瘯娉㈢壒鐜�: {}bps ... ", baudName);
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenComPort(port, comAddr, baud, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "COM";
+ log.info("鉁� 鎴愬姛锛�");
+ log.info("杩炴帴鎴愬姛锛佹尝鐗圭巼: {}bps", baudName);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+ return true;
+ } else {
+ log.warn("鉁� 澶辫触");
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ log.error("鎵�鏈夋尝鐗圭巼灏濊瘯鍧囧け璐ワ紒");
+ return false;
+ }
+
+ /**
+ * 銆愮綉缁滆繛鎺ャ�戞墦寮�缃戠粶杩炴帴
+ *
+ * @param ipAddr IP鍦板潃 (濡�: 192.168.1.190)
+ * @param port 绔彛鍙� (榛樿6000)
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectNetwork(String ipAddr, int port) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenNetPort(port, ipAddr, comAddr, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "NET";
+ log.info("========== 缃戠粶杩炴帴鎴愬姛 ==========");
+ log.info("IP鍦板潃: {}", ipAddr);
+ log.info("绔彛鍙�: {}", port);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ }
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ }
+ }
+ } catch (Exception e) {
+ log.warn("閰嶇疆澶╃嚎寮傚父: {}", e.getMessage());
+ }
+
+ return true;
+ } else {
+ log.error("缃戠粶杩炴帴澶辫触锛岄敊璇爜: 0x{} ({})", String.format("%02X", result & 0xFF), getErrorCodeMessage(result));
+ log.error("璇锋鏌P鍦板潃鍜岀鍙f槸鍚︽纭�");
+ return false;
+ }
+ } catch (UnsatisfiedLinkError e) {
+ log.error("RFID璁惧DLL鏂规硶閾炬帴澶辫触 - OpenNetPort", e);
+ log.error("閿欒淇℃伅: {}", e.getMessage());
+ log.error("鍙兘鍘熷洜锛�1. DLL鐗堟湰涓嶅尮閰� 2. 鏂规硶绛惧悕涓嶅尮閰� 3. DLL鏈纭姞杞�");
+ throw e; // 閲嶆柊鎶涘嚭寮傚父锛岃璋冪敤鑰呭鐞�
+ }
+ }
+
+ /**
+ * 銆愮綉缁滆繛鎺ャ�戜娇鐢ㄩ粯璁ょ鍙�6000杩炴帴
+ *
+ * @param ipAddr IP鍦板潃 (濡�: 192.168.1.190)
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectNetwork(String ipAddr) {
+ return connectNetwork(ipAddr, 6000);
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戝叧闂繛鎺�
+ */
+ public void disconnect() {
+ if (!isConnected) {
+ log.warn("褰撳墠娌℃湁杩炴帴");
+ return;
+ }
+
+ if ("COM".equals(connectionType)) {
+ int result = reader.CloseSpecComPort(portHandle);
+ if (result == 0) {
+ log.info("涓插彛杩炴帴宸插叧闂�");
+ }
+ } else if ("NET".equals(connectionType)) {
+ int result = reader.CloseNetPort(portHandle);
+ if (result == 0) {
+ log.info("缃戠粶杩炴帴宸插叧闂�");
+ }
+ }
+
+ portHandle = -1;
+ isConnected = false;
+ connectionType = "";
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戞鏌ヨ繛鎺ョ姸鎬�
+ *
+ * @return true=宸茶繛鎺�, false=鏈繛鎺�
+ */
+ public boolean isConnected() {
+ return isConnected && portHandle >= 0;
+ }
+
+ /**
+ * 銆愬ぉ绾块厤缃�戦噸鏂伴厤缃ぉ绾匡紙鍔ㄦ�佸垏鎹㈠ぉ绾挎椂浣跨敤锛�
+ * 褰撶墿鐞嗗ぉ绾挎彃鎷斿悗锛岃皟鐢ㄦ鏂规硶閲嶆柊閰嶇疆澶╃嚎锛岀‘淇濇墍鏈夋彃涓婄殑澶╃嚎閮借兘琚娴嬪埌
+ *
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean reconfigureAntenna() {
+ if (!isConnected()) {
+ log.warn("璁惧鏈繛鎺ワ紝鏃犳硶閰嶇疆澶╃嚎");
+ return false;
+ }
+
+ boolean configured = false;
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ configured = true;
+ }
+
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ configured = true;
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ configured = true;
+ }
+ }
+
+ return configured;
+ } catch (Exception e) {
+ log.error("閲嶆柊閰嶇疆澶╃嚎寮傚父: {}", e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戣幏鍙栬繛鎺ョ被鍨�
+ *
+ * @return "COM"=涓插彛, "NET"=缃戠粶, ""=鏈繛鎺�
+ */
+ public String getConnectionType() {
+ return connectionType;
+ }
+
+ // ==================== 妯″潡2: 璇诲彇妯″潡 ====================
+
+ public List<TagInfo> readTags(int qValue, int session, int scanTime) {
+ List<TagInfo> tagList = new ArrayList<>();
+ if (!isConnected()) {
+ return tagList;
+ }
+
+ byte maskMem = 2;
+ byte[] maskAdr = new byte[2];
+ byte maskLen = 0;
+ byte[] maskData = new byte[256];
+ byte maskFlag = 0;
+ byte adrTID = 0;
+ byte lenTID = 6;
+ byte tidFlag = 0;
+ byte target = 0;
+ byte fastFlag = 0;
+ byte[] pEPCList = new byte[20000];
+ byte[] ant = new byte[1];
+ int[] totallen = new int[1];
+ int[] cardNum = new int[1];
+
+ byte[] antennaValues = {(byte)0x80, (byte)0x81, (byte)0x82, (byte)0x83};
+ int[] antennaNumbers = {1, 2, 3, 4};
+
+ for (int antIdx = 0; antIdx < antennaValues.length; antIdx++) {
+ byte inAnt = antennaValues[antIdx];
+ int expectedAntenna = antennaNumbers[antIdx];
+
+ java.util.Arrays.fill(pEPCList, (byte)0);
+ totallen[0] = 0;
+ cardNum[0] = 0;
+
+ int result = reader.Inventory_G2(comAddr, (byte)qValue, (byte)session, maskMem, maskAdr, maskLen,
+ maskData, maskFlag, adrTID, lenTID, tidFlag, target, inAnt, (byte)scanTime,
+ fastFlag, pEPCList, ant, totallen, cardNum, portHandle);
+
+ if (cardNum[0] > 0 && totallen[0] > 0) {
+ int m = 0;
+ for (int index = 0; index < cardNum[0]; index++) {
+ if (m >= totallen[0] || m >= pEPCList.length) break;
+
+ int epcLen = pEPCList[m++] & 0xFF;
+ if (epcLen <= 0 || epcLen > 32) break;
+
+ if (m + epcLen > totallen[0] || m + epcLen > pEPCList.length) break;
+
+ byte[] epcBytes = new byte[epcLen];
+ for (int n = 0; n < epcLen; n++) {
+ epcBytes[n] = pEPCList[m++];
+ }
+
+ if (m >= totallen[0] || m >= pEPCList.length) break;
+
+ int rssi = pEPCList[m++] & 0xFF;
+ if (rssi > 127) rssi = rssi - 256;
+
+ int antennaValue = 0;
+ if (m < totallen[0] && m < pEPCList.length) {
+ antennaValue = pEPCList[m++] & 0xFF;
+ } else {
+ antennaValue = ant[0] & 0xFF;
+ }
+
+ TagInfo tag = new TagInfo();
+ tag.epc = bytesToHex(epcBytes);
+ tag.rssi = rssi;
+
+ if (antennaValue >= 0x80 && antennaValue <= 0x83) {
+ tag.antenna = antennaValue - 0x80 + 1;
+ } else if (antennaValue >= 1 && antennaValue <= 4) {
+ tag.antenna = antennaValue;
+ } else {
+ tag.antenna = expectedAntenna;
+ }
+ tag.timestamp = System.currentTimeMillis();
+
+ tagList.add(tag);
+ }
+ } else {
+ if (result != 0) {
+ int errorCode = result & 0xFF;
+ if (errorCode == 0xFB) {
+ continue;
+ }
+ if (errorCode == 0x01) {
+ continue;
+ }
+ if (errorCode == 0xF8) {
+// log.warn("澶╃嚎{}鐩樼偣澶辫触锛岄敊璇爜: 0x{} ({})", expectedAntenna, String.format("%02X", errorCode), getErrorCodeMessage(result));
+ } else {
+// log.debug("澶╃嚎{}鐩樼偣澶辫触锛岄敊璇爜: 0x{} ({})", expectedAntenna, String.format("%02X", errorCode), getErrorCodeMessage(result));
+ }
+ }
+ }
+ }
+
+ return tagList;
+ }
+
+ public List<TagInfo> readTags() {
+ return readTags(4, 0, 10);
+ }
+
+ // ==================== 宸ュ叿鏂规硶 ====================
+
+ private String bytesToHex(byte[] bytes) {
+ if (bytes == null) return "";
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02X", b & 0xFF));
+ }
+ return sb.toString();
+ }
+
+ private String getErrorCodeMessage(int errorCode) {
+ switch (errorCode & 0xFF) {
+ case 0x00: return "鏃犻敊璇紝API璋冪敤鎴愬姛";
+ case 0x01: return "璇㈡煡鏃堕棿缁撴潫鍓嶈繑鍥�";
+ case 0x02: return "鎸囧畾鐨勮鏌ユ椂闂存孩鍑�";
+ case 0x03: return "瀛樺偍鍣ㄨ秴闄愭垨涓嶈鏀寔鐨凱C鍊�";
+ case 0x04: return "瀛樺偍鍣ㄩ攣瀹�";
+ case 0x05: return "璁块棶瀵嗙爜閿欒";
+ case 0x09: return "閿�姣佸瘑鐮侀敊璇�";
+ case 0x0A: return "閿�姣佸瘑鐮佷笉鑳戒负鍏�0";
+ case 0x0B: return "鐢靛瓙鏍囩涓嶆敮鎸佽鍛戒护鎴栫數婧愪笉瓒�";
+ case 0x0C: return "瀵硅鍛戒护锛岃闂瘑鐮佷笉鑳戒负0";
+ case 0x0D: return "鐢靛瓙鏍囩宸茬粡琚缃簡璇讳繚鎶わ紝涓嶈兘鍐嶆璁剧疆";
+ case 0x0E: return "鐢靛瓙鏍囩娌℃湁琚缃淇濇姢锛屼笉闇�瑕佽В閿�";
+ case 0x0F: return "闈炵壒瀹氶敊璇紝鏍囩涓嶆敮鎸佺壒瀹氶敊璇唬鐮�";
+ case 0x10: return "鏈夊瓧鑺傜┖闂磋閿佸畾锛屽啓鍏ュけ璐�";
+ case 0x11: return "涓嶈兘閿佸畾";
+ case 0x12: return "宸茬粡閿佸畾锛屼笉鑳藉啀娆¢攣瀹�";
+ case 0x13: return "鍙傛暟淇濆瓨澶辫触,浣嗚缃殑鍊煎湪璇诲啓妯″潡鏂數鍓嶆湁鏁�";
+ case 0x14: return "鏃犳硶璋冩暣";
+ case 0x15: return "璇㈡煡鏃堕棿缁撴潫鍓嶈繑鍥�";
+ case 0x17: return "鏈潯娑堟伅涔嬪悗锛岃繕鏈夋秷鎭�";
+ case 0x18: return "璇诲啓妯″潡瀛樺偍绌洪棿宸叉弧";
+ case 0x19: return "鐢靛瓙涓嶆敮鎸佽鍛戒护鎴栬�呰闂瘑鐮佷笉鑳戒负0";
+ case 0x30: return "閫氳閿欒";
+ case 0x33: return "閫氳绻佸繖锛岃澶囨鍦ㄦ墽琛屽叾浠栧懡浠�";
+ case 0x35: return "绔彛宸叉墦寮�";
+ case 0x37: return "鏃犳晥鍙ユ焺";
+ case 0xF8: return "澶╃嚎妫�娴嬮敊璇�";
+ case 0xF9: return "鍛戒护鎵ц鍑洪敊";
+ case 0xFA: return "鏈夌數瀛愭爣绛撅紝浣嗛�氫俊涓嶇晠锛屾棤娉曟搷浣�";
+ case 0xFB: return "鏃犵數瀛愭爣绛惧彲鎿嶄綔";
+ case 0xFC: return "鐢靛瓙鏍囩杩斿洖閿欒浠g爜";
+ case 0xFD: return "鍛戒护闀垮害閿欒";
+ case 0xFE: return "涓嶅悎娉曠殑鍛戒护";
+ case 0xFF: return "鍙傛暟閿欒";
+ default: return "鏈煡閿欒鐮�";
+ }
+ }
+
+ // ==================== 鏍囩淇℃伅绫� ====================
+
+ /**
+ * 鏍囩淇℃伅绫�
+ */
+ public static class TagInfo {
+ public String epc; // EPC锛堝崄鍏繘鍒跺瓧绗︿覆锛�
+ public int rssi; // RSSI锛坉Bm锛�
+ public int antenna; // 澶╃嚎鍙�
+ public long timestamp; // 鏃堕棿鎴�
+
+ @Override
+ public String toString() {
+ return String.format("EPC: %s, RSSI: %ddBm, 澶╃嚎: %d", epc, rssi, antenna);
+ }
+ }
+}
diff --git a/src/main/java/com/zy/controller/RFIDController.java b/src/main/java/com/zy/controller/RFIDController.java
new file mode 100644
index 0000000..641e3c0
--- /dev/null
+++ b/src/main/java/com/zy/controller/RFIDController.java
@@ -0,0 +1,270 @@
+package com.zy.controller;
+
+import com.core.common.R;
+import com.zy.service.RFIDService;
+import com.zy.service.RFIDAutoConnectService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * RFID璁惧HTTP API鎺ュ彛
+ * 鎻愪緵RFID璁惧杩炴帴銆佹娴嬬瓑鍔熻兘
+ * Created on 2026/01/10
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/rfid")
+public class RFIDController {
+
+ @Autowired
+ private RFIDService rfidService;
+
+ @Autowired
+ private RFIDAutoConnectService rfidAutoConnectService;
+
+ /**
+ * 缃戠粶杩炴帴RFID璁惧
+ *
+ * POST /api/rfid/connect/network
+ * Body: {"ip": "10.10.10.210", "port": 27011}
+ *
+ * @param params 杩炴帴鍙傛暟
+ * @return 杩炴帴缁撴灉
+ */
+ @PostMapping("/connect/network")
+ public R connectNetwork(@RequestBody Map<String, Object> params) {
+ String ip = (String) params.get("ip");
+ Integer port = params.get("port") != null ?
+ Integer.valueOf(params.get("port").toString()) : null;
+
+ if (ip == null || ip.isEmpty()) {
+ return R.error("IP鍦板潃涓嶈兘涓虹┖");
+ }
+
+ Map<String, Object> result = rfidService.connectNetwork(ip, port);
+ return result.get("success").equals(true) ? R.ok(result) : R.error(result.get("message").toString());
+ }
+
+ /**
+ * 涓插彛杩炴帴RFID璁惧
+ *
+ * POST /api/rfid/connect/comport
+ * Body: {"port": 3, "baud": 3}
+ *
+ * @param params 杩炴帴鍙傛暟
+ * @return 杩炴帴缁撴灉
+ */
+ @PostMapping("/connect/comport")
+ public R connectComPort(@RequestBody Map<String, Object> params) {
+ Integer port = params.get("port") != null ?
+ Integer.valueOf(params.get("port").toString()) : null;
+ Integer baud = params.get("baud") != null ?
+ Integer.valueOf(params.get("baud").toString()) : null;
+
+ Map<String, Object> result = rfidService.connectComPort(port, baud);
+ return result.get("success").equals(true) ? R.ok(result) : R.error(result.get("message").toString());
+ }
+
+ /**
+ * 妫�娴婻FID鏍囩锛堝崟娆℃娴嬶級
+ *
+ * GET /api/rfid/detect
+ * GET /api/rfid/detect?scanTime=5
+ *
+ * @param scanTime 鎵弿鏃堕棿锛堝崟浣�: 100ms锛岄粯璁�5锛�
+ * @return 妫�娴嬬粨鏋�
+ */
+ @GetMapping("/detect")
+ public R detectTags(@RequestParam(required = false) Integer scanTime) {
+ Map<String, Object> result = rfidService.detectTags(scanTime);
+ return R.ok(result);
+ }
+
+ /**
+ * 妫�娴婻FID鏍囩锛圥OST鏂瑰紡锛屽彲浼犻�掓洿澶氬弬鏁帮級
+ *
+ * POST /api/rfid/detect
+ * Body: {"scanTime": 5}
+ *
+ * @param params 妫�娴嬪弬鏁�
+ * @return 妫�娴嬬粨鏋�
+ */
+ @PostMapping("/detect")
+ public R detectTagsPost(@RequestBody(required = false) Map<String, Object> params) {
+ Integer scanTime = null;
+ if (params != null && params.get("scanTime") != null) {
+ scanTime = Integer.valueOf(params.get("scanTime").toString());
+ }
+
+ Map<String, Object> result = rfidService.detectTags(scanTime);
+ return R.ok(result);
+ }
+
+ /**
+ * 鏂紑RFID璁惧杩炴帴
+ *
+ * POST /api/rfid/disconnect
+ *
+ * @return 鏂紑缁撴灉
+ */
+ @PostMapping("/disconnect")
+ public R disconnect() {
+ Map<String, Object> result = rfidService.disconnect();
+ return result.get("success").equals(true) ? R.ok(result) : R.error(result.get("message").toString());
+ }
+
+ /**
+ * 鑾峰彇杩炴帴鐘舵��
+ *
+ * GET /api/rfid/status
+ *
+ * @return 杩炴帴鐘舵��
+ */
+ @GetMapping("/status")
+ public R getStatus() {
+ Map<String, Object> result = rfidService.getConnectionStatus();
+ return R.ok(result);
+ }
+
+ /**
+ * 璇婃柇DLL鍔犺浇鐘舵��
+ *
+ * GET /api/rfid/diagnose
+ *
+ * @return 璇婃柇淇℃伅
+ */
+ @GetMapping("/diagnose")
+ public R diagnose() {
+ Map<String, Object> result = rfidService.diagnoseDll();
+ return R.ok(result);
+ }
+
+ /**
+ * 鑾峰彇鎵�鏈塕FID鑷姩杩炴帴璁惧鐘舵��
+ *
+ * GET /api/rfid/auto-connect/status
+ *
+ * @return 鎵�鏈夎澶囩姸鎬�
+ */
+ @GetMapping("/auto-connect/status")
+ public R getAutoConnectStatus() {
+ return R.ok(rfidAutoConnectService.getAllDeviceStatus());
+ }
+
+ /**
+ * 鑾峰彇鎸囧畾RFID鑷姩杩炴帴璁惧鐘舵��
+ *
+ * GET /api/rfid/auto-connect/status/{deviceId}
+ *
+ * @param deviceId 璁惧ID
+ * @return 璁惧鐘舵��
+ */
+ @GetMapping("/auto-connect/status/{deviceId}")
+ public R getAutoConnectDeviceStatus(@PathVariable Integer deviceId) {
+ Map<String, Object> result = rfidAutoConnectService.getDeviceStatus(deviceId);
+ return R.ok(result);
+ }
+
+ /**
+ * 鎵嬪姩鍚姩鎸囧畾RFID璁惧鑷姩杩炴帴
+ *
+ * POST /api/rfid/auto-connect/start/{deviceId}
+ *
+ * @param deviceId 璁惧ID
+ * @return 鍚姩缁撴灉
+ */
+ @PostMapping("/auto-connect/start/{deviceId}")
+ public R startAutoConnect(@PathVariable Integer deviceId) {
+ boolean success = rfidAutoConnectService.startDevice(deviceId);
+ if (success) {
+ return R.ok("RFID璁惧[" + deviceId + "]鑷姩杩炴帴宸插惎鍔�");
+ } else {
+ return R.error("RFID璁惧[" + deviceId + "]鍚姩澶辫触锛岃妫�鏌ラ厤缃垨璁惧鏄惁宸插湪杩愯");
+ }
+ }
+
+ /**
+ * 鎵嬪姩鍋滄鎸囧畾RFID璁惧鑷姩杩炴帴
+ *
+ * POST /api/rfid/auto-connect/stop/{deviceId}
+ *
+ * @param deviceId 璁惧ID
+ * @return 鍋滄缁撴灉
+ */
+ @PostMapping("/auto-connect/stop/{deviceId}")
+ public R stopAutoConnect(@PathVariable Integer deviceId) {
+ boolean success = rfidAutoConnectService.stopDevice(deviceId);
+ if (success) {
+ return R.ok("RFID璁惧[" + deviceId + "]鑷姩杩炴帴宸插仠姝�");
+ } else {
+ return R.error("RFID璁惧[" + deviceId + "]鍋滄澶辫触锛岃澶囧彲鑳芥湭鍚敤鑷姩杩炴帴");
+ }
+ }
+
+ /**
+ * 鎵嬪姩鍋滄鎵�鏈塕FID璁惧鑷姩杩炴帴
+ *
+ * POST /api/rfid/auto-connect/stop-all
+ *
+ * @return 鍋滄缁撴灉
+ */
+ @PostMapping("/auto-connect/stop-all")
+ public R stopAllAutoConnect() {
+ rfidAutoConnectService.stopAll();
+ return R.ok("鎵�鏈塕FID璁惧鑷姩杩炴帴宸插仠姝�");
+ }
+
+ /**
+ * 閲嶆柊閰嶇疆鎸囧畾RFID璁惧鐨勫ぉ绾匡紙鐢ㄤ簬澶╃嚎鎻掓嫈鍚庨噸鏂伴厤缃級
+ *
+ * POST /api/rfid/reconfigure-antenna/{deviceId}
+ *
+ * @param deviceId 璁惧ID
+ * @return 閰嶇疆缁撴灉
+ */
+ @PostMapping("/reconfigure-antenna/{deviceId}")
+ public R reconfigureAntenna(@PathVariable Integer deviceId) {
+ Map<String, Object> deviceStatus = rfidAutoConnectService.getDeviceStatus(deviceId);
+ if (!Boolean.TRUE.equals(deviceStatus.get("exists"))) {
+ return R.error("RFID璁惧[" + deviceId + "]鏈惎鐢ㄨ嚜鍔ㄨ繛鎺ユ垨涓嶅瓨鍦�");
+ }
+
+ if (!Boolean.TRUE.equals(deviceStatus.get("templateConnected"))) {
+ return R.error("RFID璁惧[" + deviceId + "]鏈繛鎺ワ紝鏃犳硶閰嶇疆澶╃嚎");
+ }
+
+ // 鑾峰彇璁惧绠$悊鍣ㄥ苟閲嶆柊閰嶇疆澶╃嚎
+ boolean success = rfidAutoConnectService.reconfigureAntenna(deviceId);
+ if (success) {
+ return R.ok("RFID璁惧[" + deviceId + "]澶╃嚎閲嶆柊閰嶇疆鎴愬姛");
+ } else {
+ return R.error("RFID璁惧[" + deviceId + "]澶╃嚎閲嶆柊閰嶇疆澶辫触锛岃鏌ョ湅鏃ュ織");
+ }
+ }
+
+ @GetMapping("/tags")
+ public R getTags(@RequestParam(required = false) Integer deviceId,
+ @RequestParam(required = false) String ip,
+ @RequestParam(required = false) Integer antenna) {
+ if (deviceId == null && (ip == null || ip.isEmpty())) {
+ return R.error("璇锋彁渚涜澶嘔D鎴朓P鍦板潃");
+ }
+ List<Map<String, Object>> tags = rfidAutoConnectService.getDeviceTags(deviceId, ip, antenna);
+ return R.ok(tags);
+ }
+
+ @GetMapping("/query-tags")
+ public R queryTags(@RequestParam(required = false) Integer deviceId,
+ @RequestParam(required = false) String ip,
+ @RequestParam(required = false) Integer antenna) {
+ if (deviceId == null && (ip == null || ip.isEmpty())) {
+ return R.error("璇锋彁渚涜澶嘔D鎴朓P鍦板潃");
+ }
+ List<Map<String, Object>> tags = rfidAutoConnectService.queryDeviceTags(deviceId, ip, antenna);
+ return R.ok(tags);
+ }
+}
diff --git a/src/main/java/com/zy/core/ServerBootstrap.java b/src/main/java/com/zy/core/ServerBootstrap.java
index b37b6b3..4660033 100644
--- a/src/main/java/com/zy/core/ServerBootstrap.java
+++ b/src/main/java/com/zy/core/ServerBootstrap.java
@@ -6,9 +6,11 @@
import com.zy.core.model.CrnSlave;
import com.zy.core.model.DevpSlave;
import com.zy.core.model.LedSlave;
+import com.zy.core.model.RFIDSlave;
import com.zy.core.properties.SlaveProperties;
import com.zy.core.thread.BarcodeThread;
import com.zy.core.thread.LedThread;
+import com.zy.core.thread.RFIDThread;
import com.zy.core.thread.SiemensCrnThread;
import com.zy.core.thread.SiemensDevpThread;
import com.zy.utils.News;
@@ -75,6 +77,10 @@
for (Slave led : slaveProperties.getLed()) {
MessageQueue.init(SlaveType.Led, led);
}
+ // 鍒濆鍖朢FID璇诲啓鍣╩q
+ for (Slave rfid : slaveProperties.getRfid()) {
+ MessageQueue.init(SlaveType.Rfid, rfid);
+ }
// 鍒濆鍖栫绉癿q
// for (Slave scale : slaveProperties.getScale()) {
// MessageQueue.init(SlaveType.Scale, scale);
@@ -121,6 +127,19 @@
new Thread(ledThread).start();
SlaveConnection.put(SlaveType.Led, led.getId(), ledThread);
}
+ // 鍒濆鍖朢FID璇诲啓鍣ㄧ嚎绋�
+ // 娉ㄦ剰锛氬鏋淩FID璁惧閰嶇疆浜哸utoConnect=true锛屽皢鐢盧FIDAutoConnectService绠$悊锛岃繖閲岃烦杩�
+ News.info("鍒濆鍖朢FID璇诲啓鍣ㄧ嚎绋�...................................................");
+ for (RFIDSlave rfid : slaveProperties.getRfid()) {
+ // 濡傛灉鍚敤浜嗚嚜鍔ㄨ繛鎺ワ紝璺宠繃RFIDThread鐨勫垱寤猴紙鐢盧FIDAutoConnectService绠$悊锛�
+ if (rfid.getAutoConnect() != null && rfid.getAutoConnect()) {
+ News.info("RFID璁惧[{}]宸插惎鐢ㄨ嚜鍔ㄨ繛鎺ワ紝璺宠繃RFIDThread鍒濆鍖�", rfid.getId());
+ continue;
+ }
+ RFIDThread rfidThread = new RFIDThread(rfid);
+ new Thread(rfidThread).start();
+ SlaveConnection.put(SlaveType.Rfid, rfid.getId(), rfidThread);
+ }
// 鍒濆鍖栫绉ょ嚎绋�
// News.info("鍒濆鍖栫绉ょ嚎绋�...................................................");
// for (Slave scale : slaveProperties.getScale()) {
diff --git a/src/main/java/com/zy/core/cache/OutputQueue.java b/src/main/java/com/zy/core/cache/OutputQueue.java
index 65df862..f6bbb65 100644
--- a/src/main/java/com/zy/core/cache/OutputQueue.java
+++ b/src/main/java/com/zy/core/cache/OutputQueue.java
@@ -17,4 +17,6 @@
public static ArrayBlockingQueue<JSONObject> BARCODE = new ArrayBlockingQueue<>(32);
// rgv杈撳嚭鏃ュ織
public static ArrayBlockingQueue<String> RGV = new ArrayBlockingQueue<>(32);
+ // RFID杈撳嚭鏃ュ織
+ public static ArrayBlockingQueue<JSONObject> RFID = new ArrayBlockingQueue<>(32);
}
diff --git a/src/main/java/com/zy/core/enums/SlaveType.java b/src/main/java/com/zy/core/enums/SlaveType.java
index 7f64d13..e44e599 100644
--- a/src/main/java/com/zy/core/enums/SlaveType.java
+++ b/src/main/java/com/zy/core/enums/SlaveType.java
@@ -8,7 +8,8 @@
Led,
Scale,
Car,
- Rgv
+ Rgv,
+ Rfid
;
public static SlaveType findInstance(String s){
diff --git a/src/main/java/com/zy/core/model/RFIDSlave.java b/src/main/java/com/zy/core/model/RFIDSlave.java
new file mode 100644
index 0000000..70ac71c
--- /dev/null
+++ b/src/main/java/com/zy/core/model/RFIDSlave.java
@@ -0,0 +1,20 @@
+package com.zy.core.model;
+
+import com.zy.core.Slave;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * RFID璁惧閰嶇疆
+ * Created on 2026/01/10
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class RFIDSlave extends Slave {
+
+ /**
+ * 鏄惁鑷姩杩炴帴锛坱rue: 绯荤粺鍚姩鏃惰嚜鍔ㄨ繛鎺ワ紝false: 鎵嬪姩杩炴帴锛�
+ */
+ private Boolean autoConnect = false;
+
+}
diff --git a/src/main/java/com/zy/core/thread/RFIDThread.java b/src/main/java/com/zy/core/thread/RFIDThread.java
new file mode 100644
index 0000000..0d0fc3d
--- /dev/null
+++ b/src/main/java/com/zy/core/thread/RFIDThread.java
@@ -0,0 +1,322 @@
+package com.zy.core.thread;
+
+import com.alibaba.fastjson.JSONObject;
+import com.core.common.Cools;
+import com.core.common.DateUtils;
+import com.zy.core.Slave;
+import com.zy.core.ThreadHandler;
+import com.zy.core.cache.OutputQueue;
+import com.rfid.uhf288.Device;
+import com.zy.utils.News;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+import java.text.MessageFormat;
+import java.util.Date;
+
+/**
+ * RFID璇诲啓鍣ㄧ嚎绋�
+ * 鍩轰簬UHF288璁惧锛屾敮鎸佷覆鍙e拰缃戠粶杩炴帴
+ * Created by chen.lin on 2026/01/10
+ */
+@Data
+@Slf4j
+public class RFIDThread implements Runnable, ThreadHandler {
+
+ private Slave slave;
+ private StringBuffer rfid = new StringBuffer();
+ private String lastRfid = "";
+
+ private Device reader;
+ private int portHandle = -1;
+ private byte[] comAddr = new byte[1];
+ private boolean isConnected = false;
+ private String connectionType = ""; // "COM" 鎴� "NET"
+
+ // 杩炴帴鍙傛暟
+ private Integer comPort; // 涓插彛鍙凤紙濡傛灉浣跨敤涓插彛锛�
+ private Byte baudRate; // 娉㈢壒鐜囷紙濡傛灉浣跨敤涓插彛锛�
+ private String ipAddress; // IP鍦板潃锛堝鏋滀娇鐢ㄧ綉缁滐級
+ private Integer netPort; // 缃戠粶绔彛锛堝鏋滀娇鐢ㄧ綉缁滐級
+
+ public RFIDThread(Slave slave) {
+ this.slave = slave;
+ try {
+ reader = new Device();
+ comAddr[0] = (byte)255; // 榛樿鍦板潃0xFF
+ } catch (Exception e) {
+ log.error("RFID璁惧鍒濆鍖栧け璐�", e);
+ }
+ }
+
+ public String getRfid() {
+ return rfid.toString();
+ }
+
+ public void setRfid(String rfid) {
+ this.rfid.delete(0, this.rfid.length());
+ this.rfid.append(rfid);
+ if(!Cools.isEmpty(rfid) && !lastRfid.equals(rfid)) {
+ News.info("RFID"+" - 1"+" - {}鍙稲FID璇诲啓鍣紝妫�绱㈡暟鎹細{}", slave.getId(), this.rfid);
+ lastRfid = rfid;
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("time", DateUtils.convert(new Date(), DateUtils.yyyyMMddHHmmss_F));
+ jsonObject.put("rfid", rfid);
+ if (OutputQueue.RFID.size() >= 32) {
+ OutputQueue.RFID.poll();
+ }
+ OutputQueue.RFID.offer(jsonObject);
+ }
+ }
+
+ @Override
+ public boolean connect() {
+ if (isConnected) {
+ log.warn("RFID璁惧宸茶繛鎺ワ紝鏃犻渶閲嶅杩炴帴");
+ return true;
+ }
+
+ boolean result = false;
+
+ try {
+ // 浼樺厛灏濊瘯缃戠粶杩炴帴锛堝鏋滈厤缃簡IP锛�
+ if (!Cools.isEmpty(slave.getIp()) && slave.getPort() != null) {
+ result = connectNetwork(slave.getIp(), slave.getPort());
+ if (result) {
+ connectionType = "NET";
+ JSONObject connMsg = new JSONObject();
+ connMsg.put("time", DateUtils.convert(new Date(), DateUtils.yyyyMMddHHmmss_F));
+ connMsg.put("message", MessageFormat.format("RFID缃戠粶杩炴帴鎴愬姛 ===>> [id:{0}] [ip:{1}] [port:{2}]",
+ slave.getId(), slave.getIp(), slave.getPort()));
+ OutputQueue.RFID.offer(connMsg);
+ log.info("RFID缃戠粶杩炴帴鎴愬姛 ===>> [id:{}] [ip:{}] [port:{}]", slave.getId(), slave.getIp(), slave.getPort());
+ return true;
+ }
+ }
+
+ // 濡傛灉缃戠粶杩炴帴澶辫触锛屽皾璇曚覆鍙h繛鎺�
+ // 娉ㄦ剰锛氫覆鍙h繛鎺ラ渶瑕侀澶栫殑閰嶇疆鍙傛暟锛堜覆鍙e彿鍜屾尝鐗圭巼锛�
+ // 杩欓噷鍋囪鍙互閫氳繃鏌愮鏂瑰紡鑾峰彇锛屾垨鑰呬娇鐢ㄩ粯璁ゅ��
+ if (comPort == null) {
+ comPort = 3; // 榛樿COM3
+ }
+ if (baudRate == null) {
+ baudRate = (byte)3; // 榛樿57600bps
+ }
+
+ result = connectComPort(comPort, baudRate);
+ if (result) {
+ connectionType = "COM";
+ JSONObject connMsg = new JSONObject();
+ connMsg.put("time", DateUtils.convert(new Date(), DateUtils.yyyyMMddHHmmss_F));
+ connMsg.put("message", MessageFormat.format("RFID涓插彛杩炴帴鎴愬姛 ===>> [id:{0}] [port:COM{1}] [baud:{2}]",
+ slave.getId(), comPort, getBaudRateName(baudRate)));
+ OutputQueue.RFID.offer(connMsg);
+ log.info("RFID涓插彛杩炴帴鎴愬姛 ===>> [id:{}] [port:COM{}] [baud:{}]", slave.getId(), comPort, getBaudRateName(baudRate));
+ return true;
+ }
+
+ } catch (Exception e) {
+ log.error("RFID杩炴帴澶辫触", e);
+ JSONObject connMsg = new JSONObject();
+ connMsg.put("time", DateUtils.convert(new Date(), DateUtils.yyyyMMddHHmmss_F));
+ connMsg.put("message", MessageFormat.format("RFID杩炴帴澶辫触锛侊紒锛� ===>> [id:{0}] [ip:{1}] [port:{2}]",
+ slave.getId(), slave.getIp(), slave.getPort()));
+ OutputQueue.RFID.offer(connMsg);
+ }
+
+ return false;
+ }
+
+ /**
+ * 涓插彛杩炴帴
+ */
+ private boolean connectComPort(int port, byte baud) {
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenComPort(port, comAddr, baud, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ return true;
+ } else {
+ log.error("RFID涓插彛杩炴帴澶辫触锛岄敊璇爜: {}", result);
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("RFID涓插彛杩炴帴寮傚父", e);
+ return false;
+ }
+ }
+
+ /**
+ * 缃戠粶杩炴帴
+ */
+ private boolean connectNetwork(String ipAddr, int port) {
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenNetPort(port, ipAddr, comAddr, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ return true;
+ } else {
+ log.error("RFID缃戠粶杩炴帴澶辫触锛岄敊璇爜: {}", result);
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("RFID缃戠粶杩炴帴寮傚父", e);
+ return false;
+ }
+ }
+
+ /**
+ * 璇诲彇RFID鏍囩
+ */
+ private void readTags() {
+ if (!isConnected || portHandle < 0) {
+ return;
+ }
+
+ try {
+ byte qValue = 4; // Q鍊硷紝鎺ㄨ崘4
+ byte session = 0; // Session鍊硷紝鎺ㄨ崘0
+ byte scanTime = 10; // 鎵弿鏃堕棿锛�10*100ms=1绉�
+ byte maskMem = 2; // EPC鍖�
+ byte[] maskAdr = new byte[2];
+ byte maskLen = 0;
+ byte[] maskData = new byte[256];
+ byte maskFlag = 0; // 涓嶄娇鐢ㄦ帺鐮�
+ byte adrTID = 0;
+ byte lenTID = 6;
+ byte tidFlag = 0; // 0-璇诲彇EPC锛�1-璇诲彇TID
+ byte target = 0;
+ byte inAnt = (byte)0x81;
+ byte fastFlag = 0;
+ byte[] pEPCList = new byte[20000];
+ byte[] ant = new byte[1];
+ int[] totallen = new int[1];
+ int[] cardNum = new int[1];
+
+ // 娓呯┖鏁扮粍
+ java.util.Arrays.fill(pEPCList, (byte)0);
+ totallen[0] = 0;
+ cardNum[0] = 0;
+
+ int result = reader.Inventory_G2(comAddr, qValue, session, maskMem, maskAdr, maskLen,
+ maskData, maskFlag, adrTID, lenTID, tidFlag, target, inAnt, scanTime,
+ fastFlag, pEPCList, ant, totallen, cardNum, portHandle);
+
+ // 瑙f瀽鏍囩鏁版嵁
+ if (cardNum[0] > 0 && totallen[0] > 0) {
+ int offset = 0;
+ for (int i = 0; i < cardNum[0]; i++) {
+ if (offset + 1 >= totallen[0]) break;
+
+ byte epcLen = pEPCList[offset];
+ offset++;
+
+ if (offset + epcLen > totallen[0]) break;
+
+ byte[] epcBytes = new byte[epcLen];
+ System.arraycopy(pEPCList, offset, epcBytes, 0, epcLen);
+ offset += epcLen;
+
+ // RSSI鍜屽ぉ绾夸俊鎭�
+ byte rssi = 0;
+ byte antenna = 0;
+ if (offset < totallen[0]) {
+ rssi = pEPCList[offset];
+ offset++;
+ }
+ if (offset < totallen[0]) {
+ antenna = pEPCList[offset];
+ offset++;
+ }
+
+ String epcHex = bytesToHex(epcBytes);
+ // 鍙彇EPC鐨勪竴閮ㄥ垎锛堢被浼煎弬鑰冮」鐩腑鐨勫鐞嗘柟寮忥級
+ if (epcHex.length() >= 24) {
+ epcHex = epcHex.substring(14, 24);
+ }
+
+ setRfid(epcHex);
+
+ // 鍙鐞嗙涓�涓爣绛�
+ break;
+ }
+ }
+ } catch (Exception e) {
+ log.error("RFID璇诲彇鏍囩寮傚父", e);
+ }
+ }
+
+ /**
+ * 瀛楄妭鏁扮粍杞崄鍏繘鍒跺瓧绗︿覆
+ */
+ private String bytesToHex(byte[] bytes) {
+ if (bytes == null) return "";
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02X", b & 0xFF));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 鑾峰彇娉㈢壒鐜囧悕绉�
+ */
+ private String getBaudRateName(byte baud) {
+ String[] names = {"9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"};
+ int index = baud & 0xFF;
+ if (index >= 0 && index < names.length) {
+ return names[index];
+ }
+ return String.valueOf(baud);
+ }
+
+ @Override
+ public void close() {
+ if (isConnected && portHandle >= 0) {
+ try {
+ if ("COM".equals(connectionType)) {
+ reader.CloseSpecComPort(portHandle);
+ } else if ("NET".equals(connectionType)) {
+ reader.CloseNetPort(portHandle);
+ }
+ isConnected = false;
+ portHandle = -1;
+ connectionType = "";
+ log.info("RFID杩炴帴宸插叧闂� ===>> [id:{}]", slave.getId());
+ } catch (Exception e) {
+ log.error("RFID鍏抽棴杩炴帴寮傚父", e);
+ }
+ }
+ }
+
+ @Override
+ public void run() {
+ connect();
+ while (true) {
+ try {
+ if (isConnected) {
+ readTags();
+ } else {
+ // 濡傛灉鏈繛鎺ワ紝灏濊瘯閲嶈繛
+ connect();
+ }
+ Thread.sleep(300);
+ } catch (Exception e) {
+ log.error("RFID绾跨▼杩愯寮傚父", e);
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException ie) {
+ Thread.currentThread().interrupt();
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/java/com/zy/rfid/RFIDTemplate.java b/src/main/java/com/zy/rfid/RFIDTemplate.java
new file mode 100644
index 0000000..4cca5af
--- /dev/null
+++ b/src/main/java/com/zy/rfid/RFIDTemplate.java
@@ -0,0 +1,506 @@
+package com.zy.rfid;
+
+import com.rfid.uhf288.Device;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * RFID璁惧鎿嶄綔妯℃澘 - 妯″潡鍖栬璁�
+ * 鍙傝�僤emo椤圭洰锛屼絾鍙寘鍚熀鏈鍙栧姛鑳斤紙绫讳技鍙傝�冮」鐩畓y-wcs-czbrwcs涓殑鍔熻兘锛�
+ * Created by chen.lin on 2026/01/10
+ *
+ * 鍔熻兘妯″潡锛�
+ * 1. 杩炴帴妯″潡 - 涓插彛杩炴帴 / 缃戠粶杩炴帴锛堢嫭绔嬶級
+ * 2. 璇诲彇妯″潡 - 鐩樼偣鏍囩锛堢嫭绔嬶級
+ *
+ * 浣跨敤鏂瑰紡锛�
+ * 1. 鍒涘缓瀹炰緥
+ * 2. 閫夋嫨杩炴帴鏂瑰紡锛堜覆鍙f垨缃戠粶锛�
+ * 3. 杩炴帴鎴愬姛鍚庯紝璋冪敤璇诲彇鍔熻兘
+ * 4. 浣跨敤瀹屾瘯鍚庡叧闂繛鎺�
+ */
+@Slf4j
+public class RFIDTemplate {
+
+ // ==================== 鍩虹缁勪欢 ====================
+ private Device reader;
+ private int portHandle = -1;
+ private byte[] comAddr = new byte[1];
+
+ // 杩炴帴鐘舵��
+ private boolean isConnected = false;
+ private String connectionType = ""; // "COM" 鎴� "NET"
+
+ // ==================== 鍒濆鍖� ====================
+
+ /**
+ * 鏋勯�犲嚱鏁� - 鍔犺浇DLL搴�
+ */
+ public RFIDTemplate() {
+ try {
+ reader = new Device();
+ comAddr[0] = (byte)255; // 榛樿鍦板潃
+ log.info("RFID妯℃澘鍒濆鍖栨垚鍔�");
+ } catch (Exception e) {
+ log.error("RFID妯℃澘鍒濆鍖栧け璐�", e);
+ }
+ }
+
+ // ==================== 妯″潡1: 杩炴帴妯″潡 ====================
+
+ /**
+ * 銆愪覆鍙h繛鎺ャ�戞墦寮�涓插彛杩炴帴
+ *
+ * @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 true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectComPort(int port, byte baud) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenComPort(port, comAddr, baud, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "COM";
+ log.info("========== 涓插彛杩炴帴鎴愬姛 ==========");
+ log.info("涓插彛鍙�: COM{}", port);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ }
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ }
+ }
+ } catch (Exception e) {
+ log.warn("閰嶇疆澶╃嚎寮傚父: {}", e.getMessage());
+ }
+ return true;
+ } else {
+ log.error("涓插彛杩炴帴澶辫触锛岄敊璇爜: 0x{} ({})", String.format("%02X", result & 0xFF), getErrorCodeMessage(result));
+ return false;
+ }
+ } catch (UnsatisfiedLinkError e) {
+ log.error("RFID璁惧DLL鏂规硶閾炬帴澶辫触 - OpenComPort", e);
+ log.error("閿欒淇℃伅: {}", e.getMessage());
+ log.error("鍙兘鍘熷洜锛�1. DLL鐗堟湰涓嶅尮閰� 2. 鏂规硶绛惧悕涓嶅尮閰� 3. DLL鏈纭姞杞�");
+ throw e; // 閲嶆柊鎶涘嚭寮傚父锛岃璋冪敤鑰呭鐞�
+ }
+ }
+
+ /**
+ * 銆愪覆鍙h繛鎺ャ�戣嚜鍔ㄥ皾璇曞涓尝鐗圭巼杩炴帴锛堟帹鑽愶級
+ *
+ * @param port 涓插彛鍙� (1=COM1, 2=COM2, 3=COM3...)
+ * @param preferredBaud 棣栭�夋尝鐗圭巼 (0-7)锛�-1琛ㄧず浣跨敤榛樿椤哄簭
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectComPortAuto(int port, int preferredBaud) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ // 娉㈢壒鐜囨槧灏�
+ byte[] baudRates = {(byte)0, (byte)1, (byte)2, (byte)3, (byte)4, (byte)5, (byte)6, (byte)7};
+ String[] baudNames = {"9600", "19200", "38400", "57600", "115200", "230400", "460800", "921600"};
+
+ // 榛樿灏濊瘯椤哄簭锛�57600浼樺厛
+ byte[] tryBauds = {(byte)3, (byte)4, (byte)2, (byte)1, (byte)0, (byte)5, (byte)6, (byte)7};
+
+ // 濡傛灉鎸囧畾浜嗛閫夋尝鐗圭巼锛屽皢鍏舵斁鍦ㄦ渶鍓嶉潰
+ if (preferredBaud >= 0 && preferredBaud <= 7) {
+ byte[] newTryBauds = new byte[tryBauds.length];
+ newTryBauds[0] = (byte)preferredBaud;
+ int idx = 1;
+ for (byte b : tryBauds) {
+ if (b != preferredBaud) {
+ newTryBauds[idx++] = b;
+ }
+ }
+ tryBauds = newTryBauds;
+ }
+
+ log.info("========== 涓插彛杩炴帴 ==========");
+ log.info("涓插彛鍙�: COM{}", port);
+ log.info("姝e湪灏濊瘯杩炴帴...");
+
+ for (int i = 0; i < tryBauds.length; i++) {
+ byte baud = tryBauds[i];
+ String baudName = "";
+ for (int j = 0; j < baudRates.length; j++) {
+ if (baudRates[j] == baud) {
+ baudName = baudNames[j];
+ break;
+ }
+ }
+
+ log.info("灏濊瘯娉㈢壒鐜�: {}bps ... ", baudName);
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenComPort(port, comAddr, baud, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "COM";
+ log.info("鉁� 鎴愬姛锛�");
+ log.info("杩炴帴鎴愬姛锛佹尝鐗圭巼: {}bps", baudName);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+ return true;
+ } else {
+ log.warn("鉁� 澶辫触");
+ }
+
+ try {
+ Thread.sleep(100);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ log.error("鎵�鏈夋尝鐗圭巼灏濊瘯鍧囧け璐ワ紒");
+ return false;
+ }
+
+ /**
+ * 銆愮綉缁滆繛鎺ャ�戞墦寮�缃戠粶杩炴帴
+ *
+ * @param ipAddr IP鍦板潃 (濡�: 192.168.1.190)
+ * @param port 绔彛鍙� (榛樿6000)
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectNetwork(String ipAddr, int port) {
+ if (isConnected) {
+ log.warn("宸插瓨鍦ㄨ繛鎺ワ紝璇峰厛鍏抽棴褰撳墠杩炴帴");
+ return false;
+ }
+
+ try {
+ int[] portHandleArray = new int[1];
+ int result = reader.OpenNetPort(port, ipAddr, comAddr, portHandleArray);
+
+ if (result == 0) {
+ portHandle = portHandleArray[0];
+ isConnected = true;
+ connectionType = "NET";
+ log.info("========== 缃戠粶杩炴帴鎴愬姛 ==========");
+ log.info("IP鍦板潃: {}", ipAddr);
+ log.info("绔彛鍙�: {}", port);
+ log.info("绔彛鍙ユ焺: {}", portHandle);
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ }
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ }
+ }
+ } catch (Exception e) {
+ log.warn("閰嶇疆澶╃嚎寮傚父: {}", e.getMessage());
+ }
+
+ return true;
+ } else {
+ log.error("缃戠粶杩炴帴澶辫触锛岄敊璇爜: 0x{} ({})", String.format("%02X", result & 0xFF), getErrorCodeMessage(result));
+ log.error("璇锋鏌P鍦板潃鍜岀鍙f槸鍚︽纭�");
+ return false;
+ }
+ } catch (UnsatisfiedLinkError e) {
+ log.error("RFID璁惧DLL鏂规硶閾炬帴澶辫触 - OpenNetPort", e);
+ log.error("閿欒淇℃伅: {}", e.getMessage());
+ log.error("鍙兘鍘熷洜锛�1. DLL鐗堟湰涓嶅尮閰� 2. 鏂规硶绛惧悕涓嶅尮閰� 3. DLL鏈纭姞杞�");
+ throw e; // 閲嶆柊鎶涘嚭寮傚父锛岃璋冪敤鑰呭鐞�
+ }
+ }
+
+ /**
+ * 銆愮綉缁滆繛鎺ャ�戜娇鐢ㄩ粯璁ょ鍙�6000杩炴帴
+ *
+ * @param ipAddr IP鍦板潃 (濡�: 192.168.1.190)
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean connectNetwork(String ipAddr) {
+ return connectNetwork(ipAddr, 6000);
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戝叧闂繛鎺�
+ */
+ public void disconnect() {
+ if (!isConnected) {
+ log.warn("褰撳墠娌℃湁杩炴帴");
+ return;
+ }
+
+ if ("COM".equals(connectionType)) {
+ int result = reader.CloseSpecComPort(portHandle);
+ if (result == 0) {
+ log.info("涓插彛杩炴帴宸插叧闂�");
+ }
+ } else if ("NET".equals(connectionType)) {
+ int result = reader.CloseNetPort(portHandle);
+ if (result == 0) {
+ log.info("缃戠粶杩炴帴宸插叧闂�");
+ }
+ }
+
+ portHandle = -1;
+ isConnected = false;
+ connectionType = "";
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戞鏌ヨ繛鎺ョ姸鎬�
+ *
+ * @return true=宸茶繛鎺�, false=鏈繛鎺�
+ */
+ public boolean isConnected() {
+ return isConnected && portHandle >= 0;
+ }
+
+ /**
+ * 銆愬ぉ绾块厤缃�戦噸鏂伴厤缃ぉ绾匡紙鍔ㄦ�佸垏鎹㈠ぉ绾挎椂浣跨敤锛�
+ * 褰撶墿鐞嗗ぉ绾挎彃鎷斿悗锛岃皟鐢ㄦ鏂规硶閲嶆柊閰嶇疆澶╃嚎锛岀‘淇濇墍鏈夋彃涓婄殑澶╃嚎閮借兘琚娴嬪埌
+ *
+ * @return true=鎴愬姛, false=澶辫触
+ */
+ public boolean reconfigureAntenna() {
+ if (!isConnected()) {
+ log.warn("璁惧鏈繛鎺ワ紝鏃犳硶閰嶇疆澶╃嚎");
+ return false;
+ }
+
+ boolean configured = false;
+
+ try {
+ int checkAntResult = reader.SetCheckAnt(comAddr, (byte)0x01, portHandle);
+ if (checkAntResult == 0) {
+// log.info("澶╃嚎妫�娴嬪紑鍚垚鍔�");
+ configured = true;
+ }
+
+ int antResult = reader.SetAntennaMultiplexing(comAddr, (byte)0x0F, portHandle);
+ if (antResult == 0) {
+ log.info("澶╃嚎澶氳矾澶嶇敤閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ configured = true;
+ } else {
+ int antennaResult = reader.SetAntenna(comAddr, (byte)0, (byte)0x0F, (byte)0, portHandle);
+ if (antennaResult == 0) {
+ log.info("澶╃嚎閰嶇疆鎴愬姛 - 鍚敤澶╃嚎1,2,3,4 (0x0F)");
+ configured = true;
+ }
+ }
+
+ return configured;
+ } catch (Exception e) {
+ log.error("閲嶆柊閰嶇疆澶╃嚎寮傚父: {}", e.getMessage(), e);
+ return false;
+ }
+ }
+
+ /**
+ * 銆愯繛鎺ョ鐞嗐�戣幏鍙栬繛鎺ョ被鍨�
+ *
+ * @return "COM"=涓插彛, "NET"=缃戠粶, ""=鏈繛鎺�
+ */
+ public String getConnectionType() {
+ return connectionType;
+ }
+
+ // ==================== 妯″潡2: 璇诲彇妯″潡 ====================
+
+ public List<TagInfo> readTags(int qValue, int session, int scanTime) {
+ List<TagInfo> tagList = new ArrayList<>();
+ if (!isConnected()) {
+ return tagList;
+ }
+
+ byte maskMem = 2;
+ byte[] maskAdr = new byte[2];
+ byte maskLen = 0;
+ byte[] maskData = new byte[256];
+ byte maskFlag = 0;
+ byte adrTID = 0;
+ byte lenTID = 6;
+ byte tidFlag = 0;
+ byte target = 0;
+ byte fastFlag = 0;
+ byte[] pEPCList = new byte[20000];
+ byte[] ant = new byte[1];
+ int[] totallen = new int[1];
+ int[] cardNum = new int[1];
+
+ byte[] antennaValues = {(byte)0x80, (byte)0x81, (byte)0x82, (byte)0x83};
+ int[] antennaNumbers = {1, 2, 3, 4};
+
+ for (int antIdx = 0; antIdx < antennaValues.length; antIdx++) {
+ byte inAnt = antennaValues[antIdx];
+ int expectedAntenna = antennaNumbers[antIdx];
+
+ java.util.Arrays.fill(pEPCList, (byte)0);
+ totallen[0] = 0;
+ cardNum[0] = 0;
+
+ int result = reader.Inventory_G2(comAddr, (byte)qValue, (byte)session, maskMem, maskAdr, maskLen,
+ maskData, maskFlag, adrTID, lenTID, tidFlag, target, inAnt, (byte)scanTime,
+ fastFlag, pEPCList, ant, totallen, cardNum, portHandle);
+
+ if (cardNum[0] > 0 && totallen[0] > 0) {
+ int m = 0;
+ for (int index = 0; index < cardNum[0]; index++) {
+ if (m >= totallen[0] || m >= pEPCList.length) break;
+
+ int epcLen = pEPCList[m++] & 0xFF;
+ if (epcLen <= 0 || epcLen > 32) break;
+
+ if (m + epcLen > totallen[0] || m + epcLen > pEPCList.length) break;
+
+ byte[] epcBytes = new byte[epcLen];
+ for (int n = 0; n < epcLen; n++) {
+ epcBytes[n] = pEPCList[m++];
+ }
+
+ if (m >= totallen[0] || m >= pEPCList.length) break;
+
+ int rssi = pEPCList[m++] & 0xFF;
+ if (rssi > 127) rssi = rssi - 256;
+
+ int antennaValue = 0;
+ if (m < totallen[0] && m < pEPCList.length) {
+ antennaValue = pEPCList[m++] & 0xFF;
+ } else {
+ antennaValue = ant[0] & 0xFF;
+ }
+
+ TagInfo tag = new TagInfo();
+ tag.epc = bytesToHex(epcBytes);
+ tag.rssi = rssi;
+
+ if (antennaValue >= 0x80 && antennaValue <= 0x83) {
+ tag.antenna = antennaValue - 0x80 + 1;
+ } else if (antennaValue >= 1 && antennaValue <= 4) {
+ tag.antenna = antennaValue;
+ } else {
+ tag.antenna = expectedAntenna;
+ }
+ tag.timestamp = System.currentTimeMillis();
+
+ tagList.add(tag);
+ }
+ } else {
+ if (result != 0) {
+ int errorCode = result & 0xFF;
+ if (errorCode == 0xFB) {
+ continue;
+ }
+ if (errorCode == 0x01) {
+ continue;
+ }
+ if (errorCode == 0xF8) {
+// log.warn("澶╃嚎{}鐩樼偣澶辫触锛岄敊璇爜: 0x{} ({})", expectedAntenna, String.format("%02X", errorCode), getErrorCodeMessage(result));
+ } else {
+// log.debug("澶╃嚎{}鐩樼偣澶辫触锛岄敊璇爜: 0x{} ({})", expectedAntenna, String.format("%02X", errorCode), getErrorCodeMessage(result));
+ }
+ }
+ }
+ }
+
+ return tagList;
+ }
+
+ public List<TagInfo> readTags() {
+ return readTags(4, 0, 10);
+ }
+
+ // ==================== 宸ュ叿鏂规硶 ====================
+
+ private String bytesToHex(byte[] bytes) {
+ if (bytes == null) return "";
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ sb.append(String.format("%02X", b & 0xFF));
+ }
+ return sb.toString();
+ }
+
+ private String getErrorCodeMessage(int errorCode) {
+ switch (errorCode & 0xFF) {
+ case 0x00: return "鏃犻敊璇紝API璋冪敤鎴愬姛";
+ case 0x01: return "璇㈡煡鏃堕棿缁撴潫鍓嶈繑鍥�";
+ case 0x02: return "鎸囧畾鐨勮鏌ユ椂闂存孩鍑�";
+ case 0x03: return "瀛樺偍鍣ㄨ秴闄愭垨涓嶈鏀寔鐨凱C鍊�";
+ case 0x04: return "瀛樺偍鍣ㄩ攣瀹�";
+ case 0x05: return "璁块棶瀵嗙爜閿欒";
+ case 0x09: return "閿�姣佸瘑鐮侀敊璇�";
+ case 0x0A: return "閿�姣佸瘑鐮佷笉鑳戒负鍏�0";
+ case 0x0B: return "鐢靛瓙鏍囩涓嶆敮鎸佽鍛戒护鎴栫數婧愪笉瓒�";
+ case 0x0C: return "瀵硅鍛戒护锛岃闂瘑鐮佷笉鑳戒负0";
+ case 0x0D: return "鐢靛瓙鏍囩宸茬粡琚缃簡璇讳繚鎶わ紝涓嶈兘鍐嶆璁剧疆";
+ case 0x0E: return "鐢靛瓙鏍囩娌℃湁琚缃淇濇姢锛屼笉闇�瑕佽В閿�";
+ case 0x0F: return "闈炵壒瀹氶敊璇紝鏍囩涓嶆敮鎸佺壒瀹氶敊璇唬鐮�";
+ case 0x10: return "鏈夊瓧鑺傜┖闂磋閿佸畾锛屽啓鍏ュけ璐�";
+ case 0x11: return "涓嶈兘閿佸畾";
+ case 0x12: return "宸茬粡閿佸畾锛屼笉鑳藉啀娆¢攣瀹�";
+ case 0x13: return "鍙傛暟淇濆瓨澶辫触,浣嗚缃殑鍊煎湪璇诲啓妯″潡鏂數鍓嶆湁鏁�";
+ case 0x14: return "鏃犳硶璋冩暣";
+ case 0x15: return "璇㈡煡鏃堕棿缁撴潫鍓嶈繑鍥�";
+ case 0x17: return "鏈潯娑堟伅涔嬪悗锛岃繕鏈夋秷鎭�";
+ case 0x18: return "璇诲啓妯″潡瀛樺偍绌洪棿宸叉弧";
+ case 0x19: return "鐢靛瓙涓嶆敮鎸佽鍛戒护鎴栬�呰闂瘑鐮佷笉鑳戒负0";
+ case 0x30: return "閫氳閿欒";
+ case 0x33: return "閫氳绻佸繖锛岃澶囨鍦ㄦ墽琛屽叾浠栧懡浠�";
+ case 0x35: return "绔彛宸叉墦寮�";
+ case 0x37: return "鏃犳晥鍙ユ焺";
+ case 0xF8: return "澶╃嚎妫�娴嬮敊璇�";
+ case 0xF9: return "鍛戒护鎵ц鍑洪敊";
+ case 0xFA: return "鏈夌數瀛愭爣绛撅紝浣嗛�氫俊涓嶇晠锛屾棤娉曟搷浣�";
+ case 0xFB: return "鏃犵數瀛愭爣绛惧彲鎿嶄綔";
+ case 0xFC: return "鐢靛瓙鏍囩杩斿洖閿欒浠g爜";
+ case 0xFD: return "鍛戒护闀垮害閿欒";
+ case 0xFE: return "涓嶅悎娉曠殑鍛戒护";
+ case 0xFF: return "鍙傛暟閿欒";
+ default: return "鏈煡閿欒鐮�";
+ }
+ }
+
+ // ==================== 鏍囩淇℃伅绫� ====================
+
+ /**
+ * 鏍囩淇℃伅绫�
+ */
+ public static class TagInfo {
+ public String epc; // EPC锛堝崄鍏繘鍒跺瓧绗︿覆锛�
+ public int rssi; // RSSI锛坉Bm锛�
+ public int antenna; // 澶╃嚎鍙�
+ public long timestamp; // 鏃堕棿鎴�
+
+ @Override
+ public String toString() {
+ return String.format("EPC: %s, RSSI: %ddBm, 澶╃嚎: %d", epc, rssi, antenna);
+ }
+ }
+}
diff --git a/src/main/java/com/zy/service/RFIDAutoConnectService.java b/src/main/java/com/zy/service/RFIDAutoConnectService.java
new file mode 100644
index 0000000..65a5b77
--- /dev/null
+++ b/src/main/java/com/zy/service/RFIDAutoConnectService.java
@@ -0,0 +1,557 @@
+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璁惧鐙珛绠$悊锛屾瘡涓澶囩嫭绔嬬殑杩炴帴绾跨▼鍜屾娴嬬嚎绋�
+ * 姣忎釜璁惧鐨刟utoConnect閰嶇疆鐙珛鎺у埗
+ *
+ * @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<Integer, DeviceManager> 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<TagInfo> 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锛岀‘淇滵LL鏂规硶閾炬帴澶辫触鏃朵篃浼氬畾鏈熼噸杩�
+ */
+ 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璁惧[{}]杩炴帴鎴愬姛锛両P: {}, 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 {
+ // 杩炴帴姝e父锛屽畾鏈熼噸鏂伴厤缃ぉ绾匡紙澶勭悊澶╃嚎鎻掓嫈鎯呭喌锛�
+ // 姣�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锛岀‘淇滵LL鏂规硶閾炬帴澶辫触鏃朵笉褰卞搷閲嶈繛
+ */
+ private void scanLoop() {
+ log.info("RFID璁惧[{}]鏍囩妫�娴嬬嚎绋嬪惎鍔� - IP: {}", config.getId(), config.getIp());
+
+ while (running.get()) {
+ try {
+ if (connected.get() && template.isConnected()) {
+ try {
+ List<TagInfo> 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<TagInfo> 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("鏈厤缃甊FID璁惧");
+ return;
+ }
+
+ log.info("RFID鍏ㄥ眬閰嶇疆 - 閲嶈繛闂撮殧: {}绉�, 妫�娴嬮棿闅�: {}姣, 鎵弿鏃堕棿: {} * 100ms",
+ globalReconnectInterval, globalTagScanInterval, globalTagScanTime);
+
+ // 閬嶅巻鎵�鏈塕FID璁惧閰嶇疆
+ 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());
+ }
+
+ /**
+ * 鎵嬪姩鍋滄鎵�鏈塕FID璁惧杩炴帴锛堥�氳繃API璋冪敤锛�
+ * 娉ㄦ剰锛氱Щ闄や簡@PreDestroy锛屾湇鍔′笉浼氳嚜鍔ㄥ叧闂紝鍙兘閫氳繃API鎵嬪姩鍏抽棴
+ */
+ public void stopAll() {
+ log.info("========== RFID鑷姩杩炴帴鏈嶅姟鎵嬪姩鍏抽棴 ==========");
+
+ // 鍋滄鎵�鏈夎澶囩鐞嗗櫒
+ for (Map.Entry<Integer, DeviceManager> 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<String, Object> getDeviceStatus(Integer deviceId) {
+ Map<String, Object> 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<Map<String, Object>> getAllDeviceStatus() {
+ List<Map<String, Object>> result = new ArrayList<>();
+
+ for (Map.Entry<Integer, DeviceManager> entry : deviceManagers.entrySet()) {
+ Map<String, Object> 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<Map<String, Object>> getDeviceTags(Integer deviceId, String ip, Integer antenna) {
+ List<Map<String, Object>> 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<TagInfo> tags = manager.latestTags;
+ if (tags == null || tags.isEmpty()) {
+ return result;
+ }
+
+ for (TagInfo tag : tags) {
+ if (antenna != null && tag.antenna != antenna) {
+ continue;
+ }
+ Map<String, Object> 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<Map<String, Object>> queryDeviceTags(Integer deviceId, String ip, Integer antenna) {
+ List<Map<String, Object>> 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<TagInfo> 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<String, Object> 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;
+ }
+}
diff --git a/src/main/java/com/zy/service/RFIDService.java b/src/main/java/com/zy/service/RFIDService.java
new file mode 100644
index 0000000..28ba437
--- /dev/null
+++ b/src/main/java/com/zy/service/RFIDService.java
@@ -0,0 +1,393 @@
+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", "杩炴帴澶辫触锛岃妫�鏌P鍜岀鍙�");
+ }
+ } 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", "璇锋鏌LL鏂囦欢鏄惁姝g‘锛屾垨灏濊瘯閲嶅惎搴旂敤");
+ } catch (Exception e) {
+ log.error("RFID璁惧杩炴帴寮傚父", e);
+ result.put("success", false);
+ result.put("message", "杩炴帴寮傚父: " + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /**
+ * 杩炴帴RFID璁惧锛堜覆鍙h繛鎺ワ級
+ *
+ * @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", "杩炴帴澶辫触锛岃妫�鏌ヤ覆鍙e拰娉㈢壒鐜�");
+ }
+ } 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", "璇锋鏌LL鏂囦欢鏄惁姝g‘锛屾垨灏濊瘯閲嶅惎搴旂敤");
+ } catch (Exception e) {
+ log.error("RFID璁惧杩炴帴寮傚父", e);
+ result.put("success", false);
+ result.put("message", "杩炴帴寮傚父: " + e.getMessage());
+ }
+
+ return result;
+ }
+
+ /**
+ * 妫�娴婻FID鏍囩锛堝崟娆℃娴嬶級
+ * 鍙湪妫�娴嬪埌鏍囩鏃舵墦鍗版棩蹇�
+ *
+ * @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 {
+ // 妫�鏌LL鏂囦欢鏄惁瀛樺湪锛堜娇鐢ㄩ」鐩牴鐩綍鐨勭浉瀵硅矾寰勶級
+ 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");
+
+ // 涔熸鏌ヤ复鏃剁洰褰曚腑鐨凞LL鏂囦欢
+ 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);
+
+ // 妫�鏌evice绫绘槸鍚﹀彲浠ュ疄渚嬪寲
+ 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);
+ }
+
+ // 妫�鏌ative鏂规硶鏄惁鍙敤锛堝疄闄呭皾璇曡皟鐢ㄩ獙璇侊級
+ boolean nativeMethodAvailable = false;
+ String nativeMethodError = null;
+ if (deviceCreated && rfidTemplate != null) {
+ try {
+ // 瀹為檯灏濊瘯璋冪敤native鏂规硶鏉ラ獙璇侊紙浣跨敤鏃犳晥鍙傛暟锛屽彧娴嬭瘯鏂规硶閾炬帴锛�
+ // 濡傛灉鏂规硶涓嶅瓨鍦ㄦ垨閾炬帴澶辫触锛屼細鎶涘嚭UnsatisfiedLinkError
+ boolean wasConnected = rfidTemplate.isConnected();
+ if (!wasConnected) {
+ // 灏濊瘯杩炴帴涓�涓棤鏁堢殑IP鍦板潃锛屽彧娴嬭瘯native鏂规硶鏄惁鍙敤
+ // 娉ㄦ剰锛氳繖閲屼細澶辫触锛屼絾鎴戜滑鍙叧蹇冩柟娉曟槸鍚﹂摼鎺ユ垚鍔�
+ try {
+ // 璋冪敤connectNetwork锛屽鏋渘ative鏂规硶閾炬帴澶辫触浼氭姏鍑篣nsatisfiedLinkError
+ boolean connected = rfidTemplate.connectNetwork("127.0.0.1", 9999);
+ // 濡傛灉鎵ц鍒拌繖閲岋紝璇存槑native鏂规硶閾炬帴鎴愬姛锛堝嵆浣胯繛鎺ュけ璐ワ級
+ nativeMethodAvailable = true;
+ // 濡傛灉鎰忓杩炴帴鎴愬姛锛屾柇寮�杩炴帴
+ if (connected) {
+ rfidTemplate.disconnect();
+ }
+ } catch (UnsatisfiedLinkError e) {
+ // 濡傛灉鎶涘嚭UnsatisfiedLinkError锛岃鏄巒ative鏂规硶閾炬帴澶辫触
+ nativeMethodError = "DLL native鏂规硶閾炬帴澶辫触: " + e.getMessage();
+ nativeMethodAvailable = false;
+ } catch (Exception e) {
+ // 鍏朵粬寮傚父锛堝杩炴帴澶辫触銆佺綉缁滈敊璇瓑锛夋槸姝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() + " 瀛楄妭)");
+ // 妫�鏌LL鏂囦欢鏄惁鍙兘鏄枃鏈枃浠讹紙琚玀aven杩囨护鎹熷潖锛�
+ if (dllFile1.length() < 1000) {
+ suggestions.add("璀﹀憡锛欴LL鏂囦欢澶у皬寮傚父灏忥紝鍙兘琚崯鍧�");
+ }
+ }
+
+ if (!deviceCreated) {
+ suggestions.add("Device绫诲疄渚嬪寲澶辫触锛岃妫�鏌LL鏂囦欢鏄惁瀛樺湪");
+ } else if (!nativeMethodAvailable) {
+ suggestions.add("DLL宸插姞杞斤紝浣唍ative鏂规硶涓嶅彲鐢�");
+ suggestions.add("閿欒淇℃伅: " + (nativeMethodError != null ? nativeMethodError : "鏈煡閿欒"));
+ suggestions.add("鍙兘鍘熷洜锛�1. DLL鐗堟湰涓嶅尮閰� 2. 鏂规硶绛惧悕涓嶅尮閰� 3. DLL鏂囦欢鎹熷潖");
+ suggestions.add("瑙e喅鏂规锛�");
+ suggestions.add("1. 浠巇emo椤圭洰(testdemo-jni)涓鍒禗LL鏂囦欢鍒板綋鍓嶉」鐩�");
+ suggestions.add("2. 纭繚DLL鏂囦欢娌℃湁琚玀aven璧勬簮杩囨护澶勭悊");
+ suggestions.add("3. 妫�鏌LL鏂囦欢澶у皬鏄惁涓巇emo椤圭洰涓殑涓�鑷�");
+ suggestions.add("4. 灏濊瘯閲嶆柊缂栬瘧椤圭洰: mvn clean compile");
+ suggestions.add("5. 妫�鏌ヤ复鏃剁洰褰曚腑鐨凞LL鏂囦欢: " + System.getProperty("java.io.tmpdir") + "rfid-lib");
+ } else {
+ suggestions.add("DLL鍔犺浇姝e父锛宯ative鏂规硶鍙敤");
+ }
+
+ 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;
+ }
+}
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 1a96d35..5e19374 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -635,4 +635,35 @@
port: 5005
devpPlcId: ${wcs-slave.devp[1].id}
staArr: 107
- crnId: 2
\ No newline at end of file
+ crnId: 2
+
+ # RFID璇诲啓鍣ㄩ厤缃�
+ rfid-config:
+ # 鍏ㄥ眬榛樿閰嶇疆
+ reconnectInterval: 10 # 閲嶈繛闂撮殧锛堢锛�
+ tagScanInterval: 500 # 鏍囩妫�娴嬮棿闅旓紙姣锛�
+ tagScanTime: 10 # 鏍囩鎵弿鏃堕棿锛堝崟浣�: 100ms锛岄粯璁�10=1绉掞級
+ # RFID璇诲啓鍣�1
+ rfid[0]:
+ id: 1
+ ip: 10.10.10.210
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴锛坱rue: 绯荤粺鍚姩鏃惰嚜鍔ㄨ繛鎺ワ紝false: 鎵嬪姩杩炴帴锛�
+ # RFID璇诲啓鍣�2
+ rfid[1]:
+ id: 2
+ ip: 10.10.10.211
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
+ # RFID璇诲啓鍣�3
+ rfid[2]:
+ id: 3
+ ip: 10.10.10.212
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
+ # RFID璇诲啓鍣�4
+ rfid[3]:
+ id: 4
+ ip: 10.10.10.213
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
\ No newline at end of file
diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml
index 88c854e..2ec24d3 100644
--- a/src/main/resources/application-prod.yml
+++ b/src/main/resources/application-prod.yml
@@ -635,4 +635,35 @@
port: 5005
devpPlcId: ${wcs-slave.devp[1].id}
staArr: 107
- crnId: 2
\ No newline at end of file
+ crnId: 2
+
+ # RFID璇诲啓鍣ㄩ厤缃�
+ rfid-config:
+ # 鍏ㄥ眬榛樿閰嶇疆
+ reconnectInterval: 10 # 閲嶈繛闂撮殧锛堢锛�
+ tagScanInterval: 500 # 鏍囩妫�娴嬮棿闅旓紙姣锛�
+ tagScanTime: 10 # 鏍囩鎵弿鏃堕棿锛堝崟浣�: 100ms锛岄粯璁�10=1绉掞級
+ # RFID璇诲啓鍣�1
+ rfid[0]:
+ id: 1
+ ip: 10.10.10.210
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴锛坱rue: 绯荤粺鍚姩鏃惰嚜鍔ㄨ繛鎺ワ紝false: 鎵嬪姩杩炴帴锛�
+ # RFID璇诲啓鍣�2
+ rfid[1]:
+ id: 2
+ ip: 10.10.10.211
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
+ # RFID璇诲啓鍣�3
+ rfid[2]:
+ id: 3
+ ip: 10.10.10.212
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
+ # RFID璇诲啓鍣�4
+ rfid[3]:
+ id: 4
+ ip: 10.10.10.213
+ port: 27011
+ autoConnect: true # 鏄惁鑷姩杩炴帴
\ No newline at end of file
diff --git a/src/main/resources/lib/UHFReader288.dll b/src/main/resources/lib/UHFReader288.dll
new file mode 100644
index 0000000..cdff98a
--- /dev/null
+++ b/src/main/resources/lib/UHFReader288.dll
Binary files differ
diff --git a/src/main/resources/lib/com_rfid_uhf288_Device.dll b/src/main/resources/lib/com_rfid_uhf288_Device.dll
new file mode 100644
index 0000000..ce026e3
--- /dev/null
+++ b/src/main/resources/lib/com_rfid_uhf288_Device.dll
Binary files differ
--
Gitblit v1.9.1