567 lines
9.7 KiB
Markdown
567 lines
9.7 KiB
Markdown
# PLC Control API
|
|
|
|
本文档基于当前后端代码整理,覆盖 HTTP API、SSE 日志流和 WebSocket 实时消息。
|
|
|
|
## 基本信息
|
|
|
|
- UI: `/ui`
|
|
- HTTP API 前缀: `/api`
|
|
- 公共 WebSocket: `/ws/public`
|
|
- 客户端专属 WebSocket: `/ws/client/{client_id}`
|
|
- 日志 SSE: `/api/logs/stream`
|
|
|
|
## 通用错误响应
|
|
|
|
失败时通常返回:
|
|
|
|
```json
|
|
{
|
|
"err_code": 400,
|
|
"err_msg": "Invalid JSON format",
|
|
"err_detail": null
|
|
}
|
|
```
|
|
|
|
常见状态码:
|
|
|
|
- `400 Bad Request`: 参数非法或业务前置条件不满足
|
|
- `403 Forbidden`: 控制条件不满足或无写入权限
|
|
- `404 Not Found`: 资源不存在
|
|
- `500 Internal Server Error`: 服务端内部错误
|
|
|
|
## Source
|
|
|
|
### GET `/api/source`
|
|
|
|
获取数据源列表及连接状态。
|
|
|
|
### POST `/api/source`
|
|
|
|
创建数据源。
|
|
|
|
请求示例:
|
|
|
|
```json
|
|
{
|
|
"name": "PLC-1",
|
|
"protocol": "opcua",
|
|
"endpoint": "opc.tcp://127.0.0.1:4840",
|
|
"enabled": true
|
|
}
|
|
```
|
|
|
|
### PUT `/api/source/{source_id}`
|
|
|
|
更新数据源,字段均可选。
|
|
|
|
### DELETE `/api/source/{source_id}`
|
|
|
|
删除数据源。成功返回 `204 No Content`。
|
|
|
|
### POST `/api/source/{source_id}/reconnect`
|
|
|
|
手动重连数据源。
|
|
|
|
### POST `/api/source/{source_id}/browse`
|
|
|
|
从 OPC UA 数据源浏览节点并写入本地 `node` 表。
|
|
|
|
### GET `/api/source/{source_id}/node-tree`
|
|
|
|
获取数据源节点树。
|
|
|
|
## Point
|
|
|
|
### GET `/api/point`
|
|
|
|
分页获取点位列表,同时返回实时监测值。
|
|
|
|
查询参数:
|
|
|
|
- `source_id`
|
|
- `equipment_id`
|
|
- `page`
|
|
- `page_size`
|
|
|
|
### GET `/api/point/{point_id}`
|
|
|
|
获取单个点位。
|
|
|
|
### GET `/api/point/{point_id}/history`
|
|
|
|
获取最近历史样本。历史数据保存在进程内环形缓冲区,服务重启后清空。
|
|
|
|
查询参数:
|
|
|
|
- `limit`: 默认 `120`,最大 `1000`
|
|
|
|
### PUT `/api/point/{point_id}`
|
|
|
|
更新点位元数据。
|
|
|
|
可更新字段:
|
|
|
|
```json
|
|
{
|
|
"name": "Temperature",
|
|
"description": "Room temperature",
|
|
"unit": "C",
|
|
"tag_id": "uuid",
|
|
"equipment_id": "uuid",
|
|
"signal_role": "run"
|
|
}
|
|
```
|
|
|
|
说明:
|
|
|
|
- 点位变更设备绑定或信号角色后,会唤醒相关控制单元任务,使控制引擎尽快使用最新映射。
|
|
|
|
### DELETE `/api/point/{point_id}`
|
|
|
|
删除单个点位。
|
|
|
|
说明:
|
|
|
|
- 删除后会同步通知相关控制单元刷新配置。
|
|
|
|
### POST `/api/point/batch`
|
|
|
|
根据节点批量创建点位。
|
|
|
|
### DELETE `/api/point/batch`
|
|
|
|
批量删除点位。
|
|
|
|
说明:
|
|
|
|
- 删除后会同步通知相关控制单元刷新配置。
|
|
|
|
### PUT `/api/point/batch/set-equipment`
|
|
|
|
批量设置点位设备绑定和信号角色。
|
|
|
|
```json
|
|
{
|
|
"point_ids": ["uuid1", "uuid2"],
|
|
"equipment_id": "uuid",
|
|
"signal_role": "run"
|
|
}
|
|
```
|
|
|
|
说明:
|
|
|
|
- 更新前后关联到的控制单元都会被唤醒,避免控制引擎继续使用旧映射。
|
|
|
|
### PUT `/api/point/batch/set-tags`
|
|
|
|
批量设置点位标签。
|
|
|
|
### POST `/api/point/value/batch`
|
|
|
|
批量写点。
|
|
|
|
请求头:
|
|
|
|
- `X-Write-Key: <key>`
|
|
|
|
请求示例:
|
|
|
|
```json
|
|
{
|
|
"items": [
|
|
{ "point_id": "uuid", "value": 12.3 }
|
|
]
|
|
}
|
|
```
|
|
|
|
## Equipment
|
|
|
|
### GET `/api/equipment`
|
|
|
|
分页获取设备列表,包含点位数量和已绑定信号角色点。
|
|
|
|
### GET `/api/equipment/{equipment_id}`
|
|
|
|
获取单个设备。
|
|
|
|
### GET `/api/equipment/{equipment_id}/points`
|
|
|
|
获取设备下所有点位。
|
|
|
|
### POST `/api/equipment`
|
|
|
|
创建设备。
|
|
|
|
说明:
|
|
|
|
- 如果设备绑定了控制单元,创建成功后会唤醒对应控制单元。
|
|
|
|
### PUT `/api/equipment/{equipment_id}`
|
|
|
|
更新设备。
|
|
|
|
说明:
|
|
|
|
- 如果设备更换了 `unit_id`、`kind` 或其他控制相关配置,旧单元和新单元都会被唤醒。
|
|
|
|
### PUT `/api/equipment/batch/set-unit`
|
|
|
|
批量调整设备所属控制单元。
|
|
|
|
说明:
|
|
|
|
- 批量更新前关联到的旧单元,以及更新后关联到的新单元,都会收到唤醒通知。
|
|
|
|
### DELETE `/api/equipment/{equipment_id}`
|
|
|
|
删除设备。成功返回 `204 No Content`。
|
|
|
|
说明:
|
|
|
|
- 删除后会唤醒原所属控制单元。
|
|
|
|
## Unit
|
|
|
|
### GET `/api/unit`
|
|
|
|
分页获取控制单元列表,返回单元基础信息、运行时快照和设备摘要。
|
|
|
|
### POST `/api/unit`
|
|
|
|
创建控制单元。
|
|
|
|
请求示例:
|
|
|
|
```json
|
|
{
|
|
"code": "U01",
|
|
"name": "1号机组",
|
|
"description": null,
|
|
"enabled": true,
|
|
"run_time_sec": 60,
|
|
"stop_time_sec": 30,
|
|
"acc_time_sec": 3600,
|
|
"bl_time_sec": 10,
|
|
"require_manual_ack_after_fault": true
|
|
}
|
|
```
|
|
|
|
约束:
|
|
|
|
- `run_time_sec > 0`
|
|
- `stop_time_sec > 0`
|
|
- `acc_time_sec > 0`
|
|
- `bl_time_sec > 0`
|
|
- `acc_time_sec > run_time_sec`
|
|
|
|
### PUT `/api/unit/{unit_id}`
|
|
|
|
更新控制单元,字段均可选。
|
|
|
|
约束:
|
|
|
|
- 如果更新后涉及时长字段,仍然必须满足上面的全部约束。
|
|
|
|
### DELETE `/api/unit/{unit_id}`
|
|
|
|
删除控制单元。成功返回 `204 No Content`。
|
|
|
|
### GET `/api/unit/{unit_id}`
|
|
|
|
获取单个控制单元及其设备摘要。
|
|
|
|
### GET `/api/unit/{unit_id}/detail`
|
|
|
|
获取控制单元完整详情,包括设备和点位列表。
|
|
|
|
### GET `/api/unit/{unit_id}/runtime`
|
|
|
|
获取控制单元当前运行时状态。
|
|
|
|
响应字段:
|
|
|
|
```json
|
|
{
|
|
"unit_id": "uuid",
|
|
"state": "running",
|
|
"auto_enabled": true,
|
|
"accumulated_run_sec": 3600000,
|
|
"display_acc_sec": 3600000,
|
|
"fault_locked": false,
|
|
"flt_active": false,
|
|
"comm_locked": false,
|
|
"manual_ack_required": false
|
|
}
|
|
```
|
|
|
|
`state` 枚举:
|
|
|
|
- `stopped`
|
|
- `running`
|
|
- `distributor_running`
|
|
- `fault_locked`
|
|
- `comm_locked`
|
|
|
|
说明:
|
|
|
|
- `accumulated_run_sec` 和 `display_acc_sec` 单位都是毫秒。
|
|
- 运行时状态保存在内存中,服务重启后重置。
|
|
|
|
## Event
|
|
|
|
### GET `/api/event`
|
|
|
|
分页获取系统事件。
|
|
|
|
查询参数:
|
|
|
|
- `unit_id`
|
|
- `event_type`
|
|
- `page`
|
|
- `page_size`
|
|
|
|
常见事件类型:
|
|
|
|
- `unit.auto_control_started`
|
|
- `unit.auto_control_stopped`
|
|
- `unit.fault_locked`
|
|
- `unit.fault_acked`
|
|
- `unit.comm_locked`
|
|
- `unit.comm_recovered`
|
|
- `equipment.start_command_sent`
|
|
- `equipment.stop_command_sent`
|
|
|
|
## Control
|
|
|
|
所有控制命令在执行前都会校验:
|
|
|
|
- 信号质量
|
|
- REM 状态
|
|
- FLT 状态
|
|
- 单元 `auto_enabled`
|
|
- 单元 `comm_locked`
|
|
- 单元 `fault_locked`
|
|
- 单元 `manual_ack_required`
|
|
|
|
### POST `/api/control/equipment/{equipment_id}/start`
|
|
|
|
发送设备启动脉冲命令。
|
|
|
|
### POST `/api/control/equipment/{equipment_id}/stop`
|
|
|
|
发送设备停止脉冲命令。
|
|
|
|
### POST `/api/control/unit/{unit_id}/start-auto`
|
|
|
|
启动单元自动控制。
|
|
|
|
前置条件:
|
|
|
|
- 单元已启用
|
|
- `fault_locked = false`
|
|
- `comm_locked = false`
|
|
- `manual_ack_required = false`
|
|
|
|
成功响应:
|
|
|
|
```json
|
|
{ "ok_msg": "Auto control started", "unit_id": "uuid" }
|
|
```
|
|
|
|
### POST `/api/control/unit/{unit_id}/stop-auto`
|
|
|
|
停止单元自动控制。
|
|
|
|
### POST `/api/control/unit/batch-start-auto`
|
|
|
|
批量启动所有已启用单元的自动控制。
|
|
|
|
会跳过以下单元:
|
|
|
|
- 已经 `auto_enabled = true`
|
|
- `fault_locked = true`
|
|
- `comm_locked = true`
|
|
- `manual_ack_required = true`
|
|
|
|
说明:
|
|
|
|
- 单个启动和批量启动现在使用相同的阻断规则。
|
|
|
|
### POST `/api/control/unit/batch-stop-auto`
|
|
|
|
批量停止自动控制。
|
|
|
|
### POST `/api/control/unit/{unit_id}/ack-fault`
|
|
|
|
人工确认故障。
|
|
|
|
前置条件:
|
|
|
|
- `fault_locked = true`
|
|
- `flt_active = false`
|
|
|
|
## Tag
|
|
|
|
### GET `/api/tag`
|
|
|
|
分页获取标签列表。
|
|
|
|
### POST `/api/tag`
|
|
|
|
创建标签。
|
|
|
|
### GET `/api/tag/{tag_id}`
|
|
|
|
获取标签下已绑定点位。
|
|
|
|
### PUT `/api/tag/{tag_id}`
|
|
|
|
更新标签。
|
|
|
|
### DELETE `/api/tag/{tag_id}`
|
|
|
|
删除标签。成功返回 `204 No Content`。
|
|
|
|
## Page
|
|
|
|
### GET `/api/page`
|
|
|
|
获取自定义页面列表。
|
|
|
|
### POST `/api/page`
|
|
|
|
创建页面。
|
|
|
|
### GET `/api/page/{page_id}`
|
|
|
|
获取单个页面。
|
|
|
|
### PUT `/api/page/{page_id}`
|
|
|
|
更新页面。
|
|
|
|
### DELETE `/api/page/{page_id}`
|
|
|
|
删除页面。成功返回 `204 No Content`。
|
|
|
|
## Log
|
|
|
|
### GET `/api/logs`
|
|
|
|
读取日志文件内容。默认读取最新的 `app.log*` 文件。
|
|
|
|
查询参数:
|
|
|
|
- `file`: 指定文件名,仅允许 `app.log*`
|
|
- `cursor`: 增量读取位置
|
|
- `tail_lines`: 默认 `200`,最大 `2000`
|
|
- `max_bytes`: 默认 `64KB`,最大 `512KB`
|
|
|
|
响应示例:
|
|
|
|
```json
|
|
{
|
|
"file": "app.log",
|
|
"cursor": 204800,
|
|
"lines": ["2026-03-25 10:00:00 INFO ..."],
|
|
"truncated": false,
|
|
"reset": false
|
|
}
|
|
```
|
|
|
|
字段说明:
|
|
|
|
- `truncated = true`: 当前还有未读完内容,可继续用新 `cursor` 拉取
|
|
- `reset = true`: 文件被截断或读取起点被重置
|
|
|
|
### GET `/api/logs/stream`
|
|
|
|
通过 SSE 推送日志增量。
|
|
|
|
查询参数:
|
|
|
|
- `file`
|
|
- `cursor`
|
|
- `max_bytes`
|
|
|
|
默认行为:
|
|
|
|
- 如果没有传 `file`,服务端会始终跟随最新的 `app.log*`
|
|
- 如果日志轮转到了新文件,流会自动切换到新文件,并推送一条 `reset = true` 的日志事件
|
|
|
|
事件示例:
|
|
|
|
```text
|
|
event: log
|
|
data: { "file": "app.log.1", "cursor": 1024, "lines": ["..."], "truncated": false, "reset": true }
|
|
|
|
event: error
|
|
data: log stream read failed
|
|
```
|
|
|
|
## WebSocket
|
|
|
|
### 服务端推送消息
|
|
|
|
#### `PointNewValue`
|
|
|
|
点位实时值更新。
|
|
|
|
#### `EventCreated`
|
|
|
|
系统事件创建。
|
|
|
|
#### `UnitRuntimeChanged`
|
|
|
|
控制单元运行时状态更新。
|
|
|
|
```json
|
|
{
|
|
"type": "UnitRuntimeChanged",
|
|
"data": {
|
|
"unit_id": "uuid",
|
|
"state": "running",
|
|
"auto_enabled": true,
|
|
"fault_locked": false,
|
|
"comm_locked": false,
|
|
"manual_ack_required": false,
|
|
"accumulated_run_sec": 3600000,
|
|
"display_acc_sec": 3600000
|
|
}
|
|
}
|
|
```
|
|
|
|
#### `PointSetValueBatchResult`
|
|
|
|
批量写点结果回调。
|
|
|
|
### 客户端消息
|
|
|
|
#### `auth_write`
|
|
|
|
```json
|
|
{
|
|
"type": "auth_write",
|
|
"data": { "key": "your-write-key" }
|
|
}
|
|
```
|
|
|
|
#### `point_set_value_batch`
|
|
|
|
```json
|
|
{
|
|
"type": "point_set_value_batch",
|
|
"data": {
|
|
"items": [
|
|
{ "point_id": "uuid", "value": 12.3 }
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
## 备注
|
|
|
|
- 控制引擎现在会在每轮单元循环中重新加载设备和角色映射,而不是只在任务启动时加载一次。
|
|
- 设备和点位的控制相关配置变更后,会主动唤醒对应单元任务,使新配置尽快生效。
|
|
- 日志流默认跟随最新日志文件,适配日志轮转场景。
|