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);
}
}
}
}