张世豪
昨天 7be65a0428a4527889b6955c56aafdb81dda28a8
开启状态线程,优化结束程序逻辑
已修改11个文件
403 ■■■■ 文件已修改
bin/chuankou/SerialPortConnectionDialog$1.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/SerialPortConnectionDialog.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/CardMachineUI$1.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/CardMachineUI.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/Homein.class 补丁 | 查看 | 原始文档 | blame | 历史
err.properties 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
log.properties 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialPortConnectionDialog.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/home/CardMachineUI.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/home/Homein.java 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/jiekou/lunxunkazhuangtai.java 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/SerialPortConnectionDialog$1.class
Binary files differ
bin/chuankou/SerialPortConnectionDialog.class
Binary files differ
bin/home/CardMachineUI$1.class
Binary files differ
bin/home/CardMachineUI.class
Binary files differ
bin/home/Homein.class
Binary files differ
err.properties
@@ -1,10 +1,2 @@
#\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连续失败次数过多,暂停轮询
#\u53D1\u5361\u673A\u9519\u8BEF\u8BB0\u5F55 - \u6240\u6709\u8BB0\u5F55\u5DF2\u6E05\u7A7A
#Fri Nov 21 19:35:34 CST 2025
log.properties
@@ -1,33 +1,67 @@
#\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被管理员取卡
#\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Fri Nov 21 19:36:06 CST 2025
#Fri Nov 21 19:36:06 CST 2025
log_1763724957486_7ed8425e=[2025-11-21 19\:35\:57] 取卡操作:卡槽1被管理员取卡
log_1763724957585_8967e0b2=[2025-11-21 19\:35\:57] 取卡操作:卡槽2被管理员取卡
log_1763724957735_6574dba5=[2025-11-21 19\:35\:57] 取卡操作:卡槽3被管理员取卡
log_1763724957835_0f410589=[2025-11-21 19\:35\:57] 取卡操作:卡槽4被管理员取卡
log_1763724957935_854f0c49=[2025-11-21 19\:35\:57] 取卡操作:卡槽5被管理员取卡
log_1763724958035_36f51e22=[2025-11-21 19\:35\:58] 取卡操作:卡槽6被管理员取卡
log_1763724958135_0945adfb=[2025-11-21 19\:35\:58] 取卡操作:卡槽7被管理员取卡
log_1763724958235_280878bc=[2025-11-21 19\:35\:58] 取卡操作:卡槽8被管理员取卡
log_1763724958335_62c3daf7=[2025-11-21 19\:35\:58] 取卡操作:卡槽9被管理员取卡
log_1763724958435_09f4db94=[2025-11-21 19\:35\:58] 取卡操作:卡槽10被管理员取卡
log_1763724958534_066792c4=[2025-11-21 19\:35\:58] 取卡操作:卡槽11被管理员取卡
log_1763724958635_6099e667=[2025-11-21 19\:35\:58] 取卡操作:卡槽12被管理员取卡
log_1763724958735_83166056=[2025-11-21 19\:35\:58] 取卡操作:卡槽13被管理员取卡
log_1763724958834_1765f7e9=[2025-11-21 19\:35\:58] 取卡操作:卡槽14被管理员取卡
log_1763724958935_e316b9ce=[2025-11-21 19\:35\:58] 取卡操作:卡槽15被管理员取卡
log_1763724959085_65c537e7=[2025-11-21 19\:35\:59] 取卡操作:卡槽16被管理员取卡
log_1763724959134_aa6dc9d6=[2025-11-21 19\:35\:59] 取卡操作:卡槽17被管理员取卡
log_1763724959285_77b24bbc=[2025-11-21 19\:35\:59] 取卡操作:卡槽18被管理员取卡
log_1763724959385_64338885=[2025-11-21 19\:35\:59] 取卡操作:卡槽19被管理员取卡
log_1763724959486_5916ce74=[2025-11-21 19\:35\:59] 取卡操作:卡槽20被管理员取卡
log_1763724959585_6384a4cc=[2025-11-21 19\:35\:59] 取卡操作:卡槽21被管理员取卡
log_1763724959685_7d45eb0b=[2025-11-21 19\:35\:59] 取卡操作:卡槽22被管理员取卡
log_1763724959786_4aa7ca6f=[2025-11-21 19\:35\:59] 取卡操作:卡槽23被管理员取卡
log_1763724959885_da92954b=[2025-11-21 19\:35\:59] 取卡操作:卡槽24被管理员取卡
log_1763724959985_277f652c=[2025-11-21 19\:35\:59] 取卡操作:卡槽25被管理员取卡
log_1763724960086_aa7cf203=[2025-11-21 19\:36\:00] 取卡操作:卡槽26被管理员取卡
log_1763724960185_2848a5cc=[2025-11-21 19\:36\:00] 取卡操作:卡槽27被管理员取卡
log_1763724960287_3b4bb2ab=[2025-11-21 19\:36\:00] 取卡操作:卡槽28被管理员取卡
log_1763724960386_f261ef41=[2025-11-21 19\:36\:00] 取卡操作:卡槽29被管理员取卡
log_1763724960535_97afbeaf=[2025-11-21 19\:36\:00] 取卡操作:卡槽30被管理员取卡
log_1763724960634_8c0920c2=[2025-11-21 19\:36\:00] 取卡操作:卡槽31被管理员取卡
log_1763724960735_06ce365d=[2025-11-21 19\:36\:00] 取卡操作:卡槽32被管理员取卡
log_1763724960835_cbfa348a=[2025-11-21 19\:36\:00] 取卡操作:卡槽33被管理员取卡
log_1763724960934_0e4d07c0=[2025-11-21 19\:36\:00] 取卡操作:卡槽34被管理员取卡
log_1763724961035_8b4bd8fe=[2025-11-21 19\:36\:01] 取卡操作:卡槽35被管理员取卡
log_1763724961135_0b4d5de9=[2025-11-21 19\:36\:01] 取卡操作:卡槽36被管理员取卡
log_1763724961236_a767eee0=[2025-11-21 19\:36\:01] 取卡操作:卡槽37被管理员取卡
log_1763724961335_822c08d8=[2025-11-21 19\:36\:01] 取卡操作:卡槽38被管理员取卡
log_1763724961435_db3ec62e=[2025-11-21 19\:36\:01] 取卡操作:卡槽39被管理员取卡
log_1763724961534_5fefc851=[2025-11-21 19\:36\:01] 取卡操作:卡槽40被管理员取卡
log_1763724961635_e21db5ef=[2025-11-21 19\:36\:01] 取卡操作:卡槽41被管理员取卡
log_1763724961735_a48231c4=[2025-11-21 19\:36\:01] 取卡操作:卡槽42被管理员取卡
log_1763724961836_be19a1e4=[2025-11-21 19\:36\:01] 取卡操作:卡槽43被管理员取卡
log_1763724961935_d9a52997=[2025-11-21 19\:36\:01] 取卡操作:卡槽44被管理员取卡
log_1763724962085_81151e8b=[2025-11-21 19\:36\:02] 取卡操作:卡槽45被管理员取卡
log_1763724962186_40dd031b=[2025-11-21 19\:36\:02] 取卡操作:卡槽46被管理员取卡
log_1763724962285_2b8f9092=[2025-11-21 19\:36\:02] 取卡操作:卡槽47被管理员取卡
log_1763724962385_8abe459c=[2025-11-21 19\:36\:02] 取卡操作:卡槽48被管理员取卡
log_1763724962485_852ad173=[2025-11-21 19\:36\:02] 取卡操作:卡槽49被管理员取卡
log_1763724962585_e5e73d2c=[2025-11-21 19\:36\:02] 取卡操作:卡槽50被管理员取卡
log_1763724962685_896c53e3=[2025-11-21 19\:36\:02] 取卡操作:卡槽51被管理员取卡
log_1763724962786_ab983c5b=[2025-11-21 19\:36\:02] 取卡操作:卡槽52被管理员取卡
log_1763724962885_8687a0c3=[2025-11-21 19\:36\:02] 取卡操作:卡槽53被管理员取卡
log_1763724962985_3709588c=[2025-11-21 19\:36\:02] 取卡操作:卡槽54被管理员取卡
log_1763724963085_3f4cc469=[2025-11-21 19\:36\:03] 取卡操作:卡槽55被管理员取卡
log_1763724963185_6e98de49=[2025-11-21 19\:36\:03] 取卡操作:卡槽56被管理员取卡
log_1763724963285_41af6941=[2025-11-21 19\:36\:03] 取卡操作:卡槽57被管理员取卡
log_1763724963385_3af18a57=[2025-11-21 19\:36\:03] 取卡操作:卡槽55被管理员取卡
log_1763724963387_fe428ae2=[2025-11-21 19\:36\:03] 取卡操作:卡槽58被管理员取卡
log_1763724963535_1c1b689f=[2025-11-21 19\:36\:03] 取卡操作:卡槽59被管理员取卡
log_1763724963636_7ca29f16=[2025-11-21 19\:36\:03] 取卡操作:卡槽60被管理员取卡
log_1763724963685_d33f12b8=[2025-11-21 19\:36\:03] 取卡操作:卡槽55被管理员取卡
log_1763724963985_8ee47f7c=[2025-11-21 19\:36\:03] 取卡操作:卡槽55被管理员取卡
log_1763724964285_ddff2a15=[2025-11-21 19\:36\:04] 取卡操作:卡槽55被管理员取卡
log_1763724966171_1001bb5c=[2025-11-21 19\:36\:06] 管理员已将全部卡槽已经打开请取卡
src/chuankou/SerialPortConnectionDialog.java
@@ -183,6 +183,8 @@
        exitButton.setFocusPainted(false);
        exitButton.setBorder(BorderFactory.createEmptyBorder(8, 20, 8, 20));
        exitButton.addActionListener(e -> {
            // 新增:退出前确保关闭串口连接
            cleanupSerialPort();
            System.exit(0);
        });
        
@@ -303,14 +305,63 @@
                        });
                        
                    } else {
                        // 连接失败处理保持不变...
                        // 连接失败
                        connectButton.setEnabled(true);
                        connectButton.setText("连接串口");
                        connectButton.setBackground(SECONDARY_COLOR);
                        statusLabel.setText("串口连接失败: " + portName);
                        showMessage("连接失败", "无法连接到串口 " + portName, "error");
                        // 关闭失败的串口连接
                        if (serialService != null) {
                            serialService.close();
                            serialService = null;
                        }
                    }
                });
                
            } catch (Exception e) {
                // 异常处理保持不变...
                SwingUtilities.invokeLater(() -> {
                    connectButton.setEnabled(true);
                    connectButton.setText("连接串口");
                    connectButton.setBackground(SECONDARY_COLOR);
                    statusLabel.setText("连接异常: " + e.getMessage());
                    showMessage("连接异常", "串口连接过程中发生错误: " + e.getMessage(), "error");
                    // 关闭异常的串口连接
                    if (serialService != null) {
                        serialService.close();
                        serialService = null;
                    }
                });
            }
        }).start();
    }
    /**
     * 新增:清理串口资源的方法
     */
    private void cleanupSerialPort() {
        if (serialService != null) {
            try {
                // 停止数据捕获
                serialService.stopCapture();
                // 停止协议解析器
                if (serialService.getProtocolParser() != null) {
                    serialService.getProtocolParser().stop();
                }
                // 关闭串口
                serialService.close();
                //System.out.println("串口连接已清理");
            } catch (Exception e) {
                System.err.println("清理串口资源时发生异常: " + e.getMessage());
            } finally {
                serialService = null;
            }
        }
    }
    
    private void showMessage(String title, String message, String type) {
@@ -351,7 +402,7 @@
    public void dispose() {
        // 如果连接失败,关闭串口
        if (!isConnected && serialService != null) {
            serialService.close();
            cleanupSerialPort();
        }
        super.dispose();
    }
src/home/CardMachineUI.java
@@ -88,6 +88,13 @@
            initializeSlots();
            startUIUpdates(); // UI刷新定时器
            startSerialStatusMonitoring(); // 串口状态监控        
            setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
            addWindowListener(new java.awt.event.WindowAdapter() {
                @Override
                public void windowClosing(java.awt.event.WindowEvent windowEvent) {
                    dispose(); // 调用我们修改过的dispose方法
                }
            });
            
            //System.out.println("主界面初始化完成");
        } catch (Exception e) {
@@ -596,6 +603,14 @@
    }
    
    public void dispose() {
        int result = JOptionPane.showConfirmDialog(this,
                "确定要退出程序吗?",
                "确认退出",
                JOptionPane.YES_NO_OPTION);
            if (result != JOptionPane.YES_OPTION) {
                return; // 用户取消退出
            }
        // 停止UI刷新定时器
        if (uiUpdateTimer != null) {
            uiUpdateTimer.stop();
@@ -624,6 +639,31 @@
        }
        
        super.dispose();
        // 新增:确保程序完全退出前释放单实例锁
        try {
            // 通过反射调用 Homein 的清理方法
            Class<?> homeinClass = Class.forName("home.Homein");
            java.lang.reflect.Method cleanupMethod = homeinClass.getDeclaredMethod("cleanupSingleInstanceLock");
            cleanupMethod.setAccessible(true);
            cleanupMethod.invoke(null);
            //System.out.println("单实例锁已释放");
        } catch (Exception e) {
            System.err.println("释放单实例锁时发生异常: " + e.getMessage());
            // 如果反射失败,尝试直接关闭端口
            try {
                java.net.ServerSocket socket = new java.net.ServerSocket();
                socket.setReuseAddress(true);
                socket.bind(new java.net.InetSocketAddress(9999));
                socket.close();
                //System.out.println("通过直接绑定方式释放端口");
            } catch (Exception ex) {
                System.err.println("直接释放端口也失败: " + ex.getMessage());
            }
        }
        // 新增:确保程序完全退出
        System.exit(0);
    }
    
    /**
src/home/Homein.java
@@ -6,9 +6,25 @@
import chushihua.Chushihua;
import chushihua.SlotManager;
import chushihua.lunxun;
import dialog.Dingshidialog;
import jiekou.lunxunkazhuangtai;
import java.io.IOException;
import java.net.ServerSocket;
public class Homein {
    // 单实例锁的端口号,选择一个不常用的端口
    private static final int SINGLE_INSTANCE_PORT = 9999;
    private static ServerSocket singleInstanceSocket;
    public static void main(String[] args) {
        // 检查是否已有实例在运行
        if (!checkSingleInstance()) {
            Dingshidialog.showTimedDialog(null,5, "软件已经在运行中,不能重复打开!");
            System.exit(0);
            return;
        }
        SwingUtilities.invokeLater(() -> {
            try {
                // 设置系统外观
@@ -26,6 +42,7 @@
                        "系统初始化失败,无法启动应用程序", 
                        "错误", 
                        JOptionPane.ERROR_MESSAGE);
                    cleanupSingleInstanceLock();
                    System.exit(1);
                }
                
@@ -35,9 +52,50 @@
                    "程序启动失败: " + e.getMessage(), 
                    "错误", 
                    JOptionPane.ERROR_MESSAGE);
                cleanupSingleInstanceLock();
                System.exit(1);
            }
        });        
    }
    /**
     * 检查是否单实例运行
     * @return 如果是唯一实例返回true,如果已有实例运行返回false
     */
    private static boolean checkSingleInstance() {
        try {
            // 尝试绑定到指定端口,如果成功说明是第一个实例
            singleInstanceSocket = new ServerSocket(SINGLE_INSTANCE_PORT);
            return true;
        } catch (IOException e) {
            // 端口已被占用,说明已有实例在运行
            return false;
        }
    }
    /**
     * 清理单实例锁 - 改为公共静态方法以便外部调用
     */
    public static void cleanupSingleInstanceLock() {
        if (singleInstanceSocket != null && !singleInstanceSocket.isClosed()) {
            try {
                singleInstanceSocket.close();
                //System.out.println("单实例锁已清理");
            } catch (IOException e) {
                System.err.println("关闭单实例锁时发生异常: " + e.getMessage());
            } finally {
                singleInstanceSocket = null;
            }
        }
        // 额外确保:尝试再次绑定端口来确认是否已释放
        try {
            ServerSocket testSocket = new ServerSocket(SINGLE_INSTANCE_PORT);
            testSocket.close();
            //System.out.println("端口确认已释放");
        } catch (IOException e) {
            System.err.println("端口可能仍被占用: " + e.getMessage());
        }
    }
    
    /**
@@ -128,10 +186,13 @@
                // 4. 串口连接成功后,启动轮询
                startPollingService();
                showMainInterface();                
                lunxunkazhuangtai.startPolling();//启动卡状态轮询发给服务器
                
            } else {
                System.err.println("串口连接失败");
                // 串口连接失败已经由SerialPortConnectionDialog处理,直接退出
                cleanupSingleInstanceLock();
                System.exit(0);
            }
            
@@ -142,6 +203,7 @@
                "应用程序启动过程中发生错误: " + e.getMessage(), 
                "错误", 
                JOptionPane.ERROR_MESSAGE);
            cleanupSingleInstanceLock();
            System.exit(1);
        }
    }
@@ -267,6 +329,9 @@
                    mainUI.dispose();
                }
                
                // 清理单实例锁 - 确保在关闭钩子中也调用
                cleanupSingleInstanceLock();
                //System.out.println("应用程序关闭完成");
                
            } catch (Exception e) {
src/jiekou/lunxunkazhuangtai.java
@@ -2,7 +2,6 @@
import chushihua.SlotManager;
import home.Fkj;
/**
 * 轮询卡槽状态类
 * 用于定期轮询并输出所有卡槽的状态信息
@@ -10,29 +9,67 @@
public class lunxunkazhuangtai {
    private static Thread pollThread;
    private static volatile boolean isRunning = false;
    private static final int POLL_INTERVAL = 30000; // 30秒间隔
    private static volatile int pollInterval = 30000; // 30秒间隔,改为可变的
    // 常量定义,避免重复创建字符串
    private static final String THREAD_NAME = "SlotStatusPollingThread";
    private static final String UNKNOWN = "未知";
    private static final String NORMAL = "正常";
    private static final String NULL_VALUE = "null";
    // 状态常量
    private static final String STATUS_INVALID = "0";
    private static final String STATUS_STANDBY = "1";
    private static final String STATUS_CHARGING = "2";
    private static final String STATUS_FULL = "3";
    private static final String STATUS_FAULT = "4";
    private static final String STATUS_AUTH_EXPIRED = "5";
    private static final String STATUS_TIMEOUT = "6";
    private static final String STATUS_UNKNOWN = "-1";
    // 故障常量
    private static final String FAULT_NORMAL = "0";
    private static final String FAULT_CARD_ERROR = "1";
    private static final String FAULT_OVER_CURRENT = "2";
    private static final String FAULT_DOOR_FAULT = "3";
    private static final String FAULT_OVER_VOLTAGE = "4";
    private static final String FAULT_UNDER_VOLTAGE = "5";
    private static final String FAULT_UNKNOWN = "-1";
    /**
     * 启动轮询线程
     */
    public static void startPolling() {
        if (isRunning) {;
        if (isRunning) {
            System.out.println("轮询线程已在运行中");
            return;
        }
        isRunning = true;
        pollThread = new Thread(new PollingTask(), "SlotStatusPollingThread");
        pollThread.setDaemon(true); // 设置为守护线程,当主线程结束时自动结束
        pollThread = new Thread(new PollingTask(), THREAD_NAME);
        pollThread.setDaemon(true);
        pollThread.start();
        System.out.println("卡槽状态轮询线程已启动,间隔: " + pollInterval + "ms");
    }
    /**
     * 停止轮询线程
     */
    public static void stopPolling() {
        if (!isRunning) {
            return;
        }
        isRunning = false;
        if (pollThread != null) {
            pollThread.interrupt();
            try {
                // 等待线程安全结束,最多等待2秒
                pollThread.join(2000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("等待轮询线程停止时被中断");
            }
            pollThread = null;
        }
        System.out.println("卡槽状态轮询线程已停止");
@@ -52,23 +89,37 @@
    private static class PollingTask implements Runnable {
        @Override
        public void run() {
            System.out.println("轮询任务开始执行");
            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    // 输出所有卡槽状态
                    printAllSlotsStatus();
                    // 等待指定间隔
                    Thread.sleep(POLL_INTERVAL);
                    // 使用动态间隔,支持运行时调整
                    Thread.sleep(pollInterval);
                } catch (InterruptedException e) {
                    System.out.println("轮询线程被中断");
                    System.out.println("轮询线程被中断,正在退出...");
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    System.err.println("轮询过程中发生错误: " + e.getMessage());
                    // 记录异常但继续运行,避免因单次异常导致整个监控停止
                    e.printStackTrace();
                    // 发生异常时短暂等待后再继续,避免频繁错误循环
                    try {
                        Thread.sleep(5000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                }
            }
            }
            isRunning = false;
//            System.out.println("轮询任务执行结束");
        }
        /**
@@ -77,10 +128,18 @@
        private void printAllSlotsStatus() {
            Fkj[] slots = SlotManager.getSlotArray();
            if (slots == null || slots.length == 0) {
//                System.out.println("无卡槽数据");
                return;
            }
            // 使用StringBuilder减少字符串拼接开销
            StringBuilder statusBuilder = new StringBuilder();
            int validSlotCount = 0;
            for (Fkj slot : slots) {
                if (slot != null) {
                    validSlotCount++;
                    //使用下面的推给服务器卡的状态
                    String kacaobianhao=safeGetValue(slot.getSlotNumber());
                    String kahao=safeGetValue(slot.getCardNumber());
@@ -89,6 +148,8 @@
                    String kacaodianya=safeGetValue(slot.getVoltage());
                    String kacaodianliu=safeGetValue(slot.getCurrent());
                    String guzhangyuanyin=formatFault(safeGetValue(slot.getFault()));                    
                }
            }
@@ -98,7 +159,7 @@
         * 安全获取值,避免空指针
         */
        private String safeGetValue(String value) {
            return value != null ? value : "null";
            return value != null ? value : NULL_VALUE;
        }
        /**
@@ -107,7 +168,7 @@
        private String formatHasCard(String hasCard) {
            if ("1".equals(hasCard)) return "有卡";
            if ("0".equals(hasCard)) return "无卡";
            if ("-1".equals(hasCard)) return "未知";
            if ("-1".equals(hasCard)) return UNKNOWN;
            return hasCard;
        }
@@ -116,14 +177,14 @@
         */
        private String formatWorkStatus(String status) {
            switch (status) {
            case "0": return "无效";
            case "1": return "待机";
            case "2": return "充电中";
            case "3": return "已充满";
            case "4": return "故障";
            case "5": return "授权到期";
            case "6": return "通信超时";
            case "-1": return "未知";
                case STATUS_INVALID: return "无效";
                case STATUS_STANDBY: return "待机";
                case STATUS_CHARGING: return "充电中";
                case STATUS_FULL: return "已充满";
                case STATUS_FAULT: return "故障";
                case STATUS_AUTH_EXPIRED: return "授权到期";
                case STATUS_TIMEOUT: return "通信超时";
                case STATUS_UNKNOWN: return UNKNOWN;
            default: return status;
            }
        }
@@ -133,13 +194,13 @@
         */
        private String formatFault(String fault) {
            switch (fault) {
            case "0": return "正常";
            case "1": return "插卡错误";
            case "2": return "过流";
            case "3": return "门控故障";
            case "4": return "过压";
            case "5": return "欠压";
            case "-1": return "未知";
                case FAULT_NORMAL: return NORMAL;
                case FAULT_CARD_ERROR: return "插卡错误";
                case FAULT_OVER_CURRENT: return "过流";
                case FAULT_DOOR_FAULT: return "门控故障";
                case FAULT_OVER_VOLTAGE: return "过压";
                case FAULT_UNDER_VOLTAGE: return "欠压";
                case FAULT_UNKNOWN: return UNKNOWN;
            default: return fault;
            }
        }
@@ -150,8 +211,11 @@
     * @param interval 间隔时间,毫秒
     */
    public static void setPollInterval(int interval) {
        // 注意:这个设置不会立即生效,需要重启轮询线程
        System.out.println("新的轮询间隔将在下次启动时生效: " + interval + "ms");
        if (interval <= 0) {
            throw new IllegalArgumentException("轮询间隔必须大于0");
        }
        pollInterval = interval;
        System.out.println("轮询间隔已更新: " + interval + "ms");
    }
    /**
@@ -159,17 +223,24 @@
     * @return 轮询间隔(毫秒)
     */
    public static int getPollInterval() {
        return POLL_INTERVAL;
        return pollInterval;
    }
    /**
     * 手动触发一次状态输出(不等待间隔)
     */
    public static void triggerManualOutput() {
        if (isRunning) {
        if (isRunning && pollThread != null) {
            new PollingTask().printAllSlotsStatus();
        } else {
            System.out.println("轮询线程未运行,无法手动触发输出");
        }
    }
    /**
     * 安全关闭所有资源
     */
    public static void shutdown() {
        stopPolling();
    }
}