|
|
@@ -10,13 +10,15 @@ from .collector_api import (
|
|
|
edit_modbus_device as api_edit_modbus_device,
|
|
|
edit_modbus_point as api_edit_modbus_point,
|
|
|
)
|
|
|
-from .gateway_api import modbus_point_collect_test as api_modbus_point_collect_test
|
|
|
+from .gateway_api import (
|
|
|
+ modbus_point_collect_test as api_modbus_point_collect_test,
|
|
|
+ modbus_raw_read as api_modbus_raw_read,
|
|
|
+)
|
|
|
from .mcp_app import mcp
|
|
|
|
|
|
|
|
|
class ModbusDeviceCreateItem(BaseModel):
|
|
|
name: str
|
|
|
- device_type: int
|
|
|
ip: str
|
|
|
port: int
|
|
|
slave_id: int
|
|
|
@@ -24,6 +26,7 @@ class ModbusDeviceCreateItem(BaseModel):
|
|
|
word_order: int
|
|
|
address_base: int
|
|
|
serial_port: str = ""
|
|
|
+ device_type: int = 1
|
|
|
timeout: int = 3
|
|
|
is_persistent: bool = False
|
|
|
baud_rate: int = 0
|
|
|
@@ -37,34 +40,72 @@ class ModbusDeviceCreateItem(BaseModel):
|
|
|
collect_interval: int = 5
|
|
|
|
|
|
|
|
|
-class ModbusPointCreateItem(TypedDict):
|
|
|
+class ModbusPointCreateItem(BaseModel):
|
|
|
device_id: int
|
|
|
name: str
|
|
|
address: int
|
|
|
type: str
|
|
|
- func_code: NotRequired[int]
|
|
|
- register_type: NotRequired[str]
|
|
|
- point_id: NotRequired[str]
|
|
|
- scale_ratio: NotRequired[float]
|
|
|
- value_offset: NotRequired[float]
|
|
|
- group_id: NotRequired[int]
|
|
|
- invalid_values: NotRequired[str]
|
|
|
- valid_range_start: NotRequired[float | None]
|
|
|
- valid_range_end: NotRequired[float | None]
|
|
|
- bit: NotRequired[int]
|
|
|
- describe: NotRequired[str]
|
|
|
+ func_code: int
|
|
|
+ register_type: str = ""
|
|
|
+ point_id: str = ""
|
|
|
+ scale_ratio: float = 1
|
|
|
+ value_offset: float = 0
|
|
|
+ group_id: int = 0
|
|
|
+ invalid_values: str = ""
|
|
|
+ valid_range_start: float | None = None
|
|
|
+ valid_range_end: float | None = None
|
|
|
+ bit: int = 0
|
|
|
+ describe: str = ""
|
|
|
+
|
|
|
+
|
|
|
+class ModbusRawReadSpec(TypedDict):
|
|
|
+ function_code: int
|
|
|
+ address: int
|
|
|
+ quantity: int
|
|
|
|
|
|
|
|
|
@mcp.tool(
|
|
|
- name="modbus.point_collect_test",
|
|
|
+ name="modbus.raw_read",
|
|
|
description=(
|
|
|
- "通过采集网关读取 Modbus TCP 点位并转换为业务值。调用 "
|
|
|
- "{base_url}/api/dc-gateway/modbus/read_points。function_code: "
|
|
|
+ "采集网关-通过Modbus TCP 读取原始数据。"
|
|
|
+ "device_type 设备类型,默认 ModbusTCP;word_byte_order 默认 ABCD,可选 ABCD、BADC、CDAB、DCBA;"
|
|
|
+ "address_base 地址偏移,默认 0。"
|
|
|
+ "read 必须包含 function_code、address、quantity;function_code: "
|
|
|
"1=Read Coils/线圈,2=Read Discrete Inputs/离散输入,"
|
|
|
- "3=Read Holding Registers/保持寄存器,4=Read Input Registers/输入寄存器。"
|
|
|
- "word_byte_order 可选 ABCD、BADC、CDAB、DCBA。若读取成功后要创建汇采设备,"
|
|
|
- "映射为 byte_order/word_order: ABCD=>1/1, BADC=>2/1, CDAB=>1/2, DCBA=>2/2。"
|
|
|
- "响应透传上游 JSON,code=0 表示业务成功。"
|
|
|
+ "3=Read Holding Registers/保持寄存器,4=Read Input Registers/输入寄存器;"
|
|
|
+ "quantity 范围 1..125。"
|
|
|
+ "不要传name字段"
|
|
|
+ ),
|
|
|
+)
|
|
|
+def modbus_raw_read(
|
|
|
+ project_key: str,
|
|
|
+ ip: str,
|
|
|
+ port: int,
|
|
|
+ slave_id: int,
|
|
|
+ read: ModbusRawReadSpec,
|
|
|
+ device_type: str = "ModbusTCP",
|
|
|
+ word_byte_order: str = "ABCD",
|
|
|
+ address_base: int = 0,
|
|
|
+) -> dict[str, Any]:
|
|
|
+ return api_modbus_raw_read(
|
|
|
+ project_key,
|
|
|
+ ip=ip,
|
|
|
+ port=port,
|
|
|
+ slave_id=slave_id,
|
|
|
+ read=dict(read),
|
|
|
+ device_type=device_type,
|
|
|
+ word_byte_order=word_byte_order,
|
|
|
+ address_base=address_base,
|
|
|
+ )
|
|
|
+
|
|
|
+
|
|
|
+@mcp.tool(
|
|
|
+ name="modbus.point_collect_test",
|
|
|
+ description=(
|
|
|
+ "通过采集网关读取 Modbus TCP 点位的数据"
|
|
|
+ "寄存器类型可选:1=Read Coils/线圈/0x,2=Read Discrete Inputs/离散输入/1x,"
|
|
|
+ "3=Read Holding Registers/保持寄存器/4x,4=Read Input Registers/输入寄存器/3x。"
|
|
|
+ "word_byte_order 可选 ABCD、BADC、CDAB、DCBA"
|
|
|
),
|
|
|
)
|
|
|
def modbus_point_collect_test(
|
|
|
@@ -92,18 +133,12 @@ def modbus_point_collect_test(
|
|
|
@mcp.tool(
|
|
|
name="collector.modbus_device_create",
|
|
|
description=(
|
|
|
- "汇采-批量创建 Modbus 设备。依次调用 {data_collector_base_url}/api/collector/device,"
|
|
|
- "全部设备创建调用完成后会内部调用设备列表并匹配每个设备 id;如果匹配到多个设备,"
|
|
|
- "选择 id 最大的。devices 每项必须传 device_type 协议类型、ip IP 地址、"
|
|
|
- "port 端口号、name 名称、slave_id、word_order 字顺序、byte_order 字节顺序、"
|
|
|
- "address_base 地址基准。address_base 会转换为汇采接口的 address_offset。"
|
|
|
+ "汇采-批量创建 Modbus 设备。"
|
|
|
"默认参数: type=modbus, timeout=3, is_persistent=false, group_id=0, "
|
|
|
"alarm_interval=90, collect_interval=5, retry_times=0。"
|
|
|
- "注意 byte_order/word_order 是汇采枚举,不是网关 word_byte_order。"
|
|
|
+ "address_base 地址偏移/address_offset。"
|
|
|
"byte_order: 1=Big Endian, 2=Small Endian。word_order: 1=Big Endian, 2=Small Endian。"
|
|
|
- "device_type: 1=TCP, 2=RTU, 3=UDP, 4=RTU OVER TCP, 5=RTU OVER UDP。"
|
|
|
- "采集网关 word_byte_order 映射: ABCD=>1/1, BADC=>2/1, CDAB=>1/2, DCBA=>2/2。"
|
|
|
- "返回批量结果,state=0 表示全部创建并匹配成功。"
|
|
|
+ "word_byte_order 映射: ABCD=>1/1, BADC=>2/1, CDAB=>1/2, DCBA=>2/2。"
|
|
|
),
|
|
|
)
|
|
|
def collector_modbus_device_create(
|
|
|
@@ -116,19 +151,13 @@ def collector_modbus_device_create(
|
|
|
@mcp.tool(
|
|
|
name="collector.modbus_device_edit",
|
|
|
description=(
|
|
|
- "汇采-编辑 Modbus 设备。调用 "
|
|
|
- "{data_collector_base_url}/api/collector/modbus/device/edit。"
|
|
|
- "这是 Modbus 专用旧编辑接口,必须传 ori_id 原设备 id、name、slave_id、"
|
|
|
- "word_order、byte_order、device_type 连接类型。TCP/UDP 类设备还必须传 ip 和 port;"
|
|
|
- "RTU 设备必须传 serial_port。"
|
|
|
+ "汇采-编辑 Modbus 设备。必须传 ori_id 原设备 id、name、slave_id、"
|
|
|
+ "word_order、byte_order、ip 和 port;"
|
|
|
"编辑前设备不能处于已连接状态;若已连接,请先调用 collector.device_disconnect。"
|
|
|
- "该接口是全量更新语义,未传字段可能被默认值覆盖。"
|
|
|
"默认参数: ip='', port=0, serial_port='', timeout=3, is_persistent=false, "
|
|
|
"baud_rate=0, data_bit=0, parity=0, stop_bit=0, mode=0, address_offset=0, "
|
|
|
"retry_times=0, device_group_id=0, alarm_interval=90, collect_interval=5。"
|
|
|
- "连接类型: 1=TCP, 2=RTU, 3=UDP, 4=RTU OVER TCP, 5=RTU OVER UDP。"
|
|
|
"byte_order: 1=Big Endian, 2=Small Endian;word_order: 1=Big Endian, 2=Small Endian。"
|
|
|
- "响应透传上游 JSON,state=0 表示业务成功。"
|
|
|
),
|
|
|
)
|
|
|
def collector_modbus_device_edit(
|
|
|
@@ -186,26 +215,21 @@ def collector_modbus_device_edit(
|
|
|
@mcp.tool(
|
|
|
name="collector.modbus_point_create",
|
|
|
description=(
|
|
|
- "汇采-批量创建 Modbus 采集点位。依次调用 "
|
|
|
- "{data_collector_base_url}/api/collector/modbus/point/add_collect_point。"
|
|
|
+ "汇采-批量创建 Modbus 采集点位。"
|
|
|
"points 每项必须传 device_id、name 名称、address 寄存器地址、"
|
|
|
- "type 数据类型,以及 func_code 或 register_type 寄存器类型。"
|
|
|
- "每个点位会补齐默认值: point_id='', scale_ratio=1, value_offset=0, group_id=0, "
|
|
|
- "invalid_values='', valid_range_start=null, valid_range_end=null, bit=0。"
|
|
|
- "func_code: 1=Read Coils/线圈,2=Read Discrete Inputs/离散输入,"
|
|
|
- "3=Read Holding Registers/保持寄存器,4=Read Input Registers/输入寄存器。"
|
|
|
- "register_type 可用 coil、discrete_input、holding_register、input_register。"
|
|
|
+ "type 数据类型,以及 func_code 寄存器类型。"
|
|
|
+ "func_code: 1=Read Coils/线圈/0x,2=Read Discrete Inputs/离散输入/1x,"
|
|
|
+ "3=Read Holding Registers/保持寄存器/4x,4=Read Input Registers/输入寄存器/3x。"
|
|
|
"数据类型应使用汇采类型: bool, int16, uint16, int32, uint32, int64, uint64, float32, float64。"
|
|
|
"常见点表类型映射: BOOL=>bool, SHORT=>int16, WORD=>uint16, LONG=>int32, "
|
|
|
"DWORD=>uint32, FLOAT/REAL=>float32, DOUBLE=>float64, LONGLONG=>int64, QWORD=>uint64。"
|
|
|
- "响应透传上游 JSON,state=0 表示业务成功。"
|
|
|
),
|
|
|
)
|
|
|
def collector_modbus_point_create(
|
|
|
project_key: str,
|
|
|
points: list[ModbusPointCreateItem],
|
|
|
) -> dict[str, Any]:
|
|
|
- return api_create_modbus_points(project_key, points)
|
|
|
+ return api_create_modbus_points(project_key, [_dump_model_or_dict(item) for item in points])
|
|
|
|
|
|
|
|
|
def _dump_model_or_dict(item: Any) -> dict[str, Any]:
|
|
|
@@ -218,21 +242,17 @@ def _dump_model_or_dict(item: Any) -> dict[str, Any]:
|
|
|
name="collector.modbus_point_edit",
|
|
|
description=(
|
|
|
"汇采-编辑 Modbus 采集点位。调用 "
|
|
|
- "{data_collector_base_url}/api/collector/modbus/point/edit_collect_point。"
|
|
|
- "必须传 ori_id 原点位 id、name 名称、address 寄存器地址、data_type 数据类型,"
|
|
|
- "以及 func_code 或 register_type 寄存器类型。"
|
|
|
+ "必须传 ori_id 原点位 id、name 名称、address 寄存器地址、type 数据类型,"
|
|
|
+ "以及 func_code 寄存器类型。"
|
|
|
"ori_id 对应 collector.device_points 返回的 data.point[].id。"
|
|
|
- "编辑点位不会迁移所属设备。"
|
|
|
- "该接口是全量更新语义,未传字段可能被默认值覆盖。"
|
|
|
"默认参数: point_id='', scale_ratio=1, value_offset=0, group_id=0, "
|
|
|
"invalid_values='', valid_range_start=null, valid_range_end=null, bit=0。"
|
|
|
- "func_code: 1=Read Coils/线圈,2=Read Discrete Inputs/离散输入,"
|
|
|
- "3=Read Holding Registers/保持寄存器,4=Read Input Registers/输入寄存器。"
|
|
|
+ "func_code: 1=Read Coils/线圈/0x,2=Read Discrete Inputs/离散输入/1x,"
|
|
|
+ "3=Read Holding Registers/保持寄存器/4x,4=Read Input Registers/输入寄存器/3x。"
|
|
|
"register_type 可用 coil、discrete_input、holding_register、input_register。"
|
|
|
"数据类型应使用汇采类型: bool, int16, uint16, int32, uint32, int64, uint64, float32, float64。"
|
|
|
"常见点表类型映射: BOOL=>bool, SHORT=>int16, WORD=>uint16, LONG=>int32, "
|
|
|
"DWORD=>uint32, FLOAT/REAL=>float32, DOUBLE=>float64, LONGLONG=>int64, QWORD=>uint64。"
|
|
|
- "响应透传上游 JSON,state=0 表示业务成功。"
|
|
|
),
|
|
|
)
|
|
|
def collector_modbus_point_edit(
|