Initial commit: CCU621_M firmware project with BLE debug link support.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,441 @@
|
||||
/**
|
||||
* @file unsettled_order_mng.c
|
||||
* @brief 未结算订单列表:EEPROM 持久化与 CRC 校验
|
||||
*
|
||||
* 功能说明:
|
||||
* - 在 EEPROM `EEPROM_ADDR_UNSETTLED_MNG` 保存 `S_UNSETTLED_ORDER_MNG`:头标志 `UNSETTLED_HEADER`、
|
||||
* 未结条数、以及除 CRC 字段外的 CRC-16 校验(与 `u16_calculate_crc` 一致)。
|
||||
* - 每条未结订单仅保存其 Flash 订单号(`u32_chg_order_save_record` 返回的 `u32_index`)的 24 位压缩形式,
|
||||
* 最多 `UNSETTLED_MAX_CNT` 条;列表按顺序追加,删除时前移尾部元素。
|
||||
* - `u8_check_order_settled`:返回 1 表示该索引仍在未结列表中(未结算),0 表示不在列表中(视为已结或从未登记)。
|
||||
* 命名与注释以头文件为准。
|
||||
*/
|
||||
|
||||
#include "unsettled_order_mng.h"
|
||||
#include "mylog/mylog.h"
|
||||
|
||||
/* 本文件打印使能:0=不编译打印,1=编译打印 */
|
||||
#ifndef UNSETTLED_MNG_LOG_EN
|
||||
#define UNSETTLED_MNG_LOG_EN (1)
|
||||
#endif
|
||||
|
||||
#if UNSETTLED_MNG_LOG_EN
|
||||
#define UNSETTLED_MNG_LOG(fmt, ...) MYLOG_MSG(TASK_ID_Meterfee, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define UNSETTLED_MNG_LOG(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
/*------ Local variables(局部变量) ----------------------*/
|
||||
|
||||
// 未结算订单管理信息全局变量
|
||||
S_UNSETTLED_ORDER_MNG s_unsettledOrderMng;
|
||||
|
||||
/*------ Local function prototypes(局部函数声明) ---------*/
|
||||
|
||||
static void v_write_eeprom_unsettledMng(S_UNSETTLED_ORDER_MNG *unsettledMng);
|
||||
static void v_read_eeprom_unsettledMng(S_UNSETTLED_ORDER_MNG *unsettledMng);
|
||||
static U16_T u16_calculate_unsettled_crc(S_UNSETTLED_ORDER_MNG *unsettledMng);
|
||||
static U8_T u8_find_order_index(U32_T orderIndex, U16_T *position);
|
||||
static void v_uint32_to_3bytes(U32_T value, U8_T *bytes);
|
||||
static U32_T u32_3bytes_to_uint32(const U8_T *bytes);
|
||||
|
||||
/*------ Exported functions(导出函数实现) ----------------*/
|
||||
|
||||
/**
|
||||
* @brief 初始化未结算订单管理模块
|
||||
*/
|
||||
void v_unsettled_order_init(void)
|
||||
{
|
||||
// 读取EEPROM中的管理信息
|
||||
v_read_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
|
||||
// 检查数据完整性
|
||||
if (s_unsettledOrderMng.u16_head != UNSETTLED_HEADER)
|
||||
{
|
||||
// 头标志错误,初始化默认值
|
||||
s_unsettledOrderMng.u16_head = UNSETTLED_HEADER;
|
||||
s_unsettledOrderMng.u16_unsettledCnt = 0;
|
||||
|
||||
// 清空索引数组(3字节数组)
|
||||
for (U16_T i = 0; i < UNSETTLED_MAX_CNT; i++)
|
||||
{
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][2] = 0;
|
||||
}
|
||||
|
||||
// 计算并保存CRC
|
||||
s_unsettledOrderMng.u16_crc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
v_write_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: init default");
|
||||
}
|
||||
else
|
||||
{
|
||||
// 验证CRC
|
||||
U16_T calculatedCrc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
if (calculatedCrc != s_unsettledOrderMng.u16_crc)
|
||||
{
|
||||
// CRC校验失败,恢复默认值
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: CRC fail, reset default");
|
||||
s_unsettledOrderMng.u16_unsettledCnt = 0;
|
||||
|
||||
// 清空索引数组(3字节数组)
|
||||
for (U16_T i = 0; i < UNSETTLED_MAX_CNT; i++)
|
||||
{
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][2] = 0;
|
||||
}
|
||||
|
||||
// 重新计算CRC并保存
|
||||
s_unsettledOrderMng.u16_crc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
v_write_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0 // 测试读取
|
||||
s_unsettledOrderMng.u16_unsettledCnt = 1;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[0][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[0][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[0][2] = 1;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[1][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[1][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[1][2] = 0;
|
||||
#endif
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: init ok, cnt=%u",
|
||||
s_unsettledOrderMng.u16_unsettledCnt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 添加未结算订单索引
|
||||
*/
|
||||
U8_T u8_add_unsettled_order(U32_T orderIndex)
|
||||
{
|
||||
// 检查订单索引是否有效
|
||||
if (orderIndex == 0)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: invalid index");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 检查索引是否超过3字节范围(最大16,777,215)
|
||||
if (orderIndex > 0xFFFFFF)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: index >24b, idx=%u", orderIndex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 检查是否已存在
|
||||
U16_T position;
|
||||
if (u8_find_order_index(orderIndex, &position) == 0)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: index exists, idx=%u", orderIndex);
|
||||
return 0; // 已存在,不算失败
|
||||
}
|
||||
|
||||
// 检查列表是否已满
|
||||
if (s_unsettledOrderMng.u16_unsettledCnt >= UNSETTLED_MAX_CNT)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: list full, add reject");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 添加到列表末尾(使用3字节存储)
|
||||
v_uint32_to_3bytes(orderIndex, s_unsettledOrderMng.u8_unsettledIndexes[s_unsettledOrderMng.u16_unsettledCnt]);
|
||||
s_unsettledOrderMng.u16_unsettledCnt++;
|
||||
|
||||
// 更新CRC并保存到EEPROM
|
||||
s_unsettledOrderMng.u16_crc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
v_write_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: add ok, idx=%u, cnt=%u",
|
||||
orderIndex, s_unsettledOrderMng.u16_unsettledCnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 移除已结算订单索引
|
||||
*/
|
||||
U8_T u8_remove_unsettled_order(U32_T orderIndex)
|
||||
{
|
||||
// 查找订单索引位置
|
||||
U16_T position;
|
||||
if (u8_find_order_index(orderIndex, &position) != 0)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: idx not found, idx=%u", orderIndex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 从列表中移除(将后面的元素前移)
|
||||
for (U16_T i = position; i < s_unsettledOrderMng.u16_unsettledCnt - 1; i++)
|
||||
{
|
||||
// 复制3字节索引
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][0] = s_unsettledOrderMng.u8_unsettledIndexes[i + 1][0];
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][1] = s_unsettledOrderMng.u8_unsettledIndexes[i + 1][1];
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][2] = s_unsettledOrderMng.u8_unsettledIndexes[i + 1][2];
|
||||
}
|
||||
|
||||
// 清空最后一个元素
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[s_unsettledOrderMng.u16_unsettledCnt - 1][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[s_unsettledOrderMng.u16_unsettledCnt - 1][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[s_unsettledOrderMng.u16_unsettledCnt - 1][2] = 0;
|
||||
s_unsettledOrderMng.u16_unsettledCnt--;
|
||||
|
||||
// 更新CRC并保存到EEPROM
|
||||
s_unsettledOrderMng.u16_crc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
v_write_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: rm ok, idx=%u, cnt=%u",
|
||||
orderIndex, s_unsettledOrderMng.u16_unsettledCnt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查订单是否已结算
|
||||
*/
|
||||
U8_T u8_check_order_settled(U32_T orderIndex)
|
||||
{
|
||||
U16_T position;
|
||||
|
||||
// 在未结算列表中查找
|
||||
if (u8_find_order_index(orderIndex, &position) == 0)
|
||||
{
|
||||
return 1; // 找到,说明未结算
|
||||
}
|
||||
|
||||
return 0; // 未找到,说明已结算
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取未结算订单数量
|
||||
*/
|
||||
U16_T u16_get_unsettled_order_count(void)
|
||||
{
|
||||
return s_unsettledOrderMng.u16_unsettledCnt;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取所有未结算订单索引
|
||||
*/
|
||||
void v_get_unsettled_order_indexes(U32_T *indexArray, U16_T *count)
|
||||
{
|
||||
if (indexArray == NULL || count == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
*count = s_unsettledOrderMng.u16_unsettledCnt;
|
||||
|
||||
for (U16_T i = 0; i < s_unsettledOrderMng.u16_unsettledCnt; i++)
|
||||
{
|
||||
// 将3字节索引转换为32位整数
|
||||
indexArray[i] = u32_3bytes_to_uint32(s_unsettledOrderMng.u8_unsettledIndexes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 清除所有未结算订单记录
|
||||
*/
|
||||
void v_clear_all_unsettled_orders(void)
|
||||
{
|
||||
s_unsettledOrderMng.u16_unsettledCnt = 0;
|
||||
|
||||
// 清空索引数组(3字节数组)
|
||||
for (U16_T i = 0; i < UNSETTLED_MAX_CNT; i++)
|
||||
{
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][0] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][1] = 0;
|
||||
s_unsettledOrderMng.u8_unsettledIndexes[i][2] = 0;
|
||||
}
|
||||
|
||||
// 更新CRC并保存到EEPROM
|
||||
s_unsettledOrderMng.u16_crc = u16_calculate_unsettled_crc(&s_unsettledOrderMng);
|
||||
v_write_eeprom_unsettledMng(&s_unsettledOrderMng);
|
||||
|
||||
UNSETTLED_MNG_LOG("UnsettledMng: clear all");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 打印未结算订单状态(调试用)
|
||||
*/
|
||||
void v_print_unsettled_order_status(void)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("=== Unsettled status ===");
|
||||
UNSETTLED_MNG_LOG("Unsettled cnt: %u", s_unsettledOrderMng.u16_unsettledCnt);
|
||||
|
||||
if (s_unsettledOrderMng.u16_unsettledCnt > 0)
|
||||
{
|
||||
UNSETTLED_MNG_LOG("Unsettled idx list:");
|
||||
for (U16_T i = 0; i < s_unsettledOrderMng.u16_unsettledCnt; i++)
|
||||
{
|
||||
U32_T orderIndex = u32_3bytes_to_uint32(s_unsettledOrderMng.u8_unsettledIndexes[i]);
|
||||
UNSETTLED_MNG_LOG(" [%u] index=%u", i, orderIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
UNSETTLED_MNG_LOG("No unsettled order");
|
||||
}
|
||||
|
||||
UNSETTLED_MNG_LOG("=====================");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算CRC校验值
|
||||
*/
|
||||
U16_T u16_calculate_crc(const U8_T *data, U16_T length)
|
||||
{
|
||||
U16_T crc = 0xFFFF;
|
||||
|
||||
if (data == NULL || length == 0)
|
||||
{
|
||||
return crc;
|
||||
}
|
||||
|
||||
for (U16_T i = 0; i < length; i++)
|
||||
{
|
||||
crc ^= (U16_T)data[i] << 8;
|
||||
|
||||
for (U8_T j = 0; j < 8; j++)
|
||||
{
|
||||
if (crc & 0x8000)
|
||||
{
|
||||
crc = (crc << 1) ^ UNSETTLED_CRC_POLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/*------ Local functions(局部函数实现) -------------------*/
|
||||
|
||||
/**
|
||||
* @brief 写入未结算订单管理信息到EEPROM
|
||||
*/
|
||||
static void v_write_eeprom_unsettledMng(S_UNSETTLED_ORDER_MNG *unsettledMng)
|
||||
{
|
||||
if (unsettledMng == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 先计算CRC
|
||||
unsettledMng->u16_crc = u16_calculate_unsettled_crc(unsettledMng);
|
||||
|
||||
// 写入到EEPROM
|
||||
eeprom_write(EEPROM_ADDR_UNSETTLED_MNG, (U8_T *)unsettledMng, sizeof(S_UNSETTLED_ORDER_MNG));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从EEPROM读取未结算订单管理信息
|
||||
*/
|
||||
static void v_read_eeprom_unsettledMng(S_UNSETTLED_ORDER_MNG *unsettledMng)
|
||||
{
|
||||
if (unsettledMng == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// 从EEPROM读取,eeprom_read返回HAL_OK(0)表示成功
|
||||
if (eeprom_read(EEPROM_ADDR_UNSETTLED_MNG, (U8_T *)unsettledMng, sizeof(S_UNSETTLED_ORDER_MNG)) != HAL_OK)
|
||||
{
|
||||
// 读取失败,初始化默认值
|
||||
unsettledMng->u16_head = 0;
|
||||
unsettledMng->u16_unsettledCnt = 0;
|
||||
unsettledMng->u16_crc = 0;
|
||||
|
||||
for (U16_T i = 0; i < UNSETTLED_MAX_CNT; i++)
|
||||
{
|
||||
unsettledMng->u8_unsettledIndexes[i][0] = 0;
|
||||
unsettledMng->u8_unsettledIndexes[i][1] = 0;
|
||||
unsettledMng->u8_unsettledIndexes[i][2] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 计算未结算订单管理信息的CRC
|
||||
*/
|
||||
static U16_T u16_calculate_unsettled_crc(S_UNSETTLED_ORDER_MNG *unsettledMng)
|
||||
{
|
||||
if (unsettledMng == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 手动计算结构体大小,避免结构体对齐问题
|
||||
// 结构体布局:u16_head(2) + u16_unsettledCnt(2) + u16_crc(2) + u8_unsettledIndexes[30][3](90)
|
||||
// 总大小:2 + 2 + 2 + 90 = 96字节
|
||||
// 计算除CRC字段外的数据:u16_head + u16_unsettledCnt + u8_unsettledIndexes
|
||||
U8_T tempBuffer[94]; // 2 + 2 + 90 = 94字节
|
||||
U16_T offset = 0;
|
||||
|
||||
// 复制头标志
|
||||
tempBuffer[offset++] = (unsettledMng->u16_head >> 8) & 0xFF;
|
||||
tempBuffer[offset++] = unsettledMng->u16_head & 0xFF;
|
||||
|
||||
// 复制未结算订单数量
|
||||
tempBuffer[offset++] = (unsettledMng->u16_unsettledCnt >> 8) & 0xFF;
|
||||
tempBuffer[offset++] = unsettledMng->u16_unsettledCnt & 0xFF;
|
||||
|
||||
// 复制索引数组(3字节数组)
|
||||
for (U16_T i = 0; i < UNSETTLED_MAX_CNT; i++)
|
||||
{
|
||||
for (U8_T j = 0; j < 3; j++)
|
||||
{
|
||||
tempBuffer[offset++] = unsettledMng->u8_unsettledIndexes[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// 计算CRC
|
||||
return u16_calculate_crc(tempBuffer, offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在未结算订单列表中查找订单索引
|
||||
*/
|
||||
static U8_T u8_find_order_index(U32_T orderIndex, U16_T *position)
|
||||
{
|
||||
for (U16_T i = 0; i < s_unsettledOrderMng.u16_unsettledCnt; i++)
|
||||
{
|
||||
U32_T storedIndex = u32_3bytes_to_uint32(s_unsettledOrderMng.u8_unsettledIndexes[i]);
|
||||
if (storedIndex == orderIndex)
|
||||
{
|
||||
if (position != NULL)
|
||||
{
|
||||
*position = i;
|
||||
}
|
||||
return 0; // 找到
|
||||
}
|
||||
}
|
||||
|
||||
return 1; // 未找到
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将32位整数转换为3字节数组
|
||||
*/
|
||||
static void v_uint32_to_3bytes(U32_T value, U8_T *bytes)
|
||||
{
|
||||
bytes[0] = (value >> 16) & 0xFF; // 最高字节
|
||||
bytes[1] = (value >> 8) & 0xFF; // 中间字节
|
||||
bytes[2] = value & 0xFF; // 最低字节
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将3字节数组转换为32位整数
|
||||
*/
|
||||
static U32_T u32_3bytes_to_uint32(const U8_T *bytes)
|
||||
{
|
||||
return ((U32_T)bytes[0] << 16) | ((U32_T)bytes[1] << 8) | (U32_T)bytes[2];
|
||||
}
|
||||
Reference in New Issue
Block a user