| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 | package modbusimport (	"bytes"	"encoding/binary"	"fmt"	"golib/gnet")const (	ProtocolModbus = 0x0000)const (	FuncCode3  uint8 = 0x03 // FuncCode3 功能码 03 读取多个连续保持寄存器	FuncCode04 uint8 = 0x04 // FuncCode04 功能码 04 读取输入寄存器	FuncCode06 uint8 = 0x06 // FuncCode06 功能码 06 写入单个保持寄存器	FuncCode16 uint8 = 0x10 // FuncCode16 功能码 16 写入多个连续保持寄存器)const (	MinTCPReqSize  = 6	MinTCPRespSize = 9)type TCPRequest struct {	TransactionID uint16 // TransactionID 事务标识符	ProtocolID    uint16 // ProtocolID 协议标识符, 通常情况下为 ProtocolModbus	length        uint16 // length 剩余数据长度, 不包含 TransactionID 和 ProtocolID	UnitID        uint8  // UnitID 单元标识符, 即起设备 ID	FunctionCode  uint8  // FunctionCode 功能码	StartNo       uint16 // StartNo 起始地址	RegisterLen   uint16 // RegisterLen 根据 StartNo 的连续读取或写入的寄存器数量	dataLength    uint8  // DataLength Data 的数据长度	Data          []byte // Data 需要写入的数据}func (m *TCPRequest) Pack() []byte {	b := make([]byte, 12)	gnet.BigEndian.PutUint16(b[0:], m.TransactionID)	gnet.BigEndian.PutUint16(b[2:], m.ProtocolID)	b[6] = m.UnitID	b[7] = m.FunctionCode	gnet.BigEndian.PutUint16(b[8:], m.StartNo)	gnet.BigEndian.PutUint16(b[10:], m.RegisterLen)	if m.FunctionCode == FuncCode16 {		m.length++                        // 加 1 表示多一个 Data 长度字段		m.dataLength = uint8(len(m.Data)) // 补充写入数据大小		b = append(b, m.dataLength)	}	if len(m.Data) > 0 {		b = append(b, m.Data...)	}	// 6 表示从 UnitID 至 RegisterLen 固定长度	m.length = m.length + 6 + uint16(len(m.Data))	gnet.BigEndian.PutUint16(b[4:6], m.length)	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) UnpackRequest(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, gnet.BigEndian, &m.TransactionID); err != nil {		return err	}	if err := binary.Read(buf, gnet.BigEndian, &m.ProtocolID); err != nil {		return err	}	if err := binary.Read(buf, gnet.BigEndian, &m.Length); err != nil {		return err	}	if err := binary.Read(buf, gnet.BigEndian, &m.UnitID); err != nil {		return err	}	if err := binary.Read(buf, gnet.BigEndian, &m.FunctionCode); err != nil {		return err	}	if err := binary.Read(buf, gnet.BigEndian, &m.DataLength); err != nil {		return err	}	m.Data = make([]byte, m.DataLength)	_, err := buf.Read(m.Data)	return err}
 |