implement Logic/Wire addressing in ModbusClients

This commit is contained in:
ig 2023-03-10 13:57:39 +01:00
parent df087b9d8e
commit 6db610d308
4 changed files with 71 additions and 38 deletions

View File

@ -1,10 +0,0 @@
namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
[Flags]
public enum Endianness
{
LittleEndian32BitIntegers = 0,
LittleEndian32Floats = 0,
BigEndian32BitIntegers = 1,
BigEndian32Floats = 2,
}

View File

@ -1,6 +1,8 @@
using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.Protocols.Modbus.Connections;
using InnovEnergy.Lib.Protocols.Modbus.Conversions; using InnovEnergy.Lib.Protocols.Modbus.Conversions;
using static InnovEnergy.Lib.Protocols.Modbus.Clients.Endianness; using InnovEnergy.Lib.Protocols.Modbus.Protocol;
using static InnovEnergy.Lib.Protocols.Modbus.Protocol.MultiRegisterEndianness;
using static InnovEnergy.Lib.Protocols.Modbus.Protocol.RegisterIndexing;
namespace InnovEnergy.Lib.Protocols.Modbus.Clients; namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
@ -13,7 +15,8 @@ public abstract class ModbusClient
{ {
protected ModbusConnection Connection { get; } protected ModbusConnection Connection { get; }
protected Byte SlaveId { get; } protected Byte SlaveId { get; }
protected Endianness Endianness { get; } protected RegisterIndexing RegisterIndexing { get; }
protected MultiRegisterEndianness Endianness { get; }
// TODO: add additional functions: coils... // TODO: add additional functions: coils...
@ -41,12 +44,20 @@ public abstract class ModbusClient
return WriteRegisters(writeAddress, (IReadOnlyList<UInt16>)values); return WriteRegisters(writeAddress, (IReadOnlyList<UInt16>)values);
} }
protected ModbusClient(ModbusConnection connection, Byte slaveId, Endianness endianness = LittleEndian32BitIntegers | LittleEndian32Floats) protected ModbusClient(ModbusConnection connection,
Byte slaveId,
RegisterIndexing registerIndexing = OneBased,
MultiRegisterEndianness endianness = LittleEndian)
{ {
Connection = connection; Connection = connection;
SlaveId = slaveId; SlaveId = slaveId;
RegisterIndexing = registerIndexing;
Endianness = endianness; Endianness = endianness;
} }
public void CloseConnection() => Connection.Close(); public void CloseConnection() => Connection.Close();
protected UInt16 LogicToWire(UInt16 address) => RegisterIndexing.LogicToSerialized(address);
protected UInt16 SerializedToLogic(UInt16 address) => RegisterIndexing.SerializedToLogic(address);
} }

View File

@ -30,7 +30,9 @@ public class ModbusRtuClient : ModbusClient
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues) public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
{ {
var cmd = new ReadInputRegistersCommandFrame(SlaveId, readAddress, nValues); var wireReadAddress = LogicToWire(readAddress);
var cmd = new ReadInputRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
var crc = CalcCrc(cmd); var crc = CalcCrc(cmd);
// TX // TX
@ -54,7 +56,9 @@ public class ModbusRtuClient : ModbusClient
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues) public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
{ {
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, readAddress, nValues); var wireReadAddress = LogicToWire(readAddress);
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
var crc = CalcCrc(cmd.Data); var crc = CalcCrc(cmd.Data);
// TX // TX
@ -82,7 +86,9 @@ public class ModbusRtuClient : ModbusClient
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values) public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
{ {
var cmd = new WriteRegistersCommandFrame(SlaveId, writeAddress, values); var wireWriteAddress = LogicToWire(writeAddress);
var cmd = new WriteRegistersCommandFrame(SlaveId, wireWriteAddress, values);
var crc = CalcCrc(cmd); var crc = CalcCrc(cmd);
var nToRead = cmd.ExpectedResponseSize + CrcSize; var nToRead = cmd.ExpectedResponseSize + CrcSize;
@ -105,9 +111,15 @@ public class ModbusRtuClient : ModbusClient
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite) public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
{ {
var cmd = new ReadWriteRegistersCommandFrame(SlaveId, readAddress, nbToRead, writeAddress, registersToWrite); var wireReadAddress = LogicToWire(readAddress);
var crc = CalcCrc(cmd); var wireWriteAddress = LogicToWire(writeAddress);
var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
wireReadAddress,
nbToRead,
wireWriteAddress,
registersToWrite);
var crc = CalcCrc(cmd);
// TX // TX
cmd.Data.Concat(crc).Apply(Connection.Transmit); cmd.Data.Concat(crc).Apply(Connection.Transmit);

View File

@ -1,10 +1,11 @@
using System.Diagnostics; using System.Diagnostics;
using InnovEnergy.Lib.Protocols.Modbus.Connections; using InnovEnergy.Lib.Protocols.Modbus.Connections;
using InnovEnergy.Lib.Protocols.Modbus.Conversions; using InnovEnergy.Lib.Protocols.Modbus.Conversions;
using InnovEnergy.Lib.Protocols.Modbus.Protocol;
using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Commands;
using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies; using InnovEnergy.Lib.Protocols.Modbus.Protocol.Frames.Replies;
using InnovEnergy.Lib.Protocols.Modbus.Tcp; using InnovEnergy.Lib.Protocols.Modbus.Tcp;
using static InnovEnergy.Lib.Protocols.Modbus.Clients.Endianness; using static InnovEnergy.Lib.Protocols.Modbus.Protocol.MultiRegisterEndianness;
namespace InnovEnergy.Lib.Protocols.Modbus.Clients; namespace InnovEnergy.Lib.Protocols.Modbus.Clients;
@ -20,16 +21,21 @@ public class ModbusTcpClient : ModbusClient
private UInt16 NextId() => unchecked(++_Id); private UInt16 NextId() => unchecked(++_Id);
public ModbusTcpClient(ModbusConnection connection, Byte slaveId, Endianness endianness = LittleEndian32BitIntegers | LittleEndian32Floats) : base(connection, slaveId, endianness) public ModbusTcpClient(ModbusConnection connection,
Byte slaveId,
RegisterIndexing registerIndexing = RegisterIndexing.OneBased,
MultiRegisterEndianness endianness = LittleEndian) : base(connection, slaveId, registerIndexing, endianness)
{ {
} }
public override IReadOnlyList<Boolean> ReadDiscreteInputs(UInt16 readAddress, UInt16 nValues) public override IReadOnlyList<Boolean> ReadDiscreteInputs(UInt16 readAddress, UInt16 nValues)
{ {
var wireReadAddress = LogicToWire(readAddress);
var id = NextId(); // TODO: check response id var id = NextId(); // TODO: check response id
var cmd = new ReadDiscreteInputsCommandFrame(SlaveId, readAddress, nValues); var cmd = new ReadDiscreteInputsCommandFrame(SlaveId, wireReadAddress, nValues);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -46,9 +52,10 @@ public class ModbusTcpClient : ModbusClient
public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues) public override ModbusRegisters ReadInputRegisters(UInt16 readAddress, UInt16 nValues)
{ {
var wireReadAddress = LogicToWire(readAddress);
var id = NextId(); // TODO: check response id var id = NextId(); // TODO: check response id
var cmd = new ReadInputRegistersCommandFrame(SlaveId, readAddress, nValues); var cmd = new ReadInputRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -66,11 +73,14 @@ public class ModbusTcpClient : ModbusClient
} }
public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues) public override ModbusRegisters ReadHoldingRegisters(UInt16 readAddress, UInt16 nValues)
{ {
var id = NextId(); // TODO: check response id var wireReadAddress = LogicToWire(readAddress);
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, readAddress, nValues); var id = NextId(); // TODO: check response id
var cmd = new ReadHoldingRegistersCommandFrame(SlaveId, wireReadAddress, nValues);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -84,14 +94,15 @@ public class ModbusTcpClient : ModbusClient
var verified = cmd.VerifyResponse(rxFrm); var verified = cmd.VerifyResponse(rxFrm);
return new ModbusRegisters(readAddress, verified.RegistersRead.ToArray()); return new ModbusRegisters(readAddress, verified.RegistersRead.ToArray()); // TODO
} }
public override UInt16 WriteMultipleCoils(UInt16 writeAddress, Coils coils) public override UInt16 WriteMultipleCoils(UInt16 writeAddress, Coils coils)
{ {
var id = NextId(); // TODO: check response id var wireWriteAddress = LogicToWire(writeAddress);
var cmd = new WriteCoilsCommandFrame(SlaveId, writeAddress, coils); var id = NextId(); // TODO: check response id
var cmd = new WriteCoilsCommandFrame(SlaveId, wireWriteAddress, coils);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -109,9 +120,10 @@ public class ModbusTcpClient : ModbusClient
public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values) public override UInt16 WriteRegisters(UInt16 writeAddress, UInt16s values)
{ {
var id = NextId(); // TODO: check response id var wireWriteAddress = LogicToWire(writeAddress);
var cmd = new WriteRegistersCommandFrame(SlaveId, writeAddress, values); var id = NextId(); // TODO: check response id
var cmd = new WriteRegistersCommandFrame(SlaveId, wireWriteAddress, values);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -130,9 +142,17 @@ public class ModbusTcpClient : ModbusClient
public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite) public override ModbusRegisters ReadWriteRegisters(UInt16 readAddress, UInt16 nbToRead, UInt16 writeAddress, UInt16s registersToWrite)
{ {
var wireReadAddress = LogicToWire(readAddress);
var wireWriteAddress = LogicToWire(writeAddress);
var id = NextId(); // TODO: check response id var id = NextId(); // TODO: check response id
var cmd = new ReadWriteRegistersCommandFrame(SlaveId, readAddress, nbToRead, writeAddress, registersToWrite); var cmd = new ReadWriteRegistersCommandFrame(SlaveId,
wireReadAddress,
nbToRead,
wireWriteAddress,
registersToWrite);
var hdr = new MbapHeader(id, cmd.Data.Count); var hdr = new MbapHeader(id, cmd.Data.Count);
var frm = new ModbusTcpFrame(hdr, cmd); var frm = new ModbusTcpFrame(hdr, cmd);
@ -146,7 +166,7 @@ public class ModbusTcpClient : ModbusClient
var verified = cmd.VerifyResponse(rxFrm); var verified = cmd.VerifyResponse(rxFrm);
return new ModbusRegisters(readAddress, verified.RegistersRead.ToArray()); return new ModbusRegisters(readAddress, verified.RegistersRead.ToArray()); // TODO
} }
} }