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

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 图片

  1. 将原始 PNG 放到 components/platform/assets/lcd_source/<名称>.png。替换图片时只修改原图,不直接编辑 lcd_optimized/。

  2. 按 LCD 图片资源优化与维护 准备 Pillow 环境,在仓库根目录执行:

    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 的语义接口请求,示例:

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 模块中使用完整名称:

    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 是否已登记到平台帧表和领域表情映射;提示音是否为项目分帧格式;设备运行的是否为本次构建的应用版本。构建目录的暂存文件不是设备上的文件系统。