feat: 添加串口失败跟踪和冷却机制,优化串口重试逻辑

This commit is contained in:
zhu-mengmeng 2025-10-14 15:53:50 +08:00
parent 275ad1a720
commit b0115059e5
2 changed files with 60 additions and 5 deletions

View File

@ -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,

View File

@ -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():
@ -1326,3 +1338,45 @@ class SerialManager:
# 尝试重新启动监控
time.sleep(10)
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]