本服务通过 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,扫描可用的 rock、slot、tsap_conn_type 组合。业务接口统一返回 HTTP 200,是否成功由 JSON 中的 code 判断。
成功:
{
"code": 0,
"msg": "success",
"data": {}
}
失败:
{
"code": 1,
"msg": "TCP : Unreachable peer",
"data": {}
}
以下字段用于 /s7/read 和 /s7/read_points。
| 字段 | 是否必传 | 默认值 | 校验 | 含义 |
|---|---|---|---|---|
device_type |
否 | S7-1200 |
S7-1200、S7-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 |
PG、OP、BASIC |
Snap7 连接类型。 |
tsap_conn_type 大小写不敏感,服务内部统一转为大写。
连接类型映射:
| tsap_conn_type | Snap7 值 |
|---|---|
PG |
0x01 |
OP |
0x02 |
BASIC |
0x03 |
| 字段 | 是否必传 | 默认值 | 校验 | 含义 |
|---|---|---|---|---|
area |
是 | 无 | DB、M、I、Q、V |
读取区域。V 仅支持 device_type=S7-Smart200。 |
db |
area=DB 时必填 |
0 |
>=0 |
DB 块号。area=DB 时必须大于 0;area=V 时内部按 DB1 读取。 |
start |
是 | 无 | >=0 |
起始字节偏移。 |
size |
/s7/read 必填 |
无 | 1..65535 |
读取字节数。 |
区域说明:
| area | 含义 |
|---|---|
DB |
数据块 Data Block |
M |
Merker 标志位区 |
I |
输入区 Inputs |
Q |
输出区 Outputs |
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 |
连接或读取失败,后面带错误消息。 |
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"
]
}
}
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
}
]
}
}
POST /api/dc-debugtool/s7/connect_scan
只需要传入设备 IP。端口固定使用 S7 TCP 默认端口 102。
{
"device_type": "S7-Smart200",
"ip": "192.168.1.10"
}
| 字段 | 扫描值 |
|---|---|
rock |
0、1、2 |
slot |
0、1、2 |
tsap_conn_type |
PG、OP、BASIC |
总计扫描 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 和只返回可用组合的逻辑。