物联网浏览器 (IoTBrowser)-Modbus 协议集成和测试
- 2024-02-01 福建
本文字数:5274 字
阅读完需:约 17 分钟
Modbus 协议在应用中一般用来与 PLC 或者其他硬件设备通讯,Modbus 集成到 IoTBrowser 使用串口插件模式开发,不同的是采用命令函数,具体可以参考前面几篇文章。目前示例实现了 Modbus-Rtu 和 Modbus-Tcp 两种,通过 js 可以与 Modbus 进行通讯控制。
一、开发插件
添加引用
添加 NModbus4,在 NuGet 搜索 NModbus4
添加 Core,路径:\IoTBrowser\src\app_x64\Core.dll
添加 Infrastructure,路径:\IoTBrowser\src\app_x64\Infrastructure.dll
添加 Newtonsoft,路径:\IoTBrowser\src\app_x64\Newtonsoft.Json.dll
开发 ModbusRtu 和 ModbusTcp 插件
ModbusRtu
public class ModbusRtuCom : ComBase
{
public override string Type => "modbusRtuCom";
public override string Name => "ModbusRtuCom";
private object _locker = new object();
public override bool Init(int port, int baudRate = 9600, string extendData = null)
{
this.Port = port;
var portName = "COM" + port;
base.PortName = portName;
ModbusRtuService.Init(portName, baudRate);
Console.WriteLine("初始化ModbusRtuCom驱动程序成功!");
return true;
}
public override event PushData OnPushData;
public override bool Open()
{
var b = false;
try
{
ModbusRtuService.Open();
b = true;
IsOpen = true;
}
catch (Exception ex)
{
string msg = string.Format("ModbusRtuCom串口打开失败:{0} ", ex.Message);
Console.WriteLine(msg);
}
return b;
}
public override bool Close()
{
ModbusRtuService.Close();
IsOpen = false;
OnPushData = null;
return true;
}
public override string Command(string name, string data)
{
var outData = string.Empty;
var dataObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(data);
switch (name)
{
case "ReadCoils":
//01
var readData = ModbusRtuService.ReadCoils(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadInputs":
//02
readData = ModbusRtuService.ReadInputs(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadHoldingRegisters":
//03
readData = ModbusRtuService.ReadHoldingRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadInputRegisters":
//04
readData = ModbusRtuService.ReadInputRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "WriteSingleCoil":
//05
ModbusRtuService.WriteSingleCoil(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ModbusHelper.BoolParse(dataObj.value.ToString()));
break;
case "WriteSingleRegister":
//06
ModbusRtuService.WriteSingleRegister(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.value.ToString()));
break;
case "WriteMultipleCoils":
//0F 写一组线圈
var values = dataObj.value.ToString().Split(' ');
var datas = new bool[values.Length];
for (var i = 0; i < values.Length; i++)
{
datas[i] = ModbusHelper.BoolParse(values[i]);
}
ModbusRtuService.WriteMultipleCoils(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), datas);
break;
case "WriteMultipleRegisters":
// 10 写一组保持寄存器
values = dataObj.value.ToString().Split(' ');
var udatas = new ushort[values.Length];
for (var i = 0; i < values.Length; i++)
{
udatas[i] = ushort.Parse(values[i]);
}
ModbusRtuService.WriteMultipleRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), udatas);
break;
}
return outData;
}
}
ModbusTcp
public class ModbusTcpCom : ComBase
{
public override string Type => "modbusTcpCom";
public override string Name => "ModbusTcpCom";
private object _locker = new object();
public override bool Init(int port, int baudRate = 9600, string extendData = null)
{
this.Port = port;
ModbusTcpService.Init(extendData, port);
Console.WriteLine("初始化ModbusTcpCom驱动程序成功!");
return true;
}
public override event PushData OnPushData;
public override bool Open()
{
var b = false;
try
{
ModbusTcpService.Open();
b = true;
IsOpen = true;
}
catch (Exception ex)
{
string msg = string.Format("ModbusTcpCom串口打开失败:{0} ", ex.Message);
Console.WriteLine(msg);
}
return b;
}
public override bool Close()
{
ModbusTcpService.Close();
IsOpen = false;
OnPushData = null;
return true;
}
public override string Command(string name, string data)
{
var outData = string.Empty;
var dataObj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(data);
switch (name)
{
case "ReadCoils":
//01
var readData = ModbusTcpService.ReadCoils(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadInputs":
//02
readData = ModbusTcpService.ReadInputs(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadHoldingRegisters":
//03
readData = ModbusTcpService.ReadHoldingRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "ReadInputRegisters":
//04
readData=ModbusTcpService.ReadInputRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.numberOfPoints.ToString()));
outData = ModbusHelper.ToString(readData);
break;
case "WriteSingleCoil":
//05
ModbusTcpService.WriteSingleCoil(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ModbusHelper.BoolParse(dataObj.value.ToString()));
break;
case "WriteSingleRegister":
//06
ModbusTcpService.WriteSingleRegister(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), ushort.Parse(dataObj.value.ToString()));
break;
case "WriteMultipleCoils":
//0F 写一组线圈
var values = dataObj.value.ToString().Split(' ');
var datas =new bool[values.Length];
for(var i=0;i< values.Length;i++)
{
datas[i] = ModbusHelper.BoolParse(values[i]);
}
ModbusTcpService.WriteMultipleCoils(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), datas);
break;
case "WriteMultipleRegisters":
// 10 写一组保持寄存器
values = dataObj.value.ToString().Split(' ');
var udatas = new ushort[values.Length];
for (var i = 0; i < values.Length; i++)
{
udatas[i] = ushort.Parse(values[i]);
}
ModbusTcpService.WriteMultipleRegisters(byte.Parse(dataObj.slaveAddress.ToString()), ushort.Parse(dataObj.startAddress.ToString()), udatas);
break;
}
return outData;
}
}
3.功能
读单个线圈
读取输入线圈/离散量线圈
读取保持寄存器
读取输入寄存器
写单个线圈
写单个输入线圈/离散量线圈
写一组线圈
写一组保持寄存器
源代码位置:\Plugins\DDS.IoT.Modbus
二、本机测试
1.测试前准备
需要安装虚拟串口和 modbusslave,可以在源代码中下载:
https://gitee.com/yizhuqing/IoTBrowser/tree/master/soft
2.串口测试
3.TCP 测试
三、部署到 IoTBrowser
1.编译
(建议生产环境使用 Release 模式)
2.拷贝到 Plugins 文件夹
也可以放到 com 文件夹。
注意:需要拷贝 NModbus4.dll 到\IoTBrowser\src\app_x64 目录下
四、IoTBrowser 集成测试
1.串口测试
写入多个数据写入以空格分割,写入线圈数据支持 0/1 或 false/true。
2.TCP 测试
TCP 注意 ip 地址通过扩展数据传入,端口号就是串口号。
文章转载自:木子清
快乐非自愿限量之名
还未添加个人签名 2023-06-19 加入
还未添加个人简介
评论