-
Notifications
You must be signed in to change notification settings - Fork 15
/
EnronModbus.cs
129 lines (114 loc) · 4.62 KB
/
EnronModbus.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using Modbus.Device;
using Modbus.Utility;
namespace Modbus.Extensions.Enron
{
/// <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("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("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("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("master");
if (data == null)
throw new ArgumentNullException("data");
if (data.Length == 0 || data.Length > 61)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture,
"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>
internal 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>
internal static IEnumerable<uint> Convert(ushort[] registers)
{
for (int i = 0; i < registers.Length; i++)
{
yield return ModbusUtility.GetUInt32(registers[i], registers[i + 1]);
i++;
}
}
internal static void ValidateNumberOfPoints(ushort numberOfPoints, ushort maxNumberOfPoints)
{
if (numberOfPoints < 1 || numberOfPoints > maxNumberOfPoints)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture,
"Argument numberOfPoints must be between 1 and {0} inclusive.",
maxNumberOfPoints));
}
}
}
}