generated from hulk/gd32f4xx_template_cmake_vscode
GUI v0.2.9: fix chronic-lag root cause (log trim crash on PySide6 6.11) + 5 hardening fixes
- log trim used instance-level enum access (removed in PySide6 6.11), crashed
This commit is contained in:
+33
-14
@@ -60,7 +60,7 @@ import config
|
||||
import filmforge_rs485 as ff
|
||||
|
||||
APP_NAME = "FilmForge"
|
||||
APP_VERSION = "0.2.7"
|
||||
APP_VERSION = "0.2.9"
|
||||
REPO_URL = "https://gitea.hulk.wang/hulk/FilmForge"
|
||||
MONO = QFont("Consolas", 10)
|
||||
CHIP_IDLE = "#666666"
|
||||
@@ -69,6 +69,7 @@ CHIP_ERR = "#D9534F"
|
||||
CHIP_WARN = "#E8833A"
|
||||
PENDING_TIMEOUT = 1.2 # 应答超时(秒): 协议建议 300ms 重发, 监视台不自动重发只提示
|
||||
RESPONSE_FRESH = 0.5 # 应答新鲜度: 该窗口内的温度帧优先按“查询应答”派发
|
||||
MAX_FAULTS = 1000 # 故障标记内存上限(条): NTC 抖动场景防无限增长
|
||||
|
||||
CHART_COLORS_DARK = dict(bg="#242424", grid="#3a3a3a", text="#c9c9c9",
|
||||
measured="#00c8d7", target=CHIP_WARN, fault=CHIP_ERR)
|
||||
@@ -133,7 +134,7 @@ class TemperatureChart(QWidget):
|
||||
ts, vs = self._samples_t, self._samples_v
|
||||
if not ts:
|
||||
return [], []
|
||||
lo, hi = 0, len(ts) # 二分找左边界(留一点前文保证连线)
|
||||
lo, hi = 0, len(ts) # 左边界二分(留一点前文保证连线)
|
||||
while lo < hi:
|
||||
m = (lo + hi) // 2
|
||||
if ts[m] < t0:
|
||||
@@ -141,7 +142,14 @@ class TemperatureChart(QWidget):
|
||||
else:
|
||||
hi = m
|
||||
lo = max(lo - 1, 0)
|
||||
t_out, v_out = ts[lo:], vs[lo:]
|
||||
end, hi = lo, len(ts) # 右边界二分: 暂停(冻结)后不切冻结尾后新样本
|
||||
while end < hi:
|
||||
m = (end + hi) // 2
|
||||
if ts[m] <= t1:
|
||||
end = m + 1
|
||||
else:
|
||||
hi = m
|
||||
t_out, v_out = ts[lo:end], vs[lo:end]
|
||||
if len(t_out) > 4000:
|
||||
stride = math.ceil(len(t_out) / 4000)
|
||||
gt, gv = [], []
|
||||
@@ -674,6 +682,9 @@ class App(QMainWindow):
|
||||
self.txt_log.setFont(MONO)
|
||||
self.txt_log.setLineWrapMode(QPlainTextEdit.NoWrap)
|
||||
self.txt_log.setMinimumHeight(200)
|
||||
# 裁剪走原生环形上限: 手工 cursor 裁剪在 PySide6 6.11 上抛 AttributeError
|
||||
# (实例级枚举访问已移除), 曾致每 tick 异常中止 + 日志无限增长 + 显示滞后
|
||||
self.txt_log.setMaximumBlockCount(500)
|
||||
body.addWidget(self.txt_log)
|
||||
self._log(f"帧格式: D5 01 LEN <命令> CRC / B5 TYPE LEN <payload> CRC; "
|
||||
f"响应超时建议 {ff.REPLY_TIMEOUT * 1000:.0f}ms 重发")
|
||||
@@ -959,6 +970,8 @@ class App(QMainWindow):
|
||||
self.samples_t.append(t)
|
||||
self.samples_v.append(float("nan"))
|
||||
self.faults.append((t, code))
|
||||
if len(self.faults) > MAX_FAULTS: # 封顶: 抖动场景不无限增长(_draw_faults 按 paint 全量扫描)
|
||||
del self.faults[:len(self.faults) - MAX_FAULTS]
|
||||
self.lbl_temp.setText("—.— ℃")
|
||||
self._csv_write(t, code, ok=False)
|
||||
self.chart.update()
|
||||
@@ -1266,9 +1279,19 @@ class App(QMainWindow):
|
||||
target = f"{self.target_hist[-1][1]:g}" if self.target_hist else ""
|
||||
heater = self.heater_state or ""
|
||||
sensor = self.sensor_state or ("OK" if ok else "")
|
||||
self._csv.write(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(t))},"
|
||||
f"{t - self._csv_t0:.3f},{temp_text},{target},{heater},{sensor}\n")
|
||||
self._csv.flush()
|
||||
try:
|
||||
self._csv.write(f"{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(t))},"
|
||||
f"{t - self._csv_t0:.3f},{temp_text},{target},{heater},{sensor}\n")
|
||||
self._csv.flush()
|
||||
except OSError as e:
|
||||
# 写失败(磁盘满/记录盘被拔): 自动停记录。本函数在 _tick 帧处理路径上,
|
||||
# 未捕获异常会中止整段消费(与 v0.2.8 日志裁剪同款失效管道, 勿回退)
|
||||
self._csv.close()
|
||||
self._csv = None
|
||||
self.btn_csv.setText("开始记录")
|
||||
self.lbl_csv.setText(f"记录失败已停止: {e}")
|
||||
self._log(f"⚠ CSV 记录失败已停止: {e}")
|
||||
return
|
||||
self._csv_count += 1
|
||||
self.lbl_csv.setText(f"记录中({self._csv_count} 行) → "
|
||||
f"{os.path.basename(self._csv_path)}")
|
||||
@@ -1279,15 +1302,11 @@ class App(QMainWindow):
|
||||
|
||||
# ================= 日志 =================
|
||||
def _log(self, line):
|
||||
self.txt_log.appendPlainText(time.strftime("%H:%M:%S ") + line)
|
||||
if self.txt_log.blockCount() > 500:
|
||||
cursor = self.txt_log.textCursor()
|
||||
cursor.movePosition(cursor.Start)
|
||||
cursor.select(cursor.BlockUnderCursor)
|
||||
cursor.removeSelectedText()
|
||||
cursor.deleteChar()
|
||||
sb = self.txt_log.verticalScrollBar()
|
||||
sb.setValue(sb.maximum())
|
||||
at_bottom = sb.value() >= sb.maximum() - 4
|
||||
self.txt_log.appendPlainText(time.strftime("%H:%M:%S ") + line)
|
||||
if at_bottom: # 仅原本贴底时跟随, 不抢用户上翻看历史
|
||||
sb.setValue(sb.maximum())
|
||||
|
||||
def _clear_log(self):
|
||||
self.txt_log.clear()
|
||||
|
||||
Reference in New Issue
Block a user