| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600 | package gnetimport (	"bytes"	"encoding/binary"	"encoding/hex"	"encoding/xml"	"errors"	"math"	"strings")type Byte bytefunc (b Byte) Hex() string {	return hex.EncodeToString([]byte{byte(b)})}func (b Byte) String() string {	return string(b)}//goland:noinspection ALLtype Bytes []byte// Prepend 将 p 添加到 Bytes 前面////goland:noinspection ALLfunc (b Bytes) Prepend(p ...byte) Bytes {	return append(p, b...)}// Append 将 p 添加到 Bytes 后面////goland:noinspection ALLfunc (b Bytes) Append(p ...byte) Bytes {	return append(b, p...)}// AppendStr 将 s 转换成 []byte 后添加到 Bytes 后面////goland:noinspection ALLfunc (b Bytes) AppendStr(s string) Bytes {	return append(b, []byte(s)...)}// From 从 Bytes 返回第 i 个字节////goland:noinspection ALLfunc (b Bytes) From(i int) Byte {	return Byte(b[i])}// Trim 循环 p 并将其从 Bytes 中移除////goland:noinspection ALLfunc (b Bytes) Trim(p ...[]byte) Bytes {	np := b	for _, x := range p {		bytes.ReplaceAll(b, x, nil)	}	return np}// TrimStr 循环 s 并将其转换为 []byte 后从 Bytes 中移除////goland:noinspection ALLfunc (b Bytes) TrimStr(s ...string) Bytes {	ns := b	for _, x := range s {		ns = bytes.ReplaceAll(b, []byte(x), nil)	}	return ns}// TrimNUL 移除 b 字符串内的 NUL 符号// 参考 https://stackoverflow.com/questions/54285346/remove-null-character-from-string////goland:noinspection ALLfunc (b Bytes) TrimNUL() Bytes {	return bytes.ReplaceAll(b, []byte{'\x00'}, nil)}// TrimEnter 移除 b 字符串内的回车符号////goland:noinspection ALLfunc (b Bytes) TrimEnter() Bytes {	return bytes.ReplaceAll(b, []byte{'\r'}, nil)}// Remake 将 b 重新分配并返回新的变量////goland:noinspection ALLfunc (b Bytes) Remake() Bytes {	if len(b) == 0 {		return []byte{}	}	n := make([]byte, len(b))	for i := 0; i < len(b); i++ {		n[i] = b[i]	}	return n}// Equal 与 dst 进行比较////goland:noinspection ALLfunc (b Bytes) Equal(dst Bytes) bool {	if len(b) != len(dst) {		return false	}	return bytes.Equal(b.Remake(), dst.Remake())}// CRC16 使用 Bytes 创建用于 Modbus/TCP 协议 2 个字节的 CRC 校验码(CRC16)// 具体应用时需要使用 BigEndian (大端模式) 或 LittleEndian 转换////goland:noinspection ALLfunc (b Bytes) CRC16() uint16 {	var crc uint16 = 0xFFFF	for _, n := range b {		crc ^= uint16(n)		for i := 0; i < 8; i++ {			if crc&1 != 0 {				crc >>= 1				crc ^= 0xA001			} else {				crc >>= 1			}		}	}	return crc}// Hex 返回不包含空格的 hex////goland:noinspection ALLfunc (b Bytes) Hex() string {	if len(b) <= 0 {		return ""	}	return hex.EncodeToString(b)}// HexTo 返回包含空格的 hex////goland:noinspection ALLfunc (b Bytes) HexTo() string {	if len(b) <= 0 {		return ""	}	src := b.Hex()	dst := strings.Builder{}	for i := 0; i < len(src); i++ {		dst.WriteByte(src[i])		if i%2 == 1 && len(src)-1 != i {			dst.WriteByte(32)		}	}	return dst.String()}//goland:noinspection ALLfunc (b Bytes) Bytes() []byte {	return b}//goland:noinspection ALLfunc (b Bytes) String() string {	return string(b)}//goland:noinspection ALLfunc (b Bytes) ToString() String {	return String(b)}//goland:noinspection ALLfunc (b *Bytes) UnmarshalXMLAttr(attr xml.Attr) error {	body := String(attr.Value).Hex()	*b = make(Bytes, len(body))	copy(*b, body)	return nil}//goland:noinspection ALLfunc (b Bytes) Len() int {	return len(b)}// ByteReadHelper TODO 全部改成使用 Pos 和 at 的方式解析. ByteReadHelper 将作为底层操作. 修改 modbus 包, 修改为引用此结构type ByteReadHelper struct {	registerSize int // 支持 2 或 1 两种处理模式	start        int // 从第几个地址开始读取	body         []byte}func (b *ByteReadHelper) SetBuffer(buff []byte) {	b.body = make([]byte, len(buff))	copy(b.body, buff)}func (b *ByteReadHelper) SetBlockSize(n int) {	switch n {	case 1, 2, 3, 4:		b.registerSize = n	default:		panic("gnet.ByteReadHelper: SetBlockSize expecting 1-4")	}}func (b *ByteReadHelper) SetStartRegister(n int) {	b.start = n}func (b *ByteReadHelper) Len() int {	return len(b.body)}func (b *ByteReadHelper) IsNonStandard(data []byte) bool {	if len(data) == 1 {		return false // binary.Read 可以处理 1 个字节	}	return len(data)%2 != 0}func (b *ByteReadHelper) patchTo(order binary.ByteOrder, data []byte, value any) ([]byte, error) {	switch len(data) {	case 3:		switch value.(type) {		case *int32, *uint32:			switch order {			case BigEndian, binary.BigEndian:				return append(append([]byte{0}, data...)), nil			case LittleEndian, binary.LittleEndian:				return append(data, 0), nil			}		}	}	return nil, errors.New("gnet.ByteReadHelper: GetValueCustom expecting int64 or uint64")}func (b *ByteReadHelper) GetValueCustom(order binary.ByteOrder, pos, at int, value any) error {	data := b.body[pos:at]	if b.IsNonStandard(data) {		var err error		data, err = b.patchTo(order, data, value)		if err != nil {			return err		}	}	buf := bytes.NewReader(data)	return binary.Read(buf, order, value)}func (b *ByteReadHelper) GetValueAt(pos int, value any) error {	return b.GetValueCustom(binary.BigEndian, pos, pos+b.registerSize, value)}func (b *ByteReadHelper) GetFloat32At(pos int) float32 {	var value uint32	if err := b.GetValueAt(pos, &value); err != nil {		return 0.0	}	float := math.Float32frombits(value)	return float}func (b *ByteReadHelper) GetFloat64At(pos int) float64 {	var value uint64	if err := b.GetValueAt(pos, &value); err != nil {		return 0.0	}	float := math.Float64frombits(value)	return float}func (b *ByteReadHelper) GetUint16(register int) (v uint16) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetUint32(register int) (v uint32) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetUint64(register int) (v uint64) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetInt16(register int) (v int16) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetInt32(register int) (v int32) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetInt64(register int) (v int64) {	_ = b.GetValueAt(register*b.registerSize, &v)	return}func (b *ByteReadHelper) GetFloat32(register int) (v float32) {	v = b.GetFloat32At(register * b.registerSize)	return}func (b *ByteReadHelper) GetFloat64(register int) (v float64) {	v = b.GetFloat64At(register * b.registerSize)	return}func (b *ByteReadHelper) GetBoolAt(pos, bitPos int) bool {	return LittleEndian.BitSplit(b.body[pos : pos+b.registerSize]).Is1(bitPos)}func (b *ByteReadHelper) GetStringAt(pos, maxLen int) string {	cache := make([]byte, maxLen)	if err := b.GetValueAt(pos, cache); err != nil {		return ""	}	return hex.EncodeToString(cache)}func (b *ByteReadHelper) GetBool(register, bitPos int) (v bool) {	v = b.GetBoolAt(register*b.registerSize, bitPos)	return}func (b *ByteReadHelper) GetRaw(register, quantity int) []byte {	pos := register*b.registerSize - b.start*b.registerSize	at := pos + quantity*b.registerSize	return b.body[pos:at]}func (b *ByteReadHelper) GetIntCustom(order binary.ByteOrder, register, quantity int) int {	pos := register*b.registerSize - b.start*b.registerSize	at := pos + quantity*b.registerSize	switch b.registerSize {	case 1:		switch quantity {		case 1:			var i int8			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i int16			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 3, 4:			var i int32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 8:			var i int64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 2:		switch quantity {		case 1:			var i int16			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i int32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 4:			var i int64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 3:		switch quantity {		case 1:			var i uint32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i int64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 4:		switch quantity {		case 1:			var i int64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	default:		return 0	}}func (b *ByteReadHelper) GetUintCustom(order binary.ByteOrder, register, quantity int) int {	pos := register*b.registerSize - b.start*b.registerSize	at := pos + quantity*b.registerSize	switch b.registerSize {	case 1:		switch quantity {		case 1:			var i uint8			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i uint16			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 3, 4:			var i uint32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 5, 6, 7, 8:			var i uint64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 2:		switch quantity {		case 1:			var i uint16			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i uint32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 3, 4:			var i uint64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 3:		switch quantity {		case 1:			var i uint32			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		case 2:			var i uint64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	case 4:		switch quantity {		case 1:			var i uint64			_ = b.GetValueCustom(order, pos, at, &i)			return int(i)		default:			return 0		}	default:		return 0	}}func (b *ByteReadHelper) GetFloatCustom(order binary.ByteOrder, register, quantity int) float64 {	pos := register*b.registerSize - b.start*b.registerSize	at := pos + quantity*b.registerSize	switch b.registerSize {	case 1:		switch quantity {		case 4:			var value uint32			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float32frombits(value)			return float64(float)		case 8:			var value uint64			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float64frombits(value)			return float		default:			return 0		}	case 2:		switch quantity {		case 2:			var value uint32			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float32frombits(value)			return float64(float)		case 4:			var value uint64			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float64frombits(value)			return float		default:			return 0		}	case 3:		switch quantity {		case 1:			var value uint32			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float32frombits(value)			return float64(float)		case 2:			var value uint64			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float64frombits(value)			return float		default:			return 0		}	case 4:		switch quantity {		case 1:			var value uint64			_ = b.GetValueCustom(order, pos, at, &value)			float := math.Float64frombits(value)			return float		default:			return 0		}	default:		return 0	}}type ByteWriteHelper struct {	registerSize int}func (h *ByteWriteHelper) SetRegisterSize(n int) {	if n != 2 && n != 1 {		panic("gnet.ByteWriteHelper: SetBlockSize expecting 2 or 1")	}	h.registerSize = n}func (h *ByteWriteHelper) SetValueCustom(order binary.ByteOrder, buff []byte, pos int, data any) error {	buf := new(bytes.Buffer)	if err := binary.Write(buf, order, data); err != nil {		return err	}	copy(buff[pos:], buf.Bytes())	return nil}func (h *ByteWriteHelper) SetValueAt(buff []byte, pos int, data any) error {	return h.SetValueCustom(binary.BigEndian, buff, pos, data)}func (h *ByteWriteHelper) SetFloat32At(buf []byte, pos int, value float32) error {	return h.SetValueAt(buf, pos, math.Float32bits(value))}func (h *ByteWriteHelper) SetFloat64At(buf []byte, pos int, value float64) error {	return h.SetValueAt(buf, pos, math.Float64bits(value))}func (h *ByteWriteHelper) SetStringAt(buff []byte, pos, maxLen int, data string) error {	s, err := hex.DecodeString(data)	if err != nil {		return err	}	copy(buff[pos:maxLen], s)	return nil}func (h *ByteWriteHelper) SetBitAt(buff []byte, pos, bitPos, bit int) {	value := binary.BigEndian.Uint16(buff[pos : pos+h.registerSize])	if bit == 0 {		ClearBit(&value, uint(bitPos))	} else {		SetBit(&value, uint(bitPos))	}	BigEndian.PutUint16(buff[pos:pos+h.registerSize], value)}func (h *ByteWriteHelper) SetBoolAt(buff []byte, pos, bitPos int, b bool) {	if b {		h.SetBitAt(buff, pos, bitPos, 1)	} else {		h.SetBitAt(buff, pos, bitPos, 0)	}}
 |