8.2 KiB
8.2 KiB
PLC Control 接口说明
本文档基于当前服务端路由与处理器代码整理,覆盖 HTTP API、SSE 日志流和 WebSocket 实时消息。
基本信息
- 服务端默认提供静态 UI:
/ui - HTTP API 前缀:
/api - 公共实时 WebSocket:
/ws/public - 客户端专属 WebSocket:
/ws/client/{client_id}
通用错误响应
接口失败时通常返回:
{
"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
获取所有已启用数据源及其连接状态。
响应示例:
[
{
"id": "uuid",
"name": "PLC-1",
"protocol": "opcua",
"endpoint": "opc.tcp://127.0.0.1:4840",
"security_policy": null,
"security_mode": null,
"enabled": true,
"created_at": "2026-03-20 10:00:00.000",
"updated_at": "2026-03-20 10:00:00.000",
"is_connected": true,
"last_error": null,
"last_time": "2026-03-20 10:05:00.000"
}
]
POST /api/source
创建数据源。
请求体:
{
"name": "PLC-1",
"endpoint": "opc.tcp://127.0.0.1:4840",
"enabled": true
}
响应:
{
"id": "uuid"
}
PUT /api/source/{source_id}
更新数据源。
请求体字段均可选:
{
"name": "PLC-1",
"endpoint": "opc.tcp://127.0.0.1:4840",
"enabled": true,
"security_policy": "None",
"security_mode": "None",
"username": "user",
"password": "pass"
}
响应:
{
"ok_msg": "Source updated successfully"
}
DELETE /api/source/{source_id}
删除数据源。
成功响应:204 No Content
POST /api/source/{source_id}/reconnect
手动重连指定数据源。
响应:
{
"ok_msg": "Source reconnected successfully"
}
POST /api/source/{source_id}/browse
从 OPC UA 源浏览节点并写入本地 node 表。
响应:
{
"ok_msg": "Browse completed",
"total_nodes": 123
}
GET /api/source/{source_id}/node-tree
获取指定数据源的节点树。
响应字段:
idsource_idexternal_idnamespace_urinamespace_indexidentifier_typeidentifierbrowse_namedisplay_namenode_classparent_idchildren
Point
GET /api/point
分页获取点位列表。
查询参数:
source_id:可选,按数据源过滤page:页码page_size:每页条数
响应示例:
{
"data": [
{
"id": "uuid",
"node_id": "uuid",
"name": "Temperature",
"description": null,
"unit": null,
"tag_id": null,
"created_at": "2026-03-20 10:00:00.000",
"updated_at": "2026-03-20 10:00:00.000",
"point_monitor": {
"protocol": "opcua",
"source_id": "uuid",
"point_id": "uuid",
"client_handle": 1001,
"scan_mode": "subscribe",
"timestamp": "2026-03-20 10:05:00.000",
"quality": "good",
"value": 12.3,
"value_type": "float",
"value_text": "12.3",
"old_value": 12.1,
"old_timestamp": "2026-03-20 10:04:59.000",
"value_changed": true
}
}
],
"total": 1,
"page": 1,
"page_size": 100
}
GET /api/point/{point_id}
获取单个点位。
GET /api/point/{point_id}/history
获取点位最近历史样本。数据来自进程内存中的环形缓冲,不是持久化历史库。
查询参数:
limit:可选,默认120,最大1000
响应示例:
[
{
"timestamp": "2026-03-20 10:05:00.000",
"quality": "good",
"value": 12.3,
"value_text": "12.3",
"value_number": 12.3
}
]
说明:
value_number便于前端直接绘图- 非数值型点位时,
value_number可能为null
PUT /api/point/{point_id}
更新点位元数据。
请求体:
{
"name": "Temperature",
"description": "Room temperature",
"unit": "°C",
"tag_id": "uuid"
}
DELETE /api/point/{point_id}
删除单个点位。
响应:
{
"ok_msg": "Point deleted successfully"
}
POST /api/point/batch
根据节点批量创建点位。
请求体:
{
"node_ids": ["uuid1", "uuid2"]
}
响应:
{
"success_count": 2,
"failed_count": 0,
"failed_node_ids": [],
"created_point_ids": ["uuid3", "uuid4"]
}
DELETE /api/point/batch
批量删除点位。
请求体:
{
"point_ids": ["uuid1", "uuid2"]
}
响应:
{
"deleted_count": 2
}
PUT /api/point/batch/set-tags
批量设置点位标签。
请求体:
{
"point_ids": ["uuid1", "uuid2"],
"tag_id": "uuid"
}
POST /api/point/value/batch
批量写点。
请求头:
X-Write-Key: <key>
请求体:
{
"items": [
{
"point_id": "uuid",
"value": 12.3
}
]
}
响应:
{
"success": true,
"err_msg": null,
"success_count": 1,
"failed_count": 0,
"results": [
{
"point_id": "uuid",
"success": true,
"err_msg": null
}
]
}
Tag
GET /api/tag
分页获取标签列表。
查询参数:
pagepage_size
GET /api/tag/{tag_id}
当前实现返回该标签下的点位列表。
POST /api/tag
创建标签。
请求体:
{
"name": "Area-A",
"description": "Area A points",
"point_ids": ["uuid1", "uuid2"]
}
PUT /api/tag/{tag_id}
更新标签。
请求体:
{
"name": "Area-A",
"description": "Updated",
"point_ids": ["uuid1", "uuid2"]
}
DELETE /api/tag/{tag_id}
删除标签。
成功响应:204 No Content
Page
page 用于保存页面布局或组件映射数据。
GET /api/page
查询页面列表。
查询参数:
name:可选,按名称模糊搜索
GET /api/page/{page_id}
获取单个页面。
POST /api/page
创建页面。
请求体:
{
"name": "Dashboard",
"data": {
"widgetA": "uuid1",
"widgetB": "uuid2"
}
}
PUT /api/page/{page_id}
更新页面。
请求体字段均可选:
{
"name": "Dashboard",
"data": {
"widgetA": "uuid1"
}
}
DELETE /api/page/{page_id}
删除页面。
成功响应:204 No Content
Log
GET /api/logs
读取日志文件内容。
查询参数:
file:可选,指定日志文件名,仅允许app.log*cursor:可选,从指定游标后读取tail_lines:可选,默认200max_bytes:可选
响应:
{
"file": "app.log",
"cursor": 1024,
"lines": ["..."],
"truncated": false,
"reset": false
}
GET /api/logs/stream
SSE 实时日志流。
事件类型:
logerror
客户端可使用 EventSource 订阅。
WebSocket
连接地址
- 公共广播:
/ws/public - 客户端专属:
/ws/client/{client_id}
服务端主动消息
PointNewValue
{
"type": "PointNewValue",
"data": {
"protocol": "opcua",
"source_id": "uuid",
"point_id": "uuid",
"client_handle": 1001,
"scan_mode": "subscribe",
"timestamp": "2026-03-20 10:05:00.000",
"quality": "good",
"value": 12.3,
"value_type": "float",
"value_text": "12.3",
"old_value": 12.1,
"old_timestamp": "2026-03-20 10:04:59.000",
"value_changed": true
}
}
PointSetValueBatchResult
{
"type": "PointSetValueBatchResult",
"data": {
"success": true,
"err_msg": null,
"success_count": 1,
"failed_count": 0,
"results": []
}
}
客户端发送消息
写权限认证
{
"type": "auth_write",
"data": {
"key": "your-write-key"
}
}
批量写点
{
"type": "point_set_value_batch",
"data": {
"items": [
{
"point_id": "uuid",
"value": 12.3
}
]
}
}
备注
- 历史曲线接口当前使用内存缓存,服务重启后历史会清空。
- 实时遥测与 WebSocket 推送是“最新值优先”的设计,在高压场景下允许丢弃部分中间消息。
/api/tag/{tag_id}当前返回的是标签下点位,而不是标签自身详情。