我正在尝试制作能源工厂模拟器,我想在我的应用程序中模拟一些设备。
这个想法是主要的东西和应用程序请求所需的奴隶并做出一些东西。
我刚开始使用Nmodbus,并且所有设备都能正常工作。 我尝试使用SlaveId来询问每个设备,但是当我读或写时,我都在相同的数据存储区中编写了所有内容。 应用和设备在localhost中运行。
这就是我在同一网络中声明每个设备的方式:
int port = 502;
IPAddress address = new IPAddress(new byte[] { 127, 0, 0, 1 });
// create and start the TCP slave
slaveTcpListener = new TcpListener(address, port);
slaveTcpListener.Start();
slave1 = ModbusTcpSlave.CreateTcp(1, slaveTcpListener);
slave1.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave1.Listen();
slave2 = ModbusTcpSlave.CreateTcp(2, slaveTcpListener);
slave2.DataStore = DataStoreFactory.CreateDefaultDataStore();
slave2.Listen();
这就是我如何请求每台设备的数据:
using (TcpClient client = new TcpClient("127.0.0.1", 502))
{
ModbusIpMaster master = ModbusIpMaster.CreateIp(client);
// read five input values
ushort startAddress = 0;
ushort numInputs = 10;
ushort[] inputs = master.ReadHoldingRegisters(1,startAddress, numInputs);
ushort[] inputs2 = master.ReadHoldingRegisters(2, startAddress, numInputs);
}
但结果始终是slave1的数据存储区。
答案 0 :(得分:1)
不幸的是,没有办法运行多个从设备,因为slave.Listen()方法包含无限循环:
public override void Listen()
{
while (true)
{
try
{
try
{
// read request and build message
byte[] frame = SerialTransport.ReadRequest();
IModbusMessage request = ModbusMessageFactory.CreateModbusRequest(frame);
if (SerialTransport.CheckFrame && !SerialTransport.ChecksumsMatch(request, frame))
{
string msg = $"Checksums failed to match {string.Join(", ", request.MessageFrame)} != {string.Join(", ", frame)}.";
Debug.WriteLine(msg);
throw new IOException(msg);
}
// only service requests addressed to this particular slave
if (request.SlaveAddress != UnitId)
{
Debug.WriteLine($"NModbus Slave {UnitId} ignoring request intended for NModbus Slave {request.SlaveAddress}");
continue;
}
// perform action
IModbusMessage response = ApplyRequest(request);
// write response
SerialTransport.Write(response);
}
catch (IOException ioe)
{
Debug.WriteLine($"IO Exception encountered while listening for requests - {ioe.Message}");
SerialTransport.DiscardInBuffer();
}
catch (TimeoutException te)
{
Debug.WriteLine($"Timeout Exception encountered while listening for requests - {te.Message}");
SerialTransport.DiscardInBuffer();
}
// TODO better exception handling here, missing FormatException, NotImplemented...
}
catch (InvalidOperationException)
{
// when the underlying transport is disposed
break;
}
}
答案 1 :(得分:0)
同样的限制给我带来了问题,所以我接手了NModbus4项目(现在只是NModbus):
https://github.com/NModbus/NModbus
public static async Task StartModbusSerialRtuSlaveNetwork()
{
using (SerialPort slavePort = new SerialPort("COM5"))
{
// configure serial port
slavePort.BaudRate = 19200;
slavePort.DataBits = 8;
slavePort.Parity = Parity.Even;
slavePort.StopBits = StopBits.One;
slavePort.Open();
//Create an instance of the ModbusFactory
IModbusFactory factory = new ModbusFactory();
//Create an adapter for the serial port
var adapter = new SerialPortAdapter(slavePort);
//Create the slave network
IModbusSlaveNetwork modbusSlaveNetwork = factory.CreateRtuSlaveNetwork(adapter);
//Create the slaves
IModbusSlave slave1 = factory.CreateSlave(1);
IModbusSlave slave2 = factory.CreateSlave(2);
//Add the slaves to the network
modbusSlaveNetwork.AddSlave(slave1);
modbusSlaveNetwork.AddSlave(slave2);
await modbusSlaveNetwork.ListenAsync();
await Task.Delay(1);
}
}