Modbus协议在应用中一般用来与PLC或者其他硬件设备通讯,Modbus集成到IoTBrowser使用串口插件模式开发,不同的是采用命令函数,具体可以参考前面几篇文章。目前示例实现了Modbus-Rtu和Modbus-Tcp两种,通过js可以与Modbus进行通讯控制。

一、开发插件

    1. 添加引用
      1. 添加NModbus4,在NuGet搜索NModbus4
      2. 添加Core,路径:\IoTBrowser\src\app_x64\Core.dll
      3. 添加Infrastructure,路径:\IoTBrowser\src\app_x64\Infrastructure.dll
      4. 添加Newtonsoft,路径:\IoTBrowser\src\app_x64\Newtonsoft.Json.dll
    2. 开发ModbusRtu和ModbusTcp插件
      1. ModbusRtu

    public classModbusRtuCom : 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 eventPushData OnPushData;public override boolOpen()
{
var b = false;try{
ModbusRtuService.Open();
b
= true;
IsOpen
= true;
}
catch(Exception ex)
{
string msg = string.Format("ModbusRtuCom串口打开失败:{0}", ex.Message);
Console.WriteLine(msg);
}
returnb;
}
public override boolClose()
{
ModbusRtuService.Close();
IsOpen
= false;
OnPushData
= null;return true;
}
public override string Command(string name, stringdata)
{
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;

}
returnoutData;
}
}

b.ModbusTcp

    public classModbusTcpCom : 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 eventPushData OnPushData;public override boolOpen()
{
var b = false;try{
ModbusTcpService.Open();
b
= true;
IsOpen
= true;
}
catch(Exception ex)
{
string msg = string.Format("ModbusTcpCom串口打开失败:{0}", ex.Message);
Console.WriteLine(msg);
}
returnb;
}
public override boolClose()
{
ModbusTcpService.Close();
IsOpen
= false;
OnPushData
= null;return true;
}
public override string Command(string name, stringdata)
{
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;

}
returnoutData;
}
}

3.功能

        1. 读单个线圈
        2. 读取输入线圈/离散量线圈
        3. 读取保持寄存器
        4. 读取输入寄存器
        5. 写单个线圈
        6. 写单个输入线圈/离散量线圈
        7. 写一组线圈
        8. 写一组保持寄存器

源代码位置:\Plugins\DDS.IoT.Modbus

二、本机测试

1.测试前准备

需要安装虚拟串口和modbusslave,可以在源代码中下载:

https://gitee.com/yizhuqing/IoTBrowser/tree/master/soft

2.串口测试

modbus03
modbus04

3.TCP测试

modbus02
modbus01

三、部署到IoTBrowser

1.编译

(建议生产环境使用Release模式)

2.拷贝到Plugins文件夹

也可以放到com文件夹。

注意:需要拷贝NModbus4.dll到\IoTBrowser\src\app_x64目录下

四、IoTBrowser集成测试

1.串口测试

modbus05

写入多个数据写入以空格分割,写入线圈数据支持0/1或false/true。

modbus06

2.TCP测试

modbus07

TCP注意ip地址通过扩展数据传入,端口号就是串口号。

标签: none

添加新评论