| | |
| | | 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; |
| | |
| | | |
| | | @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"); |
| | | } |
| | | } |
| | | } |
| | | /** |
| | | * 向指定卡槽发送查询指令 - 优化版本 |
| | | * 使用缓存指令,优化调试输出 |