Loading... # 101/104报文解析完结 最终还是采用了预设定链路地址长度(101规约报文)、公共地址长度、传送原因长度和信息体地址长度的方式。 模糊匹配的方式不是很靠谱(主要还是水平有限)。 ## 一.完整类头文件定义 ```c++ #pragma once #include <string> #include <vector> //信息体对象 struct InfoData { uint32_t Address; //地址 std::string Data; //数据 std::string TimeStamp; //时间戳(部分报文带时间戳,比如带时间戳的单/双点遥信,对时。。。) }; //CP56Time2a结构体 typedef union { uint8_t byte[7]; struct { WORD millisecond; uint8_t minute : 6; uint8_t RES1 : 1; uint8_t IV : 1; uint8_t hour : 5; uint8_t RES2 : 2; uint8_t SU : 1; uint8_t dayofmonth : 5; uint8_t dayofweek : 3; uint8_t month : 4; uint8_t RES3 : 4; uint8_t year : 7; uint8_t RES4 : 1; }; } unionCP56Time; class ProtocolCheck { public: /// <summary> /// 初始化 /// </summary> /// <param name="buf">byte[]</param> /// <param name="len">byte[]长度</param> /// <param name="linkaddrlen">链路地址长度</param> /// <param name="asdulen">公共地址长度</param> /// <param name="cotlen">传送原因长度</param> /// <param name="infoaddrlen">信息体地址长度</param> ProtocolCheck(uint8_t* buf, uint16_t len, uint8_t linkaddrlen, uint8_t asdulen, uint8_t cotlen, uint8_t infoaddrlen) { uBuffer = buf; uLen = len; uIndex = 0; uLinkAddrLen = linkaddrlen; uCotLen = cotlen; uAsduLen = asdulen; uInfoAddrLen = infoaddrlen; uType = 0; uPacketLen = 0; } ~ProtocolCheck(); /// <summary> /// 判断是否为101/104报文,忽略短帧 /// </summary> /// <returns>1:101,2:104,-1:校验和错,-2:非101/104报文</returns> int IsDL10xPacket(uint8_t& len); /// <summary> /// 获取控制字 /// </summary> /// <param name="descript">控制字解析,为空时无</param> /// <returns></returns> uint32_t GetCtrlWord(char* descript=nullptr); /// <summary> /// 获取链路地址 /// </summary> /// <param name="descript">控制字解析,为空时无</param> /// <returns></returns> uint16_t GetLinkAddr(char* descript = nullptr); /// <summary> /// 获取传送原因 /// </summary> /// <param name="descript">传送原因解析,为空时无</param> /// <returns></returns> uint16_t GetCotWord(char* descript = nullptr); /// <summary> /// 获取公共地址 /// </summary> /// <param name="descript">公共地址解析,为空时无</param> /// <returns></returns> uint16_t GetAsduWord(char* descript = nullptr); /// <summary> /// 获取类型标志 /// </summary> /// <param name="descript">类型标志解析,为空时无</param> /// <returns></returns> uint8_t GetTi(char* descript = nullptr); /// <summary> /// 获取信息体数目 /// </summary> /// <param name="infoDatas">信息体对象</param> /// <returns></returns> std::vector<InfoData> GetInfoDataNum(); private: //待解析的报文数据 uint8_t* uBuffer; //待解析的报文数据字节长度 uint16_t uLen; //有效数据帧起始地址 uint16_t uIndex; //链路地址长度 uint8_t uLinkAddrLen; //传送原因长度 uint8_t uCotLen; //公共地址长度 uint8_t uAsduLen; //信息体地址长度 uint8_t uInfoAddrLen; //报文类型,1:101报文,2:104报文 uint8_t uType; //有效数据帧字节长度 uint8_t uPacketLen; }; ``` ## 二、报文解析 ### 1.报文结构判定 根据IEC60850相关规范及DLT634.5101/104相关行标,采用报文起始字符、结束字符、和校验来识别101报文,采用报文起始字符来识别104报文(实际上其他类型诸如645、698及低压塑壳开关之类的报文结构也非常类似)。 ```c++ int ProtocolCheck::IsDL10xPacket(uint8_t& len) { uIndex = 0; int ret = -2; while (uIndex < uLen) { //首字符应为0x68 if (uBuffer[uIndex] == 0x68 && uIndex+3<uLen)//报文首判断 { //检查是否满足101报文结构要求 uint8_t tmpLen = uBuffer[uIndex + 1]; //报文长度 if (tmpLen == uBuffer[uIndex + 2] && uBuffer[uIndex + 3] == 0x68) { //报文长度判断 if (uIndex + tmpLen + 6 <= uLen) { //结束字符判断 if (uBuffer[uIndex + tmpLen + 6 - 1] == 0x16) { //和校验判断 if (ByteHandler::CalcSum(&uBuffer[uIndex + 4], tmpLen) == uBuffer[uIndex + tmpLen + 6 - 2]) { ret = 1; } else { ret = -1; } len = tmpLen + 6; break; } } } //检查是否满足104报文结构要求 else if (uIndex + tmpLen + 2 <= uLen) { ret = 2; len = tmpLen + 2; break; } } uIndex++; } if (ret <= 0) return ret; //链路地址长度、传送原因长度、ASDU公共地址长度、信息体地址长度判断 uint32_t linkAddr = 0, cot = 0, asduAddr = 0, infoAddr = 0; uint8_t ti = 0; if (ret == 1)//101报文 { //链路地址 linkAddr = ByteHandler::Hex2Dec(&uBuffer[uIndex + 5], uLinkAddrLen); //类型标志 ti = uBuffer[uIndex + 5 + uLinkAddrLen]; //传送原因 cot = ByteHandler::Hex2Dec(&uBuffer[uIndex + 7 + uLinkAddrLen], uCotLen); //ASDU公共地址 asduAddr = ByteHandler::Hex2Dec(&uBuffer[uIndex + 7 + uLinkAddrLen + uCotLen], uAsduLen); } else if (ret == 2)//104报文 { //类型标志 ti = uBuffer[uIndex + 6]; //传送原因 cot = ByteHandler::Hex2Dec(&uBuffer[uIndex + 8], uCotLen); //ASDU公共地址 asduAddr = ByteHandler::Hex2Dec(&uBuffer[uIndex + 8 + uCotLen], uAsduLen); } uPacketLen = len; uType = ret; return ret; } ``` ### 2.控制字、类型标志和传送原因等关键信息获取 根据个人理解,101规约控制字很多时候需要知道单帧报文FC的值。而104报文(I帧,U帧和S帧不考虑)的话,将发送序列号和接收序列号进行解析就行了。 ```c++ uint32_t ProtocolCheck::GetCtrlWord(char* descript) { uint32_t ctrl = 0; if (uType != 1 && uType != 2) return ctrl; if (descript == nullptr) { return ctrl; } if (uType == 1) { ctrl = uBuffer[uIndex + 4]; auto fc = ctrl & 0xf; if (descript != nullptr) { switch (fc) { case 0: strcpy(descript, "复位远方链路"); break; case 2: strcpy(descript, "发送/确认 链路测试功能"); break; case 3: strcpy(descript, "发送/确认用户数据"); break; case 4: strcpy(descript, "发送/无回答用户数据"); break; case 8: strcpy(descript, "访问请求"); break; case 9: strcpy(descript, "请求/响应 请求链路状态"); break; case 10: strcpy(descript, "请求/响应 请求1级用户数据"); break; case 11: strcpy(descript, "请求/响应 请求2级用户数据"); break; default: strcpy(descript, "未知功能码"); break; } } } else { memcpy(&ctrl, &uBuffer[uIndex + 2], 4); if (descript != nullptr) { uint16_t ns = 0, nr = 0; memcpy(&ns, &uBuffer[uIndex + 2], 2); memcpy(&nr, &uBuffer[uIndex + 4], 2); sprintf(descript, "发送序列号:%d,接收序列号:%d", ns / 2, nr / 2); } } return ctrl; } ``` 只有101报文包含链路地址: ```c++ /// <summary> /// 获取链路地址,101报文专属 /// </summary> /// <param name="descript"></param> /// <returns></returns> uint16_t ProtocolCheck::GetLinkAddr(char* descript) { uint16_t ctrl = 0; if (uType != 1 && uType != 2) return ctrl; if (uType == 1) { memcpy(&ctrl, &uBuffer[uIndex + 5], uLinkAddrLen); } return ctrl; } ``` 传送原因解析: ```c++ uint16_t ProtocolCheck::GetCotWord(char* descript) { uint16_t ctrl = 0; if (uType != 1 && uType != 2) return ctrl; if (uType == 1) { memcpy(&ctrl, &uBuffer[uIndex + 5+ uLinkAddrLen+2], uCotLen); } else { memcpy(&ctrl, &uBuffer[uIndex + 8], uCotLen); } if (descript != nullptr) { if (g_Cot.find(ctrl) != g_Cot.end()) //正常应答 { strcpy(descript, g_Cot[ctrl].c_str()); } else if (g_Cot.find(0xf & ctrl) != g_Cot.end()) //存在情形:高位 0b0100,低位正常应答,以示否定 { strcpy(descript, "否定"); strcpy(&descript[strlen(descript) + 1], g_Cot[0xf & ctrl].c_str()); } } return ctrl; } ``` 公共地址解析: ```c++ uint16_t ProtocolCheck::GetAsduWord(char* descript) { uint16_t ctrl = 0; if (uType != 1 && uType != 2) return ctrl; if (uType == 1) { memcpy(&ctrl, &uBuffer[uIndex + 5 + uLinkAddrLen + 2+ uCotLen], uAsduLen); } else { memcpy(&ctrl, &uBuffer[uIndex + 8 + uCotLen], uAsduLen); } return ctrl; } ``` 类型标志解析: ```c++ uint8_t ProtocolCheck::GetTi(char* descript) { uint8_t ctrl = 0; if (uType != 1 && uType != 2) return ctrl; if (uType == 1) { ctrl = uBuffer[uIndex + 5 + uLinkAddrLen]; } else { ctrl = uBuffer[uIndex + 6]; } if (descript == nullptr) { return ctrl; } if (g_TI.find(ctrl) != g_TI.end() && descript!=nullptr) { strcpy(descript, g_TI[ctrl].c_str()); } return ctrl; } ``` ### 3.报文所含信息体对象解析 101/104报文信息体结构完全一致(某些情况下由于SN长度不完全一致导致的差异不在考虑范围内)。 考虑到可变结构限定词(VSQ)定义如下: > 可变结构限定词=VARIABLE STRUCTURE QUALIFIER∶=CP8{number、SQ} > > number =N=数目∶=UI7[1..7]<0..127> > > SQ=单个或者顺序∶=BS1[8]<0..1> 由VSQ作为起点,对101/104报文进行合并解析: ```c++ std::vector<InfoData> ProtocolCheck::GetInfoDataNum() { uint8_t* pAsdu = nullptr; //从VSQ开始 std::vector<InfoData> infoDataVec; if (uType == 1) { pAsdu = &uBuffer[uIndex + 6 + uLinkAddrLen]; } else { pAsdu = &uBuffer[uIndex + 7]; } if (pAsdu == nullptr) return infoDataVec; auto ti = GetTi(); if (ti <= 0) return infoDataVec; if ((pAsdu[0] & 0b01111111) == 0)//信息体对象数量为0 return infoDataVec; switch (ti) { case 1://单点遥信 if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if (i + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i]; std::string str; if ((val & 0x80) == 0x80) //品质描述词 { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } uint32_t address = infoaddr + i; infoDataVec.push_back({address,str,""}); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 1) *i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 1) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); uint8_t val = pAsdu[1 + (uInfoAddrLen + 1) * i + 1 + uCotLen + uAsduLen]; std::string str; if ((val & 0x80) == 0x80) //品质描述词 { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } uint32_t address = infoaddr ; infoDataVec.push_back({ address,str,"" }); } } break; case 3://双点遥信 if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if (i + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i]; std::string str; if ((val & 0x80) == 0x80 || (val & 0x1) == 0x1)//品质描述词 、双点遥信值 0 ,3为无效 { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,"" }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 1) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 1) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); uint8_t val = pAsdu[1 + (uInfoAddrLen + 1) * i + 1 + uCotLen + uAsduLen]; std::string str; if ((val & 0x80) == 0x80 || (val & 0x1) == 0x1) { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } uint32_t address = infoaddr; infoDataVec.push_back({ address,str,"" }); } } break; case 30://带时标的单点遥信 if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if (i*8 + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i*8]; std::string str; if ((val & 0x80) == 0x80) { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } unionCP56Time spi; memcpy_s(&spi, 7, &pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i * 8 + 1], 7); std::string str1 = formatString("%d-%d-%d %d:%d:%d.%d", spi.year + 2000, spi.month, spi.dayofmonth, spi.hour, spi.minute, spi.millisecond / 1000, spi.millisecond % 1000); uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,str1 }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 1 + 7) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 1 + 7) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); uint8_t val = pAsdu[(uInfoAddrLen + 1 + 7) * i+ uInfoAddrLen + 1 + uCotLen + uAsduLen]; std::string str; if ((val & 0x80) == 0x80) { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } unionCP56Time spi; memcpy_s(&spi, 7, &pAsdu[(uInfoAddrLen + 1 + 7) * i + uInfoAddrLen + 1 + 1 + uCotLen + uAsduLen], 7); std::string str1 = formatString("%d-%d-%d %d:%d:%d.%d", spi.year + 2000, spi.month, spi.dayofmonth, spi.hour, spi.minute, spi.millisecond / 1000, spi.millisecond % 1000); uint32_t address = infoaddr; infoDataVec.push_back({ address,str,str1 }); } } break; case 31: //带时标的双点遥信 if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if (i * 8 + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i * 8]; std::string str; if ((val & 0x80) == 0x80 || (val & 0x1) == 0x1) { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } unionCP56Time spi; memcpy_s(&spi, 7, &pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i * 8 + 1], 7); std::string str1 = formatString("%d-%d-%d %d:%d:%d.%d", spi.year + 2000, spi.month, spi.dayofmonth, spi.hour, spi.minute, spi.millisecond / 1000, spi.millisecond % 1000); uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,str1 }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 1 + 7) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 1 + 7) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); uint8_t val = pAsdu[1 + (uInfoAddrLen + 1 + 7) * i + uInfoAddrLen + 1 + uCotLen + uAsduLen]; std::string str; if ((val & 0x80) == 0x80 || (val & 0x1) == 0x1) { str = formatString("%d(无效)", val & 0xF); } else { str = formatString("%d", val & 0xF); } unionCP56Time spi; memcpy_s(&spi, 7, &pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + uInfoAddrLen + 1 + (uInfoAddrLen + 1 + 7) * i + 1], 7); std::string str1 = formatString("%d-%d-%d %d:%d:%d.%d", spi.year + 2000, spi.month, spi.dayofmonth, spi.hour, spi.minute, spi.millisecond / 1000, spi.millisecond % 1000); uint32_t address = infoaddr; infoDataVec.push_back({ address,str,str1 }); } } break; case 9: break; case 11: break; case 13://单精度浮点数遥测 if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x80); i++) { if (5 * (i+1) + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; //uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5*i]; float val = ByteHandler::Hex2Float(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5 * i]); uint8_t qds = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5 * i+4]; std::string str; if ((qds & 0x80) == 0x80) { str = formatString("%.4f(无效)", val); } else { str = formatString("%.4f", val); } uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,"" }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 5) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 5) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); float val = ByteHandler::Hex2Float(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + (uInfoAddrLen + 5) * i]); uint8_t qds = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + (uInfoAddrLen + 5) * i + 4]; std::string str; if ((qds & 0x80) == 0x80) { str = formatString("%d(无效)", val ); } else { str = formatString("%d", val); } uint32_t address = infoaddr; infoDataVec.push_back({ address,str,"" }); } } break; case 42://故障事件 break; case 103: //时钟同步 { unionCP56Time spi; memcpy_s(&spi, 7, &pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen], 7); std::string str1 = formatString("%d-%d-%d %d:%d:%d.%d", spi.year + 2000, spi.month, spi.dayofmonth, spi.hour, spi.minute, spi.millisecond / 1000, spi.millisecond % 1000); infoDataVec.push_back({ 0,"",str1}); break; } case 206://电能量 { if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x80); i++) { if (5 * (i + 1) + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; //uint8_t val = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5*i]; float val = ByteHandler::Hex2Float(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5 * i]); uint8_t qds = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + 5 * i + 4]; std::string str; if ((qds & 0x80) == 0x80) { str = formatString("%.4f(无效)", val); } else { str = formatString("%.4f", val); } uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,"" }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 5) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 5) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); float val = ByteHandler::Hex2Float(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + (uInfoAddrLen + 5) * i]); uint8_t qds = pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + (uInfoAddrLen + 5) * i + 4]; std::string str; if ((qds & 0x80) == 0x80) { str = formatString("%d(无效)", val); } else { str = formatString("%d", val); } uint32_t address = infoaddr; infoDataVec.push_back({ address,str,"" }); } } break; } case 207://带时标的电能量 break; case 202: //读参数 { if (GetCotWord() == 0x6) break; uint8_t i = 0; if (uType == 1) { i = uIndex + 7 + uLinkAddrLen + uCotLen + uAsduLen; } else { i = uIndex + 8 + uCotLen + uAsduLen + 2 + 1; } while (i < uPacketLen) { unsigned long infoAddr = ByteHandler::Hex2Dec(&uBuffer[i], uInfoAddrLen); i += uInfoAddrLen; unsigned char dataType = uBuffer[i]; i++; uint8_t dataLen = uBuffer[i]; i++; std::string strData; //m_paramDataType[infoAddr] = dataType; std::string paraTypeName = "未知数据类型"; if (g_ParaType.find(dataType)!=g_ParaType.end()) { paraTypeName = g_ParaType[dataType]; } switch (dataType) { case 1: //布尔 case 32: { auto data_ = ByteHandler::Hex2Dec(&uBuffer[i], dataLen); strData = formatString("%d,(%d:%s)", data_,dataType, paraTypeName.c_str()); i += dataLen; break; } case 2: { int* data_ = (int*)&uBuffer[i]; strData = formatString("%d,(2:%s)", *data_, paraTypeName.c_str()); i += 4; break; } case 4: { strData = formatString("%s,(4:%s)", (char*)&uBuffer[i], paraTypeName.c_str());; i += dataLen /*+ 1*/; break; } case 33: { short* data_ = (short*)&uBuffer[i]; strData = formatString("%d,(33:%s)", *data_, paraTypeName.c_str()); i += 2; break; } case 45: { unsigned short* data_ = (unsigned short*)&uBuffer[i]; strData = formatString("%d,(45:%s)", *data_, paraTypeName.c_str()); i += 2; break; } case 35: { unsigned int* data_ = (unsigned int*)&uBuffer[i]; strData = formatString("%d,(35:%s)", *data_, paraTypeName.c_str()); i += 4; break; } case 36: { long* data_ = (long*)&uBuffer[i]; strData = formatString("%ld,(36:%s)", *data_, paraTypeName.c_str()); i += 8; break; } case 37: { unsigned long* data_ = (unsigned long*)&uBuffer[i]; strData = formatString("%ld,(37:%s)", *data_, paraTypeName.c_str()); i += 8; break; } case 38: { float* data_ = (float*)&uBuffer[i]; strData = formatString("%.4f,(38:%s)", *data_, paraTypeName.c_str()); i += 4; break; } case 39: { double* data_ = (double*)&uBuffer[i]; strData = formatString("%.4lf,(39:%s)", *data_, paraTypeName.c_str()); i += 8; break; } case 43: { char data_ = (char)uBuffer[i]; strData = formatString("%d,(43:%s)", (uint32_t)data_, paraTypeName.c_str()); i++; break; } default: { break; } } infoDataVec.push_back({ infoAddr,strData,"" }); } break; } case 203: break; case 210: break; case 211: break; case 114: { if (GetCotWord() == 0x6) break; if ((pAsdu[0] >> 7) & 0x1) //连续地址 { uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[1 + uCotLen + uAsduLen], uInfoAddrLen); for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if (2*i + 1 + uCotLen + uAsduLen + uInfoAddrLen >= uLen) break; auto val = ByteHandler::Hex2Dec(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i * 2], 2); std::string str = formatString("%d", val); uint32_t address = infoaddr + i; infoDataVec.push_back({ address,str,"" }); } } else { for (int i = 0; i < (pAsdu[0] & 0x7f); i++) { if ((uInfoAddrLen + 2) * i + 1 + uCotLen + uAsduLen >= uLen) break; uint32_t infoaddr = 0; memcpy_s(&infoaddr, 4, &pAsdu[(uInfoAddrLen + 2) * i + 1 + uCotLen + uAsduLen], uInfoAddrLen); //uint8_t val = pAsdu[1 + (uInfoAddrLen + 2) * i + 1 + uCotLen + uAsduLen]; auto val = ByteHandler::Hex2Dec(&pAsdu[1 + uCotLen + uAsduLen + uInfoAddrLen + i * (2+uInfoAddrLen)], 2); std::string str = formatString("%d", val); uint32_t address = infoaddr; infoDataVec.push_back({ address,str,"" }); } } break; } case 115: break; default: break; } return infoDataVec; } ``` **码的比较丑,整体设计和代码复用没在考虑范围;同时对于边界检查(指针越限)检查也做的很松散(基本上约等于没有),不具备用于实际生产环境条件和资格。** ## 三、效果       最后修改:2022 年 05 月 04 日 10 : 26 PM © 允许规范转载