Flutter Modbus TCP通信插件modbus_client_tcp的使用
Flutter Modbus TCP通信插件modbus_client_tcp的使用
Introduction
modbus_client_tcp
是一组实现Modbus Client发送请求到远程设备(即Modbus Server)的包。以下是该包的一些关键特性:
- Modbus Client:为TCP/UDP和Serial协议提供基础实现。
- Modbus Client TCP:通过以太网网络使用TCP协议发送请求。
- Modbus Client UDP:通过以太网网络使用UDP协议发送请求。
- Modbus Client Serial:通过串行端口使用ASCII和RTU协议发送请求。
为了最小化项目依赖,这些包被分开实现。对于串行实现,Flutter项目只需添加flutter_libserialport
包,而Dart项目则需要构建libserialport
库。
Features
modbus_client_tcp
提供了多种功能来优化与Modbus服务器的通信:
- 自动连接模式:通过设置
ModbusConnectionMode
来自定义send
命令的行为。 - 单元ID:可以在客户端和请求中指定目标单元ID。
- 响应超时:可以为客户端实例或请求设置响应超时。
- 服务器发现:从起始IP地址发现Modbus服务器。
- 连接超时:为TCP客户端指定连接超时。
- 连接后延迟:在某些情况下,连接后延迟发送请求。
- 元素类型:支持多种数值和位元素类型。
- 文件记录:支持文件记录功能码0x14和0x15。
- 字节序:定义Modbus寄存器中的字节排列方式。
- 元素组:创建元素组以优化请求。
- 自定义请求实现:通过继承
ModbusRequest
类实现自定义请求。 - 日志记录:启用日志记录功能。
Usage
读取请求 (Read Request)
import 'package:modbus_client/modbus_client.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
void main() async {
// 创建一个Modbus int16寄存器元素
var batteryTemperature = ModbusInt16Register(
name: "BatteryTemperature",
type: ModbusElementType.inputRegister,
address: 22,
uom: "°C",
multiplier: 0.1,
onUpdate: (self) => print(self));
// 发现Modbus服务器
var serverIp = await ModbusClientTcp.discover("192.168.0.0");
if (serverIp == null) {
ModbusAppLogger.shout("No modbus server found!");
return;
}
// 创建Modbus客户端
var modbusClient = ModbusClientTcp(serverIp, unitId: 1);
// 发送读取请求
await modbusClient.send(batteryTemperature.getReadRequest());
// 结束连接
modbusClient.disconnect();
}
写入请求 (Write Request)
import 'package:modbus_client/modbus_client.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
enum BatteryStatus implements ModbusIntEnum {
offline(0),
standby(1),
running(2),
fault(3),
sleepMode(4);
const BatteryStatus(this.intValue);
@override
final int intValue;
@override
String toString() {
return name;
}
}
void main() async {
var batteryStatus = ModbusEnumRegister(
name: "BatteryStatus",
address: 11,
type: ModbusElementType.holdingRegister,
enumValues: BatteryStatus.values,
onUpdate: (self) => print(self));
// 发现Modbus服务器
var serverIp = await ModbusClientTcp.discover("192.168.0.0");
if (serverIp == null) {
ModbusAppLogger.shout("No modbus server found!");
return;
}
// 创建Modbus客户端
var modbusClient = ModbusClientTcp(serverIp, unitId: 1);
var req = batteryStatus.getWriteRequest(BatteryStatus.running);
var res = await modbusClient.send(req);
print(res.name);
modbusClient.disconnect();
}
元素组读取请求 (Group Read Request)
import 'package:modbus_client/modbus_client.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
enum BatteryStatus implements ModbusIntEnum {
offline(0),
standby(1),
running(2),
fault(3),
sleepMode(4);
const BatteryStatus(this.intValue);
@override
final int intValue;
}
void main() async {
// 创建Modbus元素组
var batteryRegs = ModbusElementsGroup([
ModbusEnumRegister(
name: "BatteryStatus",
type: ModbusElementType.holdingRegister,
address: 37000,
enumValues: BatteryStatus.values),
ModbusInt32Register(
name: "BatteryChargingPower",
type: ModbusElementType.holdingRegister,
address: 37001,
uom: "W",
description: "> 0: charging - < 0: discharging"),
ModbusUint16Register(
name: "BatteryCharge",
type: ModbusElementType.holdingRegister,
address: 37004,
uom: "%",
multiplier: 0.1),
ModbusUint16Register(
name: "BatteryTemperature",
type: ModbusElementType.holdingRegister,
address: 37022,
uom: "°C",
multiplier: 0.1),
]);
// 发现Modbus服务器
var serverIp = await ModbusClientTcp.discover("192.168.0.0");
if (serverIp == null) {
ModbusAppLogger.shout("No modbus server found!");
return;
}
// 创建Modbus客户端
var modbusClient = ModbusClientTcp(serverIp, unitId: 1);
// 发送读取请求
await modbusClient.send(batteryRegs.getReadRequest());
print(batteryRegs[0]);
print(batteryRegs[1]);
print(batteryRegs[2]);
print(batteryRegs[3]);
// 结束连接
modbusClient.disconnect();
}
文件记录写入和读取示例 (File Records Write and Read Example)
import 'dart:typed_data';
import 'package:modbus_client/modbus_client.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
void main() async {
// 简单的Modbus日志记录
ModbusAppLogger(Level.FINE);
// 创建Modbus客户端
var modbusClient = ModbusClientTcp("127.0.0.1", unitId: 1);
// 写入两个文件记录
var r1 = ModbusFileUint16Record(
fileNumber: 4,
recordNumber: 1,
recordData: Uint16List.fromList([12573, 56312]));
var r2 = ModbusFileDoubleRecord(
fileNumber: 3,
recordNumber: 9,
recordData: Float64List.fromList([123.5634, 125756782.8492]));
await modbusClient.send(ModbusFileRecordsWriteRequest([r1, r2]));
// 读取两个文件记录
r1 = ModbusFileUint16Record.empty(
fileNumber: 4, recordNumber: 1, recordDataCount: 2);
r2 = ModbusFileDoubleRecord.empty(
fileNumber: 3, recordNumber: 9, recordDataCount: 2);
await modbusClient.send(ModbusFileRecordsReadRequest([r1, r2]));
// 写入多个记录
var multipleRecords =
ModbusFileMultipleRecord(fileNumber: 4, recordNumber: 1);
multipleRecords.addNext(ModbusRecordType.int16, -123);
multipleRecords.addNext(ModbusRecordType.uint16, 5000);
multipleRecords.addNext(ModbusRecordType.int32, -1234567890);
multipleRecords.addNext(ModbusRecordType.uint32, 1234567890);
multipleRecords.addNext(ModbusRecordType.float, 123.45);
multipleRecords.addNext(ModbusRecordType.double, 12345.6789);
await modbusClient.send(multipleRecords.getWriteRequest());
multipleRecords = ModbusFileMultipleRecord.empty(
fileNumber: 4, recordNumber: 1, recordDataByteLength: 24);
await modbusClient.send(multipleRecords.getReadRequest());
multipleRecords.start();
print(multipleRecords.getNext(ModbusRecordType.int16));
print(multipleRecords.getNext(ModbusRecordType.uint16));
print(multipleRecords.getNext(ModbusRecordType.int32));
print(multipleRecords.getNext(ModbusRecordType.uint32));
print(multipleRecords.getNext(ModbusRecordType.float));
print(multipleRecords.getNext(ModbusRecordType.double));
// 结束连接
modbusClient.disconnect();
}
华为SUN2000逆变器寄存器 (Huawei SUN2000 Inverter Registers)
import 'package:modbus_client/modbus_client.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
enum BatteryStatus implements ModbusIntEnum {
offline(0),
standby(1),
running(2),
fault(3),
sleepMode(4);
const BatteryStatus(this.intValue);
@override
final int intValue;
}
enum MeterStatus implements ModbusIntEnum {
offline(0),
normal(1);
const MeterStatus(this.intValue);
@override
final int intValue;
}
void main() async {
ModbusAppLogger(Level.INFO);
// 发现Modbus服务器
var serverIp = await ModbusClientTcp.discover("192.168.0.0");
if (serverIp == null) {
ModbusAppLogger.shout("No modbus server found!");
return;
}
// 创建Modbus客户端
var client = ModbusClientTcp(serverIp,
serverPort: 502,
unitId: 1,
responseTimeout: Duration(seconds: 3),
connectionTimeout: Duration(seconds: 1),
delayAfterConnect: Duration(seconds: 1));
var batteryRegs = ModbusElementsGroup([
ModbusEnumRegister(
name: "BatteryStatus",
type: ModbusElementType.holdingRegister,
address: 37000,
enumValues: BatteryStatus.values),
ModbusInt32Register(
name: "BatteryChargingPower",
type: ModbusElementType.holdingRegister,
address: 37001,
uom: "W",
description: "> 0: charging - < 0: discharging"),
ModbusUint16Register(
name: "BatteryTemperature",
type: ModbusElementType.holdingRegister,
address: 37022,
uom: "°C",
multiplier: 0.1),
ModbusUint16Register(
name: "BatteryCharge",
type: ModbusElementType.holdingRegister,
address: 37004,
uom: "%",
multiplier: 0.1),
]);
var meterRegs = ModbusElementsGroup([
ModbusEnumRegister(
name: "MeterStatus",
type: ModbusElementType.holdingRegister,
address: 37100,
enumValues: MeterStatus.values),
ModbusInt32Register(
name: "MeterGridVoltagePhaseA",
type: ModbusElementType.holdingRegister,
address: 37101,
uom: "V",
multiplier: 0.1),
// ... 其他寄存器 ...
]);
try {
var batteryRegsReq = batteryRegs.getReadRequest();
var res = await client.send(batteryRegsReq);
if (res == ModbusResponseCode.requestSucceed) {
for (var element in batteryRegs) {
print(element);
}
} else {
print(res);
}
var meterRegsReq = meterRegs.getReadRequest();
res = await client.send(meterRegsReq);
if (res == ModbusResponseCode.requestSucceed) {
for (var element in meterRegs) {
print(element);
}
} else {
print(res);
}
} finally {
client.disconnect();
}
}
以上代码展示了如何使用modbus_client_tcp
插件进行Modbus TCP通信的基本操作。你可以根据实际需求调整IP地址、寄存器地址和其他参数。
更多关于Flutter Modbus TCP通信插件modbus_client_tcp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter Modbus TCP通信插件modbus_client_tcp的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,以下是一个使用Flutter中的modbus_client_tcp
插件进行Modbus TCP通信的示例代码。这个示例展示了如何连接到Modbus TCP服务器、读取保持寄存器和写入单个线圈。
首先,确保你已经在pubspec.yaml
文件中添加了modbus_client_tcp
依赖:
dependencies:
flutter:
sdk: flutter
modbus_client_tcp: ^x.y.z # 请替换为最新版本号
然后,运行flutter pub get
来安装依赖。
接下来是示例代码:
import 'package:flutter/material.dart';
import 'package:modbus_client_tcp/modbus_client_tcp.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String result = "";
@override
void initState() {
super.initState();
_connectAndCommunicate();
}
Future<void> _connectAndCommunicate() async {
try {
// 创建Modbus TCP客户端
final client = ModbusTCPClient(
host: '192.168.1.100', // 替换为你的Modbus TCP服务器IP地址
port: 502, // Modbus TCP默认端口
unitId: 1, // Modbus单元标识符
);
// 连接到服务器
await client.connect();
// 读取保持寄存器(功能码03)
final holdingRegisters = await client.readHoldingRegisters(
startAddress: 0, // 起始地址
quantity: 10, // 读取数量
);
// 打印读取结果
setState(() {
result = "Holding Registers: ${holdingRegisters.map((e) => e.toHex()).join(", ")}";
});
// 写入单个线圈(功能码05)
final writeResult = await client.writeSingleCoil(
coilAddress: 0, // 线圈地址
value: true, // 写入值(true为ON,false为OFF)
);
// 打印写入结果
setState(() {
result += "\nWrite Single Coil Result: $writeResult";
});
// 断开连接
await client.disconnect();
} catch (e) {
// 处理异常
setState(() {
result = "Error: $e";
});
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Modbus TCP Communication'),
),
body: Center(
child: Text(result),
),
),
);
}
}
代码说明:
-
依赖导入:
- 导入
flutter
和modbus_client_tcp
包。
- 导入
-
主应用:
- 创建一个
MyApp
类,它包含一个状态_MyAppState
。
- 创建一个
-
状态初始化:
- 在
initState
方法中调用_connectAndCommunicate
方法,该方法负责连接Modbus TCP服务器、读取保持寄存器和写入单个线圈。
- 在
-
Modbus TCP客户端:
- 使用
ModbusTCPClient
类创建一个客户端实例,并指定服务器IP地址、端口和单元标识符。
- 使用
-
连接和通信:
- 使用
connect
方法连接到服务器。 - 使用
readHoldingRegisters
方法读取保持寄存器。 - 使用
writeSingleCoil
方法写入单个线圈。 - 使用
disconnect
方法断开连接。
- 使用
-
UI更新:
- 使用
setState
方法更新UI,显示读取和写入的结果。
- 使用
-
异常处理:
- 捕获并处理连接和通信过程中可能发生的异常。
请确保你的Modbus TCP服务器正在运行,并且IP地址、端口和单元标识符配置正确。这个示例代码只是一个简单的演示,实际应用中可能需要更复杂的错误处理和状态管理。