状态更新
parent
bb1d70795a
commit
217290a76e
|
|
@ -115,28 +115,53 @@ class ExperimentStateMonitor:
|
||||||
"""监控循环 - 定时查询并检测状态变化"""
|
"""监控循环 - 定时查询并检测状态变化"""
|
||||||
try:
|
try:
|
||||||
logger.info(f"[监控循环] 开始监控实验{self.experiment_id}")
|
logger.info(f"[监控循环] 开始监控实验{self.experiment_id}")
|
||||||
|
logger.info(
|
||||||
|
f"[监控循环] 配置信息: status_field={self.query_config.get('status_field')}, "
|
||||||
|
f"status_values={self.query_config.get('status_values')}"
|
||||||
|
)
|
||||||
|
|
||||||
while not self._stop_event.is_set():
|
while not self._stop_event.is_set():
|
||||||
try:
|
try:
|
||||||
# 查询当前状态
|
# 查询当前状态
|
||||||
logger.debug(f"[监控循环] 实验{self.experiment_id}开始查询状态...")
|
logger.info(f"[监控循环] 实验{self.experiment_id}开始查询状态...")
|
||||||
current_state = self._query_current_state()
|
current_state = self._query_current_state()
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[监控循环] 实验{self.experiment_id}查询结果: 当前状态={current_state}, "
|
f"[监控循环] 实验{self.experiment_id}查询结果: 当前状态={current_state} (type={type(current_state).__name__ if current_state else 'None'}), "
|
||||||
f"上一状态={self._last_state}"
|
f"上一状态={self._last_state} (type={type(self._last_state).__name__ if self._last_state else 'None'})"
|
||||||
)
|
)
|
||||||
|
|
||||||
if current_state is not None:
|
if current_state is not None:
|
||||||
|
|
||||||
|
# 数值比较函数:支持字符串和数值的灵活比较
|
||||||
|
def states_equal(state1: str, state2: str) -> bool:
|
||||||
|
"""比较两个状态是否相等,支持数值比较"""
|
||||||
|
if state1 == state2:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
return float(state1) == float(state2)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
# 检测状态变化
|
# 检测状态变化
|
||||||
if self._last_state is None:
|
if self._last_state is None:
|
||||||
# 第一次查询,记录初始状态
|
# 第一次查询,记录初始状态并检查是否为开始状态
|
||||||
self._last_state = current_state
|
self._last_state = current_state
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[监控循环] 实验{self.experiment_id}初始状态: {current_state}"
|
f"[监控循环] 实验{self.experiment_id}初始状态: {current_state}"
|
||||||
)
|
)
|
||||||
elif current_state != self._last_state:
|
# 检查初始状态是否为开始值,如果是则触发开始事件
|
||||||
# 状态发生变化
|
self._check_initial_state(current_state)
|
||||||
|
else:
|
||||||
|
# 比较状态是否变化
|
||||||
|
is_equal = states_equal(current_state, self._last_state)
|
||||||
|
logger.info(
|
||||||
|
f"[监控循环-比较] 实验{self.experiment_id}: "
|
||||||
|
f"current_state='{current_state}', _last_state='{self._last_state}', "
|
||||||
|
f"states_equal={is_equal}, 字符串比较={(current_state == self._last_state)}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not is_equal:
|
||||||
|
# 状态发生变化(使用数值比较)
|
||||||
old_state = self._last_state
|
old_state = self._last_state
|
||||||
self._last_state = current_state
|
self._last_state = current_state
|
||||||
|
|
||||||
|
|
@ -147,13 +172,14 @@ class ExperimentStateMonitor:
|
||||||
# 处理状态变化
|
# 处理状态变化
|
||||||
self._handle_state_change(old_state, current_state)
|
self._handle_state_change(old_state, current_state)
|
||||||
else:
|
else:
|
||||||
logger.debug(
|
logger.info(
|
||||||
f"[监控循环] 实验{self.experiment_id}状态无变化: {current_state}"
|
f"[监控循环] 实验{self.experiment_id}状态无变化: {current_state}"
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
logger.debug(f"[监控循环] 实验{self.experiment_id}暂无数据")
|
logger.info(f"[监控循环] 实验{self.experiment_id}暂无数据")
|
||||||
|
|
||||||
# 等待下一个轮询周期
|
# 等待下一个轮询周期
|
||||||
|
logger.info(f"[监控循环] 实验{self.experiment_id}等待{self.poll_interval}秒后继续...")
|
||||||
self._stop_event.wait(self.poll_interval)
|
self._stop_event.wait(self.poll_interval)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
@ -237,9 +263,10 @@ class ExperimentStateMonitor:
|
||||||
# 构建时间范围:查询最近1小时的数据
|
# 构建时间范围:查询最近1小时的数据
|
||||||
time_range = "-1h"
|
time_range = "-1h"
|
||||||
|
|
||||||
logger.debug(
|
logger.info(
|
||||||
f"[查询] 实验{self.experiment_id}查询InfluxDB: "
|
f"[查询] 实验{self.experiment_id}查询InfluxDB: "
|
||||||
f"bucket={bucket}, measurement={measurement}, fields={fields}"
|
f"bucket={bucket}, measurement={measurement}, fields={fields}, "
|
||||||
|
f"filters={filters}, status_field={status_field}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# 执行查询
|
# 执行查询
|
||||||
|
|
@ -252,23 +279,52 @@ class ExperimentStateMonitor:
|
||||||
)
|
)
|
||||||
|
|
||||||
if df.empty:
|
if df.empty:
|
||||||
logger.debug(f"[查询] 实验{self.experiment_id}查询结果为空")
|
logger.info(f"[查询] 实验{self.experiment_id}查询结果为空(DataFrame为空)")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[查询] 实验{self.experiment_id}查询到 {len(df)} 条记录, "
|
||||||
|
f"列: {list(df.columns)}"
|
||||||
|
)
|
||||||
|
|
||||||
# 获取最新的状态值
|
# 获取最新的状态值
|
||||||
if '_value' in df.columns and '_field' in df.columns:
|
if '_value' in df.columns and '_field' in df.columns:
|
||||||
|
# 显示所有字段
|
||||||
|
unique_fields = df['_field'].unique()
|
||||||
|
logger.info(
|
||||||
|
f"[查询] 实验{self.experiment_id}查询结果包含字段: {list(unique_fields)}"
|
||||||
|
)
|
||||||
|
|
||||||
# 筛选出指定字段的数据
|
# 筛选出指定字段的数据
|
||||||
status_data = df[df['_field'] == status_field]
|
status_data = df[df['_field'] == status_field]
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[查询] 实验{self.experiment_id}筛选字段'{status_field}'后有 {len(status_data)} 条记录"
|
||||||
|
)
|
||||||
|
|
||||||
if not status_data.empty:
|
if not status_data.empty:
|
||||||
# 按时间排序,取最后一条记录
|
# 按时间排序,取最后一条记录
|
||||||
if '_time' in status_data.columns:
|
if '_time' in status_data.columns:
|
||||||
status_data = status_data.sort_values('_time')
|
status_data = status_data.sort_values('_time')
|
||||||
|
logger.info(
|
||||||
|
f"[查询] 实验{self.experiment_id}时间范围: "
|
||||||
|
f"{status_data['_time'].iloc[0]} 到 {status_data['_time'].iloc[-1]}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 显示最近几条记录
|
||||||
|
if len(status_data) > 0:
|
||||||
|
recent_count = min(5, len(status_data))
|
||||||
|
logger.info(
|
||||||
|
f"[查询] 实验{self.experiment_id}最近{recent_count}条记录的值: "
|
||||||
|
f"{list(status_data['_value'].tail(recent_count))}"
|
||||||
|
)
|
||||||
|
|
||||||
latest_value = status_data['_value'].iloc[-1]
|
latest_value = status_data['_value'].iloc[-1]
|
||||||
logger.debug(
|
latest_time = status_data['_time'].iloc[-1] if '_time' in status_data.columns else 'N/A'
|
||||||
|
|
||||||
|
logger.info(
|
||||||
f"[查询] 实验{self.experiment_id}最新状态值: {latest_value} "
|
f"[查询] 实验{self.experiment_id}最新状态值: {latest_value} "
|
||||||
f"(字段: {status_field})"
|
f"(类型: {type(latest_value).__name__}, 字段: {status_field}, 时间: {latest_time})"
|
||||||
)
|
)
|
||||||
return str(latest_value)
|
return str(latest_value)
|
||||||
else:
|
else:
|
||||||
|
|
@ -350,6 +406,24 @@ class ExperimentStateMonitor:
|
||||||
f"(连续失败{self._consecutive_failures}/{self.max_consecutive_failures}次)"
|
f"(连续失败{self._consecutive_failures}/{self.max_consecutive_failures}次)"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def _try_float_compare(self, val1: str, val2: str) -> str:
|
||||||
|
"""
|
||||||
|
尝试浮点数比较,用于调试
|
||||||
|
|
||||||
|
Args:
|
||||||
|
val1: 值1
|
||||||
|
val2: 值2
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
比较结果的字符串描述
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
f1 = float(val1)
|
||||||
|
f2 = float(val2)
|
||||||
|
return f"float({val1})={f1}, float({val2})={f2}, 相等={f1 == f2}"
|
||||||
|
except (ValueError, TypeError) as e:
|
||||||
|
return f"转换失败: {e}"
|
||||||
|
|
||||||
def _handle_state_change(self, old_state: str, new_state: str) -> None:
|
def _handle_state_change(self, old_state: str, new_state: str) -> None:
|
||||||
"""
|
"""
|
||||||
处理状态变化
|
处理状态变化
|
||||||
|
|
@ -365,24 +439,126 @@ class ExperimentStateMonitor:
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
f"[状态变化] 实验{self.experiment_id}: {old_state} -> {new_state}, "
|
f"[状态变化] 实验{self.experiment_id}: {old_state} -> {new_state}, "
|
||||||
f"开始值={start_value}, 结束值={end_value}"
|
f"开始值配置={start_value} (type={type(start_value).__name__}), "
|
||||||
|
f"结束值配置={end_value} (type={type(end_value).__name__})"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 类型转换和比较日志
|
||||||
|
old_state_str = str(old_state)
|
||||||
|
new_state_str = str(new_state)
|
||||||
|
start_value_str = str(start_value)
|
||||||
|
end_value_str = str(end_value)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[状态变化-详细] 实验{self.experiment_id}: "
|
||||||
|
f"old_state_str='{old_state_str}' (type={type(old_state).__name__}), "
|
||||||
|
f"new_state_str='{new_state_str}' (type={type(new_state).__name__}), "
|
||||||
|
f"start_value_str='{start_value_str}', "
|
||||||
|
f"end_value_str='{end_value_str}'"
|
||||||
|
)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[状态变化-标志] 实验{self.experiment_id}: "
|
||||||
|
f"_experiment_started={self._experiment_started}, "
|
||||||
|
f"_experiment_ended={self._experiment_ended}"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 数值比较函数:支持字符串和数值的灵活比较
|
||||||
|
def values_equal(val1: str, val2: str) -> bool:
|
||||||
|
"""比较两个值是否相等,支持数值比较"""
|
||||||
|
# 先尝试字符串直接比较
|
||||||
|
if val1 == val2:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# 尝试作为浮点数比较(处理 '1' vs '1.0' 的情况)
|
||||||
|
try:
|
||||||
|
return float(val1) == float(val2)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
# 检测实验开始:状态从非开始值变为开始值
|
# 检测实验开始:状态从非开始值变为开始值
|
||||||
if not self._experiment_started and str(new_state) == str(start_value):
|
is_start_match = values_equal(new_state_str, start_value_str)
|
||||||
|
is_start_condition = not self._experiment_started and is_start_match
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[状态变化-开始检测] 实验{self.experiment_id}: "
|
||||||
|
f"not _experiment_started={not self._experiment_started}, "
|
||||||
|
f"values_equal(new_state_str, start_value_str)={is_start_match}, "
|
||||||
|
f"触发开始={is_start_condition}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_start_condition:
|
||||||
|
logger.info(f"[状态变化] ✅ 实验{self.experiment_id}满足开始条件,调用 _on_experiment_started()")
|
||||||
self._on_experiment_started()
|
self._on_experiment_started()
|
||||||
|
|
||||||
# 检测实验结束:状态从开始值变回非开始值
|
# 检测实验结束:状态从开始值变回结束值
|
||||||
elif self._experiment_started and str(new_state) == str(end_value):
|
is_end_match = values_equal(new_state_str, end_value_str)
|
||||||
|
is_end_condition = self._experiment_started and is_end_match
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[状态变化-结束检测] 实验{self.experiment_id}: "
|
||||||
|
f"_experiment_started={self._experiment_started}, "
|
||||||
|
f"new_state_str='{new_state_str}', end_value_str='{end_value_str}', "
|
||||||
|
f"values_equal(new_state_str, end_value_str)={is_end_match}, "
|
||||||
|
f"字符串比较=(new_state_str == end_value_str)={(new_state_str == end_value_str)}, "
|
||||||
|
f"浮点数比较尝试={self._try_float_compare(new_state_str, end_value_str)}, "
|
||||||
|
f"触发结束={is_end_condition}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_end_condition:
|
||||||
|
logger.info(f"[状态变化] ✅ 实验{self.experiment_id}满足结束条件,调用 _on_experiment_ended()")
|
||||||
self._on_experiment_ended()
|
self._on_experiment_ended()
|
||||||
|
elif self._experiment_started and not is_end_match and not is_start_match:
|
||||||
|
# 只在状态既不是开始值也不是结束值时才警告(意外的中间状态)
|
||||||
|
logger.warning(
|
||||||
|
f"[状态变化] ⚠️ 实验{self.experiment_id}检测到意外状态: "
|
||||||
|
f"new_state_str='{new_state_str}' (期望: start='{start_value_str}' 或 end='{end_value_str}')"
|
||||||
|
)
|
||||||
|
|
||||||
# 触发回调
|
# 触发回调
|
||||||
if self.on_state_changed:
|
if self.on_state_changed:
|
||||||
|
logger.debug(f"[状态变化] 实验{self.experiment_id}触发状态变化回调")
|
||||||
self.on_state_changed(old_state, new_state)
|
self.on_state_changed(old_state, new_state)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[状态变化] 实验{self.experiment_id}处理失败: {e}", exc_info=True)
|
logger.error(f"[状态变化] 实验{self.experiment_id}处理失败: {e}", exc_info=True)
|
||||||
|
|
||||||
|
def _check_initial_state(self, initial_state: str) -> None:
|
||||||
|
"""
|
||||||
|
检查初始状态,如果是开始值则触发开始事件
|
||||||
|
|
||||||
|
Args:
|
||||||
|
initial_state: 初始状态值
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
status_values = self.query_config.get('status_values', {})
|
||||||
|
start_value = str(status_values.get('start', ''))
|
||||||
|
initial_state_str = str(initial_state)
|
||||||
|
|
||||||
|
# 数值比较函数
|
||||||
|
def values_equal(val1: str, val2: str) -> bool:
|
||||||
|
if val1 == val2:
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
return float(val1) == float(val2)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
is_start_match = values_equal(initial_state_str, start_value)
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[初始状态检查] 实验{self.experiment_id}: "
|
||||||
|
f"initial_state='{initial_state_str}', start_value='{start_value}', "
|
||||||
|
f"匹配={is_start_match}"
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_start_match and not self._experiment_started:
|
||||||
|
logger.info(f"[初始状态检查] ✅ 实验{self.experiment_id}初始状态即为开始状态,触发开始事件")
|
||||||
|
self._on_experiment_started()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[初始状态检查] 实验{self.experiment_id}检查失败: {e}", exc_info=True)
|
||||||
|
|
||||||
def _on_experiment_started(self) -> None:
|
def _on_experiment_started(self) -> None:
|
||||||
"""实验开始事件处理"""
|
"""实验开始事件处理"""
|
||||||
try:
|
try:
|
||||||
|
|
@ -421,6 +597,19 @@ class ExperimentStateMonitor:
|
||||||
f"记录时间: {self._end_time_recorded}"
|
f"记录时间: {self._end_time_recorded}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 验证实验时长
|
||||||
|
if not self._validate_experiment_duration():
|
||||||
|
logger.warning(
|
||||||
|
f"[实验结束] ⚠️ 实验{self.experiment_id}时长不足3.5小时,"
|
||||||
|
f"标记为异常数据,不入库"
|
||||||
|
)
|
||||||
|
# 标记为作废状态
|
||||||
|
self._mark_experiment_as_invalid()
|
||||||
|
# 设置停止标志
|
||||||
|
self._stop_event.set()
|
||||||
|
logger.info(f"[实验结束] 🛑 异常实验已标记作废,监控退出")
|
||||||
|
return
|
||||||
|
|
||||||
# 更新数据库:设置end_ts
|
# 更新数据库:设置end_ts
|
||||||
self._update_experiment_end_time(self._end_time_recorded)
|
self._update_experiment_end_time(self._end_time_recorded)
|
||||||
|
|
||||||
|
|
@ -465,6 +654,82 @@ class ExperimentStateMonitor:
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _validate_experiment_duration(self) -> bool:
|
||||||
|
"""验证实验时长是否满足最小要求(3.5小时)"""
|
||||||
|
try:
|
||||||
|
if not self._start_time_recorded or not self._end_time_recorded:
|
||||||
|
logger.warning(f"[时长验证] 实验{self.experiment_id}缺少开始或结束时间")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 解析时间
|
||||||
|
start_dt = datetime.datetime.fromisoformat(self._start_time_recorded)
|
||||||
|
end_dt = datetime.datetime.fromisoformat(self._end_time_recorded)
|
||||||
|
|
||||||
|
# 计算时长(小时)
|
||||||
|
duration = (end_dt - start_dt).total_seconds() / 3600.0
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[时长验证] 实验{self.experiment_id}持续时长: {duration:.2f}小时 "
|
||||||
|
f"(开始: {self._start_time_recorded}, 结束: {self._end_time_recorded})"
|
||||||
|
)
|
||||||
|
|
||||||
|
# 最小时长要求:3.5小时
|
||||||
|
MIN_DURATION_HOURS = 3.5
|
||||||
|
|
||||||
|
if duration < MIN_DURATION_HOURS:
|
||||||
|
logger.warning(
|
||||||
|
f"[时长验证] ❌ 实验{self.experiment_id}时长{duration:.2f}小时 < "
|
||||||
|
f"{MIN_DURATION_HOURS}小时,不满足要求"
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[时长验证] ✅ 实验{self.experiment_id}时长{duration:.2f}小时 >= "
|
||||||
|
f"{MIN_DURATION_HOURS}小时,满足要求"
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
f"[时长验证] 实验{self.experiment_id}验证失败: {e}",
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _mark_experiment_as_invalid(self) -> None:
|
||||||
|
"""标记实验为作废状态(异常数据)"""
|
||||||
|
try:
|
||||||
|
from pathlib import Path
|
||||||
|
db_path = Path(__file__).parent / "experiments.db"
|
||||||
|
|
||||||
|
db = sqlite3.connect(str(db_path))
|
||||||
|
cur = db.cursor()
|
||||||
|
|
||||||
|
# 更新实验状态为作废,设置 is_terminated=1,并记录结束时间
|
||||||
|
cur.execute(
|
||||||
|
"""UPDATE experiments
|
||||||
|
SET end_ts=?,
|
||||||
|
is_terminated=1,
|
||||||
|
remark=CASE
|
||||||
|
WHEN remark IS NULL OR remark='' THEN '作废-时长不足3.5小时'
|
||||||
|
ELSE remark || ' [作废-时长不足3.5小时]'
|
||||||
|
END
|
||||||
|
WHERE id=?""",
|
||||||
|
(self._end_time_recorded, self.experiment_id)
|
||||||
|
)
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
logger.info(
|
||||||
|
f"[作废标记] ✅ 实验{self.experiment_id}已标记为作废状态 (is_terminated=1)"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(
|
||||||
|
f"[作废标记] 实验{self.experiment_id}标记失败: {e}",
|
||||||
|
exc_info=True
|
||||||
|
)
|
||||||
|
|
||||||
def _update_experiment_start_time(self, start_time: str) -> None:
|
def _update_experiment_start_time(self, start_time: str) -> None:
|
||||||
"""更新实验记录的开始时间"""
|
"""更新实验记录的开始时间"""
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,9 @@ def get_logger(name: str = "docx_creator") -> logging.Logger:
|
||||||
fmt = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
|
fmt = logging.Formatter("%(asctime)s [%(levelname)s] %(name)s: %(message)s")
|
||||||
handler.setFormatter(fmt)
|
handler.setFormatter(fmt)
|
||||||
logger.addHandler(handler)
|
logger.addHandler(handler)
|
||||||
# also log warnings+ to stderr for debugging
|
# also log INFO+ to stderr for debugging
|
||||||
stream = logging.StreamHandler()
|
stream = logging.StreamHandler()
|
||||||
stream.setLevel(logging.WARNING)
|
stream.setLevel(logging.INFO) # 改为 INFO 级别
|
||||||
stream.setFormatter(fmt)
|
stream.setFormatter(fmt)
|
||||||
logger.addHandler(stream)
|
logger.addHandler(stream)
|
||||||
_LOGGER = logger
|
_LOGGER = logger
|
||||||
|
|
|
||||||
|
|
@ -887,21 +887,24 @@ class Breaker:
|
||||||
self.optFlag = 3
|
self.optFlag = 3
|
||||||
|
|
||||||
def alarming(self):
|
def alarming(self):
|
||||||
|
"""报警时:红灯亮+蜂鸣器响,绿灯灭"""
|
||||||
if not self.alarm and self.closed & 0xFF == 0xF0:
|
if not self.alarm and self.closed & 0xFF == 0xF0:
|
||||||
self.exeCmd('turnOffGreen')
|
self.exeCmd('turnOffGreen')
|
||||||
self.exeCmd('turnOnRed')
|
self.exeCmd('turnOnRed')
|
||||||
self.exeCmd('turnOnAlarm')
|
self.exeCmd('turnOnAlarm')
|
||||||
|
self.alarm = 1 # 设置报警标志
|
||||||
|
|
||||||
def unalarming(self):
|
def unalarming(self):
|
||||||
|
"""解除报警:根据合闸状态控制指示灯"""
|
||||||
if self.alarm:
|
if self.alarm:
|
||||||
|
self.exeCmd('turnOffRed')
|
||||||
|
self.exeCmd('turnOffAlarm')
|
||||||
|
# 如果是合闸状态,恢复绿灯
|
||||||
if self.closed & 0xFF == 0xF0:
|
if self.closed & 0xFF == 0xF0:
|
||||||
self.exeCmd('turnOnGreen')
|
self.exeCmd('turnOnGreen')
|
||||||
self.exeCmd('turnOffRed')
|
|
||||||
self.exeCmd('turnOffAlarm')
|
|
||||||
else:
|
else:
|
||||||
self.exeCmd('turnOffGreen')
|
self.exeCmd('turnOffGreen')
|
||||||
self.exeCmd('turnOffRed')
|
self.alarm = 0 # 清除报警标志
|
||||||
self.exeCmd('turnOffAlarm')
|
|
||||||
|
|
||||||
def open(self):
|
def open(self):
|
||||||
"""打开串口连接"""
|
"""打开串口连接"""
|
||||||
|
|
@ -926,6 +929,10 @@ class Breaker:
|
||||||
case 0:
|
case 0:
|
||||||
if self.open() == 0:
|
if self.open() == 0:
|
||||||
ret0 = self.exeCmd('openBreaker')
|
ret0 = self.exeCmd('openBreaker')
|
||||||
|
# 初始化时关闭所有指示灯
|
||||||
|
self.exeCmd('turnOffGreen')
|
||||||
|
self.exeCmd('turnOffRed')
|
||||||
|
self.exeCmd('turnOffAlarm')
|
||||||
# self.logger.info(f"setOverLimitValues ret: {ret0}")
|
# self.logger.info(f"setOverLimitValues ret: {ret0}")
|
||||||
ret1 = self.exeCmd('setOverLimitValues')
|
ret1 = self.exeCmd('setOverLimitValues')
|
||||||
# self.logger.info(f"setOverLimitValues ret: {ret1}")
|
# self.logger.info(f"setOverLimitValues ret: {ret1}")
|
||||||
|
|
@ -952,6 +959,11 @@ class Breaker:
|
||||||
case 2:
|
case 2:
|
||||||
ret = self.exeCmd('openBreaker')
|
ret = self.exeCmd('openBreaker')
|
||||||
if ret[0]:
|
if ret[0]:
|
||||||
|
# 分闸成功后,关闭所有指示灯
|
||||||
|
self.exeCmd('turnOffGreen')
|
||||||
|
self.exeCmd('turnOffRed')
|
||||||
|
self.exeCmd('turnOffAlarm')
|
||||||
|
self.alarm = 0 # 清除报警标志
|
||||||
self.optFlag = 1
|
self.optFlag = 1
|
||||||
continue
|
continue
|
||||||
self.optFlag = -1
|
self.optFlag = -1
|
||||||
|
|
@ -959,6 +971,9 @@ class Breaker:
|
||||||
case 3:
|
case 3:
|
||||||
ret = self.exeCmd('closeBreaker')
|
ret = self.exeCmd('closeBreaker')
|
||||||
if ret[0]:
|
if ret[0]:
|
||||||
|
# 合闸成功后,点亮绿灯(如果没有报警)
|
||||||
|
# if not self.alarm:
|
||||||
|
self.exeCmd('turnOnGreen')
|
||||||
self.optFlag = 1
|
self.optFlag = 1
|
||||||
continue
|
continue
|
||||||
self.optFlag = -1
|
self.optFlag = -1
|
||||||
|
|
|
||||||
14
ui_main.py
14
ui_main.py
|
|
@ -5039,16 +5039,18 @@ class MainWindow(QMainWindow):
|
||||||
|
|
||||||
if row:
|
if row:
|
||||||
start_ts, end_ts = row
|
start_ts, end_ts = row
|
||||||
# 如果实验已完成(有结束时间),退出等待状态
|
# 只有实验已完成(有结束时间)时,才退出等待状态
|
||||||
if end_ts is not None:
|
if end_ts is not None:
|
||||||
self.logger.info(f"[等待状态] ✅ 实验 {self._waiting_experiment_id} 已完成,自动退出等待状态")
|
self.logger.info(f"[等待状态] ✅ 实验 {self._waiting_experiment_id} 已完成,自动退出等待状态")
|
||||||
self.statusBar().showMessage("✅ 实验已完成", 3000)
|
self.statusBar().showMessage("✅ 实验已完成", 3000)
|
||||||
self._exit_waiting_state()
|
self._exit_waiting_state()
|
||||||
elif start_ts is not None:
|
elif start_ts is not None:
|
||||||
# 实验已开始(进行中),也退出等待状态
|
# 实验已开始但未结束,更新提示为"等待实验结束"
|
||||||
self.logger.info(f"[等待状态] 🔄 实验 {self._waiting_experiment_id} 已开始,自动退出等待状态")
|
self.logger.info(f"[等待状态] 🔄 实验 {self._waiting_experiment_id} 已开始,继续监控等待结束")
|
||||||
self.statusBar().showMessage("🔄 实验已开始", 3000)
|
# 更新等待标签文本
|
||||||
self._exit_waiting_state()
|
work_order_no = self.waiting_label.text().split("工单号: ")[-1] if "工单号:" in self.waiting_label.text() else "未知"
|
||||||
|
self.waiting_label.setText(f"⏳ 等待实验结束 - 工单号: {work_order_no}")
|
||||||
|
self.statusBar().showMessage("🔄 实验进行中,等待结束...", 3000)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"[等待状态] ⏳ 实验 {self._waiting_experiment_id} 仍在等待开始")
|
self.logger.info(f"[等待状态] ⏳ 实验 {self._waiting_experiment_id} 仍在等待开始")
|
||||||
else:
|
else:
|
||||||
|
|
@ -5207,7 +5209,7 @@ class MainWindow(QMainWindow):
|
||||||
query_config=query_config,
|
query_config=query_config,
|
||||||
on_state_changed=self._on_monitor_state_changed,
|
on_state_changed=self._on_monitor_state_changed,
|
||||||
on_connection_changed=self._on_monitor_connection_changed,
|
on_connection_changed=self._on_monitor_connection_changed,
|
||||||
poll_interval=5 # 每5秒查询一次
|
poll_interval=1 # 每1秒查询一次(避免错过快速状态变化)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 启动监控器
|
# 启动监控器
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue