feat: expand companion platform, device controls, and memoir workflows
ci / verify (push) Canceled after 0s
ci / verify (push) Canceled after 0s
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
# COM6 注册与聊天测试固件
|
||||
|
||||
设备已于 2026-10-04 13:03:22(北京时间)通过真实 SaaS OTA 安装 `1.7.0-controls.27 / code 11`,用于修复 RTC 通话沿用旧计数器而自行结束的问题。首次 OTA 返回 `ESP_ERR_NO_MEM`,旧 controls26 保留;经实际 SaaS 重启后,重试任务 `be8c5931-d629-4361-ab23-6c304044cd59` 成功。13:03:56 与 13:04:54 两次只读观察确认新版本运行、心跳推进、配置 19/19、音量 56、名称和绑定保留。用户明确授权麦克风测试后,已完成一次约 110 秒的有界 RTC 通话,越过原超时边界后仍保持通话,随后主动结束并收到停止回执。
|
||||
|
||||
## 2026-10-04 controls27 RTC 通话误结束修复与有界实测
|
||||
|
||||
旧聊天循环每轮等待一秒后增加 `wait_time`,累计 60 轮便退出。RTC 的音频、状态和字幕路径不能一致地重置这个原本用于 WebSocket 的计数器,因此它会变成约一分钟的 RTC 通话时限;循环中的请求耗时也会延长实际墙钟时间,并非精确 60 秒。controls27 仅让 RTC 跳过该旧计数器,保留 WebSocket 的 60 轮超时,以及主动挂断、供应商断开、平台授权租约和平台结束指令。5403 项冻结输入只改变 `volc_conv.c` 和版本头,RTC 收发、播放器、配置、依赖和分区未变。
|
||||
|
||||
提取实际 C 的主机测试验证 RTC 连续 10000 轮不因缺少活动重置而超时、不增加计数器,同时保留 WebSocket 第 60 轮超时和独立停止条件;这是无墙钟等待的逻辑测试,不是两小时实物通话。三份字节相同的 RTC/PCM 测试复用 controls26 已通过的 ASan/UBSan 结果,更新后的诊断测试通过普通执行及两次 UBSan。Windows ASan 独立 smoke 仍在进入 main 前失败,第四项如实记录为不可用。ESP-IDF 构建、冻结输入及独立审查通过。
|
||||
|
||||
固件 `artifacts/firmware/1.7.0-controls.27/echoear-1.7.0-controls.27.bin` 为 3,772,544 字节,SHA256 `bbce917e79310b7c36d3311727f8bf347a3031dd8f44816674798c803f55b5df`。维护发布采用 service/null 审计,HTTPS 回读哈希一致。真实安装和稳定复查证据为本次证据目录中的 `ota27-core.json`、`ota27-stable.json` 与 `saas-controls27-installed.jpg`。
|
||||
|
||||
首次通话测试因缺少麦克风传输授权,在命令执行前被自动审批拦截,未触发通话;用户随后明确授权了 110 秒测试。实际通话 `828a88a1-d438-4d56-8ad2-88078700b56b` 仅发起一次 `diag-say`,没有重复补播、麦克风抑制或临时优先级覆盖。串口在采样开始后 2.968 秒确认加入房间,房间哈希与两份云端快照一致;13:12:08 同一通话已持续 95.087966 秒,仍为 TALKING,租约剩余 41.84 秒。加入房间后超过 60 秒仍有 22 份正数上行报告,合计 748 帧、发送失败为 0;这些是向 SDK 提交音频的统计,不代表语音识别或听感质量。
|
||||
|
||||
采样第 110.047 秒按计划发送 `diag-stop`,距加入房间 107.079 秒;110.656 秒收到结束确认,之前未观察到旧超时退出或提前停止。云端于 13:12:24 确认同一通话 ENDED,总时长 110.335403 秒,SDK 停止及本地音频关闭;13:12:41 设备在线空闲,首次介绍完成数仍为 1。`lifetime-analysis.json` 的针对性运行检查全部通过,分析与原始数字证据哈希已核对,未保存正文或音频。本次只验证一通有界通话跨过原超时边界并可正常主动结束,不宣称所有未来掉线原因已排除,也不代替长期自然聊天或扬声器听感验收。
|
||||
|
||||
## 2026-10-04 controls26 接收任务调度修复与实际升级(历史)
|
||||
|
||||
设备于 2026-10-04 12:27:39(北京时间)通过真实 SaaS OTA 安装 `1.7.0-controls.26 / code 10`。成功任务 `e7dc7921-da9a-4b5a-a572-0989075229b6`;升级后两次只读观察确认心跳推进、配置 19/19、音量 56、名称和绑定哈希保留。RTC 接收任务常态优先级下限为 6,正常通话实测自动生效,麦克风上行及停止回执正常。用户确认此前 controls25 的两次独立高优先级回放“这两次都没啥问题”;该听感反馈不代替 controls26 的长期实际聊天验收。
|
||||
|
||||
controls25 的 AB、BA 及两次独立高优先级试验均完成房间哈希对照,云端确认 ENDED、SDK 停止和本地音频关闭。排除首个请求窗口及切换边界前后 1 秒后,AB 的 SDK 回调加权均值从 2726.14 μs 降至 42.83 μs,最大值从 41760 μs 降至 282 μs;BA 从高优先级还原后,均值由 39.91 μs 升至 3577.17 μs,最大值由 296 μs 升至 30181 μs。pending-send 阶段耗时随优先级变化,证据支持低优先级 SDK 回调被解码 worker 抢占,增加返回前的调度等待;这些是包含抢占等待的墙钟耗时。用户反馈 AB 第二遍更连贯;BA 只听到一次,不能算完整听感对照;之后两个独立高优先级通话均反馈没有问题。
|
||||
|
||||
controls26 将当前 `VolcRTCMain` 任务的基础优先级下限设为 6,仅由 SDK 回调所属任务设置自身;已高于 6 的优先级保留,不使用历史任务指针。设置适用于正常通话和重新创建的 SDK 任务,旧 USB 临时优先级指令不再改变下限。保留有界压缩包队列、PSRAM 解码任务、播放器、麦克风和通话结束逻辑。5403 项冻结输入只有 RTC C、聊天适配 C、USB 命令 C 和版本头四项改变,依赖、配置和分区不变。
|
||||
|
||||
三份字节完全相同的队列、PCM 和 consumed 解码 C 测试复用 controls25 已执行的 GCC ASan/UBSan 结果;新增优先级/诊断 C 测试通过两次 UBSan 和普通执行。Windows ASan 独立 smoke 程序在进入 main 前崩溃,因此第四项 ASan 记录为不可用,不宣称通过。ESP-IDF 构建及制品校验通过,独立审查 READY。
|
||||
|
||||
固件 `artifacts/firmware/1.7.0-controls.26/echoear-1.7.0-controls.26.bin` 为 3,772,544 字节,SHA256 `304d57fba171d3902d950b37c17704752ad6dd71645f27a746d5e8c4d92a8606`。维护发布以 service/null 审计,HTTPS 回读与冻结包一致,生产容器保持原实例;设备安装使用现有 SaaS 页面。首次 OTA `7827dd3a-c951-4ade-9740-ae03951d3b73` 下载完整,但校验辅助任务分配返回 `0x101`,尚未切换启动分区,原固件保留。设备空闲重启后再次 OTA 成功;首次心跳前 OTA 能力暂为 false,后续恢复 true。成功下载/写入/校验合计 42055 ms,不把首次失败隐藏为成功。
|
||||
|
||||
升级后的普通 `diag-say` 通话未使用麦克风抑制或临时高优先级指令。实物记录 SDK 基础优先级从 3 自动变为 6,15 秒快照 priority/base 均为 6、观测年龄 58 ms;麦克风上行帧数持续为正。23 秒请求结束后,实际通话 `a01321c8-4a64-43f4-9ce4-0d779302ed8a` 的房间哈希与串口匹配,云端确认 ENDED、sdk_stopped、local_audio_off,首次介绍仍仅完成一次。数字采集不保存正文或音频。
|
||||
|
||||
上述测量不证明所有停顿消失:正常测试仍出现接收间隔及播放器重新预缓冲。PCM 可包含静音,TTS wrapper 返回 0 不证明实际播完,接收间隔不能直接视为网络丢包,软件队列空也不等于扬声器 DMA 已断音。controls25 的听感反馈和 controls26 的默认设置/收音/结束验证分别记录;未声称 controls26 的长期双向聊天听感已验收。完整实际升级与证据索引见制品目录 `verification.json`。
|
||||
|
||||
下方 controls24 及更早记录保留为历史证据。
|
||||
|
||||
## 2026-10-04 controls24 语音断续调查(历史)
|
||||
|
||||
RTC SDK 文档要求同步回调避免耗时工作,原实现直接在收包回调解码并转交 PCM。controls24 采用 48 个完整压缩包的有界队列,独立工作任务解码,停止和打断按 generation 隔离;PSRAM 中保存包和任务栈,低内部内存下避免 WithCaps 任务自删额外分配。实际生产 C 的队列、consumed 解码、PCM 分包三份测试通过 GCC ASan/UBSan,包括 10 组生命周期与边界测试;独立审查通过,ESP-IDF 构建成功。5403 项任务输入中只有 RTC C 和版本头两项改变,配置和依赖保持不变。
|
||||
|
||||
制品为 `artifacts/firmware/1.7.0-controls.24/echoear-1.7.0-controls.24.bin`,3,770,064 字节,SHA256 `270009b693e400c6a6b93dd7cd8a71982e31c7a1a0ad85fa074db3303c66e593`。先以 service/null 审计发布 READY,并完成 HTTPS 逐字节回读,再经实际 SaaS 安装;未重建云端容器。验收记录为该制品目录的 `verification.json`。
|
||||
|
||||
同一 USB 固定句请求的 55 秒采样中,解码最大墙钟耗时由 43 ms 降至 8 ms,压缩队列峰值 1、溢出与解码错误均为 0。但更新后仍有播放缓冲耗空,最大收包间隔为 1475 ms,SDK 回调最大墙钟耗时为 515 ms。两轮供给比 0.640 / 0.575 混合正常开场、LLM 生成及句间停顿,不能当作丢包率或音质回退证明。下一轮将直接固定 TTS、隔离麦克风回传并测量任务调度;尚未录音或证明扬声器连续播放。
|
||||
|
||||
设备于 2026-10-02 23:48:27(北京时间)经真实 SaaS 在线升级成功,当时运行 `1.7.0-controls.23 / code 7`。升级后两次观察间隔 54 秒,心跳持续推进,绑定、配置版本 19/19、音量 56 和运行模式保留。首次安装在下载完成后的内部校验任务创建阶段因内存不足失败,旧固件保留;设备空闲时重启后再次升级成功。目标硬件是 EchoEar ESP32-S3 V1.2,16 MB Flash / 16 MB PSRAM,每个应用槽为 4 MiB。下方旧版本记录保留作为历史证据。
|
||||
|
||||
## 2026-10-02 圆屏通话状态
|
||||
|
||||
保留眼睛动画,在上方显示 32px 中文:待机、正在连接、通话中、正在结束、通话结束、连接失败、连接中断。语音 SDK 报告连接成功才显示“通话中”;一段回答完成仍保持通话。本地收音和播放停止后显示结束状态,约两秒后回到待机;慢速云端结束上报的耗时计入该停留时间。
|
||||
|
||||
显示调用只提交状态,原显示任务处理字形与刷新,不在语音回调中等待屏幕。字库沿用原有字形,离线放大并转为当前 GFX 兼容格式。实际状态任务和字体解析器均通过 GCC ASan/UBSan;ESP-IDF 5.5.1 编译成功。上述主机检查不代替实物圆屏、声音和供应商旧房间回调的验收。
|
||||
|
||||
升级包为 `artifacts/firmware/1.7.0-controls.23/echoear-1.7.0-controls.23.bin`,3,767,520 字节,SHA256 `e88ff30446453072b4c2eeb06731e64a66e6bb29b43bfca3874998efec37a0f4`。云端发布记录 `980152d7-e6f4-4a33-ac41-e5f99872a652`,完整 HTTPS 下载回读与冻结包逐字节及 SHA256 一致,使用 service/null 维护审计,发布时未发起升级;随后在真实 SaaS 页面完成安装。成功任务 `896d6654-5ec8-4289-afbb-7c5171b55d64`,实际固件、心跳、配置与绑定验收见 `artifacts/firmware/1.7.0-controls.23/verification.json`。SaaS“陪伴设备”概况和详情均有“固件升级”入口。圆屏实际观感与声音仍需实物检查,未把 OTA 成功当作显示和音频验收。
|
||||
|
||||
本次完整备份后仅写活动 `ota_0 / 0x10000`,哈希校验通过;蓝牙只读交互通过,5 分钟未提交配网后实际恢复原 Wi-Fi。20:53:59 北京时间云端确认在线、MQTT 和 OTA 支持正常,原绑定、音量 56、配置版本 19/19 保留。操作和验证边界见 [远程升级交付记录](../../docs/device-remote-ota-20260930.md)。
|
||||
|
||||
## 2026-09-22 重新配网启动修复
|
||||
|
||||
进入配网分支时,原 24 KiB 启动栈仍占用内部 RAM;Wi-Fi 初始化后只剩约 41.6 KiB,出现蓝牙 `Malloc failed` 和屏幕 SPI 刷新失败。启动日志曾提前打印“配网可用”,但实际扫描不到设备。
|
||||
|
||||
现在将板级/配网启动与联网/语音启动分开:前者使用 8 KiB 内部栈,只有正常联网模式才分配 24 KiB 的网络启动栈。板级启动必须保留内部栈,屏幕资源 mmap 会冻结缓存,不能直接把该栈移到 PSRAM。蓝牙广播配置/启动结果也单独记录,不再把初始化完成当成广播成功。
|
||||
|
||||
COM6 实测:编译及应用分区烧录校验通过;BLE 初始化前内部空闲 RAM 为 57,959 字节,启动栈余量 5,224 字节;观察窗口内未出现蓝牙分配失败、屏幕 SPI 刷新失败或崩溃。电脑实际扫描并连接 `vl-ECHOEAR-S3-26091601`,协议 v2 的 `get_info` 返回本机编号 `KP01-020026091601`,`get_status` 返回 `idle`。只写入 `0x10000` 应用分区,保留绑定与 Wi-Fi。应用 SHA256:`e3d47837179bcf76e93bcd03195e3ad21dbd58daea31a14cd54d8840da817856`。
|
||||
|
||||
操作:正常运行时,持续按住圆屏底部中间区域约 3 秒(起点 x=60..300、y=280..335),进入 BLE 配网;不是长按机身电源键。小程序选择“重新配网”,搜索以上名称,发送 2.4 GHz Wi-Fi 后轻触圆屏确认。重新配网不需要解绑。窗口约 5 分钟,过期后重新开启。
|
||||
|
||||
用户随后确认手机端操作已完成、可以绑定。平台复查:有效绑定数 1,MQTT 已连接,实际固件 `1.7.0-controls.10`,上报配置版本与目标版本均为 15,音量均为 22,待执行指令为 0;最近状态上报为 `2026-09-22T13:27:45.993773Z`。手机操作、设备重新联网与配置同步已确认;真实麦克风/扬声器对话仍需单独验证。
|
||||
|
||||
## 2026-09-16 声音断续修复
|
||||
|
||||
问题在 RTC 接收时钟配置,不是本次测试中的 Wi-Fi 信号或解码失败。Opus 接收端原来设置 `r_sample_rate=16000`、`r_samples_per_frame=320`,实物每约 60 ms 才回调一包,但每包解码只有 20 ms PCM。每秒只提供约 340 ms 声音,缓冲耗尽后持续断续。
|
||||
|
||||
接收端改为 `r_sample_rate=48000`、`r_samples_per_frame=960`。Opus RTP 使用 48 kHz 时间戳时钟,和本地解码/扬声器的 16 kHz PCM 是两个概念;不应把扬声器采样率也改为 48 kHz。依据:[RFC 7587,第 4.1 节](https://datatracker.ietf.org/doc/html/rfc7587#section-4.1)。现有上行编码参数保持不变。
|
||||
|
||||
实物对照测试:
|
||||
|
||||
下表为修正前与修正后首通约 25 秒测试的对照,非所有通话的最低缓冲保证。
|
||||
|
||||
| 指标 | 修改前 | 修改接收配置后 |
|
||||
| --- | --- | --- |
|
||||
| 下行包数 | 约 17 包/秒 | 约 50 包/秒 |
|
||||
| 每秒解码出的音频时长 | 约 340 ms | 约 1000 ms |
|
||||
| 播放队列 | 持续空队列 | 约 420–450 ms 缓冲 |
|
||||
| 解码/播放器写入错误 | 0 / 0 | 0 / 0 |
|
||||
|
||||
同时补充解码器 consumed 循环,防止忽略未消费的输入,以及每秒一次的收包/播放统计。单独修改 consumed 循环不能解决本次断续;接收时钟修改后的实物对照才确认音频供给速率恢复。
|
||||
|
||||
第二通测试持续约 60 秒后主动挂断,55 个下行统计窗口合计 55,910 ms,解码音频 55,380 ms,供给比 0.991,解码错误 0;平台确认结束,未出现崩溃或重启。期间观测到最大 339 ms 的收包间隔和一次 260 ms 间隔,软件播放队列随后耗空,因此不能宣称彻底消除所有短时断续。没有基于 RSSI 判断该停顿来自 Wi-Fi,也未在缺乏证据时修改路由器或平台配置。待用户确认听感,若仍断续,再针对短时抖动和补充缓冲定位。
|
||||
|
||||
回归检查:实际 C PCM 分帧、RTC JSON(包含接收 48000/960 断言)、解码 consumed 循环及边界测试均在 ASan/UBSan 下通过;敏感日志检查通过。COM6 应用烧录哈希校验通过。第二通过滤日志位于受限目录 `audio-fix-verification.log`,不包含音频或会话正文。
|
||||
|
||||
本次只烧录 `0x10000` 应用分区,保留当前绑定、Wi-Fi 和火山凭据。原应用备份在受限目录的 `before-audio-fix-app.bin`。固定测试语句可以验证数据链路,最终扬声器听感及麦克风真实对话仍需人工确认。
|
||||
|
||||
## 本次实物
|
||||
|
||||
- 串口:COM6
|
||||
- MAC:`B4:3A:45:16:34:A8`
|
||||
- 平台设备编号:`KP01-020026091601`
|
||||
- 平台公开 ID:`623a4e54-bdc4-4c98-b03e-27267d3ff360`
|
||||
- 蓝牙名称:`vl-ECHOEAR-S3-26091601`
|
||||
- 后端:`https://82.157.201.114`
|
||||
|
||||
2026-09-16 按用户要求改为全新逻辑测试设备:`020026091601` 是本板专用测试身份,不是实测 MAC;物理 MAC 不变。平台重新登记并生成专属密钥,工厂分区换成新身份,普通 NVS 已清空(Wi-Fi、旧火山凭据、配网及聊天缓存)。旧设备 `KP01-B43A451634A8` 已解绑,历史记录及火山旧注册记录保留,不在这次测试中复用;家庭和“姥姥”保留。不得把本板身份或 Flash 复制到其他设备。
|
||||
|
||||
## 已实现的流程
|
||||
|
||||
1. 无配网记录、手动请求配网或开机确认平台已解绑时,进入 BLE 配网。
|
||||
2. 小程序通过固定 GATT Service `8e7a2000-6f4b-4a2d-9c31-7d824f5e6100` 搜索,发送 `get_info` 获取设备编号和型号。
|
||||
3. 小程序发送 `configure`(Wi-Fi 与 bind_token),设备返回 received。轻点设备屏幕确认后连接 Wi-Fi。
|
||||
4. 非空令牌调用 `/api/v1/device/ble-bind`,保存返回的 instance_id、product_key、device_name、device_secret、RTCAppID。空令牌只调用 `/api/v1/device/ble-state` 确认仍绑定,再换 Wi-Fi。
|
||||
5. 绑定成功后保存配置,约 15 秒后重启。小程序通过 `get_status` 查看成功/失败。
|
||||
6. 正常开机使用已保存的火山凭据,在本机初始化 SDK;不调用开机 register、voice-runtime、activation-results 或 activation-acks。凭据丢失时才用 `/api/v1/device/voice-config` 恢复。
|
||||
7. 轻触屏幕或唤醒后调用 `/api/v1/device/chat/start`。每次新聊天生成新 session_id;同一通每 10 秒续期,平台拒绝或授权到期停止聊天。
|
||||
8. 将 bot_id、params 和已保存的火山凭据交给现有 RTC SDK。模型、智能体和记忆配置由平台管理;聊天文字由火山回调平台,不从设备另传一份。
|
||||
9. 停止 SDK 后调用 `/api/v1/device/chat/end`。断网保存待上报结束记录,重启补报 reboot;不把未确认的停止谎报成功。
|
||||
|
||||
BLE 使用现有明文 JSON 协议:2 字节小端长度头,分片最多 20 字节,TX 使用 Indicate。Wi-Fi 密码和火山凭据不写日志。HTTP 继续沿用平台要求的 DEVREQ1 签名和校时,不改变服务器接口。
|
||||
|
||||
## 人工测试
|
||||
|
||||
1. 小程序登录,创建家庭和测试老人。
|
||||
2. 添加 `vl-ECHOEAR-S3-26091601`,填写 2.4 GHz Wi-Fi,发送后轻点设备圆屏确认。
|
||||
3. 等小程序显示成功和设备重启,再轻触圆屏开始对话。
|
||||
4. 说一句话,确认设备有声音;结束后查看小程序的聊天记录。
|
||||
5. 平台解绑后重启设备,应回到 BLE 配网,而不是用旧老人身份继续聊天。
|
||||
|
||||
BLE 配网窗口约 5 分钟。窗口过期时重启后重新搜索。未绑定时不会自动创建老人,也不会静默绑定到其他家庭。
|
||||
|
||||
开发联调命令(仅 USB 串口、本机主动触发):`diag-say` 请求固定测试语句,`diag-stop` 挂断,`diag-state` 读取运行诊断。它们不能代替真实的麦克风、扬声器和回调验收。
|
||||
|
||||
## 构建与烧录
|
||||
|
||||
```powershell
|
||||
$env:PATH = 'C:\Users\19926\.espressif\python_env\idf5.5_py3.12_env\Scripts;' + $env:PATH
|
||||
. 'E:\Codex\toolchains\esp-idf-v5.5.1\export.ps1'
|
||||
idf.py build
|
||||
```
|
||||
|
||||
首次更新只烧录应用到 `0x10000`。随后为全新设备测试,备份当前配置,擦除普通 NVS `0x9000/0x6000`,向工厂分区 `0xe4e000/0x6000` 写入新身份并校验成功。应用、唤醒模型、屏幕资源保持不变。分区不一致的其他设备不能直接照抄这些偏移。
|
||||
|
||||
## 注册版本的验证记录(1.6.0,重置当时状态)
|
||||
|
||||
- 编译链接成功:应用 3,705,056 字节,小于 5 MB 应用分区。
|
||||
- 实际 C 聊天适配测试通过:绑定凭据保存、缓存开机、缺失凭据恢复、无旧激活接口、解绑拒绝、续期和结束重试。
|
||||
- 实际 C 蓝牙接口测试通过:读取信息、配网、绑定/仅换 Wi-Fi、重试、超时和非法输入。
|
||||
- SDK 敏感日志检查通过。
|
||||
- COM6 烧录校验成功;串口实测显示正确 BLE 名称,启动任务剩余栈 21,496 字节。
|
||||
- 新身份重置后实测 BLE 为 `vl-ECHOEAR-S3-26091601`、状态 idle;平台状态 CLAIMABLE,绑定数、激活任务数、火山凭据数、聊天数均为 0。火山注册留到用户首次绑定时触发,未提前注册。
|
||||
- 真实小程序配网绑定、双向语音与火山回调:等待人工绑定后继续验证,尚未标记通过。
|
||||
|
||||
完整旧 Flash 已备份在本机受限目录 `E:\Codex\story\.local-evidence\com6-test-20260916\before-flash-16mb.bin`,SHA256 为 `b6e39391e79a10bedd16f7e2e097c267078741d18c68fbf0366d090800fbb51f`。备份包含私有凭据,不可公开分享。
|
||||
|
||||
本次重置前最新分区另备份为同目录 `before-new-device-nvs.bin` 和 `before-new-device-factory.bin`;服务器数据库备份为 `/root/com6-new-device-20260916/before-new-device.dump`。恢复板上配置与恢复绑定关系是两回事,不要直接恢复整个数据库覆盖后续人工测试数据。新初始化私有文件存放于本机受限目录,未写入本文。
|
||||
|
||||
本次只验收注册、配网绑定与聊天;不把 MQTT 在线状态、OTA 或其他型号硬件宣称为已实测。
|
||||
Reference in New Issue
Block a user