diff --git a/config/app_config.json b/config/app_config.json index f49e74a..97c20b4 100644 --- a/config/app_config.json +++ b/config/app_config.json @@ -94,10 +94,11 @@ "data_bits": 8, "parity": "N", "port": "9600", - "ser": "COM2", + "ser": "", "stable_threshold": 10, "stop_bits": 1, - "timeout": 1 + "timeout": 1, + "comment": "称重通过寄存器D11获取,无需串口" }, "xj": { "bit": 10, diff --git a/utils/serial_manager.py b/utils/serial_manager.py index b44f8bb..a889f4a 100644 --- a/utils/serial_manager.py +++ b/utils/serial_manager.py @@ -51,6 +51,12 @@ class SerialManager: # 稳定性时间跟踪 self.stability_start_time = 0 # 开始检测稳定性的时间 + # 串口失败跟踪 + self.port_failure_count: Dict[str, int] = {} # 记录每个串口的连续失败次数 + self.port_last_failure_time: Dict[str, float] = {} # 记录每个串口的最后失败时间 + self.max_failures = 5 # 最大连续失败次数 + self.failure_cooldown = 300 # 失败冷却时间(秒),5分钟 + # 数据存储 self.data = { 'mdz': 0, @@ -996,20 +1002,26 @@ class SerialManager: port_name = self.cz_config['ser'] baud_rate = self.cz_config.get('port', 9600) - if not self.is_port_open(port_name): + # 检查串口是否在冷却期内 + if self._should_skip_port_attempt(port_name): + logging.info(f"称重串口 {port_name} 在冷却期内,跳过重试(失败{self.port_failure_count.get(port_name, 0)}次)") + elif not self.is_port_open(port_name): try: if self.open_port(port_name, 'cz', baud_rate): logging.info(f"自动打开称重串口 {port_name} 成功") + self._reset_port_failure(port_name) # 成功后重置失败计数 else: logging.error(f"自动打开称重串口 {port_name} 失败") + self._record_port_failure(port_name) success = False except Exception as e: logging.error(f"自动打开称重串口 {port_name} 时发生异常: {e}") + self._record_port_failure(port_name) success = False else: logging.info(f"称重串口 {port_name} 已经打开,无需重新打开") else: - logging.warning("称重串口未配置或设置为不使用,跳过自动打开") + logging.info("称重串口未配置或设置为不使用,跳过自动打开") # 尝试打开线径串口 if self.xj_config and 'ser' in self.xj_config and self.xj_config['ser'] and self.xj_config['ser'].strip(): @@ -1325,4 +1337,46 @@ class SerialManager: logging.error(f"线程监控主循环异常: {e}") # 尝试重新启动监控 time.sleep(10) - self._start_thread_monitor() \ No newline at end of file + self._start_thread_monitor() + + def _should_skip_port_attempt(self, port_name: str) -> bool: + """检查是否应该跳过串口重试(基于失败次数和冷却时间)""" + current_time = time.time() + + # 如果没有失败记录,允许尝试 + if port_name not in self.port_failure_count: + return False + + failure_count = self.port_failure_count[port_name] + last_failure_time = self.port_last_failure_time.get(port_name, 0) + + # 如果失败次数超过最大值且在冷却期内,跳过 + if failure_count >= self.max_failures: + time_since_failure = current_time - last_failure_time + if time_since_failure < self.failure_cooldown: + return True + else: + # 冷却期结束,重置失败计数给一次机会 + logging.info(f"串口 {port_name} 冷却期结束,重置失败计数") + self._reset_port_failure(port_name) + return False + + return False + + def _record_port_failure(self, port_name: str): + """记录串口打开失败""" + current_time = time.time() + self.port_failure_count[port_name] = self.port_failure_count.get(port_name, 0) + 1 + self.port_last_failure_time[port_name] = current_time + + failure_count = self.port_failure_count[port_name] + if failure_count >= self.max_failures: + cooldown_minutes = self.failure_cooldown // 60 + logging.warning(f"串口 {port_name} 连续失败{failure_count}次,将在{cooldown_minutes}分钟内暂停重试") + + def _reset_port_failure(self, port_name: str): + """重置串口失败计数""" + if port_name in self.port_failure_count: + del self.port_failure_count[port_name] + if port_name in self.port_last_failure_time: + del self.port_last_failure_time[port_name] \ No newline at end of file