固件:A12 命令处理器 + A13 USB 分帧 + A14 WiFi/MQTT(含 C1 配网)
- A12 单一命令处理器(cmd*.c):一行 JSON 进出、seq 全局判重(32 条按值)、
限幅 / 空槽一律拒 / 拒绝记事件;命令号与错误码冻结(进 flash)。新增 power 命令,
fan 改为只抬不压的下限(t_thermal_set_floor)。rail_set_mv 注明不拿锁,调用方包 xact。
- A13 USB-Serial-JTAG 分帧(ulink*.c):@C / @R 前缀 + CRC-16,日志行首 @ 垫空格,
任意切块可切;关掉 USB 副控制台(它绕开驱动写 FIFO)。PC 端客户端 tools/prlink.py。
- A14 + C1(netcfg / mlink / cmd_net):topic phonerail/<mac>/{cmd,rsp,tele,state},
mqtts(evse-ca 编进固件)、1 s 遥测、遗嘱离线;wifi / mqtt 配置只收 USB、存 NVS,
net 永不回显密码。
- 协议定稿写进需求文档 §10.8(A12 / A13 / A14 三节);N7 撤销改 D7(机架管理前后端)。
宿主机 23 个 ctest / 400 例全绿;板 B 已烧 0.1.0-a14,经 WiFi → 公网 → 8883 TLS 真连网验过。
固件 0xE2220 / 1 MB 分区只剩 12%,C2 前要重排分区表。
Co-Authored-By: Claude Opus 5.5 <[email protected]>
这个提交包含在:
@@ -58,7 +58,8 @@ USB 通断」这些原本要人手做的动作全部电气化,交给板上 MCU
|
||||
| D3 | 两板对插的板对板接口(两条 2×20 排针,共 80 针) |
|
||||
| D4 | 手机侧线束与离板电容组(电池排线改造、尾插 USB 线、EDL 引线) |
|
||||
| D5 | ESP32-S3 固件(遥测、两级重启、按键 / EDL 模拟、VBUS 通断、风扇闭环、告警) |
|
||||
| D5a | **双链路命令接口**(2026-09-06 用户拍板):**WiFi 为常态、USB CDC 为兜底**,两条链路共用同一套命令语义。上位机侧的调用方由农场既有系统实现(N7),本项目交付板侧协议与实现,见 §10.8 |
|
||||
| D5a | **双链路命令接口**(2026-09-06 用户拍板):**WiFi 为常态、USB CDC 为兜底**,两条链路共用同一套命令语义。本项目交付板侧协议与实现,见 §10.8;上位机见 D7 |
|
||||
| D7 | **机架管理前后端**(2026-09-27 用户拍板,取代原 N7):**架构 A 纯中心化** —— home 服务器(10.5.5.13)上跑 mosquitto + Python(FastAPI)后端 + 时序库 + Vue3 前端,走统一门户;板子经 WiFi MQTT 直连。首版功能:实时总览、手动操作、自动崩溃恢复(**服务器侧 adb over WiFi 探活 + 电流曲线确认**,先软后硬)、历史曲线与事件。**不做机架旁 agent,USB CDC 只用于上架配网与调试**(代价:WiFi 故障时没有远程救援通道,见 §10.8)。开发顺序:先补固件 A12/A13/A14,再写前后端。**2026-09-27 已上线**:代码 `rack/`(说明见 `rack/README.md`),服务 `phonerail-rack`(127.0.0.1:7764),门户 key `rack` |
|
||||
| D6 | 完整原理图(11 页)+ 两块 PCB + BOM + 首板调试与验收记录 |
|
||||
|
||||
### 2.2 明确不做(Out of Scope)
|
||||
@@ -71,7 +72,7 @@ USB 通断」这些原本要人手做的动作全部电气化,交给板上 MCU
|
||||
| N4 | USB PD / BC1.2 协商,接快充充电器 | 决策 11:上游只接电脑 / Hub,VBUS 恒 5 V |
|
||||
| N5 | 把过流保护做进 MCU 实时环路 | 那是 eFuse 的职责(SR-3) |
|
||||
| N6 | 五路 Buck 错相同步 | §8.4 已否决:器件离散度远大于想制造的相位差 |
|
||||
| N7 | 上位机管理软件 / Web 界面 | 本期只交付固件与命令接口,上层由农场既有系统对接 |
|
||||
| ~~N7~~ | ~~上位机管理软件 / Web 界面~~ | **2026-09-27 撤销**,改为交付范围 D7 |
|
||||
|
||||
---
|
||||
|
||||
@@ -783,6 +784,70 @@ ESP32.KEY_SER → U21 → U22 → U33 (先移入的字节落在链尾 U
|
||||
- **命令必须幂等或带序号**:链路重传时不能让「按 10 秒电源键」执行两遍(上面第 3 条)。
|
||||
- **链路失联不触发任何动作**(10.2):没有心跳超时关输出这回事。
|
||||
|
||||
#### A12 定稿的线上格式(2026-09-27,`firmware/main/cmd.h`)
|
||||
|
||||
一行一条、单层扁平 JSON(嵌套 / 数组 / 转义 / 浮点 / null / 重复键一律 `parse`)。
|
||||
|
||||
```
|
||||
→ {"seq":17,"cmd":"key","rail":3,"keys":"pwr","ms":10000}
|
||||
← {"seq":17,"ok":true}
|
||||
← {"seq":17,"ok":false,"err":"range"} 重传命中:{"seq":17,"ok":true,"dup":true}
|
||||
```
|
||||
|
||||
| 命令 | 参数 | 与上表的差别 |
|
||||
|---|---|---|
|
||||
| `status` | — | 只读,seq 可省,不判重。读不到的量回 `null`(不是 0) |
|
||||
| `set_voltage` | `rail`, `mv` | 限 3524~4010(DAC 物理范围,比 SR-13 的 4.2 V 更紧) |
|
||||
| `power_cycle` | `rail` | **不收断电秒数**:固定 4 s(§7.4 的 3~5 s 窗口) |
|
||||
| `key` | `rail`, `keys`(`"pwr"` / `"vdn+pwr"`…), `ms`(1~15000) | 单按电源键 ≥10 s 记一条软重启事件 |
|
||||
| `edl` | `rail` | **不收 on/off**:跑一遍 SW-6 固定序列;退出 EDL 用 `power_cycle` |
|
||||
| `vbus` | `rail`, `on` | eFuse 关着时 `on:true` 拒(`state`);序列进行中拒(`busy`) |
|
||||
| `power` ⭐新增 | `rail`, `on` | 管理界面要能停一台。关 = 先断 VBUS 再关 eFuse;VBUS 断不掉也照样关 eFuse,回 `io` |
|
||||
| `fan` | `duty`(0~1000,0 = 自动) | **只是下限**:实际 = max(温度曲线, duty),远程不能把风扇调小 |
|
||||
| `events` | `from`(可省) | 一次最多 8 条 `[序号,上电ms,路,类型,arg,mV,µA]`,类型是 `log_ev_t` 的冻结数字 |
|
||||
|
||||
- 会动东西的 7 条**必须带 seq(1~2³²−1)**;判重窗口 32 条、全局、按值相等判。
|
||||
上位机同一个 seq 只用于同一条命令的重传,「再试一次」要换新 seq。
|
||||
- 错误码:`parse / unknown_cmd / no_seq / arg / range / empty / busy / state / io / overflow`。
|
||||
`range / empty / state` 记 `LOG_EV_CMD_REJECT`(arg = 命令号,bus_mv = 越界值,current_ua = 原因号),其余不记。
|
||||
- 空槽(`PRSNT#` 高)的按路命令一律 `empty`。
|
||||
- 板子重启会清空判重窗口;上位机看 `status.up` 变小识别重启。
|
||||
|
||||
#### A13 定稿的 USB 分帧(2026-09-27,`firmware/main/ulink.h`)
|
||||
|
||||
```
|
||||
上位机 → 板 @C <json>[*XXXX]
|
||||
CRC 可省(给人手敲);带了就必须对
|
||||
板 → 上位机 @R <json>*XXXX
|
||||
CRC 必带;XXXX = CRC-16/CCITT-FALSE(json),4 位大写十六进制
|
||||
其余任何一行 = 日志
|
||||
```
|
||||
|
||||
- 前缀只在行首算数;日志行若以 `@` 开头,固件会垫一个空格 ⇒ 日志永远不会被当成帧。
|
||||
- 链路层自己的错误(不进命令处理器、不记事件):`too_long` / `bad_crc` / `bad_frame`(NUL 或控制字符)/ `queue_full`,能解析出 seq 就回显。
|
||||
- **USB 副控制台已关**(`CONFIG_ESP_CONSOLE_SECONDARY_NONE`):USB 上只有「日志钩子的副本 + 回应」两路,同一把锁;`printf` / panic 只去 UART0(J33)。
|
||||
- 上位机打开串口时 **DTR / RTS 保持低**,否则可能把板子复位。参考实现 `firmware/tools/prlink.py`。
|
||||
- 实测(板 B,2026-09-27):200 条 status 连发 0 坏帧,混进的 `t_safety` 日志全部正确识别;往返 status ≈3 ms、小命令 <1 ms。
|
||||
|
||||
#### A14 定稿的 MQTT 链路(2026-09-27,`firmware/main/mlink.h` / `netcfg.h`)
|
||||
|
||||
base = `phonerail/<id>`,id = 板子 STA MAC 的 12 位小写十六进制(板 B = `b81f3fc9c8bc`)。
|
||||
|
||||
| topic | 方向 | QoS | retain | 内容 |
|
||||
|---|---|---|---|---|
|
||||
| `<base>/cmd` | 服务器 → 板 | 1 | 否 | 一条命令 JSON(与 USB `@C` 负载相同,无前缀无 CRC) |
|
||||
| `<base>/rsp` | 板 → 服务器 | 1 | 否 | 一条回应 JSON |
|
||||
| `<base>/tele` | 板 → 服务器 | 0 | 否 | 周期遥测 = 一条 status 回应(无 seq),默认 1 s(`tele_ms` 200~60000) |
|
||||
| `<base>/state` | 板 → 服务器 | 1 | 是 | `{"online":true,"fw":..,"ip":..}`;掉线由遗嘱改成 `{"online":false}`(keepalive 15 s) |
|
||||
|
||||
- **配网(C1)**:`wifi`(ssid / pass)与 `mqtt`(uri / user / pass / tele_ms)两条命令,存 NVS,**只收 USB**(经 WiFi 来回 `link` 并记事件)。
|
||||
`net` 查网络状态,**永不回显密码**(只报 `pass_set` / `mpass_set`);含 `wifi_reason`(最近一次断开原因码)。
|
||||
- uri 收 `mqtts://`(TLS,CA 编在固件:`firmware/main/certs/evse_ca.pem`)或 `mqtt://`(只该用在局域网)。
|
||||
- **broker = home 服务器现有 mosquitto 的 8883(TLS)**,与 evse 共用:板子用户名 = id,ACL 用 `pattern … phonerail/%u/…`
|
||||
只许碰自己的四个 topic;后端用户 `phonerail-backend` 可读写 `phonerail/#`。口令在服务器 `/root/phonerail/mqtt.env`(仅 root)。
|
||||
- 失联不动作:WiFi 断按 1/2/4…60 s 退避重连,MQTT 由 esp-mqtt 每 10 s 重连;没有任何分支会碰输出。
|
||||
- 实测(板 B,2026-09-27):经 WiFi `CANBOX-5G` → 公网 → 8883 TLS 连上;判重 / `link` / `empty` / `parse` 回应与遥测(1 条/s)全部符合。
|
||||
|
||||
### 10.9 启动顺序
|
||||
|
||||
```
|
||||
@@ -858,6 +923,7 @@ FR-12 是「中(可选)」,建议**首版先不做**,把接口留出来
|
||||
### 11.2 假设(若不成立需重新评估)
|
||||
|
||||
| ID | 假设 |
|
||||
| **MQTT broker 与 topic** | 2026-09-27 起由本项目自定(D7,broker 在 home 服务器);topic 约定随 A14 写进 §10.8 |
|
||||
|---|---|
|
||||
| **A-1** | 上游 USB 恒为 5 V(只接电脑 / Hub,不接快充头) |
|
||||
| **A-2** | 手机关机待机电流在 ≈50 µA 量级 |
|
||||
|
||||
在新工单中引用
屏蔽一个用户