feat(can): 优化批量发送性能并修复竞态问题

- 帧间添加5ms延时,暂停CAN反馈避免与批量SPI竞争导致偶发崩溃
- 单次批量容量从48帧提升至128帧,最大body大小从12KB增至48KB
- 单帧超时从400ms降至80ms,失败后不再拖慢整体速度
- 暂停0xC1反馈任务降低worker竞态和WDT风险
- 中途致命错误后跳过后续帧发送,避免每帧等待超时
- 添加详细的JSON错误响应格式
- 修复内存分配失败时的资源清理问题

refactor(wifi): 优化冷启动流程避免电源竞争

- 电源轨稳定等待策略调整:POWERON/BROWNOUT复位时等待200ms
- 仅BROWNOUT复位后清除PHY校准数据,避免每次上电全量校准
- 电源稳定等待期间等待400ms后再进行NVS/WiFi操作
- WiFi启动前延时从500ms调整为300ms
- BOD阈值适当放宽避免上电瞬间复位

perf(monitor): 调整堆内存监控策略

- 内存紧张时增大健康监控间隔:低于8KB时从3s增至10s
- 避免日志输出消耗更多堆内存造成雪崩效应

docs(readme): 更新冷启动优化说明

- 详细描述电源轨稳定等待机制
- 说明仅BROWNOUT后才强制PHY重校准的策略
- 解释避免与GD32抢电流的设计考虑

style(html): 更新前端资源版本号

- 更新CSS和JavaScript文件的版本参数
- 修复页面加载时的资源缓存问题

fix(ble): 修复阶段显示状态问题

- 终态阶段全部显示为完成状态(绿色)
- 优化状态栏样式更新逻辑

feat(ota): 优化SPI通信超时处理

- 将总超时拆分为发送和轮询两个阶段
- 禁止轮询单独占用500ms避免短超时批量卡顿
- 优化极短超时情况下的时间分配策略

refactor(can): 减少批量操作时的日志输出

- SPI失败和GD32拒绝时按类型聚合日志
- 每32次相同错误才输出一次完整日志
- 避免大量错误时UDP/格式化耗尽堆内存
This commit is contained in:
小龙虾
2026-07-17 00:24:09 +08:00
parent 5db3f66b8e
commit 6364eacfb1
19 changed files with 256 additions and 116 deletions
+4 -4
View File
@@ -7,10 +7,10 @@
* common/utils.js(escapeHtml/formatBytes)、
* signals.js(renderInlineSignalGrid/ensureMessageDefaults/renderSelectedMessage/updateEncodedPreview)。
*/
import { state, el, padHex, normalizeWhitespace, cssEscape } from './dbc.js?v=20260717t';
import { escapeHtml as sanitizeHtml, formatBytes } from '../common/utils.js?v=20260717t';
import { renderInlineSignalGrid, ensureMessageDefaults, renderSelectedMessage, updateEncodedPreview } from './signals.js?v=20260717t';
import { scheduleCanPersist } from './persist.js?v=20260717t';
import { state, el, padHex, normalizeWhitespace, cssEscape } from './dbc.js?v=20260717v';
import { escapeHtml as sanitizeHtml, formatBytes } from '../common/utils.js?v=20260717v';
import { renderInlineSignalGrid, ensureMessageDefaults, renderSelectedMessage, updateEncodedPreview } from './signals.js?v=20260717v';
import { scheduleCanPersist } from './persist.js?v=20260717v';
// ==================== DBC 文件信息 ====================
/** @description 更新 DBC 文件信息卡片(文件名/报文数/信号数/节点数/大小)。 */
+1 -1
View File
@@ -6,7 +6,7 @@
*
* 依赖:dbc.js(state/el/parseDbc/rebuildMergedDbc)
*/
import { state, el, parseDbc, rebuildMergedDbc } from './dbc.js?v=20260717t';
import { state, el, parseDbc, rebuildMergedDbc } from './dbc.js?v=20260717v';
var LS_KEY = 'dcu_can_session_v1';
var MAX_HISTORY = 200;
+21 -10
View File
@@ -12,12 +12,12 @@
* 注意:formatTime 保留本地实现(HH:MM:SS,不含毫秒),与 common/utils.js
* 的 formatTime(含毫秒)不同,以保证发送历史时间戳输出格式一致。
*/
import { state, el, getBaseUrl, padHex, bytesToHex, parseNumericId } from './dbc.js?v=20260717t';
import { escapeHtml as sanitizeHtml } from '../common/utils.js?v=20260717t';
import { showToast } from '../common/toast.js?v=20260717t';
import { updateBatchUi } from './messages.js?v=20260717t';
import { ensureMessageDefaults, getSignalValueMap, getSelectedMessage, updateEncodedPreview, encodeMessageData } from './signals.js?v=20260717t';
import { scheduleCanPersist } from './persist.js?v=20260717t';
import { state, el, getBaseUrl, padHex, bytesToHex, parseNumericId } from './dbc.js?v=20260717w';
import { escapeHtml as sanitizeHtml } from '../common/utils.js?v=20260717w';
import { showToast } from '../common/toast.js?v=20260717w';
import { updateBatchUi } from './messages.js?v=20260717w';
import { ensureMessageDefaults, getSignalValueMap, getSelectedMessage, updateEncodedPreview, encodeMessageData } from './signals.js?v=20260717w';
import { scheduleCanPersist } from './persist.js?v=20260717w';
// ==================== 本地工具(保持与原 can.js 一致) ====================
function formatTime(date) {
@@ -109,7 +109,18 @@ async function sendCanBatchRequest(channel, frames) {
if (!json.results || !Array.isArray(json.results)) {
throw new Error('批量响应缺少 results');
}
return json.results;
/* 设备中途 fatal 会 skipped 剩余帧(少分配堆);前端补齐等长 results */
var results = json.results.slice();
var need = frames.length - results.length;
if (need > 0) {
var pad = {
status: 'error',
code: (json.abort_code != null) ? json.abort_code : -2,
gd32_err: (json.abort_gd32_err != null) ? json.abort_gd32_err : 0
};
for (var p = 0; p < need; p++) results.push(pad);
}
return results;
}
// ==================== 响应框 ====================
@@ -161,12 +172,12 @@ export function renderHistory() {
}
// ==================== 批量发送 ====================
/** 单批最多帧数(与设备 /can/send_batch 上限一致) */
var BATCH_CHUNK = 48;
/** 单批最多帧数(与设备 /can/send_batch 上限 128 对齐;一次 HTTP 连发,避免分块成“一阵一阵”) */
var BATCH_CHUNK = 128;
/**
* @description 批量发送所有勾选的报文。
* 优先一次 HTTP /can/send_batch 在设备侧紧接连发;失败则回退单帧紧接。
* 优先一次 HTTP /can/send_batch(设备侧帧间 5ms);失败则回退单帧(无额外间隔)。
* 批量过程中不重绘历史,结束后统一刷新。
*/
export async function sendCheckedMessages() {
+3 -3
View File
@@ -6,9 +6,9 @@
*
* 依赖:dbc.js(state/el/padHex/bytesToHex/cssEscape/findSignal)、common/utils.js(escapeHtml)。
*/
import { state, el, padHex, bytesToHex, cssEscape, findSignal } from './dbc.js?v=20260717t';
import { escapeHtml as sanitizeHtml } from '../common/utils.js?v=20260717t';
import { scheduleCanPersist } from './persist.js?v=20260717t';
import { state, el, padHex, bytesToHex, cssEscape, findSignal } from './dbc.js?v=20260717v';
import { escapeHtml as sanitizeHtml } from '../common/utils.js?v=20260717v';
import { scheduleCanPersist } from './persist.js?v=20260717v';
// ==================== 信号值存取 ====================
/** @description 确保报文有 signalValues bag,并为每个信号填充默认值。返回 bag。 */