EnronModbus.cs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. using System;
  2. using System.Linq;
  3. using System.Threading.Tasks;
  4. namespace NModbus.Extensions.Enron
  5. {
  6. /// <summary>
  7. /// Utility extensions for the Enron Modbus dialect.
  8. /// </summary>
  9. public static class EnronModbus
  10. {
  11. /// <summary>
  12. /// Reads contiguous block of input registers with 32 bit register size.
  13. /// </summary>
  14. /// <param name="master">The Modbus master.</param>
  15. /// <param name="slaveAddress">Address of device to read values from.</param>
  16. /// <param name="startAddress">Address to begin reading.</param>
  17. /// <param name="numberOfPoints">Number of holding registers to read.</param>
  18. /// <returns>Input registers status.</returns>
  19. public static uint[] ReadInputRegisters32(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
  20. {
  21. var registers = master.ReadInputRegisters(slaveAddress, startAddress, (ushort)(numberOfPoints * 2));
  22. return ConvertTo32(registers);
  23. }
  24. /// <summary>
  25. /// Reads contiguous block of holding registers.
  26. /// </summary>
  27. /// <param name="master">The Modbus master.</param>
  28. /// <param name="slaveAddress">Address of device to read values from.</param>
  29. /// <param name="startAddress">Address to begin reading.</param>
  30. /// <param name="numberOfPoints">Number of holding registers to read.</param>
  31. /// <returns>Holding registers status.</returns>
  32. public static uint[] ReadHoldingRegisters32(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
  33. {
  34. var registers = master.ReadHoldingRegisters(slaveAddress, startAddress, (ushort)(numberOfPoints * 2));
  35. return ConvertTo32(registers);
  36. }
  37. /// <summary>
  38. /// Asynchronously reads contiguous block of input registers with 32 bit register size.
  39. /// </summary>
  40. /// <param name="master">The Modbus master.</param>
  41. /// <param name="slaveAddress">Address of device to read values from.</param>
  42. /// <param name="startAddress">Address to begin reading.</param>
  43. /// <param name="numberOfPoints">Number of holding registers to read.</param>
  44. /// <returns>A task that represents the asynchronous read operation.</returns>
  45. public static async Task<uint[]> ReadInputRegisters32Async(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
  46. {
  47. var registers = await master.ReadInputRegistersAsync(slaveAddress, startAddress, (ushort)(numberOfPoints * 2));
  48. return ConvertTo32(registers);
  49. }
  50. /// <summary>
  51. /// Asynchronously reads contiguous block of holding registers.
  52. /// </summary>
  53. /// <param name="master">The Modbus master.</param>
  54. /// <param name="slaveAddress">Address of device to read values from.</param>
  55. /// <param name="startAddress">Address to begin reading.</param>
  56. /// <param name="numberOfPoints">Number of holding registers to read.</param>
  57. /// <returns>A task that represents the asynchronous read operation.</returns>
  58. public static async Task<uint[]> ReadHoldingRegisters32Async(this IModbusMaster master, byte slaveAddress, ushort startAddress, ushort numberOfPoints)
  59. {
  60. var registers = await master.ReadHoldingRegistersAsync(slaveAddress, startAddress, (ushort)(numberOfPoints * 2));
  61. return ConvertTo32(registers);
  62. }
  63. /// <summary>
  64. /// Write a single 16 bit holding register.
  65. /// </summary>
  66. /// <param name="master">The Modbus master.</param>
  67. /// <param name="slaveAddress">Address of the device to write to.</param>
  68. /// <param name="registerAddress">Address to write.</param>
  69. /// <param name="value">Value to write.</param>
  70. public static void WriteSingleRegister32(
  71. this IModbusMaster master,
  72. byte slaveAddress,
  73. ushort registerAddress,
  74. uint value)
  75. {
  76. if (master == null) throw new ArgumentNullException(nameof(master));
  77. master.WriteMultipleRegisters32(slaveAddress, registerAddress, new[] { value });
  78. }
  79. /// <summary>
  80. /// Write a block of contiguous 32 bit holding registers.
  81. /// </summary>
  82. /// <param name="master">The Modbus master.</param>
  83. /// <param name="slaveAddress">Address of the device to write to.</param>
  84. /// <param name="startAddress">Address to begin writing values.</param>
  85. /// <param name="data">Values to write.</param>
  86. public static void WriteMultipleRegisters32(
  87. this IModbusMaster master,
  88. byte slaveAddress,
  89. ushort startAddress,
  90. uint[] data)
  91. {
  92. if (master == null) throw new ArgumentNullException(nameof(master));
  93. if (data == null) throw new ArgumentNullException(nameof(data));
  94. master.WriteMultipleRegisters(slaveAddress, startAddress, ConvertFrom32(data).ToArray());
  95. }
  96. /// <summary> Convert the 32 bit registers to two 16 bit values. </summary>
  97. public static ushort[] ConvertFrom32(uint[] registers)
  98. {
  99. var result = new ushort[registers.Length * 2];
  100. var index = 0;
  101. foreach (var register in registers)
  102. {
  103. var bytes = BitConverter.GetBytes(register);
  104. // low order value
  105. result[index++] = BitConverter.ToUInt16(bytes, 2);
  106. // high order value
  107. result[index++] = BitConverter.ToUInt16(bytes, 0);
  108. }
  109. return result;
  110. }
  111. /// <summary> Convert the double 16 bit registers to single 32 bit values. </summary>
  112. public static uint[] ConvertTo32(ushort[] registers)
  113. {
  114. if (registers.Length % 2 != 0)
  115. throw new ArgumentException("registers must have an even number of elements.", nameof(registers));
  116. var numberOfResult = registers.Length / 2;
  117. var result = new uint[numberOfResult];
  118. for(var index = 0; index < numberOfResult; index++)
  119. {
  120. result[index] = ((uint)registers[index * 2]) << 16 | registers[(index * 2) + 1];
  121. }
  122. return result;
  123. }
  124. }
  125. }