# 设备发现、基础信息与升级协议 仅在任务涉及设备网络发现、版本查询或 ROM 传输时读取本文件。优先使用用户提供的最新协议、现有已验证实现和抓包;文档歧义不得伪装成确定事实。 ## 本机参考资料 存在时优先核对: - `C:\Users\ZK\Documents\ChatGPT\日常开发\调试资料\设备端协议V2-工厂整合版本.md` - `C:\Users\ZK\Documents\ChatGPT\日常开发\调试资料\设备端统一配置协议V2.md` - `C:\Users\ZK\Downloads\设备端TCP文件传输类协议.md` - `C:\Users\ZK\Downloads\工厂协议V1.md` - `E:\CodeSpace\git-pro\eapil_qt_player_v2\EpProtocolDemo` - `E:\CodeSpace\git-pro\eapil_public_library\EapilPanoC\src`(V1 命令、端口、数据结构和 Qt 客户端实现;以当前源码为实现依据,部署设备仍需实测) ## V1 协议(EapilPanoC) V1 与 V2 使用不同端口和帧格式,不能把 `EPBP/EPTP/EPFP` 的 V2 帧头套用到 V1 通用配置接口。 | 功能 | 传输与端口 | 请求/响应格式 | |---|---|---| | 局域网搜索 | UDP `4942`,向广播地址 `4942` 发送并在本地 `4942` 接收 | `uint32 cmd + uint32 JSON长度 + UTF-8 JSON` | | 通用配置获取/查询 | TCP 设备端 `4941` | `uint32 cmd + uint32 payload长度 + payload`;常见无参读取长度为 0;响应为 `uint32 cmd + uint32 JSON/数据长度 + payload` | | 固件升级 | TCP 设备端 `4941` | `uint32 cmd + uint32 长度 + 32字节ASCII小写MD5十六进制文本 + ROM原始字节`;长度是 MD5 文本与 ROM 字节数之和 | V1 多字节整数由源码中的 `QDataStream` 默认网络字节序编码(大端)。TCP 是字节流,必须先累积完整 8 字节响应头,再按头内长度读取完整 payload;不能假定一次 `recv` 返回一整帧。JSON 请求/响应的长度不包含 8 字节头。搜索响应也必须校验命令、长度和请求 `session`。 ### V1 搜索 源码:`EpSearchPanocsInLan.cpp`、`json/SerachCameraRequest.cpp`、`json/SerachCameraResponse.cpp`。 请求命令 `0x5a0eff00`,响应命令 `0x5a0eff01`。请求 JSON 至少带随机 `session`: ```json {"session":12345} ``` 响应常见字段:`session`、`ip`、`dev_type`、`sn`、`mac`、`firmware`、`hardware`、`dev_id`、`dev_ver`,部分设备另有 `ipv6`、`wifi_ssid`、`wifi_quality`。按回显 session 过滤本轮响应。搜索会列出广播域中的多台设备;不得把第一个响应当目标。升级或其他写操作仍要求完整 SN 与型号核验。若设备 SN 为空,只能将搜索结果用于只读信息查询;SN 空值不构成设备身份核验,不能据此绕过写操作的身份保护。 ### V1 通用配置读取命令 以下命令来自 `EapilPanoCHead.h` 的 V1 `MessageCMDType`,对应 `EpPanoCConfigure.cpp` 的 getter/query 实现。大部分请求使用空 payload;按返回命令和 JSON `code` 判定设备是否支持,`code=0` 表示设备成功应答,不代表每个可选字段都存在。 | 项目 | 命令 | |---|---:| | 获取 SN | `0x5a0e2100` | | 获取模板 | `0x5a0e2102` | | 获取基本信息 | `0x5a0e2104` | | 获取圆心坐标 | `0x5a0e2110` | | 查询视频参数范围 / 获取视频参数 | `0x5a0e2120` / `0x5a0e2121` | | 查询音频参数范围 / 获取音频参数 | `0x5a0e2130` / `0x5a0e2131` | | 查询 ISP 参数范围 / 获取 ISP 参数 | `0x5a0e2140` / `0x5a0e2141` | | 获取缩略图 | `0x5a0e2150`(二进制 JPEG,不按 JSON 解析)| | 获取 SD 卡信息 | `0x5a0e21a0` | | 获取网络信息 | `0x5a0e21b0` | | 获取 Wi-Fi 信息 | `0x5a0e21c0` | | 获取时间信息 | `0x5a0e21d0` | | 获取夜视信息 | `0x5a0e21e0` | | 获取浪涛兼容 ID | `0x5a0e3100` | | 获取大拿兼容 ID / danale.conf | `0x5a0e3200` / `0x5a0e3210` | 兼容平台接口可能返回“不支持平台/命令”;要记录为设备能力结果,不要当作传输层故障。`0x5a0e3210` 返回配置内容,可能包含敏感字段;仅在用户任务确需时调用,控制原始结果的保存、展示和转发范围。V1 还定义工厂/扩展类读命令(如 PTZ、MAC、IMEI、老化测试、设备密码等),不属于上述通用配置接口;有的需要特定参数,有的会暴露敏感信息。不要用零参数盲发或把它们当作通用 getter。先从目标型号对应实现核对参数、返回结构和敏感性,再按明确任务范围调用。绝不调用 SET 命令来“探测”支持能力。 ### V1 固件升级 V1 升级命令为 `0x5a0e2170`,TCP 端口 `4941`。实现依据 `EpConnection::sendTcpFile`:计算 ROM MD5 并转为 32 字节 ASCII 十六进制文本,帧长度字段等于 `32 + ROM字节数`,随后发送 MD5 文本及 ROM 内容。响应仍按 V1 `cmd + length + payload` 解析,成功 JSON 示例为 `{"code":0,"desc":"update success"}`。这不是 V2 `EPFP/4001` 的状态轮询协议;不得把 V2 的 `status=2` 要求硬套到 V1。V1 成功应答后仍须检查串口重启、网络恢复、重新搜索与目标版本回查;缺项必须明确标为未验证。 执行升级前仍遵守本文“升级前保护”与主技能的用户确认要求。已有工具若只支持 V2,不能改参数伪装成 V1;应使用明确实现 V1 的客户端,并保留 ROM 路径、大小、MD5、SHA-256、目标 IP、型号、升级响应及升级后版本证据。完整 SN 缺失时不得以型号/IP 替代身份核验,也不得执行写操作。 ### V1 现场验证样例(C4662) 2026-10-21 对一台 C4662 的实测仅作为该设备/固件的实例,不代表所有 V1 设备字段恒定:V1 搜索和基本信息返回 `dev_ver=2.0.20261021.1`、`firmware=1.0.4`、`dev_type=C4662`,但 SN 为空。常见 getter 中视频、音频、ISP、SD、网络、时间、夜视、缩略图和大拿 ID 接口有成功响应;模板、浪涛兼容接口和 danale.conf 在该设备返回失败或不支持。成功但无数据字段的响应(例如 Wi-Fi 信息)应如实记录,不推测配置值。 ## V2 协议矩阵 | 功能 | 传输与端口 | 帧格式 | |---|---|---| | 设备发现请求 | UDP,客户端从本地 `8951` 向设备 `8941` 广播 | `EPBP + uint32长度 + UTF-8 JSON` | | 设备发现响应 | UDP,客户端 `8951` 接收 | 同上,完整帧在一个数据报内 | | 统一配置 | TCP,设备 `8942` | `EPTP + uint32长度 + UTF-8 JSON` | | 固件升级 | TCP,设备 `8943` | `EPFP + uint32命令 + uint32长度 + 二进制数据` | 多字节整数使用网络字节序。配置 TCP 长度端序在整合文档中没有单独声明,但现有设备和客户端验证采用网络序。 ## 发现与身份 V2 发现请求 JSON: ```json {"cmd":60000,"session":12345} ``` 响应必须回显相同 `cmd/session`。身份字段包括 `sn`、顶层烧录 `mac`、`inner`、`outer`、`hardware` 和 `net`。顶层 `mac` 与 `net.mac` 可能不同。型号判断同时展示: - `inner.type` - `outer.type` - `hardware.type` 非关键网络字段允许缺失。完整 SN 是升级身份核对的首要依据。V1 的端口与帧格式见上文 V1 章节,并以目标设备对应的 V1 文档或源码复核;不能套用 V2。 执行发现时使用 `scripts/v2_discover.py`,并遵守以下规则: 1. 默认枚举已启用、已连接且具有有效 IPv4 的物理网卡;回环、断开、APIPA、VPN、VMware、Npcap 等接口要列出并注明排除原因。用户明确要求所有活动接口时才加入虚拟接口。 2. 每个接口分别绑定其本地 IPv4 和客户端端口 `8951`,同时发送有限广播 `255.255.255.255` 和按前缀计算的定向广播。不能把 `/22` 的广播地址按 `/24` 猜测。 3. 如果 UDP `8951` 被 EapilCameraConfigurer 或其他进程占用,报告占用者,不结束进程;请用户释放端口,或使用已有工具明确支持的搜索结果。 4. 从临时源端口发包只可作为诊断。设备可能只向 `8951` 回复,因此临时端口无响应不能证明设备离线。 5. 打印所有合法候选并按完整 SN 精确匹配;不得选择第一台。响应需校验 `EPBP`、长度、`cmd/session`。只有 SN、源 IP、MAC 和型号都一致的重复响应可以合并;同一 SN 对应不同身份信息时报告冲突并禁止自动选择。 6. 未提供完整 `--expected-sn` 时脚本只是列表模式,即使退出码为 0 也不代表身份核验成功。Telnet、升级及其他设备写操作必须提供完整 SN,并根据任务要求同时传入型号。 ## 基础信息 通过 TCP `8942` 发送 `cmd=30101`。响应必须满足:同步头正确、长度合理、`cmd/session` 匹配且 `code=0`。读取: - `sn`、`mac` - `inner.type/version` - `outer.type/version` - `hardware.type/version` `hardware.version` 不是固件版本。升级后应根据 ROM 类型比较 `inner.version` 或 `outer.version`。如果无法从 ROM 或构建记录确定应变化的字段,必须明确说明并让用户确认预期。 `30102` 可能返回密码和密钥,只在调试任务确实需要时调用。用户选择保留原始调试数据,因此响应可原样写入本次任务日志,但不得写入 skill 本体。 ## 固件升级 4001 请求: ```text EPFP + uint32 4001 + uint32 ROM字节数 + ROM原始字节 ``` ROM 前没有 MD5 或目标路径业务前缀。不要把普通文件写入 `2001` 的 MD5 机制声称为升级 `4001` 自带校验。 状态业务数据为 21 字节: ```text uint8 status + uint32 sessionId + uint32 downloadTotal + uint32 downloaded + uint32 flashTotal + uint32 flashed ``` 状态:`0` 空闲、`1` 开始、`2` 完成、`3` 失败。`sessionId` 不等同于配置 JSON session,不要求匹配。解析器要兼容完整 `EPFP/cmd/length` 状态帧与设备实测出现的裸 21 字节状态,但完整帧必须校验响应命令为 `4001`。 只有 `status=2` 是协议成功终态;下载或 Flash 计数达到总量不能替代它。`status=3` 立即失败。连续 60 秒没有下载或 Flash 进度变化视为停滞,值允许覆盖。没有依据时不自动续传或重试。 设备报告的 `downloadTotal`、`flashTotal` 可能与 ROM 文件字节数不同,不能因为这种封装头、元数据或分区差异单独判失败。`status=2` 是协议成功终态;如果此时 `downloaded/flashed` 仍小于设备各自报告的非零总量,记录协议计数异常警告并纳入验证报告,但不自行推翻设备的成功终态。 ## 升级前保护 - ROM 必须是普通文件,大小大于 0 且不超过无符号 32 位长度。 - 计算并记录 SHA-256;协议本身没有 ROM 签名或来源认证,不能声称 SHA-256 提供设备侧认证。 - 精确核对设备 SN。 - 同时展示当前型号和 ROM 目标型号。ROM 元数据无法解析时显示“无法验证型号”,并重新取得用户确认。 - 多个 ROM 或设备候选时等待选择。搜索端口被占用或没有完成完整 SN 核对时不得升级。 - 确认后调用 `scripts/device_upgrade.py --execute`,不绕过其保护参数。 串口登录可以确认现场设备、读取版本并恢复网络,但不能替代升级前的 `30101` 身份响应。即使 COM 口已由用户确认且串口内的 SN、型号看似匹配,`30101` 超时、返回不完整或不匹配时仍不得发送 ROM。先检查设备端端口监听、接口 MAC、关联、DHCP、PC 多网卡选路和二层可达性;恢复后重新运行标准预检。 ## 已知协议歧义 - 状态章节没有明确说明每次状态是否带 EPFP 外层头,因此客户端兼容完整帧和裸状态。 - 没有规定分块大小、连接关闭方、断线恢复或统一总超时;使用可配置值并保存最后进度。 - 没有定义 ROM 与型号的自动匹配机制。 - TCP 是字节流,必须累积并按长度解析,不能把单次 `recv` 当作完整帧。