package ym485 import ( "encoding/hex" "errors" "fmt" "math" "strconv" "strings" "github.com/valyala/bytebufferpool" ) var ErrorInvalidChecksum = errors.New("数据校验错误") var ErrorInvalidLenght = errors.New("数据长度不够") var ErrorEncode = errors.New("编码错误") type DataPack struct { Start byte //帧起始符,恒为0x68,1字节 Addr string //地址域,6字节,整数,大端传输 Start2 byte //帧起始符,恒为0x68,1字节 Ctl uint8 //控制码,1字节 DataLen uint8 //数据域长度,1字节 Data []byte //数据域 Cs uint8 //Start到Cs之前的所有字节模256 End byte //结束符号,恒为0x16,1字节 } func (o *DataPack) EnCode(Addr string, Ctl uint8, Data []byte) (*bytebufferpool.ByteBuffer, error) { //初始化成员 o.Start = 0x68 o.Addr = Addr o.Start2 = 0x68 o.Ctl = Ctl o.DataLen = uint8(len(Data)) o.Data = Data o.End = 0x16 //addr tmpAddr := EncodeAddr(o.Addr) if tmpAddr == nil { return nil, ErrorEncode } //序列化 buf := bytebufferpool.Get() buf.WriteByte(o.Start) buf.Write(tmpAddr) buf.WriteByte(o.Start2) buf.WriteByte(o.Ctl) buf.WriteByte(o.DataLen) if o.DataLen > 0 { TmpData := make([]byte, o.DataLen) for i, b := range o.Data { TmpData[i] = b + 0x33 } buf.Write(TmpData) } //计算校验码 o.Cs = CheckSum(buf.Bytes()) buf.WriteByte(o.Cs) buf.WriteByte(o.End) return buf, nil } func CheckSum(data []byte) uint8 { var sum uint64 for _, c := range data { sum += uint64(c) } return uint8(sum % 256) } func VerifySum(data []byte) bool { if len(data) >= 12 { sum := data[len(data)-2] //倒数第二个字节 sum_ := CheckSum(data[0 : len(data)-2]) if sum == sum_ { return true } } return false } func (o *DataPack) DeCode(data []byte) error { if len(data) >= 12 { o.Start = data[0] o.Addr = DecodeAddr(data[1:7]) o.Start2 = data[7] o.Ctl = data[8] o.DataLen = data[9] if o.DataLen > 0 { if o.DataLen > uint8(len(data)-12) { return ErrorInvalidLenght } o.Data = make([]byte, o.DataLen) for i, b := range data[10 : 10+o.DataLen] { o.Data[i] = b - 0x33 } } o.Cs = data[10+o.DataLen] o.End = data[10+o.DataLen+1] cs := CheckSum(data[0 : 10+o.DataLen]) if o.Cs != cs { return ErrorInvalidChecksum } return nil } return ErrorInvalidLenght } func EncodeAddr(Addr string) []byte { len0 := len(Addr) repeat := 12 - len0 //地址长度最多12个字符 if repeat > 0 { Addr = strings.Repeat("0", repeat) + Addr } buf, err := ASCII2Lbcd([]byte(Addr)) if err != nil { return nil } buf = Rotate(buf) return buf } func DecodeAddr(addr []byte) string { if len(addr) == 0 { return "" } buf := Rotate(addr) buf = Lbcd2ASCII(buf) return strings.TrimLeft(string(buf), "0") } // DecodeFloat64 prec为小数部分的长度 func DecodeFloat64(dat []byte, prec int) (float64, error) { if len(dat) == 0 { return 0.0, errors.New("参数为空") } data := Rotate(dat) ss := []byte(hex.EncodeToString(data)) if prec == 0 { return strconv.ParseFloat(string(ss), 64) } fss := make([]byte, 0, len(ss)+1) fss = append(fss, ss[0:len(ss)-prec]...) fss = append(fss, '.') fss = append(fss, ss[len(ss)-prec:]...) return strconv.ParseFloat(string(fss), 64) } // EncodeFloat64 prec0为整数部分的长度 //prec1为小数部分的长度 func EncodeFloat64(fval float64, prec0, prec1 int) ([]byte, error) { if (prec0+prec1)%2 != 0 { return nil, errors.New("整数和小数总长度非双数") } ui := uint(fval * math.Pow10(prec1)) ss := fmt.Sprintf("%d", ui) repeat := prec0 + prec1 - len(ss) ss = strings.Repeat("0", repeat) + ss buf, err := ASCII2Lbcd([]byte(ss)) if err != nil { return nil, err } buf = Rotate(buf) return buf, nil } func ReleaseByteBuffer(p *bytebufferpool.ByteBuffer) { if p != nil { bytebufferpool.Put(p) } }