using System; using System.Linq; using System.Threading.Tasks; namespace NModbus.Extensions.Enron { /// /// Utility extensions for the Enron Modbus dialect. /// public static class EnronModbus { /// /// Reads contiguous block of input registers with 32 bit register size. /// /// The Modbus master. /// Address of device to read values from. /// Address to begin reading. /// Number of holding registers to read. /// Input registers status. public static uint[] ReadInputRegisters32(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { var registers = master.ReadInputRegisters(slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return ConvertTo32(registers); } /// /// Reads contiguous block of holding registers. /// /// The Modbus master. /// Address of device to read values from. /// Address to begin reading. /// Number of holding registers to read. /// Holding registers status. public static uint[] ReadHoldingRegisters32(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { var registers = master.ReadHoldingRegisters(slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return ConvertTo32(registers); } /// /// Asynchronously reads contiguous block of input registers with 32 bit register size. /// /// The Modbus master. /// Address of device to read values from. /// Address to begin reading. /// Number of holding registers to read. /// A task that represents the asynchronous read operation. public static async Task ReadInputRegisters32Async(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { var registers = await master.ReadInputRegistersAsync(slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return ConvertTo32(registers); } /// /// Asynchronously reads contiguous block of holding registers. /// /// The Modbus master. /// Address of device to read values from. /// Address to begin reading. /// Number of holding registers to read. /// A task that represents the asynchronous read operation. public static async Task ReadHoldingRegisters32Async(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { var registers = await master.ReadHoldingRegistersAsync(slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return ConvertTo32(registers); } /// /// Write a single 16 bit holding register. /// /// The Modbus master. /// Address of the device to write to. /// Address to write. /// Value to write. public static void WriteSingleRegister32( this IModbusMaster master, byte slaveAddress, ushort registerAddress, uint value) { if (master == null) throw new ArgumentNullException(nameof(master)); master.WriteMultipleRegisters32(slaveAddress, registerAddress, new[] { value }); } /// /// Write a block of contiguous 32 bit holding registers. /// /// The Modbus master. /// Address of the device to write to. /// Address to begin writing values. /// Values to write. public static void WriteMultipleRegisters32( this IModbusMaster master, byte slaveAddress, ushort startAddress, uint[] data) { if (master == null) throw new ArgumentNullException(nameof(master)); if (data == null) throw new ArgumentNullException(nameof(data)); master.WriteMultipleRegisters(slaveAddress, startAddress, ConvertFrom32(data).ToArray()); } /// Convert the 32 bit registers to two 16 bit values. public static ushort[] ConvertFrom32(uint[] registers) { var result = new ushort[registers.Length * 2]; var index = 0; foreach (var register in registers) { var bytes = BitConverter.GetBytes(register); // low order value result[index++] = BitConverter.ToUInt16(bytes, 2); // high order value result[index++] = BitConverter.ToUInt16(bytes, 0); } return result; } /// Convert the double 16 bit registers to single 32 bit values. public static uint[] ConvertTo32(ushort[] registers) { if (registers.Length % 2 != 0) throw new ArgumentException("registers must have an even number of elements.", nameof(registers)); var numberOfResult = registers.Length / 2; var result = new uint[numberOfResult]; for(var index = 0; index < numberOfResult; index++) { result[index] = ((uint)registers[index * 2]) << 16 | registers[(index * 2) + 1]; } return result; } } }