# FANUC TCP 10010 状态帧字段说明 本文档整理当前现场真实抓包中 `TCP 10010` 状态通道的已确认字段布局,并明确哪些结论已经由抓包和代码验证,哪些仍然只是工作假设。 读取时间:2026-05-03 ## 1. 结论范围 本文基于以下证据整理: - `../analysis/UTTC_20260428_packet_validation.md` - `../analysis/J519_stream_motion_analysis.md` - `Rvbust/uttc-20260428/20260428.pcap` - `src/Flyshot.Runtime.Fanuc/Protocol/FanucStateProtocol.cs` - `tests/Flyshot.Core.Tests/FanucProtocolTests.cs` 当前结论仅覆盖现场已确认的 `R30iB + RVBUSTSM` 这一路状态通道行为,不提前推广为所有 FANUC 机型或所有旧版本协议的通用结论。 ## 2. 通道性质 真实抓包显示,`TCP 10010` 是控制柜到上位机的单向状态流: - 上位机先主动建立 TCP 连接。 - 建连后,带应用层 payload 的业务包全部来自 `192.168.10.11:10010 -> 192.168.10.10:41726`。 - 上位机在该通道上只回 TCP `ACK`,没有观察到应用层请求体。 因此当前实现应把 `10010` 当作“持续推送的固定长度状态帧”处理,而不是像 `TCP 10012` 那样按请求/响应语义建模。 ## 3. 整体布局 当前现场抓包确认,状态帧固定为 `90B`: ```text doz 3 bytes length u32 = 90 msg_id u32 pose[6] f32 joint_or_ext[9] f32 tail[4] u32 zod 3 bytes ``` 其中: - 帧头 magic 固定为 `doz` - 帧尾 magic 固定为 `zod` - 长度字段固定为 `0x5a`,即 `90` - 当前全量抓包中 `msg_id` 恒为 `0` - `tail[4]` 当前全量抓包中恒为 `(2, 0, 0, 1)` ## 4. 样例帧 以下样例帧来自 `20260428.pcap` 中首条 `tcp.port == 10010 && tcp.len > 0` 的 payload: ```text 646f7a0000005a000000004388a23243f1ed7f43e9de6bc265031ec2b33cc3c278e0153f8742f53c3f128dbc929529bc7861d63cb0184c3c1ca1a7000000000000000000000000000000020000000000000000000000017a6f64 ``` 对应解析值: - `pose[6]` - `273.26715` - `483.85544` - `467.73764` - `-57.253044` - `-89.618675` - `-62.21883` - `joint_or_ext[9]` - `1.0567309` - `0.011662138` - `-0.01789339` - `-0.015160045` - `0.02149596` - `0.009560025` - `0` - `0` - `0` - `tail[4]` - `2` - `0` - `0` - `1` ## 5. 正式字段表 | 偏移 | 长度 | 类型 | 样例值(hex) | 样例值(解析后) | 当前推断含义 | | --- | --- | --- | --- | --- | --- | | `0x00` | `3` | `char[3]` | `64 6f 7a` | `"doz"` | 固定帧头 magic | | `0x03` | `4` | `u32 be` | `00 00 00 5a` | `90` | 帧总长度 | | `0x07` | `4` | `u32 be` | `00 00 00 00` | `0` | `msg_id`,当前抓包全为 `0` | | `0x0B` | `4` | `f32 be` | `43 88 a2 32` | `273.26715` | `pose[0]`,推断为 TCP `X(mm)` | | `0x0F` | `4` | `f32 be` | `43 f1 ed 7f` | `483.85544` | `pose[1]`,推断为 TCP `Y(mm)` | | `0x13` | `4` | `f32 be` | `43 e9 de 6b` | `467.73764` | `pose[2]`,推断为 TCP `Z(mm)` | | `0x17` | `4` | `f32 be` | `c2 65 03 1e` | `-57.253044` | `pose[3]`,推断为姿态角 `W(deg)` | | `0x1B` | `4` | `f32 be` | `c2 b3 3c c3` | `-89.618675` | `pose[4]`,推断为姿态角 `P(deg)` | | `0x1F` | `4` | `f32 be` | `c2 78 e0 15` | `-62.21883` | `pose[5]`,推断为姿态角 `R(deg)` | | `0x23` | `4` | `f32 be` | `3f 87 42 f5` | `1.0567309` | `joint_or_ext[0]`,推断为 `J1(rad)` | | `0x27` | `4` | `f32 be` | `3c 3f 12 8d` | `0.011662138` | `joint_or_ext[1]`,推断为 `J2(rad)` | | `0x2B` | `4` | `f32 be` | `bc 92 95 29` | `-0.01789339` | `joint_or_ext[2]`,推断为 `J3(rad)` | | `0x2F` | `4` | `f32 be` | `bc 78 61 d6` | `-0.015160045` | `joint_or_ext[3]`,推断为 `J4(rad)` | | `0x33` | `4` | `f32 be` | `3c b0 18 4c` | `0.02149596` | `joint_or_ext[4]`,推断为 `J5(rad)` | | `0x37` | `4` | `f32 be` | `3c 1c a1 a7` | `0.009560025` | `joint_or_ext[5]`,推断为 `J6(rad)` | | `0x3B` | `4` | `f32 be` | `00 00 00 00` | `0` | `joint_or_ext[6]`,扩展轴槽位,当前样本恒 `0` | | `0x3F` | `4` | `f32 be` | `00 00 00 00` | `0` | `joint_or_ext[7]`,扩展轴槽位,当前样本恒 `0` | | `0x43` | `4` | `f32 be` | `00 00 00 00` | `0` | `joint_or_ext[8]`,扩展轴槽位,当前样本恒 `0` | | `0x47` | `4` | `u32 be` | `00 00 00 02` | `2` | `tail[0]`,诊断状态字,物理语义未坐实 | | `0x4B` | `4` | `u32 be` | `00 00 00 00` | `0` | `tail[1]`,诊断状态字,物理语义未坐实 | | `0x4F` | `4` | `u32 be` | `00 00 00 00` | `0` | `tail[2]`,诊断状态字,物理语义未坐实 | | `0x53` | `4` | `u32 be` | `00 00 00 01` | `1` | `tail[3]`,诊断状态字,物理语义未坐实 | | `0x57` | `3` | `char[3]` | `7a 6f 64` | `"zod"` | 固定帧尾 magic | ## 6. 已确认结论 ### 6.1 已由真实抓包确认 1. `TCP 10010` 是独立状态流,不是 `TCP 10012` 的请求/响应复用。 2. 当前现场状态帧固定为 `90B`,不是早期静态分析里出现过的 `134B`。 3. `msg_id` 在 `20260428.pcap` 当前全量样本中恒为 `0`。 4. `tail[4]` 在 `20260428.pcap` 当前全量样本中恒为 `(2, 0, 0, 1)`。 5. `pose[6]` 的量纲表现符合 `X/Y/Z(mm) + W/P/R(deg)`。 6. `joint_or_ext[6..8]` 在当前现场样本中恒为 `0`。 ### 6.2 已由数值范围和交叉对照强支持 1. `joint_or_ext[0..5]` 更像关节角 `rad`,而不是 `deg`。 2. 该判断与 `../analysis/UTTC_20260428_packet_validation.md` 的结论一致。 3. 该判断也与 `UDP 60015` 响应包中的关节 `deg` 形成互补关系:二者不能简单视作同单位直接复用。 ## 7. 待确认项 以下内容当前不要写死为最终协议真义: 1. `tail[4]` 四个 `u32` 分别代表什么控制器语义。 2. `msg_id` 是否在其他控制柜版本、程序状态或异常态下会出现非零值。 3. `pose[3..5]` 是否可以严格命名为 FANUC 标准 `W/P/R`,还是只是与其数值表现一致。 4. `joint_or_ext[6..8]` 在带外部轴的现场是否仍复用同一布局。 ## 8. 与当前代码实现的对齐情况 当前仓库里 `Flyshot.Runtime.Fanuc` 已按 `90B` 固定帧解析: - `src/Flyshot.Runtime.Fanuc/Protocol/FanucStateProtocol.cs` - `tests/Flyshot.Core.Tests/FanucProtocolTests.cs` 当前实现已经与抓包对齐的部分: 1. 固定长度 `90B` 2. `doz ... zod` 帧头帧尾校验 3. `pose[6] + joint_or_ext[9] + tail[4]` 的字节布局 4. `tail[4]` 原样保留到 `ControllerStateSnapshot.StateTailWords` 当前仍建议后续关注的点: 1. `FanucStateFrame` 已把该字段从 `JointDegrees` 更正为 `JointRadians`,后续新增代码应继续沿用弧度制命名。 2. 如果后续状态页或运行时逻辑需要直接展示该通道关节值,仍需明确标注这是 `10010` 的弧度值,避免和 `UDP 60015` 的 degree 语义混淆。 ## 9. 建议用法 在当前 replacement 实现里,`TCP 10010` 更适合作为以下用途: 1. 提供机器人当前笛卡尔位姿和关节反馈快照。 2. 提供状态通道是否健康、是否陈旧的连接诊断依据。 3. 保留 `tail[4]` 原始状态字,供现场排错或后续继续逆向。 当前不建议直接用 `tail[4]` 去驱动明确业务判断,除非后续拿到新的现场对照证据。