5.0 KiB
应用内嵌素材使用与添加指南
当前机制
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 图片
-
将原始 PNG 放到
components/platform/assets/lcd_source/<名称>.png。替换图片时只修改原图,不直接编辑lcd_optimized/。 -
按 LCD 图片资源优化与维护 准备 Pillow 环境,在仓库根目录执行:
python tools/optimize_lcd_assets.py generate python tools/optimize_lcd_assets.py verify -
在
components/platform/CMakeLists.txt的platform_lcd_png_assets中加入<名称>,不带.png。未列入清单的 PNG 不会打包。 -
在
components/platform/src/lcd_direct_assets.c登记图片及其帧索引,并在lcd_direct_asset_frame()中登记对应的资源组名。仅入包不会让 LCD 自动播放它。 -
如需新增业务表情,在
components/domain/include/domain.h增加domain_expression_id_t,并在components/domain/src/runtime/domain_runtime_adapters.c的目录映射中配置帧顺序、时长、重复次数、优先级和完成后行为。现有表情只换图时,通常不需要新增表情 ID。
业务触发点放在 control_plane,通过 domain 的语义接口请求,示例:
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()。
添加或替换提示音
-
将文件放到
components/platform/assets/audio_prompts/<名称>.opus。该目录中的.opus会自动入包,无须修改 PNG 清单。当前打包格式只接受audio_prompts/下的单层文件,勿另建子目录。 -
文件必须符合项目现有提示音格式:每个 Opus 包前有 4 字节大端包长,单包长度为 1–2048 字节。普通 Ogg Opus 文件不能仅改名为
.opus使用。 -
在负责该业务时机的
control_plane模块中使用完整名称:esp_err_t err = domain_runtime_behavior_play_prompt_file( "audio_prompts/new_prompt.opus"); -
如果提示音路径由 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 是否已登记到平台帧表和领域表情映射;提示音是否为项目分帧格式;设备运行的是否为本次构建的应用版本。构建目录的暂存文件不是设备上的文件系统。