package modbus import ( "encoding/binary" "fmt" ) // proto address limit const ( AddressBroadCast = 0 AddressMin = 1 addressMax = 247 ) // AddressMax proto address max limit // you can change with SetSpecialAddressMax, // when your device have address upon addressMax var AddressMax byte = addressMax const ( PduMinSize = 1 // funcCode(1) PduMaxSize = 253 // funcCode(1) + data(252) rtuAduMinSize = 4 // address(1) + funcCode(1) + crc(2) rtuAduMaxSize = 256 // address(1) + PDU(253) + crc(2) asciiAduMinSize = 3 asciiAduMaxSize = 256 asciiCharacterMaxSize = 513 tcpProtocolIdentifier = 0x0000 // Modbus Application Protocol tcpHeaderMbapSize = 7 // MBAP header tcpAduMinSize = 8 // MBAP + funcCode tcpAduMaxSize = 260 ) // proto register limit const ( // ReadBitsQuantityMin Bits ReadBitsQuantityMin = 1 // 0x0001 ReadBitsQuantityMax = 2000 // 0x07d0 WriteBitsQuantityMin = 1 // 1 WriteBitsQuantityMax = 1968 // 0x07b0 // ReadRegQuantityMin 16 Bits ReadRegQuantityMin = 1 // 1 ReadRegQuantityMax = 125 // 0x007d WriteRegQuantityMin = 1 // 1 WriteRegQuantityMax = 123 // 0x007b ReadWriteOnReadRegQuantityMin = 1 // 1 ReadWriteOnReadRegQuantityMax = 125 // 0x007d ReadWriteOnWriteRegQuantityMin = 1 // 1 ReadWriteOnWriteRegQuantityMax = 121 // 0x0079 ) // Function Code const ( // FuncCodeReadDiscreteInputs Bit access FuncCodeReadDiscreteInputs = 2 //读离散量输入 FuncCodeReadCoils = 1 //读线圈 FuncCodeWriteSingleCoil = 5 //写单个线圈 FuncCodeWriteMultipleCoils = 15 // 写多个线圈 // FuncCodeReadInputRegisters 16-bit access FuncCodeReadInputRegisters = 4 //读输入寄存器 FuncCodeReadHoldingRegisters = 3 //读保持寄存器 FuncCodeWriteSingleRegister = 6 //写单个寄存器 FuncCodeWriteMultipleRegisters = 16 //写多个寄存器 FuncCodeReadWriteMultipleRegisters = 23 FuncCodeMaskWriteRegister = 22 FuncCodeReadFIFOQueue = 24 FuncCodeOtherReportSlaveID = 17 // FuncCodeDiagReadException = 7 // FuncCodeDiagDiagnostic = 8 // FuncCodeDiagGetComEventCnt = 11 // FuncCodeDiagGetComEventLog = 12 ) // Exception Code const ( ExceptionCodeIllegalFunction = 1 ExceptionCodeIllegalDataAddress = 2 ExceptionCodeIllegalDataValue = 3 ExceptionCodeServerDeviceFailure = 4 ExceptionCodeAcknowledge = 5 ExceptionCodeServerDeviceBusy = 6 ExceptionCodeNegativeAcknowledge = 7 ExceptionCodeMemoryParityError = 8 ExceptionCodeGatewayPathUnavailable = 10 ExceptionCodeGatewayTargetDeviceFailedToRespond = 11 ) // ExceptionError implements error interface. type ExceptionError struct { ExceptionCode byte } // Error converts known modbus exception code to error message. func (e *ExceptionError) Error() string { var name string switch e.ExceptionCode { case ExceptionCodeIllegalFunction: name = "illegal function" case ExceptionCodeIllegalDataAddress: name = "illegal data address" case ExceptionCodeIllegalDataValue: name = "illegal data value" case ExceptionCodeServerDeviceFailure: name = "server device failure" case ExceptionCodeAcknowledge: name = "acknowledge" case ExceptionCodeServerDeviceBusy: name = "server device busy" case ExceptionCodeNegativeAcknowledge: name = "Negative Acknowledge" case ExceptionCodeMemoryParityError: name = "memory parity error" case ExceptionCodeGatewayPathUnavailable: name = "gateway path unavailable" case ExceptionCodeGatewayTargetDeviceFailedToRespond: name = "gateway target device failed to respond" default: name = "unknown" } return fmt.Sprintf("modbus: exception '%v' (%s)", e.ExceptionCode, name) } // CalculateResponseLength modbus RTU 响应长度 func CalculateResponseLength(adu []byte) int { length := rtuAduMinSize switch adu[1] { case FuncCodeReadDiscreteInputs, FuncCodeReadCoils: count := int(binary.BigEndian.Uint16(adu[4:])) length += 1 + count/8 if count%8 != 0 { length++ } case FuncCodeReadInputRegisters, FuncCodeReadHoldingRegisters, FuncCodeReadWriteMultipleRegisters: count := int(binary.BigEndian.Uint16(adu[4:])) length += 1 + count*2 case FuncCodeWriteSingleCoil, FuncCodeWriteMultipleCoils, FuncCodeWriteSingleRegister, FuncCodeWriteMultipleRegisters: length += 4 case FuncCodeMaskWriteRegister: length += 6 case FuncCodeReadFIFOQueue: // undetermined default: } return length }