modbus-http-api.md 6.6 KB

Modbus HTTP 接口说明

目标

本服务通过 HTTP 接口连接 Modbus TCP 设备,并返回与 Modbus Poll Communication 窗口一致风格的原始 Tx/Rx 报文。

当前仅支持 ModbusTCP

接口列表

  • POST /api/dc-gateway/modbus/read:原始 Modbus 读取,只返回通信报文,不返回解析值。
  • POST /api/dc-gateway/modbus/read_points:按点位定义读取,返回点位值。
  • GET /api/dc-gateway/health:健康检查。

通用返回约定

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

成功:

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

失败:

{
  "code": 1,
  "msg": "failed to connect to 192.168.75.240:505",
  "data": {}
}

data 固定为对象。两个 Modbus 读取接口都会在 data.device 返回设备信息;/modbus/read 的通信报文返回在 data.communication/modbus/read_points 的点位返回在 data.points

设备参数校验

字段 是否必传 校验
device_type 默认 ModbusTCP,目前仅支持 ModbusTCP
ip 必须是合法 IP 地址
port 1 <= port <= 65535
word_byte_order 默认 ABCD,可选 ABCDBADCCDABDCBA
address_base 默认 0,必须大于等于 0
slave_id 默认 1,范围 0..247

communication 格式

communication 是字符串数组,每项格式如下:

Tx:001-00 00 33 00 00 00 06 01 03 00 00 00 04
Rx:002-00 00 33 00 00 00 0B 01 03 08 00 01 42 A8 00 00 40 F8

说明:

  • Tx 表示发送给设备的 Modbus TCP ADU。
  • Rx 表示设备返回的 Modbus TCP ADU。
  • 001002 是当前 HTTP 请求内的报文序号。
  • - 后面是大写十六进制字节,使用空格分隔。
  • 每个 HTTP 请求都会创建独立 trace,不使用全局 trace,并发请求不会互相清空或串包。
  • 若 pymodbus 因重试产生多次发送/接收,数组会包含多条 Tx/Rx

地址规则

接口只按照入参格式处理地址。address_base 作为显式地址偏移,实际发送给 Modbus 协议的地址为:

protocol_address = address + address_base

常规情况下传:

"address_base": 0

Function Code

支持以下功能码:

function_code 含义
1 读线圈 Read Coils
2 读离散输入 Read Discrete Inputs
3 读保持寄存器 Read Holding Registers
4 读输入寄存器 Read Input Registers

读取数量限制

/api/dc-gateway/modbus/readquantity 范围为:

1 <= quantity <= 125

超过范围不会返回 HTTP 422,而是返回:

{
  "code": 1,
  "msg": "read.quantity: Input should be less than or equal to 125",
  "data": {
    "communication": []
  }
}

接口一:原始读取

URL

POST /api/dc-gateway/modbus/read

请求体

{
  "device_type": "ModbusTCP",
  "ip": "192.168.75.240",
  "port": 505,
  "word_byte_order": "ABCD",
  "address_base": 0,
  "slave_id": 1,
  "read": {
    "function_code": 3,
    "address": 0,
    "quantity": 4
  }
}

成功返回

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "ModbusTCP",
      "ip": "192.168.75.240",
      "port": 505,
      "word_byte_order": "ABCD",
      "address_base": 0,
      "slave_id": 1
    },
    "communication": [
      "Tx:001-00 00 33 00 00 00 06 01 03 00 00 00 04",
      "Rx:002-00 00 33 00 00 00 0B 01 03 08 00 01 42 A8 00 00 40 F8"
    ]
  }
}

该接口不返回 values。如果需要按 int16float32 等类型解析数据,请使用点位读取接口。

错误返回

{
  "code": 1,
  "msg": "Modbus Error: [Input/Output] No response received after 3 retries, continue with next request",
  "data": {
    "device": {
      "device_type": "ModbusTCP",
      "ip": "192.168.75.240",
      "port": 505,
      "word_byte_order": "ABCD",
      "address_base": 0,
      "slave_id": 1
    },
    "communication": [
      "Tx:001-00 00 33 00 00 00 06 01 03 00 00 00 04"
    ]
  }
}

接口二:点位读取并转换

URL

POST /api/dc-gateway/modbus/read_points

请求体

{
  "device_type": "ModbusTCP",
  "ip": "192.168.75.240",
  "port": 505,
  "word_byte_order": "ABCD",
  "address_base": 0,
  "slave_id": 1,
  "points": [
    {
      "function_code": 3,
      "address": 7,
      "type": "int16"
    },
    {
      "function_code": 3,
      "address": 1,
      "type": "float32"
    },
    {
      "function_code": 1,
      "address": 0,
      "type": "bool"
    }
  ]
}

支持的数据类型

类型 读取长度 说明
bool 1 bit 或 1 register 布尔值
int16 1 register 有符号 16 位整数
uint16 1 register 无符号 16 位整数
int32 2 registers 有符号 32 位整数
uint32 2 registers 无符号 32 位整数
float32 2 registers IEEE 754 单精度浮点数
int64 4 registers 有符号 64 位整数
uint64 4 registers 无符号 64 位整数
float64 4 registers IEEE 754 双精度浮点数

成功返回

{
  "code": 0,
  "msg": "success",
  "data": {
    "device": {
      "device_type": "ModbusTCP",
      "ip": "192.168.75.240",
      "port": 505,
      "word_byte_order": "ABCD",
      "address_base": 0,
      "slave_id": 1
    },
    "points": [
      {
        "function_code": 3,
        "address": 7,
        "type": "int16",
        "value": -321
      }
    ]
  }
}

运行方式

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

也可以直接运行:

python main.py

验证方式

编译检查:

python -m compileall app main.py

调用原始读取接口:

curl -X POST http://127.0.0.1:8000/api/dc-gateway/modbus/read \
  -H "Content-Type: application/json" \
  -d '{
    "device_type": "ModbusTCP",
    "ip": "192.168.75.240",
    "port": 505,
    "word_byte_order": "ABCD",
    "address_base": 0,
    "slave_id": 1,
    "read": {
      "function_code": 3,
      "address": 0,
      "quantity": 4
    }
  }'

运行接口测试:

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

默认测试设备参数参考 D:\Projects\BACnet-Client\autotest\Integration\modbus

MODBUS_DEVICE_IP=192.168.75.240
MODBUS_TCP_PORT=505
MODBUS_SLAVE_ID=1

可通过环境变量覆盖:

set DATA_COLLECTOR_BASE_URL=http://127.0.0.1:8000
set MODBUS_DEVICE_IP=192.168.75.240
set MODBUS_TCP_PORT=505
set MODBUS_SLAVE_ID=1