| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 | package modbusimport (	"bytes"	"encoding/binary"	"fmt")const (	FuncCode3  uint8 = 0x03 // FuncCode3 功能码 3 读取多个连续保持寄存器	FuncCode16 uint8 = 0x10 // FuncCode16 功能码 16 写入多个连续保持寄存器)const (	MinTCPReqSize  = 6	MinTCPRespSize = 9)type TCPRequest struct {	TransactionID uint16 // TransactionID 事务标识符	ProtocolID    uint16 // ProtocolID 协议标识符, 通常情况下为 0x0000	length        uint16 // length 数据长度, 不包含 TransactionID 和 ProtocolID	UnitID        uint8  // UnitID 单元标识符, 即起设备 ID	FunctionCode  uint8  // FunctionCode 功能码	StartNo       uint16 // StartNo 起始地址	RegisterLen   uint16 // RegisterLen 根据 StartNo 的连续读取或写入的寄存器数量	Data          []byte // Data 需要写入的数据}func (m *TCPRequest) Pack() []byte {	b := make([]byte, 12+len(m.Data))	binary.BigEndian.PutUint16(b[0:], m.TransactionID)	binary.BigEndian.PutUint16(b[2:], m.ProtocolID)	binary.BigEndian.PutUint16(b[4:], m.length)	m.length = MinTCPReqSize + uint16(len(m.Data))	b[5] = m.UnitID	b[6] = m.FunctionCode	binary.BigEndian.PutUint16(b[7:], m.StartNo)	binary.BigEndian.PutUint16(b[9:], m.RegisterLen)	if m.length > MinTCPReqSize {		copy(b[12:], m.Data)	}	return b}type TCPResponse struct {	TransactionID uint16 // TransactionID 事务标识符	ProtocolID    uint16 // ProtocolID 协议标识符, 通常情况下为 0x0000	Length        uint16 // Length 数据长度, 不包含 TransactionID 和 ProtocolID	UnitID        uint8  // UnitID 单元标识符, 即起设备 ID	FunctionCode  uint8  // FunctionCode 功能码	DataLength    uint8  // DataLength Data 的数据长度	Data          []byte // Data 返回的数据}func (m *TCPResponse) UnpackWithRequest(b []byte, r *TCPRequest) error {	if err := m.Unpack(b); err != nil {		return err	}	if r.TransactionID != m.TransactionID {		return fmt.Errorf("TransactionID: request is not equal to that of the response")	}	if r.ProtocolID != m.ProtocolID {		return fmt.Errorf("ProtocolID: request is not equal to that of the response")	}	if r.FunctionCode != m.FunctionCode {		return fmt.Errorf("FunctionCode: request is not equal to that of the response")	}	return nil}func (m *TCPResponse) Unpack(b []byte) error {	if len(b) < MinTCPRespSize {		return fmt.Errorf("data too short: %d", len(b))	}	buf := bytes.NewReader(b)	if err := binary.Read(buf, binary.BigEndian, &m.TransactionID); err != nil {		return err	}	if err := binary.Read(buf, binary.BigEndian, &m.ProtocolID); err != nil {		return err	}	if err := binary.Read(buf, binary.BigEndian, &m.Length); err != nil {		return err	}	// UnitID 使用小端模式读取	if err := binary.Read(buf, binary.LittleEndian, &m.UnitID); err != nil {		return err	}	// FunctionCode 使用小端模式读取	if err := binary.Read(buf, binary.LittleEndian, &m.FunctionCode); err != nil {		return err	}	if err := binary.Read(buf, binary.BigEndian, &m.DataLength); err != nil {		return err	}	m.Data = make([]byte, buf.Len())	_, err := buf.Read(m.Data)	return err}
 |