Files
lucky-cat/docs/应用内嵌素材使用与添加指南.md

69 lines
5.0 KiB
Markdown

# 应用内嵌素材使用与添加指南
## 当前机制
LCD PNG 和提示音 Opus 在构建时生成 `platform_assets.pack`,作为二进制数据链接进应用固件。`ota_0`、`ota_1` 都装入完整的代码和素材,因此应用 OTA 会同步更新两者。运行时按**包内完整相对名称**查找,例如 `lcd/ota1.png`、`audio_prompts/boot.opus`;这些名称不是 VFS 文件路径,不能用 `fopen()` 读取,也不需要挂载 LittleFS。模型仍在独立的 `model` 分区,不随应用 OTA 更新。
源码、打包器和运行时入口:
| 用途 | 位置 |
| --- | --- |
| 原始 LCD PNG | `components/platform/assets/lcd_source/` |
| 优化后实际入包的 PNG | `components/platform/assets/lcd_optimized/` |
| 实际入包的 Opus | `components/platform/assets/audio_prompts/` |
| PNG 入包清单与构建暂存 | `components/platform/CMakeLists.txt` |
| 素材包格式 | `tools/pack_embedded_assets.py` |
| 只读查找实现 | `components/platform/src/platform_asset_bundle.c` |
| Flash 空间报告 | `tools/report_flash_usage.py` |
素材查找器属于 `platform` 内部接口。业务代码不要读取包内字节或拼接 Flash 地址,应调用下述 `domain`/`control_plane` 接口。
## 添加或替换 LCD 图片
1. 将原始 PNG 放到 `components/platform/assets/lcd_source/<名称>.png`。替换图片时只修改原图,不直接编辑 `lcd_optimized/`。
2. 按 [LCD 图片资源优化与维护](lcd-image-asset-optimization.zh-CN.md) 准备 Pillow 环境,在仓库根目录执行:
```bash
python tools/optimize_lcd_assets.py generate
python tools/optimize_lcd_assets.py verify
```
3. 在 `components/platform/CMakeLists.txt` 的 `platform_lcd_png_assets` 中加入 `<名称>`,不带 `.png`。未列入清单的 PNG 不会打包。
4. 在 `components/platform/src/lcd_direct_assets.c` 登记图片及其帧索引,并在 `lcd_direct_asset_frame()` 中登记对应的资源组名。**仅入包不会让 LCD 自动播放它。**
5. 如需新增业务表情,在 `components/domain/include/domain.h` 增加 `domain_expression_id_t`,并在 `components/domain/src/runtime/domain_runtime_adapters.c` 的目录映射中配置帧顺序、时长、重复次数、优先级和完成后行为。现有表情只换图时,通常不需要新增表情 ID。
业务触发点放在 `control_plane`,通过 `domain` 的语义接口请求,示例:
```c
domain_expression_request_t request = {
.id = DOMAIN_EXPRESSION_OTA_UPDATE,
.trigger = DOMAIN_EXPRESSION_TRIGGER_OTA_UPDATE,
};
esp_err_t err = domain_runtime_request_expression(&request);
```
`app_composition` 只负责启动接线;若启动阶段需要触发表情,应调用 `control_plane` 的公开入口。不要从上层直接调用 `platform_lcd_*` 或 `platform_asset_find()`。例如现有开机流程调用 `control_plane_request_boot_expression()`。
## 添加或替换提示音
1. 将文件放到 `components/platform/assets/audio_prompts/<名称>.opus`。该目录中的 `.opus` 会自动入包,无须修改 PNG 清单。当前打包格式只接受 `audio_prompts/` 下的单层文件,勿另建子目录。
2. 文件必须符合项目现有提示音格式:每个 Opus 包前有 **4 字节大端包长**,单包长度为 1–2048 字节。普通 Ogg Opus 文件不能仅改名为 `.opus` 使用。
3. 在负责该业务时机的 `control_plane` 模块中使用完整名称:
```c
esp_err_t err = domain_runtime_behavior_play_prompt_file(
"audio_prompts/new_prompt.opus");
```
4. 如果提示音路径由 Kconfig 配置,配置值也必须是完整包内名称,例如 `audio_prompts/boot.opus`;禁用可选提示音时按对应配置的空值规则处理。旧的 `/littlefs/...` 路径和裸文件名不再被解析。
播放接口同步完成分帧、下行播放会话和等待,调用位置应符合该业务的阻塞预算。需要新的语义触发或重试策略时,在对应的 `control_plane` 模块实现,不在 `app_composition` 中加入业务策略。
## 构建、更新与验收
使用项目指定的 ESP-IDF v5.5.4 环境执行 `idf.py build`。构建会先检查原图、优化图和 manifest 的一致性,再打包所选 PNG 与全部提示音。输出包括 `build/esp-idf/platform/platform_assets.pack` 和 `build/TQ_Cat_Code.bin`,并打印应用槽位、素材包、模型及 Flash 尾部空间。**素材包大小已包含在应用镜像大小中,不要重复相加。**
检查新增素材时,先确认构建通过、空间报告未超出 OTA 槽位,再在设备上验证实际画面或声音。更新素材需要重新发布应用 OTA;对于当前分区布局,首次烧录需同时烧录新的分区表、应用与模型。仅改素材也要生成新的应用镜像。
若运行时报告素材未找到,按顺序检查:调用名称是否含 `lcd/` 或 `audio_prompts/` 前缀;PNG 是否在 CMake 清单中;PNG 是否已登记到平台帧表和领域表情映射;提示音是否为项目分帧格式;设备运行的是否为本次构建的应用版本。构建目录的暂存文件不是设备上的文件系统。