/** * @content:ModbusRTU组件实现文件 * @time:2016-8-23 * @author:Mr_zhu * @version: V1.0 * @describe: * 1#2016-8-23#V1.0#首次生成 */ #include "ProtocolImpl.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "../../common/GUID.cpp" #include "../../servicemodel/Base.h" #include "../../servicemodel/Channel.h" #include "../../servicemodel/Device.h" #include "../../servicemodel/Item.h" #include "../../servicemodel/Packet.h" using namespace std; bool ProtocolImpl::hasInit = false; int ProtocolImpl::findAddrFlag = 0; int ProtocolImpl::idSuccessFlag = 0; int ProtocolImpl::currentId = 1; int ProtocolImpl::timeOut = 0; int ProtocolImpl::count = 1; int ProtocolImpl::currentState = 0; int ProtocolImpl::sendDelayCout = 0; int ProtocolImpl::flag = 0; int ProtocolImpl::deviceCounts = 0; uint8_t ProtocolImpl::retBigEndian(uint32_t value, int offset) { uint8_t ret = 0; ret = (value >> offset) & 0xFF; return ret; } int ProtocolImpl::getRegAddrMax(Packet *ppacket, Item *pitem) { std::string sParaRegAddr; int iParaRegAddr; int maxRegAddr = -1; //Base& base = pitem->getBase(); std::vector items = ppacket->getVitem(); for (size_t i = 0; i < items.size(); ++i) //遍历容器中的所有元素 { sParaRegAddr = items[i]->getBase().getParam("起始地址"); iParaRegAddr = strtol(sParaRegAddr.c_str(), NULL, HEX); if (iParaRegAddr > maxRegAddr) //更新寄存器数量最大值 { maxRegAddr = iParaRegAddr; } else { } } //log_i("最大的起始地址:0x%x", maxRegAddr); return maxRegAddr; } int ProtocolImpl::getRegAddrMin(Packet *ppacket, Item *pitem) { std::string sMinRegAddr; int iMinRegAddr = 0; std::string sParaRegAddr; int iParaRegAddr; std::vector items = ppacket->getVitem(); //log_i("Items size: %zu", items.size()); sMinRegAddr = items[0]->getBase().getParam("起始地址"); iMinRegAddr = strtol(sMinRegAddr.c_str(), NULL, HEX); //log_i("Initial minimum register address value: 0x%x", iMinRegAddr); for (size_t i = 0; i < items.size(); ++i) { //log_i("Processing item %zu", i); sParaRegAddr = items[i]->getBase().getParam("起始地址"); iParaRegAddr = strtol(sParaRegAddr.c_str(), NULL, HEX); if (iParaRegAddr < iMinRegAddr) { iMinRegAddr = iParaRegAddr; } } //log_i("最小的寄存器起始地址:0x%x", iMinRegAddr); return iMinRegAddr; } //过滤出错误帧 int ProtocolImpl::filterErrFrame(PBYTE pbuf,int len) { int validlen = len; int frameId ; int kindId; int errFrameCount = 0; for (int count = 0; ((count < validlen) && ((validlen - count) >= 12)); count += 12) { frameId = getRealFrame(pbuf,count); kindId = (frameId >> 24) & 0xffff; //log_i("frameId = 0x%x,kindID = 0X%x",frameId,kindId); if(kindId != 0xff84 ) { errFrameCount ++; } } return errFrameCount; } int ProtocolImpl::retStateResponse(Packet *ppacket, Item *pitem, const int len,PBYTE pbuf) { int maxRegAddr = -1; int minRegAddr = 0; int regNum = 0; int datasLen = 0; int errFrameCount = 0; int errFrameLen = 0; maxRegAddr = getRegAddrMax(ppacket, pitem); minRegAddr = getRegAddrMin(ppacket, pitem); regNum = maxRegAddr - minRegAddr + 1; //log_i("reg:%d", regNum); errFrameCount = filterErrFrame(pbuf,len); errFrameLen = errFrameCount * 10; datasLen = getRealValidLen(regNum); //log_i("datasLen:%d",datasLen); log_i("最大寄存器地址:0x%x,最小寄存器数量:0x%x,寄存器个数:0x%x,理论算出应收到合法数据长度:%d,\ 实际收到数据长度=%d,错误帧个数=%d,错误帧长度:%d", maxRegAddr, minRegAddr, regNum, datasLen, len,errFrameCount,errFrameLen); if (len >= (datasLen + errFrameLen)) { return S_OK; } else { return S_FALSE; } return S_FALSE; } int ProtocolImpl::getRealValidLen(int maxRegNum) { int len = 0; if (maxRegNum <= 4 && maxRegNum > 0) { len = 4 + 2 * maxRegNum; log_i("第1种情况,寄存器数量小于等于4个,计算得出合法数据长度:%d", len); } else { if (maxRegNum % 4 == 0) { len = 12 * (maxRegNum / 4); log_i("第2种情况,寄存器数量多余4且%4 == 0情况,寄存器请求数量:%d,回复帧长度:%d",maxRegNum,len); } else { len = 4*((maxRegNum / 4) +1) + (maxRegNum *2); //帧数据长度+寄存器长度 log_i("第3种情况,寄存器数量多余4,寄存器请求数量:%d,回复帧长度:%d",maxRegNum,len); } } return len; } int ProtocolImpl::getRealFrame(PBYTE pbuf, int count) { PBYTE ptemp = pbuf; int id = (((ptemp[0 + count] << 24) & 0xff000000) | ((ptemp[1 + count] << 16) & 0x00ff0000) | ((ptemp[2 + count] << 8) & 0x0000ff00) | ((ptemp[3 + count]) & 0x000000ff)); //log_i("帧id:0x%x", id); return id; } std::map ProtocolImpl::handleDataLess(PBYTE pbuf,int len,int regNum,int datasLen) { int iPbufId; std::map dataSet; iPbufId = getRealFrame(pbuf, 0); log_i("handleDataLess"); for (int i = 0; i < regNum; i++) { uint16_t regValue = 0; if (i * 2 + 4 <= datasLen) { regValue = (pbuf[i * 2 + 4] << 8) | pbuf[i * 2 + 5]; // 提取寄存器值 dataSet[iPbufId + i] = regValue; // 绑定到map } else { log_i( "Data insufficient for regNum %d, setting default value 0xFFFF", i); // 数据不足,处理错误或默认值 regValue = 0xFFFF; // 默认值为;0xFFFF dataSet[iPbufId + i] = regValue; // 绑定到map log_i("Added to dataSet: addrFrame=0x%x, value=0x%x", iPbufId + i, regValue); } } for (const auto &entry : dataSet) { log_i("addrFrame = 0x%x, value = 0x%x", entry.first, entry.second); } return dataSet; } std::map ProtocolImpl::handleDataGreater(PBYTE pbuf,int len,int regNum,int datasLen) { log_i("handleDataGreater:收到实际数据长度:%d,请求采集个数:%d,理想情况下收到数据长度:%d", len, regNum, datasLen); std::map dataSet; for (int count = 0; (count < len) && (len - count >= 12); count += 12) { int iPbufId = getRealFrame(pbuf, count); // 假设正确解析起始寄存器ID int kindId = (iPbufId >> 24) & 0xffff; //log_i("frameId = 0x%x,kindID = 0X%x",frameId,kindId); if(kindId == 0xff84 ) //代表合法数据 { for (int i = 0; i < 4 && regNum >= 0; ++i, --regNum) { uint16_t regValue; int dataOffset = count + 4 + i * 2; // 确保当前块的数据足够(两个字节) if (dataOffset + 1 < len) { regValue = (pbuf[dataOffset] << 8) | pbuf[dataOffset + 1]; } else { regValue = 0xFFFF; // 数据不足,默认值 } dataSet[iPbufId + i] = regValue; // 寄存器ID连续递增 } } // 每个块的数据部分为8字节(从count+4到count+11) } return dataSet; } //返回IO数据集 std::map ProtocolImpl::retIoDataSet(Packet *ppacket, Item *pitem,PBYTE pbuf,int len) { std::map dataSet; dataSet = handleIoData(pbuf); return dataSet; } std::map ProtocolImpl::handleIoData(PBYTE pbuf) { int iPbufId; std::map dataSet; iPbufId = getRealFrame(pbuf, 0); uint16_t regValue = 0; regValue = pbuf[7]; dataSet[iPbufId] = regValue; log_i("handleIoData"); for (const auto &entry : dataSet) { log_i("addrFrame = 0x%x, value = 0x%x", entry.first, entry.second); } return dataSet; } std::mapProtocolImpl::retDataSet(Packet *ppacket, Item *pitem,PBYTE pbuf,int len) { std::map dataSet; // 存储寄存器地址和值 int maxRegAddr, minRegAddr, regNum; int datasLen = 0; maxRegAddr = getRegAddrMax(ppacket, pitem); minRegAddr = getRegAddrMin(ppacket, pitem); regNum = maxRegAddr - minRegAddr + 1; datasLen = getRealValidLen(regNum); if (datasLen <= 12) { dataSet = handleDataLess(pbuf,len,regNum,datasLen); } else { dataSet = handleDataGreater(pbuf,len,regNum,datasLen); } return dataSet; } int ProtocolImpl::iGetItemParaConfig(Item *pitem,std::string attribute) { Item *t_item = pitem; Base &t_base = t_item->getBase(); string sAttribute = ""; int iAttribute = 0; sAttribute = t_base.getParam(attribute); //log_i("%s: %s",attribute.c_str(), sAttribute.c_str()); iAttribute = strtol(sAttribute.c_str(), NULL, HEX); //log_i("retV:0x%x",iAttribute); return iAttribute; } std::string ProtocolImpl::sGetItemParaConfig(Item *pitem, std::string attribute) { Item *t_item = pitem; Base &t_base = t_item->getBase(); string sAttribute = ""; sAttribute = t_base.getParam(attribute); //log_i("%s: %s",attribute.c_str(), sAttribute.c_str()); return sAttribute; } void ProtocolImpl::setData(Item *pitem,int16_t pbuf,int receiveData,int paraData,std::string t_sDataType,std::string t_sByteOrder,string t_sBits) { Item* t_item = pitem; int16_t buf = pbuf; string t_str; char t[256]; //log_i("receiveData:0x%x,paraData:0x%x",receiveData,paraData); if(receiveData == paraData) { //log_i("ID匹配,处理数据"); if (t_sDataType == "I") { //log_i("数据类型为I,调用merge16函数,buf=0x%x",buf); t_item->setValue(merge16(buf, t_sByteOrder)); // if(t_sByteOrder == "B") // { // log_i("字符类型B"); // int index = t_sBits.find("."); // log_i("t_sBits =%s, index = %d",t_sBits.c_str(),index); // if (index != -1) // { // string t_sBitnum = t_sBits.substr(0,index); // int t_iBitnum =(int) (strtol(t_sBitnum.c_str(),NULL, 10)); //----位起始地址 // int t_Bits =(int) (strtol(t_sBits.substr(index + 1).c_str(),NULL, 10)); // unsigned short t_usdata =(unsigned short) (strtol(merge16_u(buf,t_sByteOrder).c_str(),NULL, 10)); // unsigned short bits = 0; // log_i("位起始地址t_iBitnum = %d, t_Bits= %d, t_usdata = %d",t_iBitnum,t_Bits,t_usdata); // for (int i = 0; i < t_Bits; i++) // { // unsigned short bit = (t_usdata >> (t_iBitnum + i))& 0x0001; // bits += bit * pow(2, i); // } // snprintf(t, 256, "%d", bits); // log_i("bits:%d",bits); // t_str = t; // log_i("字符类型设置:%s",t_str.c_str()); // t_item->setValue(t_str); // } // } } else if (t_sDataType == "UI") { //log_i("数据类型为UI,调用merge16函数"); t_item->setValue(merge16(buf, t_sByteOrder)); } else if (t_sDataType == "B") { int index = t_sBits.find("."); //log_i("t_sBits =%s, index = %d",t_sBits.c_str(),index); if (index != -1) { string t_sBitnum = t_sBits.substr(0,index); int t_iBitnum =(int) (strtol(t_sBitnum.c_str(),NULL, 10)); //----位起始地址 int t_Bits =(int) (strtol(t_sBits.substr(index + 1).c_str(),NULL, 10)); //log_i("数据类型为B,调用merge16函数"); unsigned short t_usdata =(unsigned short) (strtol(merge16_u(buf,t_sByteOrder).c_str(),NULL, 10)); //log_i("位起始地址t_iBitnum = %d, t_Bits= %d, t_usdata = %d",t_iBitnum,t_Bits,t_usdata); unsigned short bits = 0; for (int i = 0; i < t_Bits; i++) { unsigned short bit = (t_usdata >> (t_iBitnum + i))& 0x0001; bits += bit * pow(2, i); } snprintf(t, 256, "%d", bits); t_str = t; t_item->setValue(t_str); //log_i("字符类型设置:%s",t_str.c_str()); } } } } int ProtocolImpl::set_gpio_value(const std::string& gpio_path, const std::string& value) { int fd = open(gpio_path.c_str(), O_WRONLY); if (fd < 0) { log_e("Failed to open GPIO value file: %s", gpio_path.c_str()); return -1; } if (write(fd, value.c_str(), value.length()) < 0) { log_e("Failed to write to GPIO value file: %s", gpio_path.c_str()); close(fd); return -1; } close(fd); return 0; } void ProtocolImpl::proceessReplyFrame(int frame,int datas) { log_i("当前状态:%d ---0-初始化,1-发送,2-接收,3-结束",currentState); if (frame == 0x7F0) // 总主分配ID回复帧的CANID { log_i("processReply datas = %d",datas); unsigned char reply_id = datas; // 回复自身的ID编号 log_i("reply_id = 0x%x",reply_id); if (reply_id == currentId) { log_i("收到设备%d的回复", reply_id); if(currentId == 2) { log_i("回复帧,currentId = %d",currentId ); currentState = END; idSuccessFlag =2; } else { if (orderMode == 0) // 根据分配次序修改下一个要分配的ID { currentId ++; // 正序分配 currentState = SEND; } else { currentId --; // 倒序分配 currentState = SEND; } // 使能下一个设备 //数据发送正确,且有回复,开始发送下一帧 } } else { currentId = 1; idSuccessFlag = 0; log_i("收到错误的回复帧,ID不匹配"); } } else { //currentId = 1; currentState = SEND; idSuccessFlag = 0; log_i("收到未知的CAN帧"); } if(idSuccessFlag == deviceCounts) { findAddrFlag = 1; currentId = 1; currentState = END; } } //发送分配帧 void ProtocolImpl::sendAllocFrame(PBYTE pbuf, int id, int &len) { pbuf[0] = 0x00; pbuf[1] = 0x00; pbuf[2] = 0x07; pbuf[3] = 0xf0; pbuf[4] = static_cast(id); // 转换为字节 pbuf[5] = static_cast(deviceCounts); // 转换为字节 pbuf[6] = static_cast(orderMode); // 转换为字节 pbuf[7] = static_cast(orderState); // 转换为字节 // pbuf[8] = 0; // pbuf[9] = 0; // pbuf[10] = 0; // pbuf[11] = 0; // 打印调试信息 log_i("发送分配地址帧: "); for (int i = 0; i < 8; i++) { log_i("%02X ", pbuf[i]); } currentState = RECEIVED ; len = 8; } void ProtocolImpl::initIO() { currentId = 1; if(count == 1) { if (set_gpio_value(devPath, lowLevel) == 0) { log_i("Set GPIO 436 to high"); } else { log_e("Failed to set GPIO 436 to high"); } } else { if(count > 4) { // 设置 GPIO 436 为低电平 if (set_gpio_value(devPath, highLevel) == 0) { log_i("Set GPIO 436 to low"); currentState = SEND; } else { log_e("Failed to set GPIO 436 to low"); } count = 0; } } count ++; } HRESULT ProtocolImpl::queryInterface(const IID &iid, void **ppv) { if (iid == IID_IProtocol) { log_d( "成功返回Protocol-CANDEXN协议句柄"); *ppv = static_cast(this); } else if (iid == IID_IUnknown) { log_d( "成功返回Protocol-CANDEXN协议IUnknown句柄"); *ppv = static_cast(this); } else { log_d( "未查询到接口"); *ppv = NULL; return E_NOINTERFACE; } reinterpret_cast(*ppv)->addRef(); return S_OK; } ULONG ProtocolImpl::addRef(void) { return ++m_cRef; } ULONG ProtocolImpl::release(void) { if (--m_cRef == 0) { delete this; return 0; } return m_cRef; } ULONG ProtocolImpl::getVersion() { return VERSION; } /** * @content:组织读数据报文 * @time:2016-9-9 * @author:Mr_zhu * @param: pdevice(设备句柄),ppacket(包句柄),pitem(点句柄),pbuf(数据缓冲区),len(返回报文长度) * @return: HRESULT(S_OK,S_FALSE) * @decribe * 1#2016-9-9#V1.0#首次生成 */ HRESULT ProtocolImpl::onRead(Device *pdevice, Packet *ppacket, Item *pitem, PBYTE pbuf, int &len) { log_i("onRead"); Channel *pC = pdevice->getParent(); log_i("Channel pointer: %p", pC); if (pC == nullptr) { log_i("Channel pointer is null"); return S_FALSE; } if (m_tmpItems.count(pC->getBase().getObjid().toString()) == 0) { deviceCounts = pC->getDeviceCount(); maxId = deviceCounts; //maxId = 2; log_i("maxid =%d",maxId); } log_i("当前状态:%d ---0-初始化,1-发送,2-接收,3-结束",currentState); if(currentState == INIT) { initIO(); } if(currentState == SEND) { log_i("currenntId = %d",currentId); if(currentId != 1) { log_i("发送延迟计数:%d",sendDelayCout); if(sendDelayCout > 3) { sendAllocFrame(pbuf,currentId , len); //sendDelayCout = 0; } sendDelayCout ++; } else { sendAllocFrame(pbuf,currentId , len); } timeOut = 0; //pdevice->getBase().setRwstate(READ_WAIT); pdevice->getBase().setRwstate(WRITE_WAIT); } if(currentState == RECEIVED) { if(timeOut > 30) { currentState = INIT; } timeOut ++; } if(currentState != END) { log_i("len的长度:%d",len); return S_OK; } if(currentState == END) //if(findAddrFlag == 1) { idSuccessFlag = 0; if (ppacket->getVitem().size() == 0) { return S_FALSE; } //pdevice->getBase().setRwstate(READ_WAIT); //----设置设备状态 std::string sParaId; int iParaId; Base &t_base = ppacket->getVitem().at(0)->getBase(); sParaId = t_base.getParam("功能码"); log_i("sParaId =%s,对应的实际名称=%s",sParaId.c_str() ,t_base.getName().c_str()); iParaId = strtol(sParaId.c_str(), NULL, HEX); string t_saddr; t_saddr = pdevice->getBase().getParam("站地址"); int t_iaddr = 0; t_iaddr = strtol(t_saddr.c_str(), NULL, HEX); int frameFuncCode = (iParaId & 0x070000); log_i("stationAddr = %d,iParaId=0x%x,frameFuncCode = 0x%x",t_iaddr,iParaId,frameFuncCode); if (ppacket == nullptr || pitem == nullptr) { log_i("Invalid packet or item"); return S_FALSE; } //iParaId |= (t_iaddr << 19); //判断寄存器是读寄存器 if(frameFuncCode == 0x030000) { int maxRegAddr = getRegAddrMax(ppacket, pitem); int minRegAddr = getRegAddrMin(ppacket, pitem); log_i("onRead中判断出寄存器是读寄存器MaxRegAddr: 0x%x, MinRegAddr: 0x%x", maxRegAddr, minRegAddr); if (maxRegAddr < minRegAddr) { log_i("Invalid register address range"); return S_FALSE; } int regNum = maxRegAddr - minRegAddr + 1; iParaId |= (t_iaddr << 19); pbuf[0] = retBigEndian(iParaId + minRegAddr, 24); pbuf[1] = retBigEndian(iParaId + minRegAddr, 16); pbuf[2] = retBigEndian(iParaId + minRegAddr, 8); pbuf[3] = retBigEndian(iParaId + minRegAddr, 0); pbuf[4] = retBigEndian(regNum, 8); pbuf[5] = retBigEndian(regNum, 0); len = 6; if (pbuf == nullptr) { log_i("pbuf is null"); return S_FALSE; } for (int i = 0; i < len; i++) { log_i("onRead-读数据:pbuf[%d]:0x%x", i, pbuf[i]); } pdevice->getBase().setRwstate(READ_WAIT); //----设置设备状态 } //判断寄存器是读写寄存器 if(frameFuncCode == 0x010000) { pdevice->getBase().setRwstate(WRITE_WAIT); } //初始化数据库容器 if (pC != NULL) { if (m_tmpItems.count(pC->getBase().getObjid().toString()) == 0) { log_i("初始化ZLink数据Temporary items not found for Channel ID: %s", pC->getBase().getObjid().toString().c_str()); int ccount = pC->getDeviceCount(); log_i("Channel device count: %d", ccount); std::multimap tmpItems; for (int i = 0; i < ccount; i++) { for (size_t j = 0; j < pC->getVDevice().at(i)->getVitem().size(); j++) { string t_sId; Base &t_base = pC->getVDevice().at(i)->getVitem().at(j)->getBase(); t_sId = t_base.getParam("写功能码"); //log_i("写功能码: %s", t_sId.c_str()); int t_iId = 0; t_iId = strtol(t_sId.c_str(), NULL, HEX); //----获取帧ID //log_i("功能码转换为整数: 0x%x", t_iId); string t_stype; t_stype = t_base.getParam("帧类型"); //log_i("帧类型: %s", t_stype.c_str()); if (t_stype == "1") { t_iId |= 0x80000000; log_i("帧类型为1,功能码更新为: 0x%x", t_iId); } string sStartAddr; //sStartAddr = pC->getVDevice().at(i)->getBase().getParam("起始地址"); sStartAddr = t_base.getParam("起始地址"); //log_i("起始地址 =%s", sStartAddr.c_str()); int iStartAddr = 0; iStartAddr = strtol(sStartAddr.c_str(), NULL, HEX); //log_i("起始地址转换为整数: 0x%x", iStartAddr); t_iId += iStartAddr; string t_saddr; t_saddr = pC->getVDevice().at(i)->getBase().getParam("站地址"); int t_iaddr = 0; t_iaddr = strtol(t_saddr.c_str(), NULL, HEX); //log_i("站地址:%d",t_iaddr); t_iId |= (t_iaddr << 19); //log_i("t_Id = %d",t_iId); tmpItems.insert( make_pair(t_iId, pC->getVDevice().at(i)->getVitem().at(j))); //log_i("插入临时条目: ID=0x%x", t_iId); } } m_tmpItems.insert( make_pair(pC->getBase().getObjid().toString(), tmpItems)); } else { log_i("Temporary items already exist for Channel ID: %s", pC->getBase().getObjid().toString().c_str()); } } return S_OK; } } /** * @content:组织写数据报文 * @time:2016-9-9 * @author:Mr_zhu * @param: pdevice(设备句柄),ppacket(包句柄),pitem(点句柄),pbuf(数据缓冲区),len(返回报文长度) * @param: swritebuf(待写字符串),writelen(待写数据长度) * @return: HRESULT(S_OK,S_FALSE) * @decribe * 1#2016-9-9#V1.0#首次生成 */ HRESULT ProtocolImpl::onWrite(Device *pdevice, Packet *ppacket, Item *pitem, PBYTE pbuf, int &len, string swritebuf, const unsigned int writelen) { log_i("onWrite"); int t_len = 0; Base &base = pitem->getBase(); string t_sRWType; t_sRWType = base.getParam("读写类型"); //----获取点读写类型 if (t_sRWType == "RO") //----只读 { log_w("%s, 对只读点进行非法写操作,点信息(UUID-%s,名称-%s)", pdevice->getBase().getName().c_str(), base.getObjid().toString().c_str(), base.getName().c_str()); return S_FALSE; } string t_sFuncCode; t_sFuncCode = base.getParam("功能码"); int t_iFuncCode = 0; t_iFuncCode = strtol(t_sFuncCode.c_str(), NULL, HEX); //----获取帧ID string t_sStartAddr; int t_iStartAddr = 0; //----起始地址 t_sStartAddr = base.getParam("起始地址"); t_iStartAddr = strtol(t_sStartAddr.c_str(), NULL, 16); t_iFuncCode += t_iStartAddr; string t_saddr; t_saddr = pdevice->getBase().getParam("站地址"); int t_iaddr = 0; t_iaddr = strtol(t_saddr.c_str(), NULL, HEX); t_iFuncCode |= (t_iaddr << 19); *(pbuf + (t_len++)) = HHByte(t_iFuncCode); *(pbuf + (t_len++)) = HLByte(t_iFuncCode); *(pbuf + (t_len++)) = LHByte(t_iFuncCode); *(pbuf + (t_len++)) = LLByte(t_iFuncCode); //----发送帧ID if (ppacket != NULL && pdevice != NULL && pitem != NULL) { struct candata t_data = //{ 0, 0, 0, 0, 0, 0, 0, 0 }; { 0, 0 }; if (m_tmpwritedata.count(t_sFuncCode) > 0) { t_data = m_tmpwritedata.find(t_sFuncCode)->second; } *(pbuf + (t_len++)) = t_data.data0 & 0x00ff; *(pbuf + (t_len++)) = t_data.data1 & 0x00ff; string t_sDataType; //----数据类型 t_sDataType = base.getParam("数据类型"); string t_sByteOrder; t_sByteOrder = base.getParam("字节序"); if (t_sDataType == "I" || t_sDataType == "UI") { long int value = 0; value = strtol(swritebuf.c_str(), NULL, 10); if (t_sByteOrder == "BA") { pbuf[4] = HByte(value); pbuf[5] = LByte(value); } else if (t_sByteOrder == "AB") { pbuf[4] = LByte(value); pbuf[5] = HByte(value); } } } len = 6; struct candata data; data.data0 = pbuf[4] & 0x00ff; data.data1 = pbuf[5] & 0x00ff; // data.data2 = pbuf[6] & 0x00ff; // data.data3 = pbuf[7] & 0x00ff; // data.data4 = pbuf[8] & 0x00ff; // data.data5 = pbuf[9] & 0x00ff; // data.data6 = pbuf[10] & 0x00ff; // data.data7 = pbuf[11] & 0x00ff; std::string sbuf; for (int i = 0; i < 12; i++) { char str[10]; snprintf(str, 10, "%x", pbuf[i]); sbuf = sbuf + str; if (i != (12 - 1)) { sbuf = sbuf + ","; } } log_i( "待发送数据为: %s", sbuf.c_str()); log_i( "%%x, %x", data.data0, data.data1); m_tmpwritedata[t_sFuncCode] = data; pitem->setValue(swritebuf); // pdevice->getBase().setRwstate(WRITE_O); pdevice->getBase().setRwstate(WRITE_WAIT); return S_OK; } /** * @content:判断回复数据是否接收完成 * @time:2016-9-9 * @author:Mr_zhu * @param: pdevice(设备句柄),ppacket(包句柄),pitem(点句柄),pbuf(数据缓冲区),len(返回报文长度) * @return: HRESULT(S_OK,S_FALSE) * @decribe * 1#2016-9-9#V1.0#首次生成 */ HRESULT ProtocolImpl::isResponseOK(Device *pdevice, Packet *ppacket, Item *pitem, PBYTE pbuf, const int len) { log_i("isResponseOk"); int ret; if(findAddrFlag == 0) { return S_OK; } switch (pdevice->getBase().getRwstate()) { case READ_O: case WRITE_WAIT: return S_OK; case READ_WAIT: ret = retStateResponse(ppacket, pitem, len,pbuf); log_i("isResponseOK返回值:%d", ret); if (ret == S_OK) { return S_OK; } else { if (ret == S_FALSE) { return S_FALSE; } } return S_FALSE; case WRITE_O: //case WRITE_WAIT: return S_OK; } return S_FALSE; } //寻址未成功,解析寻址报文 void ProtocolImpl::ioResponse(Packet *ppacket, Item *pitem,PBYTE pbuf, const int len) { // jisuan std::map dataSets; // 存储寄存器地址和值 dataSets=retIoDataSet(ppacket, pitem, pbuf, len); log_i("pbuf[4]= 0x%x,pbuf[5] = 0x%x,pbuf[6] = 0x%x,pbuf[7] = 0x%x",pbuf[4],pbuf[5],pbuf[6],pbuf[7]); // second, for (const auto &entry : dataSets) { log_i("addrFrame = 0x%x, value = 0x%x", entry.first, entry.second); } int id; int16_t buf; for (const auto &dataPair : dataSets) { log_i("addData.size=%d", dataSets.size()); id = dataPair.first; id = (0x7fffffff) & id; buf = dataPair.second; log_i("id = 0x%x,dataPair.second =0x%x",id,buf); if(currentState == RECEIVED ) { proceessReplyFrame(id,buf); } } } void ProtocolImpl::stringOutput(PBYTE pbuf, int data_len) { // 删除strlen计算,直接使用传入的data_len int groups = data_len / 12; int remainder = data_len % 12; int total_bytes = (groups + (remainder != 0)) * 12; char *result = (char *)malloc(total_bytes); if (!result) { fprintf(stderr, "内存分配失败\n"); return; } memset(result, 0, total_bytes); // 更规范的写法 int pos = 0; for (int i = 0; i < data_len; i += 12) { int bytes_to_copy = std::min(12, data_len - i); memcpy(result + pos, pbuf + i, bytes_to_copy); pos += 12; } // 以HEX格式打印二进制数据 for (int i = 0; i < total_bytes; i += 12) { std::string hexStr; for (int j = 0; j < 12; ++j) { char buf[3]; snprintf(buf, sizeof(buf), "%02X", static_cast(result[i + j])); hexStr += buf; hexStr += " "; // 可选:增加空格提高可读性 } log_i("接收到的数据展示:%s", hexStr.c_str()); } free(result); } //寻址成功,解析BMS传的数据 int ProtocolImpl::normalDatasResponse(Device* pdevice,Packet* ppacket,Item* pitem,PBYTE pbuf,const int len) { std::map dataSet; int id; int16_t buf; Channel *pC = pdevice->getParent(); if (pC == NULL) { log_e("%s, 父通道为空, 无法进行数据解析", pdevice->getBase().getName().c_str()); return S_FALSE; } //stringOutput(pbuf,len); dataSet = retDataSet(ppacket, pitem,pbuf,len); //log_i("pbuf[4]= 0x%x,pbuf[5] = 0x%x,pbuf[6] = 0x%x,pbuf[7] = 0x%x",pbuf[4],pbuf[5],pbuf[6],pbuf[7]); // for (const auto &entry : dataSet) // { // log_i("dataSet填充返回值:addrFrame = 0x%x, value = 0x%x", entry.first, // entry.second); // } for (const auto &dataPair : dataSet) { //log_i("addData.size=%d", dataSet.size()); id = dataPair.first; id = (0x7fffffff) & id; buf = dataPair.second; //log_i("Processing data pair with ID: 0x%x", id); if (m_tmpItems.count(pC->getBase().getObjid().toString()) > 0) { //log_i("Found temporary items for Channel ID: %s", //pC->getBase().getObjid().toString().c_str()); std::multimap tmpItms = m_tmpItems.find( pC->getBase().getObjid().toString())->second; //是否有效 // for (const auto &data : tmpItms) // { // log_i("缓存条目中的缓存地址:0x%x,0x%x", data.first, data.second); // } //log_i("Temporary items size: %zu", tmpItms.size()); std::multimap::size_type cnt = tmpItms.count( id); //log_i("Number of items with ID 0x%x: %zu", id, cnt); std::multimap::iterator iter = tmpItms.find(id); if (iter != tmpItms.end()) { for (; cnt > 0; cnt--, iter++) { //log_i("Processing item %zu for ID 0x%x", cnt, id); Item *t_item = iter->second; //Device *ptdevice = (Device*) (t_item->getParent()); if (t_item != NULL && pdevice != NULL) { int iId = iGetItemParaConfig(t_item,"写功能码"); int iStartAddr = iGetItemParaConfig(t_item,"起始地址"); string t_stype = sGetItemParaConfig(t_item,"帧类型"); string t_sDataType = sGetItemParaConfig(t_item,"数据类型"); string t_sByteOrder = sGetItemParaConfig(t_item,"字节序"); string t_sBits= sGetItemParaConfig(t_item ,"位地址"); iId += iStartAddr; string t_saddr; t_saddr = pdevice->getBase().getParam("站地址"); int t_iaddr = 0; t_iaddr = strtol(t_saddr.c_str(), NULL, HEX); //log_i("t_iId = 0x%x,t_iaddr =%d,",iId,t_iaddr); iId |= (t_iaddr << 19); //log_i("设置的数据buf=%d,paraID = 0x%x",buf,iId); setData(t_item, buf,id,iId,t_sDataType,t_sByteOrder,t_sBits); } else { if(t_item == NULL) { log_i("......item== NULL......"); } return S_FALSE; } } } } else { log_i("m_tmpItems.count(pC->getBase().getObjid().toString()) <0"); return S_FALSE; } } return S_OK; } /** * @content:解析数据 * @time:2016-9-9 * @author:Mr_zhu * @param: pdevice(设备句柄),ppacket(包句柄),pitem(点句柄),pbuf(数据缓冲区),len(返回报文长度),deletelen(待删除数据长度) * @return: HRESULT(S_OK,S_FALSE) * @decribe * 1#2016-9-9#V1.0#首次生成 */ HRESULT ProtocolImpl::onResponse(Device *pdevice, Packet *ppacket, Item *pitem, PBYTE pbuf, const int len, int &deletelen) { log_i("onResponse"); int validlen = len; int t_iRWState = pdevice->getBase().getRwstate(); //----设备读写状态 std::vector items = ppacket->getVitem(); switch (t_iRWState) { case READ_O: case READ_WAIT: case WRITE_WAIT: log_i("WRITE_WAIT"); log_i("当前状态:%d ---0-初始化,1-发送,2-接收,3-结束",currentState); if (validlen >= 6) { if(findAddrFlag == 0) { //寻址成功前,BCU -BAU寻址数据回应处理 ioResponse(ppacket, pitem, pbuf, len); return S_OK; } else { //寻址成功,正常解析bms上传数据 normalDatasResponse(pdevice, ppacket, pitem,pbuf,len); } } break; case WRITE_O: break; default: break; } return S_OK; } #ifdef __cplusplus extern "C" IUnknown* CreateInstance() { IUnknown *pI = static_cast(new ProtocolImpl()); pI->addRef(); return pI; } #endif