yb преди 13 часа
родител
ревизия
8951e140f9
променени са 1 файла, в които са добавени 104 реда и са изтрити 95 реда
  1. 104 95
      docs/GO_REWRITE_REQUIREMENTS.md

+ 104 - 95
docs/GO_REWRITE_REQUIREMENTS.md

@@ -34,11 +34,11 @@
 
 采用领域驱动设计 (DDD) 分层:
 
-| 层 | 职责 |
-|---|------|
-| **adapter** | REST API 控制器,对外暴露 HTTP 接口 |
-| **application** | 业务编排服务,协调领域对象与基础设施 |
-| **domain** | 核心领域模型、枚举、Gateway 接口定义 |
+| 层                 | 职责                                                      |
+| ------------------ | --------------------------------------------------------- |
+| **adapter**        | REST API 控制器,对外暴露 HTTP 接口                       |
+| **application**    | 业务编排服务,协调领域对象与基础设施                      |
+| **domain**         | 核心领域模型、枚举、Gateway 接口定义                      |
 | **infrastructure** | 外部集成实现:FFmpeg、Ably、ONVIF、ISAPI、RCS HTTP 客户端 |
 
 ---
@@ -117,6 +117,7 @@ const (
 ```
 
 辅助方法:
+
 - `IsActive()` — STARTING / STREAMING / RECONNECTING 返回 true
 - `IsTerminal()` — STOPPED / ERROR 返回 true
 
@@ -229,12 +230,12 @@ LSS 通过 Ably WebSocket 接收 RCS 下发的指令,并通过同一通道返
 
 #### Ably 通道列表
 
-| 通道名 | 方向 | 用途 |
-|--------|------|------|
-| `lss:registry` | LSS → RCS | Presence 注册/在线状态 |
-| `lss:{nodeId}:commands` | RCS → LSS | 接收指令 |
-| `lss:{nodeId}:status` | LSS → RCS | 发布状态和指令执行结果 |
-| `task:{taskId}:events` | LSS → RCS | 任务级别事件 |
+| 通道名                  | 方向      | 用途                   |
+| ----------------------- | --------- | ---------------------- |
+| `lss:registry`          | LSS → RCS | Presence 注册/在线状态 |
+| `lss:{nodeId}:commands` | RCS → LSS | 接收指令               |
+| `lss:{nodeId}:status`   | LSS → RCS | 发布状态和指令执行结果 |
+| `task:{taskId}:events`  | LSS → RCS | 任务级别事件           |
 
 #### 指令消息格式
 
@@ -271,6 +272,7 @@ LSS 通过 Ably WebSocket 接收 RCS 下发的指令,并通过同一通道返
 ```
 
 其他推流指令:
+
 - `STOP_STREAM` — payload: `{ "taskId": "task_001", "force": false }`
 - `QUERY_STATUS` — payload: `{ "taskId": "task_001" }`
 
@@ -288,6 +290,7 @@ LSS 通过 Ably WebSocket 接收 RCS 下发的指令,并通过同一通道返
 ```
 
 PTZ 指令列表:
+
 - `PTZ_CONTROL` — payload: `{ cameraId, action, speed }`
 - `PTZ_STOP` — payload: `{ cameraId }`
 - `PTZ_PRESET_GOTO` — payload: `{ cameraId, presetId }`
@@ -310,6 +313,7 @@ PTZ 指令列表:
 ```
 
 摄像头指令列表:
+
 - `CAMERA_CHECK` — 连通性测试
 - `CAMERA_SNAPSHOT` — 抓取截图,返回 Base64 编码的 JPEG
 - `CAMERA_PRESET_LIST` — 获取预置位列表
@@ -358,6 +362,7 @@ PTZ 指令列表:
 ```
 
 巡航指令列表:
+
 - `PATROL_START` — 启动巡航
 - `PATROL_STOP` — 停止巡航
 - `PATROL_PAUSE` — 暂停巡航
@@ -411,15 +416,15 @@ LSS 启动后加入 `lss:registry` 通道的 Presence,数据包含节点基本
 
 基础路径:`http://{nodeIP}:10060/api`
 
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| POST | `/stream/start` | 启动推流任务 |
-| POST | `/stream/stop` | 停止推流任务 |
-| GET | `/stream/task/{taskId}` | 查询单个任务状态 |
-| GET | `/stream/tasks/active` | 查询所有活跃任务 |
-| GET | `/stream/tasks` | 查询所有任务 |
-| GET | `/stream/node` | 获取节点信息 |
-| GET | `/stream/health` | 健康检查 |
+| 方法 | 路径                    | 说明             |
+| ---- | ----------------------- | ---------------- |
+| POST | `/stream/start`         | 启动推流任务     |
+| POST | `/stream/stop`          | 停止推流任务     |
+| GET  | `/stream/task/{taskId}` | 查询单个任务状态 |
+| GET  | `/stream/tasks/active`  | 查询所有活跃任务 |
+| GET  | `/stream/tasks`         | 查询所有任务     |
+| GET  | `/stream/node`          | 获取节点信息     |
+| GET  | `/stream/health`        | 健康检查         |
 
 **POST /stream/start 请求体:**
 
@@ -459,11 +464,11 @@ LSS 启动后加入 `lss:registry` 通道的 Presence,数据包含节点基本
 
 #### 4.2.2 LSS 调用 RCS 的 HTTP 接口
 
-| 方法 | 路径 | 说明 |
-|------|------|------|
-| POST | `{RCS_BASE_URL}/lss/register` | 节点注册 |
-| POST | `{RCS_BASE_URL}/lss/heartbeat` | HTTP 心跳(5 秒间隔) |
-| POST | `{RCS_BASE_URL}/lss/task/callback` | 任务状态回调 |
+| 方法 | 路径                               | 说明                  |
+| ---- | ---------------------------------- | --------------------- |
+| POST | `{RCS_BASE_URL}/lss/register`      | 节点注册              |
+| POST | `{RCS_BASE_URL}/lss/heartbeat`     | HTTP 心跳(5 秒间隔) |
+| POST | `{RCS_BASE_URL}/lss/task/callback` | 任务状态回调          |
 
 **POST /lss/register 请求体:**
 
@@ -570,25 +575,25 @@ SOAP Header 示例:
 
 **设备服务** — `http://{ip}:{port}/onvif/device_service`
 
-| 操作 | 用途 | 返回值 |
-|------|------|--------|
+| 操作                   | 用途         | 返回值                                                         |
+| ---------------------- | ------------ | -------------------------------------------------------------- |
 | `GetDeviceInformation` | 获取设备信息 | manufacturer, model, firmwareVersion, serialNumber, hardwareId |
-| `GetCapabilities` | 获取设备能力 | media/PTZ/device 服务地址 |
+| `GetCapabilities`      | 获取设备能力 | media/PTZ/device 服务地址                                      |
 
 **媒体服务** — `http://{ip}:{port}/onvif/media_service`
 
-| 操作 | 用途 | 返回值 |
-|------|------|--------|
+| 操作          | 用途                  | 返回值                        |
+| ------------- | --------------------- | ----------------------------- |
 | `GetProfiles` | 获取媒体 Profile 列表 | Profile Token(PTZ 操作必需) |
 
 **PTZ 服务** — `http://{ip}:{port}/onvif/ptz_service`
 
-| 操作 | 参数 | 用途 |
-|------|------|------|
-| `ContinuousMove` | profileToken, panSpeed(-1.0~1.0), tiltSpeed(-1.0~1.0), zoomSpeed(-1.0~1.0) | 持续移动 |
-| `Stop` | profileToken | 停止移动 |
-| `GotoPreset` | profileToken, presetToken | 转到预置位 |
-| `SetPreset` | profileToken, presetName | 设置预置位 |
+| 操作             | 参数                                                                       | 用途       |
+| ---------------- | -------------------------------------------------------------------------- | ---------- |
+| `ContinuousMove` | profileToken, panSpeed(-1.0~1.0), tiltSpeed(-1.0~1.0), zoomSpeed(-1.0~1.0) | 持续移动   |
+| `Stop`           | profileToken                                                               | 停止移动   |
+| `GotoPreset`     | profileToken, presetToken                                                  | 转到预置位 |
+| `SetPreset`      | profileToken, presetName                                                   | 设置预置位 |
 
 **ContinuousMove SOAP Body 示例:**
 
@@ -618,18 +623,18 @@ ONVIF 每次 PTZ 操作都需要 Profile Token。首次调用时通过 `GetProfi
 
 #### ISAPI 端点列表
 
-| 方法 | 路径 | 用途 |
-|------|------|------|
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/continuous` | 持续云台移动 |
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/momentary` | 瞬时云台移动 |
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}/goto` | 跳转到预置位 |
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}` | 设置预置位 |
-| DELETE | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}` | 删除预置位 |
-| GET | `/ISAPI/PTZCtrl/channels/{ch}/presets` | 获取预置位列表 |
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/patrols/{id}/start` | 启动巡航 |
-| PUT | `/ISAPI/PTZCtrl/channels/{ch}/patrols/{id}/stop` | 停止巡航 |
-| GET | `/ISAPI/System/deviceInfo` | 获取设备信息 |
-| GET | `/ISAPI/Streaming/channels/{ch}/picture` | 抓取截图 (JPEG) |
+| 方法   | 路径                                              | 用途            |
+| ------ | ------------------------------------------------- | --------------- |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/continuous`         | 持续云台移动    |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/momentary`          | 瞬时云台移动    |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}/goto`  | 跳转到预置位    |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}`       | 设置预置位      |
+| DELETE | `/ISAPI/PTZCtrl/channels/{ch}/presets/{id}`       | 删除预置位      |
+| GET    | `/ISAPI/PTZCtrl/channels/{ch}/presets`            | 获取预置位列表  |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/patrols/{id}/start` | 启动巡航        |
+| PUT    | `/ISAPI/PTZCtrl/channels/{ch}/patrols/{id}/stop`  | 停止巡航        |
+| GET    | `/ISAPI/System/deviceInfo`                        | 获取设备信息    |
+| GET    | `/ISAPI/Streaming/channels/{ch}/picture`          | 抓取截图 (JPEG) |
 
 `{ch}` 默认为 `1`(通道号)。
 
@@ -757,22 +762,22 @@ const (
 
 #### 5.2.3 速度映射
 
-| 参数 | 海康 ISAPI | ONVIF |
-|------|-----------|-------|
+| 参数     | 海康 ISAPI         | ONVIF                |
+| -------- | ------------------ | -------------------- |
 | 方向速度 | -100 ~ 100(整数) | -1.0 ~ 1.0(浮点数) |
-| 转换公式 | 直接使用 | `speed / 100.0` |
+| 转换公式 | 直接使用           | `speed / 100.0`      |
 
 Action 到方向的映射:
 
-| Action | pan | tilt | zoom |
-|--------|-----|------|------|
-| PAN_LEFT | -speed | 0 | 0 |
-| PAN_RIGHT | +speed | 0 | 0 |
-| TILT_UP | 0 | +speed | 0 |
-| TILT_DOWN | 0 | -speed | 0 |
-| ZOOM_IN | 0 | 0 | +speed |
-| ZOOM_OUT | 0 | 0 | -speed |
-| STOP | 0 | 0 | 0 |
+| Action    | pan    | tilt   | zoom   |
+| --------- | ------ | ------ | ------ |
+| PAN_LEFT  | -speed | 0      | 0      |
+| PAN_RIGHT | +speed | 0      | 0      |
+| TILT_UP   | 0      | +speed | 0      |
+| TILT_DOWN | 0      | -speed | 0      |
+| ZOOM_IN   | 0      | 0      | +speed |
+| ZOOM_OUT  | 0      | 0      | -speed |
+| STOP      | 0      | 0      | 0      |
 
 ---
 
@@ -844,6 +849,7 @@ const (
 #### 5.4.2 设备探测 (Probe)
 
 探测流程:
+
 1. 尝试 ONVIF `GetDeviceInformation` + `GetCapabilities` + `GetProfiles`
 2. 如果 ONVIF 失败,尝试海康 ISAPI `GET /ISAPI/System/deviceInfo`
 3. 返回设备信息和能力集
@@ -902,12 +908,12 @@ type PTZCapabilities struct {
 
 处理 Ably `camera_command` 事件:
 
-| 指令 | 处理逻辑 |
-|------|----------|
-| `CAMERA_CHECK` | HTTP GET 设备信息接口,成功则在线 |
-| `CAMERA_SNAPSHOT` | GET `/ISAPI/Streaming/channels/1/picture`,如需要则缩放图片,Base64 编码后返回 |
-| `CAMERA_PRESET_LIST` | GET `/ISAPI/PTZCtrl/channels/1/presets`,解析 XML 返回 |
-| `CAMERA_DEVICE_INFO` | 调用探测服务获取完整设备信息 |
+| 指令                 | 处理逻辑                                                                       |
+| -------------------- | ------------------------------------------------------------------------------ |
+| `CAMERA_CHECK`       | HTTP GET 设备信息接口,成功则在线                                              |
+| `CAMERA_SNAPSHOT`    | GET `/ISAPI/Streaming/channels/1/picture`,如需要则缩放图片,Base64 编码后返回 |
+| `CAMERA_PRESET_LIST` | GET `/ISAPI/PTZCtrl/channels/1/presets`,解析 XML 返回                         |
+| `CAMERA_DEVICE_INFO` | 调用探测服务获取完整设备信息                                                   |
 
 ---
 
@@ -931,10 +937,10 @@ type PTZCapabilities struct {
 
 ### 6.2 心跳机制(双通道)
 
-| 通道 | 间隔 | 传输方式 | 内容 |
-|------|------|---------|------|
-| HTTP | 5 秒 | POST /lss/heartbeat | nodeId, activeTaskCount, cpuUsage, memoryUsage, cameras |
-| Ably | 10 秒 | Ably Message | 同上 + activeTasks 详情 |
+| 通道 | 间隔  | 传输方式            | 内容                                                    |
+| ---- | ----- | ------------------- | ------------------------------------------------------- |
+| HTTP | 5 秒  | POST /lss/heartbeat | nodeId, activeTaskCount, cpuUsage, memoryUsage, cameras |
+| Ably | 10 秒 | Ably Message        | 同上 + activeTasks 详情                                 |
 
 ### 6.3 关闭流程
 
@@ -1019,46 +1025,46 @@ const (
 
 ```yaml
 server:
-  port: 10060               # HTTP 服务端口
+  port: 10060 # HTTP 服务端口
 
 ably:
-  api_key: ""               # Ably API Key(必填)
-  client_id: ""             # 自动生成: lss-{machineId}
-  heartbeat_interval: 10s   # Ably 心跳间隔
+  api_key: '' # Ably API Key(必填)
+  client_id: '' # 自动生成: lss-{machineId}
+  heartbeat_interval: 10s # Ably 心跳间隔
 
 lss:
   node:
-    name: "LSS-Node-1"      # 节点名称
-    machine_id: ""           # 机器标识(必填)
-    max_tasks: 4             # 最大并发推流数
+    name: 'LSS-Node-1' # 节点名称
+    machine_id: '' # 机器标识(必填)
+    max_tasks: 4 # 最大并发推流数
 
   ffmpeg:
-    path: "/usr/local/ffmpeg-whip/bin/ffmpeg"  # FFmpeg 路径
-    stop_timeout: 10s        # 停止超时
+    path: '/usr/local/ffmpeg-whip/bin/ffmpeg' # FFmpeg 路径
+    stop_timeout: 10s # 停止超时
 
   rcs:
-    base_url: ""             # RCS 服务地址(必填)
-    connect_timeout: 10s     # HTTP 连接超时
-    read_timeout: 30s        # HTTP 读取超时
-    heartbeat_interval: 5s   # HTTP 心跳间隔
+    base_url: '' # RCS 服务地址(必填)
+    connect_timeout: 10s # HTTP 连接超时
+    read_timeout: 30s # HTTP 读取超时
+    heartbeat_interval: 5s # HTTP 心跳间隔
 
   camera:
-    scan_enabled: true       # 是否启用摄像头扫描
-    scan_subnet: "192.168.0.0/24"  # 扫描子网
-    scan_timeout: 30s        # 扫描超时
-    rescan_interval: 60s     # 重扫描间隔
+    scan_enabled: true # 是否启用摄像头扫描
+    scan_subnet: '192.168.0.0/24' # 扫描子网
+    scan_timeout: 30s # 扫描超时
+    rescan_interval: 60s # 重扫描间隔
 ```
 
 环境变量:
 
-| 变量 | 必填 | 说明 |
-|------|------|------|
-| `ABLY_API_KEY` | 是 | Ably API Key |
-| `LSS_MACHINE_ID` | 是 | 机器标识 |
-| `RCS_BASE_URL` | 是 | RCS 服务地址 |
-| `LSS_NODE_NAME` | 否 | 节点名称,默认 "LSS-Node-1" |
-| `LSS_MAX_TASKS` | 否 | 最大并发数,默认 4 |
-| `FFMPEG_PATH` | 否 | FFmpeg 路径 |
+| 变量             | 必填 | 说明                        |
+| ---------------- | ---- | --------------------------- |
+| `ABLY_API_KEY`   | 是   | Ably API Key                |
+| `LSS_MACHINE_ID` | 是   | 机器标识                    |
+| `RCS_BASE_URL`   | 是   | RCS 服务地址                |
+| `LSS_NODE_NAME`  | 否   | 节点名称,默认 "LSS-Node-1" |
+| `LSS_MAX_TASKS`  | 否   | 最大并发数,默认 4          |
+| `FFMPEG_PATH`    | 否   | FFmpeg 路径                 |
 
 ---
 
@@ -1074,6 +1080,7 @@ lss:
 ### 9.2 Ably SDK
 
 Go 实现需使用 [Ably Go SDK](https://github.com/ably/ably-go),功能包括:
+
 - Realtime 连接
 - Channel 订阅(subscribe message)
 - Presence enter/leave
@@ -1082,6 +1089,7 @@ Go 实现需使用 [Ably Go SDK](https://github.com/ably/ably-go),功能包括
 ### 9.3 ONVIF 实现
 
 不需要完整的 ONVIF SDK,自行构建 SOAP XML 请求即可:
+
 - 使用 `net/http` 发送 POST 请求
 - 手动拼装 SOAP Envelope(参见第 4.3 节)
 - 使用正则或 `encoding/xml` 解析 XML 响应
@@ -1101,6 +1109,7 @@ Go 实现需使用 [Ably Go SDK](https://github.com/ably/ably-go),功能包括
 ### 9.6 日志
 
 使用结构化日志(推荐 `slog` 或 `zerolog`),关键操作需记录:
+
 - 推流任务启动/停止/错误
 - PTZ 控制指令
 - Ably 连接状态变化