Files
CCU621M/BSP/flash_file_mgr/unsettled_order_mng.c
T

442 lines
14 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @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];
}