docs(api): rewrite API.md to cover all current endpoints
Add Equipment, Unit, Event, Control sections. Update Point (equipment_id filter, signal_role in PUT). Add EventCreated and UnitRuntimeChanged to WebSocket. Remove stale SSE log stream section. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2732238be7
commit
c2ed1e70fb
569
API.md
569
API.md
|
|
@ -1,6 +1,6 @@
|
||||||
# PLC Control 接口说明
|
# PLC Control 接口说明
|
||||||
|
|
||||||
本文档基于当前服务端路由与处理器代码整理,覆盖 HTTP API、SSE 日志流和 WebSocket 实时消息。
|
本文档基于当前服务端路由与处理器代码整理,覆盖 HTTP API 和 WebSocket 实时消息。
|
||||||
|
|
||||||
## 基本信息
|
## 基本信息
|
||||||
|
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
常见状态码:
|
常见状态码:
|
||||||
|
|
||||||
- `400 Bad Request`:参数错误
|
- `400 Bad Request`:参数错误
|
||||||
- `403 Forbidden`:写入权限不足
|
- `403 Forbidden`:写入权限不足或控制条件不满足
|
||||||
- `404 Not Found`:资源不存在
|
- `404 Not Found`:资源不存在
|
||||||
- `500 Internal Server Error`:服务端内部错误
|
- `500 Internal Server Error`:服务端内部错误
|
||||||
|
|
||||||
|
|
@ -74,16 +74,12 @@
|
||||||
响应:
|
响应:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "id": "uuid" }
|
||||||
"id": "uuid"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### PUT `/api/source/{source_id}`
|
### PUT `/api/source/{source_id}`
|
||||||
|
|
||||||
更新数据源。
|
更新数据源。请求体字段均可选:
|
||||||
|
|
||||||
请求体字段均可选:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -97,63 +93,29 @@
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
响应:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ok_msg": "Source updated successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### DELETE `/api/source/{source_id}`
|
### DELETE `/api/source/{source_id}`
|
||||||
|
|
||||||
删除数据源。
|
删除数据源。成功响应:`204 No Content`
|
||||||
|
|
||||||
成功响应:`204 No Content`
|
|
||||||
|
|
||||||
### POST `/api/source/{source_id}/reconnect`
|
### POST `/api/source/{source_id}/reconnect`
|
||||||
|
|
||||||
手动重连指定数据源。
|
手动重连指定数据源。
|
||||||
|
|
||||||
响应:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "ok_msg": "Source reconnected successfully" }
|
||||||
"ok_msg": "Source reconnected successfully"
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### POST `/api/source/{source_id}/browse`
|
### POST `/api/source/{source_id}/browse`
|
||||||
|
|
||||||
从 OPC UA 源浏览节点并写入本地 `node` 表。
|
从 OPC UA 源浏览节点并写入本地 `node` 表。
|
||||||
|
|
||||||
响应:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "ok_msg": "Browse completed", "total_nodes": 123 }
|
||||||
"ok_msg": "Browse completed",
|
|
||||||
"total_nodes": 123
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### GET `/api/source/{source_id}/node-tree`
|
### GET `/api/source/{source_id}/node-tree`
|
||||||
|
|
||||||
获取指定数据源的节点树。
|
获取指定数据源的节点树(含 `children` 递归嵌套)。
|
||||||
|
|
||||||
响应字段:
|
|
||||||
|
|
||||||
- `id`
|
|
||||||
- `source_id`
|
|
||||||
- `external_id`
|
|
||||||
- `namespace_uri`
|
|
||||||
- `namespace_index`
|
|
||||||
- `identifier_type`
|
|
||||||
- `identifier`
|
|
||||||
- `browse_name`
|
|
||||||
- `display_name`
|
|
||||||
- `node_class`
|
|
||||||
- `parent_id`
|
|
||||||
- `children`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
@ -161,13 +123,14 @@
|
||||||
|
|
||||||
### GET `/api/point`
|
### GET `/api/point`
|
||||||
|
|
||||||
分页获取点位列表。
|
分页获取点位列表,同时返回实时监测值。
|
||||||
|
|
||||||
查询参数:
|
查询参数:
|
||||||
|
|
||||||
- `source_id`:可选,按数据源过滤
|
- `source_id`:可选,按数据源过滤
|
||||||
|
- `equipment_id`:可选,按设备过滤
|
||||||
- `page`:页码
|
- `page`:页码
|
||||||
- `page_size`:每页条数
|
- `page_size`:每页条数(`-1` 表示全量)
|
||||||
|
|
||||||
响应示例:
|
响应示例:
|
||||||
|
|
||||||
|
|
@ -175,28 +138,22 @@
|
||||||
{
|
{
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
|
"point": {
|
||||||
"id": "uuid",
|
"id": "uuid",
|
||||||
"node_id": "uuid",
|
"node_id": "uuid",
|
||||||
"name": "Temperature",
|
"name": "Temperature",
|
||||||
"description": null,
|
"equipment_id": "uuid",
|
||||||
"unit": null,
|
"signal_role": "run",
|
||||||
"tag_id": null,
|
|
||||||
"created_at": "2026-03-20 10:00:00.000",
|
"created_at": "2026-03-20 10:00:00.000",
|
||||||
"updated_at": "2026-03-20 10:00:00.000",
|
"updated_at": "2026-03-20 10:00:00.000"
|
||||||
|
},
|
||||||
"point_monitor": {
|
"point_monitor": {
|
||||||
"protocol": "opcua",
|
|
||||||
"source_id": "uuid",
|
|
||||||
"point_id": "uuid",
|
"point_id": "uuid",
|
||||||
"client_handle": 1001,
|
|
||||||
"scan_mode": "subscribe",
|
|
||||||
"timestamp": "2026-03-20 10:05:00.000",
|
"timestamp": "2026-03-20 10:05:00.000",
|
||||||
"quality": "good",
|
"quality": "good",
|
||||||
"value": 12.3,
|
"value": 12.3,
|
||||||
"value_type": "float",
|
"value_type": "float",
|
||||||
"value_text": "12.3",
|
"value_text": "12.3"
|
||||||
"old_value": 12.1,
|
|
||||||
"old_timestamp": "2026-03-20 10:04:59.000",
|
|
||||||
"value_changed": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
@ -212,13 +169,9 @@
|
||||||
|
|
||||||
### GET `/api/point/{point_id}/history`
|
### GET `/api/point/{point_id}/history`
|
||||||
|
|
||||||
获取点位最近历史样本。数据来自进程内存中的环形缓冲,不是持久化历史库。
|
获取点位最近历史样本(进程内存环形缓冲,重启后清空)。
|
||||||
|
|
||||||
查询参数:
|
查询参数:`limit`(可选,默认 `120`,最大 `1000`)
|
||||||
|
|
||||||
- `limit`:可选,默认 `120`,最大 `1000`
|
|
||||||
|
|
||||||
响应示例:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
[
|
[
|
||||||
|
|
@ -232,23 +185,17 @@
|
||||||
]
|
]
|
||||||
```
|
```
|
||||||
|
|
||||||
说明:
|
|
||||||
|
|
||||||
- `value_number` 便于前端直接绘图
|
|
||||||
- 非数值型点位时,`value_number` 可能为 `null`
|
|
||||||
|
|
||||||
### PUT `/api/point/{point_id}`
|
### PUT `/api/point/{point_id}`
|
||||||
|
|
||||||
更新点位元数据。
|
更新点位元数据,字段均可选:
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "Temperature",
|
"name": "Temperature",
|
||||||
"description": "Room temperature",
|
"description": "Room temperature",
|
||||||
"unit": "°C",
|
"unit": "°C",
|
||||||
"tag_id": "uuid"
|
"equipment_id": "uuid",
|
||||||
|
"signal_role": "run"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -256,24 +203,12 @@
|
||||||
|
|
||||||
删除单个点位。
|
删除单个点位。
|
||||||
|
|
||||||
响应:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"ok_msg": "Point deleted successfully"
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### POST `/api/point/batch`
|
### POST `/api/point/batch`
|
||||||
|
|
||||||
根据节点批量创建点位。
|
根据节点批量创建点位。
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "node_ids": ["uuid1", "uuid2"] }
|
||||||
"node_ids": ["uuid1", "uuid2"]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
响应:
|
响应:
|
||||||
|
|
@ -291,32 +226,19 @@
|
||||||
|
|
||||||
批量删除点位。
|
批量删除点位。
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "point_ids": ["uuid1", "uuid2"] }
|
||||||
"point_ids": ["uuid1", "uuid2"]
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
响应:
|
### PUT `/api/point/batch/set-equipment`
|
||||||
|
|
||||||
```json
|
批量设置点位的设备绑定和信号角色。
|
||||||
{
|
|
||||||
"deleted_count": 2
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### PUT `/api/point/batch/set-tags`
|
|
||||||
|
|
||||||
批量设置点位标签。
|
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"point_ids": ["uuid1", "uuid2"],
|
"point_ids": ["uuid1", "uuid2"],
|
||||||
"tag_id": "uuid"
|
"equipment_id": "uuid",
|
||||||
|
"signal_role": "run"
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -324,36 +246,203 @@
|
||||||
|
|
||||||
批量写点。
|
批量写点。
|
||||||
|
|
||||||
请求头:
|
请求头:`X-Write-Key: <key>`
|
||||||
|
|
||||||
- `X-Write-Key: <key>`
|
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{ "point_id": "uuid", "value": 12.3 }
|
||||||
"point_id": "uuid",
|
|
||||||
"value": 12.3
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
响应:
|
---
|
||||||
|
|
||||||
|
## Equipment
|
||||||
|
|
||||||
|
### GET `/api/equipment`
|
||||||
|
|
||||||
|
分页获取设备列表,包含每台设备绑定的点位数量。
|
||||||
|
|
||||||
|
查询参数:`page`、`page_size`(`-1` 全量)、`keyword`(可选,按 code/name 模糊搜索)
|
||||||
|
|
||||||
|
响应示例:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"success": true,
|
"data": [
|
||||||
"err_msg": null,
|
|
||||||
"success_count": 1,
|
|
||||||
"failed_count": 0,
|
|
||||||
"results": [
|
|
||||||
{
|
{
|
||||||
"point_id": "uuid",
|
"id": "uuid",
|
||||||
"success": true,
|
"unit_id": "uuid",
|
||||||
"err_msg": null
|
"code": "E01",
|
||||||
|
"name": "投煤器1",
|
||||||
|
"kind": "coal_feeder",
|
||||||
|
"description": null,
|
||||||
|
"created_at": "2026-03-20 10:00:00.000",
|
||||||
|
"updated_at": "2026-03-20 10:00:00.000",
|
||||||
|
"point_count": 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 1,
|
||||||
|
"page": 1,
|
||||||
|
"page_size": 20
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### POST `/api/equipment`
|
||||||
|
|
||||||
|
创建设备。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"unit_id": "uuid",
|
||||||
|
"code": "E01",
|
||||||
|
"name": "投煤器1",
|
||||||
|
"kind": "coal_feeder",
|
||||||
|
"description": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应:`201 Created`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "id": "uuid", "ok_msg": "Equipment created successfully" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### PUT `/api/equipment/{equipment_id}`
|
||||||
|
|
||||||
|
更新设备,字段均可选:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"unit_id": "uuid",
|
||||||
|
"code": "E01",
|
||||||
|
"name": "投煤器1",
|
||||||
|
"kind": "coal_feeder",
|
||||||
|
"description": null
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### DELETE `/api/equipment/{equipment_id}`
|
||||||
|
|
||||||
|
删除设备。成功响应:`204 No Content`
|
||||||
|
|
||||||
|
### GET `/api/equipment/{equipment_id}/points`
|
||||||
|
|
||||||
|
获取指定设备下所有绑定点位。
|
||||||
|
|
||||||
|
### PUT `/api/equipment/batch/set-unit`
|
||||||
|
|
||||||
|
批量将设备绑定到控制单元。
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"equipment_ids": ["uuid1", "uuid2"],
|
||||||
|
"unit_id": "uuid"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Unit(控制单元)
|
||||||
|
|
||||||
|
### GET `/api/unit`
|
||||||
|
|
||||||
|
分页获取控制单元列表。
|
||||||
|
|
||||||
|
查询参数:`page`、`page_size`、`keyword`(可选)
|
||||||
|
|
||||||
|
响应字段包含:`id`、`code`、`name`、`enabled`、`run_time_sec`、`stop_time_sec`、`acc_time_sec`、`bl_time_sec`、`require_manual_ack_after_fault`
|
||||||
|
|
||||||
|
### 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
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
响应:`201 Created`
|
||||||
|
|
||||||
|
```json
|
||||||
|
{ "id": "uuid", "ok_msg": "Unit created successfully" }
|
||||||
|
```
|
||||||
|
|
||||||
|
### GET `/api/unit/{unit_id}`
|
||||||
|
|
||||||
|
获取单个控制单元。
|
||||||
|
|
||||||
|
### PUT `/api/unit/{unit_id}`
|
||||||
|
|
||||||
|
更新控制单元,字段均可选。
|
||||||
|
|
||||||
|
### DELETE `/api/unit/{unit_id}`
|
||||||
|
|
||||||
|
删除控制单元。成功响应:`204 No Content`
|
||||||
|
|
||||||
|
### GET `/api/unit/{unit_id}/runtime`
|
||||||
|
|
||||||
|
获取控制单元的当前运行时状态(内存中,不持久化)。
|
||||||
|
|
||||||
|
响应示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"unit_id": "uuid",
|
||||||
|
"state": "running",
|
||||||
|
"auto_enabled": true,
|
||||||
|
"accumulated_run_sec": 3600000,
|
||||||
|
"current_run_elapsed_sec": 60000,
|
||||||
|
"current_stop_elapsed_sec": 0,
|
||||||
|
"distributor_run_elapsed_sec": 0,
|
||||||
|
"fault_locked": false,
|
||||||
|
"flt_active": false,
|
||||||
|
"comm_locked": false,
|
||||||
|
"manual_ack_required": false,
|
||||||
|
"last_tick_at": "2026-03-25 10:00:00.000"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`state` 枚举值:`stopped` / `running` / `distributor_running` / `fault_locked` / `comm_locked`
|
||||||
|
|
||||||
|
注意:时间字段单位为毫秒(ms)。
|
||||||
|
|
||||||
|
### GET `/api/unit/{unit_id}/detail`
|
||||||
|
|
||||||
|
获取控制单元及其下所有设备和点位的完整嵌套结构。
|
||||||
|
|
||||||
|
响应示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"code": "U01",
|
||||||
|
"name": "1号机组",
|
||||||
|
"enabled": true,
|
||||||
|
"equipments": [
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"code": "E01",
|
||||||
|
"name": "投煤器1",
|
||||||
|
"kind": "coal_feeder",
|
||||||
|
"points": [
|
||||||
|
{
|
||||||
|
"id": "uuid",
|
||||||
|
"name": "启动命令",
|
||||||
|
"signal_role": "start_cmd",
|
||||||
|
"equipment_id": "uuid"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
@ -361,183 +450,163 @@
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Tag
|
## Event(系统事件)
|
||||||
|
|
||||||
### GET `/api/tag`
|
### GET `/api/event`
|
||||||
|
|
||||||
分页获取标签列表。
|
分页获取系统控制事件记录。
|
||||||
|
|
||||||
查询参数:
|
查询参数:
|
||||||
|
|
||||||
- `page`
|
- `unit_id`:可选,按控制单元过滤
|
||||||
- `page_size`
|
- `event_type`:可选,按事件类型过滤
|
||||||
|
- `page`、`page_size`
|
||||||
|
|
||||||
### GET `/api/tag/{tag_id}`
|
响应示例:
|
||||||
|
|
||||||
当前实现返回该标签下的点位列表。
|
|
||||||
|
|
||||||
### POST `/api/tag`
|
|
||||||
|
|
||||||
创建标签。
|
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "Area-A",
|
"data": [
|
||||||
"description": "Area A points",
|
|
||||||
"point_ids": ["uuid1", "uuid2"]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### PUT `/api/tag/{tag_id}`
|
|
||||||
|
|
||||||
更新标签。
|
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
{
|
||||||
"name": "Area-A",
|
"id": "uuid",
|
||||||
"description": "Updated",
|
"event_type": "equipment.start_command_sent",
|
||||||
"point_ids": ["uuid1", "uuid2"]
|
"level": "info",
|
||||||
|
"unit_id": "uuid",
|
||||||
|
"equipment_id": "uuid",
|
||||||
|
"message": "Start command sent to equipment ...",
|
||||||
|
"payload": {},
|
||||||
|
"created_at": "2026-03-25 10:00:00.000"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"total": 1,
|
||||||
|
"page": 1,
|
||||||
|
"page_size": 20
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### DELETE `/api/tag/{tag_id}`
|
|
||||||
|
|
||||||
删除标签。
|
|
||||||
|
|
||||||
成功响应:`204 No Content`
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Page
|
## Control(控制命令)
|
||||||
|
|
||||||
`page` 用于保存页面布局或组件映射数据。
|
所有控制命令在执行前会校验:信号质量、REM 状态、FLT 状态、单元通讯锁、单元故障锁。
|
||||||
|
|
||||||
### GET `/api/page`
|
### POST `/api/control/equipment/{equipment_id}/start`
|
||||||
|
|
||||||
查询页面列表。
|
向设备发送启动脉冲命令(写 HIGH → 延迟 300ms → 写 LOW)。
|
||||||
|
|
||||||
查询参数:
|
响应示例:
|
||||||
|
|
||||||
- `name`:可选,按名称模糊搜索
|
|
||||||
|
|
||||||
### GET `/api/page/{page_id}`
|
|
||||||
|
|
||||||
获取单个页面。
|
|
||||||
|
|
||||||
### POST `/api/page`
|
|
||||||
|
|
||||||
创建页面。
|
|
||||||
|
|
||||||
请求体:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"name": "Dashboard",
|
"ok_msg": "Equipment start command sent",
|
||||||
"data": {
|
"equipment_id": "uuid",
|
||||||
"widgetA": "uuid1",
|
"unit_id": "uuid",
|
||||||
"widgetB": "uuid2"
|
"command_role": "start_cmd",
|
||||||
}
|
"command_point_id": "uuid",
|
||||||
|
"pulse_ms": 300
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### PUT `/api/page/{page_id}`
|
失败(设备未处于可启动状态)返回 `403 Forbidden`。
|
||||||
|
|
||||||
更新页面。
|
### POST `/api/control/equipment/{equipment_id}/stop`
|
||||||
|
|
||||||
请求体字段均可选:
|
向设备发送停止脉冲命令。响应结构同上。
|
||||||
|
|
||||||
|
### POST `/api/control/unit/{unit_id}/start-auto`
|
||||||
|
|
||||||
|
启动指定控制单元的自动控制循环。单元须已启用(`enabled = true`)。
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "ok_msg": "Auto control started", "unit_id": "uuid" }
|
||||||
"name": "Dashboard",
|
|
||||||
"data": {
|
|
||||||
"widgetA": "uuid1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### DELETE `/api/page/{page_id}`
|
### POST `/api/control/unit/{unit_id}/stop-auto`
|
||||||
|
|
||||||
删除页面。
|
停止自动控制循环。设备当前状态保持不变,不会自动停机。
|
||||||
|
|
||||||
成功响应:`204 No Content`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Log
|
|
||||||
|
|
||||||
### GET `/api/logs`
|
|
||||||
|
|
||||||
读取日志文件内容。
|
|
||||||
|
|
||||||
查询参数:
|
|
||||||
|
|
||||||
- `file`:可选,指定日志文件名,仅允许 `app.log*`
|
|
||||||
- `cursor`:可选,从指定游标后读取
|
|
||||||
- `tail_lines`:可选,默认 `200`
|
|
||||||
- `max_bytes`:可选
|
|
||||||
|
|
||||||
响应:
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{ "ok_msg": "Auto control stopped", "unit_id": "uuid" }
|
||||||
"file": "app.log",
|
|
||||||
"cursor": 1024,
|
|
||||||
"lines": ["..."],
|
|
||||||
"truncated": false,
|
|
||||||
"reset": false
|
|
||||||
}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### GET `/api/logs/stream`
|
### POST `/api/control/unit/{unit_id}/ack-fault`
|
||||||
|
|
||||||
SSE 实时日志流。
|
人工确认故障,解除故障锁定。要求:`fault_locked = true` 且 `flt_active = false`(故障信号已消失)。
|
||||||
|
|
||||||
事件类型:
|
```json
|
||||||
|
{ "ok_msg": "Fault acknowledged", "unit_id": "uuid" }
|
||||||
- `log`
|
```
|
||||||
- `error`
|
|
||||||
|
|
||||||
客户端可使用 `EventSource` 订阅。
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## WebSocket
|
## WebSocket
|
||||||
|
|
||||||
## 连接地址
|
### 连接地址
|
||||||
|
|
||||||
- 公共广播:`/ws/public`
|
- 公共广播:`/ws/public`
|
||||||
- 客户端专属:`/ws/client/{client_id}`
|
- 客户端专属:`/ws/client/{client_id}`
|
||||||
|
|
||||||
## 服务端主动消息
|
### 服务端主动推送消息
|
||||||
|
|
||||||
### `PointNewValue`
|
#### `PointNewValue`
|
||||||
|
|
||||||
|
点位实时值更新:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "PointNewValue",
|
"type": "PointNewValue",
|
||||||
"data": {
|
"data": {
|
||||||
"protocol": "opcua",
|
|
||||||
"source_id": "uuid",
|
|
||||||
"point_id": "uuid",
|
"point_id": "uuid",
|
||||||
"client_handle": 1001,
|
|
||||||
"scan_mode": "subscribe",
|
|
||||||
"timestamp": "2026-03-20 10:05:00.000",
|
"timestamp": "2026-03-20 10:05:00.000",
|
||||||
"quality": "good",
|
"quality": "good",
|
||||||
"value": 12.3,
|
"value": 12.3,
|
||||||
"value_type": "float",
|
"value_type": "float",
|
||||||
"value_text": "12.3",
|
"value_text": "12.3"
|
||||||
"old_value": 12.1,
|
|
||||||
"old_timestamp": "2026-03-20 10:04:59.000",
|
|
||||||
"value_changed": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### `PointSetValueBatchResult`
|
#### `EventCreated`
|
||||||
|
|
||||||
|
系统事件创建(控制操作、故障、状态变更等):
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "EventCreated",
|
||||||
|
"data": {
|
||||||
|
"id": "uuid",
|
||||||
|
"event_type": "equipment.start_command_sent",
|
||||||
|
"level": "info",
|
||||||
|
"unit_id": "uuid",
|
||||||
|
"equipment_id": "uuid",
|
||||||
|
"message": "...",
|
||||||
|
"created_at": "2026-03-25 10:00:00.000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `UnitRuntimeChanged`
|
||||||
|
|
||||||
|
控制单元运行时状态变更(每 500ms tick 后广播):
|
||||||
|
|
||||||
|
```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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `PointSetValueBatchResult`
|
||||||
|
|
||||||
|
批量写点结果回调:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
@ -552,30 +621,25 @@ SSE 实时日志流。
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## 客户端发送消息
|
### 客户端发送消息
|
||||||
|
|
||||||
### 写权限认证
|
#### 写权限认证
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "auth_write",
|
"type": "auth_write",
|
||||||
"data": {
|
"data": { "key": "your-write-key" }
|
||||||
"key": "your-write-key"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### 批量写点
|
#### 批量写点
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"type": "point_set_value_batch",
|
"type": "point_set_value_batch",
|
||||||
"data": {
|
"data": {
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{ "point_id": "uuid", "value": 12.3 }
|
||||||
"point_id": "uuid",
|
|
||||||
"value": 12.3
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -585,6 +649,7 @@ SSE 实时日志流。
|
||||||
|
|
||||||
## 备注
|
## 备注
|
||||||
|
|
||||||
- 历史曲线接口当前使用内存缓存,服务重启后历史会清空。
|
- 运行时状态(`/runtime`)存储在内存中,服务重启后重置。
|
||||||
- 实时遥测与 WebSocket 推送是“最新值优先”的设计,在高压场景下允许丢弃部分中间消息。
|
- 历史曲线数据(`/history`)同样是内存环形缓冲,重启后清空。
|
||||||
- `/api/tag/{tag_id}` 当前返回的是标签下点位,而不是标签自身详情。
|
- 控制单元时间配置字段(`run_time_sec` 等)单位为秒,运行时 elapsed 字段单位为毫秒。
|
||||||
|
- 自动控制启动后,状态机以 500ms 为周期运行,实时状态通过 WebSocket `UnitRuntimeChanged` 推送。
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue