标签: ESP32-C3

  • 给 Passport OS 加一个计算器:一次合规的二次开发记录

    本文记录的是在开源项目基础上、针对本人自购设备所做的一次功能扩展。所有改动均基于公开源码,遵守原项目许可证;文中不包含任何账号、令牌、Wi-Fi 密码、设备密钥或他人隐私数据。

    一、为什么选这个项目

    FoloToy AI Passport 是一块很小的随身设备:ESP32-C3、8 MB Flash、240×320 屏幕,只有上/下/确定三个按键。社区固件 Passport OS(github.com/manchunx7-bit/passport-os)以 MIT 许可证开源,已经内置首页、收音机、AI 语音、小智、Muse、俄罗斯方块、秒表、番茄钟等应用,并提供统一的启动器、设置、配网和电源管理。

    它的代码结构很适合做二次开发:

    • 应用层在 main/apps/,每个应用是一个独立目录;
    • 应用统一通过 passport_app_t 描述符注册到 main/launcher/app_registry.cc;
    • 通用界面组件、字体、图标在 main/ui/、main/fonts/、main/launcher/launcher.cc;
    • 板级驱动在 components/bsp/,不需要为了加功能去改硬件驱动。

    我想加的功能很简单:一个离线可用的计算器。它不依赖网络、不申请额外权限,也不会触碰设备上已有的账号或配网数据,是练习二次开发边界的一个合适小目标。

    二、动手前的合规边界

    二次开发最容易忽略的不是代码,而是许可与边界。这次我给自己定了四条规则:

    1. 只使用公开源码:基于 Passport OS 的 MIT 许可代码开发,保留原项目版权与许可声明;不复制、不反编译、不再分发任何未授权的第三方固件或专有资源。
    2. 不修改、不再分发第三方素材:项目中的 Muse、Jollybot 形象、字体等分别遵循各自目录下的 LICENSE/NOTICE,本次没有改动这些资源,也没有把它们单独抽出来传播。
    3. 不处理敏感数据:代码和本文都不包含 Wi-Fi 密码、API Token、设备密钥、序列号或他人数据;固件构建时使用项目的公开发布配置,清空默认的服务配置。
    4. 只在本人设备上验证:刷机仅针对自己持有的设备;不提供”破解””绕过””提权”类内容,也不把固件发布到任何应用商店或收费渠道。

    在这个前提下,二次开发就是正常的开源软件修改:读代码、加模块、跑测试、编固件、刷自己的设备。

    三、功能设计:三个按键怎么用计算器

    设备只有 UP / DOWN / OK 三个键,所以不能照搬手机计算器的九宫格点按。最终采用的交互是:

    • 屏幕下方是一块 4×5 的虚拟键盘:7 8 9 /、4 5 6 *、1 2 3 -、0 . = +、C < +/- %;
    • UP/DOWN 在按键之间线性移动高亮(走到底自动回到另一端),OK 输入当前高亮键;
    • 长按 UP 清空、长按 DOWN 退格、长按 OK 退出(沿用系统统一的返回手势);
    • 屏幕上方显示表达式与结果,出错(例如除以 0)显示 Error。

    计算逻辑被刻意做成纯 C 状态机,不依赖 LVGL/ESP-IDF:先按运算符优先级做乘除、再做加减,支持小数、取负、百分比、连续运算和表达式长度上限。这样可以用主机测试覆盖边界情况,而不必每次都刷机试。

    四、代码改动

    新增两个文件:

    • main/apps/calculator/calculator_core.c/.h:表达式状态机与求值。按键事件只修改状态,UI 只负责把 expr / result 显示出来;
    • main/apps/calculator/app_calculator.cc:LVGL 页面、键盘布局、高亮、按键分发,以及 passport_app_t 描述符。

    接入现有框架只需要几处小改动:

    • main/apps/app_base.h:应用 ID 枚举增加 APP_ID_CALCULATOR;
    • main/launcher/app_registry.cc:声明 g_calculator_app、加入启动器轮播列表、把计算器纳入允许按键音效的应用集合;
    • main/launcher/launcher.cc:为计算器补一个像素图标(机身 + 显示屏 + 3×2 按键点阵)和主题色;
    • main/CMakeLists.txt:加入新源文件与头文件目录;
    • tests/test_calculator.c + tools/test-host.sh:新增主机测试并接入测试脚本;
    • 中英文 README 的应用列表与数量同步更新。

    这体现了这类项目的一个好处:新增应用不需要改动系统层。注册表负责”发现应用”,启动器负责”展示应用”,应用自己负责”生命周期和按键”,三者解耦得很好。

    五、构建与验证

    构建使用项目要求的 ESP-IDF 5.5.3,命令行大致是:

    idf.py -B build-calc -D SDKCONFIG=build-calc/sdkconfig \
           -D PASSPORT_PUBLIC_RELEASE=ON -D PASSPORT_MUSE_USE_JOLLYBOT=ON build
    idf.py -B build-calc merge-bin -o build-calc/FoloToy-AI-Passport-full.bin
    python tools/verify_firmware.py build-calc --public

    验证分三层:

    1. 主机测试:计算器核心的状态机测试全部通过,覆盖优先级、小数、除零、退格、清空、取负、百分比、连续运算和长度上限;
    2. 固件校验:verify_firmware.py --public 检查分区布局、SRAM 预算、合并镜像和公开发布配置,全部 PASS;
    3. 真机测试:刷入设备后,启动器能看到”计算器”卡片与图标,进入后按键导航、1 + 2 = 3、错误显示和长按退出均正常。

    六、升级时如何不丢数据

    刷机有两种方式,区别很大:

    • 完整镜像写 0x0:会覆盖引导、分区表和 app,并且把 0x8000–0x10000 之间的空隙填成 0xFF,NVS(配网/资料)和 PHY 校准会被清掉;只适合首次安装或分区表变更。
    • 应用镜像写 0x10000:只覆盖 app 分区,NVS、PHY、cardid、storage(头像/名片)都保留;适合日常升级。
    python -m esptool --chip esp32c3 -p COM5 -b 460800 write_flash 0x10000 build-calc\passport-os.bin

    如果必须整片刷又要保留数据,可以先备份再恢复:

    python -m esptool -p COM5 read_flash 0x9000 0x6000 nvs.bin
    python -m esptool -p COM5 write_flash 0x9000 nvs.bin

    注意 NVS 结构要和新固件兼容,跨大版本时不要盲目恢复。

    七、这次二次开发的可复用经验

    1. 先读框架,再写功能:这类多应用固件的关键不是画界面,而是理解注册表、生命周期和按键分发;接入点找对了,代码量会很小。
    2. 逻辑与界面分离:把计算逻辑做成纯 C 状态机,既方便测试,也方便以后换成别的交互方式。
    3. 先查字体再写中文:嵌入式 UI 的中文字体通常是子集,新增中文文案前要确认字库覆盖,否则会出现方框或空白。本次用到的字符都在现有字库内,因此不需要重新生成字体。
    4. 构建环境要可控:Windows 下用 MSYS/Git Bash 调 ESP-IDF 会遇到 shell 识别问题;把 idf.py 的调用放到原生 cmd 环境、并显式处理 /tmp 路径映射,可以避免”配置成功但找不到产物”的坑。
    5. 测试分层:主机测试抓逻辑,固件校验抓布局与资源,真机测试抓交互与显示;三层都过再谈”完成”。

    八、合规声明与致谢

    • 本项目二次开发基于 MIT 许可证的 Passport OS 源码,保留原项目版权与许可声明;本文与改动不改变原项目的许可方式。
    • 未修改、未再分发 Muse、Jollybot 及其他第三方素材;相关资源仍遵循各自目录下的 LICENSE/NOTICE。
    • 未包含或传播任何账号、令牌、Wi-Fi 密码、设备密钥、序列号、日志或他人数据。
    • 未提供任何绕过技术保护措施、破解、提权或规避授权的内容;刷机仅针对本人持有的设备。
    • Passport OS 是社区固件,本文不代表 FoloToy 官方立场,也不宣称与原项目维护者有隶属或背书关系。

    感谢 Passport OS 的作者与社区把这样一套完整的固件开源出来,让”给随身小设备加一个小功能”变成一件可以在一个下午完成、并且可以坦然公开记录的事。

    九、后续可以做什么

    计算器只是一个开始。按同样的注册方式,还可以继续加:单位换算、计时器、离线词典、二维码显示等。真正需要谨慎的始终是两件事:尊重许可证与第三方资源,以及不碰别人的数据与设备。在这两条边界内,二次开发是一件很纯粹的事——读代码、写功能、刷自己的设备、把过程分享出来。