s7-http-api.md 8.1 KB

S7 HTTP 接口说明

目标

本服务通过 HTTP 接口连接 Siemens S7 TCP 设备,支持连接组合扫描、原始字节读取、点位读取并转换。

当前 S7 接口使用 python-snap7 实现。/s7/read 返回的 communication 是语义化通信记录,用于说明本次连接、读取和断开过程;它不是 Wireshark 中的 TPKT + COTP + S7Comm 原始网络帧。

接口列表

  • POST /api/dc-debugtool/s7/read:读取一段 S7 地址数据,只返回语义化 communication
  • POST /api/dc-debugtool/s7/read_points:按点位定义读取,并返回转换后的业务值。
  • POST /api/dc-debugtool/s7/connect_scan:传 ip,可选 device_type,扫描可用的 rockslottsap_conn_type 组合。

通用返回约定

业务接口统一返回 HTTP 200,是否成功由 JSON 中的 code 判断。

成功:

{
  "code": 0,
  "msg": "success",
  "data": {}
}

失败:

{
  "code": 1,
  "msg": "TCP : Unreachable peer",
  "data": {}
}

S7 通用设备字段

以下字段用于 /s7/read/s7/read_points

字段 是否必传 默认值 校验 含义
device_type S7-1200 S7-1200S7-Smart200 S7 设备类型。两者连接方式均为 S7 TCP,S7-Smart200 额外支持 V 区。
ip 合法 IP 地址 S7 设备 IP 地址。
port 102 1..65535 S7 TCP 端口,通常固定为 102
rock 0..31 PLC rock。
slot 0..31 PLC slot。
tsap_conn_type PG PGOPBASIC Snap7 连接类型。

tsap_conn_type 大小写不敏感,服务内部统一转为大写。

连接类型映射:

tsap_conn_type Snap7 值
PG 0x01
OP 0x02
BASIC 0x03

S7 地址字段

字段 是否必传 默认值 校验 含义
area DBMIQV 读取区域。V 仅支持 device_type=S7-Smart200
db area=DB 时必填 0 >=0 DB 块号。area=DB 时必须大于 0area=V 时内部按 DB1 读取。
start >=0 起始字节偏移。
size /s7/read 必填 1..65535 读取字节数。

区域说明:

area 含义
DB 数据块 Data Block
M Merker 标志位区
I 输入区 Inputs
Q 输出区 Outputs

communication 格式

communication 是字符串数组,记录连接、读取、断开过程。该字段只在 /api/dc-debugtool/s7/read 返回,/api/dc-debugtool/s7/read_points 不返回该字段。

示例:

Tx:S7_CONNECT ip=192.168.1.10 port=102 rock=0 slot=1 tsap_conn_type=PG
Rx:S7_CONNECTED pdu_length=480
Tx:S7_READ area=DB db=1 start=0 size=4
Rx:11 22 33 44
Tx:S7_DISCONNECT
Rx:S7_DISCONNECTED

说明:

片段 含义
Tx:S7_CONNECT 调试工具准备发起 S7 连接。
Rx:S7_CONNECTED S7 连接成功,可能包含协商后的 pdu_length
Tx:S7_READ 调试工具准备读取指定区域、DB、起始偏移和字节数。
Rx:11 22 33 44 读取返回的原始数据字节,十六进制大写,空格分隔。
Tx:S7_DISCONNECT 调试工具准备断开连接。
Rx:S7_DISCONNECTED 连接已断开。
Rx:S7_ERROR 连接或读取失败,后面带错误消息。

接口一:原始读取

URL

POST /api/dc-debugtool/s7/read

请求体

{
  "device_type": "S7-1200",
  "ip": "192.168.1.10",
  "port": 102,
  "rock": 0,
  "slot": 1,
  "tsap_conn_type": "PG",
  "read": {
    "area": "DB",
    "db": 1,
    "start": 0,
    "size": 4
  }
}

成功返回

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "S7-1200",
      "ip": "192.168.1.10",
      "port": 102,
      "rock": 0,
      "slot": 1,
      "tsap_conn_type": "PG"
    },
    "communication": [
      "Tx:S7_CONNECT ip=192.168.1.10 port=102 rock=0 slot=1 tsap_conn_type=PG",
      "Rx:S7_CONNECTED pdu_length=480",
      "Tx:S7_READ area=DB db=1 start=0 size=4",
      "Rx:11 22 33 44",
      "Tx:S7_DISCONNECT",
      "Rx:S7_DISCONNECTED"
    ]
  }
}

错误返回

{
  "code": 1,
  "msg": "TCP : Unreachable peer",
  "data": {
    "device": {
      "device_type": "S7-1200",
      "ip": "192.168.1.10",
      "port": 102,
      "rock": 0,
      "slot": 1,
      "tsap_conn_type": "PG"
    },
    "communication": [
      "Tx:S7_CONNECT ip=192.168.1.10 port=102 rock=0 slot=1 tsap_conn_type=PG",
      "Rx:S7_ERROR message=TCP : Unreachable peer"
    ]
  }
}

接口二:点位读取并转换

URL

POST /api/dc-debugtool/s7/read_points

请求体

{
  "device_type": "S7-1200",
  "ip": "192.168.1.10",
  "port": 102,
  "rock": 0,
  "slot": 1,
  "tsap_conn_type": "PG",
  "points": [
    {
      "area": "DB",
      "db": 1,
      "start": 0,
      "type": "float32"
    },
    {
      "area": "DB",
      "db": 1,
      "start": 4,
      "type": "bool",
      "bit": 0
    }
  ]
}

支持的数据类型

类型 读取长度 说明
bool 1 byte 布尔值。传 bit 时读取指定 bit;不传 bit 时整个字节非 0 为 true
byte 1 byte 无符号 8 位整数。
int8 1 byte 有符号 8 位整数。
int16 2 bytes 有符号 16 位整数。
uint16 2 bytes 无符号 16 位整数。
int32 4 bytes 有符号 32 位整数。
uint32 4 bytes 无符号 32 位整数。
float32 4 bytes IEEE 754 单精度浮点数。
int64 8 bytes 有符号 64 位整数。
uint64 8 bytes 无符号 64 位整数。
float64 8 bytes IEEE 754 双精度浮点数。

S7 多字节数值按大端字节序解析。

成功返回

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "S7-1200",
      "ip": "192.168.1.10",
      "port": 102,
      "rock": 0,
      "slot": 1,
      "tsap_conn_type": "PG"
    },
    "points": [
      {
        "area": "DB",
        "db": 1,
        "start": 0,
        "type": "float32",
        "value": 12.34
      },
      {
        "area": "DB",
        "db": 1,
        "start": 4,
        "type": "bool",
        "value": true,
        "bit": 0
      }
    ]
  }
}

接口三:连接扫描

URL

POST /api/dc-debugtool/s7/connect_scan

请求体

只需要传入设备 IP。端口固定使用 S7 TCP 默认端口 102

{
  "device_type": "S7-Smart200",
  "ip": "192.168.1.10"
}

扫描范围

字段 扫描值
rock 012
slot 012
tsap_conn_type PGOPBASIC

总计扫描 27 种组合。接口只返回可以连接成功的组合。

成功返回

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "S7-Smart200",
      "ip": "192.168.1.10",
      "port": 102
    },
    "available": [
      {
        "rock": 0,
        "slot": 1,
        "tsap_conn_type": "PG"
      },
      {
        "rock": 0,
        "slot": 1,
        "tsap_conn_type": "OP"
      }
    ]
  }
}

如果没有任何组合可连接,available 为空数组:

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "S7-Smart200",
      "ip": "192.168.1.10",
      "port": 102
    },
    "available": []
  }
}

调用示例

curl -X POST http://127.0.0.1:8000/api/dc-debugtool/s7/connect_scan \
  -H "Content-Type: application/json" \
  -d '{
    "device_type": "S7-Smart200",
    "ip": "192.168.1.10"
  }'

运行方式

uvicorn main:app --host 0.0.0.0 --port 8000

验证方式

编译检查:

python -m compileall app main.py

S7 接口测试:

python -m unittest discover -s intergration/s7 -p "test_*.py"

S7 测试会在本机启动 python-snap7 模拟 server,用于验证 /s7/read/s7/read_points/s7/connect_scan 使用 mock 验证固定端口 102 和只返回可用组合的逻辑。