namespace Modbus.Extensions.Enron { using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using Device; using Utility; /// /// Utility extensions for the Enron Modbus dialect. /// public static class EnronModbus { /// /// Read contiguous block of 32 bit 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 ModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { if (master == null) { throw new ArgumentNullException(nameof(master)); } ValidateNumberOfPoints(numberOfPoints, 62); // read 16 bit chunks and perform conversion var rawRegisters = master.ReadHoldingRegisters( slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return Convert(rawRegisters).ToArray(); } /// /// Read contiguous block of 32 bit input registers. /// /// 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 ModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints) { if (master == null) { throw new ArgumentNullException(nameof(master)); } ValidateNumberOfPoints(numberOfPoints, 62); var rawRegisters = master.ReadInputRegisters( slaveAddress, startAddress, (ushort)(numberOfPoints * 2)); return Convert(rawRegisters).ToArray(); } /// /// 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 ModbusMaster 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 ModbusMaster master, byte slaveAddress, ushort startAddress, uint[] data) { if (master == null) { throw new ArgumentNullException(nameof(master)); } if (data == null) { throw new ArgumentNullException(nameof(data)); } if (data.Length == 0 || data.Length > 61) { throw new ArgumentException("The length of argument data must be between 1 and 61 inclusive."); } master.WriteMultipleRegisters(slaveAddress, startAddress, Convert(data).ToArray()); } /// /// Convert the 32 bit registers to two 16 bit values. /// private static IEnumerable Convert(uint[] registers) { foreach (var register in registers) { // low order value yield return BitConverter.ToUInt16(BitConverter.GetBytes(register), 0); // high order value yield return BitConverter.ToUInt16(BitConverter.GetBytes(register), 2); } } /// /// Convert the 16 bit registers to 32 bit registers. /// private static IEnumerable Convert(ushort[] registers) { for (int i = 0; i < registers.Length; i++) { yield return ModbusUtility.GetUInt32(registers[i + 1], registers[i]); i++; } } private static void ValidateNumberOfPoints(ushort numberOfPoints, ushort maxNumberOfPoints) { if (numberOfPoints < 1 || numberOfPoints > maxNumberOfPoints) { string msg = $"Argument numberOfPoints must be between 1 and {maxNumberOfPoints} inclusive."; throw new ArgumentException(msg); } } } }