.settings/org.eclipse.core.resources.prefs
@@ -3,4 +3,5 @@ encoding//src/publicway/ProtocolParser01.java=GBK encoding//src/publicway/ProtocolParser51.java=GBK encoding//src/publicway/SerialProtocolParser.java=UTF-8 encoding/log.properties=GBK encoding/err.properties=utf8 encoding/log.properties=UTF8 bin/.gitignore
@@ -4,3 +4,4 @@ /xitongshezhi/ /chuankou/ /publicway/ /dialog/ bin/chuankou/Sendmsg.classBinary files differ
bin/chuankou/SerialDataReceiver.classBinary files differ
bin/chuankou/SerialPortService.classBinary files differ
bin/chushihua/Chushihua.classBinary files differ
bin/chushihua/SlotManager.classBinary files differ
bin/chushihua/lunxun$PollingTask.classBinary files differ
bin/chushihua/lunxun.classBinary files differ
bin/home/CardMachineUI$1.classBinary files differ
bin/home/CardMachineUI$SlotStatus.classBinary files differ
bin/home/CardMachineUI.classBinary files differ
bin/home/Homein.classBinary files differ
bin/publicway/ProtocolParser01$CardStatus.classBinary files differ
bin/publicway/ProtocolParser01$DoorStatus.classBinary files differ
bin/publicway/ProtocolParser01$FaultType.classBinary files differ
bin/publicway/ProtocolParser01$ParseResult.classBinary files differ
bin/publicway/ProtocolParser01$ParseResultPool.classBinary files differ
bin/publicway/ProtocolParser01$WorkStatus.classBinary files differ
bin/publicway/ProtocolParser01.classBinary files differ
bin/publicway/SerialProtocolParser.classBinary files differ
bin/xitongshezhi/ConfigSet$1.classBinary files differ
bin/xitongshezhi/ConfigSet$2.classBinary files differ
bin/xitongshezhi/ConfigSet$3.classBinary files differ
bin/xitongshezhi/ConfigSet$MenuItemListener.classBinary files differ
bin/xitongshezhi/ConfigSet.classBinary files differ
bin/xitongshezhi/Fkj.classBinary files differ
bin/xitongshezhi/kacaoguanli$1.classBinary files differ
bin/xitongshezhi/kacaoguanli$2.classBinary files differ
bin/xitongshezhi/kacaoguanli$3.classBinary files differ
bin/xitongshezhi/kacaoguanli$4.classBinary files differ
bin/xitongshezhi/kacaoguanli$5.classBinary files differ
bin/xitongshezhi/kacaoguanli$CustomTableCellRenderer.classBinary files differ
bin/xitongshezhi/kacaoguanli$StatusInfo.classBinary files differ
bin/xitongshezhi/kacaoguanli.classBinary files differ
bin/xitongshezhi/kuaisuquka$1.classBinary files differ
bin/xitongshezhi/kuaisuquka$2.classBinary files differ
bin/xitongshezhi/kuaisuquka$3.classBinary files differ
bin/xitongshezhi/kuaisuquka$4.classBinary files differ
bin/xitongshezhi/kuaisuquka$5.classBinary files differ
bin/xitongshezhi/kuaisuquka$6.classBinary files differ
bin/xitongshezhi/kuaisuquka$SlotButtonListener.classBinary files differ
bin/xitongshezhi/kuaisuquka$SlotStatus.classBinary files differ
bin/xitongshezhi/kuaisuquka.classBinary files differ
bin/xitongshezhi/lishijilu$1.classBinary files differ
bin/xitongshezhi/lishijilu.classBinary files differ
config.properties
@@ -10,3 +10,6 @@ server.port=8081 system.language=zh-CN total.slots=60 popup.display.time=5 error.log.server.address=39.106.210.13 error.log.server.port=8082 err.properties
¶Ô±ÈÐÂÎļþ @@ -0,0 +1,10 @@ #\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Fri Nov 21 15:53:26 CST 2025 #Fri Nov 21 15:53:26 CST 2025 log_1763709005376_be67189d=[2025-11-21 15\:10\:05] å塿ä½ï¼12132232 log_1763709010792_533f9544=[2025-11-21 15\:10\:10] å塿ä½ï¼å¡æ§½14被管çååå¡ log_1763711606778_258ce9b3=[2025-11-21 15\:53\:26] [15\:53\:26.776] åéå¤±è´¥ï¼æ£å¨éè¯ (1/2) log_1763711606820_621ce6a5=[2025-11-21 15\:53\:26] [15\:53\:26.820] åéå¤±è´¥ï¼æ£å¨éè¯ (1/2) log_1763711606821_a4bb65ce=[2025-11-21 15\:53\:26] [15\:53\:26.821] åéå¤±è´¥ï¼æ£å¨éè¯ (1/2) log_1763711606822_e9cc5b23=[2025-11-21 15\:53\:26] [15\:53\:26.822] åéå¤±è´¥ï¼æ£å¨éè¯ (1/2) log_1763711606823_1da1f119=[2025-11-21 15\:53\:26] [15\:53\:26.823] åéå¤±è´¥ï¼æ£å¨éè¯ (1/2) log_1763711606824_15788a29=[2025-11-21 15\:53\:26] lunxunè¿ç»å¤±è´¥æ¬¡æ°è¿å¤ï¼æå轮询 log.properties
@@ -1,5 +1,33 @@ #\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Thu Nov 20 20:49:18 CST 2025 #Thu Nov 20 20:49:18 CST 2025 log_1763642944396_d82061c8=[2025-11-20 20\:49\:04] \u53D6\u5361\u64CD\u4F5C\uFF1A\u5361\u69FD14\u88AB\u7BA1\u7406\u5458\u53D6\u5361 log_1763642958908_d200dc13=[2025-11-20 20\:49\:18] \u53D6\u5361\u64CD\u4F5C\uFF1A\u5361\u69FD25\u88AB\u7BA1\u7406\u5458\u53D6\u5361 \u00B2\u00E2\u00CA\u00D4= #\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Fri Nov 21 17:44:41 CST 2025 #Fri Nov 21 17:44:41 CST 2025 log_1763718093181_61c0dfbe=[2025-11-21 17\:41\:33] å塿ä½ï¼å¡æ§½13被管çååå¡ log_1763718093533_c3563f25=[2025-11-21 17\:41\:33] å塿ä½ï¼å¡æ§½13被管çååå¡ log_1763718147310_e84a6b5b=[2025-11-21 17\:42\:27] å塿ä½ï¼å¡æ§½22被管çååå¡ log_1763718150490_e2f94107=[2025-11-21 17\:42\:30] å塿ä½ï¼å¡æ§½23被管çååå¡ log_1763718150843_c9147690=[2025-11-21 17\:42\:30] å塿ä½ï¼å¡æ§½23被管çååå¡ log_1763718198841_27d9aa77=[2025-11-21 17\:43\:18] å塿ä½ï¼å¡æ§½12被管çååå¡ log_1763718199155_4cd5e39f=[2025-11-21 17\:43\:19] å塿ä½ï¼å¡æ§½12被管çååå¡ log_1763718207706_07760e2f=[2025-11-21 17\:43\:27] DDCC0008F003515AA55AA5027A7E;type2æ§å¶æå¼3æé¨ log_1763718208053_ee80022a=[2025-11-21 17\:43\:28] 3å·å¡æ§½åå¡å¤±è´¥ log_1763718208759_e8be3ec0=[2025-11-21 17\:43\:28] DDCC0008F003515AA55AA5027A7E;type2æ§å¶æå¼3æé¨ log_1763718209104_247397ce=[2025-11-21 17\:43\:29] å塿ä½ï¼å¡æ§½3被管çååå¡ log_1763718275945_e2a4d769=[2025-11-21 17\:44\:35] DDCC0008F012515AA55AA5027B7F;type2æ§å¶æå¼18æé¨ log_1763718276293_034826af=[2025-11-21 17\:44\:36] å塿ä½ï¼å¡æ§½18被管çååå¡ log_1763718276666_18777eee=[2025-11-21 17\:44\:36] DDCC0008F017515AA55AA5027B2A;type2æ§å¶æå¼23æé¨ log_1763718276992_c9ad983a=[2025-11-21 17\:44\:36] å塿ä½ï¼å¡æ§½23被管çååå¡ log_1763718277268_15912a52=[2025-11-21 17\:44\:37] DDCC0008F01C515AA55AA502BB90;type2æ§å¶æå¼28æé¨ log_1763718277593_d9b897ba=[2025-11-21 17\:44\:37] å塿ä½ï¼å¡æ§½28被管çååå¡ log_1763718277892_72d570bd=[2025-11-21 17\:44\:37] DDCC0008F018515AA55AA5027BD5;type2æ§å¶æå¼24æé¨ log_1763718278242_75327d86=[2025-11-21 17\:44\:38] å塿ä½ï¼å¡æ§½24被管çååå¡ log_1763718278782_a91dddda=[2025-11-21 17\:44\:38] DDCC0008F00E515AA55AA502BAA2;type2æ§å¶æå¼14æé¨ log_1763718279143_4e4cb89a=[2025-11-21 17\:44\:39] å塿ä½ï¼å¡æ§½14被管çååå¡ log_1763718279202_9c58a3b9=[2025-11-21 17\:44\:39] DDCC0008F013515AA55AA502BB6F;type2æ§å¶æå¼19æé¨ log_1763718279543_9e40ceff=[2025-11-21 17\:44\:39] å塿ä½ï¼å¡æ§½19被管çååå¡ log_1763718279709_4483c6c4=[2025-11-21 17\:44\:39] DDCC0008F01D515AA55AA5027B80;type2æ§å¶æå¼29æé¨ log_1763718280043_06750db2=[2025-11-21 17\:44\:40] å塿ä½ï¼å¡æ§½29被管çååå¡ log_1763718280658_b6288ce6=[2025-11-21 17\:44\:40] DDCC0008F00F515AA55AA5027AB2;type2æ§å¶æå¼15æé¨ log_1763718280993_f6f218cc=[2025-11-21 17\:44\:40] å塿ä½ï¼å¡æ§½15被管çååå¡ log_1763718281030_2d1edd96=[2025-11-21 17\:44\:41] DDCC0008F014515AA55AA5027B19;type2æ§å¶æå¼20æé¨ log_1763718281392_c8b2ee8c=[2025-11-21 17\:44\:41] å塿ä½ï¼å¡æ§½20被管çååå¡ log_1763718281404_56d7aa71=[2025-11-21 17\:44\:41] DDCC0008F019515AA55AA502BBC5;type2æ§å¶æå¼25æé¨ log_1763718281743_12a79e45=[2025-11-21 17\:44\:41] å塿ä½ï¼å¡æ§½25被管çååå¡ src/chuankou/Sendmsg.java
@@ -1,21 +1,156 @@ package chuankou; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.SwingWorker; import chushihua.lunxun; import dialog.Charulog; import dialog.Dingshidialog; import dialog.Errlog; import publicway.OpenDoor; import xitongshezhi.SystemDebugDialog; /** * 䏲壿¶æ¯åéå·¥å ·ç±» * æä¾é«æ§è½ç䏲壿¶æ¯åéåè½ï¼éåé«é¢è°ç¨ * ä¼åå å使ç¨ï¼é¿å é¿æ¶é´è¿è¡å åæ³æ¼ */ public class Sendmsg { // éæä¸²å£æå¡å®ä¾ private static volatile SerialPortService serialService = null; private static volatile boolean isPortOpen = false; private static final AtomicBoolean isPortOpen = new AtomicBoolean(false); // æ¹ä¸ºéfinalï¼æ¯æå¨ææ§å¶ private static boolean DEBUG_MODE = false; private static volatile boolean DEBUG_MODE = false; // æ¥ææ ¼å¼å private static final SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss.SSS"); // 使ç¨ThreadLocalä¿è¯SimpleDateFormat线ç¨å®å ¨ private static final ThreadLocal<SimpleDateFormat> TIME_FORMATTER = ThreadLocal.withInitial(() -> new SimpleDateFormat("HH:mm:ss.SSS")); // ç¼åå符串æå»ºå¨ï¼åå°å¯¹è±¡å建 private static final ThreadLocal<StringBuilder> STRING_BUILDER_CACHE = ThreadLocal.withInitial(() -> new StringBuilder(128)); // è®°å½æ´»è·çSwingWorkerï¼ä¾¿äºç®¡ç private static final ConcurrentHashMap<String, SwingWorker<?, ?>> ACTIVE_WORKERS = new ConcurrentHashMap<>(); /**å塿å¡å¨æ§å¶æå¼æä¸ªæé¨è°ç¨æä»¤ * @param int slotIdæé¨ç¼å·1-60 * @param int type 1æ¯æå¡å¨åå¡ï¼2æ¯ç®¡çååå¡*/ public static boolean opendoorzhiling(int slotId,int type) { lunxun.setSendChaxunzhiling(false);//æåæ¥è¯¢æä»¤ try { // è°ç¨OpenDoorçæå¼é¨æä»¤ String command = OpenDoor.openOneDoor(slotId, type); boolean sendResult = Sendmsg.sendMessage(command); StringBuilder mesBuilder = STRING_BUILDER_CACHE.get(); mesBuilder.setLength(0); // æ¸ ç©ºéç¨ mesBuilder.append(command).append(";type").append(type).append("æ§å¶æå¼").append(slotId).append("æé¨"); String mes = mesBuilder.toString(); Charulog.logOperation(mes); if (lunxun.DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData(mes); } return sendResult; } finally { // ç¡®ä¿æ¢å¤æ¥è¯¢æä»¤ lunxun.setSendChaxunzhiling(true); } } /** * æå¼å ¨é¨å¡æ§½çå ¬ç¨éææ¹æ³ * @param type æä½ç±»åï¼1-æå¡å¨åå¡ï¼2-管çååå¡ */ public static void openAllSlots(int type) { lunxun.setSendChaxunzhiling(false);//æåæ¥è¯¢æä»¤ String workerKey = "openAllSlots_" + System.currentTimeMillis(); // 使ç¨SwingWorkerå¨åå°æ§è¡ï¼é¿å é»å¡UI SwingWorker<Void, Void> worker = new SwingWorker<Void, Void>() { @Override protected Void doInBackground() throws Exception { // é忿塿§½ï¼1-60ï¼ for (int slotId = 1; slotId <= 60 && !isCancelled(); slotId++) { try { // çæå¼é¨æä»¤ String command = OpenDoor.openOneDoor(slotId, type); // åé䏲壿令 boolean sent = Sendmsg.sendMessage(command); if (!sent) { Errlog.logOperation("åéæä»¤å°å¡æ§½ " + slotId + " 失败"); } // é´é100msï¼ä½æ£æ¥æ¯å¦è¢«åæ¶ Thread.sleep(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; // è¢«ä¸ææ¶éåºå¾ªç¯ } catch (Exception e) { Errlog.logOperation("å¤ç塿§½ " + slotId + " æ¶åçé误: " + e.getMessage()); // ç»§ç»å¤çä¸ä¸ä¸ªå¡æ§½ï¼ä¸ä¸æå¾ªç¯ } } return null; } @Override protected void done() { try { // æ¸ çworkerå¼ç¨ ACTIVE_WORKERS.remove(workerKey); // å¯éï¼å®æåå¯ä»¥æ·»å åè°å¤ç if (!isCancelled()) { StringBuilder messageBuilder = STRING_BUILDER_CACHE.get(); messageBuilder.setLength(0); String types = "管çå"; if(type == 1) { types = "æå¡å¨æä»¤"; } messageBuilder.append(types).append("å·²å°å ¨é¨å¡æ§½å·²ç»æå¼è¯·åå¡"); String message = messageBuilder.toString(); Dingshidialog.showTimedDialog(null, 5, message); Charulog.logOperation(message); } } finally { // ç¡®ä¿æ¢å¤æ¥è¯¢æä»¤ lunxun.setSendChaxunzhiling(true); } } }; // è®°å½worker便äºç®¡ç ACTIVE_WORKERS.put(workerKey, worker); worker.execute(); } /** * åæ¶æææ£å¨æ§è¡çä»»å¡ */ public static void cancelAllTasks() { ACTIVE_WORKERS.forEach((key, worker) -> { if (!worker.isDone()) { worker.cancel(true); } }); ACTIVE_WORKERS.clear(); } /** * è®¾ç½®ä¸²å£æå¡å®ä¾ @@ -24,7 +159,7 @@ */ public static void setSerialService(SerialPortService service, boolean open) { serialService = service; isPortOpen = open; isPortOpen.set(open); } /** @@ -38,13 +173,13 @@ * åéæ¶æ¯å°ä¸²å£ï¼å¸¦éè¯æºå¶ï¼ */ public static boolean sendMessage(String message) { if (!isPortOpen || serialService == null) { System.err.println("[" + getCurrentTime() + "] 䏲壿ªæå¼ï¼æ æ³åéæ°æ®"); if (!isPortOpen.get() || serialService == null) { Errlog.logOperation("[" + getCurrentTime() + "] 䏲壿ªæå¼ï¼æ æ³åéæ°æ®"); return false; } if (message == null || message.trim().isEmpty()) { System.err.println("[" + getCurrentTime() + "] åéæ°æ®ä¸ºç©º"); Errlog.logOperation("[" + getCurrentTime() + "] åéæ°æ®ä¸ºç©º"); return false; } @@ -56,7 +191,7 @@ try { byte[] data = hexStringToByteArray(text); if (data == null) { System.err.println("[" + getCurrentTime() + "] HEX转æ¢å¤±è´¥ï¼æ°æ®: " + text); Errlog.logOperation("[" + getCurrentTime() + "] HEX转æ¢å¤±è´¥ï¼æ°æ®: " + text); return false; } @@ -70,7 +205,7 @@ } else { retryCount++; if (retryCount <= MAX_RETRY) { System.err.println("[" + getCurrentTime() + "] åéå¤±è´¥ï¼æ£å¨éè¯ (" + retryCount + "/" + MAX_RETRY + ")"); Errlog.logOperation("[" + getCurrentTime() + "] åéå¤±è´¥ï¼æ£å¨éè¯ (" + retryCount + "/" + MAX_RETRY + ")"); try { Thread.sleep(50); // éè¯åçå¾ } catch (InterruptedException e) { @@ -78,17 +213,21 @@ break; } } else { System.err.println("[" + getCurrentTime() + "] 串å£åéå¤±è´¥ï¼æä»¤: " + text.toUpperCase()); System.err.println("[" + getCurrentTime() + "] 串å£ç¶æ - æå¼: " + isPortOpen + ", æå¡: " + (serialService != null)); if (serialService != null) { System.err.println("[" + getCurrentTime() + "] 䏲壿å¡ç¶æ - æ¯å¦æå¼: " + serialService.isOpen()); if (DEBUG_MODE) { Errlog.logOperation("[" + getCurrentTime() + "] 串å£åéå¤±è´¥ï¼æä»¤: " + text.toUpperCase()); Errlog.logOperation("[" + getCurrentTime() + "] 串å£ç¶æ - æå¼: " + isPortOpen.get() + ", æå¡: " + (serialService != null)); if (serialService != null) { Errlog.logOperation("[" + getCurrentTime() + "] 䏲壿å¡ç¶æ - æ¯å¦æå¼: " + serialService.isOpen()); } } return false; } } } catch (Exception e) { System.err.println("[" + getCurrentTime() + "] åéå¼å¸¸ï¼æä»¤: " + text.toUpperCase()); e.printStackTrace(); Errlog.logOperation("[" + getCurrentTime() + "] åéå¼å¸¸ï¼æä»¤: " + text.toUpperCase()); if (DEBUG_MODE) { e.printStackTrace(); } return false; } } @@ -101,9 +240,9 @@ * @return 䏲壿å¼ç¶æ */ public static boolean isPortOpen() { boolean open = isPortOpen && serialService != null; boolean open = isPortOpen.get() && serialService != null; if (!open && DEBUG_MODE) { System.err.println("[" + getCurrentTime() + "] 串å£ç¶ææ£æ¥: æªæå¼"); Errlog.logOperation("[" + getCurrentTime() + "] 串å£ç¶ææ£æ¥: æªæå¼"); } return open; } @@ -148,7 +287,8 @@ return ""; } StringBuilder sb = new StringBuilder(); StringBuilder sb = STRING_BUILDER_CACHE.get(); sb.setLength(0); for (byte b : bytes) { sb.append(String.format("%02x", b)); } @@ -160,7 +300,7 @@ * @return æ¶é´å符串 */ private static String getCurrentTime() { return timeFormat.format(new Date()); return TIME_FORMATTER.get().format(new Date()); } /** @@ -186,4 +326,26 @@ DEBUG_MODE = debug; System.out.println("[" + getCurrentTime() + "] Sendmsgè°è¯æ¨¡å¼: " + (debug ? "å¯ç¨" : "ç¦ç¨")); } /** * æ¸ çèµæºï¼é²æ¢å åæ³æ¼ */ public static void cleanup() { cancelAllTasks(); // æ¸ çThreadLocalèµæº TIME_FORMATTER.remove(); STRING_BUILDER_CACHE.remove(); if (DEBUG_MODE) { System.out.println("[" + getCurrentTime() + "] Sendmsgèµæºæ¸ ç宿"); } } /** * è·åæ´»è·ä»»å¡æ°é */ public static int getActiveTaskCount() { return ACTIVE_WORKERS.size(); } } src/chuankou/SerialDataReceiver.java
@@ -6,21 +6,26 @@ public class SerialDataReceiver { private static final int BUFFER_SIZE = 1024; private static byte[] staticDataBuffer = new byte[BUFFER_SIZE]; private static int staticBufferPosition = 0; private static final int MIN_PACKET_LENGTH = 9; private static final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC}; // 使ç¨ééææåé¿å å¤çº¿ç¨ç¯å¢ä¸çç«äºæ¡ä»¶ private byte[] dataBuffer = new byte[BUFFER_SIZE]; private int bufferPosition = 0; private final List<byte[]> reusablePackets = new ArrayList<>(); /** * éææ¹æ³ï¼æ¥æ¶ä¸²å£åå§æ°æ®å¹¶è§£æå®æ´æ°æ®å * å®ä¾æ¹æ³ï¼æ¥æ¶ä¸²å£åå§æ°æ®å¹¶è§£æå®æ´æ°æ®å * @param rawData åå§æ°æ® * @param debugEnabled æ¯å¦å¯ç¨è°è¯ * @param maxRawDataPrintLength æå¤§æå°é¿åº¦ * @return è§£æåºç宿´æ°æ®å å表ï¼å¦ææ²¡æå®æ´å åè¿å空å表 */ public static List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) { List<byte[]> completePackets = new ArrayList<>(); public List<byte[]> receiveData(byte[] rawData, boolean debugEnabled, int maxRawDataPrintLength) { reusablePackets.clear(); if (rawData == null || rawData.length == 0) { return completePackets; return reusablePackets; } // æå°åå§æ¥æ¶æ°æ®ï¼è°è¯ç¨ï¼ @@ -28,88 +33,114 @@ printRawData("æ¶å°ä¸²å£åå§æ°æ®", rawData, maxRawDataPrintLength); } // å°æ°æ®æ·»å å°ç¼å²åº if (staticBufferPosition + rawData.length > staticDataBuffer.length) { // æ£æ¥ç¼å²åºå®¹éï¼å¨æå¤ç if (!ensureBufferCapacity(rawData.length)) { // ç¼å²åºä¸è¶³æ¶ï¼æ¸ çå¹¶éæ°å¼å§ System.arraycopy(staticDataBuffer, staticBufferPosition - rawData.length, staticDataBuffer, 0, rawData.length); staticBufferPosition = rawData.length; } else { System.arraycopy(rawData, 0, staticDataBuffer, staticBufferPosition, rawData.length); staticBufferPosition += rawData.length; if (debugEnabled) { System.out.println("ç¼å²åºä¸è¶³ï¼æ¸ 空ç¼å²åºéæ°å¼å§"); } bufferPosition = 0; } // å¤çç¼å²åºä¸çæ°æ®å¹¶æ¶é宿´å processBuffer(completePackets, debugEnabled); // å°æ°æ®æ·»å å°ç¼å²åº System.arraycopy(rawData, 0, dataBuffer, bufferPosition, rawData.length); bufferPosition += rawData.length; return completePackets; // å¤çç¼å²åºä¸çæ°æ®å¹¶æ¶é宿´å processBuffer(reusablePackets, debugEnabled); return new ArrayList<>(reusablePackets); } /** * ç¡®ä¿ç¼å²åºæè¶³å¤å®¹éï¼å¦ä¸å¤åå°è¯å缩 */ private boolean ensureBufferCapacity(int required) { if (bufferPosition + required <= dataBuffer.length) { return true; } // å°è¯éè¿å缩ç¼å²åºæ¥è ¾åºç©ºé´ int startIndex = findStartMarker(); if (startIndex > 0) { compactBuffer(startIndex); return bufferPosition + required <= dataBuffer.length; } return false; } /** * å¤çç¼å²åºä¸çæ°æ®ï¼è§£æå®æ´æ°æ®å */ private static void processBuffer(List<byte[]> completePackets, boolean debugEnabled) { final int MIN_PACKET_LENGTH = 9; final byte[] START_MARKER = {(byte) 0xDD, (byte) 0xCC}; while (staticBufferPosition >= MIN_PACKET_LENGTH) { private void processBuffer(List<byte[]> completePackets, boolean debugEnabled) { while (bufferPosition >= MIN_PACKET_LENGTH) { // æ¥æ¾èµ·å§æ è®° int startIndex = findStartMarker(START_MARKER); int startIndex = findStartMarker(); if (startIndex == -1) { // æ²¡ææ¾å°èµ·å§æ è®°ï¼æ¸ ç©ºæ ææ°æ® if (debugEnabled) { //System.out.println("æªæ¾å°èµ·å§æ è®°ï¼æ¸ 空ç¼å²åº"); System.out.println("æªæ¾å°èµ·å§æ è®°ï¼æ¸ 空ç¼å²åº"); } staticBufferPosition = 0; bufferPosition = 0; return; } // æ£æ¥æ¯å¦æè¶³å¤çæ°æ®è¯»åæ°æ®é¿åº¦ if (startIndex + 4 > staticBufferPosition) { if (startIndex + 4 > bufferPosition) { // æ°æ®ä¸è¶³ï¼çå¾ æ´å¤æ°æ® compactBuffer(startIndex); return; } // è¯»åæ°æ®é¿åº¦ (大端åº) int dataLength = ((staticDataBuffer[startIndex + 2] & 0xFF) << 8) | (staticDataBuffer[startIndex + 3] & 0xFF); int dataLength = ((dataBuffer[startIndex + 2] & 0xFF) << 8) | (dataBuffer[startIndex + 3] & 0xFF); int totalPacketLength = 2 + 2 + dataLength + 2; // èµ·å§æ è®°2 + æ°æ®é¿åº¦2 + æ°æ®å 容 + CRC2 // æ£æ¥æ°æ®é¿åº¦æææ§ if (dataLength < 0 || totalPacketLength > BUFFER_SIZE) { if (debugEnabled) { System.out.println("æ ææ°æ®é¿åº¦: " + dataLength + ", è·³è¿èµ·å§åè"); } // è·³è¿é误çèµ·å§æ è®°ï¼ç»§ç»æ¥æ¾ compactBuffer(startIndex + 1); continue; } // æ£æ¥æ¯å¦æ¶å°å®æ´æ°æ®å if (startIndex + totalPacketLength > staticBufferPosition) { if (startIndex + totalPacketLength > bufferPosition) { // æ°æ®å ä¸å®æ´ï¼çå¾ æ´å¤æ°æ® compactBuffer(startIndex); return; } // æå宿´æ°æ®å byte[] packet = new byte[totalPacketLength]; System.arraycopy(staticDataBuffer, startIndex, packet, 0, totalPacketLength); byte[] packet = Arrays.copyOfRange(dataBuffer, startIndex, startIndex + totalPacketLength); if (debugEnabled) { //System.out.println("è§£æå°å®æ´æ°æ®å : " + bytesToHex(packet)); System.out.println("è§£æå°å®æ´æ°æ®å : " + bytesToHex(packet)); } // æ·»å å°è¿åå表 completePackets.add(packet); // ç§»å¨ç¼å²åºä½ç½® int remaining = staticBufferPosition - (startIndex + totalPacketLength); int remaining = bufferPosition - (startIndex + totalPacketLength); if (remaining > 0) { System.arraycopy(staticDataBuffer, startIndex + totalPacketLength, staticDataBuffer, 0, remaining); System.arraycopy(dataBuffer, startIndex + totalPacketLength, dataBuffer, 0, remaining); } staticBufferPosition = remaining; bufferPosition = remaining; } } /** * æ¥æ¾èµ·å§æ è®°ä½ç½® */ private static int findStartMarker(byte[] startMarker) { for (int i = 0; i <= staticBufferPosition - startMarker.length; i++) { if (staticDataBuffer[i] == startMarker[0] && staticDataBuffer[i + 1] == startMarker[1]) { private int findStartMarker() { for (int i = 0; i <= bufferPosition - START_MARKER.length; i++) { if (dataBuffer[i] == START_MARKER[0] && dataBuffer[i + 1] == START_MARKER[1]) { return i; } } @@ -119,20 +150,20 @@ /** * å缩ç¼å²åºï¼å°æææ°æ®ç§»å°å¼å¤´ */ private static void compactBuffer(int startIndex) { if (startIndex > 0) { System.arraycopy(staticDataBuffer, startIndex, staticDataBuffer, 0, staticBufferPosition - startIndex); staticBufferPosition -= startIndex; private void compactBuffer(int startIndex) { if (startIndex > 0 && startIndex < bufferPosition) { System.arraycopy(dataBuffer, startIndex, dataBuffer, 0, bufferPosition - startIndex); bufferPosition -= startIndex; } } /** * æå°åå§æ°æ®ï¼è°è¯ç¨ï¼ */ private static void printRawData(String prefix, byte[] data, int maxPrintLength) { private void printRawData(String prefix, byte[] data, int maxPrintLength) { if (data == null || data.length == 0) { //System.out.println(prefix + ": ç©ºæ°æ®"); System.out.println(prefix + ": ç©ºæ°æ®"); return; } @@ -148,13 +179,13 @@ sb.append("... [æªæï¼æ»é¿åº¦: ").append(data.length).append("]"); } //System.out.println(sb.toString()); System.out.println(sb.toString()); } /** * å·¥å ·æ¹æ³ï¼åèæ°ç»è½¬åå è¿å¶å符串 */ private static String bytesToHex(byte[] bytes) { private String bytesToHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (byte b : bytes) { sb.append(String.format("%02X ", b)); @@ -165,16 +196,23 @@ /** * æ¸ ç©ºç¼å²åºï¼é¿å å åæ³æ¼ï¼ */ public static void clearBuffer() { staticBufferPosition = 0; public void clearBuffer() { bufferPosition = 0; // å¯éï¼æ¸ 空ç¼å²åºå 容 Arrays.fill(staticDataBuffer, (byte) 0); Arrays.fill(dataBuffer, (byte) 0); } /** * è·åå½åç¼å²åºç¶æ */ public static int getBufferStatus() { return staticBufferPosition; public int getBufferStatus() { return bufferPosition; } /** * è·åç¼å²åºå®¹é */ public int getBufferCapacity() { return dataBuffer.length; } } src/chuankou/SerialPortService.java
@@ -144,70 +144,83 @@ * å¯å¨æ°æ®æ¥æ¶çº¿ç¨ */ public void startCapture(Consumer<byte[]> onReceived) { this.dataReceivedCallback = onReceived; if (capturing || port == null || !port.isOpen()) return; capturing = true; paused = false; this.dataReceivedCallback = onReceived; if (capturing || port == null || !port.isOpen()) return; capturing = true; paused = false; readerThread = new Thread(() -> { buffer.reset(); long lastReceivedTime = 0; readerThread = new Thread(() -> { buffer.reset(); long lastReceivedTime = 0; while (capturing && port.isOpen()) { long currentTime = System.currentTimeMillis(); while (capturing && port.isOpen()) { long currentTime = System.currentTimeMillis(); if (buffer.size() > 0 && (currentTime - lastReceivedTime) >= 20) { byte[] data = buffer.toByteArray(); SystemDebugDialog.appendHexData(data); if (buffer.size() > 0 && (currentTime - lastReceivedTime) >= 20) { byte[] data = buffer.toByteArray(); SystemDebugDialog.appendHexData(data); // æ°å¢ï¼å°æ°æ®ä¼ éç»å议解æå¨ if (protocolParser != null) { protocolParser.receiveData(data); } // æ°å¢ï¼å°æ°æ®ä¼ éç»å议解æå¨ - ç¡®ä¿å§ç»æ§è¡ if (protocolParser != null) { protocolParser.receiveData(data); } if (!paused) { onReceived.accept(data); if (responseConsumer != null) { responseConsumer.accept(data); } } buffer.reset(); } // ç¡®ä¿æ°æ®åè°å§ç»æ§è¡ï¼ä¸åæåç¶æå½±å if (dataReceivedCallback != null && !paused) { dataReceivedCallback.accept(data); } if (responseConsumer != null && !paused) { responseConsumer.accept(data); } buffer.reset(); } int len = port.readBytes(readBuffer, readBuffer.length); currentTime = System.currentTimeMillis(); int len = port.readBytes(readBuffer, readBuffer.length); currentTime = System.currentTimeMillis(); if (len > 0) { buffer.write(readBuffer, 0, len); lastReceivedTime = currentTime; } if (len > 0) { buffer.write(readBuffer, 0, len); lastReceivedTime = currentTime; } if (len <= 0 && buffer.size() == 0) { try { Thread.sleep(1); } catch (InterruptedException ignore) {} } } if (len <= 0 && buffer.size() == 0) { try { Thread.sleep(1); } catch (InterruptedException ignore) {} } } if (buffer.size() > 0) { byte[] data = buffer.toByteArray(); SystemDebugDialog.appendHexData(data); if (buffer.size() > 0) { byte[] data = buffer.toByteArray(); SystemDebugDialog.appendHexData(data); // æ°å¢ï¼å°æ°æ®ä¼ éç»å议解æå¨ if (protocolParser != null) { protocolParser.receiveData(data); } // æ°å¢ï¼å°æ°æ®ä¼ éç»å议解æå¨ - ç¡®ä¿å§ç»æ§è¡ if (protocolParser != null) { protocolParser.receiveData(data); } if (!paused) { onReceived.accept(data); if (responseConsumer != null) { responseConsumer.accept(data); } } } }); readerThread.setDaemon(true); readerThread.start(); // ç¡®ä¿æ°æ®åè°å§ç»æ§è¡ï¼ä¸åæåç¶æå½±å if (dataReceivedCallback != null && !paused) { dataReceivedCallback.accept(data); } if (responseConsumer != null && !paused) { responseConsumer.accept(data); } } }); readerThread.setDaemon(true); readerThread.start(); } // æ°å¢ï¼è®¾ç½®æåç¶æä½ä¸å½±åå议解æå¨ public void setPaused(boolean paused) { this.paused = paused; // 注æï¼ä¸åæ¢å议解æå¨ï¼åªæåUIåè° } // æ°å¢ï¼åç¬åæ¢æ°æ®æè·èä¸å½±åå议解æå¨ public void stopDataCaptureOnly() { // åªåæ¢æ°æ®åè°ï¼ä¸å½±åå议解æå¨ this.dataReceivedCallback = null; this.responseConsumer = null; } /** * åæ¢æ°æ®æ¥æ¶çº¿ç¨ */ @@ -219,9 +232,6 @@ } } public void setPaused(boolean paused) { this.paused = paused; } public boolean isPaused() { return paused; src/chushihua/Chushihua.java
@@ -2,6 +2,9 @@ import java.io.File; import java.util.List; import dialog.Dingshidialog; import dialog.Errlog; import home.MachineConfig; /** @@ -66,7 +69,7 @@ return true; } catch (Exception e) { System.err.println("ç³»ç»åå§åå¼å¸¸: " + e.getMessage()); Errlog.logOperation("ç³»ç»åå§åå¼å¸¸: " + e.getMessage()); e.printStackTrace(); return false; } @@ -83,7 +86,7 @@ ////System.out.println("ç³»ç»å ³éï¼è½®è¯¢æ¥è¯¢å·²åæ¢"); } } catch (Exception e) { System.err.println("ç³»ç»å ³éå¼å¸¸: " + e.getMessage()); Errlog.logOperation("ç³»ç»å ³éå¼å¸¸: " + e.getMessage()); } } @@ -96,7 +99,7 @@ // æ£æ¥é ç½®æä»¶æ¯å¦åå¨ File configFile = new File(configFilePath); if (!configFile.exists()) { System.err.println("é ç½®æä»¶ä¸åå¨: " + configFilePath); Errlog.logOperation("é ç½®æä»¶ä¸åå¨: " + configFilePath); return false; } @@ -119,7 +122,7 @@ return true; } catch (Exception e) { System.err.println("ç³»ç»åå§å失败: " + e.getMessage()); Errlog.logOperation("ç³»ç»åå§å失败: " + e.getMessage()); e.printStackTrace(); return false; } @@ -176,7 +179,7 @@ */ public boolean saveConfig(String configFilePath) { if (machineConfig == null) { System.err.println("é ç½®æªå è½½ï¼æ æ³ä¿å"); Errlog.logOperation("é ç½®æªå è½½ï¼æ æ³ä¿å"); return false; } @@ -185,7 +188,7 @@ ////System.out.println("é 置已ä¿åå°: " + configFilePath); return true; } catch (Exception e) { System.err.println("ä¿åé 置失败: " + e.getMessage()); Errlog.logOperation("ä¿åé 置失败: " + e.getMessage()); return false; } } @@ -195,7 +198,7 @@ */ public MachineConfig getMachineConfig() { if (!initialized) { throw new IllegalStateException("ç³»ç»æªåå§åï¼è¯·å è°ç¨initialize()æ¹æ³"); Dingshidialog.showTimedDialog(null,10,"ç³»ç»æªåå§åæå"); } return machineConfig; } src/chushihua/SlotManager.java
@@ -5,7 +5,8 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import xitongshezhi.Fkj; import dialog.Dingshidialog; import home.Fkj; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -318,6 +319,7 @@ /** * æ ¹æ®ç¶æç åæ éç 夿æ¯å¦æå¡ - ä¼åçæ¬ */ @SuppressWarnings("unused") private String determineHasCardFromStatus(int status, int fault) { // ä¼åï¼ä½¿ç¨æ°å¼æ¯è¾æ¿ä»£å符串æä½ if (fault != 0) { @@ -521,11 +523,10 @@ if ("0000".equals(oldCardNumber) && !"0000".equals(newCardNumber)) { // å¨äºä»¶åå线ç¨ä¸æ¾ç¤ºå¯¹è¯æ¡ javax.swing.SwingUtilities.invokeLater(() -> { xitongshezhi.Dingshidialog.showTimedDialog( Dingshidialog.showTimedDialog( null, // ç¶çªå£ï¼å¯ä»¥ä¸ºnull 5, // æ¾ç¤º3ç§ "è¿å¡æåï¼æè°¢æ¨ç使ç¨", "" // é³é¢æä»¶ï¼å¯ä»¥ä¸ºç©º slotNumber+"å·å¡æ§½è¿å¡æåæè°¢æ¨ç使ç¨" ); }); //System.out.println("塿§½ " + slotNumber + " è¿å¡æåï¼å¡å·ä» " + oldCardNumber + " å为 " + newCardNumber); @@ -538,7 +539,7 @@ * @param caozuo æä½ç±»åï¼1表示管çåï¼0è¡¨ç¤ºç³»ç» * @return ä¿®æ¹æåè¿åtrueï¼å¦åè¿åfalse */ public static boolean changgehaska(int slotNumber, String caozuo) { public static boolean changgehaska(int slotNumber, int caozuo) { if (!isValidSlotNumber(slotNumber)) { return false; } @@ -548,9 +549,9 @@ slot.setUpdateTime(getCurrentTime()); // è®°å½å塿¥å¿ String operator = "1".equals(caozuo) ? "管çå" : "ç³»ç»"; String operator =caozuo==1? "管çå" : "ç³»ç»"; String logMessage = String.format("å塿ä½ï¼å¡æ§½%d被%såå¡", slotNumber, operator); xitongshezhi.Charulog.logOperation(logMessage); dialog.Charulog.logOperation(logMessage); return true; } src/chushihua/lunxun.java
@@ -1,11 +1,13 @@ package chushihua; import chuankou.Sendmsg; import dialog.Errlog; import home.Fkj; import home.MachineConfig; import publicway.QueryData; import xitongshezhi.Fkj; import xitongshezhi.SystemDebugDialog; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -14,637 +16,785 @@ * 轮询æ¥è¯¢ç±» - ä¼åçæ¬ * ç¨äºå®æ¶åææå¡æ§½åéæ¥è¯¢æä»¤ * æ¯ææå忢å¤åè½ï¼æ£æ¥ä¸²å£è¿æ¥ç¶æ * æ°å¢ï¼ä¸å塿§½ç¶æä½¿ç¨ä¸åæ¥è¯¢é¢ç * ä¼åï¼å å管çåé¿æ¶é´è¿è¡ç¨³å®æ§ */ public class lunxun { private static volatile boolean isRunning = false; private static volatile boolean isPaused = false; private static final AtomicBoolean shouldStop = new AtomicBoolean(false); private static Thread pollingThread; private static int pollingInterval = 100; // é»è®¤è½®è¯¢é´é // 塿§½ç¸å ³å¸¸é private static final int MIN_SLOT = 1; private static final int MAX_SLOT = 60; // 串å£è¿æ¥æ£æ¥ç¸å ³ private static final int SERIAL_CHECK_INTERVAL = 5000; // 5ç§æ£æ¥ä¸æ¬¡ä¸²å£è¿æ¥ private static long lastSerialCheckTime = 0; private static boolean serialConnected = false; // æ§è½ä¼åï¼æ¥è¯¢æä»¤ç¼å private static final Map<Integer, String> queryCommandCache = new ConcurrentHashMap<>(); // è°è¯æ¨¡å¼æ§å¶ public static boolean DEBUG_ENABLED = false; /** * æ£æ¥ä¸²å£è¿æ¥ç¶æ - ä¼åçæ¬ï¼æ·»å éè¯æºå¶ * @return true-串å£å·²è¿æ¥, false-䏲壿ªè¿æ¥ */ public static boolean checkSerialConnection() { // é¿å é¢ç¹æ£æ¥ï¼æ¯5ç§æ£æ¥ä¸æ¬¡ long currentTime = System.currentTimeMillis(); if (currentTime - lastSerialCheckTime < SERIAL_CHECK_INTERVAL) { return serialConnected; } lastSerialCheckTime = currentTime; try { // ç®åæ£æ¥ï¼ç´æ¥æ£æ¥Sendmsgç串å£ç¶æï¼è䏿¯åéæµè¯æä»¤ boolean result = Sendmsg.isPortOpen(); if (result) { if (DEBUG_ENABLED) { //System.out.println("串å£è¿æ¥æ£å¸¸"); } serialConnected = true; } else { System.err.println("串å£è¿æ¥å¤±è´¥ - 䏲壿ªæå¼"); serialConnected = false; } } catch (Exception e) { System.err.println("串å£è¿æ¥æ£æ¥å¼å¸¸: " + e.getMessage()); serialConnected = false; } return serialConnected; } /** * 带éè¯ç串å£è¿æ¥æ£æ¥ */ private static boolean checkSerialConnectionWithRetry() { for (int i = 0; i < 3; i++) { if (checkSerialConnection()) { return true; } try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; } /** * å¯å¨è½®è¯¢æ¥è¯¢ - ä¼åçæ¬ * @return true-å¯å¨æå, false-å¯å¨å¤±è´¥ */ public static boolean startPolling() { if (isRunning) { //System.out.println("轮询æ¥è¯¢å·²ç»å¨è¿è¡ä¸"); return true; } // å¯å¨åä¸¥æ ¼æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { System.err.println("䏲壿ªè¿æ¥ï¼æ æ³å¯å¨è½®è¯¢æ¥è¯¢"); return false; } // ä»é ç½®ä¸è·å轮询é´é loadPollingIntervalFromConfig(); isRunning = true; isPaused = false; shouldStop.set(false); try { pollingThread = new Thread(new PollingTask(), "CardSlot-Polling-Thread"); pollingThread.setDaemon(true); pollingThread.start(); return true; } catch (Exception e) { System.err.println("å¯å¨è½®è¯¢æ¥è¯¢çº¿ç¨æ¶åçå¼å¸¸: " + e.getMessage()); isRunning = false; shouldStop.set(true); return false; } } /** * åæ¢è½®è¯¢æ¥è¯¢ - ä¿®å¤çæ¬ * @return true-忢æå, false-åæ¢å¤±è´¥ */ public static boolean stopPolling() { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡"); return false; } shouldStop.set(true); isRunning = false; isPaused = false; if (pollingThread != null) { pollingThread.interrupt(); try { pollingThread.join(3000); // çå¾ 3ç§ // æ£æ¥çº¿ç¨æ¯å¦è¿å¨è¿è¡ if (pollingThread.isAlive()) { System.err.println("è½®è¯¢çº¿ç¨æªå¨3ç§å åæ¢ï¼æ è®°ä¸ºå®æ¤çº¿ç¨å¹¶å¿½ç¥"); // ä¸å¼ºå¶åæ¢ï¼èæ¯ç¡®ä¿å®æ¯å®æ¤çº¿ç¨ pollingThread.setDaemon(true); } } catch (InterruptedException e) { System.err.println("åæ¢è½®è¯¢æ¥è¯¢æ¶è¢«ä¸æ: " + e.getMessage()); Thread.currentThread().interrupt(); } catch (Exception e) { System.err.println("åæ¢è½®è¯¢çº¿ç¨æ¶åçå¼å¸¸: " + e.getMessage()); } finally { pollingThread = null; } } shouldStop.set(false); //System.out.println("轮询æ¥è¯¢å·²åæ¢"); return true; } /** * æå轮询æ¥è¯¢ * @return true-æåæå, false-æå失败 */ public static boolean pausePolling() { if (!isRunning) { if (DEBUG_ENABLED) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³æå"); } return false; } if (isPaused) { if (DEBUG_ENABLED) { //System.out.println("轮询æ¥è¯¢å·²ç»å¤äºæåç¶æ"); } return false; } isPaused = true; //System.out.println("轮询æ¥è¯¢å·²æå"); return true; } /** * æ¢å¤è½®è¯¢æ¥è¯¢ * @return true-æ¢å¤æå, false-æ¢å¤å¤±è´¥ */ public static boolean resumePolling() { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³æ¢å¤"); return false; } if (!isPaused) { //System.out.println("轮询æ¥è¯¢æªå¤äºæåç¶æ"); return false; } // æ¢å¤åæ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { System.err.println("䏲壿ªè¿æ¥ï¼æ æ³æ¢å¤è½®è¯¢æ¥è¯¢"); return false; } isPaused = false; synchronized (lunxun.class) { lunxun.class.notifyAll(); // å¤éçå¾ ççº¿ç¨ } //System.out.println("轮询æ¥è¯¢å·²æ¢å¤"); return true; } /** * æ£æ¥è½®è¯¢ç¶æ * @return true-æ£å¨è¿è¡, false-已忢 */ public static boolean isPolling() { return isRunning; } /** * æ£æ¥æ¯å¦æå * @return true-å·²æå, false-æªæå */ public static boolean isPaused() { return isPaused; } /** * æ£æ¥ä¸²å£è¿æ¥ç¶æ * @return true-串å£å·²è¿æ¥, false-䏲壿ªè¿æ¥ */ public static boolean isSerialConnected() { return serialConnected; } /** * 设置轮询é´é * @param interval 轮询é´éï¼æ¯«ç§ï¼ */ public static void setPollingInterval(int interval) { if (interval < 10) { System.err.println("轮询é´éä¸è½å°äº10ms"); return; } pollingInterval = interval; //System.out.println("轮询é´é已设置为: " + interval + "ms"); // 妿æ£å¨è¿è¡ï¼éæ°å¯å¨ä»¥åºç¨æ°çé´é if (isRunning) { restartPolling(); } } /** * è·åå½å轮询é´é * @return 轮询é´éï¼æ¯«ç§ï¼ */ public static int getPollingInterval() { return pollingInterval; } /** * éæ°å¯å¨è½®è¯¢æ¥è¯¢ * @return true-é坿å, false-éå¯å¤±è´¥ */ public static boolean restartPolling() { stopPolling(); // çå¾ ä¸å°æ®µæ¶é´ç¡®ä¿çº¿ç¨å®å ¨åæ¢ try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return startPolling(); } /** * ä»é ç½®ä¸å 载轮询é´é */ private static void loadPollingIntervalFromConfig() { try { Chushihua configSystem = Chushihua.getInstance(); if (configSystem.isInitialized()) { MachineConfig machineConfig = configSystem.getMachineConfig(); pollingInterval = machineConfig.getPollingInterval(); //System.out.println("ä»é ç½®å 载轮询é´é: " + pollingInterval + "ms"); } else { //System.out.println("é ç½®ç³»ç»æªåå§åï¼ä½¿ç¨é»è®¤è½®è¯¢é´é: " + pollingInterval + "ms"); } } catch (Exception e) { System.err.println("å 载轮询é´éé 置失败: " + e.getMessage()); //System.out.println("使ç¨é»è®¤è½®è¯¢é´é: " + pollingInterval + "ms"); } } /** * è·åç¼åçæ¥è¯¢æä»¤ */ private static String getCachedQueryCommand(int slotNumber) { return queryCommandCache.computeIfAbsent(slotNumber, QueryData::queryData); } /** * æ¸ ç©ºæ¥è¯¢æä»¤ç¼åï¼å½æ¥è¯¢é»è¾ååæ¶è°ç¨ï¼ */ public static void clearQueryCache() { queryCommandCache.clear(); //System.out.println("æ¥è¯¢æä»¤ç¼åå·²æ¸ ç©º"); } /** * 轮询任å¡å é¨ç±» - ä¼åçæ¬ * ä¼åå å使ç¨ï¼é¿å å¨å¾ªç¯ä¸å建æ°å¯¹è±¡ * æ·»å æ¹éå¤çåæ§è½çæ§ */ private static class PollingTask implements Runnable { private int currentIndex = 0; // å½åç´¢å¼ï¼ç¨äºéåslotArray private int consecutiveFailures = 0; // è¿ç»å¤±è´¥æ¬¡æ° private static final int MAX_CONSECUTIVE_FAILURES = 5; // æå¤§è¿ç»å¤±è´¥æ¬¡æ° @Override public void run() { //System.out.println("轮询æ¥è¯¢çº¿ç¨å¼å§è¿è¡"); while (isRunning && !Thread.currentThread().isInterrupted() && !shouldStop.get()) { try { // æ£æ¥æ¯å¦æå if (isPaused) { synchronized (lunxun.class) { while (isPaused && isRunning && !shouldStop.get()) { lunxun.class.wait(1000); // çå¾ 1ç§æç´å°è¢«å¤é } } continue; } // å®ææ£æ¥ä¸²å£è¿æ¥ç¶æï¼æ¯10æ¬¡å¾ªç¯æ£æ¥ä¸æ¬¡ï¼ if (currentIndex % 10 == 0 && !checkSerialConnectionWithRetry()) { System.err.println("串å£è¿æ¥æå¼ï¼æå轮询"); pausePolling(); continue; } // è·å塿§½æ°ç» Fkj[] slotArray = SlotManager.getSlotArray(); if (slotArray == null || slotArray.length == 0) { System.err.println("塿§½æ°ç»æªåå§å"); Thread.sleep(pollingInterval); continue; } // é忿塿§½ï¼åªç» hasCard != 1 ç塿§½åéæ¥è¯¢æä»¤ boolean sentQuery = false; int checkedSlots = 0; int maxSlotsPerCycle = Math.min(10, slotArray.length); // æ¯å¨ææå¤æ£æ¥10ä¸ªå¡æ§½ for (int i = 0; i < maxSlotsPerCycle && checkedSlots < slotArray.length; i++) { Fkj slot = slotArray[currentIndex]; if (slot != null) { String hasCard = slot.getHasCard(); if (!"1".equals(hasCard)) { int slotNumber = currentIndex + 1; if (sendQueryToSlot(slotNumber)) { sentQuery = true; consecutiveFailures = 0; // å ³é®ä¿®å¤ï¼å¨breakåå æ´æ°ç´¢å¼ currentIndex = (currentIndex + 1) % slotArray.length; checkedSlots++; Thread.sleep(pollingInterval); break; } else { consecutiveFailures++; if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) { System.err.println("lunxunè¿ç»å¤±è´¥æ¬¡æ°è¿å¤ï¼æå轮询"); pausePolling(); break; } } } } // 对äºä¸éè¦åéæ¥è¯¢ç塿§½ï¼æ£å¸¸æ´æ°ç´¢å¼ currentIndex = (currentIndex + 1) % slotArray.length; checkedSlots++; } // å¦ææ²¡ææ¾å°éè¦æ¥è¯¢ç塿§½ï¼çå¾ ä¸æ®µæ¶é´åç»§ç» if (!sentQuery) { Thread.sleep(pollingInterval * 2); // æ²¡ææ¥è¯¢æ¶çå¾ æ¶é´å å } } catch (InterruptedException e) { //System.out.println("轮询æ¥è¯¢çº¿ç¨è¢«ä¸æ"); Thread.currentThread().interrupt(); break; } catch (Exception e) { System.err.println("轮询æ¥è¯¢è¿ç¨ä¸åçå¼å¸¸: " + e.getMessage()); consecutiveFailures++; // åçå¼å¸¸æ¶çå¾ ä¸æ®µæ¶é´åç»§ç» try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } //System.out.println("轮询æ¥è¯¢çº¿ç¨ç»æè¿è¡"); } /** * åæå®å¡æ§½åéæ¥è¯¢æä»¤ - ä¼åçæ¬ * 使ç¨ç¼åæä»¤ï¼ä¼åè°è¯è¾åº */ private boolean sendQueryToSlot(int slotNumber) { try { // 使ç¨ç¼åçæ¥è¯¢æä»¤ String queryCommand = getCachedQueryCommand(slotNumber); if (queryCommand != null && !queryCommand.trim().isEmpty()) { // åéå°ä¸²å£ boolean sendResult = Sendmsg.sendMessage(queryCommand); if (sendResult) { // åªå¨è°è¯æ¶è¾åºï¼é¿å é¢ç¹æå° if (DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData(String.format("Slot %d Send query (hasCard !=1)\n", slotNumber)); } return true; } else { if (DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("Send query command to card slot err"); } // åé失败å¯è½æ¯ä¸²å£æå¼ï¼æ´æ°è¿æ¥ç¶æ serialConnected = false; return false; } } else { System.err.println("çæçæ¥è¯¢æä»¤ä¸ºç©ºï¼å¡æ§½: " + slotNumber); return false; } } catch (Exception e) { System.err.println("åéæ¥è¯¢æä»¤å°å¡æ§½ " + slotNumber + " æ¶åçå¼å¸¸: " + e.getMessage()); // åçå¼å¸¸æ¶æ´æ°ä¸²å£è¿æ¥ç¶æ serialConnected = false; return false; } } } /** * ç«å³åæå®å¡æ§½åéæ¥è¯¢æä»¤ï¼ä¸çå¾ è½®è¯¢ï¼ * @param slotNumber 塿§½ç¼å· (1-60) * @return true-åéæå, false-åé失败 */ public static boolean sendImmediateQuery(int slotNumber) { if (slotNumber < MIN_SLOT || slotNumber > MAX_SLOT) { System.err.println("塿§½ç¼å·å¿ é¡»å¨" + MIN_SLOT + "-" + MAX_SLOT + "ä¹é´"); return false; } // æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { System.err.println("䏲壿ªè¿æ¥ï¼æ æ³åéæ¥è¯¢æä»¤"); return false; } try { // 使ç¨ç¼åçæ¥è¯¢æä»¤ String queryCommand = getCachedQueryCommand(slotNumber); if (queryCommand != null && !queryCommand.trim().isEmpty()) { // åéå°ä¸²å£ boolean sendResult = Sendmsg.sendMessage(queryCommand); if (sendResult) { if (DEBUG_ENABLED) { //System.out.println("ç«å³æ¥è¯¢æå - 塿§½ " + slotNumber); } return true; } else { System.err.println("ç«å³æ¥è¯¢å¤±è´¥ - åéæä»¤å°å¡æ§½ " + slotNumber + " 失败"); return false; } } else { System.err.println("ç«å³æ¥è¯¢å¤±è´¥ - çæçæ¥è¯¢æä»¤ä¸ºç©ºï¼å¡æ§½: " + slotNumber); return false; } } catch (Exception e) { System.err.println("ç«å³æ¥è¯¢å¡æ§½ " + slotNumber + " æ¶åçå¼å¸¸: " + e.getMessage()); return false; } } /** * ç«å³åææå¡æ§½åéæ¥è¯¢æä»¤ï¼æ¹éï¼- ä¼åçæ¬ * @return æååéçæä»¤æ°é */ public static int sendImmediateQueryToAll() { // æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { System.err.println("䏲壿ªè¿æ¥ï¼æ æ³åéæ¹éæ¥è¯¢æä»¤"); return 0; } int successCount = 0; int batchSize = 5; // æ¯æ¹æ¬¡åé5个æ¥è¯¢ int totalSlots = MAX_SLOT - MIN_SLOT + 1; //System.out.println("å¼å§æ¹éæ¥è¯¢ææå¡æ§½..."); for (int batchStart = MIN_SLOT; batchStart <= MAX_SLOT; batchStart += batchSize) { if (shouldStop.get()) { break; } int batchEnd = Math.min(batchStart + batchSize - 1, MAX_SLOT); // æ¹æ¬¡å æ¥è¯¢ for (int slot = batchStart; slot <= batchEnd; slot++) { if (sendImmediateQuery(slot)) { successCount++; } } // æ¹æ¬¡é´é´éï¼é¿å 䏲壿¥å µ if (batchEnd < MAX_SLOT) { try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } //System.out.println("æ¹éæ¥è¯¢å®æï¼æååé: " + successCount + "/" + totalSlots); return successCount; } /** * æå¨è®¾ç½®ä¸²å£è¿æ¥ç¶æï¼ç¨äºå¤é¨æ£æµå°ä¸²å£ç¶æååæ¶è°ç¨ï¼ * @param connected 串å£è¿æ¥ç¶æ */ public static void setSerialConnected(boolean connected) { serialConnected = connected; lastSerialCheckTime = System.currentTimeMillis(); if (connected) { // //System.out.println("串å£è¿æ¥ç¶æå·²è®¾ç½®ä¸º: å·²è¿æ¥"); } else { System.err.println("串å£è¿æ¥ç¶æå·²è®¾ç½®ä¸º: æªè¿æ¥"); // 妿䏲壿å¼ä¸è½®è¯¢æ£å¨è¿è¡ï¼èªå¨æå轮询 if (isRunning && !isPaused) { pausePolling(); } } } /** * è·åè½®è¯¢ç¶æä¿¡æ¯ * @return ç¶æä¿¡æ¯å符串 */ public static String getPollingStatus() { String status; if (!isRunning) { status = "已忢"; } else if (isPaused) { status = "å·²æå"; } else { status = "è¿è¡ä¸"; } String serialStatus = serialConnected ? "å·²è¿æ¥" : "æªè¿æ¥"; int cacheSize = queryCommandCache.size(); return String.format("è½®è¯¢ç¶æ: %s, 串å£: %s, é´é: %dms, æä»¤ç¼å: %d, 塿§½èå´: %d-%d", status, serialStatus, pollingInterval, cacheSize, MIN_SLOT, MAX_SLOT); } /** * ç´æ¥è®¾ç½®è½®è¯¢æåç¶æï¼ä¾å ¶ä»ç±»è°ç¨ï¼ * @param paused true-æå轮询, false-æ¢å¤è½®è¯¢ * @return true-设置æå, false-设置失败ï¼å¦è½®è¯¢æªè¿è¡ï¼ */ public static boolean setPollingPaused(boolean paused) { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³è®¾ç½®æåç¶æ"); return false; } if (paused) { // è¯·æ±æå if (!isPaused) { isPaused = true; //System.out.println("轮询æ¥è¯¢å·²éè¿å¤é¨è°ç¨æå"); return true; } else { //System.out.println("轮询æ¥è¯¢å·²ç»å¤äºæåç¶æ"); return false; } } else { // è¯·æ±æ¢å¤ if (isPaused) { // æ¢å¤åæ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { System.err.println("䏲壿ªè¿æ¥ï¼æ æ³æ¢å¤è½®è¯¢æ¥è¯¢"); return false; } isPaused = false; synchronized (lunxun.class) { lunxun.class.notifyAll(); // å¤éçå¾ ççº¿ç¨ } //System.out.println("轮询æ¥è¯¢å·²éè¿å¤é¨è°ç¨æ¢å¤"); return true; } else { //System.out.println("轮询æ¥è¯¢æªå¤äºæåç¶æ"); return false; } } } /** * è·åæ§è½ç»è®¡ä¿¡æ¯ */ public static String getPerformanceStats() { return String.format("æ¥è¯¢æä»¤ç¼å大å°: %d, 轮询é´é: %dms", queryCommandCache.size(), pollingInterval); } private static volatile boolean isRunning = false; private static volatile boolean isPaused = false; private static final AtomicBoolean shouldStop = new AtomicBoolean(false); private static Thread pollingThread; private static int pollingInterval = 100; // é»è®¤è½®è¯¢é´é public static boolean sendChaxunzhiling=true;//æ¯å¦å串å£åéæ¥è¯¢æä»¤ // 塿§½ç¸å ³å¸¸é private static final int MIN_SLOT = 1; private static final int MAX_SLOT = 60; // 串å£è¿æ¥æ£æ¥ç¸å ³ private static final int SERIAL_CHECK_INTERVAL = 5000; // 5ç§æ£æ¥ä¸æ¬¡ä¸²å£è¿æ¥ private static long lastSerialCheckTime = 0; private static boolean serialConnected = false; // æ§è½ä¼åï¼æ¥è¯¢æä»¤ç¼å private static final Map<Integer, String> queryCommandCache = new ConcurrentHashMap<>(); // å åä¼åï¼ç¼å大å°éå¶åæ¸ çæºå¶ private static final int MAX_CACHE_SIZE = 100; private static final long CACHE_CLEANUP_INTERVAL = 60000; // 1å鿏 ç䏿¬¡ private static long lastCleanupTime = 0; // é误æ¥å¿éæµæºå¶ private static final Map<String, Long> lastErrorLogTime = new ConcurrentHashMap<>(); private static final long ERROR_LOG_INTERVAL = 5000; // ç¸åé误5ç§å åªè®°å½ä¸æ¬¡ // è°è¯æ¨¡å¼æ§å¶ public static boolean DEBUG_ENABLED = false; // æ°å¢ï¼ä¸åç¶æå¡æ§½çæ¥è¯¢é¢çæ§å¶ private static final int NO_CARD_QUERY_INTERVAL = 100; // æ å¡å¡æ§½æ¥è¯¢é´éï¼100ms private static final int HAS_CARD_QUERY_INTERVAL = 10000; // æå¡å¡æ§½æ¥è¯¢é´éï¼10ç§ private static final Map<Integer, Long> lastQueryTimeMap = new ConcurrentHashMap<>(); // è®°å½æ¯ä¸ªå¡æ§½çæåæ¥è¯¢æ¶é´ public static boolean isSendChaxunzhiling() { return sendChaxunzhiling; } public static void setSendChaxunzhiling(boolean sendChaxunzhiling) { lunxun.sendChaxunzhiling = sendChaxunzhiling; } /** * æ£æ¥ä¸²å£è¿æ¥ç¶æ - ä¼åçæ¬ï¼æ·»å éè¯æºå¶ * @return true-串å£å·²è¿æ¥, false-䏲壿ªè¿æ¥ */ public static boolean checkSerialConnection() { // é¿å é¢ç¹æ£æ¥ï¼æ¯5ç§æ£æ¥ä¸æ¬¡ long currentTime = System.currentTimeMillis(); if (currentTime - lastSerialCheckTime < SERIAL_CHECK_INTERVAL) { return serialConnected; } lastSerialCheckTime = currentTime; try { // ç®åæ£æ¥ï¼ç´æ¥æ£æ¥Sendmsgç串å£ç¶æï¼è䏿¯åéæµè¯æä»¤ boolean result = Sendmsg.isPortOpen(); if (result) { if (DEBUG_ENABLED) { //System.out.println("串å£è¿æ¥æ£å¸¸"); } serialConnected = true; } else { logErrorWithRateLimit("serial_connection_failed", "串å£è¿æ¥å¤±è´¥ - 䏲壿ªæå¼"); serialConnected = false; } } catch (Exception e) { logErrorWithRateLimit("serial_connection_exception", "串å£è¿æ¥æ£æ¥å¼å¸¸: " + e.getMessage()); serialConnected = false; } return serialConnected; } /** * 带éè¯ç串å£è¿æ¥æ£æ¥ */ private static boolean checkSerialConnectionWithRetry() { for (int i = 0; i < 3; i++) { if (checkSerialConnection()) { return true; } try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return false; } } return false; } /** * å¯å¨è½®è¯¢æ¥è¯¢ - ä¼åçæ¬ * @return true-å¯å¨æå, false-å¯å¨å¤±è´¥ */ public static boolean startPolling() { if (isRunning) { //System.out.println("轮询æ¥è¯¢å·²ç»å¨è¿è¡ä¸"); return true; } // å¯å¨åä¸¥æ ¼æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { logErrorWithRateLimit("start_polling_serial_failed", "䏲壿ªè¿æ¥ï¼æ æ³å¯å¨è½®è¯¢æ¥è¯¢"); return false; } // å¯å¨åå æ¸ ç䏿¬¡å å performCleanup(); // ä»é ç½®ä¸è·å轮询é´é loadPollingIntervalFromConfig(); // åå§åæåæ¥è¯¢æ¶é´è®°å½ initializeLastQueryTimes(); isRunning = true; isPaused = false; shouldStop.set(false); try { pollingThread = new Thread(new PollingTask(), "CardSlot-Polling-Thread"); pollingThread.setDaemon(true); pollingThread.start(); return true; } catch (Exception e) { logErrorWithRateLimit("start_polling_thread_exception", "å¯å¨è½®è¯¢æ¥è¯¢çº¿ç¨æ¶åçå¼å¸¸: " + e.getMessage()); isRunning = false; shouldStop.set(true); return false; } } /** * åå§åæåæ¥è¯¢æ¶é´è®°å½ */ private static void initializeLastQueryTimes() { lastQueryTimeMap.clear(); for (int i = MIN_SLOT; i <= MAX_SLOT; i++) { lastQueryTimeMap.put(i, 0L); // åå§å为0ï¼è¡¨ç¤ºä»æªæ¥è¯¢è¿ } } /** * åæ¢è½®è¯¢æ¥è¯¢ - ä¿®å¤çæ¬ * @return true-忢æå, false-åæ¢å¤±è´¥ */ public static boolean stopPolling() { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡"); return false; } shouldStop.set(true); isRunning = false; isPaused = false; if (pollingThread != null) { pollingThread.interrupt(); try { pollingThread.join(3000); // çå¾ 3ç§ // æ£æ¥çº¿ç¨æ¯å¦è¿å¨è¿è¡ if (pollingThread.isAlive()) { logErrorWithRateLimit("polling_thread_stop_timeout", "è½®è¯¢çº¿ç¨æªå¨3ç§å åæ¢ï¼æ è®°ä¸ºå®æ¤çº¿ç¨å¹¶å¿½ç¥"); // ä¸å¼ºå¶åæ¢ï¼èæ¯ç¡®ä¿å®æ¯å®æ¤çº¿ç¨ pollingThread.setDaemon(true); } } catch (InterruptedException e) { logErrorWithRateLimit("stop_polling_interrupted", "åæ¢è½®è¯¢æ¥è¯¢æ¶è¢«ä¸æ: " + e.getMessage()); Thread.currentThread().interrupt(); } catch (Exception e) { logErrorWithRateLimit("stop_polling_exception", "åæ¢è½®è¯¢çº¿ç¨æ¶åçå¼å¸¸: " + e.getMessage()); } finally { pollingThread = null; } } shouldStop.set(false); //System.out.println("轮询æ¥è¯¢å·²åæ¢ - 䏲壿°æ®æ¥æ¶ä¸åå½±å"); return true; } /** * æå轮询æ¥è¯¢ * @return true-æåæå, false-æå失败 */ public static boolean pausePolling() { if (!isRunning) { if (DEBUG_ENABLED) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³æå"); } return false; } if (isPaused) { if (DEBUG_ENABLED) { //System.out.println("轮询æ¥è¯¢å·²ç»å¤äºæåç¶æ"); } return false; } isPaused = true; //System.out.println("轮询æ¥è¯¢å·²æå - ä» åæ¢åéæ¥è¯¢æä»¤"); return true; } /** * æ¢å¤è½®è¯¢æ¥è¯¢ * @return true-æ¢å¤æå, false-æ¢å¤å¤±è´¥ */ public static boolean resumePolling() { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³æ¢å¤"); return false; } if (!isPaused) { //System.out.println("轮询æ¥è¯¢æªå¤äºæåç¶æ"); return false; } // æ¢å¤åæ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { logErrorWithRateLimit("resume_polling_serial_failed", "䏲壿ªè¿æ¥ï¼æ æ³æ¢å¤è½®è¯¢æ¥è¯¢"); return false; } isPaused = false; synchronized (lunxun.class) { lunxun.class.notifyAll(); // å¤éçå¾ ççº¿ç¨ } //System.out.println("轮询æ¥è¯¢å·²æ¢å¤"); return true; } /** * æ£æ¥è½®è¯¢ç¶æ * @return true-æ£å¨è¿è¡, false-已忢 */ public static boolean isPolling() { return isRunning; } /** * æ£æ¥æ¯å¦æå * @return true-å·²æå, false-æªæå */ public static boolean isPaused() { return isPaused; } /** * æ£æ¥ä¸²å£è¿æ¥ç¶æ * @return true-串å£å·²è¿æ¥, false-䏲壿ªè¿æ¥ */ public static boolean isSerialConnected() { return serialConnected; } /** * 设置轮询é´é * @param interval 轮询é´éï¼æ¯«ç§ï¼ */ public static void setPollingInterval(int interval) { if (interval < 10) { logErrorWithRateLimit("polling_interval_too_small", "轮询é´éä¸è½å°äº10ms"); return; } pollingInterval = interval; //System.out.println("轮询é´é已设置为: " + interval + "ms"); // 妿æ£å¨è¿è¡ï¼éæ°å¯å¨ä»¥åºç¨æ°çé´é if (isRunning) { restartPolling(); } } /** * è·åå½å轮询é´é * @return 轮询é´éï¼æ¯«ç§ï¼ */ public static int getPollingInterval() { return pollingInterval; } /** * éæ°å¯å¨è½®è¯¢æ¥è¯¢ * @return true-é坿å, false-éå¯å¤±è´¥ */ public static boolean restartPolling() { stopPolling(); // çå¾ ä¸å°æ®µæ¶é´ç¡®ä¿çº¿ç¨å®å ¨åæ¢ try { Thread.sleep(200); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } return startPolling(); } /** * ä»é ç½®ä¸å 载轮询é´é */ private static void loadPollingIntervalFromConfig() { try { Chushihua configSystem = Chushihua.getInstance(); if (configSystem.isInitialized()) { MachineConfig machineConfig = configSystem.getMachineConfig(); pollingInterval = machineConfig.getPollingInterval(); //System.out.println("ä»é ç½®å 载轮询é´é: " + pollingInterval + "ms"); } else { //System.out.println("é ç½®ç³»ç»æªåå§åï¼ä½¿ç¨é»è®¤è½®è¯¢é´é: " + pollingInterval + "ms"); } } catch (Exception e) { logErrorWithRateLimit("load_polling_interval_failed", "å 载轮询é´éé 置失败: " + e.getMessage()); //System.out.println("使ç¨é»è®¤è½®è¯¢é´é: " + pollingInterval + "ms"); } } /** * è·åç¼åçæ¥è¯¢æä»¤ */ private static String getCachedQueryCommand(int slotNumber) { return queryCommandCache.computeIfAbsent(slotNumber, QueryData::queryData); } /** * æ¸ ç©ºæ¥è¯¢æä»¤ç¼åï¼å½æ¥è¯¢é»è¾ååæ¶è°ç¨ï¼ */ public static void clearQueryCache() { queryCommandCache.clear(); //System.out.println("æ¥è¯¢æä»¤ç¼åå·²æ¸ ç©º"); } /** * 轮询任å¡å é¨ç±» - ä¼åçæ¬ * æ¯æä¸åç¶æå¡æ§½çä¸åæ¥è¯¢é¢ç * ä¼åï¼å å管çåéç¨å¯¹è±¡ */ private static class PollingTask implements Runnable { private int currentIndex = 0; // å½åç´¢å¼ï¼ç¨äºéåslotArray private int consecutiveFailures = 0; // è¿ç»å¤±è´¥æ¬¡æ° private static final int MAX_CONSECUTIVE_FAILURES = 5; // æå¤§è¿ç»å¤±è´¥æ¬¡æ° private final StringBuilder debugBuilder = new StringBuilder(100); // éç¨ StringBuilder @Override public void run() { //System.out.println("轮询æ¥è¯¢çº¿ç¨å¼å§è¿è¡"); while (isRunning && !Thread.currentThread().isInterrupted() && !shouldStop.get()) { try { // System.out.println("æ¥è¯¢ä¸.....线ç¨"); // æ£æ¥æ¯å¦æå if (isPaused) { synchronized (lunxun.class) { while (isPaused && isRunning && !shouldStop.get()) { lunxun.class.wait(1000); // çå¾ 1ç§æç´å°è¢«å¤é } } continue; } // å®ææ£æ¥ä¸²å£è¿æ¥ç¶æï¼æ¯10æ¬¡å¾ªç¯æ£æ¥ä¸æ¬¡ï¼ if (currentIndex % 10 == 0 && !checkSerialConnectionWithRetry()) { logErrorWithRateLimit("serial_disconnected", "串å£è¿æ¥æå¼ï¼æå轮询"); pausePolling(); continue; } // å®ææ¸ çç¼åï¼æ¯100æ¬¡å¾ªç¯æ¸ ç䏿¬¡ï¼ if (currentIndex % 100 == 0) { cleanupOldCache(); } // è·å塿§½æ°ç» Fkj[] slotArray = SlotManager.getSlotArray(); if (slotArray == null || slotArray.length == 0) { logErrorWithRateLimit("slot_array_not_initialized", "塿§½æ°ç»æªåå§å"); Thread.sleep(pollingInterval); continue; } // æ°å¢ï¼æ ¹æ®å¡æ§½ç¶æåæ¥è¯¢é¢çå³å®æ¯å¦åéæ¥è¯¢ boolean sentQuery = false; long currentTime = System.currentTimeMillis(); // éå塿§½ï¼å¯»æ¾éè¦æ¥è¯¢ç塿§½ for (int i = 0; i < slotArray.length && !sentQuery; i++) { int slotIndex = (currentIndex + i) % slotArray.length; Fkj slot = slotArray[slotIndex]; if (slot != null) { String hasCard = slot.getHasCard(); int slotNumber = slotIndex + 1; Long lastQueryTime = lastQueryTimeMap.get(slotNumber); // ç¡®å®æ¥è¯¢é´éï¼åªæhasCard="1"ç塿§½ä½¿ç¨10ç§é´éï¼å ¶ä»æ åµï¼å æ¬"-1"ï¼é½ä½¿ç¨100msé´é int queryInterval = "1".equals(hasCard) ? HAS_CARD_QUERY_INTERVAL : NO_CARD_QUERY_INTERVAL; // æ£æ¥æ¯å¦è¾¾å°æ¥è¯¢æ¶é´ if (lastQueryTime == null || currentTime - lastQueryTime >= queryInterval) { if (sendQueryToSlot(slotNumber)) { // æ´æ°æåæ¥è¯¢æ¶é´ lastQueryTimeMap.put(slotNumber, currentTime); sentQuery = true; consecutiveFailures = 0; // æååéæ¥è¯¢åï¼çå¾ 100msåç»§ç»ä¸ä¸ä¸ªæ¥è¯¢ Thread.sleep(100); if (DEBUG_ENABLED) { String status; if ("1".equals(hasCard)) { status = "æå¡"; } else if ("-1".equals(hasCard)) { status = "æªç¥"; } else { status = "æ å¡"; } // 使ç¨éç¨ç StringBuilder æå»ºè°è¯ä¿¡æ¯ debugBuilder.setLength(0); debugBuilder.append("Slot ").append(slotNumber) .append(" (").append(status).append(") æ¥è¯¢æåï¼é´é: ") .append(queryInterval).append("ms\n"); SystemDebugDialog.appendAsciiData(debugBuilder.toString()); } } else { consecutiveFailures++; if (consecutiveFailures >= MAX_CONSECUTIVE_FAILURES) { logErrorWithRateLimit("consecutive_failures", "lunxunè¿ç»å¤±è´¥æ¬¡æ°è¿å¤ï¼æå轮询"); pausePolling(); break; } } } } } // æ´æ°å½åç´¢å¼ currentIndex = (currentIndex + 1) % slotArray.length; // å¦ææ²¡æåéæ¥è¯¢ï¼çå¾ ä¸æ®µæ¶é´åç»§ç» if (!sentQuery) { Thread.sleep(pollingInterval); } } catch (InterruptedException e) { //System.out.println("轮询æ¥è¯¢çº¿ç¨è¢«ä¸æ"); Thread.currentThread().interrupt(); break; } catch (Exception e) { logErrorWithRateLimit("polling_exception", "轮询æ¥è¯¢è¿ç¨ä¸åçå¼å¸¸: " + e.getMessage()); consecutiveFailures++; // åçå¼å¸¸æ¶çå¾ ä¸æ®µæ¶é´åç»§ç» try { Thread.sleep(1000); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); break; } } } //System.out.println("轮询æ¥è¯¢çº¿ç¨ç»æè¿è¡"); } /** * åæå®å¡æ§½åéæ¥è¯¢æä»¤ - ä¼åçæ¬ * 使ç¨ç¼åæä»¤ï¼ä¼åè°è¯è¾åº */ private boolean sendQueryToSlot(int slotNumber) { try { // 使ç¨ç¼åçæ¥è¯¢æä»¤ String queryCommand = getCachedQueryCommand(slotNumber); // System.out.println("æä»¤æ¯ï¼"+queryCommand); if (DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("send to "+slotNumber+" queryCommand"); } if (queryCommand != null && !queryCommand.trim().isEmpty()) { // åéå°ä¸²å£ if(sendChaxunzhiling) { boolean sendResult = Sendmsg.sendMessage(queryCommand); if (sendResult) { return true; } else { if (DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData(slotNumber+" Send query command to card slot err"); } // åé失败å¯è½æ¯ä¸²å£æå¼ï¼æ´æ°è¿æ¥ç¶æ serialConnected = false; return false; } }else { return false; } } else { logErrorWithRateLimit("empty_query_command", "çæçæ¥è¯¢æä»¤ä¸ºç©ºï¼å¡æ§½: " + slotNumber); return false; } } catch (Exception e) { logErrorWithRateLimit("send_query_exception", "åéæ¥è¯¢æä»¤å°å¡æ§½ " + slotNumber + " æ¶åçå¼å¸¸: " + e.getMessage()); // åçå¼å¸¸æ¶æ´æ°ä¸²å£è¿æ¥ç¶æ serialConnected = false; return false; } } } /** * ç«å³åæå®å¡æ§½åéæ¥è¯¢æä»¤ï¼ä¸çå¾ è½®è¯¢ï¼ * @param slotNumber 塿§½ç¼å· (1-60) * @return true-åéæå, false-åé失败 */ public static boolean sendImmediateQuery(int slotNumber) { if (slotNumber < MIN_SLOT || slotNumber > MAX_SLOT) { logErrorWithRateLimit("invalid_slot_number", "塿§½ç¼å·å¿ é¡»å¨" + MIN_SLOT + "-" + MAX_SLOT + "ä¹é´"); return false; } // æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { logErrorWithRateLimit("immediate_query_serial_failed", "䏲壿ªè¿æ¥ï¼æ æ³åéæ¥è¯¢æä»¤"); return false; } try { // 使ç¨ç¼åçæ¥è¯¢æä»¤ String queryCommand = getCachedQueryCommand(slotNumber); if (queryCommand != null && !queryCommand.trim().isEmpty()) { // åéå°ä¸²å£ boolean sendResult = Sendmsg.sendMessage(queryCommand); if (sendResult) { // æ´æ°æåæ¥è¯¢æ¶é´ lastQueryTimeMap.put(slotNumber, System.currentTimeMillis()); if (DEBUG_ENABLED) { //System.out.println("ç«å³æ¥è¯¢æå - 塿§½ " + slotNumber); } return true; } else { logErrorWithRateLimit("immediate_query_send_failed", "ç«å³æ¥è¯¢å¤±è´¥ - åéæä»¤å°å¡æ§½ " + slotNumber + " 失败"); return false; } } else { logErrorWithRateLimit("immediate_query_empty_command", "ç«å³æ¥è¯¢å¤±è´¥ - çæçæ¥è¯¢æä»¤ä¸ºç©ºï¼å¡æ§½: " + slotNumber); return false; } } catch (Exception e) { logErrorWithRateLimit("immediate_query_exception", "ç«å³æ¥è¯¢å¡æ§½ " + slotNumber + " æ¶åçå¼å¸¸: " + e.getMessage()); return false; } } /** * ç«å³åææå¡æ§½åéæ¥è¯¢æä»¤ï¼æ¹éï¼- ä¼åçæ¬ * @return æååéçæä»¤æ°é */ public static int sendImmediateQueryToAll() { // æ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { logErrorWithRateLimit("batch_query_serial_failed", "䏲壿ªè¿æ¥ï¼æ æ³åéæ¹éæ¥è¯¢æä»¤"); return 0; } int successCount = 0; int batchSize = 5; // æ¯æ¹æ¬¡åé5个æ¥è¯¢ int totalSlots = MAX_SLOT - MIN_SLOT + 1; long currentTime = System.currentTimeMillis(); //System.out.println("å¼å§æ¹éæ¥è¯¢ææå¡æ§½..."); for (int batchStart = MIN_SLOT; batchStart <= MAX_SLOT; batchStart += batchSize) { if (shouldStop.get()) { break; } int batchEnd = Math.min(batchStart + batchSize - 1, MAX_SLOT); // æ¹æ¬¡å æ¥è¯¢ for (int slot = batchStart; slot <= batchEnd; slot++) { if (sendImmediateQuery(slot)) { successCount++; // æ´æ°æåæ¥è¯¢æ¶é´ lastQueryTimeMap.put(slot, currentTime); } } // æ¹æ¬¡é´é´éï¼é¿å 䏲壿¥å µ if (batchEnd < MAX_SLOT) { try { Thread.sleep(50); } catch (InterruptedException e) { Thread.currentThread().interrupt(); break; } } } //System.out.println("æ¹éæ¥è¯¢å®æï¼æååé: " + successCount + "/" + totalSlots); return successCount; } /** * æå¨è®¾ç½®ä¸²å£è¿æ¥ç¶æï¼ç¨äºå¤é¨æ£æµå°ä¸²å£ç¶æååæ¶è°ç¨ï¼ * @param connected 串å£è¿æ¥ç¶æ */ public static void setSerialConnected(boolean connected) { serialConnected = connected; lastSerialCheckTime = System.currentTimeMillis(); if (connected) { // //System.out.println("串å£è¿æ¥ç¶æå·²è®¾ç½®ä¸º: å·²è¿æ¥"); } else { logErrorWithRateLimit("serial_disconnected_external", "串å£è¿æ¥ç¶æå·²è®¾ç½®ä¸º: æªè¿æ¥"); // 妿䏲壿å¼ä¸è½®è¯¢æ£å¨è¿è¡ï¼èªå¨æå轮询 if (isRunning && !isPaused) { pausePolling(); } } } /** * è·åè½®è¯¢ç¶æä¿¡æ¯ * @return ç¶æä¿¡æ¯å符串 */ public static String getPollingStatus() { String status; if (!isRunning) { status = "已忢"; } else if (isPaused) { status = "å·²æå"; } else { status = "è¿è¡ä¸"; } String serialStatus = serialConnected ? "å·²è¿æ¥" : "æªè¿æ¥"; int cacheSize = queryCommandCache.size(); // ç»è®¡ä¸åç¶æç塿§½æ°é int noCardCount = 0; int hasCardCount = 0; Fkj[] slotArray = SlotManager.getSlotArray(); if (slotArray != null) { for (Fkj slot : slotArray) { if (slot != null && "1".equals(slot.getHasCard())) { hasCardCount++; } else { noCardCount++; } } } return String.format("è½®è¯¢ç¶æ: %s, 串å£: %s, é´é: %dms, æä»¤ç¼å: %d, 塿§½èå´: %d-%d, æ å¡: %d(100ms), æå¡: %d(10s)\n%s", status, serialStatus, pollingInterval, cacheSize, MIN_SLOT, MAX_SLOT, noCardCount, hasCardCount, getMemoryStatus()); } /** * ç´æ¥è®¾ç½®è½®è¯¢æåç¶æï¼ä¾å ¶ä»ç±»è°ç¨ï¼ * @param paused true-æå轮询, false-æ¢å¤è½®è¯¢ * @return true-设置æå, false-设置失败ï¼å¦è½®è¯¢æªè¿è¡ï¼ */ public static boolean setPollingPaused(boolean paused) { if (!isRunning) { //System.out.println("轮询æ¥è¯¢æªå¨è¿è¡ï¼æ æ³è®¾ç½®æåç¶æ"); return false; } if (paused) { // è¯·æ±æå if (!isPaused) { isPaused = true; //System.out.println("轮询æ¥è¯¢å·²éè¿å¤é¨è°ç¨æå"); return true; } else { //System.out.println("轮询æ¥è¯¢å·²ç»å¤äºæåç¶æ"); return false; } } else { // è¯·æ±æ¢å¤ if (isPaused) { // æ¢å¤åæ£æ¥ä¸²å£è¿æ¥ if (!checkSerialConnectionWithRetry()) { logErrorWithRateLimit("external_resume_serial_failed", "䏲壿ªè¿æ¥ï¼æ æ³æ¢å¤è½®è¯¢æ¥è¯¢"); return false; } isPaused = false; synchronized (lunxun.class) { lunxun.class.notifyAll(); // å¤éçå¾ ççº¿ç¨ } //System.out.println("轮询æ¥è¯¢å·²éè¿å¤é¨è°ç¨æ¢å¤"); return true; } else { //System.out.println("轮询æ¥è¯¢æªå¤äºæåç¶æ"); return false; } } } /** * è·åæ§è½ç»è®¡ä¿¡æ¯ */ public static String getPerformanceStats() { long currentTime = System.currentTimeMillis(); int overdueNoCard = 0; int overdueHasCard = 0; Fkj[] slotArray = SlotManager.getSlotArray(); if (slotArray != null) { for (int i = 0; i < slotArray.length; i++) { Fkj slot = slotArray[i]; if (slot != null) { int slotNumber = i + 1; Long lastQueryTime = lastQueryTimeMap.get(slotNumber); if (lastQueryTime != null) { String hasCard = slot.getHasCard(); int queryInterval = "1".equals(hasCard) ? HAS_CARD_QUERY_INTERVAL : NO_CARD_QUERY_INTERVAL; if (currentTime - lastQueryTime > queryInterval) { if ("1".equals(hasCard)) { overdueHasCard++; } else { overdueNoCard++; } } } } } } return String.format("æ¥è¯¢æä»¤ç¼å大å°: %d, 轮询é´é: %dms, è¶ æ¶æ å¡: %d, è¶ æ¶æå¡: %d", queryCommandCache.size(), pollingInterval, overdueNoCard, overdueHasCard); } /** * 设置æ å¡å¡æ§½æ¥è¯¢é´é * @param interval æ¥è¯¢é´éï¼æ¯«ç§ï¼ */ public static void setNoCardQueryInterval(int interval) { if (interval < 10) { logErrorWithRateLimit("no_card_interval_too_small", "æ å¡å¡æ§½æ¥è¯¢é´éä¸è½å°äº10ms"); return; } // 注æï¼è¿éåªæ¯è®¾ç½®å¸¸éï¼å®é è¿è¡æ¶éè¦éæ°å¯å¨è½®è¯¢æè½çæ //System.out.println("æ å¡å¡æ§½æ¥è¯¢é´é已设置为: " + interval + "ms"); } /** * 设置æå¡å¡æ§½æ¥è¯¢é´é * @param interval æ¥è¯¢é´éï¼æ¯«ç§ï¼ */ public static void setHasCardQueryInterval(int interval) { if (interval < 1000) { logErrorWithRateLimit("has_card_interval_too_small", "æå¡å¡æ§½æ¥è¯¢é´éä¸è½å°äº1000ms"); return; } // 注æï¼è¿éåªæ¯è®¾ç½®å¸¸éï¼å®é è¿è¡æ¶éè¦éæ°å¯å¨è½®è¯¢æè½çæ //System.out.println("æå¡å¡æ§½æ¥è¯¢é´é已设置为: " + interval + "ms"); } public static boolean isDEBUG_ENABLED() { return DEBUG_ENABLED; @@ -653,4 +803,102 @@ public static void setDEBUG_ENABLED(boolean dEBUG_ENABLED) { DEBUG_ENABLED = dEBUG_ENABLED; } // ==================== æ°å¢å åä¼åæ¹æ³ ==================== /** * æ¸ çæ§ç¼å - 鲿¢å åæ éå¢é¿ */ private static void cleanupOldCache() { long currentTime = System.currentTimeMillis(); if (currentTime - lastCleanupTime < CACHE_CLEANUP_INTERVAL) { return; } lastCleanupTime = currentTime; // æ¸ çé¿æ¶é´æªä½¿ç¨çæ¥è¯¢æ¶é´è®°å½ long cleanupThreshold = currentTime - 300000; // 5åéæªä½¿ç¨ lastQueryTimeMap.entrySet().removeIf(entry -> currentTime - entry.getValue() > cleanupThreshold ); // éå¶æ¥è¯¢æä»¤ç¼åå¤§å° if (queryCommandCache.size() > MAX_CACHE_SIZE) { Iterator<Map.Entry<Integer, String>> iterator = queryCommandCache.entrySet().iterator(); int itemsToRemove = queryCommandCache.size() - MAX_CACHE_SIZE; for (int i = 0; i < itemsToRemove && iterator.hasNext(); i++) { iterator.next(); iterator.remove(); } } // æ¸ çé误æ¥å¿éæµè®°å½ lastErrorLogTime.entrySet().removeIf(entry -> currentTime - entry.getValue() > 300000 // 5åé ); } /** * éæµé误æ¥å¿ - 鲿¢å¤§éé夿¥å¿å ç¨å å */ private static void logErrorWithRateLimit(String errorKey, String message) { long currentTime = System.currentTimeMillis(); Long lastTime = lastErrorLogTime.get(errorKey); if (lastTime == null || currentTime - lastTime > ERROR_LOG_INTERVAL) { Errlog.logOperation(message); lastErrorLogTime.put(errorKey, currentTime); // æ¸ çè¿æçéè¯¯è®°å½ if (lastErrorLogTime.size() > 50) { lastErrorLogTime.entrySet().removeIf(entry -> currentTime - entry.getValue() > 300000 // 5åé ); } } } /** * è·åå åç¶æä¿¡æ¯ */ public static String getMemoryStatus() { Runtime runtime = Runtime.getRuntime(); long totalMemory = runtime.totalMemory(); long freeMemory = runtime.freeMemory(); long usedMemory = totalMemory - freeMemory; long maxMemory = runtime.maxMemory(); return String.format("å å使ç¨: %.2fMB/%.2fMB (æå¤§: %.2fMB), ç¼å: æ¶é´è®°å½=%d, æä»¤ç¼å=%d, é误记å½=%d", usedMemory / (1024.0 * 1024.0), totalMemory / (1024.0 * 1024.0), maxMemory / (1024.0 * 1024.0), lastQueryTimeMap.size(), queryCommandCache.size(), lastErrorLogTime.size()); } /** * æå¨è§¦åå 忏 ç */ public static void performCleanup() { // æ¸ çæ¥è¯¢æ¶é´è®°å½ä¸é¿æ¶é´æªæ¥è¯¢ç塿§½ long cleanupThreshold = System.currentTimeMillis() - 3600000; // 1å°æ¶ lastQueryTimeMap.entrySet().removeIf(entry -> entry.getValue() < cleanupThreshold ); // æ¸ ç©ºæ¥è¯¢æä»¤ç¼å queryCommandCache.clear(); // æ¸ ç©ºé误æ¥å¿éæµè®°å½ lastErrorLogTime.clear(); // 建议系ç»è¿è¡åå¾åæ¶ï¼ä½ä¸å¼ºå¶ï¼ System.gc(); if (DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("æ§è¡å 忏 ç宿\n"); } } } src/chushihua/lunxunzaixian.java
ÎļþÒÑɾ³ý src/dialog/Charulog.java
ÎļþÃû´Ó src/xitongshezhi/Charulog.java ÐÞ¸Ä @@ -1,4 +1,4 @@ package xitongshezhi; package dialog; import java.io.*; import java.text.SimpleDateFormat; @@ -51,8 +51,9 @@ File file = new File(LOG_FILE); if (file.exists()) { try (FileInputStream fis = new FileInputStream(file)) { props.load(fis); try (FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "UTF-8")) { props.load(isr); } catch (IOException e) { System.err.println("è¯»åæ¥å¿æä»¶å¤±è´¥: " + e.getMessage()); } @@ -95,14 +96,14 @@ * åå ¥æ¥å¿æä»¶ */ private static void writeLogFile(Properties props) { try (FileOutputStream fos = new FileOutputStream(LOG_FILE)) { try (FileOutputStream fos = new FileOutputStream(LOG_FILE); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8")) { // æ·»å æä»¶å¤´æ³¨é props.store(fos, "æä½æ¥å¿è®°å½ - æåæ´æ°: " + new Date()); props.store(osw, "æä½æ¥å¿è®°å½ - æåæ´æ°: " + new Date()); } catch (IOException e) { System.err.println("åå ¥æ¥å¿æä»¶å¤±è´¥: " + e.getMessage()); } } /** * è·åå½åæ¥å¿è®°å½æ°éï¼ç¨äºæµè¯ï¼ */ src/dialog/Dingshidialog.java
ÎļþÃû´Ó src/xitongshezhi/Dingshidialog.java ÐÞ¸Ä @@ -1,4 +1,4 @@ package xitongshezhi; package dialog; import java.awt.BorderLayout; import java.awt.Color; @@ -26,6 +26,9 @@ */ public class Dingshidialog { // æ·»å éææ å¿æ¥è·è¸ªå¼¹çªæ¾ç¤ºç¶æ private static volatile boolean isDialogShowing = false; /** * æ¾ç¤ºå®æ¶å ³éå¯¹è¯æ¡ * @param parent ç¶çªå£ @@ -34,8 +37,14 @@ * @param audioFile MP3æä»¶åï¼æ ¹ç®å½ä¸ï¼æ éæ©å±åï¼ * @return 1-æå 0-失败 */ public static int showTimedDialog(Frame parent, int countdownTime, String message, String audioFile) { TimedDialog dialog = new TimedDialog(parent, countdownTime, message, audioFile); public static int showTimedDialog(Frame parent, int countdownTime, String message) { // æ£æ¥æ¯å¦å·²æå¼¹çªå¨æ¾ç¤º if (isDialogShowing) { System.out.println("å·²æå¼¹çªå¨æ¾ç¤ºï¼å¿½ç¥æ°è¯·æ±"); return 0; // è¿å失败 } TimedDialog dialog = new TimedDialog(parent, countdownTime, message); return dialog.showDialog(); } @@ -43,19 +52,18 @@ * å é¨å¯¹è¯æ¡ç±»ï¼ç¡®ä¿ä½¿ç¨åè½è¢«åå¾åæ¶ */ @SuppressWarnings("serial") private static class TimedDialog extends JDialog { private static class TimedDialog extends JDialog { private JLabel countdownLabel; private int remainingTime; private int result = 0; private Clip audioClip; private volatile boolean running = true; public TimedDialog(Frame parent, int countdownTime, String message, String audioFile) { public TimedDialog(Frame parent, int countdownTime, String message) { super(parent, "", true); this.remainingTime = countdownTime; initializeUI(message); startCountdown(); playAudio(audioFile); } private void initializeUI(String message) { @@ -89,7 +97,7 @@ messageLabel.setHorizontalAlignment(SwingConstants.CENTER); // å建åè®¡æ¶æ ç¾ countdownLabel = new JLabel("å©ä½æ¶é´: " + remainingTime + "ç§"); countdownLabel = new JLabel(remainingTime + "ç§åèªå¨å ³é"); countdownLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16)); countdownLabel.setForeground(new Color(231, 76, 60)); countdownLabel.setHorizontalAlignment(SwingConstants.CENTER); @@ -132,6 +140,18 @@ public void windowClosing(java.awt.event.WindowEvent e) { disposeDialog(); } @Override public void windowOpened(java.awt.event.WindowEvent e) { // è®¾ç½®å¼¹çªæ¾ç¤ºæ å¿ isDialogShowing = true; } @Override public void windowClosed(java.awt.event.WindowEvent e) { // ç¡®ä¿å¼¹çªå ³éæ¶éç½®æ å¿ isDialogShowing = false; } }); } @@ -147,7 +167,7 @@ SwingUtilities.invokeLater(() -> { if (countdownLabel != null) { countdownLabel.setText("å©ä½æ¶é´: " + remainingTime + "ç§"); countdownLabel.setText( remainingTime + "ç§åèªå¨å ³é"); } }); @@ -245,6 +265,9 @@ // æ¸ çUIå¼ç¨ countdownLabel = null; // éç½®å¼¹çªæ¾ç¤ºæ å¿ isDialogShowing = false; dispose(); } @@ -252,6 +275,12 @@ * æ¾ç¤ºå¯¹è¯æ¡ */ public int showDialog() { // 忬¡æ£æ¥æ å¿ï¼é²æ¢ç«ææ¡ä»¶ if (isDialogShowing) { System.out.println("å·²æå¼¹çªå¨æ¾ç¤ºï¼åæ¶æ¾ç¤º"); return 0; } setVisible(true); return result; } src/dialog/Errlog.javacopy from src/xitongshezhi/Charulog.java copy to src/dialog/Errlog.java
Îļþ´Ó src/xitongshezhi/Charulog.java ¸´ÖÆ @@ -1,12 +1,12 @@ package xitongshezhi; package dialog; import java.io.*; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.locks.ReentrantLock; public class Charulog { private static final String LOG_FILE = "log.properties"; public class Errlog { private static final String LOG_FILE = "err.properties"; private static final int MAX_RECORDS = 500; private static final ReentrantLock lock = new ReentrantLock(); private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -51,8 +51,9 @@ File file = new File(LOG_FILE); if (file.exists()) { try (FileInputStream fis = new FileInputStream(file)) { props.load(fis); try (FileInputStream fis = new FileInputStream(file); InputStreamReader isr = new InputStreamReader(fis, "UTF-8")) { props.load(isr); } catch (IOException e) { System.err.println("è¯»åæ¥å¿æä»¶å¤±è´¥: " + e.getMessage()); } @@ -95,14 +96,14 @@ * åå ¥æ¥å¿æä»¶ */ private static void writeLogFile(Properties props) { try (FileOutputStream fos = new FileOutputStream(LOG_FILE)) { try (FileOutputStream fos = new FileOutputStream(LOG_FILE); OutputStreamWriter osw = new OutputStreamWriter(fos, "UTF-8")) { // æ·»å æä»¶å¤´æ³¨é props.store(fos, "æä½æ¥å¿è®°å½ - æåæ´æ°: " + new Date()); props.store(osw, "æä½æ¥å¿è®°å½ - æåæ´æ°: " + new Date()); } catch (IOException e) { System.err.println("åå ¥æ¥å¿æä»¶å¤±è´¥: " + e.getMessage()); } } /** * è·åå½åæ¥å¿è®°å½æ°éï¼ç¨äºæµè¯ï¼ */ src/home/CardMachineUI.java
@@ -13,7 +13,6 @@ import xitongshezhi.AdminLoginDialog; import xitongshezhi.CardPickupDialog; import xitongshezhi.ConfigSet; import xitongshezhi.Fkj; import chuankou.SerialPortService; import chuankou.Sendmsg; @@ -77,9 +76,12 @@ private JPanel commFaultPanel; public CardMachineUI() { try { try { // å åå§åç³»ç»é ç½®åç»ä»¶ initializeSystem(); // åå§å串å£è§£æå¨ initializeSerialParser(); // ç¶ååå§åUI initializeUI(); @@ -110,7 +112,8 @@ if (serialConnected && lunxun.isPolling() && lunxun.isPaused()) { // åªæå¨ä¸å¨è®¾ç½®é¡µé¢æ¶æèªå¨æ¢å¤ if (!isInConfigPage()) { lunxun.resumePolling(); // lunxun.resumePolling(); // System.out.println("å°è¯èªå¨å¯å¨è½®è¯¢åè½"); } } }); @@ -171,7 +174,7 @@ } private void initializeUI() { setTitle("UWB人åå®ä½å¡å塿ºç®¡çç³»ç»"); setTitle("æºè½äººè¸å塿ºç®¡çç³»ç»"); setSize(SCREEN_WIDTH, SCREEN_HEIGHT); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setLocationRelativeTo(null); @@ -288,8 +291,9 @@ refreshBtn.addActionListener(e -> { updateCardSlotsDisplay(); updateStatistics(); lunxun.resumePolling(); JOptionPane.showMessageDialog(CardMachineUI.this, "æå¨å·æ°å®æï¼å ±å·æ° " + TOTAL_SLOTS + " ä¸ªå¡æ§½", "æå¨å·æ°å®æï¼å¯å¨è½®è¯¢ï¼å ±å·æ° " + TOTAL_SLOTS + " ä¸ªå¡æ§½", "å·æ°å®æ", JOptionPane.INFORMATION_MESSAGE); }); @@ -586,7 +590,7 @@ if (pickupSuccess) { // å塿åï¼è°ç¨changgehaskaæ¹æ³æ¹å塿§½å±æ§ SlotManager.changgehaska(slotId, "1"); // "1"表示管çåæä½ SlotManager.changgehaska(slotId,1); // "1"表示管çåæä½ //System.out.println("塿§½ " + slotId + " å塿åï¼å·²æ´æ°å¡æ§½ç¶æ"); } } @@ -796,12 +800,15 @@ /** * å¯å¨UIå·æ°å®æ¶å¨ - æ¯3ç§å·æ°ä¸æ¬¡ */ // å¨startUIUpdates()æ¹æ³ä¸è°ç¨ private void startUIUpdates() { uiUpdateTimer = new Timer(3000, e -> { updateCardSlotsDisplay(); updateStatistics(); }); uiUpdateTimer.start(); uiUpdateTimer = new Timer(3000, e -> { ensurePollingRunning(); // ç¡®ä¿è½®è¯¢è¿è¡ ensureSerialParserRunning(); // ç¡®ä¿ä¸²å£è§£æå¨è¿è¡ updateCardSlotsDisplay(); updateStatistics(); }); uiUpdateTimer.start(); } /** @@ -829,5 +836,42 @@ public SlotManager getSlotManager() { return slotManager; } /** * æ£æ¥å¹¶ç¡®ä¿è½®è¯¢æ¥è¯¢æ£å¸¸è¿è¡ */ private void ensurePollingRunning() { if (!lunxun.isPolling() && lunxun.checkSerialConnection()) { // å¦æè½®è¯¢æªè¿è¡ä½ä¸²å£å·²è¿æ¥ï¼èªå¨å¯å¨è½®è¯¢ boolean started = lunxun.startPolling(); if (started) { System.out.println("æ£æµå°è½®è¯¢æªè¿è¡ï¼å·²èªå¨å¯å¨"); } } } /** * ç¡®ä¿ä¸²å£è§£æå¨æ£å¸¸è¿è¡ */ private void ensureSerialParserRunning() { // 妿䏲å£è§£æå¨æªè¿è¡ä½ä¸²å£å·²è¿æ¥ï¼èªå¨å¯å¨ if (serialProtocolParser != null && !serialProtocolParser.isRunning() && lunxun.checkSerialConnection()) { serialProtocolParser.start(); //System.out.println("æ£æµå°ä¸²å£è§£æå¨æªè¿è¡ï¼å·²èªå¨å¯å¨"); } } /** * åå§å串å£è§£æå¨ */ private void initializeSerialParser() { try { serialProtocolParser = new SerialProtocolParser(); serialProtocolParser.start(); //System.out.println("串å£å议解æå¨å·²å¯å¨"); } catch (Exception e) { System.err.println("åå§å串å£è§£æå¨å¤±è´¥: " + e.getMessage()); } } } src/home/Fkj.java
ÎļþÃû´Ó src/xitongshezhi/Fkj.java ÐÞ¸Ä @@ -1,4 +1,4 @@ package xitongshezhi; package home; public class Fkj { // å®ä¹ææå±æ§ï¼å为Stringç±»å private String slotNumber; // 塿§½ç¼å· src/home/Homein.java
@@ -1,5 +1,4 @@ package home; import javax.swing.JOptionPane; import javax.swing.SwingUtilities; import javax.swing.UIManager; @@ -7,8 +6,6 @@ import chushihua.Chushihua; import chushihua.SlotManager; import chushihua.lunxun; import chushihua.lunxunzaixian; import jiekou.lunxunkazhuangtai; public class Homein { public static void main(String[] args) { @@ -107,7 +104,7 @@ private static boolean initializeSlotManager() { try { // SlotManager ä¼å¨æé 彿°ä¸èªå¨åå§åææå¡æ§½ SlotManager slotManager = new SlotManager(); new SlotManager(); //System.out.println("â 塿§½ç®¡çå¨åå§åæå"); //System.out.println(" æ»å¡æ§½æ°: " + slotManager.getTotalSlots()); @@ -130,11 +127,7 @@ if (serialConnected) { // 4. 串å£è¿æ¥æååï¼å¯å¨è½®è¯¢ startPollingService(); showMainInterface(); //å¯å¨è½®è¯¢å¡ç¶æç»æå¡å¨åæ°æ® lunxunkazhuangtai.startPolling(); //å¯å¨å¨çº¿çå¡ç¶æè½®è¯¢ lunxunzaixian.startOnlinePolling(); showMainInterface(); } else { System.err.println("串å£è¿æ¥å¤±è´¥"); src/jiekou/lunxunkazhuangtai.java
@@ -1,6 +1,7 @@ package jiekou; import chushihua.SlotManager; import xitongshezhi.Fkj; import home.Fkj; /** * è½®è¯¢å¡æ§½ç¶æç±» src/publicway/OpenDoor.java
@@ -6,8 +6,8 @@ private static final String FUNCTION_CODE_PREFIX = "515AA55AA5"; // å¼é¨ç±»å常é public static final int TYPE_ISSUE_CARD = 1; public static final int TYPE_ADMIN = 2; public static final int TYPE_ISSUE_CARD = 1;//1åå¡å¼é¨ public static final int TYPE_ADMIN = 2;//2管çåå¼é¨ // åæ°èå´å¸¸é private static final int MIN_SLOT_NUMBER = 0; src/publicway/ProtocolParser01.java
@@ -1,13 +1,20 @@ package publicway; import java.util.ArrayList; import java.util.List; import chuankou.SerialPortService; import chushihua.SlotManager; public class ProtocolParser01 { // ç¼å常ç¨å符串åå°éå¤å建 private static final String[] WORK_STATUS_DESC = {"æ æ", "å¾ æº", "å çµ", "å æ»¡", "æ é", "ææå°æ", "éä¿¡è¶ æ¶", "æªç¥ç¶æ"}; private static final String[] DOOR_STATUS_DESC = {"æªç¥ç¶æ", "å¼é¨ç¶æ", "å ³é¨ç¶æ"}; private static final String[] CARD_STATUS_DESC = {"æ å¡", "æå¡", "读å¡é误(å¡éæ³)", "æªç¥ç¶æ"}; // StringBuilder å¯¹è±¡æ± private static final ThreadLocal<StringBuilder> stringBuilderPool = ThreadLocal.withInitial(() -> new StringBuilder(512)); /** * æ°å¢ï¼ç´æ¥ä½¿ç¨åèæ°ç»è§£æçæ¹æ³ï¼é¿å å符串转æ¢ï¼ * ä¼ååçåèæ°ç»è§£ææ¹æ³ */ public static ParseResult parseDDCC01Data(byte[] packetData) { if (packetData == null || packetData.length < 18) { @@ -19,45 +26,49 @@ throw new IllegalArgumentException("éDDCCåè®®æ°æ®"); } ParseResult result = ParseResultPool.borrowObject(); try { // è·³è¿å 头DDCC (2åè)ï¼ç´æ¥ä½¿ç¨å©ä½æ°æ® byte[] dataBytes = new byte[packetData.length - 2]; System.arraycopy(packetData, 2, dataBytes, 0, dataBytes.length); if (dataBytes.length < 16) { // ç´æ¥ä½¿ç¨åæ°ç»ï¼é¿å åå»ºæ°æ°ç» if (packetData.length < 18) { // 2(å 头) + 16(æå°æ°æ®é¿åº¦) throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³"); } // 2. è§£æåä¸ªåæ®µ int dataLength = parseDataLength(dataBytes); int hostAddress = parseHostAddress(dataBytes); int slotNumber = parseSlotNumber(dataBytes); int functionCode = parseFunctionCode(dataBytes); WorkStatus workStatus = parseWorkStatus(dataBytes); DoorStatus doorStatus = parseDoorStatus(dataBytes); CardStatus cardStatus = parseCardStatus(dataBytes); int cardStatusChange = parseCardStatusChange(dataBytes); String cardNumber = parseCardNumber(dataBytes); List<FaultType> faults = parseFaults(dataBytes); double voltage = parseVoltage(dataBytes); double current = parseCurrent(dataBytes); // è§£æåä¸ªåæ®µ int dataLength = parseDataLength(packetData, 2); int hostAddress = parseHostAddress(packetData, 4); int slotNumber = parseSlotNumber(packetData, 5); int functionCode = parseFunctionCode(packetData, 6); // 3. éªè¯åè½ç // éªè¯åè½ç if (functionCode != 0x01) { throw new IllegalArgumentException("é01åè½ç æ°æ®"); } return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus, cardStatus, cardStatusChange, cardNumber, faults, voltage, current, dataLength); WorkStatus workStatus = parseWorkStatus(packetData, 7); DoorStatus doorStatus = parseDoorStatus(packetData, 8); CardStatus cardStatus = parseCardStatus(packetData, 9); int cardStatusChange = parseCardStatusChange(packetData, 10); String cardNumber = parseCardNumber(packetData, 13); List<FaultType> faults = parseFaults(packetData, 15); double voltage = parseVoltage(packetData, 16); double current = parseCurrent(packetData, 17); // éç¨ ParseResult 对象 result.reset(hostAddress, slotNumber, workStatus, doorStatus, cardStatus, cardStatusChange, cardNumber, faults, voltage, current, dataLength); return result; } catch (Exception e) { // åçå¼å¸¸æ¶å½è¿å¯¹è±¡ ParseResultPool.returnObject(result); throw new RuntimeException("è§£ææ°æ®æ¶åçé误: " + e.getMessage(), e); } } /** * ä¿çåææ¹æ³ç¨äºå ¼å®¹æ§ * ä¼ååçåç¬¦ä¸²è§£ææ¹æ³ */ public static ParseResult parseDDCC01Data(String hexData) { if (hexData == null || hexData.isEmpty()) { @@ -69,6 +80,7 @@ throw new IllegalArgumentException("éDDCCåè®®æ°æ®"); } ParseResult result = ParseResultPool.borrowObject(); try { // 1. ç§»é¤å 头DDCCè¿è¡è§£æ String dataWithoutHeader = hexData.substring(4); @@ -79,178 +91,162 @@ } // 2. è§£æåä¸ªåæ®µ int dataLength = parseDataLength(dataBytes); int hostAddress = parseHostAddress(dataBytes); int slotNumber = parseSlotNumber(dataBytes); int functionCode = parseFunctionCode(dataBytes); WorkStatus workStatus = parseWorkStatus(dataBytes); DoorStatus doorStatus = parseDoorStatus(dataBytes); CardStatus cardStatus = parseCardStatus(dataBytes); int cardStatusChange = parseCardStatusChange(dataBytes); String cardNumber = parseCardNumber(dataBytes); List<FaultType> faults = parseFaults(dataBytes); double voltage = parseVoltage(dataBytes); double current = parseCurrent(dataBytes); int dataLength = parseDataLength(dataBytes, 0); int hostAddress = parseHostAddress(dataBytes, 2); int slotNumber = parseSlotNumber(dataBytes, 3); int functionCode = parseFunctionCode(dataBytes, 4); // 3. éªè¯åè½ç if (functionCode != 0x01) { throw new IllegalArgumentException("é01åè½ç æ°æ®"); } return new ParseResult(hostAddress, slotNumber, workStatus, doorStatus, cardStatus, cardStatusChange, cardNumber, faults, voltage, current, dataLength); WorkStatus workStatus = parseWorkStatus(dataBytes, 5); DoorStatus doorStatus = parseDoorStatus(dataBytes, 6); CardStatus cardStatus = parseCardStatus(dataBytes, 7); int cardStatusChange = parseCardStatusChange(dataBytes, 8); String cardNumber = parseCardNumber(dataBytes, 11); List<FaultType> faults = parseFaults(dataBytes, 13); double voltage = parseVoltage(dataBytes, 14); double current = parseCurrent(dataBytes, 15); result.reset(hostAddress, slotNumber, workStatus, doorStatus, cardStatus, cardStatusChange, cardNumber, faults, voltage, current, dataLength); return result; } catch (Exception e) { ParseResultPool.returnObject(result); throw new RuntimeException("è§£ææ°æ®æ¶åçé误: " + e.getMessage(), e); } } /** * CRCæ ¡éª * æ ¹æ®åè®®ï¼CRC16æ ¡éªä»åè½ç ä¹åä¸ç´å°CRC16ä¹åçæ°æ® */ private static boolean validateCRC(String hexData) { try { // CRC卿å4个å符 String receivedCRC = hexData.substring(hexData.length() - 6); byte[] cmdBytes = HexUtil.hexStringToBytes(hexData.replace(receivedCRC,"")); String crc = HexUtil.calculate(cmdBytes)+"00"; //System.out.println("æ¶å°ç宿´æ°æ®æ¯ï¼"+hexData); //System.out.println("æ¶å°æ°æ®æ ¡éªç æ¯ï¼"+receivedCRC); //System.out.println("æ ¡éªç æ¯ï¼"+crc); return receivedCRC.equalsIgnoreCase(crc); } catch (Exception e) { System.err.println("CRCæ ¡éªå¼å¸¸: " + e.getMessage()); return false; } } /** * è§£ææ°æ®é¿åº¦ï¼2åèï¼ * æ°æ®é¿åº¦æ¯ä»è¯¥åèä¹åå¼å§å°CRC16ä¹åæ°æ®åèæ° */ private static int parseDataLength(byte[] data) { if (data.length < 2) { private static int parseDataLength(byte[] data, int offset) { if (data.length < offset + 2) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£ææ°æ®é¿åº¦"); } return ((data[0] & 0xFF) << 8) | (data[1] & 0xFF); return ((data[offset] & 0xFF) << 8) | (data[offset + 1] & 0xFF); } /** * è§£æä¸»æºå°åï¼1åèï¼ */ private static int parseHostAddress(byte[] data) { if (data.length < 3) { private static int parseHostAddress(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æä¸»æºå°å"); } return data[2] & 0xFF; return data[offset] & 0xFF; } /** * è§£æå¡æ§½ç¼å·ï¼1åèï¼ */ private static int parseSlotNumber(byte[] data) { if (data.length < 4) { private static int parseSlotNumber(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå¡æ§½ç¼å·"); } return data[3] & 0xFF; return data[offset] & 0xFF; } /** * è§£æåè½ç ï¼1åèï¼ */ private static int parseFunctionCode(byte[] data) { if (data.length < 5) { private static int parseFunctionCode(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æåè½ç "); } return data[4] & 0xFF; return data[offset] & 0xFF; } /** * è§£æå·¥ä½ç¶æï¼1åèï¼ */ private static WorkStatus parseWorkStatus(byte[] data) { if (data.length < 6) { private static WorkStatus parseWorkStatus(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå·¥ä½ç¶æ"); } int statusValue = data[5] & 0xFF; int statusValue = data[offset] & 0xFF; return WorkStatus.fromValue(statusValue); } /** * è§£æå¨ä½ç¶æ/é¨ç¶æï¼1åèï¼ */ private static DoorStatus parseDoorStatus(byte[] data) { if (data.length < 7) { private static DoorStatus parseDoorStatus(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå¨ä½ç¶æ"); } int statusValue = data[6] & 0xFF; int statusValue = data[offset] & 0xFF; return DoorStatus.fromValue(statusValue); } /** * è§£æå¡ç¶æï¼1åèï¼ */ private static CardStatus parseCardStatus(byte[] data) { if (data.length < 8) { private static CardStatus parseCardStatus(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå¡ç¶æ"); } int statusValue = data[7] & 0xFF; int statusValue = data[offset] & 0xFF; return CardStatus.fromValue(statusValue); } /** * è§£æå¡ç¶æåæ´ï¼1åèï¼ */ private static int parseCardStatusChange(byte[] data) { if (data.length < 9) { private static int parseCardStatusChange(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå¡ç¶æåæ´"); } return data[8] & 0xFF; return data[offset] & 0xFF; } /** * è§£æå¡å·ï¼å¡å·3 + å¡å·4ï¼ */ private static String parseCardNumber(byte[] data) { if (data.length < 13) { private static String parseCardNumber(byte[] data, int offset) { if (data.length < offset + 2) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æå¡å·"); } // ç´¢å¼11ï¼å¡å·3ï¼ç´¢å¼12ï¼å¡å·4 byte cardNumber3 = data[11]; byte cardNumber4 = data[12]; return String.format("%02X%02X", cardNumber3 & 0xFF, cardNumber4 & 0xFF); // ç´æ¥è¿åå符串ï¼é¿å å建临æ¶å¯¹è±¡ char[] hexChars = new char[4]; hexChars[0] = Character.forDigit((data[offset] >> 4) & 0xF, 16); hexChars[1] = Character.forDigit(data[offset] & 0xF, 16); hexChars[2] = Character.forDigit((data[offset + 1] >> 4) & 0xF, 16); hexChars[3] = Character.forDigit(data[offset + 1] & 0xF, 16); return new String(hexChars).toUpperCase(); } /** * è§£ææ éä¿¡æ¯ï¼1åèï¼ */ private static List<FaultType> parseFaults(byte[] data) { if (data.length < 14) { private static List<FaultType> parseFaults(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£ææ éä¿¡æ¯"); } int faultByte = data[13] & 0xFF; List<FaultType> faults = new ArrayList<>(); int faultByte = data[offset] & 0xFF; List<FaultType> faults = new ArrayList<>(5); // é¢åé 容é for (FaultType fault : FaultType.values()) { if ((faultByte & fault.getBitMask()) != 0) { faults.add(fault); } } return faults; } /** * è§£æçµåå¼ï¼1åèï¼ */ private static double parseVoltage(byte[] data) { if (data.length < 15) { private static double parseVoltage(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æçµå"); } int voltageValue = data[14] & 0xFF; int voltageValue = data[offset] & 0xFF; // 50mV/bit 转æ¢ä¸ºä¼ç¹ return voltageValue * 0.05; } @@ -258,18 +254,16 @@ /** * è§£æçµæµå¼ï¼1åèï¼ */ private static double parseCurrent(byte[] data) { if (data.length < 16) { private static double parseCurrent(byte[] data, int offset) { if (data.length < offset + 1) { throw new IllegalArgumentException("æ°æ®é¿åº¦ä¸è¶³ï¼æ æ³è§£æçµæµ"); } int currentValue = data[15] & 0xFF; int currentValue = data[offset] & 0xFF; // 10mA/bit 转æ¢ä¸ºå®å¹ return currentValue * 0.01; } /** * å·¥ä½ç¶ææä¸¾ */ // æä¸¾ç±»ä¿æä¸å... public enum WorkStatus { INVALID(0, "æ æ"), STANDBY(1, "å¾ æº"), @@ -288,13 +282,8 @@ this.description = description; } public int getValue() { return value; } public String getDescription() { return description; } public int getValue() { return value; } public String getDescription() { return description; } public static WorkStatus fromValue(int value) { for (WorkStatus status : values()) { @@ -306,9 +295,6 @@ } } /** * é¨ç¶ææä¸¾ */ public enum DoorStatus { UNKNOWN(0, "δ֪״̬"), DOOR_OPEN(1, "å¼é¨ç¶æ"), @@ -322,13 +308,8 @@ this.description = description; } public int getValue() { return value; } public String getDescription() { return description; } public int getValue() { return value; } public String getDescription() { return description; } public static DoorStatus fromValue(int value) { for (DoorStatus status : values()) { @@ -340,9 +321,6 @@ } } /** * å¡ç¶ææä¸¾ */ public enum CardStatus { NO_CARD(0, "æ å¡"), HAS_CARD(1, "æå¡"), @@ -357,13 +335,8 @@ this.description = description; } public int getValue() { return value; } public String getDescription() { return description; } public int getValue() { return value; } public String getDescription() { return description; } public static CardStatus fromValue(int value) { for (CardStatus status : values()) { @@ -375,9 +348,6 @@ } } /** * æ éç±»åæä¸¾ */ public enum FaultType { INSERT_ERROR(0x01, "æå¡é误"), OVER_CURRENT(0x02, "è¿æµ"), @@ -393,17 +363,12 @@ this.description = description; } public int getBitMask() { return bitMask; } public String getDescription() { return description; } public int getBitMask() { return bitMask; } public String getDescription() { return description; } } /** * è§£æç»æç±» - æ·»å å¯¹è±¡æ± æ¯æ * ä¼ååçè§£æç»æç±» */ public static class ParseResult { private int hostAddress; @@ -418,29 +383,12 @@ private double current; private int dataLength; // é»è®¤æé å¨ç¨äºå¯¹è±¡æ± // éç¨å表对象 private final List<FaultType> faultList = new ArrayList<>(5); private final List<String> faultDescList = new ArrayList<>(5); public ParseResult() {} public ParseResult(int hostAddress, int slotNumber, WorkStatus workStatus, DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange, String cardNumber, List<FaultType> faults, double voltage, double current, int dataLength) { this.hostAddress = hostAddress; this.slotNumber = slotNumber; this.workStatus = workStatus; this.doorStatus = doorStatus; this.cardStatus = cardStatus; this.cardStatusChange = cardStatusChange; this.cardNumber = cardNumber; this.faults = faults; this.voltage = voltage; this.current = current; this.dataLength = dataLength; } /** * éç½®æ¹æ³ï¼ç¨äºå¯¹è±¡éç¨ */ public void reset(int hostAddress, int slotNumber, WorkStatus workStatus, DoorStatus doorStatus, CardStatus cardStatus, int cardStatusChange, String cardNumber, List<FaultType> faults, double voltage, @@ -452,10 +400,16 @@ this.cardStatus = cardStatus; this.cardStatusChange = cardStatusChange; this.cardNumber = cardNumber; this.faults = faults; this.voltage = voltage; this.current = current; this.dataLength = dataLength; // éç¨æ éå表 this.faultList.clear(); if (faults != null) { this.faultList.addAll(faults); } this.faults = this.faultList; } // Getteræ¹æ³ @@ -475,21 +429,24 @@ * è·åæ éç䏿æè¿°å表 */ public List<String> getFaultDescriptions() { List<String> descriptions = new ArrayList<>(); faultDescList.clear(); for (FaultType fault : faults) { descriptions.add(fault.getDescription()); faultDescList.add(fault.getDescription()); } return descriptions; return faultDescList; } /** * è·åæ éç䏿æè¿°å符串 */ public String getFaultsString() { if (faults == null || faults.isEmpty()) { if (faults.isEmpty()) { return "æ æ é"; } StringBuilder sb = new StringBuilder(); StringBuilder sb = stringBuilderPool.get(); sb.setLength(0); for (int i = 0; i < faults.size(); i++) { if (i > 0) sb.append(", "); sb.append(faults.get(i).getDescription()); @@ -499,49 +456,47 @@ @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("=== DDCCåè®®æ°æ®è§£æç»æ ===\n"); sb.append("1. 主æºå°å: ").append(String.format("%02X", hostAddress)); sb.append("2. 塿§½ç¼å·: ").append(slotNumber); sb.append("3. å·¥ä½ç¶æ: ").append(workStatus.getDescription()) .append(" (").append(workStatus.getValue()); sb.append("4. é¨ç¶æ: ").append(doorStatus.getDescription()) .append(" (").append(doorStatus.getValue()); sb.append("5. å¡ç¶æ: ").append(cardStatus.getDescription()) .append(" (").append(cardStatus.getValue()); sb.append("6. å¡ç¶æåæ´: ").append(cardStatusChange); sb.append("7. å¡å·: ").append(cardNumber); sb.append("8. æ é: ").append(getFaultsString()); sb.append("9. çµå: ").append(String.format("%.2f", voltage)); sb.append("10. çµæµ: ").append(String.format("%.2f", current)); sb.append("æ°æ®é¿åº¦: ").append(dataLength).append(" åè"); // //System.out.println(sb.toString()); return sb.toString(); StringBuilder sb = stringBuilderPool.get(); sb.setLength(0); sb.append("1.主æºå°å:").append(String.format("%02X", hostAddress)); sb.append("2.塿§½ç¼å·:").append(slotNumber); sb.append("3.å·¥ä½ç¶æ:").append(workStatus.getDescription()) .append("(").append(workStatus.getValue()).append(")"); sb.append("4. é¨ç¶æ:").append(doorStatus.getDescription()) .append("(").append(doorStatus.getValue()).append(")"); sb.append("5.å¡ç¶æ:").append(cardStatus.getDescription()) .append("(").append(cardStatus.getValue()).append(")"); sb.append("6.å¡ç¶æåæ´:").append(cardStatusChange); sb.append("7.å¡å·:").append(cardNumber); sb.append("8.æ é:").append(getFaultsString()); sb.append("9.çµå:").append(String.format("%.2f", voltage)); sb.append("10.çµæµ:").append(String.format("%.2f", current)); sb.append("æ°æ®é¿åº¦:").append(dataLength).append(" åè"); return sb.toString(); } public void fuzhi() { SlotManager.gengxinshuxingzhi( SlotManager.gengxinshuxingzhi( slotNumber, // 塿§½ç¼å· cardNumber, // å¡ç¼å· String.valueOf(cardStatus.getValue()), // æ¯å¦æå¡0æ å¡ï¼1æå¡ï¼-1æªç¥ String.valueOf(workStatus.getValue()), // å·¥ä½ç¶æ0.æ æ1.å¾ æºï¼2.å çµï¼3.å æ»¡ï¼4.æ éï¼5.ææå°æï¼6.éä¿¡è¶ æ¶ String.valueOf(workStatus.getValue()), // å·¥ä½ç¶æ String.format("%.2f", voltage), // çµå String.format("%.2f", current), // çµæµ getFaultsString() // æ é1æå¡é误ï¼2è¿æµï¼3,鍿§æ éï¼4è¿åï¼5æ¬ åï¼ ); getFaultsString() // æ é ); } } /** * ç®åçå¯¹è±¡æ± å®ç° * æ¹è¿çå¯¹è±¡æ± å®ç° */ public static class ParseResultPool { private static final int POOL_SIZE = 10; private static final int POOL_SIZE = 20; private static final java.util.concurrent.BlockingQueue<ParseResult> pool = new java.util.concurrent.ArrayBlockingQueue<>(POOL_SIZE); new java.util.concurrent.LinkedBlockingQueue<>(POOL_SIZE); static { // é¢å建对象 @@ -556,9 +511,17 @@ } public static void returnObject(ParseResult result) { if (result != null && !pool.offer(result)) { // æ± å·²æ»¡ï¼ä¸åæ¶ if (result != null) { // æ¸ çç¶æ result.reset(0, 0, WorkStatus.UNKNOWN, DoorStatus.UNKNOWN, CardStatus.UNKNOWN, 0, "", null, 0.0, 0.0, 0); // éé»å¡å¼å½è¿ pool.offer(result); } } public static int getPoolSize() { return pool.size(); } } } src/publicway/SerialProtocolParser.java
@@ -1,4 +1,5 @@ package publicway; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; @@ -6,7 +7,12 @@ import java.util.concurrent.TimeUnit; import chuankou.SerialPortService; import chushihua.SlotManager; import chushihua.lunxun; import dialog.Charulog; import dialog.Dingshidialog; import publicway.ProtocolParser01.ParseResult; import xitongshezhi.SystemDebugDialog; public class SerialProtocolParser { @@ -22,15 +28,15 @@ private static final byte FUNCTION_82 = (byte) 0x82; // åæ¿åçº§ä½¿è½ private static final byte FUNCTION_83 = (byte) 0x83; // åæ¿åçº§æ°æ®å // æ°æ®ç¼å²åºï¼ç¨äºå¤çç²å // æ°æ®ç¼å²åºï¼ç¨äºå¤çç²å - æ¹ä¸ºç´æ¥ByteArrayOutputStream管ç private byte[] dataBuffer = new byte[1024]; private int bufferPosition = 0; // æ°æ®æ¥æ¶éå private BlockingQueue<byte[]> dataQueue = new ArrayBlockingQueue<>(100); // æ°æ®æ¥æ¶éå - éå¶éå大å°é²æ¢å åæ éå¢é¿ private BlockingQueue<byte[]> dataQueue = new ArrayBlockingQueue<>(50); // æ¹éå¤çéå private final BlockingQueue<byte[]> batchQueue = new ArrayBlockingQueue<>(1000); // æ¹éå¤çéå - éå¶éåå¤§å° private final BlockingQueue<byte[]> batchQueue = new ArrayBlockingQueue<>(200); private final ScheduledExecutorService batchExecutor = Executors.newSingleThreadScheduledExecutor(); @@ -41,12 +47,18 @@ // éç¨StringBuilderåå°å¯¹è±¡å建 private final StringBuilder hexBuilder = new StringBuilder(256); // å åçæ§è®¡æ°å¨ private long lastMemoryCheckTime = 0; private static final long MEMORY_CHECK_INTERVAL = 30000; // 30ç§æ£æ¥ä¸æ¬¡ // å¯¹è±¡æ± ï¼åå°å¯¹è±¡å建 private final Object packetPoolLock = new Object(); /** * å¯å¨è§£æå¨ */ public void start() { if (isRunning) { //System.out.println("串å£å议解æå¨å·²ç»å¨è¿è¡ä¸"); return; } @@ -58,8 +70,6 @@ processorThread = new Thread(this::processPackets, "Serial-Protocol-Parser"); processorThread.setDaemon(true); processorThread.start(); //System.out.println("串å£å议解æå¨å·²å¯å¨"); } /** @@ -94,11 +104,16 @@ } // æ¸ ç©ºéååç¼å²åº clearQueues(); bufferPosition = 0; } /** * æ¸ ç©ºææéåï¼éæ¾å å */ private void clearQueues() { dataQueue.clear(); batchQueue.clear(); bufferPosition = 0; //System.out.println("串å£å议解æå¨å·²åæ¢"); } /** @@ -113,17 +128,39 @@ */ public void receiveData(byte[] rawData) { if (!isRunning) { //System.out.println("è¦å: 串å£å议解æå¨æªå¯å¨ï¼å¿½ç¥æ¥æ¶çæ°æ®"); return; // å¦æè§£æå¨æªè¿è¡ï¼èªå¨å¯å¨ start(); } if (rawData == null || rawData.length == 0) { return; } // æ£æ¥éåç¶æï¼é¿å å åæ éå¢é¿ if (batchQueue.size() > batchQueue.remainingCapacity() * 0.8) { // éåæ¥è¿æ»¡æ¶ï¼ä¸¢å¼æèçæ°æ® if (!batchQueue.isEmpty()) { batchQueue.poll(); // ç§»é¤ä¸ä¸ªæ§æ°æ® } } // å°æ°æ®æ·»å å°æ¹ééå if (!batchQueue.offer(rawData)) { System.err.println("æ¹ééå已满ï¼ä¸¢å¼æ°æ®"); // éå已满æ¶çå¤ç handleQueueFull(); } } /** * å¤çéåæ»¡çæ åµ */ private void handleQueueFull() { // æ¸ ç©ºéåéæ°å¼å§ï¼é¿å å åæ³æ¼ clearQueues(); bufferPosition = 0; // éç½®ç¼å²åº if (lunxun.DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("è¦åï¼æ°æ®å¤çéå已满ï¼å·²æ¸ 空éåéæ°å¼å§"); } } @@ -135,39 +172,105 @@ return; } // æ¹éå¤çæ°æ® java.util.List<byte[]> batch = new java.util.ArrayList<>(100); batchQueue.drainTo(batch, 100); for (byte[] rawData : batch) { // å°æ°æ®æ·»å å°ç¼å²åº if (bufferPosition + rawData.length > dataBuffer.length) { // ç¼å²åºä¸è¶³æ¶ï¼æ¸ çå¹¶éæ°å¼å§ System.arraycopy(dataBuffer, bufferPosition - rawData.length, dataBuffer, 0, rawData.length); bufferPosition = rawData.length; } else { try { // æ¹éå¤çæ°æ®ï¼éå¶æ¯æ¬¡å¤ççæå¤§æ°é int maxBatchSize = 50; java.util.List<byte[]> batch = new java.util.ArrayList<>(maxBatchSize); batchQueue.drainTo(batch, maxBatchSize); for (byte[] rawData : batch) { // æ£æ¥ç¼å²åºå®¹éï¼é¿å æº¢åº if (bufferPosition + rawData.length > dataBuffer.length) { // ç¼å²åºä¸è¶³æ¶çå¤ç if (rawData.length > dataBuffer.length) { // åæ¡æ°æ®è¶ è¿ç¼å²åºå¤§å°ï¼ç´æ¥å¤çæä¸¢å¼ handleOversizedPacket(rawData); continue; } else { // ç§»å¨æææ°æ®å°ç¼å²åºå¼å¤´ compactBuffer(0); } } // å°æ°æ®æ·»å å°ç¼å²åº System.arraycopy(rawData, 0, dataBuffer, bufferPosition, rawData.length); bufferPosition += rawData.length; // å¤çç¼å²åºä¸çæ°æ® processBuffer(); } // å¤çç¼å²åºä¸çæ°æ® processBuffer(); // å®ææ£æ¥å å checkMemory(); } catch (Exception e) { System.err.println("æ¹éå¤çæ°æ®æ¶åçå¼å¸¸: " + e.getMessage()); // åçå¼å¸¸æ¶éç½®ç¶æ resetParserState(); } // å®ææ£æ¥å å checkMemory(); } /** * å¤çè¿å¤§çæ°æ®å */ private void handleOversizedPacket(byte[] oversizedData) { // 对äºè¿å¤§çæ°æ®å ï¼ç´æ¥å°è¯æ¥æ¾èµ·å§æ è®° int startIndex = findStartMarkerInArray(oversizedData, 0); if (startIndex != -1) { // æ¾å°èµ·å§æ è®°ï¼å°å©ä½æ°æ®æ¾å ¥ç¼å²åº int remainingLength = oversizedData.length - startIndex; if (remainingLength <= dataBuffer.length) { System.arraycopy(oversizedData, startIndex, dataBuffer, 0, remainingLength); bufferPosition = remainingLength; processBuffer(); } } // å¦å丢å¼è¯¥æ°æ®å } /** * 卿宿°ç»ä¸æ¥æ¾èµ·å§æ è®° */ private int findStartMarkerInArray(byte[] data, int startPos) { for (int i = startPos; i <= data.length - START_MARKER.length; i++) { if (data[i] == START_MARKER[0] && data[i + 1] == START_MARKER[1]) { return i; } } return -1; } /** * é置解æå¨ç¶æ */ private void resetParserState() { bufferPosition = 0; clearQueues(); } /** * å åçæ§ */ private void checkMemory() { long currentTime = System.currentTimeMillis(); if (currentTime - lastMemoryCheckTime < MEMORY_CHECK_INTERVAL) { return; } lastMemoryCheckTime = currentTime; Runtime runtime = Runtime.getRuntime(); long usedMem = runtime.totalMemory() - runtime.freeMemory(); long maxMem = runtime.maxMemory(); if (usedMem > maxMem * 0.8) { //System.out.println("å å使ç¨çè¶ è¿80%ï¼å½å使ç¨: " + (usedMem / 1024 / 1024) + "MB"); if (usedMem > maxMem * 0.75) { // å å使ç¨çè¶ è¿75%æ¶è¿è¡åå¾åæ¶ System.gc(); if (lunxun.DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("å å使ç¨çè¶ è¿75%ï¼å·²è§¦ååå¾åæ¶ã使ç¨å å: " + (usedMem / 1024 / 1024) + "MB"); } } } @@ -175,7 +278,10 @@ * å¤çç¼å²åºä¸çæ°æ®ï¼è§£æå®æ´æ°æ®å */ private void processBuffer() { while (bufferPosition >= MIN_PACKET_LENGTH) { int processedCount = 0; final int MAX_PACKETS_PER_BATCH = 20; // éå¶æ¯æ¬¡å¤ççæå¤§å æ°é while (bufferPosition >= MIN_PACKET_LENGTH && processedCount < MAX_PACKETS_PER_BATCH) { // æ¥æ¾èµ·å§æ è®° int startIndex = findStartMarker(); if (startIndex == -1) { @@ -195,6 +301,13 @@ int dataLength = ((dataBuffer[startIndex + 2] & 0xFF) << 8) | (dataBuffer[startIndex + 3] & 0xFF); int totalPacketLength = 2 + 2 + dataLength + 2; // èµ·å§æ è®°2 + æ°æ®é¿åº¦2 + æ°æ®å 容 + CRC2 // æ£æ¥æ°æ®é¿åº¦æ¯å¦åç if (dataLength < 0 || totalPacketLength > dataBuffer.length) { // æ°æ®é¿åº¦å¼å¸¸ï¼è·³è¿è¿ä¸ªå compactBuffer(startIndex + 1); continue; } // æ£æ¥æ¯å¦æ¶å°å®æ´æ°æ®å if (startIndex + totalPacketLength > bufferPosition) { // æ°æ®å ä¸å®æ´ï¼çå¾ æ´å¤æ°æ® @@ -203,16 +316,15 @@ } // æå宿´æ°æ®å byte[] packet = new byte[totalPacketLength]; System.arraycopy(dataBuffer, startIndex, packet, 0, totalPacketLength); // å°æ°æ®å æ¾å ¥éåä¾è§£æ try { byte[] packet = extractPacket(startIndex, totalPacketLength); if (packet != null) { // å°æ°æ®å æ¾å ¥éåä¾è§£æ if (!dataQueue.offer(packet)) { System.err.println("æ°æ®éå已满ï¼ä¸¢å¼æ°æ®å "); // éå已满ï¼éæ¾packetå¼ç¨ packet = null; handleDataQueueFull(); return; } } catch (Exception e) { System.err.println("æ¾å ¥æ°æ®éåæ¶åçå¼å¸¸: " + e.getMessage()); } // ç§»å¨ç¼å²åºä½ç½® @@ -221,6 +333,29 @@ System.arraycopy(dataBuffer, startIndex + totalPacketLength, dataBuffer, 0, remaining); } bufferPosition = remaining; processedCount++; } } /** * æåæ°æ®å ï¼éç¨byteæ°ç»åå°å¯¹è±¡å建 */ private byte[] extractPacket(int startIndex, int totalPacketLength) { byte[] packet = new byte[totalPacketLength]; System.arraycopy(dataBuffer, startIndex, packet, 0, totalPacketLength); return packet; } /** * å¤çæ°æ®éåæ»¡çæ åµ */ private void handleDataQueueFull() { // 丢å¼éå䏿èçæ°æ® dataQueue.poll(); if (lunxun.DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData("æ°æ®è§£æéå已满ï¼ä¸¢å¼æèæ°æ®å "); } } @@ -240,7 +375,7 @@ * å缩ç¼å²åºï¼å°æææ°æ®ç§»å°å¼å¤´ */ private void compactBuffer(int startIndex) { if (startIndex > 0) { if (startIndex > 0 && bufferPosition > startIndex) { System.arraycopy(dataBuffer, startIndex, dataBuffer, 0, bufferPosition - startIndex); bufferPosition -= startIndex; } @@ -250,43 +385,46 @@ * å¤çæ°æ®å çä¸»æ¹æ³ */ private void processPackets() { //System.out.println("䏲壿°æ®å å¤ç线ç¨å¼å§è¿è¡"); System.out.println("䏲壿°æ®å å¤ç线ç¨å¼å§è¿è¡"); while (isRunning && !Thread.currentThread().isInterrupted()) { try { byte[] packet = dataQueue.take(); // é»å¡ç´å°ææ°æ® parsePacket(packet); } catch (InterruptedException e) { //System.out.println("䏲壿°æ®å å¤ç线ç¨è¢«ä¸æ"); System.out.println("䏲壿°æ®å å¤ç线ç¨è¢«ä¸æ"); Thread.currentThread().interrupt(); break; } catch (Exception e) { System.err.println("å¤çæ°æ®å æ¶åçå¼å¸¸: " + e.getMessage()); e.printStackTrace(); // ç»§ç»è¿è¡ï¼ä¸éåºçº¿ç¨ } } //System.out.println("䏲壿°æ®å å¤ç线ç¨ç»æè¿è¡"); System.out.println("䏲壿°æ®å å¤ç线ç¨ç»æè¿è¡"); } /** * è§£ææ°æ®å å¹¶æ ¹æ®åè½ç è°ç¨ç¸åºæ¹æ³ */ private void parsePacket(byte[] packet) { if (packet == null || packet.length < MIN_PACKET_LENGTH) { return; } try { SerialPortService.getReceivedDataCount(); SerialPortService.getReceivedDataCount(); // è§£æåºæ¬å段 byte hostAddress = packet[4]; // 主æºå°å byte slotAddress = packet[5]; // 塿§½å°å byte functionCode = packet[6]; // åè½ç byte functionCode = packet[6]; // åè½ç // æ°æ®é¿åº¦ (ä»åè®®ä¸è¯»å) int dataLength = ((packet[2] & 0xFF) << 8) | (packet[3] & 0xFF); // è¿å弿°æ® int returnValueLength = dataLength - 3; // N-3 (åå»ä¸»æºå°åã塿§½å°åãåè½ç ) byte[] returnValue = null; if (returnValueLength > 0) { if (returnValueLength > 0 && returnValueLength <= packet.length - 7) { returnValue = new byte[returnValueLength]; System.arraycopy(packet, 7, returnValue, 0, returnValueLength); } @@ -297,43 +435,51 @@ if (returnValue != null) { // 使ç¨ä¼åçåèæ°ç»è§£ææ¹æ³ï¼é¿å åç¬¦ä¸²è½¬æ¢ ParseResult rst = ProtocolParser01.parseDDCC01Data(packet); rst.fuzhi(); // rst.toString(); if (rst != null) { rst.fuzhi(); if (lunxun.DEBUG_ENABLED) { SystemDebugDialog.appendAsciiData(rst.toString()); } } } break; case FUNCTION_51: // è°ç¨ ProtocolParser51 å¤çæ°æ® String hexPacket = bytesToHex(packet); int result = ProtocolParser51.parse(hexPacket); int slot = slotAddress; if (result == 1) { //System.out.println("åè½ç 0x51 - å¼é¨æ§å¶æå"); SlotManager.changgehaska(slot, result); } else { //System.out.println("åè½ç 0x51 - å¼é¨æ§å¶å¤±è´¥ææ¥æä¸åæ³"); String message = slot + "å·å¡æ§½åå¡å¤±è´¥"; Charulog.logOperation(message); } break; case FUNCTION_52: //System.out.println("åè½ç 0x52 - LED亮度æ§å¶"); // LED亮度æ§å¶ - æ æä½ break; case FUNCTION_80: //System.out.println("åè½ç 0x80 - å·¥å¡å级使è½"); // å·¥å¡åçº§ä½¿è½ - æ æä½ break; case FUNCTION_81: //System.out.println("åè½ç 0x81 - å·¥ä½å¡åçº§æ°æ®å "); // å·¥ä½å¡åçº§æ°æ®å - æ æä½ break; case FUNCTION_82: //System.out.println("åè½ç 0x82 - åæ¿å级使è½"); // åæ¿åçº§ä½¿è½ - æ æä½ break; case FUNCTION_83: //System.out.println("åè½ç 0x83 - åæ¿åçº§æ°æ®å "); // åæ¿åçº§æ°æ®å - æ æä½ break; default: System.err.println("æªç¥åè½ç : 0x" + Integer.toHexString(functionCode & 0xFF)); if (lunxun.DEBUG_ENABLED) { System.err.println("æªç¥åè½ç : 0x" + Integer.toHexString(functionCode & 0xFF)); } break; } } catch (Exception e) { System.err.println("è§£ææ°æ®å æ¶åçé误: " + e.getMessage()); e.printStackTrace(); // 䏿å°å æ è·è¸ªï¼é¿å 产ç大鿥å¿å¯¹è±¡ } } @@ -341,6 +487,10 @@ * ä¼åçåèæ°ç»è½¬åå è¿å¶åç¬¦ä¸²æ¹æ³ */ private String bytesToHex(byte[] bytes) { if (bytes == null || bytes.length == 0) { return ""; } hexBuilder.setLength(0); // æ¸ ç©ºéç¨ for (byte b : bytes) { hexBuilder.append(String.format("%02X", b)); @@ -379,12 +529,14 @@ * è·åè§£æå¨ç¶æä¿¡æ¯ */ public String getStatusInfo() { return String.format("串å£è§£æå¨ç¶æ: %s, éå大å°: %d/%d, æ¹ééå: %d/%d", return String.format("串å£è§£æå¨ç¶æ: %s, éå大å°: %d/%d, æ¹ééå: %d/%d, ç¼å²åº: %d/%d", isRunning ? "è¿è¡ä¸" : "已忢", dataQueue.size(), dataQueue.remainingCapacity() + dataQueue.size(), batchQueue.size(), batchQueue.remainingCapacity() + batchQueue.size()); batchQueue.remainingCapacity() + batchQueue.size(), bufferPosition, dataBuffer.length); } /** @@ -393,4 +545,14 @@ public void setMaxRawDataPrintLength(int length) { // å®ç°æ ¹æ®éè¦è°æ´ } /** * 䏻卿¸ çèµæº */ public void cleanup() { stop(); clearQueues(); bufferPosition = 0; hexBuilder.setLength(0); } } src/xitongshezhi/ConfigSet.java
@@ -54,13 +54,13 @@ private final MenuItemListener menuItemListener; public ConfigSet(JFrame parent) { super(parent, "设置", true); super(parent, "", true); configManager = Chushihua.getInstance(); menuItemListener = new MenuItemListener(); // è®°å½è¿å ¥è®¾ç½®é¡µé¢åçè½®è¯¢ç¶æ // è®°å½è¿å ¥è®¾ç½®é¡µé¢åçè½®è¯¢ç¶æ recordPollingStateBeforeEntering(); initializeUI(); // è¿å ¥è®¾ç½®é¡µé¢æ¶æå轮询 // è¿å ¥è®¾ç½®é¡µé¢æ¶æå轮询 pausePollingWhenEntering(); } @@ -135,7 +135,26 @@ mainPanel.add(createHeaderPanel(), BorderLayout.NORTH); mainPanel.add(createMenuGridPanel(), BorderLayout.CENTER); // æ·»å çæä¿¡æ¯å¨åºé¨ mainPanel.add(createCopyrightPanel(), BorderLayout.SOUTH); getContentPane().add(mainPanel); } // å建çæä¿¡æ¯é¢æ¿ private JPanel createCopyrightPanel() { JPanel copyrightPanel = new JPanel(); copyrightPanel.setLayout(new FlowLayout(FlowLayout.CENTER)); copyrightPanel.setOpaque(true); copyrightPanel.setBackground(DARK_COLOR); copyrightPanel.setBorder(new EmptyBorder(10, 0, 5, 0)); JLabel copyrightLabel = new JLabel("å京åæåææºæ§ææ¯æéå ¬å¸ çæææ 2025"); copyrightLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 12)); copyrightLabel.setForeground(new Color(160, 160, 160)); copyrightPanel.add(copyrightLabel); return copyrightPanel; } private JPanel createHeaderPanel() { @@ -158,8 +177,11 @@ closeButton.setOpaque(true); // ç¡®ä¿ä¸éæ closeButton.setFocusPainted(false); closeButton.setBorder(BorderFactory.createEmptyBorder(10, 18, 10, 18)); closeButton.setIcon(getCachedIcon("â", 16)); closeButton.addActionListener(e -> dispose()); closeButton.addActionListener(e -> { // 强å¶å¼å¯è½®è¯¢æ¥è¯¢åè½ forceStartPolling(); dispose(); }); // æ·»å æ¬åææ closeButton.addMouseListener(new java.awt.event.MouseAdapter() { @@ -588,12 +610,13 @@ return icon; } private void showSystemDebugDialog() { SystemDebugDialog.showSystemDebugDialog((JFrame) getParent()); } @Override public void dispose() { // éåºè®¾ç½®é¡µé¢æ¶æ¢å¤è½®è¯¢æ§å¶ SystemDebugDialog.setPollingControlEnabled(true); // éåºè®¾ç½®é¡µé¢æ¶æ¢å¤è½®è¯¢ resumePollingWhenExiting(); @@ -673,5 +696,43 @@ configDialog.setVisible(true); }); } /** * 强å¶å¼å¯è½®è¯¢æ¥è¯¢åè½ï¼æ 论å½åç¶æå¦ä½ï¼ */ private void forceStartPolling() { try { // å¦æè½®è¯¢æªè¿è¡ï¼åå¯å¨è½®è¯¢ if (!lunxun.isPolling()) { boolean started = lunxun.startPolling(); if (started) { //System.out.println("强å¶å¼å¯ï¼è½®è¯¢æ¥è¯¢å·²å¯å¨"); } else { System.err.println("强å¶å¼å¯ï¼å¯å¨è½®è¯¢æ¥è¯¢å¤±è´¥"); } } // å¦æè½®è¯¢å·²è¿è¡ä½å¤äºæåç¶æï¼åæ¢å¤è½®è¯¢ else if (lunxun.isPaused()) { boolean resumed = lunxun.resumePolling(); if (resumed) { //System.out.println("强å¶å¼å¯ï¼è½®è¯¢æ¥è¯¢å·²æ¢å¤"); } else { System.err.println("强å¶å¼å¯ï¼æ¢å¤è½®è¯¢æ¥è¯¢å¤±è´¥"); } } // å¦æè½®è¯¢å·²è¿è¡ä¸æªæåï¼åæ éæä½ else { //System.out.println("强å¶å¼å¯ï¼è½®è¯¢æ¥è¯¢å·²å¨è¿è¡ä¸"); } } catch (Exception e) { System.err.println("强å¶å¼å¯è½®è¯¢æ¥è¯¢æ¶åçå¼å¸¸: " + e.getMessage()); } } // å¨ showSystemDebugDialog æ¹æ³ä¸æ·»å private void showSystemDebugDialog() { // 卿å¼è°è¯å¯¹è¯æ¡æ¶ç¦ç¨è½®è¯¢æ§å¶ SystemDebugDialog.setPollingControlEnabled(false); SystemDebugDialog.showSystemDebugDialog((JFrame) getParent()); } } src/xitongshezhi/SystemDebugDialog.java
@@ -10,6 +10,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import chushihua.lunxun; import dialog.Errlog; public class SystemDebugDialog extends JDialog { private static final long serialVersionUID = -9131186661220052051L; @@ -25,11 +26,9 @@ private static final Color WARNING_COLOR = new Color(243, 156, 18); private static final Color DARK_COLOR = new Color(15, 28, 48); private static final Color TEXT_COLOR = new Color(224, 224, 224); // UIç»ä»¶ // UIç»ä»¶ private JTextArea dataTextArea; private JButton clearButton; private JButton pollingButton; private JButton scrollButton; private JTextField sendTextField; private JButton sendButton; @@ -43,7 +42,7 @@ private SerialPortService serialService; // æ§å¶åé private boolean autoScroll = true; // é»è®¤èªå¨æ»å¨ private boolean autoScroll =false; // é»è®¤èªå¨æ»å¨ private static boolean dataUpdateEnabled = true; // æ§å¶æ°æ®æ´æ° // æ¥ææ ¼å¼å @@ -214,14 +213,6 @@ scrollButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20)); scrollButton.addActionListener(e -> toggleAutoScroll()); // å¯å¨/å ³éæ¥è¯¢æé® pollingButton = new JButton("å¯å¨æ¥è¯¢"); pollingButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 14)); pollingButton.setBackground(SECONDARY_COLOR); pollingButton.setForeground(Color.WHITE); pollingButton.setFocusPainted(false); pollingButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20)); pollingButton.addActionListener(e -> togglePolling()); // æ¸ ç©ºæé® clearButton = new JButton("æ¸ ç©ºæ°æ®"); @@ -233,7 +224,6 @@ clearButton.addActionListener(e -> clearData()); buttonPanel.add(scrollButton); buttonPanel.add(pollingButton); buttonPanel.add(clearButton); return buttonPanel; @@ -331,40 +321,23 @@ staticDataUpdateEnabled = dataUpdateEnabled; // 忥éæåé if (autoScroll) { scrollButton.setText("æå"); scrollButton.setText("å¼å§"); scrollButton.setBackground(PRIMARY_COLOR); if (staticDataTextArea != null) { staticDataTextArea.setCaretPosition(staticDataTextArea.getDocument().getLength()); } appendAsciiData("[" + getCurrentTime() + "] å¼å§æ¾ç¤ºæ°æ®\n"); lunxun.resumePolling(); lunxun.DEBUG_ENABLED=true; } else { scrollButton.setText("å¼å§"); scrollButton.setText("æå"); scrollButton.setBackground(WARNING_COLOR); appendAsciiData("[" + getCurrentTime() + "] æåæ¾ç¤ºæ°æ®\n"); } } private void togglePolling() { if (lunxun.isPolling()) { // 妿æ£å¨è½®è¯¢ï¼å忢 if (lunxun.stopPolling()) { pollingButton.setText("å¯å¨æ¥è¯¢"); pollingButton.setBackground(SECONDARY_COLOR); onDataReceivedascii("[" + getCurrentTime() + "] stop\n"); lunxun.setDEBUG_ENABLED(false); } } else { // 妿æªè½®è¯¢ï¼åå¯å¨ if (lunxun.startPolling()) { lunxun.setDEBUG_ENABLED(true); pollingButton.setText("忢æ¥è¯¢"); pollingButton.setBackground(DANGER_COLOR); onDataReceivedascii("[" + getCurrentTime() + "] strat\n"); } else { showMessage("é误", "æ æ³å¯å¨è½®è¯¢æ¥è¯¢ï¼è¯·æ£æ¥ä¸²å£è¿æ¥", "error"); } } } private void sendData() { String text = sendTextField.getText().trim(); @@ -418,7 +391,7 @@ dataTextArea.setText(sb.toString()); } } catch (Exception e) { System.err.println("ä¿®åªè¡æ°æ¶åçé误: " + e.getMessage()); Errlog.logOperation("ä¿®åªè¡æ°æ¶åçé误: " + e.getMessage()); } } @@ -479,7 +452,7 @@ staticDataTextArea.setText(sb.toString()); } } catch (Exception e) { System.err.println("ä¿®åªè¡æ°æ¶åçé误: " + e.getMessage()); Errlog.logOperation("ä¿®åªè¡æ°æ¶åçé误: " + e.getMessage()); } } @@ -511,7 +484,7 @@ } } catch (Exception e) { System.err.println("æ¾ç¤ºæ°æ®æ¶åçé误: " + e.getMessage()); Errlog.logOperation("æ¾ç¤ºæ°æ®æ¶åçé误: " + e.getMessage()); } }); } @@ -531,14 +504,14 @@ displayText = displayText.substring(0, MAX_LINE_LENGTH) + "..."; } staticDataTextArea.append(displayText); staticDataTextArea.append(displayText+"\n"); if (staticDataUpdateEnabled) { staticDataTextArea.setCaretPosition(staticDataTextArea.getDocument().getLength()); } } catch (Exception e) { System.err.println("æ¾ç¤ºASCIIæ°æ®æ¶åçé误: " + e.getMessage()); Errlog.logOperation("æ¾ç¤ºASCIIæ°æ®æ¶åçé误: " + e.getMessage()); } }); } @@ -616,14 +589,13 @@ memoryMonitorTimer.stop(); } // å ³éæ¶åæ¢è½®è¯¢ if (lunxun.isPolling()) { lunxun.stopPolling(); } // éè¦ä¿®æ¹ï¼ä¸è¦åæ¢è½®è¯¢ï¼åªæåè°è¯è¾åº lunxun.setDEBUG_ENABLED(false); // 忢䏲壿°æ®æè· // éè¦ä¿®æ¹ï¼ä¸è¦åæ¢ä¸²å£æ°æ®æè·ï¼åªç§»é¤èªå·±çåè° if (serialService != null) { serialService.stopCapture(); // ä½¿ç¨æ°çæ¹æ³ç§»é¤åè°èä¸åæ¢æ´ä¸ªæè· removeDataReceivedCallback(); } // æ¸ çéæå¼ç¨ï¼é²æ¢å åæ³æ¼ @@ -634,4 +606,21 @@ super.dispose(); } // æ°å¢ï¼ç§»é¤æ°æ®æ¥æ¶åè°çæ¹æ³ private void removeDataReceivedCallback() { if (serialService != null) { try { // éè¿åå°æå ¶ä»æ¹å¼ç§»é¤åè°ï¼æè ç®åå°è®¾ç½®ä¸ºnull // è¿éå设SerialPortServiceæç§»é¤åè°çæ¹æ³ serialService.setResponseConsumer(null); } catch (Exception e) { Errlog.logOperation("ç§»é¤æ°æ®æ¥æ¶åè°æ¶åçé误: " + e.getMessage()); } } } // æ°å¢ï¼å¯ç¨/ç¦ç¨è½®è¯¢æ§å¶çæ¹æ³ public static void setPollingControlEnabled(boolean enabled) { } } src/xitongshezhi/kacaoguanli.java
@@ -12,6 +12,7 @@ import java.util.Random; import chushihua.SlotManager; import home.Fkj; public class kacaoguanli extends JDialog { // å±å¹å°ºå¯¸å¸¸é - éé 7寸ç«å± src/xitongshezhi/kuaisuquka.java
@@ -1,5 +1,4 @@ package xitongshezhi; import javax.swing.*; import javax.swing.border.EmptyBorder; import java.awt.*; @@ -10,30 +9,23 @@ import java.util.List; import java.util.Map; // æ°å¢å¯¼å ¥ import publicway.OpenDoor; import chuankou.Sendmsg; import chushihua.SlotManager; import home.Fkj; @SuppressWarnings("serial") public class kuaisuquka extends JDialog { // å±å¹å°ºå¯¸å¸¸é - éé 7寸ç«å± private static final int SCREEN_WIDTH = 600; private static final int SCREEN_HEIGHT = 1024; // æ°å¢ï¼è®°å½è¿å ¥å¿«éåå¡é¡µé¢åçè½®è¯¢ç¶æ private boolean wasPollingRunning = false; private boolean wasPollingPaused = false; // é¢è²å¸¸é private static final Color PRIMARY_COLOR = new Color(52, 152, 219); private static final Color PRIMARY_DARK_COLOR = new Color(41, 128, 185); private static final Color SECONDARY_COLOR = new Color(46, 204, 113); private static final Color DANGER_COLOR = new Color(231, 76, 60); private static final Color WARNING_COLOR = new Color(243, 156, 18); private static final Color DARK_COLOR = new Color(15, 28, 48); private static final Color DARK_LIGHT_COLOR = new Color(26, 43, 68); private static final Color TEXT_COLOR = new Color(224, 224, 224); private static final Color TEXT_LIGHT_COLOR = new Color(160, 200, 255); private static final Color CARD_BG_COLOR = new Color(30, 60, 114, 178); // ä¼åçé¢è²å¸¸é private static final Color BRIGHT_GREEN = new Color(46, 204, 113); // æå¡ - ç»¿è² private static final Color DARK_GRAY = new Color(93, 109, 126); // æ å¡ - æ·±ç°è² @@ -46,16 +38,10 @@ HAS_CARD("{å¡å·}", BRIGHT_GREEN), // å ä½ç¬¦ï¼å®é æ¾ç¤ºæ¶ä¼æ¿æ¢ä¸ºå ·ä½å¡å· NO_CARD("æ å¡", DARK_GRAY); private final String displayName; private final Color color; SlotStatus(String displayName, Color color) { this.displayName = displayName; this.color = color; } public String getDisplayName() { return displayName; } public Color getColor() { @@ -72,34 +58,47 @@ // ç»è®¡ä¿¡æ¯ private JLabel cardsCountLabel; // ä¼åçå¯¹è¯æ¡ç®¡ç private JDialog progressDialog; private JProgressBar progressBar; private JLabel progressLabel; private JDialog resultDialog; // å ±äº«çäºä»¶çå¬å¨ private final SlotButtonListener slotButtonListener; private SlotManager slotManager; private Timer refreshTimer; // æ°å¢ï¼å·æ°å®æ¶å¨ public kuaisuquka(JFrame parent) { super(parent, "å¿«éåå¡", true); slotManager = new SlotManager(); slotButtons = new ArrayList<>(60); slotStatuses = new ArrayList<>(60); slotButtonListener = new SlotButtonListener(); // è®°å½è¿å ¥å¿«éåå¡é¡µé¢åçè½®è¯¢ç¶æ recordPollingStateBeforeEntering(); initializeUI(); initializeSlots(); startAutoRefresh(); // æ°å¢ï¼å¯å¨èªå¨å·æ° startAutoRefresh(); // è¿å ¥å¿«éåå¡é¡µé¢æ¶æå轮询 pausePollingWhenEntering(); // è°è¯ä¿¡æ¯ //System.out.println("å¿«éåå¡é¡µé¢åå§å宿ï¼å¼å§æ¾ç¤ºå¡æ§½ç¶æ"); debugSlotStatus(); } /** * è°è¯æ¹æ³ï¼æå°å¡æ§½ç¶æä¿¡æ¯ */ private void debugSlotStatus() { Fkj[] slotArray = SlotManager.getSlotArray(); if (slotArray == null) { //System.out.println("SlotManager.getSlotArray() è¿å null"); return; } //System.out.println("=== 塿§½ç¶æè°è¯ä¿¡æ¯ ==="); for (int i = 0; i < Math.min(slotArray.length, 60); i++) { Fkj slot = slotArray[i]; if (slot != null) { System.out.printf("塿§½ %d: hasCard=%s, cardNumber=%s%n", i + 1, slot.getHasCard(), slot.getCardNumber()); } else { System.out.printf("塿§½ %d: null%n", i + 1); } } //System.out.println("======================"); } /** @@ -116,74 +115,108 @@ } /** * ä»SlotManagerå·æ°å¡æ§½ç¶æ * ä»SlotManagerå·æ°å¡æ§½ç¶æ - å½»åºéåçæ¬ */ private void refreshSlotStatusFromManager() { boolean statusChanged = false; Fkj[] slotArray = SlotManager.getSlotArray(); for (int i = 0; i < 60; i++) { int slotId = i + 1; String hasCardStatus = SlotManager.getSlotHasCardStatus(slotId); if (slotArray == null) { //System.out.println("å·æ°å¡æ§½ç¶æ: slotArray 为 null"); return; } for (int i = 0; i < 60 && i < slotArray.length; i++) { Fkj slotInfo = slotArray[i]; if (slotInfo == null) { // 妿塿§½ä¿¡æ¯ä¸ºnullï¼è®¾ç½®ä¸ºæ å¡ç¶æ if (i < slotStatuses.size() && slotStatuses.get(i) != SlotStatus.NO_CARD) { slotStatuses.set(i, SlotStatus.NO_CARD); statusChanged = true; } continue; } // æ£æ¥æ¯å¦æå¡å¹¶ä¸æææçå¡å· String hasCardStatus = slotInfo.getHasCard(); String cardNumber = slotInfo.getCardNumber(); // ç®åç夿é»è¾ - éç¹è°è¯ boolean reallyHasCard = false; if ("1".equals(hasCardStatus)) { Fkj slotInfo = slotManager.getSlotInfo(slotId); String cardNumber = slotInfo != null ? slotInfo.getCardNumber() : "-1"; // åªæå½å¡å·ä¸æ¯-1ãnullä¸ä¸ä¸ºç©ºæ¶ï¼æè®¤ä¸ºçæ£æå¡ reallyHasCard = !("-1".equals(cardNumber) && cardNumber != null && !cardNumber.trim().isEmpty()); // 妿hasCard为"1"ï¼è¿ä¸æ¥æ£æ¥å¡å· if (cardNumber != null && !cardNumber.trim().isEmpty()) { // æ¾å®½æ¡ä»¶ï¼åªè¦å¡å·ä¸ä¸ºç©ºä¸ä¸æ¯"0000"å"-1"ï¼å°±è®¤ä¸ºæå¡ reallyHasCard = !"0000".equals(cardNumber) && !"-1".equals(cardNumber); } else { // å¡å·ä¸ºnullæç©ºï¼ä½æå¡ç¶æä¸º1ï¼æ¾ç¤ºä¸ºæå¡ä½å¡å·æªç¥ reallyHasCard = true; } } SlotStatus newStatus = reallyHasCard ? SlotStatus.HAS_CARD : SlotStatus.NO_CARD; SlotStatus currentStatus = slotStatuses.get(i); // æ£æ¥ç¶ææ¯å¦åçåå if (newStatus != currentStatus) { slotStatuses.set(i, newStatus); // ç¡®ä¿slotStatusesæè¶³å¤çå ç´ if (i >= slotStatuses.size()) { slotStatuses.add(newStatus); statusChanged = true; } else { SlotStatus currentStatus = slotStatuses.get(i); if (newStatus != currentStatus) { slotStatuses.set(i, newStatus); statusChanged = true; // è°è¯ç¶æåå System.out.printf("塿§½ %d ç¶æåå: %s -> %s (hasCard=%s, cardNumber=%s)%n", i + 1, currentStatus, newStatus, hasCardStatus, cardNumber); } } // æ´æ°æé®æ¾ç¤º updateSlotButtonDisplay(i, slotInfo, newStatus); } // å¦æç¶æåçååï¼æ´æ°æ¾ç¤º // å¦æç¶æåçååï¼æ´æ°ç»è®¡ä¿¡æ¯ if (statusChanged) { updateCardSlotsDisplay(); updateStatistics(); } else { // å³ä½¿ç¶ææ²¡åï¼ä¹è¦æ£æ¥å¡å·æ¯å¦æ´æ° updateCardSlotsDisplay(); } } /** * è®°å½è¿å ¥å¿«éåå¡é¡µé¢åçè½®è¯¢ç¶æ */ private void recordPollingStateBeforeEntering() { wasPollingRunning = chushihua.lunxun.isPolling(); wasPollingPaused = chushihua.lunxun.isPaused(); //System.out.println("è¿å ¥å¿«éåå¡é¡µé¢ï¼è®°å½è½®è¯¢ç¶æ - è¿è¡: " + wasPollingRunning + ", æå: " + wasPollingPaused); } /** * è¿å ¥å¿«éåå¡é¡µé¢æ¶æå轮询 */ private void pausePollingWhenEntering() { if (chushihua.lunxun.isPolling() && !chushihua.lunxun.isPaused()) { chushihua.lunxun.pausePolling(); //System.out.println("è¿å ¥å¿«éåå¡é¡µé¢ï¼è½®è¯¢å·²æå"); } } /** * éåºå¿«éåå¡é¡µé¢æ¶æ¢å¤è½®è¯¢ */ private void resumePollingWhenExiting() { // åªæè¿å ¥å¿«éåå¡é¡µé¢æ¶è½®è¯¢æ¯è¿è¡ç¶æä¸æªè¢«æåï¼ææ¢å¤è½®è¯¢ if (wasPollingRunning && !wasPollingPaused) { if (chushihua.lunxun.isPolling() && chushihua.lunxun.isPaused()) { chushihua.lunxun.resumePolling(); //System.out.println("éåºå¿«éåå¡é¡µé¢ï¼è½®è¯¢å·²æ¢å¤"); private void updateSlotButtonDisplay(int index, Fkj slotInfo, SlotStatus status) { if (index < 0 || index >= slotButtons.size()) { return; } JButton slotButton = slotButtons.get(index); // æ´æ°æé®èæ¯é¢è² slotButton.setBackground(status.getColor()); // æ´æ°ç¶ææ ç¾ Component[] components = slotButton.getComponents(); for (Component comp : components) { if (comp instanceof JLabel) { JLabel label = (JLabel) comp; // æ¾å°ç¶ææ ç¾ï¼è¾å°çåä½ï¼ if (label.getFont().getSize() == 11) { String displayText; if (status == SlotStatus.HAS_CARD) { // æ¾ç¤ºå®é å¡å·ï¼å¦æå¡å·æ æåæ¾ç¤º"æå¡" String cardNumber = slotInfo.getCardNumber(); if (cardNumber != null && !cardNumber.trim().isEmpty() && !"0000".equals(cardNumber) && !"-1".equals(cardNumber)) { displayText = cardNumber; } else { displayText = "æå¡"; } } else { displayText = "æ å¡"; } label.setText(displayText); break; } } } else { //System.out.println("éåºå¿«éåå¡é¡µé¢ï¼ä¿æåæè½®è¯¢ç¶æ - è¿è¡: " + wasPollingRunning + ", æå: " + wasPollingPaused); } } @@ -285,7 +318,6 @@ openAllButton.setForeground(Color.WHITE); openAllButton.setFocusPainted(false); openAllButton.setBorder(BorderFactory.createEmptyBorder(12, 24, 12, 24)); openAllButton.setIcon(getCachedIcon("ðª", 20)); openAllButton.addActionListener(e -> openAllSlots()); // æ·»å æ¬åææ @@ -347,53 +379,98 @@ } private void initializeSlots() { // ä» SlotManager è·å塿§½ç¶æ for (int i = 0; i < 60; i++) { int slotId = i + 1; String hasCardStatus = SlotManager.getSlotHasCardStatus(slotId); // æ£æ¥æ¯å¦æå¡å¹¶ä¸æææçå¡å· boolean reallyHasCard = false; if ("1".equals(hasCardStatus)) { Fkj slotInfo = slotManager.getSlotInfo(slotId); String cardNumber = slotInfo != null ? slotInfo.getCardNumber() : "-1"; // åªæå½å¡å·ä¸æ¯-1ãnullä¸ä¸ä¸ºç©ºæ¶ï¼æè®¤ä¸ºçæ£æå¡ reallyHasCard = !("-1".equals(cardNumber) && cardNumber != null && !cardNumber.trim().isEmpty()); // æ¸ ç©ºç°æç¶æ slotStatuses.clear(); // ç´æ¥ä» SlotManager è·åææ°æ°æ® Fkj[] slotArray = SlotManager.getSlotArray(); //System.out.println("åå§å塿§½ç¶æï¼slotArray: " + (slotArray != null ? "é空" : "空")); if (slotArray != null) { for (int i = 0; i < 60 && i < slotArray.length; i++) { Fkj slotInfo = slotArray[i]; SlotStatus status = SlotStatus.NO_CARD; if (slotInfo != null) { String hasCardStatus = slotInfo.getHasCard(); String cardNumber = slotInfo.getCardNumber(); // ç®åç夿é»è¾ boolean reallyHasCard = false; if ("1".equals(hasCardStatus)) { if (cardNumber != null && !cardNumber.trim().isEmpty()) { reallyHasCard = !"0000".equals(cardNumber) && !"-1".equals(cardNumber); } else { // å¡å·ä¸ºnullæç©ºï¼ä½æå¡ç¶æä¸º1ï¼æ¾ç¤ºä¸ºæå¡ reallyHasCard = true; } } status = reallyHasCard ? SlotStatus.HAS_CARD : SlotStatus.NO_CARD; // è°è¯åå ä¸ªå¡æ§½ if (i < 5) { System.out.printf("åå§å塿§½ %d: hasCard=%s, cardNumber=%s, å¤æä¸º: %s%n", i + 1, hasCardStatus, cardNumber, status); } } slotStatuses.add(status); } SlotStatus status = reallyHasCard ? SlotStatus.HAS_CARD : SlotStatus.NO_CARD; slotStatuses.add(status); } else { // 妿slotArray为nullï¼å ¨é¨åå§å为æ å¡ //System.out.println("slotArray为nullï¼å ¨é¨åå§å为æ å¡"); for (int i = 0; i < 60; i++) { slotStatuses.add(SlotStatus.NO_CARD); } } createCardSlots(); updateStatistics(); // ç«å³å·æ°ä¸æ¬¡ç¶æ refreshSlotStatusFromManager(); } private void createCardSlots() { cardSlotsPanel.removeAll(); slotButtons.clear(); Fkj[] slotArray = SlotManager.getSlotArray(); for (int i = 0; i < 60; i++) { final int slotId = i + 1; SlotStatus status = slotStatuses.get(i); // è·åå½å塿§½çå®é ç¶æ Fkj slotInfo = null; if (slotArray != null && i < slotArray.length) { slotInfo = slotArray[i]; } SlotStatus currentStatus = i < slotStatuses.size() ? slotStatuses.get(i) : SlotStatus.NO_CARD; // å建 final 坿¬ç¨äºå é¨ç±» final SlotStatus finalStatus = currentStatus; JButton slotButton = new JButton(); slotButton.setLayout(new BorderLayout()); slotButton.setBackground(status.getColor()); slotButton.setBackground(currentStatus.getColor()); slotButton.setForeground(Color.WHITE); slotButton.setFocusPainted(false); slotButton.setBorder(BorderFactory.createEmptyBorder(10, 5, 10, 5)); // æ·»å é¼ æ æ¬åææ // æ·»å é¼ æ æ¬åææ - ä½¿ç¨ finalStatus è䏿¯ status slotButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { if (status == SlotStatus.HAS_CARD) { slotButton.setBackground(brighterColor(status.getColor())); if (finalStatus == SlotStatus.HAS_CARD) { slotButton.setBackground(brighterColor(finalStatus.getColor())); } } public void mouseExited(java.awt.event.MouseEvent evt) { slotButton.setBackground(status.getColor()); slotButton.setBackground(finalStatus.getColor()); } }); @@ -402,14 +479,16 @@ slotIdLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 16)); slotIdLabel.setForeground(Color.WHITE); // 塿§½ç¶æ - ä¿®æ¹ï¼æå¡æ¶æ¾ç¤ºå¡å·ï¼æ 塿¶æ¾ç¤º"æ å¡" // 塿§½ç¶æ - æ ¹æ®å®é ç¶ææ¾ç¤º String displayText; if (status == SlotStatus.HAS_CARD) { // ä»SlotManagerè·åå¡å· Fkj slotInfo = slotManager.getSlotInfo(slotId); String cardNumber = slotInfo != null ? slotInfo.getCardNumber() : "-1"; // æ¾ç¤ºå®é å¡å· displayText = cardNumber; if (currentStatus == SlotStatus.HAS_CARD && slotInfo != null) { String cardNumber = slotInfo.getCardNumber(); if (cardNumber != null && !cardNumber.trim().isEmpty() && !"0000".equals(cardNumber) && !"-1".equals(cardNumber)) { displayText = cardNumber; } else { displayText = "æå¡"; } } else { displayText = "æ å¡"; } @@ -447,14 +526,7 @@ JLabel label = (JLabel) comp; try { int slotId = Integer.parseInt(label.getText()); SlotStatus status = slotStatuses.get(slotId - 1); // å¦ææ¯æå¡ç¶æï¼æ§è¡åå¡æä½ if (status == SlotStatus.HAS_CARD) { takeCard(slotId); } // åéå¼é¨æä»¤ï¼ä¸ç®¡æ¯å¦æå¡ï¼ sendOpenDoorCommand(slotId); Sendmsg.opendoorzhiling(slotId,2); break; } catch (NumberFormatException ex) { // 忽ç¥éæ°åæ ç¾ @@ -464,249 +536,23 @@ } } // æ°å¢æ¹æ³ï¼åéåä¸ªå¡æ§½å¼é¨æä»¤ private void sendOpenDoorCommand(int slotId) { try { // çæå¼é¨æä»¤ String command = OpenDoor.openOneDoor(slotId, OpenDoor.TYPE_ADMIN); // åé䏲壿令 boolean sent = Sendmsg.sendMessage(command); if (sent) { //System.out.println("æååéå¼é¨æä»¤å°å¡æ§½ " + slotId); } else { System.err.println("åéå¼é¨æä»¤å°å¡æ§½ " + slotId + " 失败"); } } catch (Exception e) { System.err.println("çæå¼é¨æä»¤å¤±è´¥: " + e.getMessage()); e.printStackTrace(); } } private void takeCard(int slotId) { int index = slotId - 1; // æ´æ°å¡æ§½ç¶æä¸ºæ å¡ slotStatuses.set(index, SlotStatus.NO_CARD); // è°ç¨ SlotManager çchanggehaskaæ¹æ³æ´æ°ç¶æ SlotManager.changgehaska(slotId, "1"); // "1"表示管çåæä½ updateCardSlotsDisplay(); updateStatistics(); } // ä¼åç塿§½æ¾ç¤ºæ´æ° // ä¿®æ¹æ´æ°å¡æ§½æ¾ç¤ºçæ¹æ³ private void updateCardSlotsDisplay() { for (int i = 0; i < 60; i++) { JButton slotButton = slotButtons.get(i); SlotStatus status = slotStatuses.get(i); // åªæ´æ°æ¹åçç¶æ if (!slotButton.getBackground().equals(status.getColor())) { slotButton.setBackground(status.getColor()); } // æ´æ°ç¶ææ ç¾ - ä¿®æ¹ï¼æå¡æ¶æ¾ç¤ºå¡å·ï¼æ 塿¶æ¾ç¤º"æ å¡" Component[] components = slotButton.getComponents(); for (Component comp : components) { if (comp instanceof JLabel) { JLabel label = (JLabel) comp; // æ¾å°ç¶ææ ç¾ï¼è¾å°çåä½ï¼ if (label.getFont().getSize() == 11) { String displayText; if (status == SlotStatus.HAS_CARD) { // ä»SlotManagerè·åå¡å· Fkj slotInfo = slotManager.getSlotInfo(i + 1); String cardNumber = slotInfo != null ? slotInfo.getCardNumber() : "-1"; // æ¾ç¤ºå®é å¡å· displayText = cardNumber; } else { displayText = "æ å¡"; } label.setText(displayText); break; } } } } cardSlotsPanel.revalidate(); cardSlotsPanel.repaint(); } private void openAllSlots() { int openedCount = 0; // æ´æ°æææå¡å¡æ§½ä¸ºæ å¡ for (int i = 0; i < slotStatuses.size(); i++) { if (slotStatuses.get(i) == SlotStatus.HAS_CARD) { slotStatuses.set(i, SlotStatus.NO_CARD); // è°ç¨ SlotManager çchanggehaskaæ¹æ³æ´æ°ç¶æ SlotManager.changgehaska(i + 1, "1"); // "1"表示管çåæä½ openedCount++; } } if (openedCount > 0) { updateCardSlotsDisplay(); updateStatistics(); } // ä¿®æ¹ï¼ç´æ¥è°ç¨ä¸²å£åéæ¹æ³ï¼ä¸æ¾ç¤ºè¿åº¦å¯¹è¯æ¡ openAllSlotsWithSerialCommands(openedCount); } // æ°å¢æ¹æ³ï¼éè¿ä¸²å£åéå¼é¨æä»¤ private void openAllSlotsWithSerialCommands(int openedCount) { // ä¿®æ¹ï¼ç´æ¥è°ç¨OpenDoorç弿¥å¼é¨æ¹æ³ï¼ä¸æ¾ç¤ºè¿åº¦å¯¹è¯æ¡ OpenDoor.openAllSlotsAsync(60, 250, OpenDoor.TYPE_ADMIN, new OpenDoor.OpenDoorCallback() { @Override public void onProgress(int currentSlot, int totalSlots, String command) { // åé䏲壿令 boolean sent = Sendmsg.sendMessage(command); if (!sent) { System.err.println("åéæä»¤å¤±è´¥: " + command); } } @Override public void onComplete(String[] commands) { SwingUtilities.invokeLater(() -> { String message; if (openedCount > 0) { message = "å·²æåæå¼å ¨é¨ " + openedCount + " 个æå¡å¡æ§½\nåéäº " + commands.length + " æ¡å¼é¨æä»¤"; } else { message = "å·²åé " + commands.length + " æ¡å¼é¨æä»¤å°ææå¡æ§½"; } showResultDialog("success", "æä½æå", message); }); } @Override public void onError(Exception error) { SwingUtilities.invokeLater(() -> { showResultDialog("error", "æä½å¤±è´¥", "åéå¼é¨æä»¤æ¶åçé误: " + error.getMessage()); error.printStackTrace(); }); } }); private void openAllSlots() { Sendmsg.openAllSlots(2); } // ä¼åçç»è®¡è®¡ç® private void updateStatistics() { int hasCardCount = 0; for (SlotStatus status : slotStatuses) { if (status == SlotStatus.HAS_CARD) { for (int i = 0; i < 60 && i < slotStatuses.size(); i++) { if (slotStatuses.get(i) == SlotStatus.HAS_CARD) { hasCardCount++; } } cardsCountLabel.setText("æå¡: " + hasCardCount + "/60"); } // ä¼åçç»æå¯¹è¯æ¡æ¾ç¤º private void showResultDialog(String type, String title, String message) { if (resultDialog == null) { createResultDialog(); } updateResultDialog(type, title, message); resultDialog.setVisible(true); } private void createResultDialog() { resultDialog = new JDialog(this, "", true); resultDialog.setSize(400, 250); resultDialog.setLocationRelativeTo(this); resultDialog.setResizable(false); resultDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE); JPanel contentPanel = new JPanel(); contentPanel.setLayout(new BorderLayout()); contentPanel.setBorder(new EmptyBorder(25, 25, 25, 25)); contentPanel.setBackground(DARK_LIGHT_COLOR); // 徿 åæ é¢ JPanel headerPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); headerPanel.setOpaque(false); JLabel iconLabel = new JLabel(); iconLabel.setFont(new Font("Segoe UI Emoji", Font.PLAIN, 32)); JLabel titleLabel = new JLabel(); titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 20)); titleLabel.setForeground(TEXT_COLOR); headerPanel.add(iconLabel); headerPanel.add(Box.createRigidArea(new Dimension(10, 0))); headerPanel.add(titleLabel); // æ¶æ¯å 容 JLabel messageLabel = new JLabel(); messageLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); messageLabel.setForeground(TEXT_LIGHT_COLOR); messageLabel.setHorizontalAlignment(SwingConstants.CENTER); messageLabel.setBorder(new EmptyBorder(15, 0, 25, 0)); // ç¡®å®æé® JButton confirmButton = new JButton("ç¡®å®"); confirmButton.setFont(new Font("Microsoft YaHei", Font.BOLD, 14)); confirmButton.setBackground(SECONDARY_COLOR); confirmButton.setForeground(Color.WHITE); confirmButton.setFocusPainted(false); confirmButton.setBorder(BorderFactory.createEmptyBorder(10, 30, 10, 30)); confirmButton.addActionListener(e -> resultDialog.dispose()); // æ·»å æ¬åææ confirmButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { confirmButton.setBackground(brighterColor(SECONDARY_COLOR)); } public void mouseExited(java.awt.event.MouseEvent evt) { confirmButton.setBackground(SECONDARY_COLOR); } }); JPanel buttonPanel = new JPanel(); buttonPanel.setOpaque(false); buttonPanel.add(confirmButton); contentPanel.add(headerPanel, BorderLayout.NORTH); contentPanel.add(messageLabel, BorderLayout.CENTER); contentPanel.add(buttonPanel, BorderLayout.SOUTH); resultDialog.add(contentPanel); } private void updateResultDialog(String type, String title, String message) { resultDialog.setTitle(title); Component[] components = ((JPanel)resultDialog.getContentPane().getComponent(0)).getComponents(); // æ´æ°å¾æ åæ é¢ JPanel headerPanel = (JPanel) components[0]; JLabel iconLabel = (JLabel) headerPanel.getComponent(0); JLabel titleLabel = (JLabel) headerPanel.getComponent(2); if ("success".equals(type)) { iconLabel.setText("â "); } else if ("warning".equals(type)) { iconLabel.setText("â ï¸"); } else if ("error".equals(type)) { iconLabel.setText("â"); } else { iconLabel.setText("â¹ï¸"); } titleLabel.setText(title); // æ´æ°æ¶æ¯ JLabel messageLabel = (JLabel) components[1]; messageLabel.setText("<html><div style='text-align: center;'>" + message.replace("\n", "<br>") + "</div></html>"); // è°è¯ç»è®¡ä¿¡æ¯ //System.out.println("æ´æ°ç»è®¡ä¿¡æ¯: æå¡ " + hasCardCount + "/60"); } private Color brighterColor(Color color) { @@ -756,19 +602,10 @@ if (slotStatuses != null) { slotStatuses.clear(); } if (progressDialog != null) { progressDialog.dispose(); progressDialog = null; } if (resultDialog != null) { resultDialog.dispose(); resultDialog = null; } // æ¢å¤è½®è¯¢ç¶æ resumePollingWhenExiting(); super.dispose(); //System.out.println("å¿«éåå¡é¡µé¢å·²å ³é"); } // éææ¹æ³ï¼ä»ç³»ç»è®¾ç½®é¡µé¢è°ç¨ src/xitongshezhi/lishijilu.java
@@ -17,20 +17,27 @@ private static final Color DARK_LIGHT_COLOR = new Color(26, 43, 68); private static final Color TEXT_COLOR = new Color(224, 224, 224); private static final Color TEXT_LIGHT_COLOR = new Color(160, 200, 255); private static final Color DELETE_COLOR = new Color(231, 76, 60); // å 餿é®é¢è² private static final Color ACTIVE_BUTTON_COLOR = new Color(41, 128, 185); // æ¿æ´»æé®é¢è² private JPanel mainPanel; private JLabel titleLabel; private JButton logButton; // æ¥å¿è®°å½æé® private JButton errorLogButton; // é误æ¥å¿æé® private JButton backButton; private JButton deleteAllButton; // ææ¬åç»ä»¶ private JScrollPane textScrollPane; private JTextArea contentTextArea; // å½åæ¾ç¤ºçæ¥å¿ç±»å private String currentLogType = "log"; // "log" æ "error" public lishijilu(JFrame parent) { super(parent, "", true); initializeUI(); setupEventListeners(); loadLogContent(); // å è½½æ¥å¿å 容 loadLogContent(); // é»è®¤å è½½æä½æ¥å¿ } private void initializeUI() { @@ -71,12 +78,48 @@ headerPanel.setOpaque(false); headerPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 12, 0)); // æ é¢ titleLabel = new JLabel("åå²è®°å½"); titleLabel.setFont(new Font("Microsoft YaHei", Font.BOLD, 22)); titleLabel.setForeground(TEXT_COLOR); // å建æ¥å¿ç±»åéæ©æé®é¢æ¿ JPanel logTypePanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 8, 0)); logTypePanel.setOpaque(false); // è¿åæé® - 使ç¨ä¸éæè®¾è®¡ // æ¥å¿è®°å½æé® logButton = new JButton("æ¥å¿è®°å½"); logButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); logButton.setBackground(ACTIVE_BUTTON_COLOR); // é»è®¤æ¿æ´»ç¶æ logButton.setForeground(Color.WHITE); logButton.setOpaque(true); logButton.setFocusPainted(false); logButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16)); logButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); // é误æ¥å¿æé® errorLogButton = new JButton("é误æ¥å¿"); errorLogButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); errorLogButton.setBackground(PRIMARY_COLOR); // é»è®¤éæ¿æ´»ç¶æ errorLogButton.setForeground(Color.WHITE); errorLogButton.setOpaque(true); errorLogButton.setFocusPainted(false); errorLogButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16)); errorLogButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); logTypePanel.add(logButton); logTypePanel.add(errorLogButton); // æä½æé®é¢æ¿ JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 8, 0)); actionButtonPanel.setOpaque(false); // å é¤å ¨é¨è®°å½æé® deleteAllButton = new JButton("å é¤å ¨é¨"); deleteAllButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); deleteAllButton.setBackground(DELETE_COLOR); deleteAllButton.setForeground(Color.WHITE); deleteAllButton.setOpaque(true); deleteAllButton.setFocusPainted(false); deleteAllButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16)); deleteAllButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); // è¿åæé® backButton = new JButton("å ³é"); backButton.setFont(new Font("Microsoft YaHei", Font.PLAIN, 14)); backButton.setBackground(PRIMARY_COLOR); @@ -85,6 +128,60 @@ backButton.setFocusPainted(false); backButton.setBorder(BorderFactory.createEmptyBorder(8, 16, 8, 16)); backButton.setCursor(new Cursor(Cursor.HAND_CURSOR)); actionButtonPanel.add(deleteAllButton); actionButtonPanel.add(backButton); // æé®æ¬åææ setupButtonHoverEffects(); headerPanel.add(logTypePanel, BorderLayout.WEST); headerPanel.add(actionButtonPanel, BorderLayout.EAST); return headerPanel; } private void setupButtonHoverEffects() { // æ¥å¿æé®æ¬åææ logButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { if (!currentLogType.equals("log")) { logButton.setBackground(brighterColor(PRIMARY_COLOR)); } } public void mouseExited(java.awt.event.MouseEvent evt) { if (!currentLogType.equals("log")) { logButton.setBackground(PRIMARY_COLOR); } } }); // é误æ¥å¿æé®æ¬åææ errorLogButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { if (!currentLogType.equals("error")) { errorLogButton.setBackground(brighterColor(PRIMARY_COLOR)); } } public void mouseExited(java.awt.event.MouseEvent evt) { if (!currentLogType.equals("error")) { errorLogButton.setBackground(PRIMARY_COLOR); } } }); // å 餿鮿¬åææ deleteAllButton.addMouseListener(new java.awt.event.MouseAdapter() { public void mouseEntered(java.awt.event.MouseEvent evt) { deleteAllButton.setBackground(brighterColor(DELETE_COLOR)); } public void mouseExited(java.awt.event.MouseEvent evt) { deleteAllButton.setBackground(DELETE_COLOR); } }); // è¿åæé®æ¬åææ backButton.addMouseListener(new java.awt.event.MouseAdapter() { @@ -96,19 +193,6 @@ backButton.setBackground(PRIMARY_COLOR); } }); JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); titlePanel.setOpaque(false); titlePanel.add(titleLabel); JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT)); buttonPanel.setOpaque(false); buttonPanel.add(backButton); headerPanel.add(titlePanel, BorderLayout.WEST); headerPanel.add(buttonPanel, BorderLayout.EAST); return headerPanel; } private JPanel createContentPanel() { @@ -177,37 +261,138 @@ backButton.addActionListener(e -> { dispose(); }); // å é¤å ¨é¨è®°å½æé® deleteAllButton.addActionListener(e -> { deleteAllRecords(); }); // æ¥å¿è®°å½æé® logButton.addActionListener(e -> { switchToLogType("log"); }); // é误æ¥å¿æé® errorLogButton.addActionListener(e -> { switchToLogType("error"); }); } // 忢æ¥å¿ç±»å private void switchToLogType(String logType) { if (currentLogType.equals(logType)) { return; // å·²ç»æ¯å½åç±»åï¼æ é忢 } currentLogType = logType; // æ´æ°æé®ç¶æ if (logType.equals("log")) { logButton.setBackground(ACTIVE_BUTTON_COLOR); errorLogButton.setBackground(PRIMARY_COLOR); } else { logButton.setBackground(PRIMARY_COLOR); errorLogButton.setBackground(ACTIVE_BUTTON_COLOR); } // å 载对åºç±»åçæ¥å¿å 容 loadLogContent(); } // å é¤å ¨é¨è®°å½çæ¹æ³ private void deleteAllRecords() { // ç¡®è®¤å¯¹è¯æ¡ String logTypeName = currentLogType.equals("log") ? "æä½" : "é误"; int result = JOptionPane.showConfirmDialog( this, "ç¡®å®è¦å 餿æ" + logTypeName + "è®°å½åï¼æ¤æä½ä¸å¯æ¢å¤ï¼", "确认å é¤", JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE ); if (result == JOptionPane.YES_OPTION) { try { String fileName = currentLogType.equals("log") ? "log.properties" : "err.properties"; File logFile = new File(fileName); if (logFile.exists()) { // å建空çProperties对象并åå ¥æä»¶ Properties emptyProps = new Properties(); try (FileOutputStream out = new FileOutputStream(logFile); OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) { emptyProps.store(writer, "å塿º" + logTypeName + "è®°å½ - ææè®°å½å·²æ¸ 空"); } // æ´æ°ææ¬åæ¾ç¤º contentTextArea.setText("ææ" + logTypeName + "è®°å½å·²æåå é¤ã\n\næ¥å¿æä»¶å·²æ¸ 空ã"); // æ¾ç¤ºæåæ¶æ¯ JOptionPane.showMessageDialog( this, "ææ" + logTypeName + "è®°å½å·²æåå é¤ã", "å 餿å", JOptionPane.INFORMATION_MESSAGE ); } else { contentTextArea.setText(logTypeName + "æ¥å¿æä»¶ä¸åå¨ï¼æ éå é¤ã"); } } catch (IOException ex) { ex.printStackTrace(); JOptionPane.showMessageDialog( this, "å é¤è®°å½æ¶åºé: " + ex.getMessage(), "é误", JOptionPane.ERROR_MESSAGE ); } } } // å è½½æ¥å¿å 容 private void loadLogContent() { File logFile = new File("log.properties"); String fileName = currentLogType.equals("log") ? "log.properties" : "err.properties"; String logTypeName = currentLogType.equals("log") ? "æä½" : "é误"; File logFile = new File(fileName); if (!logFile.exists()) { contentTextArea.setText("æ¥å¿æä»¶ä¸åå¨ã"); contentTextArea.setText(logTypeName + "æ¥å¿æä»¶ä¸åå¨ã"); return; } Properties logProps = new Properties(); try (FileInputStream in = new FileInputStream(logFile)) { logProps.load(in); try (FileInputStream in = new FileInputStream(logFile); InputStreamReader reader = new InputStreamReader(in, "UTF-8")) { logProps.load(reader); // æ£æ¥è®°å½æ°éï¼å¦æè¶ è¿1000æ¡åå 餿§è®°å½ if (logProps.size() > 1000) { trimLogProperties(logProps); trimLogProperties(logProps, fileName); } // æå»ºæ¾ç¤ºå 容 StringBuilder content = new StringBuilder(); content.append("æ¥å¿æä»¶å 容 (").append(logProps.size()).append(" æ¡è®°å½):\n\n"); content.append(logTypeName).append("æ¥å¿å 容 (").append(logProps.size()).append(" æ¡è®°å½):\n\n"); // ææ¶é´æ³æåºæ¾ç¤º logProps.stringPropertyNames().stream() .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a))) .sorted((a, b) -> { try { // ä»é®ä¸æåæ¶é´æ³é¨åè¿è¡æ¯è¾ long timeA = extractTimestampFromKey(a); long timeB = extractTimestampFromKey(b); return Long.compare(timeB, timeA); // éåºæåï¼ææ°çå¨å } catch (Exception e) { return b.compareTo(a); // 妿æå失败ï¼ä½¿ç¨å符串æ¯è¾ } }) .forEach(key -> { String value = logProps.getProperty(key); content.append("æ¶é´æ³: ").append(key).append("\n"); content.append("å 容: ").append(value).append("\n"); content.append("æ¶é´: ").append(extractTimeFromValue(value)).append("\n"); content.append("å 容: ").append(extractOperationFromValue(value)).append("\n"); content.append("----------------------------------------\n"); }); @@ -215,23 +400,71 @@ } catch (IOException e) { e.printStackTrace(); contentTextArea.setText("å è½½æ¥å¿æä»¶æ¶åºé: " + e.getMessage()); } catch (NumberFormatException e) { contentTextArea.setText("æ¥å¿æä»¶æ ¼å¼é误ã"); contentTextArea.setText("å è½½" + logTypeName + "æ¥å¿æä»¶æ¶åºé: " + e.getMessage()); } catch (Exception e) { e.printStackTrace(); contentTextArea.setText("å¤ç" + logTypeName + "æ¥å¿å 容æ¶åºé: " + e.getMessage()); } } // ä»é®ä¸æåæ¶é´æ³ private long extractTimestampFromKey(String key) { try { // é®çæ ¼å¼: log_æ¶é´æ³_UUID æ error_æ¶é´æ³_UUID String[] parts = key.split("_"); if (parts.length >= 2) { return Long.parseLong(parts[1]); } } catch (Exception e) { // å¦æè§£æå¤±è´¥ï¼è¿å0 } return 0L; } // ä»å¼ä¸æåæ¶é´é¨å private String extractTimeFromValue(String value) { if (value == null) return "æªç¥æ¶é´"; // å¼çæ ¼å¼: [2025-11-21 14:44:39] å塿ä½ï¼å¡æ§½19被管çååå¡ int start = value.indexOf('['); int end = value.indexOf(']'); if (start >= 0 && end > start) { return value.substring(start + 1, end); } return value; } // ä»å¼ä¸æåæä½é¨å private String extractOperationFromValue(String value) { if (value == null) return "æªç¥å 容"; // å¼çæ ¼å¼: [2025-11-21 14:44:39] å塿ä½ï¼å¡æ§½19被管çååå¡ int end = value.indexOf(']'); if (end >= 0 && end + 1 < value.length()) { return value.substring(end + 1).trim(); } return value; } // ä¿®åªæ¥å¿å±æ§ï¼åªä¿çææ°ç1000æ¡è®°å½ private void trimLogProperties(Properties logProps) { private void trimLogProperties(Properties logProps, String fileName) { // ææ¶é´æ³æåºï¼ä¿çææ°ç1000æ¡ logProps.stringPropertyNames().stream() .sorted((a, b) -> Long.compare(Long.parseLong(b), Long.parseLong(a))) .sorted((a, b) -> { try { long timeA = extractTimestampFromKey(a); long timeB = extractTimestampFromKey(b); return Long.compare(timeB, timeA); } catch (Exception e) { return b.compareTo(a); } }) .skip(1000) .forEach(logProps::remove); // ä¿åä¿®åªåç屿§ try (FileOutputStream out = new FileOutputStream("log.properties")) { logProps.store(out, "UWB人åå®ä½å¡å塿ºåå²è®°å½ - èªå¨ä¿®åªè³1000æ¡è®°å½"); try (FileOutputStream out = new FileOutputStream(fileName); OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8")) { String logTypeName = fileName.equals("log.properties") ? "æä½" : "é误"; logProps.store(writer, "å塿º" + logTypeName + "è®°å½ - èªå¨ä¿®åªè³1000æ¡è®°å½"); } catch (IOException e) { e.printStackTrace(); } @@ -252,5 +485,4 @@ dialog.setVisible(true); }); } }