d22349714c8d199c02f336f90fba841ef8f5cd39..0f1509097818fbf48d7741d0fe0d9b973e88730d
19 小时以前 张世豪
新增人脸检测暂停有卡卡槽查询
0f1509 对比 | 目录
昨天 张世豪
开启状态线程,优化结束程序逻辑
7be65a 对比 | 目录
已修改15个文件
1038 ■■■■■ 文件已修改
bin/.gitignore 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/SerialPortConnectionDialog$1.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chuankou/SerialPortConnectionDialog.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chushihua/lunxun$PollingTask.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/chushihua/lunxun.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/CardMachineUI$1.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/CardMachineUI.class 补丁 | 查看 | 原始文档 | blame | 历史
bin/home/Homein.class 补丁 | 查看 | 原始文档 | blame | 历史
err.properties 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
log.properties 150 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chuankou/SerialPortConnectionDialog.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/chushihua/lunxun.java 233 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/home/CardMachineUI.java 104 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/home/Homein.java 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/jiekou/lunxunkazhuangtai.java 371 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
bin/.gitignore
@@ -1,7 +1,5 @@
/jiekou/
/home/
/chushihua/
/xitongshezhi/
/chuankou/
/chushihua/
/home/
/publicway/
/dialog/
/xitongshezhi/
bin/chuankou/SerialPortConnectionDialog$1.class
Binary files differ
bin/chuankou/SerialPortConnectionDialog.class
Binary files differ
bin/chushihua/lunxun$PollingTask.class
Binary files differ
bin/chushihua/lunxun.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,38 @@
#\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连续失败次数过多,暂停轮询
#\u64CD\u4F5C\u65E5\u5FD7\u8BB0\u5F55 - \u6700\u540E\u66F4\u65B0: Sat Nov 22 15:43:39 CST 2025
#Sat Nov 22 15:43:39 CST 2025
log_1763789446376_988d7c49=[2025-11-22 13\:30\:46] [13\:30\:46.374] 发送失败,正在重试 (1/2)
log_1763789446456_a6ac3722=[2025-11-22 13\:30\:46] [13\:30\:46.456] 发送失败,正在重试 (2/2)
log_1763789446514_b6a71823=[2025-11-22 13\:30\:46] [13\:30\:46.514] 发送失败,正在重试 (1/2)
log_1763789446569_161a5712=[2025-11-22 13\:30\:46] [13\:30\:46.569] 发送失败,正在重试 (2/2)
log_1763789446630_1077c7e6=[2025-11-22 13\:30\:46] [13\:30\:46.630] 发送失败,正在重试 (1/2)
log_1763789446684_7cae2d01=[2025-11-22 13\:30\:46] [13\:30\:46.684] 发送失败,正在重试 (2/2)
log_1763789446742_b8870ee0=[2025-11-22 13\:30\:46] [13\:30\:46.742] 发送失败,正在重试 (1/2)
log_1763789446798_316ed82f=[2025-11-22 13\:30\:46] [13\:30\:46.798] 发送失败,正在重试 (2/2)
log_1763789446856_96be7593=[2025-11-22 13\:30\:46] [13\:30\:46.856] 发送失败,正在重试 (1/2)
log_1763789446910_a8beea8f=[2025-11-22 13\:30\:46] [13\:30\:46.910] 发送失败,正在重试 (2/2)
log_1763789446966_3df74d56=[2025-11-22 13\:30\:46] lunxun连续失败次数过多,暂停轮询
log_1763795783674_8b53ec90=[2025-11-22 15\:16\:23] [15\:16\:23.672] 发送失败,正在重试 (1/2)
log_1763795783704_0d7f2bae=[2025-11-22 15\:16\:23] [15\:16\:23.704] 发送失败,正在重试 (1/2)
log_1763795783706_764a8720=[2025-11-22 15\:16\:23] [15\:16\:23.705] 发送失败,正在重试 (1/2)
log_1763795783707_91d6a74e=[2025-11-22 15\:16\:23] [15\:16\:23.707] 发送失败,正在重试 (1/2)
log_1763795783709_453e8e32=[2025-11-22 15\:16\:23] [15\:16\:23.708] 发送失败,正在重试 (1/2)
log_1763795783710_9ba2c525=[2025-11-22 15\:16\:23] 连续失败次数过多,暂停轮询
log_1763797334626_04df8243=[2025-11-22 15\:42\:14] 连续失败次数过多,暂停轮询
log_1763797334658_a6c75b5f=[2025-11-22 15\:42\:14] 轮询查询过程中发生异常\: current thread is not owner
log_1763797339663_93d1b1d9=[2025-11-22 15\:42\:19] 轮询查询过程中发生异常\: current thread is not owner
log_1763797344667_704d7e7d=[2025-11-22 15\:42\:24] 轮询查询过程中发生异常\: current thread is not owner
log_1763797349672_ee6dbf12=[2025-11-22 15\:42\:29] 轮询查询过程中发生异常\: current thread is not owner
log_1763797354677_c65e7427=[2025-11-22 15\:42\:34] 轮询查询过程中发生异常\: current thread is not owner
log_1763797359682_57e9a05f=[2025-11-22 15\:42\:39] 轮询查询过程中发生异常\: current thread is not owner
log_1763797364688_043b5709=[2025-11-22 15\:42\:44] 轮询查询过程中发生异常\: current thread is not owner
log_1763797369693_f5906191=[2025-11-22 15\:42\:49] 轮询查询过程中发生异常\: current thread is not owner
log_1763797374697_b47cdd8c=[2025-11-22 15\:42\:54] 轮询查询过程中发生异常\: current thread is not owner
log_1763797379702_ed7100c0=[2025-11-22 15\:42\:59] 轮询查询过程中发生异常\: current thread is not owner
log_1763797384707_1c168ae5=[2025-11-22 15\:43\:04] 轮询查询过程中发生异常\: current thread is not owner
log_1763797389712_b4cf898c=[2025-11-22 15\:43\:09] 轮询查询过程中发生异常\: current thread is not owner
log_1763797394717_0d58d8a9=[2025-11-22 15\:43\:14] 轮询查询过程中发生异常\: current thread is not owner
log_1763797399721_2c2dc0d0=[2025-11-22 15\:43\:19] 轮询查询过程中发生异常\: current thread is not owner
log_1763797404726_31fbf23a=[2025-11-22 15\:43\:24] 轮询查询过程中发生异常\: current thread is not owner
log_1763797409731_5ef27119=[2025-11-22 15\:43\:29] 轮询查询过程中发生异常\: current thread is not owner
log_1763797414736_ac54bee3=[2025-11-22 15\:43\:34] 轮询查询过程中发生异常\: current thread is not owner
log_1763797419741_8fcdd344=[2025-11-22 15\:43\:39] 轮询查询过程中发生异常\: current thread is not owner
log.properties
@@ -1,33 +1,117 @@
#\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: Sat Nov 22 15:43:14 CST 2025
#Sat Nov 22 15:43:14 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] 管理员已将全部卡槽已经打开请取卡
log_1763789484180_b8a899e1=[2025-11-22 13\:31\:24] 取卡操作:卡槽3被管理员取卡
log_1763789484496_04c6c8c1=[2025-11-22 13\:31\:24] 取卡操作:卡槽3被管理员取卡
log_1763796570996_9e09fb61=[2025-11-22 15\:29\:30] 取卡操作:卡槽8被管理员取卡
log_1763796584253_3d102b2d=[2025-11-22 15\:29\:44] 取卡操作:卡槽18被管理员取卡
log_1763796584613_89e54457=[2025-11-22 15\:29\:44] 取卡操作:卡槽18被管理员取卡
log_1763796595461_dfba9a6c=[2025-11-22 15\:29\:55] 取卡操作:卡槽19被管理员取卡
log_1763796601266_3c1efc15=[2025-11-22 15\:30\:01] 取卡操作:卡槽17被管理员取卡
log_1763796601612_be728bba=[2025-11-22 15\:30\:01] 取卡操作:卡槽17被管理员取卡
log_1763796639618_a4f98efe=[2025-11-22 15\:30\:39] 取卡操作:卡槽8被管理员取卡
log_1763796645488_c1b9fdbc=[2025-11-22 15\:30\:45] 取卡操作:卡槽18被管理员取卡
log_1763796645862_d8280caa=[2025-11-22 15\:30\:45] 取卡操作:卡槽18被管理员取卡
log_1763796649004_765f3a76=[2025-11-22 15\:30\:49] 取卡操作:卡槽13被管理员取卡
log_1763796666877_dc07a7e9=[2025-11-22 15\:31\:06] 取卡操作:卡槽8被管理员取卡
log_1763796671164_0bfd4da1=[2025-11-22 15\:31\:11] 取卡操作:卡槽13被管理员取卡
log_1763796683199_aaa5f071=[2025-11-22 15\:31\:23] 取卡操作:卡槽9被管理员取卡
log_1763796687126_8c5e091a=[2025-11-22 15\:31\:27] 取卡操作:卡槽7被管理员取卡
log_1763796690465_e506e75d=[2025-11-22 15\:31\:30] 取卡操作:卡槽22被管理员取卡
log_1763796690812_f26b1bca=[2025-11-22 15\:31\:30] 取卡操作:卡槽22被管理员取卡
log_1763796701339_8c2dce1b=[2025-11-22 15\:31\:41] 取卡操作:卡槽12被管理员取卡
log_1763796701663_0c96bb85=[2025-11-22 15\:31\:41] 取卡操作:卡槽12被管理员取卡
log_1763796706036_0dd4c910=[2025-11-22 15\:31\:46] 取卡操作:卡槽13被管理员取卡
log_1763796706413_31ebd822=[2025-11-22 15\:31\:46] 取卡操作:卡槽13被管理员取卡
log_1763796743734_613127ce=[2025-11-22 15\:32\:23] 取卡操作:卡槽27被管理员取卡
log_1763796744066_e4897b75=[2025-11-22 15\:32\:24] 取卡操作:卡槽27被管理员取卡
log_1763796746892_73a3de50=[2025-11-22 15\:32\:26] 取卡操作:卡槽37被管理员取卡
log_1763796852928_a74783df=[2025-11-22 15\:34\:12] 取卡操作:卡槽7被管理员取卡
log_1763796853265_ce89adf4=[2025-11-22 15\:34\:13] 取卡操作:卡槽7被管理员取卡
log_1763796862831_c78dcd41=[2025-11-22 15\:34\:22] 取卡操作:卡槽33被管理员取卡
log_1763797078465_84863744=[2025-11-22 15\:37\:58] 取卡操作:卡槽36被管理员取卡
log_1763797334627_489b424f=[2025-11-22 15\:42\:14] DDCC0008F009515AA55AA5027AD4;type2控制打开9柜门
log_1763797334670_248f0207=[2025-11-22 15\:42\:14] 取卡操作:卡槽9被管理员取卡
log_1763797334972_1587297d=[2025-11-22 15\:42\:14] 取卡操作:卡槽9被管理员取卡
log_1763797340020_7949f20b=[2025-11-22 15\:42\:20] DDCC0008F012515AA55AA5027B7F;type2控制打开18柜门
log_1763797340034_7af9f995=[2025-11-22 15\:42\:20] 取卡操作:卡槽18被管理员取卡
log_1763797340372_132dbb3f=[2025-11-22 15\:42\:20] 取卡操作:卡槽18被管理员取卡
log_1763797343370_5d7c1f77=[2025-11-22 15\:42\:23] DDCC0008F016515AA55AA502BB3A;type2控制打开22柜门
log_1763797343382_e189fce9=[2025-11-22 15\:42\:23] 取卡操作:卡槽22被管理员取卡
log_1763797343721_fce66d08=[2025-11-22 15\:42\:23] 取卡操作:卡槽22被管理员取卡
log_1763797346135_163e3113=[2025-11-22 15\:42\:26] DDCC0008F015515AA55AA502BB09;type2控制打开21柜门
log_1763797346145_e7aaa999=[2025-11-22 15\:42\:26] 取卡操作:卡槽21被管理员取卡
log_1763797346472_4c86428b=[2025-11-22 15\:42\:26] 取卡操作:卡槽21被管理员取卡
log_1763797349064_db936542=[2025-11-22 15\:42\:29] DDCC0008F013515AA55AA502BB6F;type2控制打开19柜门
log_1763797349073_7d4f1ad8=[2025-11-22 15\:42\:29] 取卡操作:卡槽19被管理员取卡
log_1763797349421_3e727453=[2025-11-22 15\:42\:29] 取卡操作:卡槽19被管理员取卡
log_1763797356580_3d7e82a4=[2025-11-22 15\:42\:36] DDCC0008F00D515AA55AA502BA91;type2控制打开13柜门
log_1763797356590_53e0c788=[2025-11-22 15\:42\:36] 取卡操作:卡槽13被管理员取卡
log_1763797356923_36b384c1=[2025-11-22 15\:42\:36] 取卡操作:卡槽13被管理员取卡
log_1763797394271_ad30a236=[2025-11-22 15\:43\:14] DDCC0008F003515AA55AA5027A7E;type2控制打开3柜门
log_1763797394281_00876aa0=[2025-11-22 15\:43\:14] 取卡操作:卡槽3被管理员取卡
log_1763797394622_9137f63b=[2025-11-22 15\:43\:14] 3号卡槽取卡失败
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/chushihua/lunxun.java
@@ -26,6 +26,8 @@
    private static Thread pollingThread;
    private static int pollingInterval = 100; // 默认轮询间隔
    public static boolean sendChaxunzhiling=true;//是否向串口发送查询指令
    // 添加静态变量控制人脸检测
    public static boolean ishaveface = false; // 是否检测到人脸,默认没有人脸
    // 卡槽相关常量
    private static final int MIN_SLOT = 1;
@@ -375,127 +377,152 @@
        @Override
        public void run() {
            //System.out.println("轮询查询线程开始运行");
            //System.out.println("轮询查询线程开始运行");
            while (isRunning && !Thread.currentThread().isInterrupted() && !shouldStop.get()) {
                try {
            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;
                    }
//                  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;
                    }
                    // 定期检查串口连接状态(每10次循环检查一次)
                    if (currentIndex % 10 == 0 && !checkSerialConnectionWithRetry()) {
                        logErrorWithRateLimit("serial_disconnected", "串口连接断开,暂停轮询");
                        pausePolling();
                        continue;
                    }
                    // 定期清理缓存(每100次循环清理一次)
                    if (currentIndex % 100 == 0) {
                        cleanupOldCache();
                    }
                    // 定期清理缓存(每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;
                    }
                    // 获取卡槽数组
                    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();
                    // 新增:根据卡槽状态和查询频率决定是否发送查询
                    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);
                    // 遍历卡槽,寻找需要查询的卡槽
                    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 (ishaveface && "1".equals(hasCard)) {
                                // 跳过有卡卡槽的查询
                                if (DEBUG_ENABLED) {
                                    debugBuilder.setLength(0);
                                    debugBuilder.append("检测到人脸,跳过有卡卡槽 ").append(slotNumber).append(" 的查询\n");
                                    SystemDebugDialog.appendAsciiData(debugBuilder.toString());
                                }
                                continue;
                            }
                            // 检查是否达到查询时间
                            if (lastQueryTime == null || currentTime - lastQueryTime >= queryInterval) {
                                if (sendQueryToSlot(slotNumber)) {
                                    // 更新最后查询时间
                                    lastQueryTimeMap.put(slotNumber, currentTime);
                                    sentQuery = true;
                                    consecutiveFailures = 0;
                            // 确定查询间隔:只有hasCard="1"的卡槽使用10秒间隔,其他情况(包括"-1")都使用100ms间隔
                            int queryInterval = "1".equals(hasCard) ? HAS_CARD_QUERY_INTERVAL : NO_CARD_QUERY_INTERVAL;
                                    // 成功发送查询后,等待100ms再继续下一个查询
                                    Thread.sleep(100);
                            // 检查是否达到查询时间
                            if (lastQueryTime == null || currentTime - lastQueryTime >= queryInterval) {
                                if (sendQueryToSlot(slotNumber)) {
                                    // 更新最后查询时间
                                    lastQueryTimeMap.put(slotNumber, currentTime);
                                    sentQuery = true;
                                    consecutiveFailures = 0;
                                    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;
                                    }
                                }
                            }
                        }
                    }
                                    // 成功发送查询后,等待100ms再继续下一个查询
                                    Thread.sleep(100);
                    // 更新当前索引
                    currentIndex = (currentIndex + 1) % slotArray.length;
                                    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;
                                    }
                                }
                            }
                        }
                    }
                    // 如果没有发送查询,等待一段时间再继续
                    if (!sentQuery) {
                        Thread.sleep(pollingInterval);
                    }
                    // 更新当前索引
                    currentIndex = (currentIndex + 1) % slotArray.length;
                } catch (InterruptedException e) {
                    //System.out.println("轮询查询线程被中断");
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    logErrorWithRateLimit("polling_exception", "轮询查询过程中发生异常: " + e.getMessage());
                    consecutiveFailures++;
                    // 如果没有发送查询,等待一段时间再继续
                    if (!sentQuery) {
                        Thread.sleep(pollingInterval);
                    }
                    // 发生异常时等待一段时间再继续
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
                } catch (InterruptedException e) {
                    //System.out.println("轮询查询线程被中断");
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    logErrorWithRateLimit("polling_exception", "轮询查询过程中发生异常: " + e.getMessage());
                    consecutiveFailures++;
            //System.out.println("轮询查询线程结束运行");
                    // 发生异常时等待一段时间再继续
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException ie) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
            }
            //System.out.println("轮询查询线程结束运行");
        }
        // 添加获取和设置人脸检测状态的方法
        public static boolean isIshaveface() {
            return ishaveface;
        }
        public static void setIshaveface(boolean ishaveface) {
            lunxun.ishaveface = ishaveface;
            if (DEBUG_ENABLED) {
                if (ishaveface) {
                    SystemDebugDialog.appendAsciiData("检测到人脸,轮询将只查询无卡卡槽\n");
                } else {
                    SystemDebugDialog.appendAsciiData("未检测到人脸,轮询恢复正常查询模式\n");
                }
            }
        }
        /**
         * 向指定卡槽发送查询指令 - 优化版本
         * 使用缓存指令,优化调试输出
src/home/CardMachineUI.java
@@ -87,7 +87,14 @@
            initializeUI();
            initializeSlots();
            startUIUpdates(); // UI刷新定时器
            startSerialStatusMonitoring(); // 串口状态监控
            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) {
@@ -174,7 +181,7 @@
    }
    private void initializeUI() {
        setTitle("智能人脸发卡机管理系统");
        setTitle("发卡机控制软件V1.0");
        setSize(SCREEN_WIDTH, SCREEN_HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);
@@ -596,34 +603,67 @@
    }
    
    public void dispose() {
        // 停止UI刷新定时器
        if (uiUpdateTimer != null) {
            uiUpdateTimer.stop();
        }
        // 停止串口状态监控
        if (serialStatusTimer != null) {
            serialStatusTimer.stop();
        }
        // 停止轮询查询
        if (lunxun.isPolling()) {
            lunxun.stopPolling();
            //System.out.println("应用程序关闭,轮询查询已停止");
        }
        // 停止串口协议解析器(新增)
        if (serialProtocolParser != null) {
            serialProtocolParser.stop();
        }
        // 停止串口服务
        if (serialPortService != null) {
            serialPortService.stopCapture();
            serialPortService.close();
        }
        super.dispose();
        int result = JOptionPane.showConfirmDialog(this,
                "确定要退出程序吗?",
                "确认退出",
                JOptionPane.YES_NO_OPTION);
            if (result != JOptionPane.YES_OPTION) {
                return; // 用户取消退出
            }
        // 停止UI刷新定时器
        if (uiUpdateTimer != null) {
            uiUpdateTimer.stop();
        }
        // 停止串口状态监控
        if (serialStatusTimer != null) {
            serialStatusTimer.stop();
        }
        // 停止轮询查询
        if (lunxun.isPolling()) {
            lunxun.stopPolling();
            //System.out.println("应用程序关闭,轮询查询已停止");
        }
        // 停止串口协议解析器(新增)
        if (serialProtocolParser != null) {
            serialProtocolParser.stop();
        }
        // 停止串口服务
        if (serialPortService != null) {
            serialPortService.stopCapture();
            serialPortService.close();
        }
        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);
    }
    
    /**
@@ -661,10 +701,10 @@
    public boolean performCardPickup(int slotId) {
        try {
            // 调用OpenDoor生成开门指令
            String command = OpenDoor.openOneDoor(slotId, OpenDoor.TYPE_ISSUE_CARD);
//            String command = OpenDoor.openOneDoor(slotId, OpenDoor.TYPE_ISSUE_CARD);
            // 使用Sendmsg发送指令到串口
            boolean sendResult = Sendmsg.sendMessage(command);
            boolean sendResult = Sendmsg.opendoorzhiling(slotId, 2);
            if (sendResult) {                
                return true;
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());
        }
    }
    
    /**
@@ -127,11 +185,14 @@
            if (serialConnected) {
                // 4. 串口连接成功后,启动轮询
                startPollingService();
                showMainInterface();
                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,174 +2,245 @@
import chushihua.SlotManager;
import home.Fkj;
/**
 * 轮询卡槽状态类
 * 用于定期轮询并输出所有卡槽的状态信息
 */
public class lunxunkazhuangtai {
    private static Thread pollThread;
    private static volatile boolean isRunning = false;
    private static final int POLL_INTERVAL = 30000; // 30秒间隔
    private static Thread pollThread;
    private static volatile boolean isRunning = false;
    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) {;
            return;
        }
    /**
     * 启动轮询线程
     */
    public static void startPolling() {
        if (isRunning) {
            System.out.println("轮询线程已在运行中");
            return;
        }
        isRunning = true;
        pollThread = new Thread(new PollingTask(), "SlotStatusPollingThread");
        pollThread.setDaemon(true); // 设置为守护线程,当主线程结束时自动结束
        pollThread.start();
    }
        isRunning = true;
        pollThread = new Thread(new PollingTask(), THREAD_NAME);
        pollThread.setDaemon(true);
        pollThread.start();
        System.out.println("卡槽状态轮询线程已启动,间隔: " + pollInterval + "ms");
    }
    /**
     * 停止轮询线程
     */
    public static void stopPolling() {
        isRunning = false;
        if (pollThread != null) {
            pollThread.interrupt();
            pollThread = null;
        }
        System.out.println("卡槽状态轮询线程已停止");
    }
    /**
     * 停止轮询线程
     */
    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("卡槽状态轮询线程已停止");
    }
    /**
     * 检查轮询线程是否在运行
     * @return 运行状态
     */
    public static boolean isPolling() {
        return isRunning;
    }
    /**
     * 检查轮询线程是否在运行
     * @return 运行状态
     */
    public static boolean isPolling() {
        return isRunning;
    }
    /**
     * 轮询任务实现
     */
    private static class PollingTask implements Runnable {
        @Override
        public void run() {
            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    // 输出所有卡槽状态
                    printAllSlotsStatus();
    /**
     * 轮询任务实现
     */
    private static class PollingTask implements Runnable {
        @Override
        public void run() {
            System.out.println("轮询任务开始执行");
            while (isRunning && !Thread.currentThread().isInterrupted()) {
                try {
                    // 输出所有卡槽状态
                    printAllSlotsStatus();
                    // 等待指定间隔
                    Thread.sleep(POLL_INTERVAL);
                } catch (InterruptedException e) {
                    System.out.println("轮询线程被中断");
                    Thread.currentThread().interrupt();
                    break;
                } catch (Exception e) {
                    System.err.println("轮询过程中发生错误: " + e.getMessage());
                    e.printStackTrace();
                }
            }
            isRunning = false;
        }
                    // 使用动态间隔,支持运行时调整
                    Thread.sleep(pollInterval);
                } catch (InterruptedException e) {
                    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("轮询任务执行结束");
        }
        /**
         * 输出所有卡槽状态信息
         */
        private void printAllSlotsStatus() {
            Fkj[] slots = SlotManager.getSlotArray();
            if (slots == null || slots.length == 0) {
                return;
            }
            for (Fkj slot : slots) {
                if (slot != null) {
                    //使用下面的推给服务器卡的状态
                    String kacaobianhao=safeGetValue(slot.getSlotNumber());
                    String kahao=safeGetValue(slot.getCardNumber());
                    String shifouyouka=formatHasCard(safeGetValue(slot.getHasCard()));
                    String kazhuangtai=formatWorkStatus(safeGetValue(slot.getWorkStatus()));
                    String kacaodianya=safeGetValue(slot.getVoltage());
                    String kacaodianliu=safeGetValue(slot.getCurrent());
                    String guzhangyuanyin=formatFault(safeGetValue(slot.getFault()));
                }
            }
        /**
         * 输出所有卡槽状态信息
         */
        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());
                    String shifouyouka = formatHasCard(safeGetValue(slot.getHasCard()));
                    String kazhuangtai = formatWorkStatus(safeGetValue(slot.getWorkStatus()));
                    String kacaodianya = safeGetValue(slot.getVoltage());
                    String kacaodianliu = safeGetValue(slot.getCurrent());
                    String guzhangyuanyin = formatFault(safeGetValue(slot.getFault()));
                }
            }
        }
        }
        /**
         * 安全获取值,避免空指针
         */
        private String safeGetValue(String value) {
            return value != null ? value : "null";
        }
        /**
         * 安全获取值,避免空指针
         */
        private String safeGetValue(String value) {
            return value != null ? value : NULL_VALUE;
        }
        /**
         * 格式化有卡状态
         */
        private String formatHasCard(String hasCard) {
            if ("1".equals(hasCard)) return "有卡";
            if ("0".equals(hasCard)) return "无卡";
            if ("-1".equals(hasCard)) return "未知";
            return hasCard;
        }
        /**
         * 格式化有卡状态
         */
        private String formatHasCard(String hasCard) {
            if ("1".equals(hasCard)) return "有卡";
            if ("0".equals(hasCard)) return "无卡";
            if ("-1".equals(hasCard)) return UNKNOWN;
            return hasCard;
        }
        /**
         * 格式化工作状态
         */
        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 "未知";
            default: return status;
            }
        }
        /**
         * 格式化工作状态
         */
        private String formatWorkStatus(String status) {
            switch (status) {
                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;
            }
        }
        /**
         * 格式化故障状态
         */
        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 "未知";
            default: return fault;
            }
        }
    }
        /**
         * 格式化故障状态
         */
        private String formatFault(String fault) {
            switch (fault) {
                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;
            }
        }
    }
    /**
     * 设置轮询间隔(单位:毫秒)
     * @param interval 间隔时间,毫秒
     */
    public static void setPollInterval(int interval) {
        // 注意:这个设置不会立即生效,需要重启轮询线程
        System.out.println("新的轮询间隔将在下次启动时生效: " + interval + "ms");
    }
    /**
     * 设置轮询间隔(单位:毫秒)
     * @param interval 间隔时间,毫秒
     */
    public static void setPollInterval(int interval) {
        if (interval <= 0) {
            throw new IllegalArgumentException("轮询间隔必须大于0");
        }
        pollInterval = interval;
        System.out.println("轮询间隔已更新: " + interval + "ms");
    }
    /**
     * 获取当前轮询间隔
     * @return 轮询间隔(毫秒)
     */
    public static int getPollInterval() {
        return POLL_INTERVAL;
    }
    /**
     * 获取当前轮询间隔
     * @return 轮询间隔(毫秒)
     */
    public static int getPollInterval() {
        return pollInterval;
    }
    /**
     * 手动触发一次状态输出(不等待间隔)
     */
    public static void triggerManualOutput() {
        if (isRunning) {
            new PollingTask().printAllSlotsStatus();
        } else {
            System.out.println("轮询线程未运行,无法手动触发输出");
        }
    }
    /**
     * 手动触发一次状态输出(不等待间隔)
     */
    public static void triggerManualOutput() {
        if (isRunning && pollThread != null) {
            new PollingTask().printAllSlotsStatus();
        } else {
            System.out.println("轮询线程未运行,无法手动触发输出");
        }
    }
    /**
     * 安全关闭所有资源
     */
    public static void shutdown() {
        stopPolling();
    }
}