/** @file DiProcess.cpp @brief 处理全数字量数据和变化数字量数据 @author 周正龙 */ #include "DigProcess.h" #include "pub_utility_api/I18N.h" #include "pub_utility_api/TimeUtil.h" #include "common/Common.h" #include "pub_utility_api/CommonConfigParse.h" using namespace std; using namespace iot_service; using namespace iot_idl; using namespace iot_public; using namespace iot_dbms; CDigProcess::CDigProcess(iot_public::SRunAppInfo stRunAppInfo, CDataProcessApiPtr ptrDataProcApi,\ CSrvDataPublishPtr ptrDataPublish):CPointBase() { m_stRunAppInfo = stRunAppInfo; m_ptrDataProcApi = ptrDataProcApi; m_ptrDataPublish = ptrDataPublish; m_nChgAlarmCount = 0 ; m_nSoeAlarmCount = 0 ; m_nChangeCount = 0 ; } bool CDigProcess::initialize() { if(false == CPointBase::initialize()) { LOGERROR("CDigProcess::initialize() fail!\n"); return false; } if(readConfig()) { LOGWARN("initialize::readConfig() 读取配置文件设备 .\n"); } m_nStartupTimes = getUTCTimeSec(); m_nMenuStateDiGkOff = m_mapDiState["MENU_STATE_DI_GK_OFF"]; m_nMenuStateDiSetData = m_mapDiState["MENU_STATE_DI_SET_DATA"]; m_nMenuStateDiInvalid = m_mapDiState["MENU_STATE_DI_INVALID"]; m_nMenuStateDiAbnormal = m_mapDiState["MENU_STATE_DI_ABNORMAL"]; m_nMenuStateDiAlmNotAck = m_mapDiState["MENU_STATE_DI_ALM_NOT_ACK"]; return true; } CDigProcess::~CDigProcess() { } bool CDigProcess::readConfig() { iot_public::CCommonConfigParse objCfgParse; if(objCfgParse.load( iot_public::CFileUtil::getPathOfCfgFile("dataprocess_cfg.xml") ) == kbdFailed) { LOGDEBUG("CDigProcess::readConfig() dataprocess_cfg.xml load fail .\n"); return false; } m_nStartAlarmDelay = objCfgParse.getIntWithDefault("fulldata","alarmDelay",60); //默认60秒 return true; } bool CDigProcess::getDigAlarmStatus(int &nAlmStatus,int nPointType,int nPointSort) { int nRetCode = -1; SAlarmStatusDigSet stAlmStatusDigSet; int Key[2] ; Key[0] = nPointType ; Key[1] = nPointSort ; if(nPointSort <= 0) { LOGDEBUG("getDigAlarmStatus,nPointSort=[%d] <=0 return.",nPointSort); return true; } nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_ALARM_STATUS_DIG_SET,&Key,stAlmStatusDigSet); if(nRetCode <0 ) //reach fail { LOGERROR("getDigAlarmStatus::get table[%s] record Fail ,nPointSort=%d",RT_ALARM_STATUS_DIG_SET,nPointSort); return false; } else if(nRetCode == 0) { LOGDEBUG("getDigAlarmStatus::get table[%s] nPointSort=%d not find ",RT_ALARM_STATUS_DIG_SET,nPointSort); return true; } if(nAlmStatus == ALM_STAT_SOE) { nAlmStatus = stAlmStatusDigSet.alm_status_soe ; } else if(nAlmStatus == ALM_STAT_DI_CHANGE) { nAlmStatus = stAlmStatusDigSet.alm_status_change ; } else { LOGERROR("getDigAlarmStatus:: input nAlmStatus[%d] Error!",nAlmStatus); return false; } return true; } /** @brief 得到分量值得和状态 @param stDigPoint 数字量实时库值 nIndex 分量索引,nValue 分量值 nStatus 状态值 @return 无 @retval */ bool CDigProcess::getValuexStatusx(const SDigPointAll &stDigPoint,const int nIndex,int &nValue,int &nStatus) { if (nIndex > stDigPoint.value_num || nIndex < 1 ) { LOGERROR( "getValueStatus 分量nIndex:%d > nValueNum:%d OR <1,ERROR. ",nIndex,stDigPoint.value_num ); return false; } switch(nIndex) { case 1: nValue = stDigPoint.value1; nStatus = stDigPoint.status1; break; case 2: nValue = stDigPoint.value2; nStatus = stDigPoint.status2; break; case 3: nValue = stDigPoint.value3; nStatus = stDigPoint.status3; break; case 4: nValue = stDigPoint.value4; nStatus = stDigPoint.status4; break; case 5: nValue = stDigPoint.value5; nStatus = stDigPoint.status5; break; default: return false; }; return true; } /** @brief 更新变化数据值/statue到实时库 @param strTagName测点标签 nValue 值 nStatus 状态,nUpdTimes 时间 @return 成功 TRUE; 失败 FALSE @retval */ bool CDigProcess::updateDigValStatus(const string &strTagName,int nValue,int nStatus,int64 nUpdTimes) { bool bRetCode = 0 ; std::vector vecUpdColumn ; CRdbPublic::addUpColumnInfo(vecUpdColumn ,"value", nValue ); CRdbPublic::addUpColumnInfo(vecUpdColumn ,"status",nStatus); CRdbPublic::addUpColumnInfo(vecUpdColumn ,"last_update_time",nUpdTimes); string strKeyTagName = strTagName ; strKeyTagName.resize(64); bRetCode = m_ptrRdbTableMng->updateRecordMultiValueByKey(RT_DIG_TBL,(const void*)strKeyTagName.c_str(),vecUpdColumn); if (bRetCode == false) { LOGERROR("updateDigValStatus::tag_name = %s, updateRecordMultiValueByKey error!",strKeyTagName.c_str()); return false; } return true; } /** @brief 更新数字量statue到实时库,针对单分量 @param strTagName测点标签 nStatus 状态,nUpdTimes 时间 @return 成功 TRUE; 失败 FALSE @retval */ bool CDigProcess::updateDigStatus(const string &strTagName,int nStatus1,int nStatus,int64 nUpdTimes) { bool bRetCode = 0 ; std::vector vecUpdColumn ; CRdbPublic::addUpColumnInfo(vecUpdColumn ,"status1", nStatus1 ); CRdbPublic::addUpColumnInfo(vecUpdColumn ,"status", nStatus); CRdbPublic::addUpColumnInfo(vecUpdColumn ,"last_change_time1",nUpdTimes); string strKeyTagName =strTagName ; strKeyTagName.resize(64); bRetCode = m_ptrRdbTableMng->updateRecordMultiValueByKey(RT_DIG_TBL,(const void*)strKeyTagName.c_str(),vecUpdColumn); if (bRetCode == false) { LOGERROR("updateDigStatus::tag_name = %s, updateRecordMultiValueByKey error!",strKeyTagName.c_str()); return false; } return true; } /** @brief 更新变化数据分量值到实时库中,如果没有变化,返回 @param stChgDiInfo FES 变化数据报文 nIndex 分量索引,nLastValue 分量上次值 nLastStatus 分量上次状态 @return 成功 TRUE; 失败 FALSE @retval */ bool CDigProcess::updateDigitalPart(const SChangeDiInfo &stChgDiInfo,int nIndex) { std::vector vecUpdColumn ; string strValueColName ="value" + to_string(nIndex); string strStatusColName ="status"+ to_string(nIndex); string strChTimeColName ="last_change_time"+ to_string(nIndex); //LOGDEBUG("updateDigitalPart: tag_name = %s, %s = %d,%s = %d", // stUpdateDiInfo.tag_name, strValueColName.c_str(), stUpdateDiInfo.value,strStatusColName.c_str(), stUpdateDiInfo.status); // 更新全数据分量的值 //============================================================================================ vecUpdColumn.clear(); CRdbPublic::addUpColumnInfo(vecUpdColumn ,strValueColName, stChgDiInfo.nValue); CRdbPublic::addUpColumnInfo(vecUpdColumn ,strStatusColName, stChgDiInfo.nStatus); CRdbPublic::addUpColumnInfo(vecUpdColumn ,strChTimeColName, stChgDiInfo.lTimes); //更新变化时间 bool nRetCode = m_ptrRdbTableMng->updateRecordMultiValueByKey(RT_DIG_TBL,(const void*)stChgDiInfo.tag_name,vecUpdColumn); if (nRetCode == false) { LOGERROR("updateDigitalPart::nRetCode = %d, tagName = %s, updateRecordByKey() error!", nRetCode, stChgDiInfo.tag_name); return false; } return true; } /** @brief 更新全数据的分量的值和状态到实时库 @param stUpdateDiInfo FES 全数据报文 nIndex 分量索引,nLastValue 分量上次值 nLastStatus 分量上次状态 @return 有变化 TRUE; 无变化 FALSE @retval */ bool CDigProcess::updateDigitalPart(const SUpdateDiInfo &stUpdateDiInfo,int nIndex,int64 nUpdateTime,int nLastValue,int nLastStatus) { std::vector vecUpdColumn ; string strValueColName ="value" + to_string(nIndex); string strStatusColName ="status"+ to_string(nIndex); string strChTimeColName ="last_change_time"+ to_string(nIndex); //LOGDEBUG("updateDigitalPart: tag_name = %s, %s = %d,%s = %d", // stUpdateDiInfo.tag_name, strValueColName.c_str(), stUpdateDiInfo.value,strStatusColName.c_str(), stUpdateDiInfo.status); // 更新全数据分量的值 //============================================================================================ vecUpdColumn.clear(); if(nLastValue != stUpdateDiInfo.value )//应该比较分量的值 { CRdbPublic::addUpColumnInfo(vecUpdColumn ,strValueColName, stUpdateDiInfo.value); } if(nLastStatus != stUpdateDiInfo.status)//应该比较分量的状态 { CRdbPublic::addUpColumnInfo(vecUpdColumn ,strStatusColName, stUpdateDiInfo.status); } if(vecUpdColumn.size()>0) // 全数据,测点值有变化->放入队列 { CRdbPublic::addUpColumnInfo(vecUpdColumn ,strChTimeColName, nUpdateTime); //更新变化时间 bool nRetCode = m_ptrRdbTableMng->updateRecordMultiValueByKey(RT_DIG_TBL,(const void*)stUpdateDiInfo.tag_name,vecUpdColumn); if (nRetCode == false) { LOGERROR("updateDigitalPart::nRetCode = %d, tagName = %s, updateRecordByKey() error!", nRetCode, stUpdateDiInfo.tag_name); return false; } return true; } return false; //没有变化 } /** @brief 得到数字量分量索引 @param const SUpdateDiInfo &stUpdateDiInfo: FES 过来的全数据报文 nValueNum 测点总分量数量 @return 无 @retval */ int CDigProcess::getDigPartIndex(const SUpdateDiInfo &stUpdateDiInfo,const int nValueNum) { //判读 DI 分量数是否合法 //============================================================================================ if (nValueNum > MAX_DI_BIT_NUM || nValueNum < 1) { LOGERROR("getDigValueIndex::invalid nValueNum:%d, tag_name = %s", nValueNum,stUpdateDiInfo.tag_name); return -1; } //得到分量号索引 //============================================================================================ int nIndex = (int)(stUpdateDiInfo.column_name[5] - 48);//ascii '0'=48 if (nIndex > nValueNum || nIndex < 1) { LOGERROR( "getDigValueIndex::invalid nIndex:%d, nValueNum:%d, tag_name = %s, column_name = %s", nIndex, nValueNum, stUpdateDiInfo.tag_name, stUpdateDiInfo.column_name); return -1; } return nIndex; } /** @brief 得到数字量分量索引 @param const SChangeDiInfo &stChangeDiInfo: FES 过来的全数据报文 nValueNum 测点总分量数量 @return 无 @retval */ int CDigProcess::getDigPartIndex(const SChangeDiInfo &stChangeDiInfo,const int nValueNum) { //判读 DI 分量数是否合法 //============================================================================================ if (nValueNum > MAX_DI_BIT_NUM || nValueNum < 1) { LOGERROR("getDigValueIndex::invalid nValueNum:%d, tag_name = %s", nValueNum,stChangeDiInfo.tag_name); return -1; } //得到分量号索引 //============================================================================================ int nIndex = (int)(stChangeDiInfo.column_name[5] - 48);//ascii '0'=48 if (nIndex > nValueNum || nIndex < 1) { LOGERROR( "getDigValueIndex::invalid nIndex:%d, nValueNum:%d, tag_name = %s, column_name = %s", nIndex, nValueNum, stChangeDiInfo.tag_name, stChangeDiInfo.column_name); return -1; } return nIndex; } /** @brief 是否获取更新数据有效状态标志 @param const nLastStatus: 实时库状态 stUpdateDiInfo:全数据报文 @return 数据有效状态 TURE 有效 FLASE 无效 @retval */ bool CDigProcess::isUpdatedByValidData(const int nLastStatus,const SUpdateDiInfo &stUpdateDiInfo ) { map ::iterator pos; string strTagName = stUpdateDiInfo.tag_name; if( (nLastStatus & (1 << m_nMenuStateDiInvalid)) ) //上次无效=4(未初始化) { return false; } int64 lCurTimes = getUTCTimeSec(); if((lCurTimes - m_nStartupTimes) <= m_nStartAlarmDelay) return false; //大于启动延时,如果全数据有变化,才会产生告警(用于FES 启动比较慢的情况) pos = m_mapUpdatePackRecord.find(stUpdateDiInfo.tag_name); if (pos == m_mapUpdatePackRecord.end()) //没找到 { //实时库点状态不是工况退出且全数据状态不是工况退出 if ( !(nLastStatus & (1 << m_nMenuStateDiInvalid)) //上次状态没有异常 && !(stUpdateDiInfo.status & (1 << m_nMenuStateDiInvalid )) ) //当前状态没有异常 { m_mapUpdatePackRecord[strTagName] = 0; } return false; } else { return true; } return true; } /** @brief 处理全数字量 @param const SFesUpdateDiPkg &stUpdateDiPkg: FES 过来的全数据报文 @return 无 @retval */ int CDigProcess::processDiUpdate(const SFesUpdateDiPkg &stUpdateDiPkg) { int nLoop=0; int nRetCode; int nIndex; //记录INDEX int nUpdateNum; map mapUpdatePoint; SDigPointAll stDigPointAll; nUpdateNum = stUpdateDiPkg.stdidata_size(); if (nUpdateNum == 0) { LOGWARN( "ProcessDiUpdate:nUpdateNum =0,return!"); return -1; } bool bUpdatedByValidDataFlag = (true);//在本进程重启后在本包全数据之前点表中的值已被全数据更新 if (stUpdateDiPkg.ultime() == 0) { LOGWARN( "ProcessDiUpdate:ultime = %ld", stUpdateDiPkg.ultime()); } LOGDEBUG( "ProcessDiUpdate:收到全数据报文,数目[%d],时间[%" PRId64 "]", nUpdateNum,(int64)stUpdateDiPkg.ultime()); for (nLoop = 0; nLoop < nUpdateNum; ++nLoop) { SUpdateDiInfo stUpdateDiInfo; SFesDiDataWithoutTm stDiData = stUpdateDiPkg.stdidata(nLoop); strcpy(stUpdateDiInfo.table_name, (const char *)stDiData.strapptablename().c_str()); strcpy(stUpdateDiInfo.tag_name, (const char *)stDiData.strapptagname().c_str()); strcpy(stUpdateDiInfo.column_name, (const char *)stDiData.strappcolumnname().c_str()); stUpdateDiInfo.value = 0x01 & stDiData.nvalue(); stUpdateDiInfo.status = 0xffff & stDiData.ustatus(); //LOGDEBUG("raw stUpdateDiInfo: tag_name = %s, column_name = %s, value = %d,status = %d", // stUpdateDiInfo.tag_name, stUpdateDiInfo.column_name, stUpdateDiInfo.value, stUpdateDiInfo.status); m_ptrDataProcApi->changeDigStatusRawToRipe(stUpdateDiInfo.status, stUpdateDiInfo.status); //从实时库获取记录信息到结构体stDigPointAll //============================================================================================ nIndex = m_ptrRdbTableMng->searchRecordByKey(RT_DIG_TBL,(const void*)stUpdateDiInfo.tag_name); if (nIndex <0) { LOGERROR( "nIndex = %d, tag_name = %s, searchRecordByKey error!", nIndex, stUpdateDiInfo.tag_name); continue; } nRetCode = m_ptrRdbTableMng->getRecordAllColumnByIndex(RT_DIG_TBL, nIndex,stDigPointAll) ; if (nRetCode == false) { LOGERROR( "nRetCode = %d, tag_name = %s, m_rdbDigTable.getRecordByKey error!", nRetCode, stUpdateDiInfo.tag_name); continue; } //判断是否本进程重启后在本包全数据之前是否点表中的值已被全数据更新; //前提:工况退出会出现在本包中所有记录中 //============================================================================================ //if (nLoop == 0) //用第一个记录代表本包全数据 { bUpdatedByValidDataFlag = isUpdatedByValidData(stDigPointAll.status,stUpdateDiInfo); } //获取数字量分量号 //============================================================================================ int nDigPartIndex = getDigPartIndex(stUpdateDiInfo,stDigPointAll.value_num) ; if( nDigPartIndex <1) { LOGERROR( "invalid nDigPartIndex nValueNum:%d, tag_name = %s, column_name = %s", stDigPointAll.value_num,stUpdateDiInfo.tag_name,stUpdateDiInfo.column_name); continue; } // 从实时库RDB 得到全数据分量的值和状态(上次的值和状态) //============================================================================================ int nLastValue = 0,nLastStatus = 0; if(false == getValuexStatusx(stDigPointAll,nDigPartIndex,nLastValue,nLastStatus)) { LOGERROR("getValuexStatusx: tagName = %s, 获取分量值得错误!", stUpdateDiInfo.tag_name); continue; } // 分量值和状态有变化->更新全数据分量的值和状态 // 修改 value1~5;status1~5 ,last_update_time 不管是否修改设备表(点表)中值域的值 //============================================================================================ int64 nUpdateTime = stUpdateDiPkg.ultime(); if(updateDigitalPart(stUpdateDiInfo,nDigPartIndex,nUpdateTime,nLastValue,nLastStatus)) //分量有变化 { mapUpdatePoint[string(stUpdateDiInfo.tag_name)] = nIndex; } } //处理更新点MAP中的数据 //============================================================================================ updateDigValueStatus(mapUpdatePoint, bUpdatedByValidDataFlag,(int64)stUpdateDiPkg.ultime()); return 1; } /** @brief 设置测点复归状态子 @param SDigAlarmPara stDigAlmPara:变化点MAP int nNewStatus @return 无 @retval */ void CDigProcess::setAbnormalStatus(const SDigPointAll & stDigPoint,const SDigAlarmPara &stDigAlmPara,int &nNewStatus) { int nOldStatus = nNewStatus; int nLastStatus = stDigPoint.status; //新值=未复归,老状态已经复归 ==>状态字增加未复归 if ( stDigAlmPara.is_abnormal && !(nLastStatus & (1 << m_nMenuStateDiAbnormal)) ) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,1 << m_nMenuStateDiAbnormal,0, STATUS_ORI_RECV); //add DiAbnormal flag } else if ( !stDigAlmPara.is_abnormal && (nLastStatus & (1 << m_nMenuStateDiAbnormal)) ) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,0,1 << m_nMenuStateDiAbnormal, STATUS_ORI_RECV); //del DiAbnormal flag } //LOGDEBUG("setAbnormalStatus: 标签点[%s] 未复归=[%d],旧状态=[%d],新状态=[%d].",stDigPoint.tag_name, // stDigAlmPara.is_abnormal,nOldStatus,nNewStatus); return; } /** @brief 数字量变为更新事实库 VALUE1~5 到VALUE ,status 等的值 @param map &mapUpdatePoint:变化点MAP bool bValidChange 是否有效变位 int second; int msecond:时间 @return 无 @retval */ void CDigProcess::updateDigValueStatus(map &mapUpdatePoint, bool bValidChange, int64 lUpdateTimes) { int nRetCode; int nNewStatus; int nNewValue; map ::iterator pos; SDigPointAll stDigPointAll; string strKeyIdTag; for (pos = mapUpdatePoint.begin(); pos != mapUpdatePoint.end(); ++pos) { strKeyIdTag = RT_DIG_TBL; strKeyIdTag += "."; strKeyIdTag += pos->first.c_str(); strKeyIdTag += ".value"; nRetCode = m_ptrRdbTableMng->getRecordAllColumnByIndex(RT_DIG_TBL,pos->second,stDigPointAll); if (nRetCode == false) { LOGERROR( "UpdateDigValueStatus:nRetCode = %d, tag_name = %s, getRecordByIndex error!", nRetCode, pos->first.c_str()); continue; } //计算点不刷新fes实时值 //=========================================================================================== if((stDigPointAll.point_property & (1<<0)) == 1) //计算点 { LOGDEBUG("UpdateDigValueStatus, 计算点[%s]不刷新fes实时值.",stDigPointAll.tag_name); continue ; } //下面开始通过status1...status5得到status,状态OK后,同时删除通信状态和无效状态 //========================================================================================== getStatusByStatusx(stDigPointAll,nNewStatus) ; //通过单分量状态或者总状态 备注:双分量一个状态不对总体就不对 //LOGDEBUG("UpdateDigValueStatus: getStatusByStatusx tag_name = %s, nNewStatus = %d", // stDigPointAll.tag_name, nNewStatus); //下面开始通过 value1...value5 得到value //========================================================================================== int valuex[MAX_DI_BIT_NUM]; int statusx[MAX_DI_BIT_NUM]; initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuex,statusx nNewValue = getValueByValuex(stDigPointAll.value_num,&valuex[0],&statusx[0]); //得到合成值 if (nNewValue < 0) { LOGINFO("UpdateDigValueStatus:getValueByValuex Error"); continue ; } //通过状态文本获取报警方式,报警显示文本; SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,nNewValue ,stDigAlmPara); //老状态报警未复归;新状态已经复归 ==>状态字增加报警未复归 setAbnormalStatus(stDigPointAll,stDigAlmPara,nNewStatus); //实时值发生改变-修改实时值-rdb if (stDigPointAll.value != nNewValue) { //在本进程重启后在本包全数据之前点表中的值是否已被全数据更新,是:发送报警 否:不发送报警 LOGDEBUG("UpdateDigValueStatus::tagname = %s, value = %d,nNewStatus = %d, times = %ld", stDigPointAll.tag_name, stDigPointAll.value,nNewStatus, lUpdateTimes); nRetCode = processValueChange(stDigPointAll,stDigAlmPara,nNewValue,nNewStatus,lUpdateTimes,bValidChange); if (nRetCode < 0) { LOGERROR( " ProcessValueChange error tag_name = %s", stDigPointAll.tag_name); } } else if (stDigPointAll.status != nNewStatus) //状态发生改变 { nRetCode = m_ptrRdbTableMng->updateRecordOneValueByIndex(RT_DIG_TBL, pos->second, "status", nNewStatus); if (nRetCode == false) { LOGERROR( "nRetCode = %d, tag_name = %s, updateRecordByIndex error!", nRetCode, pos->first.c_str()); continue; } //增加变位告警信息 m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system, RT_DIG_TBL, \ stDigPointAll.tag_name, "value", nNewValue,nNewStatus); } else { //LOGDEBUG("UpdateDigValueStatus: 标签[%s]值和状态未发送改变, nNewValue = %d,nNewStatus = %d .", // stDigPointAll.tag_name, nNewValue, nNewStatus); } } return; } /** @brief 通过分量的状态更新总的状态 @param stDigPointAll: INT 测点实时库值 nNewStatus: out 输出状态 @return 无 @retval */ void CDigProcess::getStatusByStatusx(const SDigPointAll&stDigPointAll,int &nNewStatus ) { //下面开始通过status1...status5得到status //=================================================================================================== bool bIsTxOff = false; bool bIsInvalid = false; //如果存在工况退出、非实测值这两种情况,则status域必须加上此标志 //=================================================================================================== if (getDigSpelStatus(bIsTxOff, bIsInvalid, stDigPointAll) < 0) { LOGERROR("getStatusByStatusx:GetDiStatusSpelFlag error!tag_name = %s", stDigPointAll.tag_name); return; } nNewStatus = stDigPointAll.status; //新状态赋值 //处理工况退出状态 //=================================================================================================== if ( bIsTxOff ) //增加通讯异常状态 { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 1 << m_nMenuStateDiGkOff, 0, STATUS_ORI_RECV); //add m_nMenuStateDiGkOff flag } else //删除通讯异常状态 { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 0, 1 << m_nMenuStateDiGkOff, STATUS_ORI_RECV); //del m_nMenuStateDiGkOff flag } //处理无效状态 //=================================================================================================== if ( bIsInvalid ) //添加无效 { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 1 << m_nMenuStateDiInvalid, 0, STATUS_ORI_RECV); //add MENU_STATE_DI_INVALID flag } else //删除无效 { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 0, 1 << m_nMenuStateDiInvalid, STATUS_ORI_RECV); //del MENU_STATE_DI_INVALID flag } //如果没有不正常,增加状态正常位置。 m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 0, 0, STATUS_ORI_RECV); //for initialize ,主要用于判是否正常状态 //LOGDEBUG("getStatusByStatusx: getNewStatus tag_name = %s, value = %d,status = %d", // stDigPointAll.tag_name, stDigPointAll.value, nNewStatus); return ; } /** @brief 检查DI变化MAP缓冲区,把没有用的数据清除 @param 无 @return 无 @retval */ void CDigProcess::checkDiChgBuf() { int nRetCode; int nResultValue; int nValueNum; int nNewStatus; int64 nLastChgMescond = 0; map ::iterator pos; int64 ulCurMsec = (int64)getMonotonicMsec(); for (pos = m_mapDiChgBuf.begin(); pos != m_mapDiChgBuf.end(); ) { if(ulCurMsec - pos->second.first_chg_time > (pos->second.input_delay_time*1000) ) { SDigPointAll stDigPointAll; string strTagName = pos->first.c_str(); strTagName.resize(64); nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,strTagName.c_str(), stDigPointAll); if (nRetCode <=0 ) { LOGERROR("CheckDiChgBuf::nRetCode = %d, tag_name = %s, 获取测点参数错误!", nRetCode, strTagName.c_str()); m_mapDiChgBuf.erase(pos++); continue; } nValueNum = stDigPointAll.value_num; if (nValueNum > MAX_DI_BIT_NUM || nValueNum <= 0 ) { LOGINFO( "CheckDiChgBuf::nValueNum=%d > MAX_DI_BIT_NUM", nValueNum); m_mapDiChgBuf.erase(pos++); continue ; } int valuex[MAX_DI_BIT_NUM]={0}; int statusx[MAX_DI_BIT_NUM]={0}; initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuex,statusx //获得最新报警时间 int nLoop; nLastChgMescond = 0; for (nLoop = 0 ; nLoop < nValueNum; nLoop++) { if (pos->second.di_bit_chg_array[nLoop].use_flag == SHARE_BUF_USE) { valuex[nLoop] = pos->second.di_bit_chg_array[nLoop].value; statusx[nLoop] = pos->second.di_bit_chg_array[nLoop].status; if (nLastChgMescond < pos->second.di_bit_chg_array[nLoop].times) //目前未处理msecond { nLastChgMescond = pos->second.di_bit_chg_array[nLoop].times; } } } nResultValue = getValueByValuex(stDigPointAll.value_num,&valuex[0],&statusx[0]);//通过DI分量得到DI值 if (nResultValue < 0) { LOGERROR("CheckDiChgBuf::getValueByValuex return Error,nValueNum= %d", nValueNum); m_mapDiChgBuf.erase(pos++); continue ; } //下面开始通过status1...status5得到status,状态OK后,同时删除通信状态和无效状态 //========================================================================================== getStatusByStatusx(stDigPointAll,nNewStatus) ; //通过单分量状态或者总状态 备注:双分量一个状态不对总体就不对 //for (nLoop = 0; nLoop < nValueNum; ++nLoop)//通过状态分量得到状态,这里合并但是没有取消(状态Off->off) //{ // m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, statusx[nLoop], 0, STATUS_ORI_RECV,1); //} SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,nResultValue ,stDigAlmPara); setAbnormalStatus(stDigPointAll,stDigAlmPara,nNewStatus); //设置复归状态 if (stDigPointAll.value != nResultValue || stDigPointAll.status != nNewStatus) //状态变化或者值变化 { if (stDigPointAll.value != nResultValue) //值变化 { nRetCode = processValueChange(stDigPointAll,stDigAlmPara,nResultValue,nNewStatus,nLastChgMescond,true); if (nRetCode < 0) { LOGERROR("CheckDiChgBuf::ProcessValueChange error tag_name = %s", stDigPointAll.tag_name); m_mapDiChgBuf.erase(pos++); continue; } } else { std::vector vecUpdColumn ; CRdbPublic::addUpColumnInfo(vecUpdColumn ,"value", nResultValue); CRdbPublic::addUpColumnInfo(vecUpdColumn ,"status", nNewStatus); int nRetCode = m_ptrRdbTableMng->updateRecordMultiValueByKey(RT_DIG_TBL,(const void*)stDigPointAll.tag_name,vecUpdColumn); if (nRetCode == false) { LOGERROR("CheckDiChgBuf::nRetCode = %d, tag_name = %s, updateRecordMultiValueByKey error!", nRetCode, pos->first.c_str()); m_mapDiChgBuf.erase(pos++); continue; } m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system, RT_DIG_TBL, stDigPointAll.tag_name, "value", nResultValue,nNewStatus); } } else { LOGDEBUG("CheckDiChgBuf::tag_name=%s, value=%d, status=%d, delay buf not change", pos->first.c_str(), nResultValue, nNewStatus); } m_mapDiChgBuf.erase(pos++); } else { ++pos; } } return; } /** @brief 检查DI SOE MAP缓冲区,把没有用的数据清除 @param 无 @return 无 @retval */ void CDigProcess::checkDiSoeBuf() { int nRetCode; map ::iterator pos; int64 ulCurMsec = (int64)getMonotonicMsec(); for (pos = m_mapDiSoeBuf.begin(); pos != m_mapDiSoeBuf.end(); ) { if((ulCurMsec - (int64)(pos->second.first_chg_time)) > (int64)(pos->second.input_delay_time*1000)) { SDigPointAll stDigPointAll; string strTagName = pos->first.c_str() ; strTagName.resize(64); nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,strTagName.c_str(), stDigPointAll); if (nRetCode <=0 ) { LOGERROR("CheckDiSoeBuf::nRetCode = %d, tag_name = %s, 获取实时值 error!", nRetCode, strTagName.c_str()); m_mapDiSoeBuf.erase(pos++); continue; } int nValueNum = stDigPointAll.value_num; if (nValueNum > MAX_DI_BIT_NUM || nValueNum <= 0 ) { LOGINFO( "CheckDiSoeBuf::nValueNum=%d > MAX_DI_BIT_NUM", nValueNum); m_mapDiSoeBuf.erase(pos++); continue ; } int valuex[MAX_DI_BIT_NUM] ={0}; int statusx[MAX_DI_BIT_NUM]={0}; //initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuex,statusx //获得最新报警时间 报警分量信息初始化到valuex ,statusx中 //============================================================================================== int nLoop =0 ; int64 nLastChgMescond = 0; for (nLoop = 0 ; nLoop < nValueNum; nLoop++) { if (pos->second.di_bit_chg_array[nLoop].use_flag == SHARE_BUF_USE) { valuex[nLoop] = pos->second.di_bit_chg_array[nLoop].value; statusx[nLoop] = pos->second.di_bit_chg_array[nLoop].status; if (nLastChgMescond < pos->second.di_bit_chg_array[nLoop].times) { nLastChgMescond = pos->second.di_bit_chg_array[nLoop].times; } } } //通过分量获取合成的值 //合成后即使值不对,也产生无效告警,合成周期超时情况,可能产生2条告警; //============================================================================================== int nRetValue = getValueByValuex(stDigPointAll.value_num,&valuex[0],&statusx[0]); if (nRetValue < 0)// 分量错误 { LOGERROR("checkDiSoeBuf::getValueByValuex Error,nRetValue=%d, nValueNum= %d",nRetValue, nValueNum); m_mapDiSoeBuf.erase(pos++); continue ; } //或者报警状态文本 SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,nRetValue ,stDigAlmPara); //产生SOE报警 //============================================================================================== addOneDigAlarm(ALM_TYPE_SOE,stDigPointAll,stDigAlmPara,nLastChgMescond) ; m_mapDiSoeBuf.erase(pos++); } else { ++pos; } } return; } /** @brief 得到告警字符串 @param char *strAlarm: OUT 报警字符串 SDiAlarm *stAlarm: INT 报警结构体 @return 成功>0 失败<=0 @retval */ int CDigProcess::getDigAlarmDesc(string &strAlarm,const string &strTagName,\ const string& strDevTagName,const string& strStatusText,const int nDescFlag)//ALARM_DESC_POINT_FLAG { int nRetValue = 1; int nRetCode = 0; strAlarm = strStatusText ; return 0 ; string strName; string strTempTagName = strTagName; strTempTagName.resize(64); string strTempDevTagName = strDevTagName; strTempDevTagName.resize(64); if (nDescFlag == ALARM_DESC_POINT_FLAG) { nRetCode = m_ptrDataProcApi->getNameStringByTag(RT_DIG_TBL, strTempTagName.c_str(), strName); if (nRetCode < 0) { LOGINFO("nRetCode = %d, m_ptrDataProcApi->getNameStringByTag ERROR,tag_name = %s", nRetCode, strTagName.c_str()); strName = strTagName; nRetValue = -1; } strAlarm = strName +" "+ strStatusText; } else if (nDescFlag == ALARM_DESC_DEV_FLAG) { nRetCode = m_ptrDataProcApi->getNameStringByTag(RT_DEV_INFO, strTempDevTagName.c_str(), strName); if (nRetCode < 0) { LOGERROR("nRetCode = %d, m_ptrDataProcApi->getNameStringByTag ERROR,tag_name = %s", nRetCode, strDevTagName.c_str()); strName = strDevTagName; nRetValue = -1; } strAlarm = strName ; } else { LOGERROR( "nDescFlag = %d ERROR", nDescFlag); strName = strTagName; strAlarm = strName ; nRetValue = -1; } return nRetValue; } /** @brief 处理变化数字量变化接口函数 @param const SFesChangeDiPkg &stChangeDiPkg: 消息总线接收的数据包 int nSoeFlag: INT SOE标志 @return 成功>0 失败<=0 @retval */ int CDigProcess::processDiChange(const SFesChangeDiPkg &stChangeDiPkg) { int nChangeNum; int nLoop = 0; nChangeNum = stChangeDiPkg.stdidata_size(); if(nChangeNum>0) { m_nChangeCount = m_nChangeCount + nChangeNum; LOGDEBUG("ProcessDiChange:收到变化数据报文,数目[%d],总计收到数目[%d],时间[%" PRId64 "].",nChangeNum,m_nChangeCount,(int64)stChangeDiPkg.stdidata(0).ultime()); } for (nLoop = 0; nLoop < nChangeNum; ++nLoop) { SChangeDiInfo stChangeInfo; SFesDiDataWithTm stDiData = stChangeDiPkg.stdidata(nLoop); strcpy(stChangeInfo.table_name, (const char *)stDiData.strapptablename().c_str()); strcpy(stChangeInfo.tag_name, (const char *)stDiData.strapptagname().c_str()); strcpy(stChangeInfo.column_name, (const char *)stDiData.strappcolumnname().c_str()); stChangeInfo.nValue = 0x01 & stDiData.nvalue(); stChangeInfo.nStatus = 0xffff & stDiData.ustatus(); stChangeInfo.lTimes = stDiData.ultime(); if (stChangeInfo.lTimes < 0) { LOGERROR("CDigProcess::ProcessDiChange(),strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = [%" PRId64 "] < 0 error!", stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, stChangeInfo.nStatus, stChangeInfo.lTimes); continue; } //LOGDEBUG("CDigProcess::ProcessDiChange(),strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = %d", // stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, // stChangeInfo.nStatus, stChangeInfo.lTimes); processOneDiChange(stChangeInfo); } return 1; } /** @brief 处理前置SOE事件,增加报警信息到 报警消息队列 @param 无 @return 无 @retval */ int CDigProcess::processSoeEvent(iot_idl::SFesSoeEventPkg objFesSoeEventPkg) //处理soe事件 { int nLoop=0; int nSoeNum; int nRetCode; nSoeNum = objFesSoeEventPkg.stsoeevent_size(); //m_nFesSoeSum += nSoeNum; LOGDEBUG("CDigProcess::ProcessSoeEvent(), recv SoeNum = %d",nSoeNum); for (nLoop = 0; nLoop < nSoeNum; ++nLoop) { SChangeDiInfo stChangeInfo; SFesSoeEventInfo stOneSoeEvent = objFesSoeEventPkg.stsoeevent(nLoop); strcpy(stChangeInfo.table_name, (const char *)stOneSoeEvent.strapptablename().c_str()); strcpy(stChangeInfo.tag_name, (const char *)stOneSoeEvent.strapptagname().c_str()); strcpy(stChangeInfo.column_name, (const char *)stOneSoeEvent.strappcolumnname().c_str()); stChangeInfo.nValue = 0x01 & stOneSoeEvent.nvalue(); stChangeInfo.nStatus = 0xffff & stOneSoeEvent.ustatus(); stChangeInfo.lTimes = stOneSoeEvent.ultime(); string strFaultDesc = stOneSoeEvent.strfaultdesc(); if (stChangeInfo.lTimes < 0) { LOGERROR("CDigProcess::ProcessSoeEvent(),strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = [%" PRId64 "] < 0 error!", stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, stChangeInfo.nStatus, stChangeInfo.lTimes); continue; } //LOGINFO("CDigProcess::ProcessSoeEvent(), strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = %ld,strFaultDesc=%s", // stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, // stChangeInfo.nStatus, stChangeInfo.lTimes,strFaultDesc.c_str()); nRetCode = processOneSoeEvent(stChangeInfo,strFaultDesc); if (nRetCode < 0) { LOGERROR("ProcessOnePscadaSoe Error"); continue; } //stSoeDataPkg.add_seq_soe()->CopyFrom(stSoeDataMsg); } return 1; } /** @brief 处理一个DI点的变位,包括更新值和状态,写时序库,以及调用ProcessValueChange进行值变化处理; @param SChangeDiInfo stChangeInfo: IN 变化DI点信息结构 @return 成功>0 失败<=0 @retval */ int CDigProcess::processOneDiChange(SChangeDiInfo &stChangeInfo) { string strKeyIdTag = ""; strKeyIdTag = RT_DIG_TBL; strKeyIdTag += "."; strKeyIdTag += stChangeInfo.tag_name; strKeyIdTag += ".value"; //在此之前记住那些应该处理的状态(不出现在状态菜单中的状态) //将前置发过来的状态转换成数字量状态菜单对应的值,删掉不处理的状态 m_ptrDataProcApi->changeDigStatusRawToRipe(stChangeInfo.nStatus, stChangeInfo.nStatus); //获取新状态 if ( stChangeInfo.nStatus & (1 << m_nMenuStateDiGkOff) ) { LOGDEBUG("stChangeInfo.status = %d, include m_nMenuStateDiGkOff bit", stChangeInfo.nStatus); } LOGDEBUG("ProcessOneDiChange::strKeyIdTag = %s.%s.%s, value = %d,status = %d, times=[%" PRId64 "].", stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, stChangeInfo.nStatus, stChangeInfo.lTimes); SDigPointAll stDigPointAll; //得到指定标签点的实时库记录 //================================================================================= int nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,stChangeInfo.tag_name,stDigPointAll); if (nRetCode <=0 ) { LOGERROR("nRetCode = %d, tag_name = %s, getRecordAllColumnByKey error!", nRetCode, stChangeInfo.tag_name); return -1; } //计算点不刷新fes实时值 //=========================================================================================== if((stDigPointAll.point_property & (1<<0)) == 1) //计算点 { LOGDEBUG("ProcessOneDiChange, 计算点[%s]不刷新fes实时值.",stDigPointAll.tag_name); return 1; } //首先更新分量实时值和状态(不管的单点还是双点) //============================================================================================ //获取数字量分量号 int nDigPartIndex = getDigPartIndex(stChangeInfo,stDigPointAll.value_num) ; if( nDigPartIndex <1) { LOGERROR( "invalid nDigPartIndex nValueNum:%d, tag_name = %s, column_name = %s", stDigPointAll.value_num,stChangeInfo.tag_name,stChangeInfo.column_name); return -1; } // 分量值和状态有变化->更新全数据分量的值和状态 // 修改 value1~5;status1~5 ,last_update_time 不管是否修改设备表(点表)中值域的值 //============================================================================================ if(false == updateDigitalPart(stChangeInfo,nDigPartIndex)) //分量有变化,x修改分量值和状态 { LOGERROR("processOneDiChange::updateDigitalPart TagName=%s error!", stChangeInfo.tag_name); return -1; } int nNewStatus(0); if (stDigPointAll.value_num == 1) { //下面开始通过status1...status5得到status,状态OK后,同时删除通信状态和无效状态 //========================================================================================== stDigPointAll.value1 = stChangeInfo.nValue; stDigPointAll.status1 = stChangeInfo.nStatus; getStatusByStatusx(stDigPointAll,nNewStatus) ; //通过单分量状态或者总状态 备注:双分量一个状态不对总体就不对 //LOGDEBUG("ProcessDiChange,getNewStatus strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = [%" PRId64 "] ", // stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, // nNewStatus, stChangeInfo.lTimes); SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,stChangeInfo.nValue ,stDigAlmPara); setAbnormalStatus(stDigPointAll,stDigAlmPara,nNewStatus); if ((stDigPointAll.value != stChangeInfo.nValue) || (stDigPointAll.status != nNewStatus)) //当变化的值和实时库中的值不同时 { nRetCode = processValueChange(stDigPointAll,stDigAlmPara,stChangeInfo.nValue,nNewStatus,stChangeInfo.lTimes,true); if (nRetCode < 0) { LOGERROR("ProcessValueChange error tag_name = %s", stChangeInfo.tag_name); } } } else //多分量处理 { if( stDigPointAll.input_delay_time <= 0) stDigPointAll.input_delay_time = 1 ;//多分量延时时间=0 if (stDigPointAll.input_delay_time > 0) //数据量报警延时处理 { addDigPartToBuff(m_mapDiChgBuf, strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); } } return 1; //============================================================================================ /* int nNewStatus(0); if (nValueNum == 1) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, stDigPointAll.status, stChangeInfo.nStatus, 0, STATUS_ORI_RECV, 1); //LOGDEBUG("ProcessDiChange,getNewStatus strKeyIdTag = %s.%s.%s, value = %d,status = %d, times = [%" PRId64 "] ", // stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, // nNewStatus, stChangeInfo.lTimes); SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,stChangeInfo.nValue ,stDigAlmPara); setAbnormalStatus(stDigPointAll,stDigAlmPara,nNewStatus); if (stDigPointAll.value != stChangeInfo.nValue) //当变化的值和实时库中的值不同时 { // 更新分量到实时库的值/状态/时间 //============================================================================================ if(false == updateDigitalPart(stChangeInfo,1)) //更新分量值到实时库 { LOGERROR("processOneDiChange::updateDigitalPart TagName=%s error!", stChangeInfo.tag_name); return -1; } nRetCode = processValueChange(stDigPointAll,stDigAlmPara,stChangeInfo.nValue,nNewStatus,stChangeInfo.lTimes,true); if (nRetCode < 0) { LOGERROR("ProcessValueChange error tag_name = %s", stChangeInfo.tag_name); } } else //当变化的值和实时库中的值相同时,状态不同 { if (stDigPointAll.status != nNewStatus)//值相同,状态不同,,需要更新实时库,发变化数据和写全景库 { if (false == updateDigStatus(stChangeInfo.tag_name,stChangeInfo.nStatus,nNewStatus,stChangeInfo.lTimes)) { LOGERROR("updateDigStatus tag_name = %s, updateDigStatus error!", stChangeInfo.tag_name); return -1; } m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system,\ RT_DIG_TBL, stChangeInfo.tag_name, "value", stChangeInfo.nValue,nNewStatus);//增加变位事件 } else//值和状态都相同,有可能是在全数据中已经更新过 { //LOGINFO("CHG SINGLE: tag_name=%s, old_value=nNewValue=%d, old_status=nNewStatus=%d", // stChangeInfo.tag_name, stChangeInfo.nValue, nNewStatus); } } } else //多分量处理 { //获取数字量分量号 //============================================================================================ int nDigPartIndex = getDigPartIndex(stChangeInfo,stDigPointAll.value_num) ; if( nDigPartIndex <1) { LOGERROR( "invalid nDigPartIndex:%d, nValueNum:%d, tag_name = %s, column_name = %s", nDigPartIndex,stDigPointAll.value_num,stChangeInfo.tag_name,stChangeInfo.column_name); return -1; } // 更新实时库的值/状态/时间 //============================================================================================ if(false == updateDigitalPart(stChangeInfo,nDigPartIndex)) //分量有变化,更新到RDB { LOGERROR("updateDigitalPart:: TagName=%s index=%d, error!", stChangeInfo.tag_name,nDigPartIndex); return -1; } //多分量延时时间=0 //=============================================================================================================== if( stDigPointAll.input_delay_time <= 0) stDigPointAll.input_delay_time = 1 ; if (stDigPointAll.input_delay_time <= 0) // { int valuex[MAX_DI_BIT_NUM]; int statusx[MAX_DI_BIT_NUM]; //备注:如果原来实时库值=2 (10)bit0新值=1/0 都无法通过判断,导致不报警 BUG initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuex,statusx int nResultValue = GetResultValueByValuex(stDigPointAll,&valuex[0], &statusx[0],&stChangeInfo); if (nResultValue < 0) { LOGINFO("GetResultValueByValuex,通过DI分量获取DI值错误,分量非法!"); return -1; } nNewStatus = stDigPointAll.status; for (int nLoop = 0; nLoop < nValueNum; ++nLoop) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus,statusx[nLoop],0,STATUS_ORI_RECV,1); } SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,nResultValue ,stDigAlmPara); setAbnormalStatus(stDigPointAll,stDigAlmPara,nNewStatus); if (stDigPointAll.value != nResultValue) { nRetCode = ProcessValueChange(stDigPointAll,stDigAlmPara,nResultValue,nNewStatus,stChangeInfo.lTimes,true); if (nRetCode < 0) { LOGERROR( " ProcessValueChange error tag_name = %s", stDigPointAll.tag_name); } } else { if (stDigPointAll.status != nNewStatus) { nRetCode = m_ptrRdbTableMng->updateRecordOneValueByKey(RT_DIG_TBL,(const void*)stChangeInfo.tag_name,"status",nNewStatus); if (nRetCode == false) { LOGERROR( "nRetCode = %d, updateRecordOneValueByKey error!", nRetCode); return -1; } m_ptrDataPublish->AddOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system,\ RT_DIG_TBL, stChangeInfo.tag_name, "value", nResultValue,nNewStatus); } else { LOGINFO(" CHG MULTI:tag_name=%s, old_value=nNewValue=%d, old_status=nNewStatus=%d ", stChangeInfo.tag_name, nResultValue, nNewStatus); } } } //多分量延时时间>=0,加入m_mapDiChgBuf //========================================================================================== else //数据量报警延时处理 { addDigPartToBuff(m_mapDiChgBuf, strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); } } return 1;*/ } /** @brief 处理一个DI点的变位,包括更新值和状态,写时序库,以及调用ProcessValueChange进行值变化处理; @param SChangeDiInfo stChangeInfo: IN 变化DI点信息结构 @return 成功>0 失败<=0 @retval */ void CDigProcess::addOneDigAlarm(int nAlarmType,const SDigPointAll &stDigPointAll,SDigAlarmPara &stDigAlmPara, const int64 lTimes,const string &strFaultDesc) { string strKeyIdTag = ""; strKeyIdTag = RT_DIG_TBL; strKeyIdTag += "."; strKeyIdTag += stDigPointAll.tag_name; strKeyIdTag += ".value"; int nAlarmStatus = ALM_STAT_SOE ; if(nAlarmType == ALM_TYPE_DI_CHANGE) //遥信变位 { nAlarmStatus = ALM_STAT_DI_CHANGE ; m_nChgAlarmCount = m_nChgAlarmCount+1; LOGDEBUG( "addOneDigAlarm::ChgAlarmCount=%d!",m_nChgAlarmCount); } if(nAlarmType == ALM_TYPE_SOE) { nAlarmStatus = ALM_STAT_SOE ; m_nSoeAlarmCount = m_nSoeAlarmCount+1; LOGDEBUG( "addOneDigAlarm::SoeAlarmCount=%d!",m_nSoeAlarmCount); } //初始化报警 故障值文本。。。。 string strAlarmDesc = stDigAlmPara.display_value; if(strlen(strFaultDesc.c_str())>0) { strAlarmDesc +=","; strAlarmDesc +=strFaultDesc ; } if(getDigAlarmStatus(nAlarmStatus,stDigPointAll.point_type,stDigPointAll.point_sort)== false) { LOGWARN( "addOneDigAlarm::getDigAlarmStatus error,tag_name=%s!",stDigPointAll.tag_name); } m_ptrDataPublish->addOneDigAlarm(stDigPointAll,nAlarmType,nAlarmStatus,stDigAlmPara.alarm_manner, strKeyIdTag,strAlarmDesc,lTimes); return ; } /** @brief 处理一个DI点的变位,包括更新值和状态,写时序库,以及调用ProcessValueChange进行值变化处理; @param SChangeDiInfo stChangeInfo: IN 变化DI点信息结构 @return 成功>0 失败<=0 @retval */ int CDigProcess::processOneSoeEvent(SChangeDiInfo &stChangeInfo,const string &strFaultDesc) { string strKeyIdTag = ""; strKeyIdTag = RT_DIG_TBL; strKeyIdTag += "."; strKeyIdTag += stChangeInfo.tag_name; strKeyIdTag += ".value"; LOGDEBUG("ProcessOneSoeEvent::strKeyIdTag = %s.%s.%s, value = %d,status = %d, times =[%" PRId64 "].", stChangeInfo.table_name, stChangeInfo.tag_name, stChangeInfo.column_name, stChangeInfo.nValue, stChangeInfo.nStatus, stChangeInfo.lTimes); //得到指定标签点的实时库记录 //============================================================================================================== SDigPointAll stDigPointAll; int nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,stChangeInfo.tag_name,stDigPointAll); if (nRetCode <=0 ) { LOGERROR("ProcessOneSoeEvent:: nRetCode = %d, tag_name = %s, getRecordAllColumnByKey error!", nRetCode, stChangeInfo.tag_name); return -1; } //设备禁止报警等,不报警 , SOE 不判断通讯状态 //============================================================================================================= if(true == checkAlarmDisable(stDigPointAll.status,POINT_TYPE_DIG)) { LOGINFO("ProcessOneSoeEvent:: 禁止告警,tag_name = %s, return 1 ", stChangeInfo.tag_name); return 1; } //置数、禁止刷新时不写事件,不写实时值 //============================================================================================================= if (stDigPointAll.value_num == 1) { SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPointAll,stChangeInfo.nValue ,stDigAlmPara); //产生SOE事件 //========================================================================================================= addOneDigAlarm(ALM_TYPE_SOE,stDigPointAll,stDigAlmPara,stChangeInfo.lTimes,strFaultDesc) ; } //多分量情况 //============================================================================================================= else { int nDigPartIndex = getDigPartIndex(stChangeInfo,stDigPointAll.value_num) ; if (nDigPartIndex < 0) { LOGERROR( "ProcessOneSoeEvent::getDigPartIndex index<0 error."); return -1; } //多分量延时时间=0 //========================================================================================================= if (stDigPointAll.input_delay_time <= 0) //SOE 多位延迟最少1秒 stDigPointAll.input_delay_time = 1 ; addDigPartToBuff(m_mapDiSoeBuf,strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); //SOE分量加入队列,进行延时判断 /* if (stDigPointAll.input_delay_time <= 0) // { int valuex[MAX_DI_BIT_NUM] ={0}; int statusx[MAX_DI_BIT_NUM]={0}; //多分量的情况,保证只有一个分量的值为1,如果分量全部为0也不对; //==================================================================================================== initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuex,statusx int nResultValue = getResultValueByValuex(stDigPointAll,&valuex[0], &statusx[0],&stChangeInfo); if (nResultValue < 0) { LOGINFO("ProcessOneSoeEvent::GetResultValueByValuex,通过DI分量获取DI值错误,分量非法!"); return -1; } //增加SOE 事件发送到报警服务器 //==================================================================================================== SDigAlarmPara stDigAlmPara; nRetCode = getDigAlarmPara(stDigPointAll,nResultValue ,stDigAlmPara); //获取状态文本失败 addOneDigAlarm(ALM_TYPE_SOE,stDigPointAll,stDigAlmPara,stChangeInfo.lTimes,strFaultDesc) ; } //多分量延时时间>=0,加入m_mapDiChgBuf //======================================================================================================== else //数据量报警延时处理 { addDigPartToBuff(m_mapDiSoeBuf,strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); }*/ } return 1; } /** @brief 得到数字量报警参数,如:报警方式,数字量文本等 @param INT SDigPointAll& stDigPointAll:测点RDB实时信息 INT SDigAlarmPara &stDigAlmPara:报警输出参数 @return 失败<0 成功=0 @retval */ int CDigProcess::getDigAlarmPara(const SDigPointAll& stDigPointAll,int nValue,SDigAlarmPara &stDigAlmPara) { int nRetCode = -1 ; SDigAlarmInfo stDigAlmInfo; strcpy(stDigAlmInfo.state_text_name, stDigPointAll.state_text_name); stDigAlmInfo.value = nValue; stDigAlmInfo.alarm_priority = stDigPointAll.alarm_priority; stDigAlmInfo.is_water_alm = stDigPointAll.is_water_alm; stDigAlmInfo.is_ack_on_rtn = stDigPointAll.is_ack_on_rtn; nRetCode = m_ptrDataProcApi->getDigAlarmPara(stDigAlmInfo, stDigAlmPara); if (nRetCode <0 ) { LOGDEBUG("getDigAlarmPara::tag_name(%s), getDigAlarmPara error!", stDigPointAll.tag_name); } //LOGDEBUG("getDigAlarmPara:测点[%s] 数字量文本=[%s],值=[%d],报警方式=[%d],未复归=[%d]!",stDigPointAll.tag_name, // stDigPointAll.state_text_name, nValue,stDigAlmPara.alarm_manner,stDigAlmPara.is_abnormal); return nRetCode; } /** @brief 增加数字量分量到缓冲区 @param IN string strKeyIdTag :测点KEY 标签 IN const int nIndex :分量号 OUT mapDiChgBuf:数字量缓冲去 INT SDigPointAll& stDigPointAll:测点RDB实时信息 INT SChangeDiInfo &stChangeInfo:测点FES变化信息 @return 无 @retval */ void CDigProcess::addDigPartToBuff(std::map &mapDiChgBuf,const string strKeyIdTag, const int nIndex,const SDigPointAll& stDigPointAll,const SChangeDiInfo stChangeInfo) { map ::iterator itPos; string strTagName = stChangeInfo.tag_name; itPos = mapDiChgBuf.find(strTagName); if (itPos == mapDiChgBuf.end()) //缓冲区没有找到 { SDiChange stDiChgInfo; strcpy(stDiChgInfo.key_id_tag, strKeyIdTag.c_str()); strcpy(stDiChgInfo.state_text_name, stDigPointAll.state_text_name); stDiChgInfo.first_chg_time = (int64)getMonotonicMsec(); //初次变位时间 stDiChgInfo.location_id = stDigPointAll.location_id; stDiChgInfo.region_id = stDigPointAll.region_id; stDiChgInfo.input_delay_time = stDigPointAll.input_delay_time; stDiChgInfo.value_num = stDigPointAll.value_num; stDiChgInfo.di_bit_chg_array[nIndex - 1].use_flag = SHARE_BUF_USE; stDiChgInfo.di_bit_chg_array[nIndex - 1].value = stChangeInfo.nValue; stDiChgInfo.di_bit_chg_array[nIndex - 1].status = stChangeInfo.nStatus; stDiChgInfo.di_bit_chg_array[nIndex - 1].times = stChangeInfo.lTimes; mapDiChgBuf.insert(make_pair(strTagName, stDiChgInfo)); } else { itPos->second.di_bit_chg_array[nIndex - 1].use_flag = SHARE_BUF_USE; itPos->second.di_bit_chg_array[nIndex - 1].value = stChangeInfo.nValue; ; itPos->second.di_bit_chg_array[nIndex - 1].status = stChangeInfo.nStatus; itPos->second.di_bit_chg_array[nIndex - 1].times = stChangeInfo.lTimes; } return; } /** @brief 初始化数字化分量值和状态到数组valuex,statusx @param IN SDigPointAll stDigPoint:测点RDB实时值 OUT value[MAX_DI_BIT_NUM]: DI分量数据 OUT statusx[MAX_DI_BIT_NUM]:DI分量状态 @return 无 @retval */ void CDigProcess::initValuexStatusx(const SDigPointAll &stDigPoint,int *valuex,int *statusx) { if(valuex == NULL|| statusx == NULL) return; valuex[0] = stDigPoint.value1; valuex[1] = stDigPoint.value2; valuex[2] = stDigPoint.value3; valuex[3] = stDigPoint.value4; valuex[4] = stDigPoint.value5; statusx[0] = stDigPoint.status1; statusx[1] = stDigPoint.status2; statusx[2] = stDigPoint.status3; statusx[3] = stDigPoint.status4; statusx[4] = stDigPoint.status5; return; } /** @brief 通过DI 分量获取 DI值是 @param IN SDigPointAll stDigPoint:测点RDB实时值 IN SChangeDiInfo stChangeInfo:测点变化数据 OUT value[MAX_DI_BIT_NUM]: DI分量数据 OUT statusx[MAX_DI_BIT_NUM]:DI分量状态 @return DI值 @retval */ int CDigProcess::getValueByValuex(const int nValueNum,int *valuex,int */*statusx*/) { int nLoop; int nRetValue = 0; //分量数最大值判断 //========================================================================================================== if ((nValueNum > MAX_DI_BIT_NUM) ) { LOGERROR( "getValueByValuex:分量数[%d]>MAX_DI_BIT_NUM Error", nValueNum); return -1; } //分量值按位合并,从低到高[bit0~bt4]对应分量1~5 //========================================================================================================== int nCount = 0; //分量值=1数量统计 for (nLoop = 0; nLoop < nValueNum; ++nLoop) { if (valuex[nLoop]) //分量=1 { nCount++; nRetValue += (1 << nLoop) ; } } return nRetValue; //分量有效判断 //========================================================================================================== /* if(nValueNum>1) { if((nRetValue ==0) || (nRetValue == ((1<tm_year + 1900, pCurTime->tm_mon + 1, pCurTime->tm_mday, pCurTime->tm_hour, pCurTime->tm_min, pCurTime->tm_sec, sMsec); } else { sprintf(cTimeBuf, "%04d年%02d月%02d日%02d时%02d分%02d秒", pCurTime->tm_year + 1900, pCurTime->tm_mon + 1, pCurTime->tm_mday, pCurTime->tm_hour, pCurTime->tm_min, pCurTime->tm_sec); strcat(cTimeBuf, " "); } return; } /*--------------------------------------------------------------------------------- - 函 数 名: StripWhiteSpace - 功能描述: Returns a string that has whitespace removed from the start and the end of the string Whitespace means any character for which QChar::isSpace() returns TRUE. This includes UNICODE characters with decimal values 9 (TAB), 10 (LF), 11 (VT),12 (FF), 13 (CR), and 32 (Space). - 输 入: source_str - 输 出: des_str -------------------------------------------------------------------------------------*/ void CDigProcess::stripWhiteSpace(char *des_str, const char *source_str) { int nLoop; int start_pos, end_pos; int source_str_len; source_str_len = strlen(source_str); start_pos = 0; for (nLoop = 0; nLoop < source_str_len; ++nLoop ) { if ( (source_str[nLoop] != 9) && (source_str[nLoop] != 10) && (source_str[nLoop] != 11) && (source_str[nLoop] != 12) && (source_str[nLoop] != 13) && (source_str[nLoop] != 32) ) { //start_pos = nLoop; break; } else { ++start_pos; } } end_pos = source_str_len - 1; for (nLoop = source_str_len - 1; nLoop >= 0; nLoop-- ) { if ( (source_str[nLoop] != 9) && (source_str[nLoop] != 10) && (source_str[nLoop] != 11) && (source_str[nLoop] != 12) && (source_str[nLoop] != 13) && (source_str[nLoop] != 32) ) { break; } else { end_pos--; } } if (start_pos > end_pos) { des_str[0] = 0; } else { int des_str_len = end_pos - start_pos + 1; memcpy(des_str, source_str + start_pos, des_str_len); des_str[des_str_len] = 0; } } /** @brief 处理人工置数/取消人工置数/取消禁止刷新等,生成报警结构体,调用函数产生报警 @param const char *strTagName: int flag:SET_DATA_FLAG,1; UN_SET_DATA_FLAG,2;UN_INHABIT_REF_FLAG,3 @return 无 @retval */ int CDigProcess::processSetData(SDigPointAll &stDigPoint,const int nNewValue,const int nNewStatus ,const bool bNotAlarm ) { int nRetCode = -1; string strKeyTagName = stDigPoint.tag_name; int nValueNum = stDigPoint.value_num; if ( (nValueNum < 1) || (nValueNum > MAX_DI_BIT_NUM)) { LOGWARN("ProcessSetData: nValueNum = %d is invalid (tag_name = %s)",stDigPoint.value_num, stDigPoint.tag_name); return -1; } strKeyTagName.resize(64); nRetCode = m_ptrRdbTableMng->updateRecordTwoValueByKey(RT_DIG_TBL, strKeyTagName.c_str(),"value", nNewValue,"status",nNewStatus); if (nRetCode == false) { LOGWARN( "ProcessSetData, nRetCode = %d, strTableName = %s, strTagName = %s, value = %d, status = %d, updateRecordByKey error!", nRetCode,RT_DIG_TBL, stDigPoint.tag_name, nNewValue, nNewStatus); return -1; } //不是人工设置 || 值没有发生改变 if( stDigPoint.value == nNewValue ) { LOGINFO("ProcessSetData,OldValue[%d]=NewValue[%d],return 1",stDigPoint.value,nNewValue); return 1; //value not change return; } stDigPoint.value = nNewValue ; //更新值 用于报警 stDigPoint.status = nNewStatus ; //更新值 用于报警 SDigAlarmPara stDigAlmPara; getDigAlarmPara(stDigPoint,stDigPoint.value ,stDigAlmPara); bool bAlarmDisable = checkAlarmDisable(nNewStatus,POINT_TYPE_DIG) ; if (stDigAlmPara.is_send_alarm &&(bNotAlarm == false) && (bAlarmDisable == false)) //状态变化 { addOneDigAlarm(ALM_TYPE_DI_CHANGE,stDigPoint,stDigAlmPara) ; } return 1; } /** @brief 置数、取消置数、取消禁止刷新处理,操作数据处理入口 @param const SLockDataPkg &stTransDataPkg @return 无 @retval */ int CDigProcess::processOperate(const SOptSetDataPkg &stOptSetDataPkg,const int nOperateType) { int nNum = 0; int nRetCode = 0; nNum = stOptSetDataPkg.seq_set_data_info_size(); bool bInit = stOptSetDataPkg.package_head().b_not_alarm() ; for (int nLoop = 0; nLoop < nNum; nLoop++) { int nNewStatus; SOptSetDataMsg stOptSetData = stOptSetDataPkg.seq_set_data_info(nLoop); string strTableName = RT_DIG_TBL; string strTagName = stOptSetData.str_tag_name(); int nNewValue = stOptSetData.var_value().nvalue() ; int nAddStatus = stOptSetData.u_add_status(); int nDelStatus = stOptSetData.u_del_status(); SDigPointAll stDigPoint; string strKeyTagName = strTagName; strKeyTagName.resize(64); //得到指定标签点的实时库记录 //============================================================================================================= nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,strKeyTagName.c_str(),stDigPoint); if (nRetCode <=0 ) { LOGERROR("nRetCode = %d, tag_name = %s, getRecordAllColumnByKey error!",nRetCode, strKeyTagName.c_str()); continue; } //状态字处理,如果计算点过来的值没有增加删除状态,保证计算点状态有效 //============================================================================================================= if(nAddStatus == 0 && nDelStatus == 0) { nDelStatus = (1<getNewStatus(TYPE_STATUS_DI, nNewStatus,stDigPoint.status,nAddStatus,nDelStatus,STATUS_ORI_OPT); if(nRetCode < 0) { LOGWARN( "processOperate:getNewStatus Error, strTagName = %s error!",stDigPoint.tag_name); continue; } if(stDigPoint.status == nNewStatus && nNewValue == stDigPoint.value) { LOGDEBUG( "processOperate:status=NewStatus && nNewValue=value ,strTagName = %s!",stDigPoint.tag_name); m_ptrDataPublish->addOneChangeInt(stDigPoint.location_id,stDigPoint.sub_system,strTableName, strTagName, "value", nNewValue, nNewStatus); continue; } //初始化缓存队列字段信息 STagStatusValue stTagInfo ; stTagInfo.strTagName = stDigPoint.tag_name; stTagInfo.lTimes = stDigPoint.last_update_time; stTagInfo.unValue.nValue = stDigPoint.value ; stTagInfo.nStatus = stDigPoint.status; UTagValue unSetValue; unSetValue.nValue = nNewValue ; LOGDEBUG( "processOperate:strTagName = %s ,NewStatus=%d nNewValue=%d !",stDigPoint.tag_name,nNewStatus,nNewValue); //< 计算服务计算点处理,fbd_server 如果:测点已经人工置数|静止刷新->更新缓冲再直接返回 //============================================================================================================= if(OPT_TYPE_CAL_SET == nOperateType) { if((stDigPoint.point_property & (1<<0)) == 0) //采集点 { LOGDEBUG("processOperate::操作错误,对采集点[%s]人工置数,请检查配置!",stDigPoint.tag_name); return 1; } nRetCode = checkTagStatus(stDigPoint.tag_name,stDigPoint.status, unSetValue,stDigPoint.last_update_time, POINT_TYPE_DIG);//禁止刷新 保存旧的值 if (nRetCode == false) { LOGDEBUG("processOperate::checkTagStatus() tag_name = %s, newValue = %d, status = %d NewStatus = %d ! ", stDigPoint.tag_name, nNewValue, stDigPoint.status, nNewStatus); return 1; } } //如果禁止刷新,保存标签数据 ;否则,还原标签数据 //============================================================================================================= else if(nOperateType == OPERATE_TYPE) { if(procTagOperate(nAddStatus,nDelStatus,unSetValue,stTagInfo,POINT_TYPE_DIG)== false) //针对人工置数等OPT操作 { LOGERROR("CAnaProcess::procOneAnaChange,procTagOperate Error tagname=%s ",stDigPoint.tag_name); } nNewValue = stTagInfo.unValue.nValue ; //取消操作,值来自保存的队列,添加状态为人工置数<-设置值unSetValue } //处理人工置数/取消人工置数/取消禁止刷新等,生成报警结构体,调用函数产生报警 //============================================================================================================= if(processSetData(stDigPoint, nNewValue, nNewStatus,bInit) <0) { LOGWARN( "ProcessSetData, strTableName = %s, strTagName = %s, nNewValue = %d, nNewValue = %d, error!", RT_DIG_TBL, strTagName.c_str(), nNewStatus,nNewStatus); continue; } m_ptrDataPublish->addOneChangeInt(stDigPoint.location_id,stDigPoint.sub_system,strTableName, strTagName, "value", nNewValue, nNewStatus); } return 1; } /** @brief 通过测定状态字获取 工况状态和有效状态; @param bool &bIsTxOff OUT 是否工况推出 bool &bIsInvalid OUT 是否有效 const SDigPointAll &stDigPoint: INT DI RTB结构 @return 1:成功 <0 失败 @retval */ int CDigProcess::getDigSpelStatus(bool &bIsTxOff, bool &bIsInvalid,const SDigPointAll &stDigPoint) { bIsTxOff = false; bIsInvalid = false; if ( (stDigPoint.value_num < 1) || (stDigPoint.value_num > MAX_DI_BIT_NUM)) { LOGINFO( "nValueNum = %d is invalid (tag_name = %s)", stDigPoint.value_num, stDigPoint.tag_name); return -1; } for (int j = 0; j != stDigPoint.value_num; ++j) { if ((bIsTxOff) && (bIsInvalid) ) { break; } if (j == 0) { if (stDigPoint.status1 & (1 << m_nMenuStateDiGkOff)) { bIsTxOff = true; } if (stDigPoint.status1 & (1 << m_nMenuStateDiInvalid)) { bIsInvalid = true; } } else if (j == 1 ) { if (stDigPoint.status2 & (1 << m_nMenuStateDiGkOff)) { bIsTxOff = true; } if (stDigPoint.status2 & (1 << m_nMenuStateDiInvalid)) { bIsInvalid = true; } } else if (j == 2) { if (stDigPoint.status3 & (1 << m_nMenuStateDiGkOff)) { bIsTxOff = true; } if (stDigPoint.status3 & (1 << m_nMenuStateDiInvalid)) { bIsInvalid = true; } } else if (j == 3) { if (stDigPoint.status4 & (1 << m_nMenuStateDiGkOff)) { bIsTxOff = true; } if (stDigPoint.status4 & (1 << m_nMenuStateDiInvalid)) { bIsInvalid = true; } } else if (j == 4) { if (stDigPoint.status5 & (1 << m_nMenuStateDiGkOff)) { bIsTxOff = true; } if (stDigPoint.status5 & (1 << m_nMenuStateDiInvalid)) { bIsInvalid = true; } } } return 1; } /** @brief Di量变化处理;包括更新值/状态,处理报警计时,报警计次 @param nTypeFlag: DI_UPDATE_TYPE:来源于全数据 ; DI_CHANGE_TYPE:来源于变化数据 bIsActualChg:0 在本进程重启后在本包全数据之前点表中的值未被全数据更新情况下全数据报文判出的变化数据 1 在本进程重启后在本包全数据之前点表中的值已被全数据更新后全数据报文判出的变化数据,或者变化报文判出的变化数据 @return 1:成功 0 失败 @retval */ int CDigProcess::processValueChange(const SDigPointAll &stDigPointAll,SDigAlarmPara &stDigAlmPara, int nChgValue,int nNewStatus,int64 lUpdateTime,bool bIsActualChg) { bool bAlarmDisable = checkAlarmDisable(nNewStatus,POINT_TYPE_DIG,false) ; //置数、禁止刷新时不写事件,不写实时值 //==================================================================================================== UTagValue utValue ; utValue.nValue = nChgValue; if(false == checkTagStatus(stDigPointAll.tag_name,stDigPointAll.status, utValue,stDigPointAll.last_update_time, POINT_TYPE_DIG))//禁止刷新 保存旧的值 { LOGDEBUG("测点[%s],状态[%d] 人工置数/禁止刷新!", stDigPointAll.tag_name, stDigPointAll.status); return 0; } LOGDEBUG("ProcessValueChange tag_name[%s], is_send_alarm=%d, bIsNeedAlarm=%d,Status=%d bIsActualChg=%d", stDigPointAll.tag_name,stDigAlmPara.is_send_alarm,bAlarmDisable,nNewStatus,bIsActualChg); if ( stDigAlmPara.is_send_alarm && bIsActualChg && (bAlarmDisable == false)) { if (stDigAlmPara.is_alm_not_ack) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 1 << m_nMenuStateDiAlmNotAck, 0, STATUS_ORI_RECV); //add m_nMenuStateDiAlmNotAck } else { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nNewStatus, 0, 1 << m_nMenuStateDiAlmNotAck, STATUS_ORI_RECV); //del m_nMenuStateDiAlmNotAck } if(stDigPointAll.value != nChgValue) //值发送变化,产生告警 { addOneDigAlarm(ALM_TYPE_DI_CHANGE,stDigPointAll,stDigAlmPara,lUpdateTime) ; } } //LOGDEBUG("ProcessValueChange:updateRecordMultiValueByKey tag_name = %s, value = %d, nNewStatus = %d ", // stDigPointAll.tag_name, nResultValue,nNewStatus); if(false == updateDigValStatus(stDigPointAll.tag_name, nChgValue,nNewStatus,lUpdateTime)) { LOGERROR("ProcessValueChange,tag_name = %s,updateDigValStatus error!",stDigPointAll.tag_name); } //发生状态变位实时值到消息总线(HMI...) m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system,\ RT_DIG_TBL, stDigPointAll.tag_name, "value", nChgValue,nNewStatus); return 1; } /** @brief 处理报警计时,新报警增加到map;报警返回删除 @param int nAlarmStyle :报警类型 SDiAlarm *stDiAlarmStru:DI报警信息结构 @return 无 @retval */ void CDigProcess::processAlarmTime(int nAlarmStyle, SDiAlarm *stDiAlarm) //处理报警计时 { map ::iterator pos; string strTagName = stDiAlarm->tag_name; if (nAlarmStyle == m_mapAlarmStyle["MENU_RTNALARM_AND_EVENT"])//报警返回删除 { pos = m_mapDiAlarmTimeBuf.find(strTagName); if (pos != m_mapDiAlarmTimeBuf.end())//MAP找到该点 { m_mapDiAlarmTimeBuf.erase(pos); } } else if (nAlarmStyle == m_mapAlarmStyle["MENU_ALARM_AND_EVENT"])//新报警增加到map { m_mapDiAlarmTimeBuf[strTagName] = *stDiAlarm; } else if (nAlarmStyle == m_mapAlarmStyle["MENU_EVENT_ONLY"]) { LOGINFO("tag_name = %s, if_alarm_time = 1,nAlarmStyle = MENU_EVENT_ONLY", stDiAlarm->tag_name); } else if (nAlarmStyle == m_mapAlarmStyle["MENU_DO_NOTHING"]) { LOGINFO( "tag_name = %s, if_alarm_time = 1,nAlarmStyle = MENU_DO_NOTHING", stDiAlarm->tag_name); } LOGINFO("ProcessAlarmTime m_mapDiAlarmTimeBuf.size() = %d",(int)m_mapDiAlarmTimeBuf.size()); return; } /** @brief 检查报警计时,m_mapDiAlarmTimeBuf 删除无用信息,有DI变位发送实时数据 @param 无 @return 无 @retval */ void CDigProcess::checkAlarmTimeBuf() { int nRetCode; LOGINFO("CheckAlarmTimeBuf m_mapDiAlarmTimeBuf.size() = %d",(int)m_mapDiAlarmTimeBuf.size()); int64 ulCurMsec = (int64)getMonotonicMsec(); map ::iterator pos; for (pos = m_mapDiAlarmTimeBuf.begin(); pos != m_mapDiAlarmTimeBuf.end(); ) { if ((ulCurMsec - pos->second.occur_time) > pos->second.alarm_time*1000) { SDigPointAll stDigPointAll; //AddOneDigAlarm((SDiAlarm *)(&(pos->second)), "CheckAlarmTimeBuf", ALARM_TIME_FLAG); //RDB找不到这个点 nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,pos->second.tag_name,stDigPointAll); if (nRetCode <=0 ) { LOGERROR("nRetCode = %d, tag_name = %s, Read error!", nRetCode, pos->second.tag_name); m_mapDiAlarmTimeBuf.erase(pos++); continue; } //实际上只需要修改status if (pos->second.is_alm_not_ack) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, stDigPointAll.status, stDigPointAll.status, 1 << m_nMenuStateDiAlmNotAck, 0, STATUS_ORI_RECV); //add m_nMenuStateDiAlmNotAck } else { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, stDigPointAll.status, stDigPointAll.status, 0, 1 << m_nMenuStateDiAlmNotAck, STATUS_ORI_RECV); //del m_nMenuStateDiAlmNotAck } nRetCode = m_ptrRdbTableMng->updateRecordOneValueByKey(RT_DIG_TBL, pos->second.tag_name,"status",stDigPointAll.status); if (nRetCode == false) { LOGERROR("nRetCode = %d, tag_name = %s, TableModifyByKey error!", nRetCode, pos->second.tag_name); m_mapDiAlarmTimeBuf.erase(pos++); continue; } m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system, \ RT_DIG_TBL, pos->second.tag_name, "value",\ stDigPointAll.value, stDigPointAll.status); m_mapDiAlarmTimeBuf.erase(pos++); } else { ++pos; } } return; } /** @brief 处理报警计次,维护m_mapDiAlarmFreqBuf,报警次数>报警设定计次,增加DI报警信息 @param int nAlarmStyle:报警方式 SDiAlarm *stDiAlarmStru:报警信息结构体 bool &bIsCreateAlarm:OUT 是否新增加报警 @return 无 @retval */ void CDigProcess::processAlarmFreq(int nAlarmStyle, SDiAlarm *stDiAlarmStru, bool &bIsCreateAlarm) { bIsCreateAlarm = false; map ::iterator pos; SAlarmFreq stFreqInfo; string strTagName = stDiAlarmStru->tag_name; if (nAlarmStyle == m_mapAlarmStyle["MENU_ALARM_AND_EVENT"]) //报警和事件 { pos = m_mapDiAlarmFreqBuf.find(strTagName); if (pos != m_mapDiAlarmFreqBuf.end()) //队列存在该测定报警信息 { stFreqInfo = pos->second ; ++stFreqInfo.now_alarm_freq; LOGINFO("stFreqInfo.now_alarm_freq = %d, stDiAlarmStru->alarm_freq = %d",\ stFreqInfo.now_alarm_freq, stDiAlarmStru->alarm_freq); if (stFreqInfo.now_alarm_freq >= stDiAlarmStru->alarm_freq )//报警次数>报警设定计次 { //AddOneDigAlarm(stDiAlarmStru, "ProcessAlarmFreq", ALARM_FREQ_FLAG); bIsCreateAlarm = true; m_mapDiAlarmFreqBuf.erase(pos); } else { m_mapDiAlarmFreqBuf[strTagName] = stFreqInfo; } } else { SAlarmFreq stFreqInfo; stFreqInfo.now_alarm_freq = 1; stFreqInfo.alarm_stru = *stDiAlarmStru; m_mapDiAlarmFreqBuf[strTagName] = stFreqInfo; } } else if (nAlarmStyle == m_mapAlarmStyle["MENU_EVENT_ONLY"]) { LOGINFO("tag_name = %s, if_alarm_freq = 1,nAlarmStyle = MENU_EVENT_ONLY",strTagName.c_str()); } else if (nAlarmStyle == m_mapAlarmStyle["MENU_DO_NOTHING"]) { LOGINFO("tag_name = %s, if_alarm_freq = 1,nAlarmStyle = MENU_EVENT_ONLY",strTagName.c_str()); } LOGINFO("ProcessAlarmFreq m_mapDiAlarmFreqBuf.size() = %d",(int)m_mapDiAlarmFreqBuf.size()); return; } /** @brief 检查报警次数 @param 无 @return 无 @retval */ void CDigProcess::checkAlarmFreqBuf() { LOGINFO("CheckAlarmFreqBuf m_mapDiAlarmFreqBuf.size() = %d", (int)m_mapDiAlarmFreqBuf.size()); int64 ulCurMsec = (int64)getMonotonicMsec() ; map ::iterator pos; for (pos = m_mapDiAlarmFreqBuf.begin(); pos != m_mapDiAlarmFreqBuf.end(); ) { if((ulCurMsec - pos->second.alarm_stru.occur_time) > (pos->second.alarm_stru.is_alarm_freq*1000) ) { m_mapDiAlarmFreqBuf.erase(pos++); } else { ++pos; } } } /** @brief 处理DI报警延时,需要延迟的报警先放入延迟报警队列 @param SDiAlarm *pDiAlarm IN 需要延迟报警信息 @return DI值 @retval */ void CDigProcess::processAlarmDelay(SDiAlarm *pDiAlarm) { string strTagName = pDiAlarm->tag_name; m_mapDiAlarmDelayBuf[strTagName] = *pDiAlarm; LOGINFO("ProcessAlarmDelay m_mapDiAlarmDelayBuf.size() = %d",(int)m_mapDiAlarmDelayBuf.size()); return; } /** @brief 处理DI报警延时,需要延迟的报警先放入延迟报警队列 @param SDiAlarm *pDiAlarm IN 需要延迟报警信息 @return DI值 @retval */ void CDigProcess::checkAlarmDelayBuf() { int nRetCode; map ::iterator pos; int64 ulCurMsec = getMonotonicMsec(); //LOGDEBUG("CheckAlarmDelayBuf m_mapDiAlarmDelayBuf.size() = %d", m_mapDiAlarmDelayBuf.size()); for (pos = m_mapDiAlarmDelayBuf.begin(); pos != m_mapDiAlarmDelayBuf.end(); ) { if((ulCurMsec - pos->second.occur_time) > pos->second.alarm_delay_time*1000 ) { SDigPointAll stDigPointAll; //AddOneDigAlarm((SDiAlarm *)(&(pos->second)), "CheckAlarmDelayBuf"); nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL, pos->second.tag_name, stDigPointAll); if (nRetCode <=0 ) { LOGINFO("nRetCode = %d, tag_name = %s, TableGetByKey error!", nRetCode, pos->second.tag_name); m_mapDiAlarmDelayBuf.erase(pos++); continue; } //只需要修改status if (pos->second.is_alm_not_ack) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, stDigPointAll.status, stDigPointAll.status, 1 << m_nMenuStateDiAlmNotAck, 0, STATUS_ORI_RECV); //add m_nMenuStateDiAlmNotAck } else { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, stDigPointAll.status, stDigPointAll.status, 0, 1 << m_nMenuStateDiAlmNotAck, STATUS_ORI_RECV); //del m_nMenuStateDiAlmNotAck } nRetCode = m_ptrRdbTableMng->updateRecordOneValueByKey(RT_DIG_TBL, pos->second.tag_name,"status", stDigPointAll.status); if (nRetCode == false) { LOGERROR("nRetCode = %d, tag_name = %s, updateRecordOneValueByKey error!", nRetCode, pos->second.tag_name); m_mapDiAlarmDelayBuf.erase(pos++); continue; } m_ptrDataPublish->addOneChangeInt(stDigPointAll.location_id,stDigPointAll.sub_system, \ RT_DIG_TBL, pos->second.tag_name, "value", stDigPointAll.value, stDigPointAll.status); m_mapDiAlarmDelayBuf.erase(pos++); } else { ++pos; } } return; } /** @brief 通过设备分组得到RTU信息 @param 无 @return 无 @retval */ int CDigProcess::getRtuTag(const int nAlmGrpId, vector &vecRtuTagName, const int nDomainId /*=-1*/) { vecRtuTagName.clear(); vector vecFesGroupDevSelect; std::vector strSelColumn ={"tag_name","nDomainId"} ; int nRetCode = m_ptrRdbTableMng->selectSelColumnOneCondition("fes_group_dev",strSelColumn,vecFesGroupDevSelect,"alarm_group_id",nAlmGrpId); if (nRetCode == false) { LOGERROR("GetRtuTag, ret = %d, alarm_group_id = %d, table_name = fes_group_dev, m_Rdbmng.ConGet error!", nRetCode, nAlmGrpId); return -1; } for (vector::size_type i = 0; i != vecFesGroupDevSelect.size(); ++i) { if (nDomainId != -1 && nDomainId != vecFesGroupDevSelect[i].domain_id) { continue; } vector vecFesRtuDevSelect; nRetCode = m_ptrRdbTableMng->selectOneColumnOneCondition("fes_rtu_dev","tag_name",vecFesRtuDevSelect ,\ "group_tag",vecFesGroupDevSelect[i].tag_name); if (nRetCode == false) { LOGERROR("GetRtuTag, ret = %d, group_tag = %s, table_name = fes_rtu_dev, m_Rdbmng.ConGet error!", nRetCode, vecFesGroupDevSelect[i].tag_name); continue; } for (vector::size_type j = 0; j != vecFesRtuDevSelect.size(); ++j) { vecRtuTagName.push_back(vecFesRtuDevSelect[j]); } } if (vecRtuTagName.size() < 1) { LOGWARN("GetRtuTag, record_app = %d, nAlmGrpId = %d, can't find any rtu!", m_stRunAppInfo.nAppId, nAlmGrpId); } return 0; }