feat(main): 将全局函数重构为单例类模式

- 将 debug_log 模块重构为 DebugLog 单例类,封装 UART、UDP 和环形缓冲区日志输出
- 将 health_monitor 模块重构为 HealthMonitor 单例类,统一健康状态管理和监控逻辑
- 更新 main.cpp 中的初始化调用,使用单例实例替代原有全局函数
- 添加健康监控任务作为第四个 FreeRTOS 任务,增强系统监控能力
- 更新固件版本从 0.2.11 到 0.3.0,反映架构重大变更
This commit is contained in:
小龙虾
2026-05-31 03:20:26 +08:00
parent 56f26fa0d1
commit 1586a81b97
16 changed files with 1501 additions and 2245 deletions
+35 -106
View File
@@ -1,7 +1,9 @@
/*
/*
* protocol.h - 帧格式、CRC16、AES 加密解密
* T2.2, T1.3
* ESP-IDF 6.0 适配版本 - 使用硬件 AES-128-CBC + 硬件 RNG
*
* Protocol 类封装协议层功能。
*/
#ifndef PROTOCOL_H
#define PROTOCOL_H
@@ -50,115 +52,42 @@ typedef struct {
} session_ctx_t;
/**
* @brief 初始化协议层资源,建立 CRC/AES 等基础能力的可用状态。
* @brief 协议层类(单例)
*
* 封装 CRC16、AES-128-CBC、帧构建/解析、会话管理等功能。
* 大部分方法为静态工具方法,单例仅持有初始化标志。
*/
void protocol_init(void);
class Protocol {
public:
static Protocol& instance();
/**
* @brief 计算一段数据的 CRC16-Modbus 校验值。
* @param data 待校验的数据指针。
* @param len 数据长度(字节)。
* @return CRC16 校验值。
*/
uint16_t crc16_modbus(const uint8_t *data, size_t len);
void init();
/**
* @brief 按协议格式构建一帧数据,返回生成后的总帧长度。
* @param cmd 命令码。
* @param payload 负载数据指针,可为 NULL。
* @param len 负载长度(字节)。
* @param out_frame 输出帧缓冲区。
* @return 帧总长度,失败返回 -1。
*/
int frame_build(uint8_t cmd, const uint8_t *payload, size_t len, uint8_t *out_frame);
static uint16_t crc16Modbus(const uint8_t *data, size_t len);
static int buildFrame(uint8_t cmd, const uint8_t *payload, size_t len, uint8_t *out_frame);
static int parseFrame(const uint8_t *frame, size_t frame_len,
uint8_t *out_cmd, uint8_t *out_payload, size_t *out_len);
static int aesEncrypt(const uint8_t *plaintext, size_t len,
const uint8_t *key, const uint8_t *iv,
uint8_t *ciphertext_out);
static int aesDecrypt(const uint8_t *ciphertext, size_t len,
const uint8_t *key, const uint8_t *iv,
uint8_t *plaintext_out);
static void scrambleGenerate(uint32_t timestamp, uint32_t mem_addr,
uint32_t rand_seed, uint8_t *nonce_out);
static int sessionKeyInit(session_ctx_t *sess, const uint8_t *k_session);
static void sessionKeyClear(session_ctx_t *sess);
static int sessionEncrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out);
static int sessionDecrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out);
static void generateRandomNonce(uint8_t *nonce, size_t len);
/**
* @brief 解析一帧协议数据,提取命令字、负载和长度,失败返回 -1。
* @param frame 待解析的帧数据。
* @param frame_len 帧数据总长度。
* @param out_cmd 输出参数,解析出的命令码。
* @param out_payload 输出缓冲区,存放解析出的负载。
* @param out_len 输出参数,负载实际长度。
* @return 0 成功,-1 失败。
*/
int frame_parse(const uint8_t *frame, size_t frame_len,
uint8_t *out_cmd, uint8_t *out_payload, size_t *out_len);
private:
Protocol() = default;
~Protocol() = default;
Protocol(const Protocol&) = delete;
Protocol& operator=(const Protocol&) = delete;
/**
* @brief 使用 AES-128-CBC 对明文进行加密,返回密文长度,失败返回负值。
* @param plaintext 明文数据。
* @param len 明文长度(字节)。
* @param key 128 位 AES 密钥。
* @param iv 128 位 CBC 初始向量。
* @param ciphertext_out 输出缓冲区,存放密文。
* @return 密文长度,失败返回 -1。
*/
int protocol_aes_encrypt(const uint8_t *plaintext, size_t len,
const uint8_t *key, const uint8_t *iv,
uint8_t *ciphertext_out);
/**
* @brief 使用 AES-128-CBC 对密文进行解密,返回去除填充后的明文长度。
* @param ciphertext 密文数据。
* @param len 密文长度(字节,须为 16 的倍数)。
* @param key 128 位 AES 密钥。
* @param iv 128 位 CBC 初始向量。
* @param plaintext_out 输出缓冲区,存放解密后的明文。
* @return 明文长度,失败返回 -1。
*/
int protocol_aes_decrypt(const uint8_t *ciphertext, size_t len,
const uint8_t *key, const uint8_t *iv,
uint8_t *plaintext_out);
/**
* @brief 根据时间戳、内存地址和随机种子生成 16 字节随机数。
* @param timestamp 时间戳种子。
* @param mem_addr 内存地址种子。
* @param rand_seed 随机数种子。
* @param nonce_out 输出缓冲区,存放生成的 16 字节随机数。
*/
void scramble_generate(uint32_t timestamp, uint32_t mem_addr,
uint32_t rand_seed, uint8_t *nonce_out);
/**
* @brief 用给定会话密钥初始化会话上下文。
* @param sess 待初始化的会话上下文。
* @param k_session 128 位会话密钥。
* @return 0 成功,-1 失败。
*/
int session_key_init(session_ctx_t *sess, const uint8_t *k_session);
/**
* @brief 清除会话上下文中的密钥与状态信息。
* @param sess 待清除的会话上下文。
*/
void session_key_clear(session_ctx_t *sess);
/**
* @brief 使用当前会话上下文对输入数据执行加密。
* @param sess 会话上下文。
* @param in 输入明文。
* @param len 数据长度。
* @param out 输出密文缓冲区。
* @return 密文长度,失败返回 -1。
*/
int session_encrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out);
/**
* @brief 使用当前会话上下文对输入数据执行解密。
* @param sess 会话上下文。
* @param in 输入密文。
* @param len 数据长度。
* @param out 输出明文缓冲区。
* @return 明文长度,失败返回 -1。
*/
int session_decrypt(session_ctx_t *sess, const uint8_t *in, size_t len, uint8_t *out);
/**
* @brief 使用 ESP-IDF 硬件 RNG 生成指定长度的随机数。
* @param nonce 输出缓冲区。
* @param len 随机数字节数。
*/
void generate_random_nonce(uint8_t *nonce, size_t len);
bool m_initialized = false;
};
#endif // PROTOCOL_H