common.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package modbus
  2. import (
  3. "encoding/binary"
  4. "fmt"
  5. )
  6. // proto address limit
  7. const (
  8. AddressBroadCast = 0
  9. AddressMin = 1
  10. addressMax = 247
  11. )
  12. // AddressMax proto address max limit
  13. // you can change with SetSpecialAddressMax,
  14. // when your device have address upon addressMax
  15. var AddressMax byte = addressMax
  16. const (
  17. PduMinSize = 1 // funcCode(1)
  18. PduMaxSize = 253 // funcCode(1) + data(252)
  19. rtuAduMinSize = 4 // address(1) + funcCode(1) + crc(2)
  20. rtuAduMaxSize = 256 // address(1) + PDU(253) + crc(2)
  21. asciiAduMinSize = 3
  22. asciiAduMaxSize = 256
  23. asciiCharacterMaxSize = 513
  24. tcpProtocolIdentifier = 0x0000
  25. // Modbus Application Protocol
  26. tcpHeaderMbapSize = 7 // MBAP header
  27. tcpAduMinSize = 8 // MBAP + funcCode
  28. tcpAduMaxSize = 260
  29. )
  30. // proto register limit
  31. const (
  32. // ReadBitsQuantityMin Bits
  33. ReadBitsQuantityMin = 1 // 0x0001
  34. ReadBitsQuantityMax = 2000 // 0x07d0
  35. WriteBitsQuantityMin = 1 // 1
  36. WriteBitsQuantityMax = 1968 // 0x07b0
  37. // ReadRegQuantityMin 16 Bits
  38. ReadRegQuantityMin = 1 // 1
  39. ReadRegQuantityMax = 125 // 0x007d
  40. WriteRegQuantityMin = 1 // 1
  41. WriteRegQuantityMax = 123 // 0x007b
  42. ReadWriteOnReadRegQuantityMin = 1 // 1
  43. ReadWriteOnReadRegQuantityMax = 125 // 0x007d
  44. ReadWriteOnWriteRegQuantityMin = 1 // 1
  45. ReadWriteOnWriteRegQuantityMax = 121 // 0x0079
  46. )
  47. // Function Code
  48. const (
  49. // FuncCodeReadDiscreteInputs Bit access
  50. FuncCodeReadDiscreteInputs = 2 //读离散量输入
  51. FuncCodeReadCoils = 1 //读线圈
  52. FuncCodeWriteSingleCoil = 5 //写单个线圈
  53. FuncCodeWriteMultipleCoils = 15 // 写多个线圈
  54. // FuncCodeReadInputRegisters 16-bit access
  55. FuncCodeReadInputRegisters = 4 //读输入寄存器
  56. FuncCodeReadHoldingRegisters = 3 //读保持寄存器
  57. FuncCodeWriteSingleRegister = 6 //写单个寄存器
  58. FuncCodeWriteMultipleRegisters = 16 //写多个寄存器
  59. FuncCodeReadWriteMultipleRegisters = 23
  60. FuncCodeMaskWriteRegister = 22
  61. FuncCodeReadFIFOQueue = 24
  62. FuncCodeOtherReportSlaveID = 17
  63. // FuncCodeDiagReadException = 7
  64. // FuncCodeDiagDiagnostic = 8
  65. // FuncCodeDiagGetComEventCnt = 11
  66. // FuncCodeDiagGetComEventLog = 12
  67. )
  68. // Exception Code
  69. const (
  70. ExceptionCodeIllegalFunction = 1
  71. ExceptionCodeIllegalDataAddress = 2
  72. ExceptionCodeIllegalDataValue = 3
  73. ExceptionCodeServerDeviceFailure = 4
  74. ExceptionCodeAcknowledge = 5
  75. ExceptionCodeServerDeviceBusy = 6
  76. ExceptionCodeNegativeAcknowledge = 7
  77. ExceptionCodeMemoryParityError = 8
  78. ExceptionCodeGatewayPathUnavailable = 10
  79. ExceptionCodeGatewayTargetDeviceFailedToRespond = 11
  80. )
  81. // ExceptionError implements error interface.
  82. type ExceptionError struct {
  83. ExceptionCode byte
  84. }
  85. // Error converts known modbus exception code to error message.
  86. func (e *ExceptionError) Error() string {
  87. var name string
  88. switch e.ExceptionCode {
  89. case ExceptionCodeIllegalFunction:
  90. name = "illegal function"
  91. case ExceptionCodeIllegalDataAddress:
  92. name = "illegal data address"
  93. case ExceptionCodeIllegalDataValue:
  94. name = "illegal data value"
  95. case ExceptionCodeServerDeviceFailure:
  96. name = "server device failure"
  97. case ExceptionCodeAcknowledge:
  98. name = "acknowledge"
  99. case ExceptionCodeServerDeviceBusy:
  100. name = "server device busy"
  101. case ExceptionCodeNegativeAcknowledge:
  102. name = "Negative Acknowledge"
  103. case ExceptionCodeMemoryParityError:
  104. name = "memory parity error"
  105. case ExceptionCodeGatewayPathUnavailable:
  106. name = "gateway path unavailable"
  107. case ExceptionCodeGatewayTargetDeviceFailedToRespond:
  108. name = "gateway target device failed to respond"
  109. default:
  110. name = "unknown"
  111. }
  112. return fmt.Sprintf("modbus: exception '%v' (%s)", e.ExceptionCode, name)
  113. }
  114. // CalculateResponseLength modbus RTU 响应长度
  115. func CalculateResponseLength(adu []byte) int {
  116. length := rtuAduMinSize
  117. switch adu[1] {
  118. case FuncCodeReadDiscreteInputs,
  119. FuncCodeReadCoils:
  120. count := int(binary.BigEndian.Uint16(adu[4:]))
  121. length += 1 + count/8
  122. if count%8 != 0 {
  123. length++
  124. }
  125. case FuncCodeReadInputRegisters,
  126. FuncCodeReadHoldingRegisters,
  127. FuncCodeReadWriteMultipleRegisters:
  128. count := int(binary.BigEndian.Uint16(adu[4:]))
  129. length += 1 + count*2
  130. case FuncCodeWriteSingleCoil,
  131. FuncCodeWriteMultipleCoils,
  132. FuncCodeWriteSingleRegister,
  133. FuncCodeWriteMultipleRegisters:
  134. length += 4
  135. case FuncCodeMaskWriteRegister:
  136. length += 6
  137. case FuncCodeReadFIFOQueue:
  138. // undetermined
  139. default:
  140. }
  141. return length
  142. }