| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 | 
							- package modbus
 
- import (
 
- 	"bytes"
 
- 	"encoding/binary"
 
- 	"fmt"
 
- 	"golib/v2/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
 
- }
 
 
  |