Files

81 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# V1 搜索、查询与固件下发
本页摘记已实现接口;来源文件、修订及摘要见 [协议范围](protocol-support.md)。完整原文保留在资料提供方本地,分发包不附其他配置章节。实现在 `scripts/v1_protocol.py`,由适配器 `--protocol v1` 路由,不发送 V2 报文。
## 报文与端口
报文头共 8 字节:CMD、Length 各为网络字节序 U32,随后是恰好 Length 字节的 Data。长度按字节计算。只读 JSON 响应须为 UTF-8 对象;实现拒绝命令/长度不符、超过 1 MiB、错误类型及未完整接收的报文。
| 操作 | 传输 | 请求 | 返回 |
| --- | --- | --- | --- |
| 搜索 | 设备 UDP 4942,广播 | `0x5a0eff00`;JSON `{"session":1234}`,每次使用新的随机整数 | `0x5a0eff01`;同一整数 session,完整字符串 sn,以及 dev_type、ip、mac、firmware、hardware |
| 基本/固件信息 | 设备 TCP 4941 | `0x5a0e2104`;Length=0,无 Data;十六进制请求 `5a0e210400000000` | 同命令 JSON;整数 code=0 成功,其他值失败 |
| 固件升级 | 设备 TCP 4941 | `0x5a0e2170`;Data 为小写 ASCII MD5[32] + ROM,Length=32+ROM字节数 | 同命令、完整 JSON、整数 code=0;只确认协议应答,另行回读版本 |
TCP 查询处理报文分片,在连接/发送/接收阶段扣减同一时限,不自动重试。较新工厂文档建议查询 5 秒无响应超时,示例显式使用 `--timeout 5`。主机名解析及多地址尝试由系统 socket 负责,严格现场时限宜使用已确认的数字设备 IP。
广播接收绑定 `0.0.0.0:<client-port>`,默认 4942;请求从同一 socket 发到各选定 IPv4 网段的定向广播地址,目的端口 4942。默认枚举已启用物理网卡并排除回环/APIPA;可用 `--interface IPv4/PREFIX` 指定网段。相同网段只发一次,/31、/32 跳过。出接口服从 Windows 路由,特殊路由环境需现场核实。原文未规定客户端接收端口;默认 4942 是本机已验证的实现选择,`--client-port` 可调整,不能推广为所有固件的规范要求。
设备可能广播回复,因此接收 socket 不只绑定某个单播 IP。不启用端口复用、不结束占用进程;端口被占用时报告错误并释放本次 socket。忽略自身请求、错误 session/帧和非成功 code,精确筛选完整 SN/型号。按 SN、UDP 源 IP、MAC、型号去重;同 SN 出现冲突身份时阻断选择。后续连接使用实际 UDP 源 IP,报文中的 ip 只保留为观测。无响应只说明本轮未发现,不等于设备离线。
## 身份与版本字段
`2104` 保留文档字段 code、desc、sn、dev_type、firmware、hardware、dev_id、dev_ver。除整数 code 外均按字符串校验。如果设备额外直接上报 inner.version 或 outer.version 字符串,只保留该字面路径的版本值,供任务明确指定字段时观测;不保留其余未知字段。
| 字段 | 文档含义 | 用途 |
| --- | --- | --- |
| sn | 设备 SN | 与本次完整 SN 精确比较,不截尾、不去空格 |
| dev_type | 设备类型 | V1 `--expected-model` 唯一匹配字段 |
| dev_id | 设备 ID | 只保留,不代替型号 |
| firmware | 固件版本号 | 可由任务明确选择为原生固件验收字段 |
| dev_ver | 设备版本号 | 可由任务明确选择,不推断与 V2 字段的关系 |
| hardware | 硬件版本号 | 只观测,不作为固件验收 |
两份文档和 V1 查询源码没有 `firmware/dev_ver` 到 `inner.version/outer.version` 的对应关系。选择缺失的 outer.version 得到 `INCOMPLETE`,不会把 firmware 或 dev_ver 自动改名。如果设备直接上报所选字面路径,则可按该值比较。设备/文件名看起来可以猜出对应关系,也不能据此完成指定字段验收。
适配器用显式封套区分协议:
```json
{"protocol":"v1","cmd":1510875396,"code":0,"data":{"code":0,"sn":"<完整SN>","dev_type":"<型号>","firmware":"<版本>"}}
```
1510875396 是 `0x5a0e2104` 的十进制值。封套是适配器输出格式;线上 Data 是内部 JSON 本身。`verify-version --response` 接受此封套,或含 response 的完整 CLI 输出;不能使用 V2 30101 文件冒充 V1 响应。
## 调用示例
在技能目录执行,下列值均为占位符。型号未知时先 identify,只证明 SN 一致并观察型号,返回 model_verified=false;再带实测型号执行 info/预检。
```powershell
python scripts/device_adapter.py discover --protocol v1 --interface "<本机IPv4/前缀>" --expected-sn "<完整SN>" --timeout 5
python scripts/device_adapter.py identify --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --timeout 5
python scripts/device_adapter.py info --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --timeout 5
python scripts/device_adapter.py upgrade --protocol v1 --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --rom "<ROM路径>" --rom-sha256 "<64位SHA256>" --target-version "<目标版本>" --version-field firmware --timeout 5
python scripts/device_adapter.py upgrade --protocol v1 --host "<数字设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --rom "<ROM路径>" --rom-sha256 "<审阅过的64位SHA256>" --target-version "<目标版本>" --version-field firmware --timeout 5 --execute
python scripts/device_adapter.py verify-version --protocol v1 --host "<设备IP>" --expected-sn "<完整SN>" --expected-model "<实测dev_type>" --target-version "<目标版本>" --version-field firmware --timeout 5
```
只有任务明确选择 firmware 时才使用示例字段;已有其他验收条件时保持原条件。V1 upgrade 默认返回 `PREFLIGHT_ONLY`,preflight_complete=true、write_supported=true、write_executed=false;selected_version_field_available 说明指定字段是否存在。当前任务已授权升级时,带审阅摘要及 `--execute` 才执行一次下发;不重复请求已给出的授权。
## 升级报文与完成含义
用户提供的 Qt 源码 `EpConnection::sendTcpFile` 补齐了文档第 21 节的空白 Data,线格式为:
```text
U32_BE 0x5a0e2170
U32_BE (32 + ROM字节数)
MD5_hex_ascii[32] # 全 ROM 的 MD5,小写十六进制文本;不是16字节原始摘要
ROM[ROM字节数]
```
总线上字节数为 ROM大小+40。没有 EPFP 前缀、文件名或自定义块头。源码使用约200 KiB块;TCP分块不改变线上字节序列,CLI采用256 KiB缓冲并处理部分send。不能把同一源码中的 `sendTcpFileV2(protocol=1)`(端口8940、EPFP/4001)混作此接口。
CLI 在完整 SN/dev_type 在线预检后重新验证 SHA-256。V1 发送器在同一个打开的文件上计算 MD5及SHA-256,核对大小/审阅摘要后才连接;回到文件开头发送,再对发送内容核对 SHA-256。Data长度必须适合 U32。总时限覆盖哈希、连接、发送、接收;各次 socket 操作还有连接/停滞时限。不会重连或自动重试传包,所有退出路径释放句柄。
收到完整 `2170` JSON 且整数 code=0、客户端实际发送 ROM 字节数等于文件大小,才返回 `PROTOCOL_SUCCESS_POSTCHECK_REQUIRED`。acknowledged=true 和 desc 只记录设备应答,不能证明烧录或启动完成。之后有界等待并重新查询同一 SN 的指定版本字段;发送/接收超时、断开或错误也应先只读检查状态,不能自动重刷。缺失验收字段不阻断已授权传包,但必须在最终验收中保留 `INCOMPLETE`。
## 验证范围
2026-10-19,全部118项离线测试通过,其中 V1 查询/发现24项、升级14项、适配器28项。V1 测试运行实际编解码及发送器,覆盖已知 MD5报文、分片发送/响应、计数、错误应答、文件变化、总/停滞时限、精确身份、摘要门槛、默认不写入及无自动重刷。
同日,在一台用户授权 V1 设备上完成一次19,420,244字节 ROM 下发,收到同命令code=0/desc=update success。随后连续两次只读查询与原 SN/dev_type 一致,原生 firmware 从2.0.1变为2.0.2、dev_ver 从2.0.20260908.5变为2.0.20260908.6。指定 outer.version 仍缺失,验收为 INCOMPLETE;不改用原生字段冒充指定字段通过。该实测不代表所有 V1 固件兼容,现场身份及日志独立保存。