refactor(ota): 移除ESP32 OTA架构中的高危设计问题并优化状态管理

- 移除OtaRelay职责过载问题,将状态查询统一收口到OtaCoordinator::getSnapshot()
- 新增OtaSnapshot结构体,一次性获取完整的OTA系统状态快照,避免分散读取
- 将GD32 APP探测逻辑从system_status_handler中分离,提供独立的/system/probe端点
- 修复并发安全隐患,确保processEvent()读取relayState时持有锁保护
- 优化SPI通信相关代码结构,提升系统稳定性

BREAKING CHANGE: 移除了原有的分散状态查询接口,统一使用快照方式获取状态
This commit is contained in:
小龙虾
2026-06-23 00:05:56 +08:00
parent 1491e9a3de
commit 7a41eac526
11 changed files with 236 additions and 189 deletions
+51
View File
@@ -8,10 +8,12 @@
#include "esp32_ota_core.h"
#include "relay/ota_relay.h"
#include "storage/gd32_flash_store.h"
#include "transport/spi_master.h"
#include "monitor/debug_log.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <inttypes.h>
#define TAG "OTA_COORD"
@@ -599,6 +601,55 @@ bool OtaCoordinator::isGd32StorageDone() const
return done;
}
// ============================================================
// OTA 状态快照(PR1: 收口状态读取)
// ============================================================
OtaSnapshot OtaCoordinator::getSnapshot() const
{
OtaSnapshot snap{};
// ── coordinator 自身状态(一次 mutex)──
bool h = lock();
if (h) {
snap.sys_state = m_sysState;
snap.storage_done = m_gd32StorageDone;
unlock(h);
}
snap.sys_state_str = getSystemStateString();
// ── GD32 NVS 元数据 ──
Gd32FlashStore::instance().metaLoad(&snap.meta);
// ── relay 进度(一次 relay mutex)──
snap.relay = OtaRelay::getSnapshot();
return snap;
}
// ============================================================
// GD32 APP 探测(PR2: 从 /system/status 移出)
// ============================================================
esp_err_t OtaCoordinator::probeGd32AppOnce(gd32_version_t *out_version, uint32_t *out_uptime)
{
uint32_t uptime = 0;
gd32_version_t ver = {};
esp_err_t err = SpiMaster::instance().appPing(500, &uptime, &ver);
if (err == ESP_OK) {
OtaRelay::setGd32AppAlive(true);
OtaRelay::setGd32Version(ver);
if (out_version) *out_version = ver;
if (out_uptime) *out_uptime = uptime;
DEBUG_INFO(TAG, "GD32 APP 探测成功: alive, uptime=%" PRIu32 "s", uptime);
} else {
OtaRelay::setGd32AppAlive(false);
if (out_version) *out_version = ver;
if (out_uptime) *out_uptime = 0;
DEBUG_WARN(TAG, "GD32 APP 探测失败: %s", esp_err_to_name(err));
}
return err;
}
// ============================================================
// 完全复位
// ============================================================
+35 -1
View File
@@ -20,7 +20,7 @@
#include "freertos/semphr.h"
#include "esp_err.h"
#include "storage/gd32_flash_store.h"
#include "relay/ota_relay.h" // IRelayListener 接口定义(H4 解耦)
#include "relay/ota_relay.h" // IRelayListener 接口定义 + RelaySnapshot(H4 解耦)
// ============================================================
// 系统级 OTA 状态枚举
@@ -37,6 +37,22 @@ typedef enum {
OTA_SYS_ERROR // 错误状态
} ota_system_state_t;
// ============================================================
// OTA 系统全量只读快照(PR1: 收口状态读取)
// ============================================================
/**
* @brief OTA 系统全量只读快照。
* 由 OtaCoordinator::getSnapshot() 一次性填充,
* 供 /system/status 等只读接口消费,避免散读各模块状态。
*/
struct OtaSnapshot {
ota_system_state_t sys_state = OTA_SYS_IDLE; ///< 系统级 OTA 状态
const char *sys_state_str = "IDLE"; ///< 状态字符串
bool storage_done = false; ///< GD32 固件存储完成标志
ota_meta_t meta = {}; ///< GD32 NVS 元数据
RelaySnapshot relay; ///< 中继进度快照
};
// ============================================================
// IBleCoexListener - BLE 射频共存通知接口(解决 L1 横向耦合)
// ============================================================
@@ -242,6 +258,24 @@ public:
void abortCurrent();
// ── 状态查询 ──
/**
* @brief 一次性读取系统 OTA 全量状态快照(PR1: 收口状态读取)。
* coordinator mutex + relay mutex 各取一次,
* 供 /system/status 等只读接口消费。
* @return 包含 sys_state、meta、relay 进度的完整快照。
*/
OtaSnapshot getSnapshot() const;
/**
* @brief 单次 SPI 探测 GD32 APP 是否存活(PR2: 从 status 移出)。
* 成功时更新 OtaRelay 缓存的 alive/version,
* 失败时清除 alive 标志。
* @param out_version 输出版本信息,可为 nullptr。
* @param out_uptime 输出 GD32 运行时间(秒),可为 nullptr。
* @return ESP_OK 存活,其他失败。
*/
esp_err_t probeGd32AppOnce(gd32_version_t *out_version, uint32_t *out_uptime);
/**
* @brief 获取当前系统级 OTA 状态。
* @return 当前 ota_system_state_t 状态值。
+16
View File
@@ -0,0 +1,16 @@
/*
* ota_snapshot.h - OTA 状态只读快照(便捷聚合头文件)
*
* 本文件本身不包含结构体定义,仅聚合两个快照来源:
* - RelaySnapshot → 定义在 relay/ota_relay.h(一次锁保护读取 relay 进度)
* - OtaSnapshot → 定义在 ota/ota_coordinator.h(coordinator + meta + relay 快照)
*
* HTTP handler 等消费方只需 #include "ota/ota_snapshot.h" 即可使用两种快照。
*/
#ifndef OTA_SNAPSHOT_H
#define OTA_SNAPSHOT_H
#include "relay/ota_relay.h" // RelaySnapshot
#include "ota/ota_coordinator.h" // OtaSnapshot
#endif // OTA_SNAPSHOT_H