package protocol import ( "bytes" "dlt645-server/errors" "encoding/binary" "encoding/json" "github.com/gogf/gf/os/glog" "reflect" "strconv" ) // 消息包 type Message struct { Header Header Body Entity } type DHeader struct { MsgID MsgID } type Data struct { DataType int PowerData VIData IData } type PowerData struct { ActivePower float64 `json:"active_power"` } type VIData struct { AV float64 `json:"av"` // A相电压 AI float64 `json:"ai"` // A相电流 BV float64 `json:"bv"` // B相电压 BI float64 `json:"bi"` // B相电流 CV float64 `json:"cv"` // C相电压 CI float64 `json:"ci"` // C相电流 } type IData struct { AI2 float64 `json:"ai"` // A相电流 BI2 float64 `json:"bi"` // B相电流 CI2 float64 `json:"ci"` // C相电流 } // 协议编码 func (message *Message) Encode() ([]byte, error) { // 编码消息体 var err error var data []byte if message.Body != nil && !reflect.ValueOf(message.Body).IsNil() { data, err = message.Body.Encode(nil) if err != nil { return nil, err } } // 二进制转义 buffer := bytes.NewBuffer(nil) message.write(buffer, data) return buffer.Bytes(), nil } // 协议解码 func (message *Message) Decode(ctx *PacketContext, buf []byte, data *Data) (result *Data, err error) { // 检验标志位 length := len(buf) if length == 0 { return result, errors.ErrInvalidMessage } for i := 0; i <= length; i++ { if buf[i] == SendByte { continue } else { buf = buf[i:length] glog.Debugf("收到数据:%2X", buf) break } } if buf[0] != ReceiveByte { return result, nil } if buf[len(buf)-1] != EndByte { buf = append(buf, 0x16) } if !message.checkSum(buf) { return result, errors.ErrInvalidCheckSum } //处理注册包 if buf[0] == RegisterByte { header := Header{} _ = json.Unmarshal(buf, &header) header.IccID, err = strconv.ParseUint(header.Imei, 10, 64) header.MsgID = 0x0040 //消息ID if err != nil { if err != nil { glog.Errorf("解析报文失败:%s", err.Error()) } } message.Body = nil message.Header = header return result, nil } if len(buf) < 8 { if err != nil { glog.Errorf("解析报文失败:%s", errors.ErrInvalidBody) } } if buf[8] == 0x93 { err = message.decode(ctx, uint32(0x93), buf[:], data) if err != nil { glog.Errorf("解析报文失败:%s", err.Error()) } } else { msgID := MsgID(binary.BigEndian.Uint32(buf[10:15])) //消息ID err = message.decode(ctx, uint32(msgID), buf[:], data) //解析实体对象 entity buffer : 为消息标识 if err != nil { glog.Errorf("解析报文失败:%s", err.Error()) } } return result, nil } //---> func (message *Message) decode(ctx *PacketContext, dataType uint32, buf []byte, data *Data) error { creator, ok := entityMapper[dataType] if !ok { return errors.ErrTypeNotRegistered } entity := creator() err := entity.Decode(ctx, buf, data) //解析data数据 if err != nil { return err } return err } // 写入二进制数据 func (message *Message) write(buffer *bytes.Buffer, data []byte) *Message { for _, b := range data { if b == PrefixID { buffer.WriteByte(EscapeByte) buffer.WriteByte(EscapeByteSufix2) } else if b == EscapeByte { buffer.WriteByte(EscapeByte) buffer.WriteByte(EscapeByteSufix1) } else { buffer.WriteByte(b) } } return message } // 和校验 func (message *Message) checkSum(data []byte) bool { var checkSum byte for _, b := range data[:len(data)-2] { checkSum += b } checkSum = checkSum & 0xFF if checkSum == data[len(data)-2] { return true } return false }