// 协议栈模块 // 秒寻科技 // zt 2024-09-15 package ap import ( "encoding/binary" "errors" "ipsomc/module/ps/psmodel" ) type Ap struct { } // 全局变量 var ( s_crc_table = [16]uint16{0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef} ) // AP层上行处理单元 func (obj *Ap) ApUl(dataList []byte, dataListLen *int) (*psmodel.PS_HEAD_T, *psmodel.PS_TAIL_T, error) { newLen := *dataListLen var wCrc uint16 = 0 var psCrc uint16 = 0 var psHeadModel *psmodel.PS_HEAD_T var psTailModel *psmodel.PS_TAIL_T var wStopIndex uint16 = 0 //长度容错检查 if newLen < psmodel.PS_FRAME_MIN_LEN { return nil, nil, errors.New("帧长度不合法") } //帧头帧尾检查 if dataList[0] != psmodel.PS_AP_END_FLAG || dataList[newLen-1] != psmodel.PS_AP_END_FLAG { return nil, nil, errors.New("数据错误") } //逆向转义处理 if err := obj.ApTransferReverse(dataList, &newLen); err != nil { return nil, nil, err } *dataListLen = newLen //解析数据到结构(协议头,协议尾) psHeadModel, psTailModel = obj.ApParseSlicToStruct(dataList, int32(newLen)) //CRC校验 psCrc = psTailModel.Crc //数据报文中的CRC校验码 wStopIndex = uint16(newLen - 3) wCrc = obj.ApGenCrc16(dataList[1:wStopIndex], uint16(newLen), 0) //基于数据报文生成CRC校验码 if wCrc != psCrc { return psHeadModel, psTailModel, errors.New("CRC校验错误") } return psHeadModel, psTailModel, nil } // 对输入数据实施逆向转义处理 // byData:待逆转义数据,返回参数 // pdwLen:数据长度,返回参数 func (obj *Ap) ApTransferReverse(byData []byte, pdwLen *int) error { outData := make([]byte, 0) wCounter := 0 // 逆向转义处理 for i := 1; i < (*pdwLen - 1); i++ { //处理0x5E和0x5D两个连续字符 if byData[i] == 0x5E && byData[i+1] == 0x5D { outData = append(outData, 0x5E) i++ wCounter++ } else if byData[i] == 0x5E && byData[i+1] == 0x7D { //处理0x5E和0x7D两个连续字符 outData = append(outData, 0x7E) i++ wCounter++ } else { //处理其它字符 outData = append(outData, byData[i]) wCounter++ } } // 将临时数据拷贝回byData切片中 byData = byData[:0] //清空切片 byData = append(byData, 0x7E) //保存帧头 byData = append(byData, outData...) //保存数据 byData = append(byData, 0x7E) //保存帧尾 *pdwLen = wCounter + 2 return nil } // 将切片数据解析到结构体中 // dataList:数据切片 func (obj *Ap) ApParseSlicToStruct(dataList []byte, dwLen int32) (*psmodel.PS_HEAD_T, *psmodel.PS_TAIL_T) { var psHeadModel psmodel.PS_HEAD_T var psTailModel psmodel.PS_TAIL_T var wTailIndex uint16 = 0 var wStopIndex uint16 = 0 //AP层 psHeadModel.StApHead.StartFlag = dataList[0] //协议头 //VP层 psHeadModel.StVpHead.ProjectID = int(binary.LittleEndian.Uint32(dataList[1:5])) //项目编号 //项目编号 psHeadModel.StVpHead.PacketNo = dataList[5] //协议包号 psHeadModel.StVpHead.DeviceID = int(binary.LittleEndian.Uint32(dataList[6:10])) //设备编号 psHeadModel.StVpHead.VpFlag = dataList[10] //VP层标识符 psHeadModel.StVpHead.McpType = dataList[11] //MCP层协议类型 //MCP层 psHeadModel.StMcpHead.Comd = dataList[12] //MCP命令标识符 psHeadModel.StMcpHead.Resp = dataList[13] //MCP响应标识符 ////帧尾 wTailIndex = uint16(dwLen - 3) wStopIndex = uint16(dwLen - 1) psTailModel.Crc = uint16(binary.LittleEndian.Uint16(dataList[wTailIndex:wStopIndex])) //CRC校验码 psTailModel.StopFlag = dataList[wStopIndex] //结束标识符 return &psHeadModel, &psTailModel } // 生成CRC16校验码 // data:数据 // len:数据长度 // def_crc func (obj *Ap) ApGenCrc16(data []byte, len uint16, def_crc uint16) uint16 { var crc uint16 = def_crc var crc_h4 uint8 = 0 for _, v := range data { crc_h4 = (uint8)(crc >> 12) crc <<= 4 crc ^= s_crc_table[crc_h4^(v>>4)] crc_h4 = (uint8)(crc >> 12) crc <<= 4 crc ^= s_crc_table[crc_h4^(v&0x0f)] } return crc } // AP层下行处理单元 func (obj *Ap) ApDl(dataList []byte, dataListLen int) ([]byte, int, error) { newLen := dataListLen //长度容错检查 if newLen < psmodel.PS_FRAME_MIN_LEN { return nil, 0, errors.New("帧长度不合法") } //帧头帧尾检查 if dataList[0] != psmodel.PS_AP_END_FLAG || dataList[newLen-1] != psmodel.PS_AP_END_FLAG { return nil, 0, errors.New("数据错误") } //转义处理 apFrame, err := obj.ApTransfer(dataList, &newLen) if err != nil { return nil, 0, err } return apFrame, newLen, nil } // 对输入数据实施转义处理 // byData:待逆转义数据,返回参数 // pdwLen:数据长度,返回参数 func (obj *Ap) ApTransfer(byData []byte, pdwLen *int) ([]byte, error) { outData := make([]byte, 0) //帧头 outData = append(outData, 0x7E) // 转义处理 for i := 1; i < (*pdwLen - 1); i++ { if byData[i] == 0x5E { //将0x5E转义成0x5E,0x5D outData = append(outData, 0x5E) outData = append(outData, 0x5D) } else if byData[i] == 0x7E { //将0x7E转义成0x5E,0x7D outData = append(outData, 0x5E) outData = append(outData, 0x7D) } else { //其它字符 outData = append(outData, byData[i]) } } //帧尾 outData = append(outData, 0x7E) //保存帧头 *pdwLen = len(byData) //队列长度 return outData, nil }