2025-03-12 18:14:45 +08:00

2625 lines
99 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
@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"
#include <bitset>
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;
}
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") ) == iotFailed)
{
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<RSQL_UPD_COLUMN> 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<RSQL_UPD_COLUMN> 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<RSQL_UPD_COLUMN> 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<RSQL_UPD_COLUMN> 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 <string, int>::iterator pos;
string strTagName = stUpdateDiInfo.tag_name;
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_nMenuStateDiGkOff)) //
&& !(stUpdateDiInfo.status & (1 << m_nMenuStateDiGkOff)) )
{
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<string, int> 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~5status1~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;
//新值=未复归,老状态已经复归 ==>状态字增加未复归
if ( stDigAlmPara.is_abnormal && !(nOldStatus & (1 << m_nMenuStateDiAbnormal)) )
{
m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,1 << m_nMenuStateDiAbnormal,0,
STATUS_ORI_RECV); //del DiAbnormal flag
}
else if ( !stDigAlmPara.is_abnormal && (nOldStatus & (1 << m_nMenuStateDiAbnormal)) )
{
m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,0,1 << m_nMenuStateDiAbnormal,
STATUS_ORI_RECV); //add DiAbnormal flag
}
//LOGDEBUG("setAbnormalStatus 标签点[%s] 未复归=[%d],旧状态=[%d],新状态=[%d].",stDigPoint.tag_name,
// stDigAlmPara.is_abnormal,nOldStatus,nNewStatus);
return;
}
/**
@brief 数字量变为更新事实库 VALUE1~5 到VALUE ,status 等的值
@param map<string, int> &mapUpdatePoint变化点MAP
bool bValidChange 是否有效变位
int second int msecond时间
@return 无
@retval
*/
void CDigProcess::updateDigValueStatus(map<string, int> &mapUpdatePoint,
bool bValidChange, int64 lUpdateTimes)
{
int nRetCode;
int nNewStatus;
int nNewValue;
map <string, int>::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( "UpdateDigValueStatusnRetCode = %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]);//初始化分量值到valuexstatusx
nNewValue = getValueByValuex(stDigPointAll.value_num,&valuex[0],&statusx[0]); //得到合成值
if (nNewValue < 0)
{
LOGINFO("UpdateDigValueStatusgetValueByValuex 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("getStatusByStatusxGetDiStatusSpelFlag 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()
{
map <string, SDiChange>::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) )
{
processDiWithMultiVal(pos->first,pos->second); //到达防抖时间,从缓存中清理
m_mapDiChgBuf.erase(pos++);
}
else
{
++pos;
}
}
return;
}
void CDigProcess::checkDiChgBuf_bak()
{
int nRetCode;
int nResultValue;
int nValueNum;
int nNewStatus;
int64 nLastChgMescond = 0;
map <string, SDiChange>::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]);//初始化分量值到valuexstatusx
//获得最新报警时间
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<RSQL_UPD_COLUMN> 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()
{
map <string, SDiChange>::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))
{
processDiSOEWithMultiVal(pos->first,pos->second); //到达防抖时间,从缓存中清理
m_mapDiSoeBuf.erase(pos++);
}
else
{
++pos;
}
}
return;
}
void CDigProcess::checkDiSoeBuf_bak()
{
int nRetCode;
map <string, SDiChange>::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]);//初始化分量值到valuexstatusx
//获得最新报警时间 报警分量信息初始化到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)
{
LOGDEBUG("ProcessDiChange:收到变化数据报文,数目[%d],时间[%" PRId64 "].",nChangeNum,(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~5status1~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);
//如果多个分量都已经采集到,并且是合法值就会在处理的同时直接从缓存删除掉
testAndProcessDiWithMultiVal(stDigPointAll);
}
}
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 10bit0新值=1/0 都无法通过判断,导致不报警 BUG
initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuexstatusx
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 ;
}
//初始化报警 故障值文本。。。。
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分量加入队列进行延时判断
testAndProcessDiSOEWithMultiVal(stDigPointAll);
/*
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]);//初始化分量值到valuexstatusx
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 <std::string,SDiChange> &mapDiChgBuf,const string strKeyIdTag,
const int nIndex,const SDigPointAll& stDigPointAll,const SChangeDiInfo stChangeInfo)
{
map <string, SDiChange>::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 初始化数字化分量值和状态到数组valuexstatusx
@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)
{
boost::ignore_unused_variable_warning(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<<nValueNum) -1)) ) //全0||全1
{
LOGALARM( "getValueByValuexValue=%d,Num=%d Error!", nRetValue,nValueNum);
return -1;
}
}
return nRetValue;
*/
}
/**
@brief 删除无用的信息各种BUFFER
@param 无
@return 无
@retval
*/
void CDigProcess::checkBuffInfo()
{
checkDiSoeBuf();
checkDiChgBuf();
//CheckAlarmTimeBuf();
//CheckAlarmFreqBuf();
//CheckAlarmDelayBuf();
}
/**
@brief 得到时间字符串
@param 无
@return 无
@retval
*/
void CDigProcess::getTimeString(char *cTimeBuf, const int nSec, short sMsec, bool bMsecFlag)
{
struct tm *pCurTime;
time_t tTimes =(time_t)nSec;
pCurTime = localtime(&tTimes);
if (pCurTime == NULL)
{
LOGERROR("CDigProcess::GetTimeString(),localtime(&tTimes) return error !");
return;
}
if (bMsecFlag)
{
sprintf(cTimeBuf, "%04d年%02d月%02d日%02d时%02d分%02d秒%03d",
pCurTime->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 = static_cast<int>(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 flagSET_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<<m_nMenuStateDiInvalid); //删除无效状态
}
nRetCode = m_ptrDataProcApi->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) //采集点
{
LOGWARN("processOperate::操作错误,对采集点[%s]人工置数,请检查配置!",stDigPoint.tag_name);
continue;
// return 1;
}
nRetCode = checkTagStatus(stDigPoint.tag_name,stDigPoint.status,
unSetValue,stDigPoint.last_update_time, POINT_TYPE_DIG);//禁止刷新 保存旧的值
if (nRetCode == false)
{
LOGWARN("processOperate::checkTagStatus() tag_name = %s, newValue = %d, status = %d NewStatus = %d ! ",
stDigPoint.tag_name, nNewValue, stDigPoint.status, nNewStatus);
//return 1;
continue;
}
}
//如果禁止刷新,保存标签数据 ;否则,还原标签数据
//=============================================================================================================
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 <string, SDiAlarm>::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 <string, SDiAlarm>::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 <string, SAlarmFreq>::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 <string, SAlarmFreq>::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 <string, SDiAlarm>::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<string> &vecRtuTagName, const int nDomainId /*=-1*/)
{
vecRtuTagName.clear();
vector<SFesGroupDevSelect> vecFesGroupDevSelect;
std::vector<std::string> 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<SFesGroupDevSelect>::size_type i = 0; i != vecFesGroupDevSelect.size(); ++i)
{
if (nDomainId != -1 && nDomainId != vecFesGroupDevSelect[i].domain_id)
{
continue;
}
vector<string> 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<string>::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;
}
bool CDigProcess::processDiWithMultiVal(const std::string &strTagName,const SDiChange &stDiChange)
{
int nNewStatus = 0;
SDigPointAll stDigPointAll;
string strDiTagName = strTagName;
strDiTagName.resize(64);
int nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,strDiTagName.c_str(), stDigPointAll);
if (nRetCode <=0 )
{
LOGERROR("CheckDiChgBuf::nRetCode = %d, tag_name = %s, 获取测点参数错误!", nRetCode, strDiTagName.c_str());
return true;//出错,可以删除缓存
}
int nValueNum = stDigPointAll.value_num;
if (nValueNum > MAX_DI_BIT_NUM || nValueNum <= 0 )
{
LOGWARN( "CheckDiChgBuf::nValueNum=%d > MAX_DI_BIT_NUM", nValueNum);
return true;//出错,可以删除缓存
}
int valuex[MAX_DI_BIT_NUM]={0};
int statusx[MAX_DI_BIT_NUM]={0};
initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuexstatusx
//获得最新报警时间
int nLoop;
int64 nLastChgMescond = 0;
for (nLoop = 0 ; nLoop < nValueNum; nLoop++)
{
if (stDiChange.di_bit_chg_array[nLoop].use_flag == SHARE_BUF_USE)
{
valuex[nLoop] = stDiChange.di_bit_chg_array[nLoop].value;
statusx[nLoop] = stDiChange.di_bit_chg_array[nLoop].status;
if (nLastChgMescond < stDiChange.di_bit_chg_array[nLoop].times) //目前未处理msecond
{
nLastChgMescond = stDiChange.di_bit_chg_array[nLoop].times;
}
}
}
int nResultValue = getValueByValuex(stDigPointAll.value_num,&valuex[0],&statusx[0]);//通过DI分量得到DI值
if (nResultValue < 0)
{
LOGERROR("CheckDiChgBuf::getValueByValuex return Error,nValueNum= %d", nValueNum);
return true;//出错,可以删除缓存
}
//下面开始通过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);
return true;//出错,可以删除缓存
}
}
else
{
std::vector<RSQL_UPD_COLUMN> 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,strDiTagName.c_str());
return true;//出错,可以删除缓存
}
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",
strDiTagName.c_str(), nResultValue, nNewStatus);
}
return true;
}
bool CDigProcess::processDiSOEWithMultiVal(const string &strTagName, const SDiChange &stDiChange)
{
SDigPointAll stDigPointAll;
string strDiSOETagName = strTagName;
strDiSOETagName.resize(64);
int nRetCode = m_ptrRdbTableMng->getRecordAllColumnByKey(RT_DIG_TBL,strDiSOETagName.c_str(), stDigPointAll);
if (nRetCode <=0 )
{
LOGERROR("CheckDiSoeBuf::nRetCode = %d, tag_name = %s, 获取实时值 error!", nRetCode, strDiSOETagName.c_str());
return true;//出错,可以删除缓存
}
int nValueNum = stDigPointAll.value_num;
if (nValueNum > MAX_DI_BIT_NUM || nValueNum <= 0 )
{
LOGINFO( "CheckDiSoeBuf::nValueNum=%d > MAX_DI_BIT_NUM", nValueNum);
return true;//出错,可以删除缓存
}
int valuex[MAX_DI_BIT_NUM] ={0};
int statusx[MAX_DI_BIT_NUM]={0};
//initValuexStatusx(stDigPointAll,&valuex[0],&statusx[0]);//初始化分量值到valuexstatusx
//获得最新报警时间 报警分量信息初始化到valuex statusx中
//==============================================================================================
int nLoop =0 ;
int64 nLastChgMescond = 0;
for (nLoop = 0 ; nLoop < nValueNum; nLoop++)
{
if (stDiChange.di_bit_chg_array[nLoop].use_flag == SHARE_BUF_USE)
{
valuex[nLoop] = stDiChange.di_bit_chg_array[nLoop].value;
statusx[nLoop] = stDiChange.di_bit_chg_array[nLoop].status;
if (nLastChgMescond < stDiChange.di_bit_chg_array[nLoop].times)
{
nLastChgMescond = stDiChange.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);
return true;//出错,可以删除缓存
}
//或者报警状态文本
SDigAlarmPara stDigAlmPara;
getDigAlarmPara(stDigPointAll,nRetValue ,stDigAlmPara);
//产生SOE报警
//==============================================================================================
addOneDigAlarm(ALM_TYPE_SOE,stDigPointAll,stDigAlmPara,nLastChgMescond) ;
return true;
}
void CDigProcess::testAndProcessDiWithMultiVal(const SDigPointAll &stDiInfo)
{
//经过前面处理mapDiChgBuf一定会存在strTagName
auto pIter = m_mapDiChgBuf.find(stDiInfo.tag_name);
if(pIter == m_mapDiChgBuf.end())
{
return;
}
SDiChange &stCurDi = pIter->second;
std::bitset<MAX_DI_BIT_NUM> bitDi;
for(int i = 0;i < stDiInfo.value_num;i++)
{
if(stCurDi.di_bit_chg_array[i].use_flag == SHARE_BUF_USE)
{
bitDi.set(i,stCurDi.di_bit_chg_array[i].value != 0);
}
else
{
return; //如果分量数量不满足,意味着可能只有部分分量采集到了,延迟处理
}
}
if(m_ptrDataProcApi->isExistStateText(stDiInfo.state_text_name,static_cast<int>(bitDi.to_ulong()) ) )
{
//在数字量文本中存在,则认为值已经正常,可以直接处理,如果存在可能处于过渡态
processDiWithMultiVal(stDiInfo.tag_name,stCurDi);
m_mapDiChgBuf.erase(pIter);
}
//注意后面pIter已经失效不能使用了
return;
}
void CDigProcess::testAndProcessDiSOEWithMultiVal(const SDigPointAll &stDiInfo)
{
//经过前面处理mapDiChgBuf一定会存在strTagName
auto pIter = m_mapDiSoeBuf.find(stDiInfo.tag_name);
if(pIter == m_mapDiSoeBuf.end())
{
return;
}
SDiChange &stCurDi = pIter->second;
std::bitset<MAX_DI_BIT_NUM> bitDi;
for(int i = 0;i < stDiInfo.value_num;i++)
{
if(stCurDi.di_bit_chg_array[i].use_flag == SHARE_BUF_USE)
{
bitDi.set(i,stCurDi.di_bit_chg_array[i].value != 0);
}
else
{
return; //如果分量数量不满足,意味着可能只有部分分量采集到了,延迟处理
}
}
if(m_ptrDataProcApi->isExistStateText(stDiInfo.state_text_name,static_cast<int>(bitDi.to_ulong()) ) )
{
//在数字量文本中存在,则认为值已经正常,可以直接处理,如果存在可能处于过渡态
processDiSOEWithMultiVal(stDiInfo.tag_name,stCurDi);
m_mapDiSoeBuf.erase(pIter);
}
//注意后面pIter已经失效不能使用了
return;
}