package bx import ( "bytes" "encoding/binary" "fmt" ) type BxDataPack struct { WRAP_A5_NUM int WRAP_5A_NUM int dstAddr uint16 srcAddr uint16 r0 byte r1 byte r2 byte option byte crcMode byte dispMode byte deviceType byte version byte dataLen uint16 data []byte crc uint16 } func NewBxDataPackData(data []byte) BxDataPack { return BxDataPack{ data: data, dataLen: uint16(len(data)), WRAP_A5_NUM: 8, WRAP_5A_NUM: 1, dstAddr: 0xfffe, srcAddr: 0x8000, deviceType: 0xfe, version: 0x02, } } func NewBxDataPackCmd(cmd BxCmd) BxDataPack { b := cmd.Build() fmt.Printf("build Data:% 02x\n", b) return BxDataPack{ data: b, dataLen: uint16(len(b)), WRAP_A5_NUM: 8, WRAP_5A_NUM: 1, dstAddr: 0x0002, srcAddr: 0x8000, deviceType: 0xfe, version: 0x02, } } // SetDispType 注:特殊动态区不支持动态模式 // 0x00:普通模式,动态区与节目可同时显示,但各区域不可重叠。 // 0x01:动态模式,优先显示动态区,无动态区则显示节目,动态区与节目区可重叠。 func (dp *BxDataPack) SetDispType(typ byte) { dp.dispMode = typ } func (dp *BxDataPack) wrap(src []byte) []byte { len := len(src) for _, v := range src { //每次转义会使长度+1 if v == 0xa5 || v == 0x5a || v == 0xa6 || v == 0x5b { len++ } } len += dp.WRAP_5A_NUM len += dp.WRAP_A5_NUM dst := make([]byte, len) offset := 0 for i := 0; i < dp.WRAP_A5_NUM; i++ { dst[offset] = 0xa5 offset++ } //转义 for _, v := range src { if v == 0xa5 { dst[offset] = 0xa6 offset++ dst[offset] = 0xa2 offset++ } else if v == 0xa6 { dst[offset] = 0xa6 offset++ dst[offset] = 0xa1 offset++ } else if v == 0x5a { dst[offset] = 0x5b offset++ dst[offset] = 0xa2 offset++ } else if v == 0x5b { dst[offset] = 0x5b offset++ dst[offset] = 0x01 offset++ } else { dst[offset] = v offset++ } } for i := 0; i < dp.WRAP_5A_NUM; i++ { dst[offset] = 0x5a offset++ } return dst } func (dp *BxDataPack) Pack() []byte { w := bytes.NewBuffer(make([]byte, 0, 1024)) //目标地址 binary.Write(w, binary.LittleEndian, dp.dstAddr) //源地址 binary.Write(w, binary.LittleEndian, dp.srcAddr) binary.Write(w, binary.LittleEndian, dp.r0) binary.Write(w, binary.LittleEndian, dp.r1) binary.Write(w, binary.LittleEndian, dp.r2) binary.Write(w, binary.LittleEndian, dp.option) binary.Write(w, binary.LittleEndian, dp.crcMode) binary.Write(w, binary.LittleEndian, dp.dispMode) binary.Write(w, binary.LittleEndian, dp.deviceType) binary.Write(w, binary.LittleEndian, dp.version) binary.Write(w, binary.LittleEndian, dp.dataLen) binary.Write(w, binary.LittleEndian, dp.data) dp.crc = 0x0 binary.Write(w, binary.LittleEndian, dp.crc) data := w.Bytes() len := w.Len() dp.crc = CRC16(data, 0, len-2) data[len-2] = byte(dp.crc & 0xff) data[len-1] = byte(dp.crc >> 8) return dp.wrap(data) } func dpParse(src []byte, length int) *BxDataPack { dst := unwrap(src, length) if dst == nil { return nil } crcCalculated := CRC16(dst, 0, len(dst)-2) crcGot := bytesToUint16(dst, len(dst)-2, binary.LittleEndian) if crcCalculated != crcGot { return nil } dp := BxDataPack{} offset := 0 //目标地址 dp.dstAddr = bytesToUint16(dst, offset, binary.LittleEndian) offset += 2 //源地址 dp.srcAddr = bytesToUint16(dst, offset, binary.LittleEndian) offset += 2 //保留字 r0,r1,r2 dp.r0 = dst[offset] offset++ dp.r1 = dst[offset] offset++ dp.r2 = dst[offset] offset++ dp.option = dst[offset] offset++ dp.crcMode = dst[offset] offset++ dp.dispMode = dst[offset] offset++ dp.deviceType = dst[offset] offset++ dp.version = dst[offset] offset++ dp.dataLen = bytesToUint16(dst, offset, binary.LittleEndian) offset += 2 //数据 dp.data = dst[offset : offset+int(dp.dataLen)] offset += int(dp.dataLen) dp.crc = bytesToUint16(dst, offset, binary.LittleEndian) return &dp } func unwrap(src []byte, length int) []byte { len := length for _, v := range src { if v == 0xa5 || v == 0x5a || v == 0xa6 { len-- } } //如果计算的帧长度为0, 说明数据不正确 if len == 0 { return nil } dst := make([]byte, len) offset := 0 for i := 0; i < length; { if src[i] == 0xa5 || src[i] == 0x5a { i++ } else if src[i] == 0xa6 { if src[i+1] == 0x01 { dst[offset] = 0xa6 offset++ i = i + 2 } else if src[i+1] == 0x02 { dst[offset] = 0xa5 offset++ i = i + 2 } else { return nil } } else if src[i] == 0x5b { if src[i+1] == 0x01 { dst[offset] = 0x5b offset++ i = i + 2 } else if src[i+1] == 0x02 { dst[offset] = 0x5a offset++ i = i + 2 } else { return nil } } else { dst[offset] = src[i] offset++ i++ } } return dst }