# T-WIN-003 接收 Android 关键点帧 - **状态**: done - **依赖**: T-WIN-001 ## 目标 在本端监听 `ws://:8765/pose`,作为 WebSocket **服务端**接收 Android 辅助 App 的推流。 ## load ``` DSH.md contracts/websocket-keypoints.md # 锚点:1 端点与子协议、3 文本控制帧 src/net/pose_server.gd src/autoload/pose_receiver.gd ``` ## 交付物 - `src/net/pose_server.gd`: TCPServer + `WebSocketPeer.accept_stream()` 实现服务端 - `src/autoload/pose_receiver.gd`:绑定 AppConfig,暴露 `latest_frame` 与统计 ## 能力 | 项 | 说明 | |--|--| | 子协议 | 协商 `opendance.pose.v1`,客户端选择不符时告警 | | 控制帧 | `hello` -> 回 `welcome`(含 sessionId);`bye` -> 关闭 | | 协议不匹配 | 回 `bye{reason: protocol_mismatch}` 并以 1002 关闭 | | 二进制帧 | 严格校验 239 字节与 magic,畸形帧计数但不影响连接 | | 丢包统计 | 按 `frame_id` 跳号计数(含 u32 回绕保护) | | 帧率统计 | 1 秒窗口计算 FPS | | 超时剔除 | 5 秒无数据判定超时断开 | | config 推送 | 每 2 秒广播 mirror / targetFps / upperBodyOnly / resolution | ## 已知限制 Godot 的 `WebSocketPeer` 不暴露握手请求路径,因此**无法校验 path 是否为 `/pose`**, 实现接受任意 path,仅校验子协议。已记录于 DSH.md 与任务文档。 ## 验收 `tests/test_pose_server.gd` 在真实 socket 上端到端验证:握手、子协议协商、 hello/welcome、二进制帧往返、畸形帧拒绝、丢包计数、flag 保留、config 广播、snapshot、stop。