ModbusMessageImpl.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  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. #if NET5_0_OR_GREATER
  34. [AllowNull]
  35. #endif
  36. public IModbusMessageDataCollection Data { get; set; }
  37. public byte[] MessageFrame
  38. {
  39. get
  40. {
  41. var pdu = ProtocolDataUnit;
  42. var frame = new MemoryStream(1 + pdu.Length);
  43. frame.WriteByte(SlaveAddress);
  44. frame.Write(pdu, 0, pdu.Length);
  45. return frame.ToArray();
  46. }
  47. }
  48. public byte[] ProtocolDataUnit
  49. {
  50. get
  51. {
  52. List<byte> pdu = new List<byte>();
  53. pdu.Add(FunctionCode);
  54. if (ExceptionCode.HasValue)
  55. {
  56. pdu.Add(ExceptionCode.Value);
  57. }
  58. if (SubFunctionCode.HasValue)
  59. {
  60. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)SubFunctionCode.Value)));
  61. }
  62. if (StartAddress.HasValue)
  63. {
  64. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)StartAddress.Value)));
  65. }
  66. if (NumberOfPoints.HasValue)
  67. {
  68. pdu.AddRange(BitConverter.GetBytes(IPAddress.HostToNetworkOrder((short)NumberOfPoints.Value)));
  69. }
  70. if (ByteCount.HasValue)
  71. {
  72. pdu.Add(ByteCount.Value);
  73. }
  74. if (Data != null)
  75. {
  76. pdu.AddRange(Data.NetworkBytes);
  77. }
  78. return pdu.ToArray();
  79. }
  80. }
  81. public void Initialize(byte[] frame)
  82. {
  83. if (frame == null)
  84. {
  85. throw new ArgumentNullException(nameof(frame), "Argument frame cannot be null.");
  86. }
  87. if (frame.Length < MinimumFrameSize)
  88. {
  89. string msg = $"Message frame must contain at least {MinimumFrameSize} bytes of data.";
  90. throw new FormatException(msg);
  91. }
  92. SlaveAddress = frame[0];
  93. FunctionCode = frame[1];
  94. }
  95. }
  96. }