iotgateway/Plugins/Drivers/PLC.ModBusMaster/NModbus4/Extensions/Enron/EnronModbus.cs

164 lines
5.6 KiB
C#
Raw Normal View History

namespace Modbus.Extensions.Enron
{
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Device;
using Utility;
/// <summary>
/// Utility extensions for the Enron Modbus dialect.
/// </summary>
public static class EnronModbus
{
/// <summary>
/// Read contiguous block of 32 bit holding registers.
/// </summary>
/// <param name="master">The Modbus master.</param>
/// <param name="slaveAddress">Address of device to read values from.</param>
/// <param name="startAddress">Address to begin reading.</param>
/// <param name="numberOfPoints">Number of holding registers to read.</param>
/// <returns>Holding registers status</returns>
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();
}
/// <summary>
/// Read contiguous block of 32 bit input registers.
/// </summary>
/// <param name="master">The Modbus master.</param>
/// <param name="slaveAddress">Address of device to read values from.</param>
/// <param name="startAddress">Address to begin reading.</param>
/// <param name="numberOfPoints">Number of holding registers to read.</param>
/// <returns>Input registers status</returns>
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();
}
/// <summary>
/// Write a single 16 bit holding register.
/// </summary>
/// <param name="master">The Modbus master.</param>
/// <param name="slaveAddress">Address of the device to write to.</param>
/// <param name="registerAddress">Address to write.</param>
/// <param name="value">Value to write.</param>
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 });
}
/// <summary>
/// Write a block of contiguous 32 bit holding registers.
/// </summary>
/// <param name="master">The Modbus master.</param>
/// <param name="slaveAddress">Address of the device to write to.</param>
/// <param name="startAddress">Address to begin writing values.</param>
/// <param name="data">Values to write.</param>
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());
}
/// <summary>
/// Convert the 32 bit registers to two 16 bit values.
/// </summary>
private static IEnumerable<ushort> 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);
}
}
/// <summary>
/// Convert the 16 bit registers to 32 bit registers.
/// </summary>
private static IEnumerable<uint> 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);
}
}
}
}