纳入固件源码、屏幕组件、nand_xfer 工具和文档。忽略本机构建产物、sdkconfig,以及含本机路径的依赖锁。 Co-authored-by: Cursor <[email protected]>
8.6 KiB
8.6 KiB
表情包持久化存储方案
一、需求分析
需要在掉电不丢失的存储中记录:
- 已使用的表情包系列:当前正在使用的表情包ID
- 已下载的表情包系列:所有已下载并安装的表情包ID列表
二、技术方案
2.1 存储介质选择
- 使用ESP-IDF的NVS(Non-Volatile Storage)
- 理由:
- 项目已有NVS基础设施(
main/NVS_FLASH/nvs_flash.c) - NVS支持掉电不丢失
- 已有命名空间
emoji_config - 操作简单,性能可靠
- 项目已有NVS基础设施(
2.2 数据结构设计
2.2.1 已使用的表情包
- 存储方式:单个字符(char)
- NVS键名:
"using_pack" - 数据类型:
NVS_TYPE_STR(存储单个字符字符串,如 "0", "A", "B", "C", "D") - 默认值:
"0"(表示默认表情包) - 命名规则:支持字符命名,如
0,A,B,C,D等
2.2.2 已下载的表情包列表
- 存储方式:JSON字符串数组(推荐)或逗号分隔字符串
- NVS键名:
"downloaded_packs" - 数据类型:
NVS_TYPE_STR(blob方式存储字符串) - 格式示例:
- JSON格式:
["0", "A", "B", "C", "D"](推荐,易于解析和扩展) - 或简单格式:
"0,A,B,C,D"(节省空间)
- JSON格式:
- 命名规则:支持字符命名,如
0,A,B,C,D等
2.3 功能接口设计
2.3.1 初始化接口
/**
* @brief 从NVS加载表情包信息到内存
* @return esp_err_t ESP_OK表示成功
*/
esp_err_t emoji_storage_load(void);
2.3.2 保存已使用的表情包
/**
* @brief 保存当前使用的表情包ID到NVS
* @param pack_id 表情包ID(字符,如'0', 'A', 'B', 'C', 'D'等)
* @return esp_err_t ESP_OK表示成功
*/
esp_err_t emoji_storage_save_using_pack(char pack_id);
2.3.3 添加已下载的表情包
/**
* @brief 添加已下载的表情包ID到列表并保存到NVS
* @param pack_id 表情包ID(字符,如'0', 'A', 'B', 'C', 'D'等)
* @return esp_err_t ESP_OK表示成功
*/
esp_err_t emoji_storage_add_downloaded_pack(char pack_id);
2.3.4 获取已使用的表情包
/**
* @brief 获取当前使用的表情包ID
* @return char 表情包ID,'0'表示默认表情包
*/
char emoji_storage_get_using_pack(void);
2.3.5 获取已下载的表情包列表
/**
* @brief 获取已下载的表情包列表
* @param packs 输出缓冲区,存储表情包ID数组(字符串形式,如"0,A,B")
* @param max_len 缓冲区最大长度
* @return int 实际返回的表情包数量,-1表示失败
*/
int emoji_storage_get_downloaded_packs(char *packs, int max_len);
2.3.6 检查表情包是否已下载
/**
* @brief 检查指定表情包是否已下载
* @param pack_id 表情包ID(字符)
* @return true 已下载,false 未下载
*/
bool emoji_storage_is_downloaded(char pack_id);
2.3.7 删除已下载的表情包
/**
* @brief 从列表中删除指定的表情包(可选功能)
* @param pack_id 表情包ID(字符)
* @return esp_err_t ESP_OK表示成功
*/
esp_err_t emoji_storage_remove_downloaded_pack(char pack_id);
三、实现细节
3.1 文件结构
main/
├── NVS_FLASH/
│ ├── nvs_flash.h (已有,需要扩展)
│ └── nvs_flash.c (已有,需要扩展)
└── EMOJI_STORAGE/ (新建模块)
├── emoji_storage.h (新建)
└── emoji_storage.c (新建)
3.2 内存缓存设计
- 在内存中维护缓存,避免频繁读写NVS
- 系统启动时从NVS加载到内存
- 每次更新时同步写入NVS
3.3 数据同步策略
- 写操作:立即写入NVS(保证数据不丢失)
- 读操作:优先从内存缓存读取(提高性能)
- 初始化:系统启动时从NVS加载到内存
3.4 错误处理
- NVS操作失败时记录日志
- 读取失败时使用默认值('0'表示默认表情包)
- 写入失败时重试机制
四、集成点
4.1 系统初始化
- 在系统启动时调用
emoji_storage_load()加载数据
4.2 表情包下载完成
- 在下载成功回调中调用
emoji_storage_add_downloaded_pack()
4.3 表情包切换
- 在切换表情包时调用
emoji_storage_save_using_pack()
4.4 查询已下载表情包
- 在
BLE_SEND_DOWNLOADED_PACKS处理中调用emoji_storage_get_downloaded_packs()
4.5 查询正在使用表情包
- 在
BLE_SEND_EMOJI_USING处理中调用emoji_storage_get_using_pack()
4.6 蓝牙连接时发送正在使用的表情包
- 重要:在蓝牙连接成功时(
BLE_CONNECTED_BIT事件),除了发送版本信息,还要发送正在使用的表情包系列 - 在
main.c的main_task中,处理BLE_CONNECTED_BIT时,同时触发BLE_SEND_EMOJI_USING - 在
ble.c的notification_task中,处理BLE_SEND_EMOJI_USING时,发送JSON格式的表情包信息
五、数据格式示例
5.1 NVS存储示例
命名空间: "emoji_config"
键值对:
- "using_pack" = "A" (当前使用表情包A)
- "downloaded_packs" = "[\"0\",\"A\",\"B\",\"C\"]" (已下载0,A,B,C)
5.2 JSON格式示例
{
"using_pack": "A",
"downloaded_packs": ["0", "A", "B", "C", "D"]
}
5.3 蓝牙发送格式示例
{
"action": "emoji_using_info",
"data": {
"pack_id": "A"
}
}
六、优势
- 可靠性:使用NVS保证掉电不丢失
- 性能:内存缓存减少NVS读写次数
- 扩展性:JSON格式易于扩展字段
- 兼容性:复用现有NVS基础设施
- 可维护性:独立模块,接口清晰
七、注意事项
- NVS空间限制:注意NVS分区大小,避免存储过多数据
- 线程安全:如果多线程访问,需要添加互斥锁保护
- 数据迁移:如果后续需要修改数据结构,考虑版本兼容
- 默认值处理:首次使用时需要初始化默认值
八、实现完成情况
8.1 已实现的功能
✅ 创建了 EMOJI_STORAGE 模块
emoji_storage.h- 接口定义emoji_storage.c- 实现代码
✅ 核心功能实现
emoji_storage_load()- 从NVS加载数据(系统启动时自动调用)emoji_storage_save_using_pack()- 保存正在使用的表情包emoji_storage_add_downloaded_pack()- 添加已下载的表情包emoji_storage_get_using_pack()- 获取正在使用的表情包emoji_storage_get_downloaded_packs_json()- 获取JSON格式的已下载列表emoji_storage_get_downloaded_packs()- 获取逗号分隔的已下载列表emoji_storage_is_downloaded()- 检查是否已下载emoji_storage_remove_downloaded_pack()- 删除已下载的表情包
✅ 集成到现有代码
- 在
ble_main()中自动加载表情包数据 - 在
main.c中,蓝牙连接时发送正在使用的表情包 - 在
ble.c中,添加了BLE_SEND_EMOJI_USING的处理逻辑 - 更新了
CMakeLists.txt,添加新模块到编译列表
8.2 使用示例
8.2.1 系统启动时自动加载
系统启动时,在 ble_main() 中会自动调用 emoji_storage_load() 加载数据。
8.2.2 下载表情包后保存
// 下载表情包成功后
emoji_storage_add_downloaded_pack('A'); // 添加表情包A到已下载列表
8.2.3 切换表情包时保存
// 切换到表情包B
emoji_storage_save_using_pack('B');
8.2.4 查询正在使用的表情包
char using_pack = emoji_storage_get_using_pack(); // 返回 '0', 'A', 'B' 等
8.2.5 查询已下载的表情包列表
char packs[256];
int count = emoji_storage_get_downloaded_packs_json(packs, sizeof(packs));
// packs 内容: ["0","A","B","C"]
8.2.6 蓝牙连接时自动发送
蓝牙连接成功时,系统会自动发送正在使用的表情包信息:
{
"action": "emoji_using_info",
"data": {
"pack_id": "A"
}
}
8.3 数据格式
NVS存储格式
- 命名空间:
"emoji_config" "using_pack": 字符串,如"A","B","0"等"downloaded_packs": JSON字符串,如"[\"0\",\"A\",\"B\",\"C\"]"
默认值
- 首次使用时,
using_pack默认为"0"(默认表情包) downloaded_packs默认为"[\"0\"]"(只有默认表情包)
九、后续优化建议
- 添加数据版本号,支持数据结构升级
- 添加数据校验(CRC或校验和)
- 支持表情包元数据存储(名称、大小、下载时间等)
- 支持表情包使用统计(使用次数、最后使用时间等)
- 在下载表情包成功后自动调用
emoji_storage_add_downloaded_pack() - 在切换表情包时自动调用
emoji_storage_save_using_pack()