Files

74 lines
12 KiB
Markdown
Raw Permalink Normal View History

# EchoEar 出门前远程升级交付记录
日期:2026-09-30。目标设备为 COM6,工厂号 `KP01-020026091601`,型号 `ECHOEAR-S3`。
## 最新结果(2026-10-01)
真实 21 → 22 远程升级已成功,任务 `18216193-939f-47a4-b49b-96e9002eb05e` 于 09:44:31 北京时间回报成功。设备运行 `1.7.0-controls.22 / code 6`,MQTT 在线,配置 19/19、音量 56、原绑定数 1 保留。3,761,200 字节镜像下载、写入和安装校验耗时 41.003 秒,发起至重启成功回执共 67.394 秒。USB 只供电及采集日志,镜像经 Wi-Fi/HTTPS 下载;独立供电、受控实物启动失败回退和手机更换热点仍未验收。详细对照、失败过程及修复见 [性能验收记录](device-ota-performance-20261001.md)。
## 逐次验收记录
- 设备已通过 USB 安装 `1.7.0-controls.13`,只写已确认的活动应用槽 `ota_0 / 0x10000`;应用哈希校验成功。写入前已完整备份 16 MiB Flash,保留 NVS、工厂身份、分区、启动程序、OTA 数据及屏幕/语音资源。
- 原设备停留在过期的 BLE 窗口,云端最后心跳为 9 月 27 日。本次安装后真实蓝牙扫描、连接、`get_info/get_status` 均通过。
- 未提交新配网信息,5 分钟窗口到期后设备恢复原来保存的 `asus` Wi-Fi。20:53:59 北京时间云端确认实时在线、MQTT 已连接、`ota_supported=true`、设备空闲。
- 原账号绑定数 1、音量 56、配置版本 19/19、正常运行状态均保留。用户提供了同名 Wi-Fi;因为设备已自行恢复联网,没有再写入密码,也没有将密码加入项目文件。
- 云端已发布 `1.7.0-controls.14`,版本顺序号 **2**,状态 `READY`。它与串口安装的修复版仅版本字符串不同,用于真实远程升级和 A/B 槽切换验收。
- 家属已完成新版拼图验证并登录。23:13:04 北京时间通过真实家庭端发起远程 OTA;设备接收任务并开始 HTTPS 下载,23:14:39 返回 `OTA failed: ESP_FAIL; original firmware retained`。原固件 `controls.13`、顺序号 0 和原绑定、音量、配置均保留。**该次真实 OTA 未通过,不能把编译、USB 刷写、HTTP 200 或 `ota_supported=true` 当成成功。**
- 23:32:42 通过同一已登录家庭端发起一次受控重试;23:40:05 返回 `ESP_ERR_TIMEOUT`,原固件保留。该次 `/f/` 请求持续 430.039 秒,向设备发送 2,719,221 / 3,757,536 字节(72.36%),上游读取 2,739,701 字节。数据确认当前实物下载在固件 420 秒总期限内没有完成;不能把 HTTP 200 当作完整送达。
- 临时传输日志仅记录固定脱敏路由、状态和计数,不记录下载票据、IP 或请求头。采样后已恢复网关原配置,SHA256 和所有容器 ID 一致。两个任务均失败,当前设备仍为 `controls.13` / code 0,MQTT 在线、配置 19/19、音量 56、绑定数 1。
- 10 月 1 日 00:00 前后,用户将 USB 接回,已确认同一 MAC、原 `controls.13` 应用 SHA256、活动 `ota_0` 的有效选择数据与原分区表一致。只写 `0x10000` 的应用镜像 `controls.15`,完整读回 SHA256 为 `cdb2852dd113ce551f95742b7ea784a3c70bb96f23c369a665a04c47f89b4236`;没有写启动程序、分区、OTA 数据、NVS、身份或资源。分区表/OTA 数据写前写后逐字节相同。
- 修复版将下载总期限改为 **900 秒**;同一连接无数据的 EAGAIN 最多连续等待三次,收到数据重置计数。每次等待按剩余总期限裁剪;提前 EOF 和其他负值不盲重试。失败回执包含具体阶段、成功写入字节数、原始读取值及 errno,不包含私有下载地址。
- USB 本地更新后,云端真实确认 `controls.15` / code 0、MQTT 在线、支持 OTA;配置 19/19、音量 56、原绑定数 1 保留。**这只证明本地更新后的运行状态,不是远程升级通过。**
- 配套 API `0.99.20-rc.ota-budget1` 已上线:已接收任务、下载授权和下载写入期限为 **20 分钟**,覆盖 15 分钟下载和 3 分钟启动健康确认;待接收仍为 30 秒,票据仍为 30 分钟,晚到真实终态回执的纠正行为保留。只重建 API;网页 19、其他容器 ID、运行环境/端口/挂载、滑块策略 4 和数据库版本 74 均保留。
- `controls.16` / code **3** 已发布 `READY`,与本地启动修复版 15 仅版本宏不同,大小 3,758,224 字节、SHA256 `6868bcb45f6c211e5e91524e7be5944fe2989f2e377f3bb455f3cdaacfbe0ecf`。发布使用真实 SSH 维护服务身份并记录 service/null 审计,没有使用或构造用户/运营登录会话;公网 HTTPS 全量读回与冻结镜像相同。发布记录 `a67129e0-e9c1-45e2-a30b-141018f74c76`。
- 当时 15 → 16 的无线验收尚未发起。后续在 17 → 18 排除 Flash 写入瓶颈,在 19 → 20 证实接收端提速并定位 PSRAM 栈安装错误,最终 21 → 22 完整成功;以上旧状态按发生顺序保留。
## 明天远程升级的方法
1. 设备持续通电,连接有互联网的 Wi-Fi 或 2.4 GHz 手机热点;设备状态须实时在线。
2. 运营端“固件管理”上传 **应用固件 `.bin`**,填写准确型号、版本名称和更新说明,等待平台大小/摘要校验完成并发布。
3. 用对该设备有管理权限的家属账号进入设备详情,在“固件与远程控制”点“更新固件”并确认。小程序的设备管理也沿用同一云端升级流程。设备通话中须结束通话后再发起。
4. 观察“等待设备接收 → 设备正在升级 → 升级完成”;升级期间会短暂离线。只有重启确认和成功回执都完成,才算升级成功。
5. 如果显示未接收/失败/超时,确认设备恢复在线,刷新状态再发起;旧的 30 秒接收窗口不会因重连自动延长。
当前修复上传包在 `artifacts/firmware/1.7.0-controls.22/echoear-1.7.0-controls.22.bin`。大小为 3,761,200 字节,SHA256:`c13ae3b2aab18431466d40b5d60b101a8c3345e438be87ef474f85ac8653616f`;同目录的 `verification.json` 记录真实成功回执和计时。之前的 14/16/18/20 仅用于前述分阶段验证,不代表最终修复。
该设备每个应用槽为 4 MiB;不得上传合并后的整片 Flash、工厂身份、分区表、模型或屏幕资源镜像。远程升级不会更新这些独立资源分区。后续构建完成后可用工具生成经过型号、芯片、大小及编译版本检查的上传包:
```powershell
python tools/package-ota.py --model ECHOEAR-S3 --out <输出目录>
```
## 升级与联网修复
MQTT 仅唤醒升级任务;设备通过 DEVREQ1 签名 HTTPS 请求取不可变升级清单,再检查型号、顺序号、有效期、大小和 SHA256,写入非活动应用槽。启动健康确认后才报告成功;结果暂时发不出去则持久化补报。固件下载和安装失败保留原槽,待确认镜像有启动健康期限和 bootloader 回退保护。
本次补齐清单请求暂时失败后的有限重试,避免 MQTT 已确认投递后丢失唯一唤醒;终态回执的本地持久化失败不会放行下一次升级。云端已完成任务的冲突响应也不会永久卡住后续升级。日志只记录运行槽、版本顺序号、字节数和阶段,不记录私有下载票据。
云端修复 fleet OTA 与已有 SaaS `ASSIGNED` 升级任务的互斥判断。API 最小增量 `0.99.17-rc.ota-ready1` 已上线,实际生产源码只改该判断;运行环境、端口及挂载保持一致,其余服务未重建。
网页最小增量 `0.99.18-rc.reconnect-copy1` 的配网提示更正为“长按设备屏幕底部中央 3 秒”,已通过类型检查、构建和静态文件哈希检查。当前生产 `0.99.19-rc.local-slide1` 保留上述 OTA 和配网修复,并已部署本地开源拼图验证码。当前本地小程序文案也已更正并通过测试,本次未发布小程序。
重新联网与重新配网的完整规则见 [重新联网说明](device-reconnect-20260930.md):正常掉线持续重试,异地开机旧网络失败自动进入 BLE,已有配网设备无人确认时超时返回旧网络。**操作入口为长按屏幕底部中央 3 秒,发送新网络后 60 秒内轻触确认;保留原绑定。**
## 验证边界
### 10 月 1 日 08:28 下载慢的复查
- 电脑通过真实家庭端取得同一个 16 固件的短下载地址,正常 TLS 校验、无重定向,全量下载 3,758,224 字节用时 5.812 秒(646.6 KB/s),SHA256 与冻结包一致。未启动设备升级、未写设备 Flash,私有下载地址只临时保存在本地并在测试后删除。
- 设备当前实际 RSSI 为 -21 dBm,报告时间 08:23:50,固件仍 15、在线;该信号是当前值,不能充当昨夜下载全程的信号测量。
- 设备旧实测 430.039 秒发送 2,719,221 字节(约 6.3 KB/s),这个速度包含设备同步读取、擦写、校验及调度产生的反压,不是单独的网络吞吐测量。电脑对照与已排查的服务端限速/负载表明,应进一步定位设备处理和到设备的网络路径。
- 当前每次最多读 4 KiB,再同步 `esp_ota_write`,使用 `OTA_WITH_SEQUENTIAL_WRITES` 逐扇区擦除。16 镜像按 4 KiB 对齐为 918 扇区;本板两个应用分区均按 64 KiB 对齐,当前 SDK 允许 64 KiB block erase,按已验证大小预擦可形成 57 个 64 KiB 块加 6 个 4 KiB 扇区。这是可测的优化点,**尚无分段实物计时,不能把它认定为全部慢速的唯一原因,也不能按擦除次数推导提速倍数。**
- 本机开启 PSRAM 指令/常量读取,不能泛称本板每次擦除都会关掉 Wi-Fi/双核缓存。SDK 的 600ms 是擦除超时上限,不是固定等待时间。
- 截止此复查,未修改预擦算法、未启用额外设备计时、未写新固件;此前 900 秒预算修复没有证明下载已提速。后续需要分别记录 begin/read/write/SHA 耗时,对比预擦方案并验收完整 OTA。
- 最终生产 OTA C 全部故障注入场景通过 GCC AddressSanitizer、UndefinedBehaviorSanitizer 与 float-cast-overflow,覆盖真实 SHA256、正常安装/确认、两槽版本恢复、重复任务、非法清单、截断/重定向/下载失败、持久化与计时器故障及本次恢复路径。
- 网络重连和 BLE 超时的生产函数测试通过 ASan/UBSan,原有 BLE Wi-Fi 22 项生命周期测试通过。家庭端微信一键登录改造后的当前小程序 140 项测试及 9 页原生编译检查通过;网页类型检查通过。
- ESP-IDF 5.5.1 最终固件编译通过,`controls.14` 的 host 测试编译单元与已验证 `controls.13` 完全相同。
- 云端升级生命周期使用隔离数据库和真实 MQTT broker 验证;发布包经公网 HTTPS 下载回读,大小和 SHA256 与冻结包一致。
- 已确认真实 USB 应用写入、BLE 只读交互和无人操作后自动回旧 Wi-Fi;首次真实 OTA 失败后原槽继续运行,最终 21 → 22 完成真实 A/B 远程安装、重启确认和成功回执,原绑定和设置保留。**受控实物启动失败回滚和手机更换热点仍未验收。**
- 下载时间限制已用精确生产源码和完整 Middleware/otel 包装,在真实 TCP 上做三组对照:40ms 默认写超时会截断,下载处理器覆盖至 15 分钟后完整传输且 SHA256 一致。MinIO 活动下载体没有 60/90 秒总超时。此证据排除所测服务器期限问题,不能代替实物下载成功。
- 最终 20 分钟云端增量通过隔离 Linux 的 8 项真实数据库/MQTT 生命周期测试(0 跳过)和 3 项完整 HTTP 封装 TCP 测试;测试覆盖 19:59/20:01、待接收 29/31 秒、撤销票据与晚到终态纠正。固件读取修复的完整生产 C 测试 15 组通过,包含 11 个新增故障场景,ASan/UBSan 无错误;14 验证构建、15 启动包和 16 OTA 包均通过 ESP-IDF 编译,源哈希已冻结。
受限本机证据保存在工作区外的 `.local-evidence/com6-ota-20260930` 和 `.local-evidence/remote-ota-20260930`;完整备份包含设备凭据,不应作为上传固件分发。