ModbusMessageImpl.cs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics.CodeAnalysis;
  4. using System.IO;
  5. using System.Net;
  6. using NModbus.Data;
  7. namespace NModbus.Message
  8. {
  9. /// <summary>
  10. /// Class holding all implementation shared between two or more message types.
  11. /// Interfaces expose subsets of type specific implementations.
  12. /// </summary>
  13. internal class ModbusMessageImpl
  14. {
  15. // smallest supported message frame size (sans checksum)
  16. private const int MinimumFrameSize = 2;
  17. public ModbusMessageImpl()
  18. {
  19. }
  20. public ModbusMessageImpl(byte slaveAddress, byte functionCode)
  21. {
  22. SlaveAddress = slaveAddress;
  23. FunctionCode = functionCode;
  24. }
  25. public byte? ByteCount { get; set; }
  26. public byte? ExceptionCode { get; set; }
  27. public ushort TransactionId { get; set; }
  28. public byte FunctionCode { get; set; }
  29. public ushort? NumberOfPoints { get; set; }
  30. public byte SlaveAddress { get; set; }
  31. public ushort? StartAddress { get; set; }
  32. public ushort? SubFunctionCode { get; set; }
  33. [AllowNull]
  34. public IModbusMessageDataCollection Data { get; set; }
  35. public byte[] MessageFrame
  36. {
  37. get
  38. {
  39. var pdu = ProtocolDataUnit;
  40. var frame = new MemoryStream(1 + pdu.Length);
  41. frame.WriteByte(SlaveAddress);
  42. frame.Write(pdu, 0, pdu.Length);
  43. return frame.ToArray();
  44. }
  45. }
  46. public byte[] ProtocolDataUnit
  47. {
  48. get
  49. {
  50. List<byte> pdu = new List<byte>();
  51. pdu.Add(FunctionCode);
  52. if (ExceptionCode.HasValue)
  53. {
  54. pdu.Add(ExceptionCode.Value);
  55. }
  56. if (SubFunctionCode.HasValue)
  57. {
  58. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)SubFunctionCode.Value)));
  59. }
  60. if (StartAddress.HasValue)
  61. {
  62. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)StartAddress.Value)));
  63. }
  64. if (NumberOfPoints.HasValue)
  65. {
  66. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)NumberOfPoints.Value)));
  67. }
  68. if (ByteCount.HasValue)
  69. {
  70. pdu.Add(ByteCount.Value);
  71. }
  72. if (Data != null)
  73. {
  74. pdu.AddRange(Data.NetworkBytes);
  75. }
  76. return pdu.ToArray();
  77. }
  78. }
  79. public void Initialize(byte[] frame)
  80. {
  81. if (frame == null)
  82. {
  83. throw new ArgumentNullException(nameof(frame), "Argument frame cannot be null.");
  84. }
  85. if (frame.Length < MinimumFrameSize)
  86. {
  87. string msg = $"Message frame must contain at least {MinimumFrameSize} bytes of data.";
  88. throw new FormatException(msg);
  89. }
  90. SlaveAddress = frame[0];
  91. FunctionCode = frame[1];
  92. }
  93. }
  94. }