plc_control/API.md

12 KiB
Raw Blame History

PLC Control 接口说明

本文档基于当前服务端路由与处理器代码整理,覆盖 HTTP API 和 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"
}

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

获取指定数据源的节点树(含 children 递归嵌套)。


Point

GET /api/point

分页获取点位列表,同时返回实时监测值。

查询参数:

  • source_id:可选,按数据源过滤
  • equipment_id:可选,按设备过滤
  • page:页码
  • page_size:每页条数(-1 表示全量)

响应示例:

{
  "data": [
    {
      "point": {
        "id": "uuid",
        "node_id": "uuid",
        "name": "Temperature",
        "equipment_id": "uuid",
        "signal_role": "run",
        "created_at": "2026-03-20 10:00:00.000",
        "updated_at": "2026-03-20 10:00:00.000"
      },
      "point_monitor": {
        "point_id": "uuid",
        "timestamp": "2026-03-20 10:05:00.000",
        "quality": "good",
        "value": 12.3,
        "value_type": "float",
        "value_text": "12.3"
      }
    }
  ],
  "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
  }
]

PUT /api/point/{point_id}

更新点位元数据,字段均可选:

{
  "name": "Temperature",
  "description": "Room temperature",
  "unit": "°C",
  "equipment_id": "uuid",
  "signal_role": "run"
}

DELETE /api/point/{point_id}

删除单个点位。

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"] }

PUT /api/point/batch/set-equipment

批量设置点位的设备绑定和信号角色。

{
  "point_ids": ["uuid1", "uuid2"],
  "equipment_id": "uuid",
  "signal_role": "run"
}

POST /api/point/value/batch

批量写点。

请求头:X-Write-Key: <key>

{
  "items": [
    { "point_id": "uuid", "value": 12.3 }
  ]
}

Equipment

GET /api/equipment

分页获取设备列表,包含每台设备绑定的点位数量。

查询参数:pagepage_size-1 全量)、keyword(可选,按 code/name 模糊搜索)

响应示例:

{
  "data": [
    {
      "id": "uuid",
      "unit_id": "uuid",
      "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

创建设备。

{
  "unit_id": "uuid",
  "code": "E01",
  "name": "投煤器1",
  "kind": "coal_feeder",
  "description": null
}

响应:201 Created

{ "id": "uuid", "ok_msg": "Equipment created successfully" }

PUT /api/equipment/{equipment_id}

更新设备,字段均可选:

{
  "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

批量将设备绑定到控制单元。

{
  "equipment_ids": ["uuid1", "uuid2"],
  "unit_id": "uuid"
}

Unit控制单元

GET /api/unit

分页获取控制单元列表。

查询参数:pagepage_sizekeyword(可选)

响应字段包含:idcodenameenabledrun_time_secstop_time_secacc_time_secbl_time_secrequire_manual_ack_after_fault

POST /api/unit

创建控制单元。

{
  "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

{ "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

获取控制单元的当前运行时状态(内存中,不持久化)。

响应示例:

{
  "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

获取控制单元及其下所有设备和点位的完整嵌套结构。

响应示例:

{
  "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"
        }
      ]
    }
  ]
}

Event系统事件

GET /api/event

分页获取系统控制事件记录。

查询参数:

  • unit_id:可选,按控制单元过滤
  • event_type:可选,按事件类型过滤
  • pagepage_size

响应示例:

{
  "data": [
    {
      "id": "uuid",
      "event_type": "equipment.start_command_sent",
      "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
}

Control控制命令

所有控制命令在执行前会校验信号质量、REM 状态、FLT 状态、单元通讯锁、单元故障锁。

POST /api/control/equipment/{equipment_id}/start

向设备发送启动脉冲命令(写 HIGH → 延迟 300ms → 写 LOW

响应示例:

{
  "ok_msg": "Equipment start command sent",
  "equipment_id": "uuid",
  "unit_id": "uuid",
  "command_role": "start_cmd",
  "command_point_id": "uuid",
  "pulse_ms": 300
}

失败(设备未处于可启动状态)返回 403 Forbidden

POST /api/control/equipment/{equipment_id}/stop

向设备发送停止脉冲命令。响应结构同上。

POST /api/control/unit/{unit_id}/start-auto

启动指定控制单元的自动控制循环。单元须已启用(enabled = true)。

{ "ok_msg": "Auto control started", "unit_id": "uuid" }

POST /api/control/unit/{unit_id}/stop-auto

停止自动控制循环。设备当前状态保持不变,不会自动停机。

{ "ok_msg": "Auto control stopped", "unit_id": "uuid" }

POST /api/control/unit/{unit_id}/ack-fault

人工确认故障,解除故障锁定。要求:fault_locked = trueflt_active = false(故障信号已消失)。

{ "ok_msg": "Fault acknowledged", "unit_id": "uuid" }

WebSocket

连接地址

  • 公共广播:/ws/public
  • 客户端专属:/ws/client/{client_id}

服务端主动推送消息

PointNewValue

点位实时值更新:

{
  "type": "PointNewValue",
  "data": {
    "point_id": "uuid",
    "timestamp": "2026-03-20 10:05:00.000",
    "quality": "good",
    "value": 12.3,
    "value_type": "float",
    "value_text": "12.3"
  }
}

EventCreated

系统事件创建(控制操作、故障、状态变更等):

{
  "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 后广播):

{
  "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

批量写点结果回调:

{
  "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 }
    ]
  }
}

备注

  • 运行时状态(/runtime)存储在内存中,服务重启后重置。
  • 历史曲线数据(/history)同样是内存环形缓冲,重启后清空。
  • 控制单元时间配置字段(run_time_sec 等)单位为秒,运行时 elapsed 字段单位为毫秒。
  • 自动控制启动后,状态机以 500ms 为周期运行,实时状态通过 WebSocket UnitRuntimeChanged 推送。