diff --git a/platform/src/service/alarm_server/CAppMsgProcThread.cpp b/platform/src/service/alarm_server/CAppMsgProcThread.cpp index fb975bdd..1dff58ed 100644 --- a/platform/src/service/alarm_server/CAppMsgProcThread.cpp +++ b/platform/src/service/alarm_server/CAppMsgProcThread.cpp @@ -378,10 +378,14 @@ void CAppMsgProcThread::handleOneMbMsg() if (iot_idl::AS_DO_NOTHING == objAlmInfoSrc.alm_style()) { //< 不处理 - std::string strPrint; - google::protobuf::TextFormat::PrintToString(objAlmInfoSrc, &strPrint); - - LOGINFO("alm_style值为AS_DO_NOTHING,不做任何处理,消息内容:\n%s", strPrint.c_str()); + if ( objAlmInfoSrc.has_key_id_tag() && !( objAlmInfoSrc.key_id_tag().empty())) + LOGINFO( "alm_style值为AS_DO_NOTHING,不做任何处理,key_id_tag:%s", objAlmInfoSrc.key_id_tag().c_str()); + else + { + std::string strPrint; + google::protobuf::TextFormat::PrintToString( objAlmInfoSrc, &strPrint ); + LOGINFO( "alm_style值为AS_DO_NOTHING,不做任何处理,消息内容:\n%s", strPrint.c_str()); + } } else { diff --git a/platform/src/service/data_process/AccProcess.cpp b/platform/src/service/data_process/AccProcess.cpp index 64382a34..d1092a9c 100644 --- a/platform/src/service/data_process/AccProcess.cpp +++ b/platform/src/service/data_process/AccProcess.cpp @@ -95,7 +95,7 @@ int CAccProcess::procAccChange(const SFesChangePiPkg &stChgAccPkg) stChangeAccData.strTableName = stChgAccPkg.stpidata(nLoop).strapptablename(); //表名 stChangeAccData.strPointName = stChgAccPkg.stpidata(nLoop).strapptagname(); //点名 stChangeAccData.strColumnName = stChgAccPkg.stpidata(nLoop).strappcolumnname(); //列名 - stChangeAccData.dValue = stChgAccPkg.stpidata(nLoop).nvalue(); + stChangeAccData.dValue = stChgAccPkg.stpidata(nLoop).dvalue(); stChangeAccData.lTime = stChgAccPkg.stpidata(nLoop).ultime(); nTmpStatus = 0xffff & stChgAccPkg.stpidata(nLoop).ustatus(); @@ -177,12 +177,11 @@ int CAccProcess::procOneAccChange(SChangeAccData &stChangeAccData,SAccNewValueSt nRetCode, m_stRunAppInfo.nAppId, stChangeAccData.strTableName.c_str(), stChangeAccData.strPointName.c_str()); return -1; } - stAccOldValueStatus.oldvalue = stAccPoint.value; + stAccOldValueStatus.oldvalue = stAccPoint.value; stAccOldValueStatus.oldstatus = stAccPoint.status; m_stChangeAccInfo.dValue = stAccOldValueStatus.oldvalue; m_stChangeAccInfo.uStatus = stAccOldValueStatus.oldstatus; - stChangeAccData.nLocation = stAccPoint.location_id; stChangeAccData.nSubSystem = stAccPoint.sub_system; @@ -356,7 +355,7 @@ int CAccProcess::procAccUpdate(const SFesUpdatePiPkg &stUpAccPkg) stChangeAccData.strTableName = stUpAccPkg.stpidata(nLoop).strapptablename(); //表名 stChangeAccData.strPointName = stUpAccPkg.stpidata(nLoop).strapptagname(); //点名 stChangeAccData.strColumnName = stUpAccPkg.stpidata(nLoop).strappcolumnname(); //列名 - stChangeAccData.dValue = stUpAccPkg.stpidata(nLoop).nvalue(); + stChangeAccData.dValue = stUpAccPkg.stpidata(nLoop).dvalue(); stChangeAccData.lTime = m_lCurTime; nTmpStatus = 0xffff & stUpAccPkg.stpidata(nLoop).ustatus(); m_ptrDataProcApi->changeAnaStatusRawToRipe(stChangeAccData.uStatus, nTmpStatus); @@ -471,7 +470,7 @@ int CAccProcess::writeAccRdb(const string& strPointName , m_stChangeAccInfo.dValue = stAccOldValueStatus.oldvalue; m_stChangeAccInfo.uStatus = stAccNewValueStatus.newstatus; m_stChangeAccInfo.bIfLimitChange = false; - //LOGDEBUG("writeAccRtdb MENU_STATE_AI_GK_OFF!,tag_name =%s,value =%.2f,status =%d",\ + LOGDEBUG("writeAccRtdb MENU_STATE_AI_GK_OFF!,tag_name =%s,value =%.2f,status =%d", m_stChangeAccInfo.strPointName.c_str(),m_stChangeAccInfo.dValue, m_stChangeAccInfo.uStatus); return 2; @@ -495,6 +494,7 @@ int CAccProcess::writeAccRdb(const string& strPointName , return 1; } + /** @brief 处理电度系数 @param stOneAiLimit:变化数据 diff --git a/platform/src/service/data_process/AccStructDefine.h b/platform/src/service/data_process/AccStructDefine.h index ba2598df..627a3510 100644 --- a/platform/src/service/data_process/AccStructDefine.h +++ b/platform/src/service/data_process/AccStructDefine.h @@ -81,7 +81,6 @@ struct SAccMapToFes char description[128] ; }; - struct SAccOldValueStatus { double oldvalue; diff --git a/platform/src/service/data_process/AccWorkThread.cpp b/platform/src/service/data_process/AccWorkThread.cpp index b73993aa..a6bc9296 100644 --- a/platform/src/service/data_process/AccWorkThread.cpp +++ b/platform/src/service/data_process/AccWorkThread.cpp @@ -190,7 +190,7 @@ int CAccWorkThread::processOptMessage() { SOptSetDataPkg &objOptCalSetPkg = *it ; m_ptrAccProcess->processOperate(objOptCalSetPkg,OPT_TYPE_CAL_SET); - LOGINFO("processOptMessage: 处理计算点操作 num=%d .",objOptCalSetPkg.seq_set_data_info_size()); + LOGDEBUG("processOptMessage: 处理计算点操作 num=%d .",objOptCalSetPkg.seq_set_data_info_size()); } } diff --git a/platform/src/service/data_process/AnaProcess.cpp b/platform/src/service/data_process/AnaProcess.cpp index de626033..9528a6f6 100644 --- a/platform/src/service/data_process/AnaProcess.cpp +++ b/platform/src/service/data_process/AnaProcess.cpp @@ -551,7 +551,7 @@ int CAnaProcess:: writeAnaRtdb(const string &strPointName, SOldValueStatus &stOl m_stChangeAiInfo.dValue = stOldValueStatus.oldvalue; m_stChangeAiInfo.uStatus = stNewValueStatus.newstatus; m_stChangeAiInfo.bIfLimitChange = false; - LOGINFO("CAnaProcess::writeAnaRtdb MENU_STATE_AI_GK_OFF!,ifprocess =%d,strPointName =%s,value =%f,status =%d,iflimitchange =%d", + LOGDEBUG("CAnaProcess::writeAnaRtdb MENU_STATE_AI_GK_OFF!,ifprocess =%d,strPointName =%s,value =%f,status =%d,iflimitchange =%d", m_stChangeAiInfo.bIfProcess, m_stChangeAiInfo.strPointName.c_str(), m_stChangeAiInfo.dValue, m_stChangeAiInfo.uStatus, m_stChangeAiInfo.bIfLimitChange); return 2; @@ -756,6 +756,7 @@ int CAnaProcess::writeRdbAndSendMsg(const SChangeAiData &stOneAiLimit, int /*sty //<< 实时值写入数据库中同时发布到 HMI //============================================================================================ strKeyTagName.resize(64); + nRetCode = m_ptrRdbTableMng->updateRecordTwoValueByKey(stOneAiLimit.strTableName,strKeyTagName.c_str(),\ "status",m_stChangeAiInfo.uStatus, "value", m_stChangeAiInfo.dValue); if (nRetCode == false) @@ -766,7 +767,7 @@ int CAnaProcess::writeRdbAndSendMsg(const SChangeAiData &stOneAiLimit, int /*sty } m_ptrDataPublish->addOneChangeFloat( stOneAiLimit.nLocation,stOneAiLimit.nSubSystem,stOneAiLimit.strTableName,stOneAiLimit.strPointName,\ - stOneAiLimit.strColumnName, m_stChangeAiInfo.dValue, m_stChangeAiInfo.uStatus); + stOneAiLimit.strColumnName, static_cast(m_stChangeAiInfo.dValue), m_stChangeAiInfo.uStatus); //LOGDEBUG( "CAnaProcess::writeRdbAndSendMsg,not optlock" ); diff --git a/platform/src/service/data_process/DataPublish.cpp b/platform/src/service/data_process/DataPublish.cpp index 46799f9b..e6af2644 100644 --- a/platform/src/service/data_process/DataPublish.cpp +++ b/platform/src/service/data_process/DataPublish.cpp @@ -219,7 +219,7 @@ void CSrvDataPublish::addOneChangeLong(const int nLocationId,const int nSubSyste const string strTagName, const string strColumnName, const int64 lValue, const int nStatus ) { - m_ptrSampleApi->addAccChange(strTableName,strTagName,strColumnName,nStatus,lValue); + m_ptrSampleApi->addAccChange(strTableName,strTagName,strColumnName,nStatus,static_cast(lValue)); SPiRealTimeData *stOneRealData = m_stChangeMsg.add_stpirtd(); diff --git a/platform/src/service/data_process/DigProcess.cpp b/platform/src/service/data_process/DigProcess.cpp index ff98bca0..dedc41bd 100644 --- a/platform/src/service/data_process/DigProcess.cpp +++ b/platform/src/service/data_process/DigProcess.cpp @@ -8,6 +8,7 @@ #include "pub_utility_api/TimeUtil.h" #include "common/Common.h" #include "pub_utility_api/CommonConfigParse.h" +#include using namespace std; using namespace iot_service; @@ -23,9 +24,7 @@ CDigProcess::CDigProcess(iot_public::SRunAppInfo stRunAppInfo, m_ptrDataProcApi = ptrDataProcApi; m_ptrDataPublish = ptrDataPublish; - m_nChgAlarmCount = 0 ; - m_nSoeAlarmCount = 0 ; - m_nChangeCount = 0 ; + } bool CDigProcess::initialize() @@ -351,11 +350,6 @@ bool CDigProcess::isUpdatedByValidData(const int nLastStatus,const SUpdateDiInfo 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 启动比较慢的情况) @@ -364,8 +358,8 @@ bool CDigProcess::isUpdatedByValidData(const int nLastStatus,const SUpdateDiInfo if (pos == m_mapUpdatePackRecord.end()) //没找到 { //实时库点状态不是工况退出且全数据状态不是工况退出 - if ( !(nLastStatus & (1 << m_nMenuStateDiInvalid)) //上次状态没有异常 - && !(stUpdateDiInfo.status & (1 << m_nMenuStateDiInvalid )) ) //当前状态没有异常 + if ( !(nLastStatus & (1 << m_nMenuStateDiGkOff)) // + && !(stUpdateDiInfo.status & (1 << m_nMenuStateDiGkOff)) ) { m_mapUpdatePackRecord[strTagName] = 0; } @@ -447,7 +441,7 @@ int CDigProcess::processDiUpdate(const SFesUpdateDiPkg &stUpdateDiPkg) //判断是否本进程重启后在本包全数据之前是否点表中的值已被全数据更新; //前提:工况退出会出现在本包中所有记录中 //============================================================================================ - //if (nLoop == 0) //用第一个记录代表本包全数据 + if (nLoop == 0) //用第一个记录代表本包全数据 { bUpdatedByValidDataFlag = isUpdatedByValidData(stDigPointAll.status,stUpdateDiInfo); } @@ -495,21 +489,20 @@ int CDigProcess::processDiUpdate(const SFesUpdateDiPkg &stUpdateDiPkg) @return 无 @retval */ -void CDigProcess::setAbnormalStatus(const SDigPointAll & stDigPoint,const SDigAlarmPara &stDigAlmPara,int &nNewStatus) +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)) ) + if ( stDigAlmPara.is_abnormal && !(nOldStatus & (1 << m_nMenuStateDiAbnormal)) ) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,1 << m_nMenuStateDiAbnormal,0, - STATUS_ORI_RECV); //add DiAbnormal flag + STATUS_ORI_RECV); //del DiAbnormal flag } - else if ( !stDigAlmPara.is_abnormal && (nLastStatus & (1 << m_nMenuStateDiAbnormal)) ) + else if ( !stDigAlmPara.is_abnormal && (nOldStatus & (1 << m_nMenuStateDiAbnormal)) ) { m_ptrDataProcApi->getNewStatus(TYPE_STATUS_DI, nNewStatus, nOldStatus,0,1 << m_nMenuStateDiAbnormal, - STATUS_ORI_RECV); //del DiAbnormal flag + STATUS_ORI_RECV); //add DiAbnormal flag } //LOGDEBUG("setAbnormalStatus: 标签点[%s] 未复归=[%d],旧状态=[%d],新状态=[%d].",stDigPoint.tag_name, @@ -691,6 +684,27 @@ void CDigProcess::getStatusByStatusx(const SDigPointAll&stDigPointAll,int &nNewS @retval */ void CDigProcess::checkDiChgBuf() +{ + 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) ) + { + processDiWithMultiVal(pos->first,pos->second); //到达防抖时间,从缓存中清理 + m_mapDiChgBuf.erase(pos++); + } + else + { + ++pos; + } + } + + return; +} + +void CDigProcess::checkDiChgBuf_bak() { int nRetCode; int nResultValue; @@ -817,6 +831,26 @@ void CDigProcess::checkDiChgBuf() @retval */ void CDigProcess::checkDiSoeBuf() +{ + 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)) + { + processDiSOEWithMultiVal(pos->first,pos->second); //到达防抖时间,从缓存中清理 + m_mapDiSoeBuf.erase(pos++); + } + else + { + ++pos; + } + } + return; +} + +void CDigProcess::checkDiSoeBuf_bak() { int nRetCode; map ::iterator pos; @@ -972,8 +1006,7 @@ int CDigProcess::processDiChange(const SFesChangeDiPkg &stChangeDiPkg) if(nChangeNum>0) { - m_nChangeCount = m_nChangeCount + nChangeNum; - LOGDEBUG("ProcessDiChange:收到变化数据报文,数目[%d],总计收到数目[%d],时间[%" PRId64 "].",nChangeNum,m_nChangeCount,(int64)stChangeDiPkg.stdidata(0).ultime()); + LOGDEBUG("ProcessDiChange:收到变化数据报文,数目[%d],时间[%" PRId64 "].",nChangeNum,(int64)stChangeDiPkg.stdidata(0).ultime()); } for (nLoop = 0; nLoop < nChangeNum; ++nLoop) @@ -1158,6 +1191,8 @@ int CDigProcess::processOneDiChange(SChangeDiInfo &stChangeInfo) if (stDigPointAll.input_delay_time > 0) //数据量报警延时处理 { addDigPartToBuff(m_mapDiChgBuf, strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); + //如果多个分量都已经采集到,并且是合法值就会在处理的同时直接从缓存删除掉 + testAndProcessDiWithMultiVal(stDigPointAll); } } return 1; @@ -1320,14 +1355,6 @@ void CDigProcess::addOneDigAlarm(int nAlarmType,const SDigPointAll &stDigPointAl 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); } //初始化报警 故障值文本。。。。 @@ -1416,6 +1443,7 @@ int CDigProcess::processOneSoeEvent(SChangeDiInfo &stChangeInfo,const string &st stDigPointAll.input_delay_time = 1 ; addDigPartToBuff(m_mapDiSoeBuf,strKeyIdTag, nDigPartIndex,stDigPointAll,stChangeInfo); //SOE分量加入队列,进行延时判断 + testAndProcessDiSOEWithMultiVal(stDigPointAll); /* if (stDigPointAll.input_delay_time <= 0) // { @@ -1523,6 +1551,7 @@ void CDigProcess::addDigPartToBuff(std::map &mapDiChgBuf itPos->second.di_bit_chg_array[nIndex - 1].status = stChangeInfo.nStatus; itPos->second.di_bit_chg_array[nIndex - 1].times = stChangeInfo.lTimes; } + return; } @@ -1563,8 +1592,10 @@ void CDigProcess::initValuexStatusx(const SDigPointAll &stDigPoint,int *valuex,i @return DI值 @retval */ -int CDigProcess::getValueByValuex(const int nValueNum,int *valuex,int */*statusx*/) +int CDigProcess::getValueByValuex(const int nValueNum,int *valuex,int *statusx) { + boost::ignore_unused_variable_warning(statusx); + int nLoop; int nRetValue = 0; @@ -1662,7 +1693,7 @@ void CDigProcess::getTimeString(char *cTimeBuf, const int nSec, short sMsec, pCurTime->tm_sec); strcat(cTimeBuf, " "); } - return; + return; } @@ -1678,8 +1709,7 @@ 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); + int source_str_len = static_cast(strlen(source_str)); start_pos = 0; for (nLoop = 0; nLoop < source_str_len; ++nLoop ) @@ -1853,16 +1883,18 @@ int CDigProcess::processOperate(const SOptSetDataPkg &stOptSetDataPkg,const int { if((stDigPoint.point_property & (1<<0)) == 0) //采集点 { - LOGDEBUG("processOperate::操作错误,对采集点[%s]人工置数,请检查配置!",stDigPoint.tag_name); - return 1; + 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) { - LOGDEBUG("processOperate::checkTagStatus() tag_name = %s, newValue = %d, status = %d NewStatus = %d ! ", + LOGWARN("processOperate::checkTagStatus() tag_name = %s, newValue = %d, status = %d NewStatus = %d ! ", stDigPoint.tag_name, nNewValue, stDigPoint.status, nNewStatus); - return 1; + //return 1; + continue; } } @@ -2367,3 +2399,226 @@ int CDigProcess::getRtuTag(const int nAlmGrpId, vector &vecRtuTagName, c 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]);//初始化分量值到valuex,statusx + + //获得最新报警时间 + 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 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]);//初始化分量值到valuex,statusx + + //获得最新报警时间 报警分量信息初始化到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 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(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 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(bitDi.to_ulong()) ) ) + { + //在数字量文本中存在,则认为值已经正常,可以直接处理,如果存在可能处于过渡态 + processDiSOEWithMultiVal(stDiInfo.tag_name,stCurDi); + m_mapDiSoeBuf.erase(pIter); + } + + //注意后面pIter已经失效,不能使用了 + + return; +} diff --git a/platform/src/service/data_process/DigProcess.h b/platform/src/service/data_process/DigProcess.h index 680efa49..0e8312d5 100644 --- a/platform/src/service/data_process/DigProcess.h +++ b/platform/src/service/data_process/DigProcess.h @@ -31,10 +31,6 @@ public: private: //系统启动全数据告警延时 - int m_nChangeCount;//变化次数统计 - int m_nChgAlarmCount;//产生的告警统计 - int m_nSoeAlarmCount;//产生SOE数量 - int64 m_nStartupTimes; //单位秒 int m_nStartAlarmDelay; //数字量状态 @@ -94,7 +90,9 @@ private: bool bUpdatedByValidDataFlag, int64 lUpdateTimes) ; void checkDiChgBuf(); + void checkDiChgBuf_bak(); void checkDiSoeBuf(); + void checkDiSoeBuf_bak(); bool isUpdatedByValidData(const int nLastStatus,const SUpdateDiInfo &stUpdateDiInfo ); int processValueChange(const SDigPointAll &stDigPointAll, SDigAlarmPara &stDigAlmPara, @@ -113,6 +111,16 @@ private: const std::string& strStatusText,const int nDescFlag= ALARM_DESC_POINT_FLAG); void getTimeString(char *strTimeBuf, const int nSec, short sMsec = 0, bool bMsecFlag = false); + //多分量测点暂时打了一个补丁解决多分量只能等到防抖时间才会合并,有个不完善的地方是:如果只上传分量间隔长,有可能无法进入快速处理的逻辑中 + //比如2个分量初始值都为0,分量1上传1,分量2不上传,这样虽然是个合法值,因为缓存中只有一个分量,所以进不了快速合并的逻辑 + //处理1条m_mapDiChgBuf中多个分量的DI点,返回true表示可以从缓存中删除了(不一定是正常处理了,也可能是异常需要删除) + bool processDiWithMultiVal(const std::string &strTagName,const SDiChange &stDiChange); + bool processDiSOEWithMultiVal(const std::string &strTagName,const SDiChange &stDiChange); + + //检测一下缓冲区中多个分量是不是已经都有缓存,并且缓存合成值在数字量文本中存在,如果成立则直接处理,如果不存在就等抖动延时再处理 + void testAndProcessDiWithMultiVal(const SDigPointAll &stDiInfo); + void testAndProcessDiSOEWithMultiVal(const SDigPointAll &stDiInfo); + }; typedef boost::shared_ptr CDigProcessPtr; } diff --git a/platform/src/service/data_process/MsgRecvThread.cpp b/platform/src/service/data_process/MsgRecvThread.cpp index 1834fc7c..7a559b61 100644 --- a/platform/src/service/data_process/MsgRecvThread.cpp +++ b/platform/src/service/data_process/MsgRecvThread.cpp @@ -18,7 +18,7 @@ using namespace iot_service; using namespace std; CMsgRecvThread::CMsgRecvThread(iot_public::SRunAppInfo stRunAppInfo,CPacketQueuePtr ptrPacketQueue): - CTimerThreadBase("CMsgRecvThread",1) + CTimerThreadBase("CMsgRecvThread",0) { m_ptrPacketQueue = ptrPacketQueue ; m_stRunAppInfo = stRunAppInfo; @@ -131,7 +131,7 @@ int CMsgRecvThread::parseOptPackage(const iot_net::CMbMessage &objRecvMsg) int nMessageType = objRecvMsg.getMsgType(); SOptSetDataPkg objOptSetDataPkg; - bRetCode = objOptSetDataPkg.ParseFromArray(objRecvMsg.getDataPtr(),objRecvMsg.getDataSize()); + bRetCode = objOptSetDataPkg.ParseFromArray(objRecvMsg.getDataPtr(),static_cast(objRecvMsg.getDataSize())); if(bRetCode == false) { LOGWARN("parseOptPackage, objOptSetDataPkg.ParseFromArray fail "); @@ -175,7 +175,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) { SFesChangeDiPkg objFesChanageDiPkg; //t1 = getUTCTimeMsec() ; - bRetCode = objFesChanageDiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesChanageDiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); //t2 = getUTCTimeMsec() ; //LOGINFO("parseFesPackage:解析变化数字量 num=%d,用时=%d(ms)",objFesChanageDiPkg.stdidata_size(),t2-t1); if(!bRetCode) @@ -190,7 +190,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) { SFesUpdateDiPkg objFesUpdateDiPkg; //t1 = getUTCTimeMsec() ; - bRetCode = objFesUpdateDiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesUpdateDiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); //t2 = getUTCTimeMsec() ; //LOGINFO("parseFesPackage:解析数字量全数据 num=%d,用时=%d(ms)",objFesUpdateDiPkg.stdidata_size(),t2-t1); if(!bRetCode) @@ -204,7 +204,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_AI_CHANGE://AI Change Data { SFesChangeAiPkg objFesChanageAiPkg; - bRetCode = objFesChanageAiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesChanageAiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesChanageAiPkg解析错误!"); @@ -216,7 +216,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_AI_UPDATE://AI UPDATE Data { SFesUpdateAiPkg objFesUpdateAiPkg; - bRetCode = objFesUpdateAiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesUpdateAiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesUpdateAiPkg解析错误!"); @@ -228,7 +228,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_MI_CHANGE://MI Change Data { SFesChangeMiPkg objFesChanageMiPkg; - bRetCode = objFesChanageMiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesChanageMiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesChanageMiPkg解析错误!"); @@ -240,7 +240,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_MI_UPDATE://MI UPDATE Data { SFesUpdateMiPkg objFesUpdateMiPkg; - bRetCode = objFesUpdateMiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesUpdateMiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesUpdateMiPkg解析错误!"); @@ -252,7 +252,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_PI_CHANGE://PI Change Data { SFesChangePiPkg objFesChangePiPkg; - bRetCode = objFesChangePiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesChangePiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesChangePiPkg解析错误!"); @@ -264,7 +264,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_PI_UPDATE://PI UPDATE Data { SFesUpdatePiPkg objFesUpdatePiPkg; - bRetCode = objFesUpdatePiPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesUpdatePiPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesUpdatePiPkg解析错误!"); @@ -276,7 +276,7 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) case MT_FES_SOE_EVENT: //SOE事件信息 { SFesSoeEventPkg objFesSoeEventPkg ; - bRetCode = objFesSoeEventPkg.ParseFromArray(objRecvMsg.getDataPtr(), objRecvMsg.getDataSize()); + bRetCode = objFesSoeEventPkg.ParseFromArray(objRecvMsg.getDataPtr(), static_cast(objRecvMsg.getDataSize())); if(!bRetCode) { LOGWARN("parseFesPackage::objFesSoeEventPkg解析错误!"); @@ -285,6 +285,11 @@ int CMsgRecvThread::parseFesPackage(const iot_net::CMbMessage &objRecvMsg) m_ptrPacketQueue->addFesSoeEventPkg(objFesSoeEventPkg); break; } + case MT_FES_CHAN_UPDATE: //通道状态信息,暂不处理 + case MT_FES_RTU_UPDATE: //RTU状态信息,暂不处理 + { + break; + } default: { LOGWARN("parseFesPackage::MsgType = %d 消息类型不支持!",nMessageType); diff --git a/platform/src/service/data_process/PacketQueue.cpp b/platform/src/service/data_process/PacketQueue.cpp index d73538af..b9b7f035 100644 --- a/platform/src/service/data_process/PacketQueue.cpp +++ b/platform/src/service/data_process/PacketQueue.cpp @@ -301,7 +301,7 @@ void CPacketQueue::addOptCalSetPkg(const SOptSetDataPkg &objOptCalSetPkg)//计 deqCalSetPkg.clear(); deqCalSetPkg.push_back(objOptCalSetPkg); m_mapOptCalSetPkg.insert(pair>(nPointType,deqCalSetPkg)); - LOGINFO("addOptCalSetPkg::计算点map中未找到数据类型为[%d]的队列,insert!",nPointType); + LOGDEBUG("addOptCalSetPkg::计算点map中未找到数据类型为[%d]的队列,insert!",nPointType); } return; } @@ -321,7 +321,8 @@ bool CPacketQueue::getOptCalSetPkg(const int nPointType,std::deque second; pos->second.clear(); m_mapOptCalSetPkg.erase(pos); //map结点删除 - LOGINFO("getOptCalSetPkg::数据交换完成,队列数量num=%llu!",(unsigned long long)deqOptCalSetPkg.size()); + //LOGINFO("getOptCalSetPkg::数据交换完成,队列数量num=%llu!",(unsigned long long)deqOptCalSetPkg.size()); + LOGDEBUG("getOptCalSetPkg::数据交换完成,队列数量num=%d",static_cast(deqOptCalSetPkg.size())); } else { diff --git a/platform/src/service/data_process/PacketQueue.h b/platform/src/service/data_process/PacketQueue.h index 6742e13d..83f089e5 100644 --- a/platform/src/service/data_process/PacketQueue.h +++ b/platform/src/service/data_process/PacketQueue.h @@ -11,12 +11,12 @@ #include "OptDataMessage.pb.h" #include -#define MAX_CHG_ANA_QUEUE_NUM 50 //变化数据最大队列数,如果超出,丢弃最老数据(50*1000 一秒变化数据5万,windwo 处理5秒左右,linux2秒左右) -#define MAX_CHG_DIG_QUEUE_NUM 100 //变化数据最大队列数,最多保证不丢失 15万YX点,10%变化率,30秒持续,不丢失事件(1.5*10000*30 万点的容量) -#define MAX_MAN_SET_QUEUE_NUM 500 //人工置数最大队列数(考虑对一个间隔,最多200个测点) -#define MAX_CAL_SET_QUEUE_NUM 200 //计算公式最大队列数(考虑公式不会超时1000,变化率20%) -#define MAX_UPD_QUEUE_NUM 20 //全数据最大队列数,如果超出,丢弃最老数据 (每种类型25*10000 20万点的容量) -#define MAX_EVT_QUEUE_NUM 500000//变化事件,如果超出,丢弃最老数据(考虑15万YX点,10%变化率,30秒持续,共45万点不丢失事件) +#define MAX_CHG_ANA_QUEUE_NUM 500 //变化数据最大队列数,如果超出,丢弃最老数据(50*1000 一秒变化数据5万,windwo 处理5秒左右,linux2秒左右) +#define MAX_CHG_DIG_QUEUE_NUM 1000 //变化数据最大队列数,最多保证不丢失 15万YX点,10%变化率,30秒持续,不丢失事件(1.5*10000*30 万点的容量) +#define MAX_MAN_SET_QUEUE_NUM 1000 //人工置数最大队列数(考虑对一个间隔,最多200个测点) +#define MAX_CAL_SET_QUEUE_NUM 10000 //计算公式最大队列数(考虑公式不会超时1000,变化率20%) +#define MAX_UPD_QUEUE_NUM 50 //全数据最大队列数,如果超出,丢弃最老数据 (每种类型25*10000 20万点的容量) +#define MAX_EVT_QUEUE_NUM 500000 //变化事件,如果超出,丢弃最老数据(考虑15万YX点,10%变化率,30秒持续,共45万点不丢失事件) namespace iot_service { diff --git a/platform/src/service/data_process/PointBase.cpp b/platform/src/service/data_process/PointBase.cpp index 6e69749e..284c8346 100644 --- a/platform/src/service/data_process/PointBase.cpp +++ b/platform/src/service/data_process/PointBase.cpp @@ -62,9 +62,9 @@ bool CPointBase::initialize() } //得到数字量文本报警方式 //============================================================================================= - if (m_ptrDataProcApi->getMenuMacToValMap("数字量文本报警方式", m_mapAlarmStyle) < 0) + if (m_ptrDataProcApi->getMenuMacToValMap("数字量文本告警方式", m_mapAlarmStyle) < 0) { - LOGERROR("CPointBase::initialize(), getMenu 数字量文本报警方式 fail!\n"); + LOGERROR("CPointBase::initialize(), getMenu 数字量文本告警方式 fail!\n"); return false; } //得到模拟量状态字信息 diff --git a/platform/src/service/data_process_api/DataProcessImpl.cpp b/platform/src/service/data_process_api/DataProcessImpl.cpp index a470c3ea..d4ec043f 100644 --- a/platform/src/service/data_process_api/DataProcessImpl.cpp +++ b/platform/src/service/data_process_api/DataProcessImpl.cpp @@ -8,12 +8,15 @@ #include "DataProcessImpl.h" #include "alarm_server_api/AlarmCommonDef.h" #include "public/pub_utility_api/TimeUtil.h" +#include "public/pub_utility_api/CharUtil.h" using namespace iot_dbms; using namespace iot_service; using namespace iot_public; using namespace std; +const std::string CN_STATETEXT_CACHE_DELIMITER = "_#@#_"; //用于拼接数字量文本标识+分隔符+动作值 + CDataProcessImpl::CDataProcessImpl(std::string strAppName) { m_IsInit = false; @@ -117,10 +120,10 @@ int CDataProcessImpl::initialize() //数字量文本报警方式 //========================================================================== - nRetCode = getMenuMacToValMap("数字量文本报警方式", menu_map); + nRetCode = getMenuMacToValMap("数字量文本告警方式", menu_map); if (nRetCode < 0) { - LOGERROR( "CDataProcessImpl::Init(), getMenuMacToValMap(数字量文本报警方式) error!"); + LOGERROR( "CDataProcessImpl::Init(), getMenuMacToValMap(数字量文本告警方式) error!"); return -1; } MENU_EVENT_ONLY = menu_map["MENU_EVENT_ONLY"]; @@ -656,6 +659,7 @@ int CDataProcessImpl::readAllStateText(map > &mapStat } mapStateText.clear(); + m_setStateTextAndValue.clear(); std::vector vecStateTextSelect ; vecStateTextSelect.clear(); @@ -691,6 +695,9 @@ int CDataProcessImpl::readAllStateText(map > &mapStat { pos->second.push_back(stOneStateText); } + + //缓存数字量文本+值 + m_setStateTextAndValue.insert(strStateTextName + CN_STATETEXT_CACHE_DELIMITER + IntToString(stOneStateText.actual_value)); } m_LastReadStateText = getUTCTimeSec(); @@ -890,3 +897,13 @@ int CDataProcessImpl::getDigAlarmPara(const SDigAlarmInfo &stDigAlmInfo,SDigAla return 0; } + +bool CDataProcessImpl::isExistStateText(const string &strStateText, const int &nValue) +{ + if(m_setStateTextAndValue.count(strStateText + CN_STATETEXT_CACHE_DELIMITER + IntToString(nValue))) + { + return true; + } + + return false; +} diff --git a/platform/src/service/data_process_api/DataProcessImpl.h b/platform/src/service/data_process_api/DataProcessImpl.h index 414275b3..d7c3e2b9 100644 --- a/platform/src/service/data_process_api/DataProcessImpl.h +++ b/platform/src/service/data_process_api/DataProcessImpl.h @@ -83,6 +83,7 @@ private: std::string m_strAppName; iot_dbms::CRdbTableMngPtr m_ptrRdbTableMng; std::map > m_mapStateText; + std::set m_setStateTextAndValue; //用来缓存所有的数字量文本信息,有数字量文本+值组成 public: /** @@ -204,6 +205,15 @@ public: @retval */ int getDigAlarmPara(const SDigAlarmInfo &stDigAlmInfo,SDigAlarmPara &stDigAlmPara); + + /** + @brief 查询指定的数字量文本值是否存在 + @param strStateText 数字量文本 + @param nValue 对应数字量文本的actual_value + @return bool + @retval true代表存在,false代表不存在 + */ + bool isExistStateText(const std::string &strStateText,const int &nValue); }; typedef boost::shared_ptr CDataProcessImplPtr; } diff --git a/platform/src/service/dp_chg_data_api/CDpcdaForDpImpl.cpp b/platform/src/service/dp_chg_data_api/CDpcdaForDpImpl.cpp index bb9c1826..fdc23ae1 100644 --- a/platform/src/service/dp_chg_data_api/CDpcdaForDpImpl.cpp +++ b/platform/src/service/dp_chg_data_api/CDpcdaForDpImpl.cpp @@ -552,7 +552,7 @@ void CDpcdaForDpImpl::handle_MT_DPCDA_APP2DP_CHG(iot_net::CMbMessage &objMbMsg) { //< 反序列化 iot_idl::SDpcdaSubPkg objSubPkgChg; - if (!objSubPkgChg.ParseFromArray(objMbMsg.getDataPtr(), objMbMsg.getDataSize())) + if (!objSubPkgChg.ParseFromArray(objMbMsg.getDataPtr(), static_cast(objMbMsg.getDataSize()))) { LOGWARN("handle_MT_DPCDA_APP2DP_CHG(): 反序列化失败,忽略消息!"); return; @@ -697,7 +697,7 @@ void CDpcdaForDpImpl::handle_MT_DPCDA_APP2DP_ALL(iot_net::CMbMessage &objMbMsg) { //< 反序列化 iot_idl::SDpcdaSubPkg objSubPkgAll; - if (!objSubPkgAll.ParseFromArray(objMbMsg.getDataPtr(), objMbMsg.getDataSize())) + if (!objSubPkgAll.ParseFromArray(objMbMsg.getDataPtr(), static_cast(objMbMsg.getDataSize()))) { LOGWARN("handle_MT_DPCDA_APP2DP_ALL(): 反序列化失败,忽略消息!"); return; @@ -913,7 +913,7 @@ bool CDpcdaForDpImpl::getAiDataFromRtdb(const std::string &strTagName, iot_idl:: { if (m_pRtdb_AI->getColumnValueByIndex(nRcdIndex, "value", objValue)) { - pRtd->set_fvalue(objValue.toDouble()); + pRtd->set_fvalue(static_cast(objValue.toDouble())); } else { diff --git a/platform/src/service/intelli_alm_srv/CIntelliAlmSrv.cpp b/platform/src/service/intelli_alm_srv/CIntelliAlmSrv.cpp index 9ad00205..b5801c91 100644 --- a/platform/src/service/intelli_alm_srv/CIntelliAlmSrv.cpp +++ b/platform/src/service/intelli_alm_srv/CIntelliAlmSrv.cpp @@ -10,8 +10,19 @@ #include "boost/typeof/typeof.hpp" #include "boost/lexical_cast.hpp" #include "boost/filesystem.hpp" + +//< 屏蔽xml_parser编译告警 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#endif + #include "boost/property_tree/xml_parser.hpp" +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "pub_logger_api/logger.h" #include "pub_utility_api/FileUtil.h" diff --git a/platform/src/service/iscs_wise_mnp/CWebServerMng.cpp b/platform/src/service/iscs_wise_mnp/CWebServerMng.cpp index 52df490b..fe542964 100644 --- a/platform/src/service/iscs_wise_mnp/CWebServerMng.cpp +++ b/platform/src/service/iscs_wise_mnp/CWebServerMng.cpp @@ -3,7 +3,19 @@ #include "pub_logger_api/logger.h" #include "CRelativeCallback.h" #include "boost/property_tree/ptree.hpp" + +//< 屏蔽xml_parser编译告警 +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-copy" +#endif + #include "boost/property_tree/xml_parser.hpp" + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + #include "boost/typeof/typeof.hpp" #include "pub_utility_api/FileUtil.h" #include "pub_utility_api/CommonConfigParse.h" diff --git a/platform/src/service/iscs_wise_mnp/iscs_wise_mnp.pro b/platform/src/service/iscs_wise_mnp/iscs_wise_mnp.pro index ad3c53cb..1093655f 100644 --- a/platform/src/service/iscs_wise_mnp/iscs_wise_mnp.pro +++ b/platform/src/service/iscs_wise_mnp/iscs_wise_mnp.pro @@ -2,7 +2,7 @@ # ARM板上资源有限,不会与云平台混用,不编译 message("Compile only in x86 environment") # requires(contains(QMAKE_HOST.arch, x86_64)) -requires(!contains(QMAKE_HOST.arch, aarch64)) +requires(!contains(QMAKE_HOST.arch, aarch64) : !linux-aarch64*) TEMPLATE = app CONFIG += console c++11 diff --git a/platform/src/service/operate_server/OperateServerClass.cpp b/platform/src/service/operate_server/OperateServerClass.cpp index 9d0e89e5..107bcb41 100644 --- a/platform/src/service/operate_server/OperateServerClass.cpp +++ b/platform/src/service/operate_server/OperateServerClass.cpp @@ -6,6 +6,9 @@ #include "OperateServerClass.h" #include "pub_logger_api/logger.h" +#include "pub_utility_api/CharUtil.h" +#include "pub_utility_api/FileUtil.h" +#include "pub_utility_api/CommonConfigParse.h" #include "MessageChannel.h" using namespace std; @@ -30,6 +33,12 @@ COperateServerClass::~COperateServerClass() bool COperateServerClass::initialize() { + //读取配置文件 + if(!readConfig()) + { + return false; + } + //data_process_api 实例 //======================================================================================== m_ptrDataProcApi = getDataProcInstance(m_stRunAppInfo.strAppName); @@ -313,7 +322,7 @@ int COperateServerClass::getUserAndUserGroup(const int nUserId,const int nUsergI /** @brief 通过标签点获取标签点的状态和值 - @return 成功返回iotSuccess,失败返回相应错误码 + @return 成功返回iotSucces,失败返回相应错误码 */ int COperateServerClass::getValueStatus(const std::string &strTagName, SOptValueStatus &stValueStatus,\ int nDomainId ,int nAppNo) @@ -1077,6 +1086,17 @@ int COperateServerClass::addOperateEvent(const SOptCtrlInfoAll &stOptCtrlInfo, stOptCtrlInfo.table_name,stOptCtrlInfo.tag_name); return -1; } + + //格式化控制值 + if(stPoinBase.point_type == POINT_TYPE_DIG || stPoinBase.point_type == POINT_TYPE_MIX || stPoinBase.point_type == POINT_TYPE_DO) + { + strCtrlValue = DoubleToString(stOptCtrlInfo.target_value,0); + } + else if(stPoinBase.point_type == POINT_TYPE_ANA || stPoinBase.point_type == POINT_TYPE_AO || stPoinBase.point_type == POINT_TYPE_ACC) + { + strCtrlValue = DoubleToString(stOptCtrlInfo.target_value,m_nAlarmCtrlPrecision); + } + //得到测点基本信息 //====================================================================================== if(nAlarmStatus <=0) @@ -1140,7 +1160,14 @@ int COperateServerClass::addOperateEvent(const SOptCtrlInfoAll &stOptCtrlInfo, addAlarmKeyword(stAlarmInfo,ALM_KEY_OPT_HOST,stOptCtrlInfo.host_name); //报警内容关键字-操作主机名 addAlarmKeyword(stAlarmInfo,ALM_KEY_CTRL_VAL,strCtrlValue); //报警内容关键字-设备控制值 addAlarmKeyword(stAlarmInfo,ALM_KEY_DEV_OPT_VAL,strCtrlValue); //报警内容关键字-设备操作值 - addAlarmKeyword(stAlarmInfo,ALM_KEY_DEV_OPT_NAME,strCtrlOptName); //报警内容关键字-设备操作名 + if(strCtrlOptName.empty()) + { + addAlarmKeyword(stAlarmInfo,ALM_KEY_DEV_OPT_NAME,strCtrlValue); //报警内容关键字-设备操作名为空时填充控制值 + } + else + { + addAlarmKeyword(stAlarmInfo,ALM_KEY_DEV_OPT_NAME,strCtrlOptName); //报警内容关键字-设备操作名 + } addAlarmKeyword(stAlarmInfo,ALM_KEY_RTN_RESULT,strCtrlResult); //报警内容关键字-设备操作结果 getTimeStrBySeconds(stOptCtrlInfo.opt_time/1000, strNameString); addAlarmKeyword(stAlarmInfo,ALM_KEY_DEV_OPT_TIME,strNameString); //报警内容关键字-设备操作时间 @@ -1702,3 +1729,16 @@ void COperateServerClass::sendAlarm()//向报警服务器发送报警信息 m_ptrOptComand->sendAlarm(); } } + +bool COperateServerClass::readConfig() +{ + iot_public::CCommonConfigParse objCfgParse; + if(objCfgParse.load( iot_public::CFileUtil::getPathOfCfgFile("operate_server_cfg.xml") ) == iotFailed) + { + LOGERROR("COperateServerClass::readConfig() operate_server_cfg.xml load fail"); + return false; + } + m_nAlarmCtrlPrecision = objCfgParse.getIntWithDefault("alarm_param","precision",2); //默认2位小数 + + return true; +} diff --git a/platform/src/service/operate_server/OperateServerClass.h b/platform/src/service/operate_server/OperateServerClass.h index 4c85f655..eeb50377 100644 --- a/platform/src/service/operate_server/OperateServerClass.h +++ b/platform/src/service/operate_server/OperateServerClass.h @@ -22,6 +22,7 @@ #include #include "string.h" +#include "boost/unordered_map.hpp" namespace iot_service { @@ -79,6 +80,8 @@ private: map m_mapHandoverInfo; map m_mapCtrlResvInfo; map m_mapCtrlPrev;//tag_name + //std::vector m_vecCtrlWithoutResp; //< 主要用于功率控制场景,不等待反馈 + boost::unordered_map m_mapCtrlWithoutResp; //< 防止指令挤压,将缓存中指令全部合并,只发送最后一次的指令 //状态字变量 //====================================================================================================== @@ -92,7 +95,7 @@ private: int m_nAiLockStatus; int m_nAiInhibitCtlStatus; int m_nAiAlmRstStatus; - + int m_nAlarmCtrlPrecision; //告警描述中的精度 public: //初始化相关函数 //====================================================================================================== @@ -135,6 +138,8 @@ public: //====================================================================================================== int optAutoCtrl(const string &strJson);//标志牌同步、外部权限移交 int doOptAutoCtrl(); + int optAutoCtrlWithoutResp(const std::string &strJson); + int doOptAutoCtrlWithoutResp(); //挂牌/点标签/屏蔽相关函数 //====================================================================================================== @@ -154,6 +159,15 @@ public: //====================================================================================================== void sendChange();//MANSET 发送变化数据信息给HMI void sendAlarm();//向报警服务器发送报警信息 + + +private: + //点控/单控相关函数 + //====================================================================================================== + int optCtrlRequest(const SOptCtrlRequest &stCtrlRequest, string &strResult);//HMI遥控请求处理 + int optCtrlSelect(const SOptCtrlRequest &stOptCtrlSelect);//HMI遥控选择处理 + int optCtrlExecute(const SOptCtrlRequest &stOptDoCtrlExecute);//HMI遥控执行处理 + private: //公共内部接口函数 //====================================================================================================== @@ -236,6 +250,9 @@ private: const bool bIsCtrlResv,const bool bCheckInterLock,string &strRequest); int getAnaCtrlValue(SOptCtrlInfoAll &stOptCtrlInfoAll ); + //< 获取禁止控制的设备列表 + int getInhibitCtrlDevList(std::set &setDev); + //点标签接口函数 //====================================================================================================== int getTagType(const int nMsgType); @@ -254,6 +271,8 @@ private: int modifyTokenStatus(const int nIsSet,const int nTokenId,const string strDevTag,bool bNotAlarm=false); int getTokenAlmStatus(int &nAlarmStatus, string &strOptDesc); int optTokenAlarm(const STokenInfoAll &stOptTokenInfo, const bool bIsSync = false); + //< 获取携带禁止控制属性的设备列表 + int getTokenDevWithInhibitCtrl(std::set &setDev); //屏蔽接口函数 //====================================================================================================== @@ -269,6 +288,8 @@ private: bool getShieldDevice(SOptShieldObj &stShieldObj,vector &vecDeviceTag); int getShieldAlmStatus(const int &ShieldnMode,int &nAlarmStatus); int optShieldAlarm(const SOptShieldInfo &stOptShieldInfo, const SOptShieldObj &stOptShieldObj, const int nIsSet,const int nFlag); + //< 获取携带禁止控制属性的设备列表 + int getShieldDevWithInhibitCtrl(std::set &setDev); //权限移交内部接口函数 //====================================================================================================== @@ -279,6 +300,8 @@ private: void addOneHandoverChange(const string strTagName, const int location, const int nDomainID); int getHandoverAlmStatus(const int nOptType,int &nAlarmStatus,string &strOptDesc,const int nType); int addOneInternHandoverReply(const SOptInternHandover &stOptHandoverInfo, const int nType); + + bool readConfig(); //读数据处理配置 }; typedef boost::shared_ptr COperateServerClassPtr; } diff --git a/platform/src/service/operate_server/OperateServerStruct.h b/platform/src/service/operate_server/OperateServerStruct.h index 43d3e099..22caa3c8 100644 --- a/platform/src/service/operate_server/OperateServerStruct.h +++ b/platform/src/service/operate_server/OperateServerStruct.h @@ -460,10 +460,12 @@ struct SPointCtrlInfo int is_tagt_state; int ctrl_timeout; int resv_timeout; + char rtu_tag[64]; char offset_no[48]; SOptCtrlActAll stCtrlActInfo;//控制动作组信息; SPointCtrlInfo() { + memset(rtu_tag,0,sizeof(rtu_tag)); memset(offset_no,0,48); } }; @@ -652,7 +654,7 @@ struct SOptCtrlInfoAll int64 opt_local_time ; double target_value ; double ctrl_tolerance ; - int ctrl_act_type ; + int ctrl_act_type ; //< DO和MO经过控制动作组转换的对FES的控制值,对AO没有用 char ctrl_act_name[64] ; char rtu_tag[64] ; //new char offset_no[48] ; diff --git a/platform/src/service/operate_server/OptCommand.cpp b/platform/src/service/operate_server/OptCommand.cpp index 5daf4136..70f26ae0 100644 --- a/platform/src/service/operate_server/OptCommand.cpp +++ b/platform/src/service/operate_server/OptCommand.cpp @@ -8,6 +8,7 @@ #include "pub_utility_api/TimeUtil.h" #include "rdb_api/FuncForNet.h" #include "MessageChannel.h" +#include "service/common/RdbTableDefine.h" using namespace iot_service; using namespace iot_idl; @@ -120,8 +121,9 @@ int COptCommand::sendDigCtrlToFes(const SOptCtrlInfoAll &stOptCtrlInfoAll, const stDoCtrlPkg.set_norder(atoi(stOptCtrlInfoAll.offset_no)); stDoCtrlPkg.set_naction(stOptCtrlInfoAll.ctrl_act_type); //动作值 stDoCtrlPkg.set_niftagtstate(stOptCtrlInfoAll.is_tagt_state);//是否等待目标状态 + stDoCtrlPkg.set_nctrltype(stOptCtrlInfoAll.msg_type); //控制类型:选择、执行、取消 - if(stDoCtrlPkg.SerializeToString(&strSendMessage) == false) + if(!stDoCtrlPkg.SerializeToString(&strSendMessage)) { LOGERROR("SendDoCtrlToFes,stDoCtrlPkg.SerializeToString error! "); return -1; @@ -195,7 +197,7 @@ int COptCommand::sendSetCtrlToFes(const SOptCtrlInfoAll &stOptCtrlInfoAll, return 0; } -//发送AO控制信息给FES +//发送MO控制信息给FES int COptCommand::sendMixCtrlToFes(const SOptCtrlInfoAll &stOptCtrlInfoAll, const string &strSrcTag) { string strSendMessage ="" ; @@ -207,8 +209,12 @@ int COptCommand::sendMixCtrlToFes(const SOptCtrlInfoAll &stOptCtrlInfoAll, const stMoCtrlPkg.set_strappcolumnname("value"); stMoCtrlPkg.set_strrtuname(stOptCtrlInfoAll.rtu_tag); stMoCtrlPkg.set_norder(atoi(stOptCtrlInfoAll.offset_no)); - stMoCtrlPkg.set_nvalue(stOptCtrlInfoAll.ctrl_act_type); - stMoCtrlPkg.set_nctrltype(stOptCtrlInfoAll.ctrl_act_type); + /* 原来的逻辑:nctrltype才是控制动作组转换后的值,但是对应FES的逻辑,此字段应该对应选择、控制、取消这些类型 + * 本次修正为set_nvalue设置控制值,由于FES没有使用nctrltype字段,为避免歧义,删除set_nctrltype + */ + stMoCtrlPkg.set_nctrltype(stOptCtrlInfoAll.msg_type); //< 控制类型:选择、执行、取消 + //stMoCtrlPkg.set_nvalue(static_cast(stOptCtrlInfoAll.target_value)); //(stOptCtrlInfoAll.target_value)); + stAoCtrlPkg.set_nctrltype(stOptCtrlInfoAll.msg_type); //控制类型:选择、执行、取消 stAoCtrlPkg.set_niftagtstate(stOptCtrlInfoAll.is_tagt_state); stAoCtrlPkg.SerializeToString(&strSendMessage); @@ -280,6 +286,7 @@ int COptCommand::sendRequestToFes( stFesCtrlReqPkg.set_norder(atoi(stOptCtrlInfoAll.offset_no)); stFesCtrlReqPkg.set_naction(stOptCtrlInfoAll.ctrl_act_type); //动作值 stFesCtrlReqPkg.set_niftagtstate(stOptCtrlInfoAll.is_tagt_state);//是否等待目标状态 + stFesCtrlReqPkg.set_nctrltype(stOptCtrlInfoAll.msg_type); //控制类型:选择、执行、取消 stFesCtrlReqPkg.SerializeToString(&strSendMessage); int nRetCode = m_ptrNetMsgBus->sendToHost(stOptCtrlInfoAll.msg_type, @@ -462,6 +469,51 @@ int COptCommand::sendVirCtrlToApp(const SOptCtrlInfoAll &stOptCtrlInfoAll, const return 0 ; } +int COptCommand::batchSendCtrlToFes(const std::vector &vecCtrlInfo, const string &strSrcTag) +{ + //< 注意:SOptCtrlInfoAll中变量赋值不全,仅有FES中使用的 + SFesCtrlRequestSeq vecReq; +// vecReq.mutable_do_seq()->Reserve(vecCtrlInfo.size()); //< 预先开辟空间 +// vecReq.mutable_mo_seq()->Reserve(vecCtrlInfo.size()); + vecReq.mutable_ao_seq()->Reserve( static_cast(vecCtrlInfo.size()) ); + + for(size_t i = 0; i < vecCtrlInfo.size(); i++) + { + const SOptCtrlInfoAll &stInfo = vecCtrlInfo[i]; + if(strcmp(stInfo.table_name,RT_ANA_TBL) == 0) + { + SFesAoRequestPkg *pAO = vecReq.add_ao_seq(); + pAO->set_strsourcetag(strSrcTag); + pAO->set_strapptablename(stInfo.table_name); + pAO->set_strapptagname(stInfo.tag_name); + pAO->set_strappcolumnname("value"); + pAO->set_strrtuname(stInfo.rtu_tag); + pAO->set_norder(atoi(stInfo.offset_no)); + pAO->set_fvalue(static_cast(stInfo.target_value)); + pAO->set_nctrltype(stInfo.msg_type); //< 借用了ctrltype字段,以使FES能够识别该命令 + pAO->set_niftagtstate(stInfo.is_tagt_state); + } + } + + string strSendMessage; + if(!vecReq.SerializeToString(&strSendMessage)) + { + LOGERROR("batchSendCtrlToFes: SerializeToString error! "); + return -1; + } + + int nRetCode = m_ptrNetMsgBus->sendToHost(MT_FES_BATCH_PNT_CMD,CH_OPT_TO_FES_CTRL_DOWN,strSendMessage); + if (nRetCode <= 0) + { + LOGERROR("batchSendCtrlToFes, ret_code(%d),sendToHost error!",nRetCode); + return -1; + } + + LOGTRACE( "batchSendCtrlToFes do_size=%d mo_size=%d ao_size=%d success", + vecReq.do_seq_size(),vecReq.mo_seq_size(),vecReq.ao_seq_size()); + return 0; +} + //发送报警信息给alarm_server int COptCommand::sendAlarm() { diff --git a/platform/src/service/operate_server/OptCommand.h b/platform/src/service/operate_server/OptCommand.h index f4308578..cc01e7a5 100644 --- a/platform/src/service/operate_server/OptCommand.h +++ b/platform/src/service/operate_server/OptCommand.h @@ -56,6 +56,9 @@ public: int sendRequestToFes(const SOptCtrlInfoAll &stOptCtrlInfo, const string &strSrcTag); //数据请求 int sendVirCtrlToApp(const SOptCtrlInfoAll &stOptCtrlInfoAll, const iot_idl::SVariable &varValue); + //< 批量发送控制命令到FES,暂时仅处理了AO + int batchSendCtrlToFes(const std::vector &vecCtrlInfo, const string &strSrcTag); + /*发送给HMI控制面板的反馈*/ void initUpOptPanel(SOptCtrlReply &stOptCtrlReply, const string strSourceTag,int nAppID,int nDomainID,\ const string strHostName,const string strstrInstName,const string strKeyIdTag,\ diff --git a/platform/src/service/operate_server/OptControl.cpp b/platform/src/service/operate_server/OptControl.cpp index 0a6e4da6..f37e1193 100644 --- a/platform/src/service/operate_server/OptControl.cpp +++ b/platform/src/service/operate_server/OptControl.cpp @@ -8,6 +8,8 @@ #include "operate_server_api/JsonOptCommand.h" #include "pub_utility_api/I18N.h" #include +#include "boost/unordered_map.hpp" +#include using namespace iot_service; using namespace iot_idl; @@ -460,6 +462,7 @@ int COperateServerClass::getPointCtrlInfo(const std::string &strTableName,const stCtrlInfo.ctrl_timeout = stDigCtrlAll.ctrl_timeout; stCtrlInfo.is_tagt_state = stDigCtrlAll.is_tagt_state; stCtrlInfo.resv_timeout = stDigCtrlAll.resv_timeout; + strncpy(stCtrlInfo.rtu_tag,stDigCtrlAll.rtu_tag, sizeof(stCtrlInfo.rtu_tag)); //获取RTU_TAG vecCtrlOffsetNo.push_back((stDigCtrlAll.offset_no1)); vecCtrlOffsetNo.push_back((stDigCtrlAll.offset_no2)); @@ -511,7 +514,9 @@ int COperateServerClass::getPointCtrlInfo(const std::string &strTableName,const stCtrlInfo.ctrl_timeout = stOptMixCtrlAll.ctrl_timeout; stCtrlInfo.is_tagt_state = stOptMixCtrlAll.is_tagt_state; stCtrlInfo.resv_timeout = stOptMixCtrlAll.resv_timeout; + strncpy(stCtrlInfo.rtu_tag,stOptMixCtrlAll.rtu_tag, sizeof(stCtrlInfo.rtu_tag)); //获取RTU_TAG strncpy(stCtrlInfo.offset_no,stOptMixCtrlAll.offset_no, 48); + for (int i = 0; i <5; ++i) { vecCtrlOffsetNo.push_back((stOptMixCtrlAll.offset_no)); @@ -561,6 +566,7 @@ int COperateServerClass::getPointCtrlInfo(const std::string &strTableName,const //获得控制动作组参数 //================================================================================================ stCtrlInfo.stCtrlActInfo.action_allow = true; + strncpy(stCtrlInfo.rtu_tag,stOptAnaCtrlAll.rtu_tag, sizeof(stCtrlInfo.rtu_tag)); //获取RTU_TAG strncpy(stCtrlInfo.offset_no,stOptAnaCtrlAll.offset_no, 48); return 1; } @@ -727,23 +733,23 @@ int COperateServerClass::checkCtrlRequest(SOptCtrlInfoAll &stOptCtrlInfo, const //遥控请求 int COperateServerClass::optCtrlRequest(const string &strJson, string &strResult) { - int nRetCode = -1 ; - //JSON解码到结构体 //================================================================================================= - COptCtrlRequest objCtrlRequest; SOptCtrlRequest stCtrlRequest; - SOptCtrlInfoAll stOptCtrlInfo; - - nRetCode = objCtrlRequest.parse(strJson, stCtrlRequest); + int nRetCode = COptCtrlRequest::parse(strJson, stCtrlRequest); if ( nRetCode <= 0) { LOGWARN("OptCtrlRequest, GetJsonHead() error!"); return -1; } + return optCtrlRequest(stCtrlRequest,strResult); +} + +int COperateServerClass::optCtrlRequest(const SOptCtrlRequest &stCtrlRequest, string &strResult) +{ //初始化控制请求信息到结构体 - //================================================================================================= + SOptCtrlInfoAll stOptCtrlInfo; stOptCtrlInfo.src_domain = stCtrlRequest.stHead.nSrcDomainID; stOptCtrlInfo.domain_id = stCtrlRequest.stHead.nDstDomainID; strcpy(stOptCtrlInfo.host_name, stCtrlRequest.stHead.strHostName.c_str()); @@ -753,10 +759,8 @@ int COperateServerClass::optCtrlRequest(const string &strJson, string &strResult stOptCtrlInfo.opt_time = stCtrlRequest.stHead.nOptTime; string strSrcTag = stCtrlRequest.stHead.strSrcTag; - for (size_t nLoop = 0; nLoop != stCtrlRequest.vecOptCtrlQueue.size(); ++nLoop) + for (size_t nLoop = 0; nLoop < stCtrlRequest.vecOptCtrlQueue.size(); ++nLoop) { - string strRequest="" ; - string strKeyIdTag = stCtrlRequest.vecOptCtrlQueue[nLoop].strKeyIdTag ; bool bIsDeviceOccupy = stCtrlRequest.vecOptCtrlQueue[nLoop].bIsDeviceOccupy; //是否设备占用 bool bCheckInterLock = stCtrlRequest.vecOptCtrlQueue[nLoop].bCheckInterLock; //是否检查闭锁 @@ -766,10 +770,11 @@ int COperateServerClass::optCtrlRequest(const string &strJson, string &strResult strKeyIdTag.c_str(), bIsDeviceOccupy, bCheckInterLock); //遥控请求;判断闭锁等;设备占用 - //================================================================================================= - nRetCode = checkCtrlRequest(stOptCtrlInfo, strKeyIdTag,dTargValue, + //=========================================================== + string strRequest="" ; + int nRetCode = checkCtrlRequest(stOptCtrlInfo, strKeyIdTag,dTargValue, bIsDeviceOccupy,bCheckInterLock,strRequest); - if (nRetCode <0 ) + if (nRetCode < 0 ) { strResult = I18N("遥控请求失败!!!"); strResult += strRequest; @@ -799,8 +804,7 @@ int COperateServerClass::optCtrlRequest(const string &strJson, string &strResult stOptCtrlReply.stHead.strResultStr = strResult ; stOptCtrlReply.stHead.nOptTime = stCtrlRequest.stHead.nOptTime ; - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlRequest(),json 命令编码失败! \n"); @@ -812,6 +816,7 @@ int COperateServerClass::optCtrlRequest(const string &strJson, string &strResult return nRetCode; } } + return 0; } @@ -1091,23 +1096,24 @@ int COperateServerClass::sendCancelCtrl (SOptCtrlInfoAll &stOptCtrlInfoAll,cons //遥控选择 int COperateServerClass::optCtrlSelect(const string &strJson) { - string strResult=""; - string strCtrlResult=""; - - COptCtrlRequest objOptCtrlSelect; SOptCtrlRequest stOptCtrlSelect; - - int nRetCode = objOptCtrlSelect.parse(strJson,stOptCtrlSelect); + int nRetCode = COptCtrlRequest::parse(strJson,stOptCtrlSelect); if ( nRetCode <= 0) { LOGWARN("OptCtrlSelect, GetJsonHead() error!"); return -1; } + return optCtrlSelect(stOptCtrlSelect); +} + +int COperateServerClass::optCtrlSelect(const SOptCtrlRequest &stOptCtrlSelect) +{ + string strResult=""; + string strCtrlResult=""; string strSourceTagSend = stOptCtrlSelect.stHead.strSrcTag + "#" + m_strSrcTagLocal + ":OptCtrlSelect"; SOptCtrlInfoAll stOptCtrlInfoAll; - stOptCtrlInfoAll.src_domain = stOptCtrlSelect.stHead.nSrcDomainID; stOptCtrlInfoAll.domain_id = stOptCtrlSelect.stHead.nDstDomainID; strcpy(stOptCtrlInfoAll.host_name, stOptCtrlSelect.stHead.strHostName.c_str()); @@ -1117,7 +1123,7 @@ int COperateServerClass::optCtrlSelect(const string &strJson) stOptCtrlInfoAll.opt_time = stOptCtrlSelect.stHead.nOptTime; string strKeyIdTag; - int nFlag = (0); //1:获取控制参数出错 2:设备控制保留 3:发送给FES失败或者控制信息表中插入记录失败 4:工程配置错误 + int nFlag = 0; //1:获取控制参数出错 2:设备控制保留 3:发送给FES失败或者控制信息表中插入记录失败 4:工程配置错误 bool bIsCalculate = false ;//是否计算量 SOptValueStatus stCurValueStatus, stNewValueStatus; @@ -1239,8 +1245,7 @@ int COperateServerClass::optCtrlSelect(const string &strJson) stOptCtrlReply.stHead.nOptTime = stOptCtrlInfoAll.opt_time ; stOptCtrlReply.stHead.strResultStr = strCtrlResult ; - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("OptCtrlSelect(),json 命令编码失败! \n"); @@ -1384,8 +1389,7 @@ int COperateServerClass::optVirtCtrlExeReply(const iot_idl::SOptVirtCtrlReply st stOptCtrlReply.stHead.strResultStr = I18N("遥控执行成功"); } - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("optVirtCtrlExeReply(),json 命令编码失败! \n"); @@ -1538,8 +1542,7 @@ int COperateServerClass::optVirtCtrlSelReply(const iot_idl::SOptVirtCtrlReply st stOptCtrlReply.stHead.strResultStr = I18N("遥控执行成功"); } - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("optVirtCtrlSelReply(),json 命令编码失败! \n"); @@ -1697,8 +1700,7 @@ int COperateServerClass::optCtrlSelectReply(const SFesCtrlReplyPkg &stReplyPkg) stOptCtrlReply.stHead.strResultStr = strResult; - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlSelectReply(),json 命令编码失败! \n"); @@ -1729,10 +1731,8 @@ int COperateServerClass::optCtrlClose(const string &strJson) int nRetCode =-1; string strResult=""; - COptCtrlRequest objOptCtrlClose; SOptCtrlRequest stOptCtrlClose; - - nRetCode = objOptCtrlClose.parse(strJson,stOptCtrlClose); + nRetCode = COptCtrlRequest::parse(strJson,stOptCtrlClose); if ( nRetCode <= 0) { LOGWARN("OptCtrlClose, GetJsonHead() error!"); @@ -1801,9 +1801,8 @@ int COperateServerClass::optCtrlCustom(const string &strJson) string strResultStr =""; string strResult=""; - COptCustCtrlRequest objOptCustCtrlRequest; SOptCustCtrlRequest stOptCustCtrlRequest; - nRetCode = objOptCustCtrlRequest.parse(strJson,stOptCustCtrlRequest); + nRetCode = COptCustCtrlRequest::parse(strJson,stOptCustCtrlRequest); if ( nRetCode <= 0) { LOGWARN("OptCtrlCustom, GetJsonHead() error!"); @@ -1922,8 +1921,7 @@ int COperateServerClass::optCtrlCustom(const string &strJson) stOptCtrlReply.stHead.nIsSuccess = false ; stOptCtrlReply.stHead.strResultStr = strResultStr ; - COptCustCtrlReply objOptCtrlReply; - string strReplyJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strReplyJson = COptCustCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("OptCtrlCustom(),json 命令编码失败! \n"); @@ -2034,8 +2032,7 @@ int COperateServerClass::optCtrlCustomReply(const SFesCustCmdReplyPkg &stFesCust //发送 SendUpOptPanel to Hmi //================================================================================ - COptCustCtrlReply objOptCtrlReply; - string strReplyJson = objOptCtrlReply.generate(stOptCustCtrlReply) ; + string strReplyJson = COptCustCtrlReply::generate(stOptCustCtrlReply) ; if(strReplyJson.size()<=1) { LOGWARN("OptCtrlCustCmdReply(),json 命令编码失败! \n"); @@ -2147,20 +2144,22 @@ int COperateServerClass::addSettingAlarm(const string &strKeyIdTag,const string //DO遥控执行 int COperateServerClass::optCtrlExecute(const string &strJson) { - int nRetCode =-1; - string strResult=""; - string strCtrlResult =""; - - COptCtrlRequest objOptDoCtrlExecute; SOptCtrlRequest stOptDoCtrlExecute; - - nRetCode = objOptDoCtrlExecute.parse(strJson,stOptDoCtrlExecute); + int nRetCode = COptCtrlRequest::parse(strJson,stOptDoCtrlExecute); if ( nRetCode <= 0) { LOGWARN("OptCtrlExecute, GetJsonHead() error!"); return -1; } + return optCtrlExecute(stOptDoCtrlExecute); +} + +int COperateServerClass::optCtrlExecute(const SOptCtrlRequest &stOptDoCtrlExecute) +{ + string strResult=""; + string strCtrlResult =""; + string strSrcTag = stOptDoCtrlExecute.stHead.strSrcTag; string strSourceTagSend = strSrcTag + "#" + m_strSrcTagLocal + ":OptCtrlExecute"; @@ -2319,8 +2318,7 @@ int COperateServerClass::optCtrlExecute(const string &strJson) stOptCtrlReply.stHead.strResultStr = I18N("遥控执行成功") ; } - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlExecute(),json 命令编码失败! \n"); @@ -2527,8 +2525,7 @@ int COperateServerClass::optCtrlExecuteReply(const SFesCtrlReplyPkg &stReplyPkg) stOptCtrlReply.stHead.strResultStr = I18N("遥控执行成功"); } - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlExecuteReply(),json 命令编码失败! \n"); @@ -2715,8 +2712,7 @@ int COperateServerClass::optCtrlCheckTargetVal() m_ptrOptComand->initUpOptPanel(stOptCtrlReply,strSourceTagSend,m_stRunAppInfo.nAppId,stOptCtrlInfoAll.domain_id,\ stOptCtrlInfoAll.host_name,stOptCtrlInfoAll.instance_name,strKeyIdTag,strResult,true,stOptCtrlInfoAll.opt_time); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlCheckTargetVal(),json 命令编码失败! \n"); @@ -2743,10 +2739,9 @@ int COperateServerClass::optCtrlCancel(const string &strJson) { int nFlag = (0); bool bIsCalculate = false; - COptCtrlRequest objOptCtrlCancel; - SOptCtrlRequest stOptCtrlCancel; - int nRetCode = objOptCtrlCancel.parse(strJson,stOptCtrlCancel); + SOptCtrlRequest stOptCtrlCancel; + int nRetCode = COptCtrlRequest::parse(strJson,stOptCtrlCancel); if ( nRetCode <= 0) { LOGWARN("OptCtrlCancel, GetJsonHead() error!"); @@ -2844,8 +2839,7 @@ int COperateServerClass::optCtrlCancel(const string &strJson) stOptCtrlCancel.stHead.strHostName, stOptCtrlCancel.stHead.strInstName,strKeyIdTag, strCtrlResult,false,stOptCtrlInfoAll.opt_time); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("OptCtrlCancel(),json 命令编码失败! \n"); @@ -2957,8 +2951,7 @@ int COperateServerClass::optCtrlCancelReply(const SFesCtrlReplyPkg &stReplyPkg) stOptCtrlReply.stHead.strResultStr=I18N("遥控取消成功"); } - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlCancelReply(),json 命令编码失败! \n"); @@ -3129,8 +3122,7 @@ int COperateServerClass::checkTimeOutCtrlRec() m_ptrOptComand->initUpOptPanel(stOptCtrlReply,strSourceTagSend,m_stRunAppInfo.nAppId,vecOptCtrlInfoAll[i].domain_id,\ vecOptCtrlInfoAll[i].host_name, vecOptCtrlInfoAll[i].instance_name,strKeyIdTag,strResult,false,vecOptCtrlInfoAll[i].opt_time); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::CheckTimeOutCtrlRec(),json 命令编码失败! \n"); @@ -3178,7 +3170,6 @@ int COperateServerClass::doOptAutoCtrl() return 1; } - string strJson; string strResult; for (m_itLinkageMapPos = m_mapLinkageInfo.begin(); m_itLinkageMapPos != m_mapLinkageInfo.end();) @@ -3212,7 +3203,7 @@ int COperateServerClass::doOptAutoCtrl() m_itLinkageMapPos->second.target_value, m_itLinkageMapPos->second.source_tag.c_str()); } - COptCtrlRequest objOptAutoCtrl; + SOptCtrlRequest stOptAutoCtrl; stOptAutoCtrl.stHead.strSrcTag = m_itLinkageMapPos->second.source_tag; //源标签(即发送端进程名) @@ -3240,10 +3231,9 @@ int COperateServerClass::doOptAutoCtrl() stOptCtrlQueue.bCheckInterLock = m_itLinkageMapPos->second.is_interlock; //闭锁检查 stOptAutoCtrl.vecOptCtrlQueue.push_back(stOptCtrlQueue); - strJson = objOptAutoCtrl.generate(stOptAutoCtrl) ; m_itLinkageMapPos->second.opt_step = LINKAGE_CTRL_REQUEST; - nRetCode = optCtrlRequest(strJson, strResult); //自动控制遥控请求命令 + nRetCode = optCtrlRequest(stOptAutoCtrl, strResult); //自动控制遥控请求命令 if (nRetCode < 0) { bIsSendFeedback = true; @@ -3301,9 +3291,8 @@ int COperateServerClass::doOptAutoCtrl() stOptCtrlQueue.bIsDeviceOccupy = false ; stOptAutoCtrl.vecOptCtrlQueue.push_back(stOptCtrlQueue); - strJson = objOptAutoCtrl.generate(stOptAutoCtrl) ; - nRetCode = optCtrlSelect(strJson); + nRetCode = optCtrlSelect(stOptAutoCtrl); if (nRetCode < 0) { bIsSendFeedback = true; @@ -3355,9 +3344,8 @@ int COperateServerClass::doOptAutoCtrl() stOptCtrlQueue.bIsDeviceOccupy = false ; stOptAutoCtrl.vecOptCtrlQueue.push_back(stOptCtrlQueue); - strJson = objOptAutoCtrl.generate(stOptAutoCtrl) ; - nRetCode = optCtrlExecute(strJson); + nRetCode = optCtrlExecute(stOptAutoCtrl); if (nRetCode == -1) { bIsSendFeedback = true; @@ -3513,8 +3501,7 @@ int COperateServerClass::doOptAutoCtrl() stOptCtrlReply.stHead.strResultStr+= m_itLinkageMapPos->second.ctrl_result; //FES控制返回结果 stOptCtrlReply.stHead.nOptTime = m_itLinkageMapPos->second.opt_time ; - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptCtrlSelectReply(),json 命令编码失败! \n"); @@ -3568,16 +3555,134 @@ int COperateServerClass::doOptAutoCtrl() return 0; } +int COperateServerClass::optAutoCtrlWithoutResp(const string &strJson) +{ + SOptCtrlRequest stReq; + int nRetCode = COptCtrlRequest::parse(strJson,stReq); + if ( nRetCode <= 0) + { + LOGWARN("optAutoCtrlWithoutResp, parse json error!"); + return -1; + } + + for(size_t nTag = 0; nTag < stReq.vecOptCtrlQueue.size(); nTag++) + { + const SOptCtrlReqQueue &stCtrl = stReq.vecOptCtrlQueue[nTag]; + auto iterCtrl = m_mapCtrlWithoutResp.find(stCtrl.strKeyIdTag); + if(iterCtrl != m_mapCtrlWithoutResp.end()) + { + LOGINFO("测点[%s]已经存在控制值[%lf],忽略旧值,采用新控制值[%lf]",stCtrl.strKeyIdTag.c_str(), + iterCtrl->second.dTargetValue,stCtrl.dTargetValue); + + iterCtrl->second = stCtrl; //< 覆盖掉老控制命令 + } + else + { + m_mapCtrlWithoutResp[stCtrl.strKeyIdTag] = stCtrl; + } + } + + return 0; +} + + +/********************************************** + * 现阶段主要针对功率控制场景,特点如下: + * 1、定时发送控制指令,所以不太关注本次控制是否成功 + * 2、一般一次性会下发很多控制点 + * 3、尽快下发,一般不会做太多的校验和判断,所以现阶段仅做简单的是否禁止控制的判断 + * 4、暂时仅处理AO控制 + **********************************************/ +int COperateServerClass::doOptAutoCtrlWithoutResp() +{ + if(m_mapCtrlWithoutResp.empty()) + { + return 0; + } + + std::set setInhibitCtrlDev; + getInhibitCtrlDevList(setInhibitCtrlDev); //获取禁止控制的设备列表 + + std::vector vecCtrlInfo; + vecCtrlInfo.reserve(m_mapCtrlWithoutResp.size()); + + for(auto iter = m_mapCtrlWithoutResp.begin(); iter != m_mapCtrlWithoutResp.end(); iter++) + { + const SOptCtrlReqQueue &stCtrl = iter->second; + + string strTableName,strTagName,strColumnName,strDevTag,strPntTag; + + if (splitKeyidTag(stCtrl.strKeyIdTag, strTableName, strTagName, strColumnName) < 0) + { + LOGWARN( "doOptAutoCtrlWithoutResp:SplitKeyidTag error! strKeyIdTag = %s",stCtrl.strKeyIdTag.c_str()); + continue; + } + + if(strTableName != RT_ANA_TBL) //< 暂时仅处理AO控制 + { + LOGWARN( "doOptAutoCtrlWithoutResp:仅支持AO控制. strKeyIdTag = %s",stCtrl.strKeyIdTag.c_str()); + continue; + } + + if(splitTagname(strTagName,strDevTag,strPntTag) < 0) + { + LOGWARN( "doOptAutoCtrlWithoutResp:splitTagname error! strKeyIdTag = %s",stCtrl.strKeyIdTag.c_str()); + continue; + } + + if(setInhibitCtrlDev.count(strDevTag)) //< 禁止控制,跳过 + { + LOGINFO("doOptAutoCtrlWithoutResp: 设备[%s]禁止控制,跳过",strDevTag.c_str()); + continue; + } + + SPointCtrlInfo stPntCtrlInfo; + string strGetPntCtrlInfoResult; + if(getPointCtrlInfo(strTableName,strTagName,0,stPntCtrlInfo,strGetPntCtrlInfoResult) < 0) + { + LOGWARN("doOptAutoCtrlWithoutResp:获取测点[%s]控制参数失败",stCtrl.strKeyIdTag.c_str()); + continue; + } + + //< 注意此处暂时只赋值了发送给FES需要的属性,其它未赋值! + SOptCtrlInfoAll stCtrlInfo; + strTableName.copy(stCtrlInfo.table_name,sizeof(stCtrlInfo.table_name) - 1); //< 减一的目的是保证最后一个字符为0 + strTagName.copy(stCtrlInfo.tag_name,sizeof(stCtrlInfo.tag_name)); //< 减一的目的是保证最后一个字符为0 + strncpy(stCtrlInfo.rtu_tag,stPntCtrlInfo.rtu_tag, sizeof(stCtrlInfo.rtu_tag)); + strncpy(stCtrlInfo.offset_no,stPntCtrlInfo.offset_no, sizeof(stCtrlInfo.offset_no)); + stCtrlInfo.target_value = stCtrl.dTargetValue; //< 没有处理基值和K值,与原有的OPT逻辑保持一致 + stCtrlInfo.ctrl_act_type = 0; //< DO和MO经过控制动作组转换的对FES的控制值,对AO没有用 + stCtrlInfo.is_tagt_state = CTRL_TYPE_NWAIT_ACK; //< 不能用测点上配置的,本指令因定时发送故不等待反馈,0:不等待返信 1:等待返信 2:不等遥控确认 + stCtrlInfo.msg_type = MT_FES_AO_EXECUTE; //< 暂时仅支持AO,所以直接写死 + + vecCtrlInfo.push_back(stCtrlInfo); + } + + if(vecCtrlInfo.empty()) + { + return 0; + } + + string strSourceTagSend = m_strSrcTagLocal + ":BatchOptCtrlExec"; + int nRetCode = m_ptrOptComand->batchSendCtrlToFes(vecCtrlInfo,strSourceTagSend); //< 内部暂时仅处理的AO + + if(nRetCode < 0) + { + LOGWARN("doOptAutoCtrlWithoutResp,批量发送控制命令失败!"); + return nRetCode; + } + + return 0; +} + //联动/顺控,直控/外部权限移交、标志牌同步等自动控制处理 int COperateServerClass::optAutoCtrl(const string &strJson) { int nRetCode =-1; - COptCtrlRequest objOptAutoCtrl; SOptCtrlRequest stOptAutoCtrl; - - nRetCode = objOptAutoCtrl.parse(strJson,stOptAutoCtrl); + nRetCode = COptCtrlRequest::parse(strJson,stOptAutoCtrl); if ( nRetCode <= 0) { LOGWARN("OptAutoCtrl, GetJsonHead() error!"); @@ -3615,15 +3720,21 @@ int COperateServerClass::optAutoCtrl(const string &strJson) //得到是否需要遥控选择 //============================================================================================ - nRetCode = getCtrlTableName(strTableName,strCtrlTableName) ; - strKeyTagName.resize(64); - nRetCode = m_ptrRdbTableMng->getRecordOneColumnByKey(strCtrlTableName, strKeyTagName.c_str(), "ctrl_type",nCtrlType); - if (nRetCode == false) + if(nPointType == POINT_TYPE_ANA) { - LOGWARN("OptAutoCtrl, nRetCode = %d, strTableName = %s, strTagName = %s, getRecordOneColumnByKey(ctrl_type) error! ", - nRetCode, strTableName.c_str(), strTagName.c_str() ); + nCtrlType = CTRL_TYPE_DIRECTEXE; //模拟量直接控制 + } + else + { + nRetCode = getCtrlTableName(strTableName,strCtrlTableName) ; + strKeyTagName.resize(64); + nRetCode = m_ptrRdbTableMng->getRecordOneColumnByKey(strCtrlTableName, strKeyTagName.c_str(), "ctrl_type",nCtrlType); + if (nRetCode == false) + { + LOGWARN("OptAutoCtrl, nRetCode = %d, strTableName = %s, strTagName = %s, getRecordOneColumnByKey(ctrl_type) error! ", + nRetCode, strTableName.c_str(), strTagName.c_str() ); + } } - if(nPointType == POINT_TYPE_ANA) nCtrlType = CTRL_TYPE_DIRECTEXE; //模拟量直接控制 //初始化自动控结构信息 //============================================================================================ @@ -3828,6 +3939,16 @@ int COperateServerClass::getAnaCtrlValue(SOptCtrlInfoAll &stOptCtrlInfoAll ) return 1; } +int COperateServerClass::getInhibitCtrlDevList(std::set &setDev) +{ + std::set setShieldDev; + getTokenDevWithInhibitCtrl(setDev); + getShieldDevWithInhibitCtrl(setShieldDev); + + setDev.insert(setShieldDev.begin(),setShieldDev.end()); + + return 0; +} //五防校验超时 int COperateServerClass::checkTimeOutCtrlPrev() diff --git a/platform/src/service/operate_server/OptHandover.cpp b/platform/src/service/operate_server/OptHandover.cpp index 8b8a4f2d..a7018620 100644 --- a/platform/src/service/operate_server/OptHandover.cpp +++ b/platform/src/service/operate_server/OptHandover.cpp @@ -26,12 +26,11 @@ using namespace std; int COperateServerClass::optInternHandover(const string &strJson) { int nRetCode = 0; - CHandoverRequest objHandoverRequest; SHandoverRequest stHandoverRequest; LOGINFO("OptInternHandover, json =%s !",strJson.c_str()); - int bRetCode = objHandoverRequest.parse(strJson,stHandoverRequest) ; + int bRetCode = CHandoverRequest::parse(strJson,stHandoverRequest) ; if ( bRetCode == false) { LOGWARN("OptInternHandover, objHandoverRequest.parse() error!"); @@ -605,8 +604,7 @@ int COperateServerClass::addOneInternHandoverReply(const SOptInternHandover &st stHandoverReply.stHead.nIsSuccess = bIsSucess ; stHandoverReply.stHead.strResultStr = strResultStr ; - CHandoverReply objHandoverReply ; - string strJson = objHandoverReply.generate(stHandoverReply) ; + string strJson = CHandoverReply::generate(stHandoverReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::AddOneInternHandoverReply(),json 命令编码失败! \n"); diff --git a/platform/src/service/operate_server/OptMainThread.cpp b/platform/src/service/operate_server/OptMainThread.cpp index 293fd843..05a3e20a 100644 --- a/platform/src/service/operate_server/OptMainThread.cpp +++ b/platform/src/service/operate_server/OptMainThread.cpp @@ -97,7 +97,7 @@ void COptMainThread::processAppMessage(const iot_net::CMbMessage &recvMsg) case MT_APP2OPT_VIRT_CTRL_MIX_REPLY: { iot_idl::SOptVirtCtrlReply objAppVirtCtrlReply; - objAppVirtCtrlReply.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objAppVirtCtrlReply.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize()) ); LOGDEBUG("processAppMessage, APP控制命令返回: tagName = %s, nResult = %d,strError = %s ", objAppVirtCtrlReply.str_tag_name().c_str(),objAppVirtCtrlReply.n_ctrl_result(),objAppVirtCtrlReply.str_err().c_str()); m_ptrOperateServer->optVirtCtrlExeReply(objAppVirtCtrlReply); @@ -130,7 +130,7 @@ void COptMainThread::processFesMessage(const iot_net::CMbMessage &recvMsg) case MT_FES_DO_SELECT_REPLY: // 遥控选择返校 { SFesCtrlReplyPkg objFesCtrlReplyPkg; - objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize()) ); LOGDEBUG("processAppMessage, fes遥控选择返回: tagName = %s, nResult = %d,strError = %s ", objFesCtrlReplyPkg.strapptagname().c_str(),objFesCtrlReplyPkg.nresult(),objFesCtrlReplyPkg.strpara().c_str()); m_ptrOperateServer->optCtrlSelectReply(objFesCtrlReplyPkg); @@ -141,7 +141,7 @@ void COptMainThread::processFesMessage(const iot_net::CMbMessage &recvMsg) case MT_FES_MO_EXECUTE_REPLY: { SFesCtrlReplyPkg objFesCtrlReplyPkg; - objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize())); LOGDEBUG("processAppMessage, fes遥控执行返回: tagName = %s, nResult = %d,strError = %s ", objFesCtrlReplyPkg.strapptagname().c_str(),objFesCtrlReplyPkg.nresult(),objFesCtrlReplyPkg.strpara().c_str()); m_ptrOperateServer->optCtrlExecuteReply(objFesCtrlReplyPkg); @@ -150,7 +150,7 @@ void COptMainThread::processFesMessage(const iot_net::CMbMessage &recvMsg) case MT_FES_DO_CANCEL_REPLY: //遥控撤销返校 { SFesCtrlReplyPkg objFesCtrlReplyPkg; - objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objFesCtrlReplyPkg.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize())); LOGDEBUG("processAppMessage, fes遥控撤销返回: tagName = %s, nResult = %d,strError = %s ", objFesCtrlReplyPkg.strapptagname().c_str(),objFesCtrlReplyPkg.nresult(),objFesCtrlReplyPkg.strpara().c_str()); m_ptrOperateServer->optCtrlCancelReply(objFesCtrlReplyPkg); @@ -159,7 +159,7 @@ void COptMainThread::processFesMessage(const iot_net::CMbMessage &recvMsg) case MT_FES_DEFINE_CMD_REPLAY://自定义控制命令 { SFesCustCmdReplyPkg objFesCustCmdReplyPkg; - objFesCustCmdReplyPkg.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objFesCustCmdReplyPkg.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize())); LOGDEBUG("processAppMessage, fes自定义控制命令返回: tagName = %s, nResult = %d,strError = %s ", objFesCustCmdReplyPkg.strapptagname().c_str(),objFesCustCmdReplyPkg.nresult(),objFesCustCmdReplyPkg.strretresult().c_str()); m_ptrOperateServer->optCtrlCustomReply(objFesCustCmdReplyPkg); @@ -168,13 +168,13 @@ void COptMainThread::processFesMessage(const iot_net::CMbMessage &recvMsg) case MT_FES_VIRTUAL_CTRL: //前置发过来的虚拟控制 { SFesChangeVirtualDataPkg objFesVirCtrlPkg; - objFesVirCtrlPkg.ParseFromArray(recvMsg.getDataPtr(),recvMsg.getDataSize()); + objFesVirCtrlPkg.ParseFromArray(recvMsg.getDataPtr(),static_cast(recvMsg.getDataSize())); m_ptrOperateServer->optFesCtrlExecute(objFesVirCtrlPkg); break; } default: { - LOGINFO("processFesMessage, MsgType = %d, operate_server not support this message",nMessageType); + LOGTRACE("processFesMessage, MsgType = %d, operate_server not support this message",nMessageType); break; } }// end switch @@ -237,6 +237,11 @@ void COptMainThread::processHmiMessage(const iot_net::CMbMessage &recvMsg) m_ptrOperateServer->optAutoCtrl(strMessage); break; } + case MT_OPT_AUTO_CTRL_WITHOUT_RESP: //无需等待反馈,主要用于功率控制的场景 + { + m_ptrOperateServer->optAutoCtrlWithoutResp(strMessage); + break; + } case MT_OPT_PINHIBIT_REF: //静止刷新 case MT_OPT_PINHIBIT_ALARM://静止报警 case MT_OPT_PINHIBIT_CTRL: //静止控制 @@ -354,6 +359,7 @@ void COptMainThread::execute() //=============================================================================================== //if (lCurTime - m_lLastAutoCtrlTime >= 10) { + m_ptrOperateServer->doOptAutoCtrlWithoutResp(); //< 处理无需等待的缓存的控制命令 m_ptrOperateServer->doOptAutoCtrl(); //读自动控制Map 并执行 m_lLastAutoCtrlTime = lCurTime; } diff --git a/platform/src/service/operate_server/OptShieldSet.cpp b/platform/src/service/operate_server/OptShieldSet.cpp index 4e8272f5..f74221d2 100644 --- a/platform/src/service/operate_server/OptShieldSet.cpp +++ b/platform/src/service/operate_server/OptShieldSet.cpp @@ -157,9 +157,8 @@ int COperateServerClass::optShieldSet(const string &strJson) { int nIsSet = 0 ; SOptShieldSet stOptShieldSet; - COptShieldSet objOptShieldSet; - bool bRetCode = objOptShieldSet.parse(strJson,stOptShieldSet) ; + bool bRetCode = COptShieldSet::parse(strJson,stOptShieldSet) ; if ( bRetCode == false) { LOGWARN("OptShieldSet, GetJsonHead() error!"); @@ -330,8 +329,7 @@ int COperateServerClass::setShieldObjInfo(SOptShieldCfgInfo stShieldCfgInfo,SOpt m_ptrOptComand->initUpOptPanel(stOptCtrlReply, stHead.strSrcTag, m_stRunAppInfo.nAppId, stHead.nSrcDomainID, \ stHead.strHostName, stHead.strInstName, iterObj->key_id_tag, "屏蔽操作成功", true); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply); + string strJson = COptCtrlReply::generate(stOptCtrlReply); if (strJson.size() <= 1) { LOGWARN("COperateServerClass::OptToken(),json 命令编码失败! \n"); @@ -821,3 +819,10 @@ int COperateServerClass::initShieldStatus() } return 1; } + +int COperateServerClass::getShieldDevWithInhibitCtrl(std::set &setDev) +{ + boost::ignore_unused_variable_warning(setDev); + //LOGINFO("暂未实现获取禁止控制的设备屏蔽列表"); + return 0; +} diff --git a/platform/src/service/operate_server/OptTagSet.cpp b/platform/src/service/operate_server/OptTagSet.cpp index 233a2e8c..3de5ad48 100644 --- a/platform/src/service/operate_server/OptTagSet.cpp +++ b/platform/src/service/operate_server/OptTagSet.cpp @@ -59,9 +59,8 @@ bool COperateServerClass::checkIsOptTag(int &nIsSet,const string &strKeyIdTag,co int COperateServerClass::optPointTag(const string &strJson) { SOptTagSet stOptTagSet; - COptTagSet objOptTagSet; - int bRetCode = objOptTagSet.parse(strJson,stOptTagSet) ; + int bRetCode = COptTagSet::parse(strJson,stOptTagSet) ; if ( bRetCode == false) { LOGWARN("OptPointTag, GetJsonHead() error!"); @@ -229,8 +228,7 @@ int COperateServerClass::optPointTag(const string &strJson) m_ptrOptComand->initUpOptPanel(stOptCtrlReply,strSrcTag,m_stRunAppInfo.nAppId,stOptTagSet.stHead.nSrcDomainID,\ stOptTagSet.stHead.strHostName,stOptTagSet.stHead.strInstName ,stOptCtrlInfo.key_id_tag,I18N("点标签操作成功"),true); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptToken(),json 命令编码失败! \n"); @@ -413,7 +411,6 @@ int COperateServerClass::updateTagInfo(const SOptCtrlInfoAll &stOptTagInfo,const // update rdb // ---------------------------------------------------------------------------------- - /* vector vecCondInfo; CRdbPublic::addCondInfo(vecCondInfo,"tag_type", nTagType); CRdbPublic::addCondInfo(vecCondInfo,"key_id_tag",stOptTagInfo.key_id_tag); @@ -421,7 +418,7 @@ int COperateServerClass::updateTagInfo(const SOptCtrlInfoAll &stOptTagInfo,const { LOGERROR("UpdateTagInfo, table_name = %s, tag_type=%d,key_id_tag=%s,removeMultiCondition error!", RT_OPT_TAG_INFO,nTagType,stOptTagInfo.key_id_tag); - }*/ + } } else { @@ -446,7 +443,6 @@ int COperateServerClass::updateTagInfo(const SOptCtrlInfoAll &stOptTagInfo,const // update rdb // ---------------------------------------------------------------------------------- - SOptTagInfoAll stTagInfo ; strcpy(stTagInfo.key_id_tag,stOptTagInfo.key_id_tag) ; stTagInfo.tag_type =nTagType; @@ -538,10 +534,9 @@ int COperateServerClass::optAiLimitSet(const string &strJson) //JSON解码到结构体 //=========================================================================================================== - CAiLimitSet objAiLimitSet; SAiLimitSet stAiLimitSet; - bRetCode = objAiLimitSet.parse(strJson, stAiLimitSet); + bRetCode = CAiLimitSet::parse(strJson, stAiLimitSet); if ( bRetCode == false) { LOGWARN("OptAiLimitSet, parse() error!"); @@ -621,8 +616,7 @@ int COperateServerClass::optAiLimitSet(const string &strJson) m_ptrOptComand->initUpOptPanel(stOptCtrlReply,strSourceTagSend,m_stRunAppInfo.nAppId,stOptCtrlInfo.domain_id,\ stAiLimitSet.stHead.strHostName,stAiLimitSet.stHead.strInstName,strkeyIdTag,strResult,nIsSucess); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptAiLimitSet(),json 命令编码失败! \n"); diff --git a/platform/src/service/operate_server/OptToken.cpp b/platform/src/service/operate_server/OptToken.cpp index e80b6d6d..3115844a 100644 --- a/platform/src/service/operate_server/OptToken.cpp +++ b/platform/src/service/operate_server/OptToken.cpp @@ -322,10 +322,9 @@ int COperateServerClass::optToken(const string &strJson, const bool bIsSync /*= int nRetCode =0 ; int nIsSet = OPT_TOKEN_SET; //默认挂牌操作 - CTokenSet objOptTkokenSet; STokenSet stOptTokenSet; - int bRetCode = objOptTkokenSet.parse(strJson,stOptTokenSet) ; + int bRetCode = CTokenSet::parse(strJson,stOptTokenSet) ; if ( bRetCode == false) { LOGWARN("OptToken, objOptTkokenSet.parse() error!"); @@ -469,8 +468,7 @@ int COperateServerClass::optToken(const string &strJson, const bool bIsSync /*= m_ptrOptComand->initUpOptPanel(stOptCtrlReply,strSourceTag,m_stRunAppInfo.nAppId,stOptTokenSet.stHead.nSrcDomainID,\ stOptTokenSet.stHead.strHostName,stOptTokenSet.stHead.strInstName ,stOptTokenInfo.key_id_tag,strResult,true); - COptCtrlReply objOptCtrlReply; - string strJson = objOptCtrlReply.generate(stOptCtrlReply) ; + string strJson = COptCtrlReply::generate(stOptCtrlReply) ; if(strJson.size()<=1) { LOGWARN("COperateServerClass::OptToken(),json 命令编码失败! \n"); @@ -606,3 +604,55 @@ int COperateServerClass::optTokenAlarm(const STokenInfoAll &stOptTokenInfo, cons return 0; } + +int COperateServerClass::getTokenDevWithInhibitCtrl(std::set &setDev) +{ + //< 因为挂牌一般都比较少,所以直接遍历 + int nTokenInfoCount = m_ptrRdbTableMng->getTableRecordCount(RT_OPT_TOKEN_INFO); + if(nTokenInfoCount <= 0) + { + return iotSuccess; + } + + int nTokenDefCount = m_ptrRdbTableMng->getTableRecordCount(RT_OPT_TOKEN_DEF); + if(nTokenDefCount <= 0) + { + return iotSuccess; + } + + //< 获取被设置禁止控制的挂牌ID + int nMask = 1 << STATE_DI_TOKEN_PROHIBIT; + set setTokenID; + for(int nDefIndex = 0; nDefIndex < nTokenDefCount; nDefIndex++) + { + STokenDefine *pDef = (STokenDefine*)m_ptrRdbTableMng->getRecordAllColumnByIndex(RT_OPT_TOKEN_DEF,nDefIndex); + if(pDef == NULL) + { + LOGWARN("获取挂牌定义表记录失败"); + continue; + } + + if(pDef->token_prop & nMask) + { + setTokenID.insert(pDef->token_id); + } + } + + //< 判断设备是否被禁止控制 + for(int nInfo = 0; nInfo < nTokenInfoCount; nInfo++) + { + STokenInfoAll *pInfo = (STokenInfoAll*)m_ptrRdbTableMng->getRecordAllColumnByIndex(RT_OPT_TOKEN_INFO,nInfo); + if(pInfo == NULL) + { + LOGWARN("获取挂牌信息表记录失败"); + continue; + } + + if(setTokenID.count(pInfo->token_id)) //< 禁止控制 + { + setDev.insert(pInfo->device); + } + } + + return iotSuccess; +} diff --git a/platform/src/service/perm_mng_api/PermMngImpl.cpp b/platform/src/service/perm_mng_api/PermMngImpl.cpp index 0af4983e..f0bdb5fc 100644 --- a/platform/src/service/perm_mng_api/PermMngImpl.cpp +++ b/platform/src/service/perm_mng_api/PermMngImpl.cpp @@ -1607,11 +1607,48 @@ int CPermMngImpl::getAllUsergID(std::vector &vecUsergID) return PERM_NORMAL; } +int CPermMngImpl::GetAllowDurationByUserId(const int &nPermId, int &nAllowDuration) +{ + int ret = 0; + + int permId; + + permId = nPermId; + + nAllowDuration = 0; + + std::vector mVecUserInfo; + ret = m_ptrRdbTableMng->selectAllColumnOneCondition(RT_RM_USER_DEF,mVecUserInfo,"perm_id",permId); + if (ret == false) + { + LOGERROR("CPermMngImpl::GetAllowDurationByUserId, ret = %d, m_RdbTable.ConGet(PERM_USER_DEF) error! userId = %d", + ret, permId); + return PERM_ERROR; + } + if (mVecUserInfo.size() == 0) + { + LOGERROR("CPermMngImpl::GetAllowDurationByUserId, 用户名id不存在!userId = %d", + permId); + return PERM_NO_NAME; + } + if (mVecUserInfo.size() > 1) + { + LOGERROR("CPermMngImpl::GetAllowDurationByUserId, 用户名id有重复!userId = %d", + permId); + return PERM_REDUP_NAME; + } + nAllowDuration = mVecUserInfo[0].allow_duration; + + return PERM_NORMAL; +} + //以下为私有函数 //写共享内存 int CPermMngImpl::WritePermShm(const int nUserId, const int userg_id, const int64 os_uptime, const int64 login_time, const int login_sec, const char *instance_name) { + boost::ignore_unused_variable_warning(os_uptime); + m_spUserInfo->user_id = nUserId; m_spUserInfo->userg_id = userg_id; //m_spUserInfo->os_uptime = os_uptime; @@ -1625,6 +1662,8 @@ int CPermMngImpl::WritePermShm(const int nUserId, const int userg_id, const int6 int CPermMngImpl::GetCurUserInfo(int &nUserId, int &userg_id, int64 &os_uptime, int64 &login_time, int &login_sec, string &instance_name) { + boost::ignore_unused_variable_warning(os_uptime); + nUserId = m_spUserInfo->user_id; userg_id = m_spUserInfo->userg_id; //os_uptime = m_spUserInfo->os_uptime; diff --git a/platform/src/service/perm_mng_api/PermMngImpl.h b/platform/src/service/perm_mng_api/PermMngImpl.h index 86c73f06..cae7b3a8 100644 --- a/platform/src/service/perm_mng_api/PermMngImpl.h +++ b/platform/src/service/perm_mng_api/PermMngImpl.h @@ -306,6 +306,12 @@ public: */ int getAllUsergID(std::vector &vecUsergID) override; + /** + @brief 由用户ID号得到允许持续时间 + @param [in/out] int & nPermId 用户名对应的用户ID号 + @param [in/out] int & nAllowDuration 用户名对应的允许持续时间 + */ + int GetAllowDurationByUserId(const int &nPermId,int &nAllowDuration) override; private: class CBioIdentify { diff --git a/platform/src/service/sample_server_api/SampleThreadImpl.cpp b/platform/src/service/sample_server_api/SampleThreadImpl.cpp index 28ca19a2..8d57e3d3 100644 --- a/platform/src/service/sample_server_api/SampleThreadImpl.cpp +++ b/platform/src/service/sample_server_api/SampleThreadImpl.cpp @@ -61,6 +61,7 @@ void CSampleThreadImpl::execute() //1.所有点存盘周期为固定5分钟 //================================================================================================= + /* 暂时禁用掉 int mMin = m_lCurTime/(60000) ;//转换为分钟 if ( (mMin % (SAMPLE_CYC_MIN) == 0) && (m_lCurTime/60000 - m_lLastTime/60000) >0 )//每5 min判一次 { @@ -68,6 +69,7 @@ void CSampleThreadImpl::execute() saveAllPoint() ; LOGDEBUG("CSampleThreadImpl::execute, saveAllPoint() Time=[%" PRId64 "] ", m_lCurTime); } + */ //2.从消息缓存队列读取消息并处理 //================================================================================================= @@ -498,7 +500,7 @@ void CSampleThreadImpl::saveAllCfgPoint() int64 nTimeStamp = (getUTCTimeMsec()/(60*1000)) * 60000; //得到固定的分钟 if(nPeriod<=0) nPeriod = 1;// - int mMin = m_lCurTime/(60*1000) ;//转换为分钟 + int64 mMin = m_lCurTime/(60*1000) ;//转换为分钟 if( (mMin % nPeriod == 0)) { if(POINT_TYPE_ANA == nPointType) @@ -531,8 +533,9 @@ void CSampleThreadImpl::saveAllCfgPoint() void CSampleThreadImpl::saveAllPoint() { int64 nTimeStamp = (getUTCTimeMsec()/(60*1000)) * 60000; //得到固定的分钟 + LOCALTIME localTime = convertUTCMsecToLocalTime(nTimeStamp); - saveAllAnaPoint(nTimeStamp); + saveAllAnaPoint(nTimeStamp,localTime.wMinute); saveAllDigPoint(nTimeStamp); @@ -544,7 +547,7 @@ void CSampleThreadImpl::saveAllPoint() } //模拟量周期存盘 -void CSampleThreadImpl::saveAllAnaPoint(const int64 nTimeStamp) +void CSampleThreadImpl::saveAllAnaPoint(const int64 nTimeStamp,const int &minOfHour) { STssInsert stTsdbData; stTsdbData.Clear(); @@ -556,6 +559,13 @@ void CSampleThreadImpl::saveAllAnaPoint(const int64 nTimeStamp) pAnaPoint = (SAnaPointAll*)m_ptrRdbTableMng->getRecordAllColumnByIndex(RT_ANA_TBL,nIndex); if(NULL != pAnaPoint) { + //caodingfa:存盘周期不等于SAMPLE_CYC_MIN时,按存盘周期定时存储,可以是一个小时内的一个分钟数,比如0、15、30、45 + if((pAnaPoint->sample_period != SAMPLE_CYC_MIN) && + (pAnaPoint->sample_period == 0 || minOfHour % pAnaPoint->sample_period != 0)) + { + continue; + } + addOneTsdbData(stTsdbData, pAnaPoint->tag_name,pAnaPoint->status,pAnaPoint->value,nTimeStamp); } else diff --git a/platform/src/service/sample_server_api/SampleThreadImpl.h b/platform/src/service/sample_server_api/SampleThreadImpl.h index 40a3a678..91c3f994 100644 --- a/platform/src/service/sample_server_api/SampleThreadImpl.h +++ b/platform/src/service/sample_server_api/SampleThreadImpl.h @@ -50,7 +50,7 @@ private: //全数据存盘 void saveAllCfgPoint(); //保存所有配置的点全数据 void saveAllPoint(); //存盘全数据 - void saveAllAnaPoint(const int64 uTimeStamp); + void saveAllAnaPoint(const int64 uTimeStamp,const int &minOfHour); void saveAllDigPoint(const int64 uTimeStamp); void saveAllAccPoint(const int64 uTimeStamp); void saveAllMixPoint(const int64 uTimeStamp); diff --git a/platform/src/service/sample_server_api/sample_server_api.pro b/platform/src/service/sample_server_api/sample_server_api.pro index 25d7a6c1..9dbd3b35 100644 --- a/platform/src/service/sample_server_api/sample_server_api.pro +++ b/platform/src/service/sample_server_api/sample_server_api.pro @@ -35,7 +35,8 @@ LIBS += \ -lprotobuf \ -ltsdb_save_api \ -llog4cplus\ - -lboost_chrono + -lboost_chrono \ + -lboost_date_time include($$PWD/../../idl_files/idl_files.pri) diff --git a/platform/src/service/service.pro b/platform/src/service/service.pro index 949910ba..6f2c144d 100644 --- a/platform/src/service/service.pro +++ b/platform/src/service/service.pro @@ -11,9 +11,9 @@ SUBDIRS+= interlock_api \ operate_server \ alarm_server \ web_server \ - web_server_bi \ +# web_server_bi \ alarm_system \ - iscs_wise_mnp \ +# iscs_wise_mnp \ alarm_resource \ operate_server.depends = interlock_api perm_mng_api data_process_api diff --git a/platform/src/service/web_server/module_alarm/AlmCntWsLsnr.cpp b/platform/src/service/web_server/module_alarm/AlmCntWsLsnr.cpp index 15d80d08..ff5f28d4 100644 --- a/platform/src/service/web_server/module_alarm/AlmCntWsLsnr.cpp +++ b/platform/src/service/web_server/module_alarm/AlmCntWsLsnr.cpp @@ -47,6 +47,8 @@ oatpp::async::CoroutineStarter CAlmCntWsLsnr::onPing oatpp::async::CoroutineStarter CAlmCntWsLsnr::onPong ( const std::shared_ptr &spSocket, const oatpp::String &strMsg ) { + boost::ignore_unused_variable_warning(spSocket); + LOGINFO( "onPong(): message='%s'", strMsg->c_str()); assert( spSocket == m_spHolder->m_spSocket ); @@ -56,6 +58,8 @@ oatpp::async::CoroutineStarter CAlmCntWsLsnr::onPong oatpp::async::CoroutineStarter CAlmCntWsLsnr::onClose ( const std::shared_ptr &spSocket, v_uint16 nCode, const oatpp::String &strMsg ) { + boost::ignore_unused_variable_warning(spSocket); + LOGINFO( "onClose(): code=%d message='%s'", nCode, strMsg->c_str()); assert( spSocket == m_spHolder->m_spSocket ); @@ -68,6 +72,8 @@ oatpp::async::CoroutineStarter CAlmCntWsLsnr::onClose oatpp::async::CoroutineStarter CAlmCntWsLsnr::readMessage ( const std::shared_ptr &spSocket, v_uint8 nOpCode, p_char8 pData, oatpp::v_io_size nSize ) { + boost::ignore_unused_variable_warning(spSocket); + assert( spSocket == m_spHolder->m_spSocket ); if ( nSize > 0 ) @@ -77,8 +83,7 @@ oatpp::async::CoroutineStarter CAlmCntWsLsnr::readMessage else if ( nSize == 0 ) { //< size为0,表示消息传送完毕 - if ( (oatpp::websocket::Frame::OPCODE_TEXT != nOpCode) - && (oatpp::websocket::Frame::OPCODE_CONTINUATION != nOpCode) ) + if ( oatpp::websocket::Frame::OPCODE_TEXT != nOpCode ) { LOGERROR( "onMessage(): opcode=%d, not Text, 非预期!", nOpCode ); m_buffMsgRcv.reset(); @@ -197,7 +202,7 @@ void CAlmCntWsLsnr::sendMessage() //< 预分配,提升性能 { - size_t nReserve = 1.6 * ( vecSpAllAlm.size() > 10000 ? vecSpAllAlm.size() : 10000 ); + size_t nReserve = static_cast(1.6 * ( vecSpAllAlm.size() > 10000 ? vecSpAllAlm.size() : 10000 ) ); m_objAlmTable.get().reserve( nReserve ); } diff --git a/platform/src/service/web_server/module_alarm/AlmWsLsnr.cpp b/platform/src/service/web_server/module_alarm/AlmWsLsnr.cpp index c05e4fe5..d2432100 100644 --- a/platform/src/service/web_server/module_alarm/AlmWsLsnr.cpp +++ b/platform/src/service/web_server/module_alarm/AlmWsLsnr.cpp @@ -61,6 +61,8 @@ oatpp::async::CoroutineStarter CAlmWsLsnr::onPing oatpp::async::CoroutineStarter CAlmWsLsnr::onPong ( const std::shared_ptr &spSocket, const oatpp::String &strMsg ) { + boost::ignore_unused_variable_warning(spSocket); + LOGINFO( "onPong(): message='%s'", strMsg->c_str()); assert( spSocket == m_spHolder->m_spSocket ); @@ -70,6 +72,8 @@ oatpp::async::CoroutineStarter CAlmWsLsnr::onPong oatpp::async::CoroutineStarter CAlmWsLsnr::onClose ( const std::shared_ptr &spSocket, v_uint16 nCode, const oatpp::String &strMsg ) { + boost::ignore_unused_variable_warning(spSocket); + LOGINFO( "onClose(): code=%d message='%s'", nCode, strMsg->c_str()); assert( spSocket == m_spHolder->m_spSocket ); @@ -82,6 +86,8 @@ oatpp::async::CoroutineStarter CAlmWsLsnr::onClose oatpp::async::CoroutineStarter CAlmWsLsnr::readMessage ( const std::shared_ptr &spSocket, v_uint8 nOpCode, p_char8 pData, oatpp::v_io_size nSize ) { + boost::ignore_unused_variable_warning(spSocket); + assert( spSocket == m_spHolder->m_spSocket ); if ( nSize > 0 ) @@ -91,8 +97,7 @@ oatpp::async::CoroutineStarter CAlmWsLsnr::readMessage else if ( nSize == 0 ) { //< size为0,表示消息传送完毕 - if ( (oatpp::websocket::Frame::OPCODE_TEXT != nOpCode) - && (oatpp::websocket::Frame::OPCODE_CONTINUATION != nOpCode) ) + if ( oatpp::websocket::Frame::OPCODE_TEXT != nOpCode ) { LOGERROR( "onMessage(): opcode=%d, not Text, 非预期!", nOpCode ); m_buffMsgRcv.reset(); @@ -289,6 +294,28 @@ oatpp::async::CoroutineStarter CAlmWsLsnr::readMessage } } + //< keyIdTag + m_spHolder->m_setKeyIdTag.clear(); + if ( spReq->keyIdTag != nullptr && !spReq->keyIdTag->empty()) + { + strTemp = spReq->keyIdTag->c_str(); + auto list = strTemp.split( ";" ); + for ( auto &it:list ) + { + // 转化后台测点格式 + auto listTemp = it.split( "." ); + if(listTemp.size() == 7) + { + listTemp.removeAt(0); + listTemp.removeAt(0); + + it = listTemp.join("."); + } + if ( !it.isEmpty()) + m_spHolder->m_setKeyIdTag.emplace( std::move( it.toStdString())); + } + } + //< type m_spHolder->m_setAlmType.clear(); if ( !spReq->type->empty()) @@ -507,63 +534,72 @@ void CAlmWsLsnr::sendMessage() spRep->total = std::ceil( static_cast ( spRep->records ) / spRep->pageSize ); if ( spRep->total <= 0 ) spRep->total = 1; //< 前流程已保证 m_spHolder->m_nPageNo 大于 0 - spRep->pageNo = m_spHolder->m_nPageNo > spRep->total ? - spRep->total.getValue( 0 ) : m_spHolder->m_nPageNo; - spRep->data = oatpp::Vector>::createShared(); - const int nBeginIdx = ( spRep->pageNo - 1 ) * spRep->pageSize; - //< 使用std::min或者std::max的时候加上括号,避免与Windows.h中的min、max宏定义冲突 - const int nEndIdx = ( std::min )( nBeginIdx + spRep->pageSize, ( int ) m_pAlmTable->size()); - int nIdx = 0; - auto &indexOrder = m_pAlmTable->get(); - for ( auto it = indexOrder.cbegin(); it != indexOrder.cend() && nIdx < nEndIdx; ++it, ++nIdx ) + if(m_spHolder->m_nPageNo <= spRep->total) { - if ( nIdx < nBeginIdx ) - continue; + spRep->pageNo = m_spHolder->m_nPageNo > spRep->total ? + spRep->total.getValue( 0 ) : m_spHolder->m_nPageNo; - const auto &spAlm = *it; - auto spRepData = dto::CAlmRepData::createShared(); + const int nBeginIdx = ( spRep->pageNo - 1 ) * spRep->pageSize; + //< 使用std::min或者std::max的时候加上括号,避免与Windows.h中的min、max宏定义冲突 + const int nEndIdx = ( std::min )( nBeginIdx + spRep->pageSize, ( int ) m_pAlmTable->size()); + int nIdx = 0; + auto &indexOrder = m_pAlmTable->get(); + for ( auto it = indexOrder.cbegin(); it != indexOrder.cend() && nIdx < nEndIdx; ++it, ++nIdx ) + { + if ( nIdx < nBeginIdx ) + continue; - spRepData->content = spAlm->getContent(); + const auto &spAlm = *it; + auto spRepData = dto::CAlmRepData::createShared(); - spRepData->other = oatpp::Vector::createShared(); - const auto &spOther = spRepData->other; - spOther->emplace_back( oatpp::Int32( nIdx + 1 )); - //< todo 建议前端把告警窗和事件窗统一成一样的 - if ( 0 == m_spHolder->m_nEndPointType ) - {//< 告警窗 - //< 前端按序号访问other,需注意顺序不能乱,示例如下: - //< other: [136, "数字量变位", "状态变位", "未确认", 1643019095930, "EMS监控中心域", "EMS监控中心", "EMS监控", "高", "母线", "默认责任区"] - spOther->emplace_back( oatpp::String( spAlm->getAlmTypeDesc())); - spOther->emplace_back( oatpp::String( spAlm->getAlmStatusDesc())); - const char *szCfm = spAlm->isConfirmed() ? "已确认" : "未确认"; - spOther->emplace_back( oatpp::String( szCfm )); - spOther->emplace_back( oatpp::Int64( spAlm->getTimeStamp())); - spOther->emplace_back( oatpp::String( spAlm->getDomainDesc())); - spOther->emplace_back( oatpp::String( spAlm->getLocationDesc())); - spOther->emplace_back( oatpp::String( spAlm->getSubSystemDesc())); - spOther->emplace_back( oatpp::String( spAlm->getPriorityDesc())); - spOther->emplace_back( oatpp::String( spAlm->getDevTypeDesc())); - spOther->emplace_back( oatpp::String( spAlm->getRegionDesc())); - } - else - {//< 事件窗 - //< 前端按序号访问other,需注意顺序不能乱,示例如下: - //< other: [482, "母线", "状态变位", 1645008132566, "EMS监控中心域", "EMS监控中心", "EMS监控", "高", "数字量变位", "默认责任区"] - spOther->emplace_back( oatpp::String( spAlm->getDevTypeDesc())); - spOther->emplace_back( oatpp::String( spAlm->getAlmStatusDesc())); - spOther->emplace_back( oatpp::Int64( spAlm->getTimeStamp())); - spOther->emplace_back( oatpp::String( spAlm->getDomainDesc())); - spOther->emplace_back( oatpp::String( spAlm->getLocationDesc())); - spOther->emplace_back( oatpp::String( spAlm->getSubSystemDesc())); - spOther->emplace_back( oatpp::String( spAlm->getPriorityDesc())); - spOther->emplace_back( oatpp::String( spAlm->getAlmTypeDesc())); - spOther->emplace_back( oatpp::String( spAlm->getRegionDesc())); + spRepData->content = spAlm->getContent(); + spRepData->keyIdTag = oatpp::String( spAlm->getKeyIdTag()); + + spRepData->other = oatpp::Vector::createShared(); + const auto &spOther = spRepData->other; + spOther->emplace_back( oatpp::Int32( nIdx + 1 )); + //< todo 建议前端把告警窗和事件窗统一成一样的 + if ( 0 == m_spHolder->m_nEndPointType ) + {//< 告警窗 + //< 前端按序号访问other,需注意顺序不能乱,示例如下: + //< other: [136, "数字量变位", "状态变位", "未确认", 1643019095930, "EMS监控中心域", "EMS监控中心", "EMS监控", "高", "母线", "默认责任区","itOTHopke3PTjYn2lUHxkk","digital.station1.G02-YB_jgxh.TX.value",5,1] + spOther->emplace_back( oatpp::String( spAlm->getAlmTypeDesc())); + spOther->emplace_back( oatpp::String( spAlm->getAlmStatusDesc())); + const char *szCfm = spAlm->isConfirmed() ? "已确认" : "未确认"; + spOther->emplace_back( oatpp::String( szCfm )); + spOther->emplace_back( oatpp::Int64( spAlm->getTimeStamp())); + spOther->emplace_back( oatpp::String( spAlm->getDomainDesc())); + spOther->emplace_back( oatpp::String( spAlm->getLocationDesc())); + spOther->emplace_back( oatpp::String( spAlm->getSubSystemDesc())); + spOther->emplace_back( oatpp::String( spAlm->getPriorityDesc())); + spOther->emplace_back( oatpp::String( spAlm->getDevTypeDesc())); + spOther->emplace_back( oatpp::String( spAlm->getRegionDesc())); + spOther->emplace_back( oatpp::String( spAlm->getUuidBase64())); + spOther->emplace_back( oatpp::String( spAlm->getKeyIdTag())); + spOther->emplace_back( oatpp::Int64( spAlm->getAlmType())); + spOther->emplace_back( oatpp::Int64( spAlm->getAppId())); + } + else + {//< 事件窗 + //< 前端按序号访问other,需注意顺序不能乱,示例如下: + //< other: [482, "母线", "状态变位", 1645008132566, "EMS监控中心域", "EMS监控中心", "EMS监控", "高", "数字量变位", "默认责任区"] + spOther->emplace_back( oatpp::String( spAlm->getDevTypeDesc())); + spOther->emplace_back( oatpp::String( spAlm->getAlmStatusDesc())); + spOther->emplace_back( oatpp::Int64( spAlm->getTimeStamp())); + spOther->emplace_back( oatpp::String( spAlm->getDomainDesc())); + spOther->emplace_back( oatpp::String( spAlm->getLocationDesc())); + spOther->emplace_back( oatpp::String( spAlm->getSubSystemDesc())); + spOther->emplace_back( oatpp::String( spAlm->getPriorityDesc())); + spOther->emplace_back( oatpp::String( spAlm->getAlmTypeDesc())); + spOther->emplace_back( oatpp::String( spAlm->getRegionDesc())); + } + + spRep->data->emplace_back( std::move( spRepData )); } - spRep->data->emplace_back( std::move( spRepData )); } - } + } OATPP_COMPONENT( std::shared_ptr, spMapper ); return oatpp::async::synchronize( &m_spHolder->m_lockWrite, diff --git a/platform/src/service/web_server/module_alarm/AlmWsLsnr.hpp b/platform/src/service/web_server/module_alarm/AlmWsLsnr.hpp index 9cc64d06..795b0fb8 100644 --- a/platform/src/service/web_server/module_alarm/AlmWsLsnr.hpp +++ b/platform/src/service/web_server/module_alarm/AlmWsLsnr.hpp @@ -1,4 +1,4 @@ - + /********************************************************************************** * @file AlmWsLsnr.hpp * @brief 告警内容WebSocket的监听类 @@ -105,9 +105,8 @@ private: if ( 0 == m_nEndPointType ) {//< 告警窗 - if (!m_setDevGroup.empty() && spAlm->hasDevGroupTag() && m_setDevGroup.count( spAlm->getDevGroupTag()) <= 0 ) + if ( spAlm->hasDevGroupTag() && !m_setDevGroup.empty()&&m_setDevGroup.count( spAlm->getDevGroupTag()) <= 0 ) return 8; - } else {//< 事件窗 @@ -115,6 +114,9 @@ private: return 9; } + if ( !m_setKeyIdTag.empty() && m_setKeyIdTag.count( spAlm->getKeyIdTag()) <= 0 ) + return 10; + return 0; } @@ -128,6 +130,7 @@ private: int64_t m_nStartTime{-1}; //< 小于等于0表示不过滤 int64_t m_nEndTime{-1}; //< 小于等于0表示不过滤 std::unordered_set m_setDevGroup; + std::unordered_set m_setKeyIdTag; std::unordered_set m_setAlmType; std::unordered_set m_setLocationID; std::unordered_set m_setPriority; diff --git a/platform/src/service/web_server/module_alarm/DTOs.hpp b/platform/src/service/web_server/module_alarm/DTOs.hpp index ad1fa80b..4fc6772a 100644 --- a/platform/src/service/web_server/module_alarm/DTOs.hpp +++ b/platform/src/service/web_server/module_alarm/DTOs.hpp @@ -200,6 +200,7 @@ class CAlmReq : public oatpp::DTO DTO_FIELD( Any, endTime ); //todo 是否已确认 前端传过来的是"almStatus",不符合我们的命名,可以考虑让前端修改 DTO_FIELD( String, almStatus ); + DTO_FIELD( String, keyIdTag ); DTO_FIELD( String, type ); //< json里有,但没用,界面就没有按内容过滤的的功能 //DTO_FIELD( String, content ); @@ -222,7 +223,7 @@ class CAlmRepData : public oatpp::DTO DTO_FIELD( String, content ); //< 前端并没有使用 //DTO_FIELD( String, graphName ); - //DTO_FIELD( String, keyIdTag ); + DTO_FIELD( String, keyIdTag ); //DTO_FIELD( Vector < String > , soundFile ); //< 前端按序号访问other,需注意顺序不能乱 @@ -252,6 +253,107 @@ class CAlmRep : public oatpp::DTO DTO_FIELD( Vector < Object < CAlmRepData >>, data ); }; +///////////////////////////////////////////////////////////////// +/** + * @brief 用于获取区域告警数量统计 + */ + +class CAlmLevelRelation : public oatpp::DTO +{ + DTO_INIT( CAlmLevelRelation, DTO ); + DTO_FIELD( String, address_id ) = "name"; + DTO_FIELD( String, alarm_level ) = "level_name"; + DTO_FIELD( String, value ) = "value"; +}; + +class CAlmLevelDataUnit : public oatpp::DTO +{ + DTO_INIT( CAlmLevelDataUnit, DTO ); + DTO_FIELD( String, level_color ); + DTO_FIELD( String, level_name ); + DTO_FIELD( String, alarm_level ); + DTO_FIELD( String, code ); + DTO_FIELD( Boolean, hasChildren ); + DTO_FIELD( String, address_id ); + DTO_FIELD( String, name ); + DTO_FIELD( Int32, value ); +}; + +class CAlmLevelData : public oatpp::DTO +{ + DTO_INIT( CAlmLevelData, DTO ); + DTO_FIELD( String, databaseType ); + DTO_FIELD( String, tableName ) = "getAlarmLevelCount"; + DTO_FIELD( Object, relationship ); + DTO_FIELD( List>, data ); +}; + +class CAlmLevelResp : public oatpp::DTO +{ + DTO_INIT( CAlmLevelResp, DTO ); + DTO_FIELD( Int32, code ); + DTO_FIELD( String, message ); + DTO_FIELD( Object, data ); +}; + +///////////////////////////////////////////////////////////////// +// 告警信息获取接口,目前用于app,部分无用字段为了性能暂时注释 +class CAlmData : public oatpp::DTO +{ + DTO_INIT( CAlmData, DTO ); + DTO_FIELD( Int32, alm_type ); + DTO_FIELD( Int32, alm_status ); + DTO_FIELD( String, alm_status_desc ); + DTO_FIELD( Int32, alm_logic_status ); + DTO_FIELD( String, timestamp ); +// DTO_FIELD( Int32, domain_id ); +// DTO_FIELD( String, domain_desc ); +// DTO_FIELD( Int32, location_id ); +// DTO_FIELD( Int32, app_id ); + DTO_FIELD( Int32, priority ); + DTO_FIELD( String, priority_desc ); + DTO_FIELD( Int32, priority_order ); +// DTO_FIELD( Boolean, is_water_alm ); + DTO_FIELD( String, uuid_base64 ); + DTO_FIELD( String, content ); +// DTO_FIELD( Int32, sub_system ); +// DTO_FIELD( String, sub_system_desc ); +// DTO_FIELD( Int32, dev_type ); +// DTO_FIELD( String, dev_type_desc ); +// DTO_FIELD( Int32, region_id ); +// DTO_FIELD( Boolean, has_region_id ); +// DTO_FIELD( String, region_desc ); + DTO_FIELD( String, dev_group_tag ); + DTO_FIELD( Boolean, has_dev_group_tag ); + DTO_FIELD( String, key_id_tag ); +// DTO_FIELD( String, graph_name ); +// DTO_FIELD( Boolean, is_visible ); +}; + +class CGetAllAlmResp : public oatpp::DTO +{ + DTO_INIT( CGetAllAlmResp, DTO ); + DTO_FIELD( Int32, code ); + DTO_FIELD( String, message ); + DTO_FIELD( Int32, version_no ); + DTO_FIELD( Int32, size ); + DTO_FIELD( List>, data ); +}; + +class CGetChgLogAfterResp : public oatpp::DTO +{ + DTO_INIT( CGetChgLogAfterResp, DTO ); + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( Int32, version_no ) = 0; + DTO_FIELD( String, message ); + DTO_FIELD( List>, chg_alm_add ); + DTO_FIELD( List>, chg_alm_update ); + DTO_FIELD( List, chg_alm_del ); + +}; + +///////////////////////////////////////////////////////////////// + } //namespace dto } //namespace module_alarm } //namespace web_server diff --git a/platform/src/service/web_server/module_alarm/DataStruct.hpp b/platform/src/service/web_server/module_alarm/DataStruct.hpp index 735fe2ec..cd67ef34 100644 --- a/platform/src/service/web_server/module_alarm/DataStruct.hpp +++ b/platform/src/service/web_server/module_alarm/DataStruct.hpp @@ -179,7 +179,7 @@ public: //< 是否流水账告警 inline bool isWaterAlm() const { - return m_spAlmInfo->if_water_alm(); + return (m_spAlmInfo->if_water_alm() != 0); } //< 本条告警信息的唯一标识,使用base64编码缩短后的uuid diff --git a/platform/src/service/web_server/module_alarm/SimpleCtrl.cpp b/platform/src/service/web_server/module_alarm/SimpleCtrl.cpp index aa25788b..4311a987 100644 --- a/platform/src/service/web_server/module_alarm/SimpleCtrl.cpp +++ b/platform/src/service/web_server/module_alarm/SimpleCtrl.cpp @@ -14,11 +14,14 @@ #include "pub_logger_api/logger.h" #include "pub_utility_api/TimeUtil.h" +#include "pub_utility_api/I18N.h" #include "db_api_ex/CDbApi.h" #include "rdb_api/CRdbAccess.h" //#include "alarm_server_api/AlarmCommonDef.h" #include "../include/SessionApi.h" +#include "../module_alarm/DataMngThread.hpp" + #include "DTOs.hpp" #include "SimpleCtrl.hpp" @@ -265,9 +268,9 @@ std::shared_ptr CSimpleCtrl::que nStartTimeMsec = nTemp; } - if ( content != "" || regionId != "" ) + if ( regionId != "" ) { - const char *szMsg = "请求错误:按内容或者按区域搜索未启用"; + const char *szMsg = "请求错误:按区域搜索未启用"; LOGERROR( "%s", szMsg ); return createResponse( Status::CODE_400, szMsg ); } @@ -406,6 +409,13 @@ std::shared_ptr CSimpleCtrl::que addCondtion( vecDevType, "dev_type" ); addCondtion( vecType, "alm_type" ); + if( content != "" ) + { + strCondition += QString(" content like '%%1%'").arg(urldecode(*content).c_str()); + strCondition += " and "; + + } + if ( strCondition != "" ) { strCondition = " and " + strCondition; @@ -431,7 +441,7 @@ std::shared_ptr CSimpleCtrl::que LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); return createResponse( Status::CODE_500, "数据库查询错误" ); } - LOGDEBUG( "SQL语句如下:\n%s", strSql.toUtf8().constData()); + //LOGDEBUG( "SQL语句如下:\n%s", strSql.toUtf8().constData()); auto spResp = dto::EventMsDto::createShared(); @@ -937,6 +947,428 @@ CSimpleCtrl::queryEventConditionMs( /*const oatpp::Int32 &type, const oatpp::Int return createDtoResponse( Status::CODE_200, spDto ); } +//////////////////////////////////////////////////////////////////////// + +std::shared_ptr +CSimpleCtrl::getAlarmLevelCount(const std::shared_ptr &request) +{ + auto spResp = dto::CAlmLevelResp::createShared(); + spResp->data = dto::CAlmLevelData::createShared(); + spResp->data->relationship = dto::CAlmLevelRelation::createShared(); + spResp->data->data = {}; + spResp->data->databaseType = std::string(I18N( "接口" )); + + // 列出所有参数,不一定用的到,暂时注释不实现 + QString strAreaCode,strDimensions; + //,strAlarmLevel,strOrderBy,strLimit; + int nShowSubSet; + //nTop; + + // 检查参数 + bool bParaOk = true; + QString strTmp = request->getQueryParameter( "showSubSet" ).getValue( "" ).c_str(); + nShowSubSet = strTmp.toInt(&bParaOk); + if ( !bParaOk ) + { + const std::string strMsg = I18N( "无效的请求参数" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + strAreaCode = request->getQueryParameter( "areaCode" ).getValue( "" ).c_str(); + strDimensions = request->getQueryParameter( "dimensions" ).getValue( "" ).c_str(); + QStringList listAreaCode = strAreaCode.split(":",QString::SkipEmptyParts); + // 检查areadCode + if( listAreaCode.size() != 2 || listAreaCode.at(0) != "location") + { + const std::string strMsg = I18N( "无效的请求参数,不支持location以外的areaCode" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + // 打开数据库 + CDbApi objDb(DB_CONN_MODEL_READ); + if ( !objDb.open() ) + { + const std::string strMsg = I18N( "获取模型可读关系库失败" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + // 验证location存在 + if( listAreaCode.at(0) == "location") + { + // 查找location是否存在 + QSqlQuery objQuery; + QString sSql = QString("select tag_name from sys_model_location_info where location_id='%1'").arg(listAreaCode.at(1)); + if ( !objDb.execute(sSql,objQuery) ) + { + const std::string strMsg = I18N( "查询关系库表 sys_model_location_info 失败" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + if( !objQuery.next() ) + { + const std::string strMsg = I18N( "location不存在" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + } + + // 获取所有的设备组 + QMap subset; + if( listAreaCode.at(0) == "location" ) + { + QSqlQuery objQuery; + QString sSql = QString("select tag_name,description from dev_group where location_id='%1'").arg(listAreaCode.at(1)); + if ( !objDb.execute(sSql,objQuery) ) + { + const std::string strMsg = I18N( "查询关系库表 dev_group 失败" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + while( objQuery.next() ) + { + subset[objQuery.value(0).toString()] = objQuery.value(1).toString(); + } + } + + //< 查询告警颜色配置 + QMap mapCfgColor; + QMap mapCfgDesc; + { + QSqlQuery objQuery; + //< SQL中写明列名,代码中无需再判断列是否存在 + QString sSql = "SELECT id,color FROM alarm_color ORDER BY id"; + if ( objDb.execute( sSql, objQuery )) + { + bool bOk = true; + while ( objQuery.next()) + { + const int nId = objQuery.value( 0 ).toInt( &bOk ); + if ( !bOk ) + { + continue; + } + mapCfgColor[nId] = objQuery.value( 1 ).toString(); + } + } + objQuery.clear(); + + //< SQL中写明列名,代码中无需再判断列是否存在 + sSql = "SELECT priority_id,priority_name FROM alarm_level_define ORDER BY priority_id"; + if ( !objDb.execute( sSql, objQuery )) + { + const std::string strMsg = I18N( "查询关系库表 alarm_level_define 失败" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + while ( objQuery.next() ) + { + + const int nId = objQuery.value( 0 ).toInt(); + + QString desc = objQuery.value( 1 ).toString(); + + QString color; + auto it = mapCfgColor.find( nId ); + if ( it == mapCfgColor.end()) + { + //< 没找到 + if ( nId >= ( int ) g_vecDefaultAlmColor.size()) + color = *g_vecDefaultAlmColor.rbegin()->c_str(); + else if ( nId < 0 ) + color = *g_vecDefaultAlmColor.begin()->c_str(); + else + color = g_vecDefaultAlmColor[nId].c_str(); + } + else + { + color = *it; + } + + mapCfgDesc[nId] = desc; + mapCfgColor[nId] = color; + } + } + + + QStringList listDimensions = strDimensions.split(",",QString::SkipEmptyParts); + if( listDimensions.size() != 2 ) + { + const std::string strMsg = I18N( "无效的请求参数,dimensions不支持一个参数" ); + LOGERROR( "getAlarmLevelCount():%s", strMsg.c_str()); + spResp->code = 400; + spResp->message = strMsg; + return createDtoResponse( Status::CODE_200, spResp ); + } + + QMap mapAlmSize; + for(const auto &almLevelId_keys : mapCfgColor.keys()) + { + for(const auto &itSub : subset.keys() ) + { + QString key = QString("%1_%2").arg( QString::number( almLevelId_keys ) ) + .arg( itSub ); + mapAlmSize[key] = 0; + } + } + + int nVer = 0; + std::vector vecAlm; + CDataMngThread::getInstance()->getAllAlm(nVer,vecAlm); + for ( const auto &it : vecAlm ) + { + if(!it->hasDevGroupTag()) + { + continue; + } + + if(!it->isVisible()) + { + continue; + } + + QString key = QString("%1_%2").arg( QString::number( it->getPriority() ) ) + .arg( it->getDevGroupTag().c_str() ); + + if(mapAlmSize.find(key) != mapAlmSize.end()) + { + mapAlmSize[key] += 1; + } + } + + + for(const auto &almLevelId_keys : mapCfgColor.keys()) + { + for(const auto &itSub : subset.keys() ) + { + QString key = QString("%1_%2").arg( QString::number( almLevelId_keys ) ) + .arg( itSub ); + + auto oneUnit = dto::CAlmLevelDataUnit::createShared(); + oneUnit->level_color = mapCfgColor[almLevelId_keys].toStdString(); + oneUnit->level_name = mapCfgDesc[almLevelId_keys].toStdString(); + oneUnit->alarm_level = QString::number(almLevelId_keys).toStdString(); + oneUnit->code = itSub.toStdString(); + oneUnit->hasChildren = false; + oneUnit->address_id = QString("dev_group:%1").arg(itSub).toStdString(); + oneUnit->name = subset[itSub].toStdString(); + oneUnit->value = mapAlmSize[key]; + + spResp->data->data->push_back( oneUnit ); + } + } + + spResp->code = 200; + const std::string cn_strSuccess = I18N( "成功" ); + spResp->message = cn_strSuccess; + return createDtoResponse( Status::CODE_200, spResp ); +} + +void fillOneAlm(dto::CAlmData::Wrapper& oneAlmResp, const CLiveAlmSp & almSp) +{ + oneAlmResp->alm_type = almSp->getAlmType(); + oneAlmResp->alm_status = almSp->getAlmStatus(); + oneAlmResp->alm_status_desc = almSp->getAlmStatusDesc(); + oneAlmResp->alm_logic_status = (int)almSp->getLogicState(); + oneAlmResp->timestamp = QString::number(almSp->getTimeStamp()).toStdString(); +// spOne->domain_id = almSp->getDomainId(); +// spOne->domain_desc = almSp->getDomainDesc(); +// spOne->location_id = almSp->getLocationId(); +// spOne->app_id = almSp->getAppId(); + oneAlmResp->priority = almSp->getPriority(); + oneAlmResp->priority_desc = almSp->getPriorityDesc(); + oneAlmResp->priority_order = almSp->getPriorityOrder(); +// spOne->is_water_alm = almSp->isWaterAlm(); + oneAlmResp->uuid_base64 = almSp->getUuidBase64(); + oneAlmResp->content = almSp->getContent(); +// spOne->sub_system = it->getSubSystem(); +// spOne->sub_system_desc = it->getSubSystemDesc(); + +// spOne->dev_type = it->getDevType(); +// spOne->dev_type_desc = it->getDevTypeDesc(); + +// spOne->has_region_id = it->hasRegionId(); +// if(it->hasRegionId()) +// { +// spOne->region_id = it->getRegionId(); +// spOne->region_desc = it->getRegionDesc(); + +// } +// else +// { +// spOne->region_id = -1; +// spOne->region_desc = ""; +// } + + oneAlmResp->has_dev_group_tag = almSp->hasDevGroupTag(); + if(almSp->hasDevGroupTag()) + { + oneAlmResp->dev_group_tag = almSp->getDevGroupTag(); + + } + else + { + oneAlmResp->dev_group_tag = ""; + } + + oneAlmResp->key_id_tag = almSp->getKeyIdTag(); +// oneAlmResp->graph_name = almSp->getGraphName(); +} +std::shared_ptr +CSimpleCtrl::getAllAlm() +{ + auto spResp = dto::CGetAllAlmResp::createShared(); + spResp->data = {}; + const std::string cn_strSuccess = I18N( "成功" ); + spResp->message = cn_strSuccess; + + + int nVer = 0; + std::vector vecAlm; + CDataMngThread::getInstance()->getAllAlm(nVer,vecAlm); + spResp->version_no = nVer; + + for ( auto &spAlm : vecAlm ) + { + if ( !spAlm->isVisible() ) + continue; + + auto spOne = dto::CAlmData::createShared(); + fillOneAlm(spOne,spAlm); + + spResp->data->push_back( spOne ); + + } + spResp->size = static_cast(spResp->data->size()); + spResp->code = 200; + + return createDtoResponse(Status::CODE_200, spResp); +} + + +std::shared_ptr +CSimpleCtrl::getChgLogAfter(const oatpp::Int32 & version_no) +{ + auto spResp = dto::CGetChgLogAfterResp::createShared(); + const std::string cn_strSuccess = I18N( "成功" ); + spResp->message = cn_strSuccess; + spResp->chg_alm_add = {}; + spResp->chg_alm_update = {}; + spResp->chg_alm_del = {}; + + + std::vector vecSpChgLog; + if ( !CDataMngThread::getInstance()->getChgLogAfter( version_no, vecSpChgLog )) + { + const std::string cn_strFailed = I18N( "失败" ); + spResp->message = cn_strFailed; + spResp->code = 201; + spResp->version_no = version_no; + return createDtoResponse(Status::CODE_200, spResp); + } + + if(vecSpChgLog.empty()) + { + spResp->version_no = version_no; + return createDtoResponse(Status::CODE_200, spResp); + } + + spResp->version_no = ( *vecSpChgLog.rbegin())->getVerNo(); + + + for ( auto &spChgLog:vecSpChgLog ) + { + switch ( spChgLog->getChgType()) + { + case CAlmChgLog::EN_CT_NULL: + break; + case CAlmChgLog::EN_CT_ADD: + { + const auto &vecRefAlm = spChgLog->getRefAlm(); + for ( auto &wpAlm:vecRefAlm ) + { + CLiveAlmSp spAlm = wpAlm.lock(); + if ( !spAlm ) + continue; + + if ( !spAlm->isVisible()) + continue; + + auto spOne = dto::CAlmData::createShared(); + fillOneAlm(spOne,spAlm); + spResp->chg_alm_add->push_back( spOne ); + } + } + break; + case CAlmChgLog::EN_CT_UPDATE: + { + const auto &vecRefAlm = spChgLog->getRefAlm(); + for ( auto &wpAlm:vecRefAlm ) + { + CLiveAlmSp spAlm = wpAlm.lock(); + if ( !spAlm ) + continue; + + if ( !spAlm->isVisible()) + continue; + + auto spOne = dto::CAlmData::createShared(); + fillOneAlm(spOne,spAlm); + spResp->chg_alm_update->push_back( spOne ); + } + } + break; + case CAlmChgLog::EN_CT_DEL: + { + const auto &vecRefAlm = spChgLog->getRefAlm(); + for ( auto &wpAlm:vecRefAlm ) + { + CLiveAlmSp spAlm = wpAlm.lock(); + if ( !spAlm ) + continue; + + spResp->chg_alm_del->push_back(spAlm->getUuidBase64()); + } + } + break; + default: + break; + } + } + + spResp->code = 200; + + return createDtoResponse(Status::CODE_200, spResp); +} + + +// 获得设备告警数量 TODO 待实现 +//std::shared_ptr +//CSimpleCtrl::getDeviceAlarmById(const std::shared_ptr &request) +//{ +// return createResponse(Status::CODE_200, "ok"); +//} + + } //namespace module_alarm } //namespace web_server diff --git a/platform/src/service/web_server/module_alarm/SimpleCtrl.hpp b/platform/src/service/web_server/module_alarm/SimpleCtrl.hpp index d080597b..331bec9e 100644 --- a/platform/src/service/web_server/module_alarm/SimpleCtrl.hpp +++ b/platform/src/service/web_server/module_alarm/SimpleCtrl.hpp @@ -46,6 +46,28 @@ public: ENDPOINT( "GET", "queryEventConditionMs", queryEventConditionMs, /*QUERY( Int32 , type ), QUERY( Int32, id ),*/REQUEST( std::shared_ptr, spRequest )); + + /** + * @brief 告警级别告警时间统计 + */ + ENDPOINT( "GET", "/api-query/databind/getAlarmLevelCount", getAlarmLevelCount, + REQUEST( std::shared_ptr, spRequest )); + + /** + * @brief 获得全部告警 + */ + ENDPOINT( "GET", "getAllAlm", getAllAlm); + /** + * @brief 获得版本vetsion_no之后的告警 + */ + ENDPOINT( "GET", "getChgLogAfter", getChgLogAfter, QUERY( Int32, version_no )); + + + /** + * @brief 机柜告警统计 + */ + // ENDPOINT( "GET", "/api-query/databind/getDeviceAlarmById", getDeviceAlarmById , + // REQUEST( std::shared_ptr, spRequest )); }; } //namespace module_alarm diff --git a/platform/src/service/web_server/module_app/CtrlApp.cpp b/platform/src/service/web_server/module_app/CtrlApp.cpp new file mode 100644 index 00000000..a5cb2979 --- /dev/null +++ b/platform/src/service/web_server/module_app/CtrlApp.cpp @@ -0,0 +1,1946 @@ + +#include "CtrlApp.h" +#include "../include/ServerApi.h" +#include "../include/SessionApi.h" + +#include +#include "db_api_ex/CDbApi.h" +#include + + +#include "../module_alarm/DataMngThread.hpp" +#include "AlarmMessage.pb.h" + +#include "dbms/db_his_query_api/DbHisQueryApi.h" +#include "tsdb_api/TsdbApi.h" +#include "pub_sysinfo_api/SysInfoApi.h" + +using namespace iot_dbms; +namespace web_server +{ +namespace module_app +{ + + + +bool CtrlApp::init() +{ + m_ptrRdbTableMng = boost::make_shared( + getServerApi()->getRunAppInfo().strAppName.c_str()); //RDB管理实例 + if ( m_ptrRdbTableMng == NULL ) + { + LOGERROR( " make_shared fail!\n" ); + return false; + } + return true; +} + +static inline unsigned char from_hex( unsigned char ch ) +{ + if ( ch <= '9' && ch >= '0' ) + ch -= '0'; + else if ( ch <= 'f' && ch >= 'a' ) + ch -= 'a' - 10; + else if ( ch <= 'F' && ch >= 'A' ) + ch -= 'A' - 10; + else + ch = 0; + return ch; +} + +static inline std::string urldecode( const std::string &str ) +{ + using namespace std; + string result; + string::size_type i; + for ( i = 0; i < str.size(); ++i ) + { + if ( str[i] == '+' ) + { + result += ' '; + } + else if ( str[i] == '%' && str.size() > i + 2 ) + { + const unsigned char ch1 = from_hex( str[i + 1] ); + const unsigned char ch2 = from_hex( str[i + 2] ); + const unsigned char ch = ( ch1 << 4 ) | ch2; + result += ch; + i += 2; + } + else + { + result += str[i]; + } + } + return result; +} + +std::shared_ptr CtrlApp::getAllDeviceTempCode() +{ + auto resp = allDeviceTempDTO::createShared(); + resp->message = "查询成功!"; + resp->data = {}; + + + // 先查询数量,再返回结果 + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + resp->message = szMsg; + return createDtoResponse( Status::CODE_201, resp ); + } + + QString strSql = "select TAG_NAME,DESCRIPTION from dev_temp_def;"; + QSqlQuery objQuery; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "getAllTxCodeByDevGrp(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + resp->message = szMsg; + return createDtoResponse( Status::CODE_201, resp ); + } + + while ( objQuery.next()) + { + auto unit = deviceTempUnitDTO::createShared(); + unit->tag_name = objQuery.value( 0 ).toString().toStdString(); + unit->desc = objQuery.value( 1 ).toString().toStdString(); + + resp->data->insert(resp->data->end(),unit); + } + + return createDtoResponse( Status::CODE_200, resp ); +} + + +std::shared_ptr CtrlApp::getAllTxCodeByDevGrp( + const oatpp::String & name , + const oatpp::Int32 & pageNo, + const oatpp::Int32 & pageSize + ) +{ + + auto txCodedto = txCodeDTO::createShared(); + txCodedto->message = "查询成功!"; + txCodedto->data = txCodeDataDTO::createShared(); + txCodedto->data->dataMap = {}; + // 暂时不作参数检查 + + // 先查询数量,再返回结果 + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + txCodedto->message = szMsg; + return createDtoResponse( Status::CODE_201, txCodedto ); + } + + QString countSelect = "select " + " count(*) " + " "; + + QString sqlCond = " FROM digital AS t1 LEFT JOIN dev_info AS t2 ON t1.DEVICE = t2.TAG_NAME LEFT JOIN dev_group AS t3 ON t2.GROUP_TAG_NAME = t3.TAG_NAME LEFT JOIN sys_model_location_info as t4 on t3.LOCATION_ID = t4.LOCATION_ID LEFT JOIN sys_model_sub_system_info as t5 on t1.SUB_SYSTEM = t5.SUB_SYSTEM_ID WHERE t1.tag_name LIKE '%.TX'"; + if( name->compare("") != 0) + { + sqlCond += QString(" and t3.DESCRIPTION like '%%%1%%'").arg( urldecode(*name).c_str() ); + } + QString resultSelect = "select t3.TAG_NAME, t3.DESCRIPTION, t1.TAG_NAME AS txcode , t4.TAG_NAME as LOCATION_TAG, t5.TAG_NAME as SUB_SYSTEM_TAG "; + + QSqlQuery objQuery; + + QString strSql = countSelect + sqlCond; + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + txCodedto->message = szMsg; + return createDtoResponse( Status::CODE_201, txCodedto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, txCodedto ); + } + txCodedto->data->records = totalCnt; + txCodedto->data->total = totalCnt / pageSize + 1; + txCodedto->data->pageSize = pageSize; + txCodedto->data->pageNo = pageNo; + + + strSql = resultSelect + sqlCond + QString(" limit %1 offset %2").arg(QString::number(pageSize)).arg(QString::number( pageSize *(pageNo - 1 ))); + //LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + + //再得到结果 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + txCodedto->message = szMsg; + return createDtoResponse( Status::CODE_201, txCodedto ); + } + while ( objQuery.next()) + { + auto txCodeUnit = txCodeUnitDTO::createShared(); + txCodeUnit->code = objQuery.value( 0 ).toString().toStdString(); + txCodeUnit->name = objQuery.value( 1 ).toString().toStdString(); + txCodeUnit->TxCode = QString("%1.%2.digital.%3.value") + .arg(objQuery.value( 3 ).toString()) + .arg(objQuery.value( 4 ).toString()) + .arg(objQuery.value( 2 ).toString()).toStdString() + ; + txCodedto->data->dataMap->insert(txCodedto->data->dataMap->end(),txCodeUnit); + } + + + return createDtoResponse( Status::CODE_200, txCodedto ); +} + +std::shared_ptr +CtrlApp::getAllDeviceByGroupCode( + const oatpp::String & groupCode, + const oatpp::Int32 & pageNo, + const oatpp::Int32 & pageSize) +{ + auto deviceRsp = deviceCodeDTO::createShared(); + deviceRsp->message = "查询成功!"; + deviceRsp->data= deviceCodeDataDTO::createShared(); + deviceRsp->data->dataMap = {}; + + + // 检查参数 + if( groupCode == "" ) + { + const char *szMsg = "参数有误"; + LOGERROR( "%s", szMsg ); + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + + QString selectCount = "SELECT count(*)"; + QString selectResult = "SELECT treeCode,code,unitName,sname,unitCode,name,keyValue,diNum,type"; + QString sqlCond = QString( + " FROM\ + (\ + SELECT\ + \"\" AS treeCode,\ + TAG_NAME AS CODE,\ + \"\" AS unitName,\ + \"\" AS sname,\ + \"\" AS unitCode,\ + DESCRIPTION AS NAME,\ + \"\" AS keyValue,\ + \"\" AS diNum,\ + 1 AS type \ + FROM\ + dev_group \ + WHERE\ + dev_group.TAG_NAME = \'%1\' UNION\ + SELECT\ + t1.GROUP_TAG_NAME AS treeCode,\ + t1.TAG_NAME AS CODE,\ + \"\" AS unitName,\ + \"\" AS sname,\ + \"\" AS unitCode,\ + concat( t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) as NAME,\ + \"\" AS keyValue,\ + \"\" AS diNum,\ + 2 AS type \ + FROM\ + dev_info as t1\ + left join dev_group as t2 on t1.GROUP_TAG_NAME = t2.TAG_NAME\ + WHERE\ + t1.GROUP_TAG_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treeCode,\ + t1.TAG_NAME AS CODE,\ + \"\" AS unitName,\ + concat( t4.TAG_NAME, \'.\', t5.TAG_NAME, \'.digital.\', t1.TAG_NAME, \'.value\' ) AS sname,\ + \"\" AS unitCode,\ + concat( t3.DESCRIPTION,\',\',t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) as NAME,\ + t6.KEY_VALUE AS keyValue,\ + t1.VALUE_NUM AS diNum,\ + \"yx\" AS type \ + FROM\ + digital AS t1\ + LEFT JOIN dev_info AS t2 ON t1.DEVICE = t2.TAG_NAME\ + LEFT JOIN dev_group AS t3 ON t2.GROUP_TAG_NAME = t3.TAG_NAME\ + LEFT JOIN sys_model_location_info AS t4 ON t3.LOCATION_ID = t4.LOCATION_ID\ + LEFT JOIN sys_model_sub_system_info AS t5 ON t1.SUB_SYSTEM = t5.SUB_SYSTEM_ID\ + LEFT JOIN digital_temp_define AS t6 ON t1.POINT_TP_NAME = t6.TAG_NAME \ + WHERE\ + t2.GROUP_TAG_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treeCode,\ + t1.TAG_NAME AS CODE,\ + t7.UNIT_NAME AS unitName,\ + concat( t4.TAG_NAME, \'.\', t5.TAG_NAME, \'.analog.\', t1.TAG_NAME, \'.value\' ) AS sname,\ + t7.UNIT_DESC AS unitCode,\ + concat( t3.DESCRIPTION,\',\',t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) as NAME,\ + t6.KEY_VALUE AS keyValue,\ + \"\" AS diNum,\ + \"yc\" AS type \ + FROM\ + analog AS t1\ + LEFT JOIN dev_info AS t2 ON t1.DEVICE = t2.TAG_NAME\ + LEFT JOIN dev_group AS t3 ON t2.GROUP_TAG_NAME = t3.TAG_NAME\ + LEFT JOIN sys_model_location_info AS t4 ON t3.LOCATION_ID = t4.LOCATION_ID\ + LEFT JOIN sys_model_sub_system_info AS t5 ON t1.SUB_SYSTEM = t5.SUB_SYSTEM_ID\ + LEFT JOIN analog_temp_define AS t6 ON t1.POINT_TP_NAME = t6.TAG_NAME\ + LEFT JOIN dict_unit_info AS t7 ON t1.UNIT_ID = t7.UNIT_ID \ + WHERE\ + t2.GROUP_TAG_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treeCode,\ + t1.TAG_NAME AS CODE,\ + t7.UNIT_NAME AS unitName,\ + concat( t4.TAG_NAME, \'.\', t5.TAG_NAME, \'.accuml.\', t1.TAG_NAME, \'.value\' ) AS sname,\ + t7.UNIT_DESC AS unitCode,\ + concat( t3.DESCRIPTION,\',\',t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) as NAME,\ + t6.KEY_VALUE AS keyValue,\ + \"\" AS diNum,\ + \"ym\" AS type \ + FROM\ + accuml AS t1\ + LEFT JOIN dev_info AS t2 ON t1.DEVICE = t2.TAG_NAME\ + LEFT JOIN dev_group AS t3 ON t2.GROUP_TAG_NAME = t3.TAG_NAME\ + LEFT JOIN sys_model_location_info AS t4 ON t3.LOCATION_ID = t4.LOCATION_ID\ + LEFT JOIN sys_model_sub_system_info AS t5 ON t1.SUB_SYSTEM = t5.SUB_SYSTEM_ID\ + LEFT JOIN accuml_temp_define AS t6 ON t1.POINT_TP_NAME = t6.TAG_NAME\ + LEFT JOIN dict_unit_info AS t7 ON t1.UNIT_ID = t7.UNIT_ID \ + WHERE\ + t2.GROUP_TAG_NAME = \'%1\' \ + ) AS u1").arg(groupCode->c_str()); + + QString strSql = selectCount + sqlCond; + QSqlQuery objQuery; + + + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "getAllDeviceByGroupCode(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + //LOGERROR( "getAllDeviceByGroupCode(): 查询,SQL语句如下:\n%s", strSql.toUtf8().constData()); + + + // 得到统计数据 + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + const char *szMsg = "未查询到记录,数据库"; + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + deviceRsp->data->records = totalCnt; + deviceRsp->data->total = totalCnt / pageSize + 1; + deviceRsp->data->pageSize = pageSize; + deviceRsp->data->pageNo = pageNo; + + strSql = selectResult + sqlCond + QString(" limit %1 offset %2").arg(QString::number(pageSize)).arg(QString::number( pageSize *(pageNo - 1 ))); + + + // 得到结果 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + while ( objQuery.next()) + { + // treeCode,code,unitName,sname,unitCode,name,keyValue,diNum,type + auto deviceCodeUnit = deviceCodeUnitDTO::createShared(); + + deviceCodeUnit->treePcode = objQuery.value( 0 ).toString().toStdString(); + deviceCodeUnit->code = objQuery.value( 1 ).toString().toStdString(); + deviceCodeUnit->unitName = objQuery.value( 2 ).toString().toStdString(); + deviceCodeUnit->sname = objQuery.value( 3 ).toString().toStdString(); + deviceCodeUnit->unitCode = objQuery.value( 4 ).toString().toStdString(); + deviceCodeUnit->name = objQuery.value( 5 ).toString().toStdString(); + deviceCodeUnit->keyValue = objQuery.value( 6 ).toString().toStdString(); + deviceCodeUnit->diNum = objQuery.value( 7 ).toString().toStdString(); + deviceCodeUnit->type = objQuery.value( 8 ).toString().toStdString(); + + deviceRsp->data->dataMap->insert(deviceRsp->data->dataMap->end(),deviceCodeUnit); + } + + return createDtoResponse( Status::CODE_200, deviceRsp ); +} + +bool CtrlApp::getRealTimeValStatus(const QStringList & listKeyIdTag,oatpp::Object & rtData,const std::string &tableName) +{ + // station1.PSCADA.analog.station1.state_income.daily_income.value + // 取得location和sub_system + // 取得表名 + // 从内存库获取值,并赋值 + + iot_dbms::CRdbNetApi netRdbApi; + netRdbApi.connect( getServerApi()->getRunAppInfo().nDomainId, 4 ); // 连接电力监控 + + iot_idl::RdbRet objRet; + std::vector vecKey, vecColumn; + for ( const QString& keyIdTag : listKeyIdTag ) + { + QStringList pieces = keyIdTag.split("."); + pieces.removeFirst(); + pieces.removeFirst(); + pieces.removeFirst(); + pieces.removeLast(); + + vecKey.push_back( pieces.join(".").toStdString() ); + } + + vecColumn.push_back( "status" ); + vecColumn.push_back( "value" ); + + bool ret = netRdbApi.queryByKey( tableName.c_str(), vecKey, vecColumn, objRet ); + if ( !ret ) + { + LOGERROR( "fail to query rdb! tableName:%s",tableName.c_str() ); + return false; + } + + if( objRet.msgrecord_size() != vecKey.size() ) + { + LOGERROR( "wrong size of result" ); + return false; + } + + for(int idx = 0; idx < objRet.msgrecord_size(); idx ++ ) + { + auto unit = rtDataUnitDTO::createShared(); + unit->key_id_tag = listKeyIdTag[idx].toStdString(); + unit->value = objRet.msgrecord( idx ).msgvaluearray( 0 ).dvalue(); + unit->status = objRet.msgrecord( idx ).msgvaluearray( 0 ).nvalue(); + rtData->data->insert(rtData->data->end(),unit); + } + return true; +} + +std::shared_ptr CtrlApp::getRealDataByCode( const oatpp::String &strReq ) +{ + auto rtDataResp = rtDataDTO::createShared(); + rtDataResp->message = "查询成功!"; + rtDataResp->time = QString::number(QDateTime::currentMSecsSinceEpoch()).toStdString(); + rtDataResp->data={}; + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "getRealDataByCode(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + + QStringList listKeyIdTag = QString(spReq->code->c_str()).split(";"); + + + QStringList listMixKeyIdTag; + QStringList listAccKeyIdTag; + QStringList listDigKeyIdTag; + QStringList listAnaKeyIdTag; + + for ( const QString& keyIdTag : listKeyIdTag ) + { + if(keyIdTag == "") + { + continue; + } + QString table = keyIdTag.split(".")[2]; + if(table == "accuml") + { + listAccKeyIdTag.append(keyIdTag); + } + else if(table == "digital") + { + listDigKeyIdTag.append(keyIdTag); + } + else if(table == "mix") + { + listMixKeyIdTag.append(keyIdTag); + } + else if(table == "analog") + { + listAnaKeyIdTag.append(keyIdTag); + } + else + { + const char *szMsg = "参数有误"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + } + + if(!listMixKeyIdTag.empty()) + { + if( !getRealTimeValStatus( listMixKeyIdTag, rtDataResp,"mix" ) ) + { + const char *szMsg = "参数有误"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + } + + if(!listAccKeyIdTag.empty()) + { + if( !getRealTimeValStatus( listAccKeyIdTag, rtDataResp,"accuml" ) ) + { + const char *szMsg = "参数有误"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + } + + if(!listDigKeyIdTag.empty()) + { + if( !getRealTimeValStatus( listDigKeyIdTag, rtDataResp,"digital" ) ) + { + const char *szMsg = "参数有误"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + } + + if(!listAnaKeyIdTag.empty()) + { + if( !getRealTimeValStatus( listAnaKeyIdTag, rtDataResp,"analog" ) ) + { + const char *szMsg = "参数有误"; + rtDataResp->message = szMsg; + return createDtoResponse( Status::CODE_201, rtDataResp ); + } + } + + return createDtoResponse( Status::CODE_200, rtDataResp); +} + +std::shared_ptr CtrlApp::getAlarmCount( + const oatpp::String & startTime , const oatpp::String &endTime , + const oatpp::String &priority , const oatpp::String &type, const oatpp::String &devType , + const oatpp::String &content + ) +{ + auto almCntDto = almCountDTO::createShared(); + almCntDto->message = "查询成功!"; + almCntDto->data = almCountDataDTO::createShared(); + + if ( startTime == "" || endTime == "" ) + { + const char *szMsg = "请求错误s:时间为空"; + LOGERROR( "%s", szMsg ); + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + + int64 nStartTimeMsec = 0, nEndTimeMsec = 0; + nStartTimeMsec = QString(startTime->c_str()).toLongLong() ; + nEndTimeMsec = QString(endTime->c_str()).toLongLong() ; + + if ( nStartTimeMsec > nEndTimeMsec ) + {//< 不作为错误,调换 + const int64 nTemp = nEndTimeMsec; + nEndTimeMsec = nStartTimeMsec; + nStartTimeMsec = nTemp; + } + + std::string decodedPriority,decodedDevType,decodedType,decodedContent; + std::vector vecPriority, vecDevType, vecType; + + + if ( priority != "" ) + { + decodedPriority = urldecode(*priority); + boost::split( vecPriority, decodedPriority, boost::is_any_of( ";" )); + if ( vecPriority.empty()) + { + const char *szMsg = "请求错误:错误的priority参数"; + LOGERROR( "%s", szMsg ); + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + } + + if ( devType != "" ) + { + decodedDevType = urldecode(*devType); + boost::split( vecDevType, decodedDevType, boost::is_any_of( ";" )); + if ( vecDevType.size() != 1 ) + { + const char *szMsg = "请求错误:devType请求参数数量为1或0"; + LOGERROR( "%s", szMsg ); + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + } + + if ( type != "" ) + { + decodedType = urldecode(*type); + boost::split( vecType, decodedType, boost::is_any_of( ";" )); + if ( vecType.empty()) + { + const char *szMsg = "请求错误:错误的type参数"; + LOGERROR( "%s", szMsg ); + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + } + + if( content != "" ) + { + decodedContent = urldecode(*content); + } + + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + + QString basicStrSql = "select " + " count(*) " + " from his_event "; + + + // 构造查询条件 + QString strCondition = ""; + { // vecPriority,vecLocation,vecDevType,vecType; + auto addCondtion = [&strCondition]( std::vector &vecCondition, const std::string &condName ) + { + if ( !vecCondition.empty()) + { + strCondition += " ( "; + for ( const std::string &x : vecCondition ) + { + strCondition += QString( " " ) + condName.c_str() + "=" + x.c_str() + " or"; + } + strCondition.chop( 3 ); + strCondition += " ) "; + strCondition += " and "; + } + }; + + addCondtion( vecPriority, "priority" ); + addCondtion( vecDevType, "dev_type" ); + addCondtion( vecType, "alm_type" ); + + if ( strCondition != "" ) + { + strCondition = " and " + strCondition; + strCondition.chop( 5 ); // delete " and " + } + + // 增加时间戳 + strCondition = QString( " where " ) + " time_stamp > " + QString::number( nStartTimeMsec ) + + " and time_stamp < " + QString::number( nEndTimeMsec ) + strCondition ; + + if( decodedContent != "" ) + { + strCondition += QString(" and content like '%%%1'").arg(decodedContent.c_str()); + } + } + + + QString strCntAllAck = QString(" and CONFIRM_TIME != 0 "); //已确认 + + QString strSql = basicStrSql + strCondition; + LOGERROR("strSql is %s",strSql.toStdString().c_str()); + QSqlQuery objQuery; + + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, almCntDto ); + } + almCntDto->data->total = totalCnt; + + + objQuery.clear(); + strSql = basicStrSql + strCondition + strCntAllAck; + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + almCntDto->message = szMsg; + return createDtoResponse( Status::CODE_200, almCntDto ); + } + + int totalCntAck{0}; + while ( objQuery.next()) + { + totalCntAck = objQuery.value( 0 ).toString().toInt(); + } + + almCntDto->data->ack = totalCntAck; + almCntDto->data->unAck = totalCnt - totalCntAck; + return createDtoResponse( Status::CODE_200, almCntDto ); +} + +std::shared_ptr CtrlApp::getDeviceTempKeyValue( + const oatpp::String & tag_name, + const oatpp::Int32 & pageNo, + const oatpp::Int32 & pageSize) +{ + auto deviceRsp = deviceTPDTO::createShared(); + deviceRsp->message = "查询成功!"; + deviceRsp->data= deviceTPDataDTO::createShared(); + deviceRsp->data->dataMap = {}; + + // 检查参数 + if( tag_name == "" ) + { + const char *szMsg = "参数有误"; + LOGERROR( "%s", szMsg ); + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + + QString selectCount = "SELECT count(*)"; + QString selectResult = "\ + SELECT treePCode,\ + CODE,\ + NAME,\ + keyValue,\ + type "; + + QString sqlCond = QString( + "FROM\ + (\ + SELECT\ + \"\" AS treePCode,\ + TAG_NAME AS CODE,\ + DESCRIPTION AS NAME,\ + \"\" AS keyValue,\ + \"2\" AS type \ + FROM\ + dev_temp_def \ + WHERE\ + TAG_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treePCode,\ + t1.TAG_NAME AS CODE,\ + concat( t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) AS NAME,\ + key_value,\ + \"yc\" AS type \ + FROM\ + analog_temp_define AS t1\ + LEFT JOIN dev_temp_def AS t2 ON t1.DEV_TP_NAME = t2.TAG_NAME \ + WHERE\ + t1.DEV_TP_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treePCode,\ + t1.TAG_NAME AS CODE,\ + concat( t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) AS NAME,\ + key_value,\ + \"ym\" AS type \ + FROM\ + accuml_temp_define AS t1\ + LEFT JOIN dev_temp_def AS t2 ON t1.DEV_TP_NAME = t2.TAG_NAME \ + WHERE\ + t1.DEV_TP_NAME = \'%1\' UNION\ + SELECT\ + t2.TAG_NAME AS treePCode,\ + t1.TAG_NAME AS CODE,\ + concat( t2.DESCRIPTION, \'.\', t1.DESCRIPTION ) AS NAME,\ + key_value,\ + \"yx\" AS type \ + FROM\ + digital_temp_define AS t1\ + LEFT JOIN dev_temp_def AS t2 ON t1.DEV_TP_NAME = t2.TAG_NAME \ + WHERE\ + t1.DEV_TP_NAME = \'%1\' \ + ) AS u1").arg(tag_name->c_str()); + + + QString strSql = selectCount + sqlCond; + QSqlQuery objQuery; + + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + + // 得到统计数据 + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + deviceRsp->data->records = totalCnt; + deviceRsp->data->total = totalCnt / pageSize + 1; + deviceRsp->data->pageSize = pageSize; + deviceRsp->data->pageNo = pageNo; + + strSql = selectResult + sqlCond + QString(" limit %1 offset %2").arg(QString::number(pageSize)).arg(QString::number( pageSize *(pageNo - 1 ))); + + + // 得到结果 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryEventMsFromMySql(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceRsp->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceRsp ); + } + while ( objQuery.next()) + { + auto deviceTPUnit = deviceTPUnitDTO::createShared(); + + deviceTPUnit->treePcode = objQuery.value( 0 ).toString().toStdString(); + deviceTPUnit->code = objQuery.value( 1 ).toString().toStdString(); + deviceTPUnit->name = objQuery.value( 2 ).toString().toStdString(); + deviceTPUnit->keyValue = objQuery.value( 3 ).toString().toStdString(); + deviceTPUnit->type = objQuery.value( 4 ).toString().toStdString(); + + deviceRsp->data->dataMap->insert(deviceRsp->data->dataMap->end(),deviceTPUnit); + } + return createDtoResponse( Status::CODE_200, deviceRsp ); +} + +std::shared_ptr CtrlApp::setDeviceTempKeyValue( const oatpp::String &strReq ) +{ + + auto spResp = setDevceTPDTO::createShared(); + spResp->message = "设置成功!"; + + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "setDeviceTempKeyValue(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + if(spReq->total != spReq->data->size() ) + { + const char *szMsg = "参数数量不对"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + QString strSql; + QString singleUpdate = "UPDATE %1 SET KEY_VALUE = %2 WHERE TAG_NAME = '%3';"; + for(auto it = spReq->data->cbegin(); it != spReq->data->cend();it++) + { + QString strTable; + if( (*it)->type == "yx" ) + { + strTable = "digital_temp_define"; + }else if( (*it)->type == "yc" ) + { + strTable = "analog_temp_define"; + } + else if( (*it)->type == "ym" ) + { + strTable = "accuml_temp_define"; + } + strSql += singleUpdate.arg(strTable).arg( (*it)->keyValue->c_str() ).arg((*it)->code->c_str()); + } + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_WRITE ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + LOGERROR( "sql:%s", strSql.toStdString().c_str() ); + + if ( !objDbConn.execute(strSql) ) + { + const char *szMsg = "执行失败"; + LOGERROR( "sql:%s, %s", strSql.toStdString().c_str(),szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + return createDtoResponse( Status::CODE_200, spResp ); +} + +std::shared_ptr +CtrlApp::confirmAlm( + const oatpp::String &strReq, + const std::shared_ptr &spRequest) +{ + using namespace web_server::module_alarm; + + LOGERROR("fuck"); + + // 获取用户 + auto spPermApi = getSessionApi()->getCurPermApi( spRequest ); + if ( !spPermApi ) + { + LOGERROR( "未登录,无法获取用户ID" ); + return createResponse( Status::CODE_400, "未登录" ); + } + + int nUserId, nUserGrpId, nLevel, nLoginSec; + std::string strInstanceName; + if ( PERM_NORMAL != spPermApi->CurUser( nUserId, nUserGrpId, nLevel, nLoginSec, strInstanceName )) + { + LOGERROR( "cannot query curuser" ); + return createResponse( Status::CODE_200, "{\"flag\": false}" ); + } + + auto spResp = confirmAlmRepDTO::createShared(); + spResp->message = "确认成功!"; + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "confirmAlm(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + if(spReq->total != spReq->data->size() ) + { + const char *szMsg = "参数数量不对"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + if(spReq->total == 0 ) + { + const char *szMsg = "参数数量为0"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + QMap pkgMap; //Domain-cfmPkg; + + const int domain_id = getServerApi()->getRunAppInfo().nDomainId; + const std::string nodeName = getServerApi()->getRunAppInfo().strLocalNodeName; + auto confirmTime = QDateTime::currentMSecsSinceEpoch(); + + + for(auto it = spReq->data->cbegin(); it != spReq->data->cend();it++) + { + int alm_type = (*it)->alm_type; + int app_id = (*it)->app_id; + QString key = QString("%1_%2").arg( QString::number( alm_type ) ) + .arg( QString::number( app_id ) ); + auto itAlm = pkgMap.find(key); + if(itAlm == pkgMap.end()) + { + iot_idl::SAlmCltCfmAlm pkg = iot_idl::SAlmCltCfmAlm(); + pkg.set_node_name(nodeName); + pkg.set_user_id(nUserId); + pkg.set_confirm_time(confirmTime); + pkg.set_domain_id(domain_id); + pkg.set_app_id(alm_type); + pkg.set_alm_type(app_id); + pkgMap[key] = pkg; + } + pkgMap[key].add_key_id_tag((*it)->key_id_tag); + pkgMap[key].add_time_stamp((*it)->timestamp); + pkgMap[key].add_uuid_base64((*it)->uuid_base64); + } + bool ret = true; + //请求确认 + foreach ( auto pkg, pkgMap) + { + if(CDataMngThread::getInstance()->requestCfmAlm(pkg) != true) + { + LOGERROR("action to alarm failed"); + ret = false; + break; + } + } + + if(ret) + { + return createDtoResponse( Status::CODE_200, spResp ); + } + else + { + const char *szMsg = "确认失败"; + spResp->message = szMsg; + spResp->code = 201; + return createDtoResponse( Status::CODE_201, spResp ); + } +} + +std::shared_ptr +CtrlApp::deleteAlm( + const oatpp::String &strReq) +{ + using namespace web_server::module_alarm; + + auto spResp = deleteAlmRepDTO::createShared(); + spResp->message = "删除成功!"; + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "deleteAlm(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + if(spReq->total != spReq->data->size() ) + { + const char *szMsg = "参数数量不对"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + if(spReq->total == 0 ) + { + const char *szMsg = "参数数量为0"; + LOGERROR( "%s", szMsg ); + spResp->message = szMsg; + return createDtoResponse( Status::CODE_201, spResp ); + } + + iot_idl::SAlmCltDelAlm pkg; + pkg.set_domain_id(getServerApi()->getRunAppInfo().nDomainId); + + for(auto it = spReq->data->cbegin(); it != spReq->data->cend();it++) + { + pkg.add_uuid_base64(*it); + } + bool ret = CDataMngThread::getInstance()->requestDelAlm(pkg); + + if(ret) + { + return createDtoResponse( Status::CODE_200, spResp ); + } + else + { + LOGERROR("fail to delete alarm"); + const char *szMsg = "删除失败"; + spResp->message = szMsg; + spResp->code = 201; + return createDtoResponse( Status::CODE_201, spResp ); + } +} + + +std::shared_ptr +CtrlApp::queryLocationList( + const oatpp::String & filterStr, + const oatpp::String & devStr, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + auto locationlistdto=locationListDTO::createShared(); + locationlistdto->rows={}; + //先查location + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + QString strSql; + strSql="select count(1) from sys_model_location_info"; + QSqlQuery objQuery; + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryLocationList(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, locationlistdto ); + } + + locationlistdto->total = totalCnt / pageSize + 1; + locationlistdto->pageSize = pageSize; + locationlistdto->page = page; + + //查询单位 + QMap unitMap; + strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryLocationList(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + //查询列表数据 + strSql="select location_id, tag_name,description from sys_model_location_info "; + strSql = strSql + QString(" limit %1 offset %2").arg(QString::number(pageSize)).arg(QString::number( pageSize *(page - 1 ))); + + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationList(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + + // 获取tsdb连接 + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + if ( !pTsdbConn ) + { + LOGERROR("getOneUseableConn() return NULL !"); + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + + QDateTime currentDateTime = QDateTime::currentDateTime(); + QDate currentDate = currentDateTime.date(); + QDateTime startOfDay(currentDate, QTime(0, 0, 0)); + + std::string stdFilterStr(filterStr->c_str(), filterStr->size()); + QString qFilterStr=QString::fromStdString(stdFilterStr); + std::string stdDevStr(devStr->c_str(), devStr->size()); + QString qDevStr=QString::fromStdString(stdDevStr); + + QMap tagDataMap; + while ( objQuery.next()) + { + QSqlQuery objSubQuery; + //查询设备数 + auto locationdto= locationDTO::createShared(); + locationdto->id = objQuery.value( 0 ).toString().toInt(); + locationdto->tagName = objQuery.value( 1 ).toString().toStdString(); + locationdto->locationName = objQuery.value( 2 ).toString().toStdString(); + + + strSql=QString("select count(1) from dev_info where location_id=%1 and tag_name like '%%2%'").arg(QString::number(locationdto->id)).arg(qDevStr); + + + if ( !objDbConn.execute( strSql, objSubQuery )) + { + LOGERROR( "queryLocationList(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + + int devCnt{0}; + while ( objSubQuery.next()) + { + devCnt = objSubQuery.value( 0 ).toString().toInt(); + } + + locationdto->devCnt = devCnt; + locationdto->data={}; + + //location下的累计点数据数据 + + //查询符合条件的测点列表 + QStringList listTag; + std::string tableName="accuml"; + + if(qFilterStr.isEmpty()) + { + strSql="select tag_name,unit_id,description from "+QString::fromStdString(tableName); + }else + { + strSql="select tag_name,unit_id,description from "+QString::fromStdString(tableName)+" where tag_name like '%"+qFilterStr+"%'"; + } + + + if ( !objDbConn.execute( strSql, objSubQuery )) + { + LOGERROR( "queryLocationList(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationlistdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationlistdto ); + } + while ( objSubQuery.next()) + { + tagDataMap.insert(objSubQuery.value( 0 ).toString(),{objSubQuery.value( 1 ).toString().toInt(),objSubQuery.value( 2 ).toString()}); + } + + std::vector vecKey; + + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + stPointKey.m_enType = MPT_ACC; + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName = tag; + vecKey.push_back( stPointKey ); + } + + + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + startOfDay.toMSecsSinceEpoch(), currentDateTime.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("queryLocationList-getHisSamplePoint 查询失败"); + } + + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto historyDatadto=historyDataDTO::createShared(); + historyDatadto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString::fromStdString(vecKey.at(i).m_pszTagName); + historyDatadto->unitName=unitMap[tagDataMap[key].unitId]; + historyDatadto->desc=tagDataMap[key].description.toStdString(); + //size为1 + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + historyDatadto->value=dVal; + + } + locationdto->data->insert(locationdto->data->end(),historyDatadto); + } + + + locationlistdto->rows->insert(locationlistdto->rows->end(),locationdto); + } + + + return createDtoResponse( Status::CODE_200, locationlistdto ); +} + + + +std::shared_ptr +CtrlApp::queryLocationDetail( + const oatpp::String & filterStr, + const oatpp::Int32 & locationId, + const oatpp::String & startTime, + const oatpp::String & endTime + ) +{ + auto locationDetailResponsedto=locationDetailResponseDTO::createShared(); + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + QString strSql; + strSql=QString("select location_id,tag_name,description from sys_model_location_info where location_id=%1 ").arg(locationId); + QSqlQuery objQuery; + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationDetail(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + auto locationDetaildto=locationDetailDTO::createShared(); + locationDetailResponsedto->data=locationDetaildto; + while ( objQuery.next()) + { + locationDetaildto->id = objQuery.value( 0 ).toString().toInt(); + locationDetaildto->tagName =objQuery.value( 1 ).toString().toStdString(); + locationDetaildto->locationName =objQuery.value( 2 ).toString().toStdString(); + } + + //查询单位 + QMap unitMap; + strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryLocationDetail(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + //根据字符串查询所有表字符串的表--累积量 + QMap tagDataMap; + QStringList tables; + tables.append("analog"); + tables.append("accuml"); + std::string stdStr(filterStr->c_str(), filterStr->size()); + + for (const QString &tableName : tables) { + strSql="select tag_name,unit_id,description from "+tableName+" where tag_name like '%"+QString::fromStdString(stdStr)+"%'"; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationDetail(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + while ( objQuery.next()) + { + tagDataMap.insert(objQuery.value( 0 ).toString(),{objQuery.value( 1 ).toString().toInt(),objQuery.value( 2 ).toString()}); + } + } + + //进行influxdb查询 + QStringList listTag; + listTag=tagDataMap.keys(); + std::vector vecKey; + + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + stPointKey.m_enType = MPT_ACC; + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName=tag; + vecKey.push_back( stPointKey ); + + } + + if(vecKey.size() <= 0) + { + LOGERROR("queryLocationDetail tag-key is null"); + const char *szMsg = "无有效的key"; + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + if(startTime=="" || endTime=="") + { + LOGERROR("queryLocationDetail tag-key is null"); + const char *szMsg = "无效的参数"; + locationDetailResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + + QString sStartTime=QString::fromUtf8(startTime->c_str()); + QString sEndTime=QString::fromUtf8(endTime->c_str()); + QDateTime dtStart = QDateTime::fromString(sStartTime,"yyyy-MM-dd hh:mm:ss"); + QDateTime dtEnd = QDateTime::fromString(sEndTime,"yyyy-MM-dd hh:mm:ss"); + + // 获取tsdb连接 + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + if ( !pTsdbConn ) + { + LOGERROR("getOneUseableConn() return NULL !"); + return createDtoResponse( Status::CODE_201, locationDetailResponsedto ); + } + + + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + dtStart.toMSecsSinceEpoch(), dtEnd.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("queryLocationDetail-getHisSamplePoint 查询失败"); + } + + locationDetaildto->data={}; + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto historyDatadto=historyDataDTO::createShared(); + historyDatadto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString(vecKey.at(i).m_pszTagName); + historyDatadto->unitName=unitMap[tagDataMap[key].unitId]; + historyDatadto->desc=tagDataMap[key].description.toStdString(); + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + + historyDatadto->value=dVal; + } + locationDetaildto->data->insert(locationDetaildto->data->end(),historyDatadto); + } + + + + return createDtoResponse( Status::CODE_200, locationDetailResponsedto ); +} + + +std::shared_ptr +CtrlApp::queryDeviceGroups( + const oatpp::String & filterStr, + const oatpp::String & devStr, + const oatpp::Int32 & locationId, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + auto deviceGroupListdto=deviceGroupListDTO::createShared(); + deviceGroupListdto->rows={}; + //先查location + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + deviceGroupListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupListdto ); + } + QString strSql; + strSql=QString("select count(1) from dev_group where location_id=%1").arg(QString::number(locationId)); + QSqlQuery objQuery; + //先查询符合条件的数量 + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryDeviceGroups(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceGroupListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupListdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, deviceGroupListdto ); + } + + deviceGroupListdto->total = totalCnt / pageSize + 1; + deviceGroupListdto->pageSize = pageSize; + deviceGroupListdto->page = page; + + + //查询单位 + QMap unitMap; + strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryDeviceGroups(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceGroupListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupListdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + std::string stdDevStr(devStr->c_str(), devStr->size()); + QString sDevStr=QString::fromStdString(stdDevStr); + strSql=QString("select tag_name, description from dev_group where location_id=%1 and tag_name like '%%2%'").arg(QString::number(locationId)).arg(sDevStr); + strSql = strSql + QString(" limit %1 offset %2").arg(QString::number(pageSize)).arg(QString::number( pageSize *(page- 1 ))); + + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryDeviceGroups(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceGroupListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupListdto ); + } + + List> historyDatas=List>::createShared(); + // 获取tsdb连接 + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + if ( !pTsdbConn ) + { + LOGERROR("getOneUseableConn() return NULL !"); + const char *szMsg = "influxdb链接打开失败"; + deviceGroupListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupListdto ); + } + + std::string stdStr(filterStr->c_str(), filterStr->size()); + QString sfilterStr=QString::fromStdString(stdStr); + + + while(objQuery.next()) + { + auto deviceGroupdto= deviceGroupDTO::createShared(); + deviceGroupdto->deviceGroupTag = objQuery.value( 0 ).toString().toStdString(); + deviceGroupdto->deviceGroupName = objQuery.value( 1 ).toString().toStdString(); + deviceGroupdto->data={}; + + // 获取当前时间 + QDateTime now = QDateTime::currentDateTime(); + // 获取当天的开始时间 + QDateTime start = now.addSecs(-24 * 60 * 60); + + //查询符合条件的测点列表 + QStringList tableNames; + + tableNames.append("accuml"); + tableNames.append("mix"); + tableNames.append("digital"); + tableNames.append("analog"); + + for(int i=0;iclear(); + if(!getInfluxdbDataByDeviceGroup(objDbConn,pTsdbConn,historyDatas,tableName,unitMap,start,now,sfilterStr,objQuery.value( 0 ).toString())) + { + LOGERROR("queryDeviceGroups(): %s influxdb查询%s错误",objQuery.value( 0 ).toString().toStdString().c_str(),tableName.toStdString().c_str()); + }else + { + deviceGroupdto->data->insert(deviceGroupdto->data->end(),historyDatas->begin(),historyDatas->end()); + } + } + + deviceGroupListdto->rows->insert(deviceGroupListdto->rows->end(),deviceGroupdto); + + } + + + return createDtoResponse( Status::CODE_200, deviceGroupListdto ); +} + + +bool CtrlApp::getInfluxdbDataByDeviceGroup(iot_dbms::CDbApi& objDbConn,CTsdbConnPtr& pTsdbConn,List> & hData,const QString& tableName, + QMap& unitMap,QDateTime dtStart,QDateTime dtEnd,QString filterStr ,QString deviceGroup) +{ + //进行influxdb查询 + QStringList listTag; + std::vector vecKey; + QMap tagDataMap; + QSqlQuery objSubQuery; + QString strSql; + if(tableName=="analog" ||tableName=="accuml") + { + strSql="select tag_name,unit_id,description, '' as state_text_name from "+tableName+" where tag_name like '%"+deviceGroup+"%' and tag_name like '%"+filterStr+"%'"; + } + else + { + strSql="select tag_name,'' as unit_id,description, state_text_name from "+tableName+" where tag_name like '%"+deviceGroup+"%' and tag_name like '%"+filterStr+"%'"; + } + if ( !objDbConn.execute( strSql, objSubQuery )) + { + LOGERROR( "查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + return false; + } + while ( objSubQuery.next()) + { + tagDataMap.insert(objSubQuery.value( 0 ).toString(),{objSubQuery.value( 1 ).toString().toInt(),objSubQuery.value( 2 ).toString()}); + } + + + listTag=tagDataMap.keys(); + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + if(tableName=="accuml") + { + stPointKey.m_enType = MPT_ACC; + }else if(tableName=="digital") + { + stPointKey.m_enType = MPT_DI; + }else if(tableName=="mix") + { + stPointKey.m_enType = MPT_MIX; + }else if(tableName=="analog") + { + stPointKey.m_enType = MPT_AI; + } + + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName = tag; + vecKey.push_back( stPointKey ); + } + + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + dtStart.toMSecsSinceEpoch(), dtEnd.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("getHisSamplePoint 查询失败"); + return false; + } + + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto historyDatadto=historyDataDTO::createShared(); + historyDatadto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString(vecKey.at(i).m_pszTagName); + historyDatadto->unitName=unitMap[tagDataMap[key].unitId]; + historyDatadto->desc=tagDataMap[key].description.toStdString(); + historyDatadto->stateTxt=tagDataMap[key].stateTxt.toStdString(); + + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + historyDatadto->value=dVal; + + } + if(tableName=="accuml") + { + historyDatadto->type = MPT_ACC; + }else if(tableName=="digital") + { + historyDatadto->type = MPT_DI; + }else if(tableName=="mix") + { + historyDatadto->type = MPT_MIX; + }else if(tableName=="analog") + { + historyDatadto->type = MPT_AI; + } + + hData->insert(hData->end(),historyDatadto); + } + + + + return true; + +} + +void CtrlApp::initBaseInfo() +{ + // 创建系统信息访问对象 + iot_public::CSysInfoInterfacePtr pSysInfo; + if ( iot_public::createSysInfoInstance(pSysInfo) == false || pSysInfo == NULL ) + { + LOGERROR( "app-module初始化CSysInfoInterface失败" ); + return; + } + + // 获取location信息 + std::vector vecLocationInfo; + if ( iotSuccess != pSysInfo->getAllLocationInfo(vecLocationInfo) ) + { + LOGERROR( "app-modulegetAllLocationInfo失败" ); + return; + } + for ( size_t i=0; i vecSubsystemInfo; + if ( iotSuccess != pSysInfo->getAllSubsystemInfo(vecSubsystemInfo) ) + { + LOGERROR( "app-modulegetAllSubsystemInfo失败" ); + return; + } + for ( size_t i=0; i +CtrlApp::queryDeviceGroupInfo(const oatpp::String & deviceGroupTag,const oatpp::String & deviceStr) +{ + auto deviceGroupInfodto=deviceGroupInfoDTO::createShared(); + deviceGroupInfodto->rows={}; + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + deviceGroupInfodto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupInfodto ); + } + + QString strSql; + std::string stdStr(deviceGroupTag->c_str(), deviceGroupTag->size()); + QString sdeviceGroupTag=QString::fromStdString(stdStr); + + std::string stdDevStr(deviceStr->c_str(), deviceStr->size()); + QString devStr=QString::fromStdString(stdDevStr); + QStringList devList=devStr.split(";"); + QStringList conditions; + for (const QString& part : devList) { + conditions.append(QString("tag_name LIKE '%%1%'").arg(part)); + } + QString condStr=conditions.join(" or "); + + + strSql=QString("select tag_name,description from dev_info where group_tag_name='%1' and (%2)").arg(sdeviceGroupTag).arg(condStr); + QSqlQuery objQuery; + + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryDeviceGroupInfo(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + deviceGroupInfodto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupInfodto ); + } + + while ( objQuery.next()) + { + auto deviceDTO= deviceDTO::createShared(); + deviceDTO->deviceTag = objQuery.value( 0 ).toString().toStdString(); + deviceDTO->desc = objQuery.value( 1 ).toString().toStdString(); + deviceGroupInfodto->rows->insert(deviceGroupInfodto->rows->end(),deviceDTO); + } + + + return createDtoResponse( Status::CODE_200, deviceGroupInfodto ); +} + + +std::shared_ptr +CtrlApp::getCodeByDevice( + const oatpp::String & deviceTag, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + //hl1c1.EMS.analog.hl1c1.WEB_WEB.YCsoc178.value--location.subssyetem.pointtag.colName + auto devicePointCodeListdto=devicePointCodeListDTO::createShared(); + devicePointCodeListdto->rows={}; + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "打开数据库失败"; + LOGERROR( "%s", szMsg ); + devicePointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, devicePointCodeListdto ); + } + + //查询单位 + QMap unitMap; + QString strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "getCodeByDevice(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + devicePointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, devicePointCodeListdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + + + std::string stdStr(deviceTag->c_str(), deviceTag->size()); + QString sDeviceStr=QString::fromStdString(stdStr); + + QString sCondition=QString(" where device='%1' ").arg(sDeviceStr); + QString sql="SELECT location_id,sub_system,tag_name,description, unit_id,'accuml' AS table_name,'' AS state_text_name " + " from accuml "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, unit_id,'analog' AS table_name,'' AS state_text_name " + " from analog "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'digital' AS table_name, state_text_name " + " from digital "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'mix' AS table_name,state_text_name " + " from mix "+sCondition; + + QString cntSql=QString("select count(1) from ( %1 ) as cnt_query").arg(sql); + if ( !objDbConn.execute( cntSql, objQuery )) + { + + LOGERROR( "getCodeByDevice(): 查询错误,SQL语句如下:\n%s", cntSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + devicePointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, devicePointCodeListdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, devicePointCodeListdto ); + } + + devicePointCodeListdto->total = totalCnt / pageSize + 1; + devicePointCodeListdto->pageSize = pageSize; + devicePointCodeListdto->page = page; + + QString pageSql=QString("select location_id,sub_system,tag_name,description, unit_id,table_name,state_text_name from (%1) as page_query limit %2 offset %3 ").arg(sql).arg(QString::number(pageSize)).arg(QString::number( pageSize *(page- 1 ))); + if ( !objDbConn.execute( pageSql, objQuery )) + { + LOGERROR( "getCodeByDevice(): 查询错误,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "数据库查询失败"; + devicePointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, devicePointCodeListdto ); + } + + while(objQuery.next()) + { + auto pointCodedto= pointCodeDTO::createShared(); + QString tableName=objQuery.value("table_name").toString(); + QString fmtTag=QString("%1.%2.%3.%4.%5") + .arg(m_mapLocation[objQuery.value("location_id").toString().toInt()]) + .arg(m_mapSubsystem[objQuery.value("sub_system").toString().toInt()]) + .arg(tableName) + .arg(objQuery.value("tag_name").toString()) + .arg("value"); + pointCodedto->tagName = fmtTag.toStdString(); + pointCodedto->desc = objQuery.value("description").toString().toStdString(); + pointCodedto->unitName = unitMap[ objQuery.value("unit_id").toString().toInt()]; + pointCodedto->stateTxt=objQuery.value("state_text_name").toString().toStdString(); + if(tableName=="analog") + { + pointCodedto->type=MPT_AI; + }else if(tableName=="digital") + { + pointCodedto->type=MPT_DI; + }else if(tableName=="mix") + { + pointCodedto->type=MPT_MIX; + }else if(tableName=="accuml") + { + pointCodedto->type=MPT_ACC; + } + + + devicePointCodeListdto->rows->insert(devicePointCodeListdto->rows->end(),pointCodedto); + } + + return createDtoResponse( Status::CODE_200, devicePointCodeListdto ); + +} + +} //namespace module_app +} //namespace web_server diff --git a/platform/src/service/web_server/module_app/CtrlApp.h b/platform/src/service/web_server/module_app/CtrlApp.h new file mode 100644 index 00000000..169cb318 --- /dev/null +++ b/platform/src/service/web_server/module_app/CtrlApp.h @@ -0,0 +1,157 @@ + +#pragma once + +#include "DTOs.hpp" + +#include "oatpp/web/server/api/ApiController.hpp" +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/macro/component.hpp" + + +#include "rdb_api/RdbTableMng.h" +#include "perm_mng_api/PermMngDefine.h" +#include "service/common/RdbTableDefine.h" +#include "rdb_api/CRdbAccess.h" +#include "rdb_net_api/CRdbNetApi.h" +#include "db_api_ex/CDbApi.h" + +#include +#include <../include/SessionApi.h> + +#include +#include +#include "tsdb_api/CTsdbConn.h" + + +#include OATPP_CODEGEN_BEGIN( ApiController ) //<-- Begin Codegen + +namespace web_server +{ +namespace module_app +{ + + +/** + * Sample Api Controller. + */ +class CtrlApp : public oatpp::web::server::api::ApiController +{ + +private: + iot_dbms::CRdbTableMngPtr m_ptrRdbTableMng; + QMap m_mapLocation; // locationId -> locationName + QMap m_mapSubsystem; // subsystemId -> subsystemName + + bool getRealTimeValStatus(const QStringList & listKeyIdTag,oatpp::Object & rtData,const std::string &tableName); + + bool getInfluxdbDataByDeviceGroup(iot_dbms::CDbApi& objDbConn,iot_dbms::CTsdbConnPtr& pTsdbConn,List> & hData,const QString& tableName, + QMap& unitMap,QDateTime dtStart,QDateTime dtEnd,QString filterStr,QString deviceGroup); + + void initBaseInfo(); +public: + /** + * Constructor with object mapper. + * @param objectMapper - default object mapper used to serialize/deserialize DTOs. + */ + CtrlApp( OATPP_COMPONENT( std::shared_ptr, objectMapper )) + : oatpp::web::server::api::ApiController( objectMapper ) + { + initBaseInfo(); + } + + bool init(); +public: + + // 获得系统时间和安全天数 + ENDPOINT( "GET", "/getAllDeviceTempCode", getAllDeviceTempCode ); + + ENDPOINT("GET", "/getAllTxCodeByDevGrp", getAllTxCodeByDevGrp, + QUERY( String, name,"name",""), + QUERY( Int32, pageNo,"pageNo",1), + QUERY( Int32, pageSize,"pageSize",30) ) ; + + ENDPOINT("GET", "/getAllDeviceByGroupCode", getAllDeviceByGroupCode, + QUERY( String, groupCode ), + QUERY( Int32, pageNo,"pageNo",0), + QUERY( Int32, pageSize,"pageSize",0) + ); + ENDPOINT("POST", "/getRealDataByCode", getRealDataByCode, BODY_STRING( String, strReq )) ; + + ENDPOINT("GET", "/getAlarmCount", getAlarmCount, + QUERY( String, startTime ), QUERY( String, endTime ), + QUERY( String, priority,"priority",""), QUERY( String, type,"type",""), QUERY( String, devType,"devType",""), + QUERY( String, content,"content","") + ) ; + + ENDPOINT("GET", "/getDeviceTempKeyValue", getDeviceTempKeyValue, + QUERY( String, tag_name ), + QUERY( Int32, pageNo,"pageNo",0), + QUERY( Int32, pageSize,"pageSize",0) + ); + + ENDPOINT( "POST", "/setDeviceTempKeyValue", setDeviceTempKeyValue, BODY_STRING( String, strReq )); + + ENDPOINT("POST", "/confirmAlm", confirmAlm,BODY_STRING( String, strReq ), + REQUEST( std::shared_ptr, spRequest )) ; + + ENDPOINT("POST", "/deleteAlm", deleteAlm,BODY_STRING( String, strReq )) ; + + /** + * @brief location列表分页查询 + */ + ENDPOINT("GET", "/app/location", queryLocationList, + QUERY( String, filterStr,"filterStr",""), + QUERY( String, devStr,"devStr",""), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + /** + * @brief location详情查询 + */ + ENDPOINT("GET", "/app/locationDetail", queryLocationDetail, + QUERY( String, filterStr,"filterStr",""), + QUERY( Int32, locationId,"locationId",0), + QUERY( String, startTime,"startTime",""), + QUERY( String, endTime,"endTime","") + ); + + /** + * @brief 设备组列表查询 + */ + ENDPOINT("GET", "/app/deviceGroups", queryDeviceGroups, + QUERY( String, filterStr,"filterStr",""), + QUERY( String, devStr,"devStr",""), + QUERY( Int32, locationId,"locationId",0), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + + + /** + * @brief 设备组信息查询 + */ + ENDPOINT("GET", "/app/deviceGroupInfo", queryDeviceGroupInfo, + QUERY( String, deviceGroupTag,"deviceGroupTag",""), + QUERY( String, deviceStr,"deviceStr","") + ); + + + + /** + * @brief 测点标签查询 + */ + ENDPOINT("GET", "/app/getCodeByDevice", getCodeByDevice, + QUERY( String, deviceTag,"deviceTag",""), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + +}; + + +} //namespace module_app +} //namespace web_server + +#include OATPP_CODEGEN_END( ApiController ) //<-- End Codegen + + diff --git a/platform/src/service/web_server/module_app/DTOs.hpp b/platform/src/service/web_server/module_app/DTOs.hpp new file mode 100644 index 00000000..b1b8dadc --- /dev/null +++ b/platform/src/service/web_server/module_app/DTOs.hpp @@ -0,0 +1,379 @@ + +#pragma once + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" +#include +#include OATPP_CODEGEN_BEGIN( DTO ) + +namespace web_server +{ +namespace module_app +{ + +/** + * Data Transfer Object. Object containing fields only. + * Used in API for serialization/deserialization and validation + */ + + + +class almCountDataDTO : public oatpp::DTO +{ + DTO_INIT( almCountDataDTO, DTO ) + DTO_FIELD( Int32, ack ) = 0; + DTO_FIELD( Int32, unAck ) = 0; + DTO_FIELD( Int32, total ) = 0; +}; + +class almCountDTO : public oatpp::DTO +{ + DTO_INIT( almCountDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); + DTO_FIELD(Object , data ); + +}; + + +class txCodeUnitDTO : public oatpp::DTO +{ + DTO_INIT( txCodeUnitDTO, DTO ) + DTO_FIELD( String, code ) ; + DTO_FIELD( String, name ) ; + DTO_FIELD( String, TxCode ) ; +}; + +class txCodeDataDTO : public oatpp::DTO +{ + DTO_INIT( txCodeDataDTO, DTO ) + DTO_FIELD( Int32, pageNo ) = 0; + DTO_FIELD( Int32, pageSize ) = 0; + DTO_FIELD( Int32, records ) = 0; + DTO_FIELD( Int32, total ) = 0; + DTO_FIELD(List>, dataMap); +}; + +class txCodeDTO : public oatpp::DTO +{ + DTO_INIT( txCodeDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); + DTO_FIELD(Object , data ); +}; + + + +class deviceCodeUnitDTO : public oatpp::DTO +{ + DTO_INIT( deviceCodeUnitDTO, DTO ) + DTO_FIELD( String, treePcode ) ; + DTO_FIELD( String, code ) ; + DTO_FIELD( String, unitName ) ; + DTO_FIELD( String, unitCode ) ; + DTO_FIELD( String, sname ) ; + DTO_FIELD( String, name ) ; + DTO_FIELD( String, keyValue ) ; + DTO_FIELD( String, diNum ) ; + DTO_FIELD( String, type ) ; + +}; + +class deviceCodeDataDTO : public oatpp::DTO +{ + DTO_INIT( deviceCodeDataDTO, DTO ) + DTO_FIELD( Int32, pageNo ) = 0; + DTO_FIELD( Int32, pageSize ) = 0; + DTO_FIELD( Int32, records ) = 0; + DTO_FIELD( Int32, total ) = 0; + DTO_FIELD(List>, dataMap); +}; + +class deviceCodeDTO : public oatpp::DTO +{ + DTO_INIT( deviceCodeDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); + DTO_FIELD(Object , data ); +}; + + + + + +class deviceTPUnitDTO : public oatpp::DTO +{ + DTO_INIT( deviceTPUnitDTO, DTO ) + DTO_FIELD( String, treePcode ) ; + DTO_FIELD( String, code ) ; + DTO_FIELD( String, name ) ; + DTO_FIELD( String, keyValue ) ; + DTO_FIELD( String, type ) ; + +}; + +class deviceTPDataDTO : public oatpp::DTO +{ + DTO_INIT( deviceTPDataDTO, DTO ) + DTO_FIELD( Int32, pageNo ) = 0; + DTO_FIELD( Int32, pageSize ) = 0; + DTO_FIELD( Int32, records ) = 0; + DTO_FIELD( Int32, total ) = 0; + DTO_FIELD(List>, dataMap); +}; + +class deviceTPDTO : public oatpp::DTO +{ + DTO_INIT( deviceTPDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); + DTO_FIELD(Object , data ); +}; + + +class setDevceTPDTO: public oatpp::DTO +{ + DTO_INIT( setDevceTPDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); +}; + + +class setDevceTPReqUnitDTO: public oatpp::DTO +{ + DTO_INIT( setDevceTPReqUnitDTO, DTO ) + DTO_FIELD(String, deviceCode ); + DTO_FIELD(String, code ); + DTO_FIELD(String, keyValue ); + DTO_FIELD(String, type ); +}; + +class setDevceTPReqDTO: public oatpp::DTO +{ + DTO_INIT( setDevceTPReqDTO, DTO ) + DTO_FIELD( Int32, total ) ; + DTO_FIELD(List> , data ); +}; + + + +class rtDataUnitDTO : public oatpp::DTO +{ + DTO_INIT( rtDataUnitDTO, DTO ) + DTO_FIELD( String, key_id_tag ) ; + DTO_FIELD( Float64, value ) ; + DTO_FIELD( Int32, status ) ; +}; + + +class rtDataDTO : public oatpp::DTO +{ + DTO_INIT( rtDataDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( String, time ) ; + DTO_FIELD(List>, data ); +}; + + +class rtReqDTO : public oatpp::DTO +{ + DTO_INIT( rtReqDTO, DTO ) + DTO_FIELD( String, code ); +}; + + +class confirmAlmUnitReqDTO : public oatpp::DTO +{ + DTO_INIT( confirmAlmUnitReqDTO, DTO ) + DTO_FIELD( String, key_id_tag ) ; + DTO_FIELD( Int64, timestamp ) ; + DTO_FIELD( String, uuid_base64 ) ; + DTO_FIELD( Int32, alm_type ) ; + DTO_FIELD( Int32, app_id ) ; +}; + + +class confirmAlmReqDTO: public oatpp::DTO +{ + DTO_INIT( confirmAlmReqDTO, DTO ) + DTO_FIELD( Int32, total ) ; + DTO_FIELD(List> , data ); +}; + +class confirmAlmRepDTO: public oatpp::DTO +{ + DTO_INIT( confirmAlmRepDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); +}; + + +class deleteAlmReqDTO: public oatpp::DTO +{ + DTO_INIT( deleteAlmReqDTO, DTO ) + DTO_FIELD( Int32, total ) ; + DTO_FIELD(List , data ); +}; + +class deviceTempUnitDTO : public oatpp::DTO +{ + DTO_INIT( deviceTempUnitDTO, DTO ) + DTO_FIELD( String, tag_name ) ; + DTO_FIELD( String, desc ) ; + +}; + + +class allDeviceTempDTO: public oatpp::DTO +{ + DTO_INIT( allDeviceTempDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(List> , data ); +}; + +class deleteAlmRepDTO: public oatpp::DTO +{ + DTO_INIT( deleteAlmRepDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD(String, message ); +}; + +class realTimeDataDTO: public oatpp::DTO +{ + DTO_INIT( realTimeDataDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD( Float64, value ); + DTO_FIELD( Int32, status ); + DTO_FIELD(String, unitName ); + +}; + +class historyDataDTO: public oatpp::DTO +{ + DTO_INIT(historyDataDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD( Float64, value ); + DTO_FIELD( Int32, status ); + DTO_FIELD(String, unitName ); + DTO_FIELD(Int32, type ); + DTO_FIELD(String, stateTxt ); +}; + + + +class locationDTO: public oatpp::DTO +{ + DTO_INIT( locationDTO, DTO ) + DTO_FIELD(String, locationName ); + DTO_FIELD( Int32, id ); + DTO_FIELD( Int32, devCnt ); + DTO_FIELD( String, tagName ); + DTO_FIELD(List> , data ); +}; + +class locationListDTO: public oatpp::DTO +{ + DTO_INIT( locationListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); +}; + + +class locationDetailDTO: public oatpp::DTO +{ + DTO_INIT( locationDetailDTO, DTO ) + DTO_FIELD(String, locationName ); + DTO_FIELD( Int32, id ); + DTO_FIELD( String, tagName ); + DTO_FIELD(List> , data ); +}; + +class locationDetailResponseDTO:public oatpp::DTO +{ + DTO_INIT( locationDetailResponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(Object , data ); +}; + + + + +class deviceGroupDTO: public oatpp::DTO +{ + DTO_INIT( deviceGroupDTO, DTO ) + DTO_FIELD(String, deviceGroupName ); + DTO_FIELD( String, deviceGroupTag ); + DTO_FIELD(List> , data ); +}; +class deviceGroupListDTO: public oatpp::DTO +{ + DTO_INIT( deviceGroupListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); +}; + + +struct TagTuple { + int unitId; + QString description; + QString stateTxt; +}; + +class deviceDTO:public oatpp::DTO +{ + DTO_INIT( deviceDTO, DTO ) + DTO_FIELD( String, deviceTag ); + DTO_FIELD( String, desc ); +}; + +class deviceGroupInfoDTO:public oatpp::DTO +{ + DTO_INIT( deviceGroupInfoDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(List> , rows ); +}; + + +class pointCodeDTO:public oatpp::DTO +{ + DTO_INIT( pointCodeDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD(String, unitName ); + DTO_FIELD(Int32, type ); + DTO_FIELD(String, stateTxt ); +}; + +class devicePointCodeListDTO: public oatpp::DTO +{ + DTO_INIT( devicePointCodeListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); +}; + + + + +} //namespace module_app +} //namespace web_server + + +#include OATPP_CODEGEN_END( DTO ) diff --git a/platform/src/service/web_server/module_app/ModuleApp.cpp b/platform/src/service/web_server/module_app/ModuleApp.cpp new file mode 100644 index 00000000..a81215dc --- /dev/null +++ b/platform/src/service/web_server/module_app/ModuleApp.cpp @@ -0,0 +1,51 @@ + +#include "boost/make_shared.hpp" +#include "oatpp/web/server/HttpRouter.hpp" + +#include "CtrlApp.h" +#include "ModuleApp.h" + +namespace web_server +{ +namespace module_app +{ + +bool CModuleApp::init() +{ + auto router = getSimpleRouter(); + auto ctrlGen = std::make_shared(); + if(!ctrlGen->init()) + { + LOGERROR(" ctrlUser failed to init!\n"); + return false; + } + + router->addController( ctrlGen ); + + return true; +} + +bool CModuleApp::redundantSwitch( bool bMaster, bool bSlave ) +{ + //< 避免参数未使用编译告警 + ( void ) bMaster; + ( void ) bSlave; + + + return true; +} + +bool CModuleApp::clean() +{ + + return true; +} + +boost::shared_ptr CModuleApp::create() +{ + return boost::make_shared(); +} + +} +} + diff --git a/platform/src/service/web_server/module_app/ModuleApp.h b/platform/src/service/web_server/module_app/ModuleApp.h new file mode 100644 index 00000000..1172291b --- /dev/null +++ b/platform/src/service/web_server/module_app/ModuleApp.h @@ -0,0 +1,28 @@ + +#pragma once + +#include "../include/BaseModule.h" + +namespace web_server +{ +namespace module_app +{ + +class CModuleApp final : public CBaseModule +{ +public: + CModuleApp() = default; + ~CModuleApp() override = default; + + bool init() override; + + bool redundantSwitch( bool bMaster, bool bSlave ) override; + + bool clean() override; + + static boost::shared_ptr create(); + +}; + +} //< namespace module_app +} //< namespace web_server diff --git a/platform/src/service/web_server/module_app/module_app.pro b/platform/src/service/web_server/module_app/module_app.pro new file mode 100644 index 00000000..8da85bc7 --- /dev/null +++ b/platform/src/service/web_server/module_app/module_app.pro @@ -0,0 +1,30 @@ + +# 该模块为 工业级电源智能监控项目APP需要 + +QT += sql + +#module.pri中已指定编译为静态库,生成路径在编译的临时目录 +TEMPLATE = lib +TARGET = module_app + +HEADERS += \ + DTOs.hpp \ + ModuleApp.h \ + CtrlApp.h + +SOURCES += \ + ModuleApp.cpp \ + CtrlApp.cpp + +#静态库,不要连接,统一在server中连接 +#LIBS += + +#------------------------------------------------------------------- +#所有web_server的模块应包含此pri,无需包含common.pri +MODULE_PRI=$$PWD/../module.pri +exists($$MODULE_PRI) { + include($$MODULE_PRI) +}else { + error("FATAL error: can not find module.pri") +} + diff --git a/platform/src/service/web_server/module_general/CtrlGeneral.cpp b/platform/src/service/web_server/module_general/CtrlGeneral.cpp index dc0f754a..6b7104d1 100644 --- a/platform/src/service/web_server/module_general/CtrlGeneral.cpp +++ b/platform/src/service/web_server/module_general/CtrlGeneral.cpp @@ -1,6 +1,9 @@  #include "CtrlGeneral.hpp" #include "../include/ServerApi.h" +#include +#include "db_api_ex/CDbApi.h" + namespace web_server { @@ -40,7 +43,7 @@ std::shared_ptr CtrlGeneral::get } if ( objRet.msgrecord_size() != 1 || objRet.msgrecord( 0 ).msgvaluearray_size() != 2 ) { - LOGERROR( "wropng size of results of the safe_day" ); + LOGERROR( "wrong size of results of the safe_day" ); return createResponse( Status::CODE_500, "查询失败" ); } auto safeDto = SafeDayDto::createShared(); @@ -146,5 +149,101 @@ CtrlGeneral::isPageAndReportAuthority( const oatpp::Int32 &type, const oatpp::St } +std::shared_ptr +CtrlGeneral::getDictStateText(const oatpp::Int32 &subSystemId) +{ + auto dstResp = dictTextDto::createShared(); + dstResp->data=Fields >::createShared(); + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + dstResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dstResp ); + } + + QString strSql=QString("select state_text_name,actual_value,display_value from dict_state_text_info where sub_system=%1").arg(subSystemId); + if(!objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "getDictStateText(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dstResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dstResp ); + } + while (objQuery.next()) { + oatpp::String sttn=objQuery.value("state_text_name").toString().toStdString(); + oatpp::String av=objQuery.value("actual_value").toString().toStdString(); + oatpp::String dv=objQuery.value("display_value").toString().toStdString(); + if(!dstResp->data[sttn]) + { + oatpp::Fields newInnerFields=oatpp::Fields::createShared(); + newInnerFields[av] = dv; + dstResp->data[sttn]=newInnerFields; + }else{ + + dstResp->data[sttn][av]=dv; + } + } + + + + return createDtoResponse( Status::CODE_200, dstResp ); + +} + + + +std::shared_ptr +CtrlGeneral::getCtrlGrpName(const oatpp::Int32 &subSystemId) +{ + auto dstResp = dictTextDto::createShared(); + dstResp->data=Fields >::createShared(); + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + dstResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dstResp ); + } + + QString strSql=QString("select ctrl_grp_name,ctrl_act_name,ctrl_act_type from opt_ctrl_act_define where sub_system=%1").arg(subSystemId); + if(!objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "getCtrlGrpName(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dstResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dstResp ); + } + while (objQuery.next()) { + oatpp::String sttn=objQuery.value("ctrl_grp_name").toString().toStdString(); + oatpp::String can=objQuery.value("ctrl_act_name").toString().toStdString(); + oatpp::String cat=objQuery.value("ctrl_act_type").toString().toStdString(); + if(!dstResp->data[sttn]) + { + oatpp::Fields newInnerFields=oatpp::Fields::createShared(); + newInnerFields[can] = cat; + dstResp->data[sttn]=newInnerFields; + }else{ + + dstResp->data[sttn][can]=cat; + + + } + } + + + + return createDtoResponse( Status::CODE_200, dstResp ); + +} + + + + + } //namespace module_general } //namespace web_server diff --git a/platform/src/service/web_server/module_general/CtrlGeneral.hpp b/platform/src/service/web_server/module_general/CtrlGeneral.hpp index da198037..8c828376 100644 --- a/platform/src/service/web_server/module_general/CtrlGeneral.hpp +++ b/platform/src/service/web_server/module_general/CtrlGeneral.hpp @@ -70,6 +70,14 @@ public: ,QUERY(String, content) ,REQUEST(std::shared_ptr, request) ); + + ENDPOINT("GET","/gen/getDictStateText",getDictStateText, + QUERY(Int32, subSystemId) + ); + + ENDPOINT("GET","/gen/getCtrlGrpName",getCtrlGrpName, + QUERY(Int32, subSystemId) + ); }; } //namespace module_general diff --git a/platform/src/service/web_server/module_general/DTOs.hpp b/platform/src/service/web_server/module_general/DTOs.hpp index 2d568847..d3cf5b04 100644 --- a/platform/src/service/web_server/module_general/DTOs.hpp +++ b/platform/src/service/web_server/module_general/DTOs.hpp @@ -45,6 +45,14 @@ class SystemDateTimeDto : public oatpp::DTO }; +class dictTextDto:public oatpp::DTO +{ + DTO_INIT( dictTextDto, DTO ) + DTO_FIELD( Int32, code )=200; + DTO_FIELD( String, message ); + DTO_FIELD( Fields >, data ) = {}; +}; + } //namespace module_general } //namespace web_server diff --git a/platform/src/service/web_server/module_general/module_general.pro b/platform/src/service/web_server/module_general/module_general.pro index 6b9f7b37..afca9818 100644 --- a/platform/src/service/web_server/module_general/module_general.pro +++ b/platform/src/service/web_server/module_general/module_general.pro @@ -1,5 +1,6 @@ #module.pri中已指定编译为静态库,生成路径在编译的临时目录 +QT += sql TEMPLATE = lib TARGET = module_general diff --git a/platform/src/service/web_server/module_operate/CModule.cpp b/platform/src/service/web_server/module_operate/CModule.cpp new file mode 100644 index 00000000..d032921d --- /dev/null +++ b/platform/src/service/web_server/module_operate/CModule.cpp @@ -0,0 +1,43 @@ +#include +#include +#include "CModule.h" +#include "CSimpleController.h" + + +using namespace web_server::module_operate; +bool CModule::init() +{ + //< todo 按oatpp的注释,貌似依赖注入和获取区分线程,尚未验证 + //< todo 本程序依赖注入在主线程中,本段代码在主线程中执行没有问题,不知在其他线程中获取注入的component是否有问题 + OATPP_COMPONENT( std::shared_ptr, router, "simpleRouter" ); + router->addController( std::make_shared()); + + //< todo 初始化业务资源,比如自己的线程 + + return true; +} + +bool CModule::redundantSwitch( bool bMaster, bool bSlave ) +{ + //< 避免参数未使用编译告警 + ( void ) bMaster; + ( void ) bSlave; + + //< todo 按业务需求启、停自己的线程等 + + return true; +} + +bool CModule::clean() +{ + //< todo 貌似没有 addController 的逆操作 + //< todo 清理业务资源 + + return true; +} + +boost::shared_ptr CModule::create() +{ + return boost::make_shared(); +} + diff --git a/platform/src/service/web_server/module_operate/CModule.h b/platform/src/service/web_server/module_operate/CModule.h new file mode 100644 index 00000000..a9da0c30 --- /dev/null +++ b/platform/src/service/web_server/module_operate/CModule.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../include/BaseModule.h" + +namespace web_server { namespace module_operate +{ + +class CModule final : public CBaseModule +{ +public: + CModule() = default; + ~CModule() override = default; + +public: + bool init() override; + bool redundantSwitch( bool bMaster, bool bSlave ) override; + bool clean() override; + static boost::shared_ptr create(); +}; + +}} diff --git a/platform/src/service/web_server/module_operate/CMsgDeal.cpp b/platform/src/service/web_server/module_operate/CMsgDeal.cpp new file mode 100644 index 00000000..7d498976 --- /dev/null +++ b/platform/src/service/web_server/module_operate/CMsgDeal.cpp @@ -0,0 +1,155 @@ +#include "CMsgDeal.h" +#include +#include + +namespace web_server { +namespace module_operate{ + +CMsgDeal::CMsgDeal(int appId) +{ + m_sysInfo = NULL; + m_objSendCMb = new CMbCommunicator; + m_objRecvCMb = new CMbCommunicator; + m_appId=appId; + InitMsgBus(); +} + +CMsgDeal::~CMsgDeal() +{ + delete m_objSendCMb; + m_objSendCMb = nullptr; + + m_objRecvCMb->delSub(m_appId, CH_OPT_TO_HMI_OPTCMD_UP); + delete m_objRecvCMb; + m_objRecvCMb = nullptr; +} + +int CMsgDeal::SendMessage(int channelId, int msgType, const std::string &content, int domain) +{ + int ret = 0; + iot_net::CMbMessage msg; + msg.setData(content); + msg.setMsgType(msgType); + msg.setSubject(m_appId, channelId); + + if(m_objSendCMb->sendMsgToDomain(msg, domain)) + { + ret = 1; + } + + return ret; +} + +int CMsgDeal::RevMessage(int msgType,QString& result,std::string& resultStr, SOptCtrlRequest& request) +{ + iot_net::CMbMessage msg; + while(m_objRecvCMb->recvMsg(msg, 60000)) + { + if(msg.getMsgType() != msgType) + { + continue; + } + std::string str((const char*)msg.getDataPtr(), msg.getDataSize()); + SOptCtrlReply socr; + if(!COptCtrlReply::parse(str,socr)) + { + return 1; + } + if(socr.stHead.nIsSuccess==1&& + socr.stHead.strKeyIdTag==request.vecOptCtrlQueue[0].strKeyIdTag + ) + { + resultStr=socr.stHead.strResultStr; + return 0; + }else + { + result=QString::fromStdString(str); + resultStr=socr.stHead.strResultStr; + return 2; + } + + } + return 3; + +} + +int CMsgDeal::RevMessage(int msgType,QString& result,std::string& resultStr, SOptCustCtrlRequest& request, SOptCustCtrlReply& socr) +{ + iot_net::CMbMessage msg; + while(m_objRecvCMb->recvMsg(msg, 60000)) + { + if(msg.getMsgType() != msgType) + { + continue; + } + std::string str((const char*)msg.getDataPtr(), msg.getDataSize()); + if(!COptCustCtrlReply::parse(str,socr)) + { + return 1; + } + if(socr.stHead.nIsSuccess==1&& + socr.stHead.strKeyIdTag==request.strKeyIdTag + ) + { + resultStr=socr.stHead.strResultStr; + return 0; + }else + { + result=QString::fromStdString(str); + resultStr=socr.stHead.strResultStr; + return 2; + } + + } + return 3; + +} + + + + + + +QString CMsgDeal::getNodeName() +{ + SNodeInfo sNodeInfo; + m_sysInfo->getLocalNodeInfo(sNodeInfo); + return QString::fromStdString(sNodeInfo.strName); +} + +QString CMsgDeal::getSendCMbName() +{ + return QString::fromStdString(m_objSendCMb->getName()); +} + +void CMsgDeal::InitMsgBus() +{ + if(!createSysInfoInstance(m_sysInfo)) + { + qDebug() << QObject::tr("创建系统信息访问库实例失败!"); + } + if(!m_objRecvCMb->addSub(m_appId, CH_OPT_TO_HMI_OPTCMD_UP)) + { + qDebug() << QObject::tr("总线订阅失败!"); + return; + } +} + +void CMsgDeal::clearMsgBus() +{ + iot_net::CMbMessage msg; + while(true) + { + if(!m_objRecvCMb->recvMsg(msg, 0)) + { + break; + } + } +} + + + + +}} + + diff --git a/platform/src/service/web_server/module_operate/CMsgDeal.h b/platform/src/service/web_server/module_operate/CMsgDeal.h new file mode 100644 index 00000000..a2fc4cb9 --- /dev/null +++ b/platform/src/service/web_server/module_operate/CMsgDeal.h @@ -0,0 +1,50 @@ +#ifndef CMSGDEAL_H +#define CMSGDEAL_H + +#include "public/pub_sysinfo_api/SysInfoApi.h" +#include "perm_mng_api/PermMngApi.h" +#include "net_msg_bus_api/CMbCommunicator.h" +#include "common/MessageChannel.h" +#include "QString" +#include "service/operate_server_api/JsonMessageStruct.h" +#include "service/operate_server_api/JsonOptCommand.h" + + +using namespace std; +using namespace iot_public; +using namespace iot_service; +using namespace iot_net; + +namespace web_server { +namespace module_operate{ +class CMsgDeal +{ +public: + CMsgDeal(int appId); + ~CMsgDeal(); + +public: + int SendMessage(int channelId, int msgType, const std::string &content, int domain); + int RevMessage(int msgType,QString& result,std::string& resultStr, SOptCtrlRequest& request); + int RevMessage(int msgType,QString& result,std::string& resultStr, SOptCustCtrlRequest& request,SOptCustCtrlReply& socr); + QString getNodeName(); + QString getSendCMbName(); +private: + void InitMsgBus(); + void clearMsgBus(); + +private: + iot_public::CSysInfoInterfacePtr m_sysInfo; + iot_net::CMbCommunicator* m_objSendCMb;//发送 + iot_net::CMbCommunicator* m_objRecvCMb;//接收 + int m_appId; + + +}; + + + + + +}} +#endif // CMSGDEAL_H diff --git a/platform/src/service/web_server/module_operate/CSimpleController.cpp b/platform/src/service/web_server/module_operate/CSimpleController.cpp new file mode 100644 index 00000000..db44d80c --- /dev/null +++ b/platform/src/service/web_server/module_operate/CSimpleController.cpp @@ -0,0 +1,647 @@ +#include "CSimpleController.h" +#include "dbms/db_his_query_api/DbHisQueryApi.h" +#include +#include "public/pub_logger_api/logger.h" +#include "DTOs.hpp" +#include "dbms/db_his_query_api/DbHisQueryBase.h" +#include "tsdb_api/TsdbApi.h" +#include "CMsgDeal.h" + +using namespace iot_dbms; + +namespace web_server { +namespace module_operate { + +std::shared_ptr +CSimpleController::getControlDeviceByDeviceGroup(const oatpp::String & deviceGroupTag) +{ + + auto deviceGroupInfodto=deviceGroupInfoDTO::createShared(); + deviceGroupInfodto->rows={}; + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + deviceGroupInfodto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupInfodto ); + } + + QString strSql; + std::string stdStr(deviceGroupTag->c_str(), deviceGroupTag->size()); + QString sdeviceGroupTag=QString::fromStdString(stdStr); + + strSql=QString("select tag_name,description from dev_info where group_tag_name='%1'").arg(sdeviceGroupTag); + QSqlQuery objQuery; + + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryDeviceGroupInfo(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupInfodto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupInfodto ); + } + + while ( objQuery.next()) + { + QString deviceTag=objQuery.value( 0 ).toString(); + auto deviceDTO= deviceDTO::createShared(); + deviceDTO->deviceTag = deviceTag.toStdString(); + deviceDTO->desc = objQuery.value( 1 ).toString().toStdString(); + if(deviceHasControl(objDbConn,deviceTag)) + { + deviceDTO->type=1; + deviceGroupInfodto->rows->insert(deviceGroupInfodto->rows->end(),deviceDTO); + }else if(deviceHasConst(objDbConn,deviceTag)) + { + deviceDTO->type=2; + deviceGroupInfodto->rows->insert(deviceGroupInfodto->rows->end(),deviceDTO); + } + + } + + return createDtoResponse( Status::CODE_200, deviceGroupInfodto ); + +} + +bool CSimpleController::deviceHasControl(iot_dbms::CDbApi& objDbConn,QString deviceTag) +{ + QSqlQuery objQuery; + QString condition=QString(" where is_control=1 and device='%1' ").arg(deviceTag); + + + QString sql="SELECT tag_name " + " from analog "+condition+ + " union "+ + "SELECT tag_name"+ + " from digital "+condition+ + " union "+ + "SELECT tag_name"+ + " from mix "+condition; + + QString cntSql=QString("select count(1) from ( %1 ) as cnt_query").arg(sql); + if ( !objDbConn.execute( cntSql, objQuery )) + { + LOGERROR( "deviceHasControl(): 查询错误,SQL语句如下:\n%s", cntSql.toUtf8().constData()); + return false; + } + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return false; + } + + return true; +} + +bool CSimpleController::deviceHasConst(CDbApi &objDbConn, QString deviceTag) +{ + QSqlQuery objQuery; + QString cntSql=QString("select count(1) from fes_const where dev_tag='%1' ").arg(deviceTag); + if ( !objDbConn.execute( cntSql, objQuery )) + { + LOGERROR( "deviceHasConst(): 查询错误,SQL语句如下:\n%s", cntSql.toUtf8().constData()); + return false; + } + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return false; + } + + return true; +} + + +std::shared_ptr +CSimpleController::getControlCodeInfoByDevice( + const oatpp::String & deviceTag, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + //查出控制测点,查询influxdb最新值 + auto controlPointListdto=controlPointListDTO::createShared(); + controlPointListdto->rows={}; + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + controlPointListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, controlPointListdto ); + } + + //查询单位 + QMap unitMap; + QString strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "getControlCodeInfoByDevice(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + controlPointListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, controlPointListdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + + std::string stdStr(deviceTag->c_str(), deviceTag->size()); + QString sDeviceStr=QString::fromStdString(stdStr); + + QString sCondition=QString(" where is_control=1 and device='%1' ").arg(sDeviceStr); + QString sql="SELECT location_id,sub_system,tag_name,description, unit_id,'analog' AS table_name,'' AS state_text_name, '' AS ctrl_act_name " + " from analog "+sCondition+ + " union " + "SELECT d.location_id,d.sub_system,d.tag_name,description, '' as unit_id,'digital' AS table_name,state_text_name,dc.ctrl_act_name" + " from digital d INNER JOIN digital_control dc ON d.tag_name=dc.tag_name "+sCondition+ + " union " + "SELECT m.location_id,m.sub_system,m.tag_name,description, '' as unit_id,'mix' AS table_name,state_text_name,mc.ctrl_act_name" + " from mix m INNER JOIN mix_control mc ON m.tag_name=mc.tag_name "+sCondition; + + QString cntSql=QString("select count(1) from ( %1 ) as cnt_query").arg(sql); + if ( !objDbConn.execute( cntSql, objQuery )) + { + + LOGERROR( "getControlCodeInfoByDevice(): 查询错误,SQL语句如下:\n%s", cntSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + controlPointListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, controlPointListdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, controlPointListdto ); + } + + controlPointListdto->total = totalCnt / pageSize + 1; + controlPointListdto->pageSize = pageSize; + controlPointListdto->page = page; + + QString pageSql=QString("select location_id,sub_system,tag_name,description, unit_id,table_name,state_text_name,ctrl_act_name from (%1) as page_query limit %2 offset %3 ").arg(sql).arg(QString::number(pageSize)).arg(QString::number( pageSize *(page- 1 ))); + if ( !objDbConn.execute( pageSql, objQuery )) + { + LOGERROR( "getControlCodeInfoByDevice(): 查询错误,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + controlPointListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, controlPointListdto ); + } + //如果三个表出现相同的tag,则需要修改逻辑 + QMap tagDataMap; + while(objQuery.next()) + { + tagDataMap[objQuery.value("tag_name").toString()]={ + objQuery.value("unit_id").toString().toInt(), + objQuery.value("table_name").toString(), + objQuery.value("description").toString(), + objQuery.value("state_text_name").toString(), + objQuery.value("ctrl_act_name").toString() + }; + + } + + //查询influxdb最新值 + QStringList listTag; + std::vector vecKey; + listTag=tagDataMap.keys(); + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + if((*it).tableName=="analog") + { + stPointKey.m_enType = MPT_AI; + }else if((*it).tableName=="digital") + { + stPointKey.m_enType = MPT_DI; + }else if((*it).tableName=="mix") + { + stPointKey.m_enType = MPT_MIX; + } + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName = tag; + vecKey.push_back( stPointKey ); + } + + + QDateTime dtStart(QDateTime::currentDateTime().date(),QTime(0,0,0)); + QDateTime dtEnd=QDateTime::currentDateTime(); + + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + dtStart.toMSecsSinceEpoch(), dtEnd.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("getHisSamplePoint 查询失败"); + const char *szMsg = "influxdb query faild"; + controlPointListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, controlPointListdto ); + } + + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto pointdto=pointDTO::createShared(); + pointdto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString(vecKey.at(i).m_pszTagName); + pointdto->unitName=unitMap[tagDataMap[key].unitId]; + pointdto->desc=tagDataMap[key].desc.toStdString(); + + pointdto->stateTxt=tagDataMap[key].stateTxt.toStdString(); + pointdto->ctlTxt=tagDataMap[key].ctrlActName.toStdString(); + if(tagDataMap[key].tableName=="analog") + { + pointdto->tagType = MPT_AI; + }else if(tagDataMap[key].tableName=="digital") + { + pointdto->tagType = MPT_DI; + }else if(tagDataMap[key].tableName=="mix") + { + pointdto->tagType = MPT_MIX; + } + + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + pointdto->value=QString::number(dVal).toStdString(); + } + controlPointListdto->rows->insert(controlPointListdto->rows->end(),pointdto); + } + + return createDtoResponse( Status::CODE_200, controlPointListdto); + +} + + +std::shared_ptr CSimpleController::deviceControl( const oatpp::String &strReq,const std::shared_ptr &request) +{ + auto dcResp = deviceControlReponseDTO::createShared(); + + auto perm_mng_api = getSessionApi()->getCurPermApi( request ); + if ( nullptr == perm_mng_api ) + { + LOGERROR( "perm_mng_api is nullptr!" ); + const char *szMsg = " 解析session失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_500, dcResp ); + } + int nUserId, nUserGrpId, nLevel, nLoginSec; + std::string strInstanceName; + if ( PERM_NORMAL != perm_mng_api->CurUser( nUserId, nUserGrpId, nLevel, nLoginSec, strInstanceName )) + { + LOGERROR( "cannot query cur-user" ); + const char *szMsg = " 查询用户失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp); + } + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "deviceControl(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + int locationId=spReq->locationId; + QString strSql=QString("select domain_id from sys_model_location_info where location_id=%1 ").arg(locationId); + QSqlQuery objQuery; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "deviceControl(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + int domianId; + while ( objQuery.next()) + { + domianId=objQuery.value( 0 ).toString().toInt(); + } + + + + CMsgDeal msgDeal(spReq->appId); + SOptCtrlRequest socReq; + + SOptReqHead stHead; + std::string stdStr(spReq->controlSrc->c_str(), spReq->controlSrc->size()); + QString strChain=QString("%1:%2:web_server:modelue_operate:deviceControl").arg(QString::fromStdString(stdStr)).arg(msgDeal.getNodeName()); + stHead.strSrcTag=strChain.toStdString(); + stHead.nSrcDomainID=domianId; + stHead.nDstDomainID=domianId; + stHead.nAppID=spReq->appId; + stHead.strInstName=msgDeal.getNodeName().toStdString(); + stHead.strHostName="web_server"; + stHead.strCommName=msgDeal.getSendCMbName().toStdString(); + stHead.nUserID=nUserId; + stHead.nUserGroupID=nUserGrpId; + stHead.nOptTime=QDateTime::currentDateTime().currentMSecsSinceEpoch(); + + socReq.stHead=stHead; + + + for(auto it = spReq->data->cbegin(); it != spReq->data->cend(); ++it) + { + SOptCtrlReqQueue sosRq; + if((*it)->tagType == MPT_AI) + { + sosRq.strKeyIdTag=("analog."+(*it)->tagName+".value")->c_str(); + }else if((*it)->tagType == MPT_DI) + { + sosRq.strKeyIdTag=("digital."+(*it)->tagName+".value")->c_str(); + }else if((*it)->tagType == MPT_MIX) + { + sosRq.strKeyIdTag=("mix."+(*it)->tagName+".value")->c_str(); + } + + sosRq.nCtrlType=1; + sosRq.dTargetValue=QString::fromStdString((*it)->value).toDouble(); + socReq.vecOptCtrlQueue.push_back(sosRq); + } + + + + std::string content = COptCtrlRequest::generate(socReq); + + //发送总线消息 + if(1!=msgDeal.SendMessage(CH_HMI_TO_OPT_OPTCMD_DOWN,MT_OPT_CTRL_DOWN_EXECUTE,content,domianId)) + { + LOGERROR( "deviceControl(): 命令发送失败,遥控内容:%s", content.c_str()); + const char *szMsg = " 命令发送失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + //接受响应消息 + QString result; + std::string messages; + int msgRes=msgDeal.RevMessage(MT_OPT_CTRL_UP_EXECUTE_REPLY,result,messages,socReq); + if(0==msgRes) + { + dcResp->message = messages.c_str(); + return createDtoResponse( Status::CODE_200, dcResp ); + } + else if(1==msgRes) + { + LOGERROR( "deviceControl():结果解析失败,遥控内容:%s", content.c_str()); + const char *szMsg = "响应结果解析失败"; + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + }else if(3==msgRes) + { + LOGERROR( "deviceControl():命令无响应,遥控内容:%s", content.c_str()); + const char *szMsg = "命令无响应"; + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + } + else{ + LOGERROR( "deviceControl(): 命令执行失败,遥控内容:%s,遥控结果:%s", content.c_str(),result.toStdString().c_str()); + messages="执行失败:"+messages; + const char *szMsg = messages.c_str(); + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + + } + +} + + + +std::shared_ptr CSimpleController::customQuery( const oatpp::String &strReq,const std::shared_ptr &request) +{ + auto dcResp = customQueryReponseDTO::createShared(); + dcResp->data={}; + + auto perm_mng_api = getSessionApi()->getCurPermApi( request ); + if ( nullptr == perm_mng_api ) + { + LOGERROR( "perm_mng_api is nullptr!" ); + const char *szMsg = " 解析session失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_500, dcResp ); + } + int nUserId, nUserGrpId, nLevel, nLoginSec; + std::string strInstanceName; + if ( PERM_NORMAL != perm_mng_api->CurUser( nUserId, nUserGrpId, nLevel, nLoginSec, strInstanceName )) + { + LOGERROR( "cannot query cur-user" ); + const char *szMsg = " 查询用户失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp); + } + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "customQuery(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + int locationId=spReq->locationId; + int commType = spReq->commType; //用于区分自定义命令类型 + + + QString strSql=QString("select domain_id from sys_model_location_info where location_id=%1 ").arg(locationId); + QSqlQuery objQuery; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "customQuery(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + int domianId; + while ( objQuery.next()) + { + domianId=objQuery.value( 0 ).toString().toInt(); + } + + std::string devStr(spReq->devTag->c_str(), spReq->devTag->size()); + //取其中一条来找前置设备名 + strSql=QString("select dev_tag from fes_digital where location_id=%1 and app_tag_name LIKE '%2%' LIMIT 1 ").arg(locationId).arg(QString::fromStdString(devStr)); + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "customQuery(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + QString fesDevStr=""; + while ( objQuery.next()) + { + fesDevStr=objQuery.value( 0 ).toString(); + } + strSql=QString("select tag_name,rtu_tag from fes_const where location_id=%1 and dev_tag='%2' ").arg(locationId).arg(fesDevStr); + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "customQuery(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + QList> tagList; + while ( objQuery.next()) + { + tagList.append(QPair(objQuery.value( 0 ).toString(), objQuery.value( 1 ).toString())); + } + + CMsgDeal msgDeal(spReq->appId); + SOptCustCtrlRequest socReq; + + SOptReqHead stHead; + std::string stdStr(spReq->controlSrc->c_str(), spReq->controlSrc->size()); + QString strChain=QString("%1:%2:web_server:modelue_operate:customQuery").arg(QString::fromStdString(stdStr)).arg(msgDeal.getNodeName()); + stHead.strSrcTag=strChain.toStdString(); + stHead.nSrcDomainID=domianId; + stHead.nDstDomainID=domianId; + stHead.nAppID=spReq->appId; + stHead.strInstName=msgDeal.getNodeName().toStdString(); + stHead.strHostName="web_server"; + stHead.strCommName=msgDeal.getSendCMbName().toStdString(); + stHead.nUserID=nUserId; + stHead.nUserGroupID=nUserGrpId; + stHead.nOptTime=QDateTime::currentDateTime().currentMSecsSinceEpoch(); + socReq.stHead=stHead; + + SOptCustCtrlQueue commInfo; //用于自定义查询存放命令; + commInfo.strKeyName = "CustomType"; + commInfo.strKeyValue = std::to_string(commType); + socReq.vecOptCustCtrlQueue.push_back(commInfo); + + + if(0==tagList.size()) + { + LOGERROR( "customQuery(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "custom config bad"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + + for (int i = 0; i < tagList.size(); ++i) + { + //接受响应消息 + QString result; + std::string messages; + SOptCustCtrlReply socr; + socReq.strKeyIdTag="fes_const."+tagList[i].first.toStdString()+".value"; + socReq.strRtuTag=tagList[i].second.toStdString(); + std::string content = COptCustCtrlRequest::generate(socReq); + //发送总线消息 + if(1!=msgDeal.SendMessage(CH_HMI_TO_OPT_OPTCMD_DOWN,MT_OPT_COMMON_DOWN,content,domianId)) + { + LOGERROR( "customQuery(): 命令发送失败,遥控内容:%s", content.c_str()); + const char *szMsg = " 命令发送失败"; + dcResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dcResp ); + } + int msgRes=msgDeal.RevMessage(MT_OPT_COMMON_UP,result,messages,socReq,socr); + if(0==msgRes) + { + for(auto it=socr.vecOptCustCtrlQueue.begin();it!=socr.vecOptCustCtrlQueue.end();++it) + { + SOptCustCtrlQueue info=*(it); + oatpp::Fields kv=oatpp::Fields::createShared(); + kv["key"]=info.strKeyName; + kv["value"]=info.strKeyValue; + dcResp->data->insert(dcResp->data->end(),kv); + } + + } + else if(1==msgRes) + { + LOGERROR( "customQuery():结果解析失败,遥控内容:%s", content.c_str()); + const char *szMsg = "响应结果解析失败"; + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + }else if(3==msgRes) + { + LOGERROR( "customQuery():命令无响应,遥控内容:%s", content.c_str()); + const char *szMsg = "命令无响应"; + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + } + else{ + LOGERROR( "customQuery(): 命令执行失败,遥控内容:%s,遥控结果:%s", content.c_str(),result.toStdString().c_str()); + messages="执行失败:"+messages; + const char *szMsg = messages.c_str(); + dcResp->message = szMsg; + dcResp->code=500; + return createDtoResponse( Status::CODE_201, dcResp ); + + } + + } + + return createDtoResponse( Status::CODE_200, dcResp ); + +} + + +} +} diff --git a/platform/src/service/web_server/module_operate/CSimpleController.h b/platform/src/service/web_server/module_operate/CSimpleController.h new file mode 100644 index 00000000..900de23d --- /dev/null +++ b/platform/src/service/web_server/module_operate/CSimpleController.h @@ -0,0 +1,56 @@ +#pragma once + +#include "oatpp/core/macro/component.hpp" +#include "oatpp/web/server/api/ApiController.hpp" +#include "QString" +#include "db_api_ex/CDbApi.h" +#include <../include/SessionApi.h> + +#include OATPP_CODEGEN_BEGIN( ApiController ) +namespace web_server { +namespace module_operate{ + class CSimpleController: public oatpp::web::server::api::ApiController + { + public: + CSimpleController( OATPP_COMPONENT(std::shared_ptr,objectMapper) ) + : oatpp::web::server::api::ApiController( objectMapper ) + {} + + ~CSimpleController() + {} + + private: + bool deviceHasControl(iot_dbms::CDbApi& objDbConn,QString deviceTag); + bool deviceHasConst(iot_dbms::CDbApi& objDbConn,QString deviceTag); + + public: + /** + * @brief 控制设备的信息查询 + */ + ENDPOINT("GET", "/operate/getControlDeviceByDeviceGroup", getControlDeviceByDeviceGroup, + QUERY( String, deviceGroupTag,"deviceGroupTag","") + ); + + /** + * @brief 遥调遥测标签查询 + */ + ENDPOINT("GET", "/operate/getControlCodeInfoByDevice", getControlCodeInfoByDevice, + QUERY( String, deviceTag,"deviceTag",""), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + + /** + * @brief 设备的遥调遥控 + */ + ENDPOINT("POST", "/operate/deviceControl", deviceControl, BODY_STRING( String, strReq ),REQUEST(std::shared_ptr, request)) ; + + /** + * @brief 设备的自定义查询 + */ + ENDPOINT("POST", "/operate/customQuery", customQuery, BODY_STRING( String, strReq ),REQUEST(std::shared_ptr, request)) ; + + }; +} +} +#include OATPP_CODEGEN_END( ApiController ) diff --git a/platform/src/service/web_server/module_operate/DTOs.hpp b/platform/src/service/web_server/module_operate/DTOs.hpp new file mode 100644 index 00000000..dc1e7307 --- /dev/null +++ b/platform/src/service/web_server/module_operate/DTOs.hpp @@ -0,0 +1,114 @@ +#pragma once + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" +#include +#include OATPP_CODEGEN_BEGIN( DTO ) + +namespace web_server { +namespace module_operate { + +class deviceDTO:public oatpp::DTO +{ + DTO_INIT( deviceDTO, DTO ) + DTO_FIELD( String, deviceTag ); + DTO_FIELD( String, desc ); + DTO_FIELD( Int32, type ); +}; + +class deviceGroupInfoDTO:public oatpp::DTO +{ + DTO_INIT( deviceGroupInfoDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(List> , rows ); +}; + + +class pointDTO:public oatpp::DTO +{ + DTO_INIT( pointDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD(Int32, tagType ); + DTO_FIELD(String, value ); + DTO_FIELD(String, unitName ); + DTO_FIELD(String, stateTxt ); + DTO_FIELD(String, ctlTxt ); + +}; + +class controlPointListDTO:public oatpp::DTO +{ + DTO_INIT( controlPointListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); +}; + +struct TagTuple { + int unitId; + QString tableName; + QString desc; + QString stateTxt; + QString ctrlActName; + int type; +}; + + +class controlPointDTO:public oatpp::DTO +{ + DTO_INIT( controlPointDTO, DTO ) + DTO_FIELD( Int32, tagType ); + DTO_FIELD( String, value ); + DTO_FIELD( String, tagName ); +}; + + +class deviceControlRequestDTO:public oatpp::DTO +{ + DTO_INIT( deviceControlRequestDTO, DTO ) + DTO_FIELD( Int32, appId ); + DTO_FIELD( Int32, locationId ); + DTO_FIELD( String, controlSrc ); + DTO_FIELD(List> , data ); + +}; + + + +class deviceControlReponseDTO:public oatpp::DTO +{ + DTO_INIT( deviceControlReponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); +}; + +class customQueryRequestDTO:public oatpp::DTO +{ + DTO_INIT( customQueryRequestDTO, DTO ) + DTO_FIELD( Int32, locationId ); + DTO_FIELD( Int32, appId ); + DTO_FIELD( Int32, commType ); + DTO_FIELD( String, controlSrc ); + DTO_FIELD( String, devTag ); +}; + + +class customQueryReponseDTO:public oatpp::DTO +{ + DTO_INIT( customQueryReponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( List >, data ) = {}; +}; + + +} +} + + +#include OATPP_CODEGEN_END( DTO ) diff --git a/platform/src/service/web_server/module_operate/module_operate.pro b/platform/src/service/web_server/module_operate/module_operate.pro new file mode 100644 index 00000000..9c2fe580 --- /dev/null +++ b/platform/src/service/web_server/module_operate/module_operate.pro @@ -0,0 +1,42 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2024-07-25T14:57:04 +# 该模块为web提供控制功能的模块 +#------------------------------------------------- + +QT += sql + +TARGET = module_operate +TEMPLATE = lib + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + ../../../../../platform/src/include/service/operate_server_api/JsonOptCommand.cpp \ + CModule.cpp \ + CSimpleController.cpp \ + CMsgDeal.cpp + +HEADERS += \ + ../../../../../platform/src/include/service/operate_server_api/JsonMessageStruct.h \ + ../../../../../platform/src/include/service/operate_server_api/JsonOptCommand.h \ + CModule.h \ + CSimpleController.h \ + DTOs.hpp \ + CMsgDeal.h + +#静态库,不要连接,统一在server中连接 +#LIBS += + +#------------------------------------------------------------------- +#所有web_server的模块应包含此pri,无需包含common.pri +MODULE_PRI=$$PWD/../module.pri +exists($$MODULE_PRI) { + include($$MODULE_PRI) +}else { + error("FATAL error: can not find module.pri") +} + diff --git a/platform/src/service/web_server/module_statistics/CModule.cpp b/platform/src/service/web_server/module_statistics/CModule.cpp new file mode 100644 index 00000000..52056d79 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CModule.cpp @@ -0,0 +1,42 @@ +#include +#include +#include "CModule.h" +#include "CSimpleController.h" + +using namespace web_server::module_statistics; + +bool CModule::init() +{ + //< todo 按oatpp的注释,貌似依赖注入和获取区分线程,尚未验证 + //< todo 本程序依赖注入在主线程中,本段代码在主线程中执行没有问题,不知在其他线程中获取注入的component是否有问题 + OATPP_COMPONENT( std::shared_ptr, router, "simpleRouter" ); + router->addController( std::make_shared()); + + //< todo 初始化业务资源,比如自己的线程 + + return true; +} + +bool CModule::redundantSwitch( bool bMaster, bool bSlave ) +{ + //< 避免参数未使用编译告警 + ( void ) bMaster; + ( void ) bSlave; + + //< todo 按业务需求启、停自己的线程等 + + return true; +} + +bool CModule::clean() +{ + //< todo 貌似没有 addController 的逆操作 + //< todo 清理业务资源 + + return true; +} + +boost::shared_ptr CModule::create() +{ + return boost::make_shared(); +} diff --git a/platform/src/service/web_server/module_statistics/CModule.h b/platform/src/service/web_server/module_statistics/CModule.h new file mode 100644 index 00000000..f21f2123 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CModule.h @@ -0,0 +1,21 @@ +#pragma once + +#include "../include/BaseModule.h" + +namespace web_server { namespace module_statistics +{ + +class CModule final : public CBaseModule +{ +public: + CModule() = default; + ~CModule() override = default; + +public: + bool init() override; + bool redundantSwitch( bool bMaster, bool bSlave ) override; + bool clean() override; + static boost::shared_ptr create(); +}; + +}} diff --git a/platform/src/service/web_server/module_statistics/CSimpleController.cpp b/platform/src/service/web_server/module_statistics/CSimpleController.cpp new file mode 100644 index 00000000..2dee5e42 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CSimpleController.cpp @@ -0,0 +1,756 @@ +#include "CSimpleController.h" +#include "dbms/db_his_query_api/DbHisQueryApi.h" +#include "DTOs.hpp" +#include +#include "db_api_ex/CDbApi.h" +#include +#include "public/pub_logger_api/logger.h" +#include "tsdb_api/TsdbApi.h" +#include "dbms/db_his_query_api/DbHisQueryBase.h" +#include "CTsdbQuery.h" + +using namespace iot_dbms; +using namespace web_server::module_statistics; + +namespace web_server { + +namespace module_statistics { + + +std::shared_ptr CSimpleController::queryLocationStatistics( + const oatpp::String & filterStr, + const oatpp::Int32 & locationId + ) +{ + auto locationStatResponsedto=locationStatResponseDTO::createShared(); + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg ="db open faild"; + LOGERROR( "%s", szMsg ); + locationStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + QString strSql; + strSql=QString("select location_id,tag_name,description from sys_model_location_info where location_id=%1 ").arg(locationId); + QSqlQuery objQuery; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + locationStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + auto locationStatdto=locationStatDTO::createShared(); + locationStatResponsedto->data=locationStatdto; + locationStatdto->data={}; + while ( objQuery.next()) + { + locationStatdto->id = objQuery.value( 0 ).toString().toInt(); + locationStatdto->tagName =objQuery.value( 1 ).toString().toStdString(); + locationStatdto->locationName =objQuery.value( 2 ).toString().toStdString(); + } + + //查询单位 + QMap unitMap; + strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryLocationStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + locationStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + //根据字符串查询所有表字符串的表--累积量 + QMap tagDataMap; + QString tableName="accuml"; + std::string stdStr(filterStr->c_str(), filterStr->size()); + + QString locationCondition=QString(" location_id=%1 ").arg(locationId); + strSql="select tag_name,unit_id,description from "+tableName+" where "+ locationCondition +" and tag_name like '%"+QString::fromStdString(stdStr)+"%'"; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + locationStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + while ( objQuery.next()) + { + tagDataMap.insert(objQuery.value( 0 ).toString(),{objQuery.value( 1 ).toString().toInt(),objQuery.value( 2 ).toString()}); + } + + //进行influxdb查询 + QStringList listTag; + listTag=tagDataMap.keys(); + std::vector vecKey; + + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + stPointKey.m_enType = MPT_ACC; + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName = tag; + vecKey.push_back( stPointKey ); + } + + if(vecKey.size() <= 0) + { + LOGERROR("queryLocationStatistics tag-key is null"); + const char *szMsg = "无有效的key"; + locationStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + + QDateTime currentDateTime = QDateTime::currentDateTime(); + QDate currentDate = currentDateTime.date(); + QDateTime startOfDay(currentDate, QTime(0, 0, 0)); + + // 获取tsdb连接 + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + if ( !pTsdbConn ) + { + LOGERROR("getOneUseableConn() return NULL !"); + return createDtoResponse( Status::CODE_201, locationStatResponsedto ); + } + + + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + startOfDay.toMSecsSinceEpoch(), currentDateTime.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("queryLocationStatistics-getHisSamplePoint 查询失败"); + } + + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto historyDatadto=historyDataDTO::createShared(); + historyDatadto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString(vecKey.at(i).m_pszTagName); + historyDatadto->unitName=unitMap[tagDataMap[key].unitId]; + historyDatadto->desc=tagDataMap[key].description.toStdString(); + + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + historyDatadto->value=dVal; + + } + locationStatdto->data->insert(locationStatdto->data->end(),historyDatadto); + } + + + return createDtoResponse( Status::CODE_200, locationStatResponsedto ); +} + + + + +std::shared_ptr CSimpleController::getCodeByLocation( + const oatpp::String & filterStr, + const oatpp::Int32 & locationId, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + auto locationPointCodeListdto=locationPointCodeListDTO::createShared(); + locationPointCodeListdto->rows={}; + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + locationPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationPointCodeListdto ); + } + + //查询单位 + QMap unitMap; + QString strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "getCodeByLocation(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + locationPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationPointCodeListdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + + std::string stdStr(filterStr->c_str(), filterStr->size()); + QString sFilterStr=QString::fromStdString(stdStr); + QString sCondition; + if(sFilterStr.isEmpty()) + { + sCondition=QString(" where location_id=%1").arg(locationId); + }else{ + sCondition=QString(" where location_id=%1 and tag_name like '%%2%' ").arg(locationId).arg(sFilterStr); + } + + + QString sql="SELECT location_id,sub_system,tag_name,description, unit_id,'accuml' AS table_name" + " from accuml "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, unit_id,'analog' AS table_name" + " from analog "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'digital' AS table_name" + " from digital "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'mix' AS table_name" + " from mix "+sCondition; + + QString cntSql=QString("select count(1) from (%1) as cnt_query").arg(sql); + if ( !objDbConn.execute( cntSql, objQuery )) + { + + LOGERROR( "getCodeByLocation(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + locationPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationPointCodeListdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, locationPointCodeListdto ); + } + + locationPointCodeListdto->total = totalCnt / pageSize + 1; + locationPointCodeListdto->pageSize = pageSize; + locationPointCodeListdto->page = page; + + QString pageSql=QString("select location_id,sub_system,tag_name,description, unit_id,table_name from (%1) as page_query limit %2 offset %3 ").arg(sql) + .arg(QString::number(pageSize)).arg(QString::number( pageSize *(page- 1 ))); + if ( !objDbConn.execute( pageSql, objQuery )) + { + LOGERROR( "getCodeByLocation(): 查询错误,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "db query error"; + locationPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationPointCodeListdto ); + } + + + while(objQuery.next()) + { + auto pointCodedto= pointCodeDTO::createShared(); + pointCodedto->tagName = objQuery.value("tag_name").toString().toStdString(); + pointCodedto->desc = objQuery.value("description").toString().toStdString(); + pointCodedto->unitName = unitMap[ objQuery.value("unit_id").toString().toInt()]; + + QString tableName=objQuery.value("table_name").toString(); + if(tableName=="analog") + { + pointCodedto->type=EnMeasPiontType::MPT_AI; + }else if(tableName=="accuml") + { + pointCodedto->type=EnMeasPiontType::MPT_DI; + }else if(tableName=="digital") + { + pointCodedto->type=EnMeasPiontType::MPT_MIX; + }else if(tableName=="mix") + { + pointCodedto->type=EnMeasPiontType::MPT_ACC; + }else + { + LOGERROR( "getCodeByLocation(): 查询错误-point-type-miss,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "point type miss"; + locationPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, locationPointCodeListdto ); + } + + locationPointCodeListdto->rows->insert(locationPointCodeListdto->rows->end(),pointCodedto); + } + return createDtoResponse( Status::CODE_200, locationPointCodeListdto ); +} + + + + +std::shared_ptr CSimpleController::queryLocationDataSeries( const oatpp::String &strReq) +{ + + auto ldResp = locationDataSeriesReponseDTO::createShared(); + ldResp->rows={}; + + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "queryLocationDataSeries(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + ldResp->message = szMsg; + return createDtoResponse( Status::CODE_201, ldResp ); + } + + std::vector vecKey; + + for(auto it = spReq->tags->cbegin(); it != spReq->tags->cend(); ++it) + { + SMeasPointKey stPointKey; + if((*it)->type == MPT_AI) + { + stPointKey.m_enType = MPT_AI; + }else if((*it)->type == MPT_DI) + { + stPointKey.m_enType = MPT_DI; + }else if((*it)->type == MPT_MIX) + { + stPointKey.m_enType = MPT_MIX; + } + stPointKey.m_pszTagName =(*it)->tagName->c_str(); + vecKey.push_back( stPointKey ); + } + std::string stdYearStr(spReq->year->c_str(), spReq->year->size()); + QString sYear=QString::fromStdString(stdYearStr); + std::string stdMonthStr(spReq->month->c_str(), spReq->month->size()); + QString sMonth=QString::fromStdString(stdMonthStr); + std::string stdDayStr(spReq->day->c_str(), spReq->day->size()); + QString sDay=QString::fromStdString(stdDayStr); + std::vector>> allData; + + CTsdbQuery tdbQuery; + auto ret=tdbQuery.queryTagByTimeType(QString("%1-%2-%3").arg(sYear).arg(sMonth).arg(sDay),spReq->timeType,vecKey,allData); + if(!ret) + { + LOGERROR( "queryLocationDataSeries():query influxdb faild,请求内容:%s", strReq->c_str()); + const char *szMsg = " query influxdb faild"; + ldResp->message = szMsg; + return createDtoResponse( Status::CODE_201, ldResp ); + }; + //列向获取同一个测点的数据 + size_t col=allData[0].size(); + size_t row=allData.size(); + + for(int i=0;itagName= spReq->tags[i]->tagName; + unitdto->data={}; + for(int j=0;jdata->insert(unitdto->data->end(),allData[j][i].second); + } + + ldResp->rows->insert(ldResp->rows->end(),unitdto); + } + + return createDtoResponse( Status::CODE_200, ldResp ); + +} + + + + +std::shared_ptr CSimpleController::queryDeviceGroupStatistics( + const oatpp::String & filterStr, + const oatpp::String & deviceGroupTag + ) +{ + + auto deviceGroupStatResponsedto=deviceGroupStatResponseDTO::createShared(); + auto deviceGroupStatdto=deviceGroupStatDTO::createShared(); + deviceGroupStatResponsedto->data=deviceGroupStatdto; + + QSqlQuery objQuery; + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + if ( !objDbConn.open()) + { + const char *szMsg ="db open faild"; + LOGERROR( "%s", szMsg ); + deviceGroupStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + //查询单位 + QMap unitMap; + QString strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "queryDeviceGroupStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + //查询设备组下的设备 + QStringList devices; + std::string devStdStr(deviceGroupTag->c_str(), deviceGroupTag->size()); + QString deviceGroupCondition=QString("where group_tag_name='%1' ").arg(QString::fromStdString(devStdStr)); + strSql="select tag_name from dev_info "+deviceGroupCondition; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryLocationStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + while ( objQuery.next()) + { + devices.append(objQuery.value( 0 ).toString()); + } + for (int i = 0; i < devices.size(); ++i) { + devices[i] = QString("'%1'").arg(devices[i]); + } + QString sDevice=devices.join(","); + + //根据字符串查询所有表字符串的表--累积量 + QMap tagDataMap; + QString tableName="accuml"; + std::string stdStr(filterStr->c_str(), filterStr->size()); + + QString deviceCondition=QString(" device in (%1) ").arg(sDevice); + strSql="select tag_name,unit_id,description from "+tableName+" where "+ deviceCondition +" and tag_name like '%"+QString::fromStdString(stdStr)+"%'"; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "queryDeviceGroupStatistics(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + while ( objQuery.next()) + { + tagDataMap.insert(objQuery.value( 0 ).toString(),{objQuery.value( 1 ).toString().toInt(),objQuery.value( 2 ).toString()}); + } + + //进行influxdb查询 + QStringList listTag; + listTag=tagDataMap.keys(); + std::vector vecKey; + + for(auto it = tagDataMap.cbegin(); it != tagDataMap.cend(); ++it) + { + SMeasPointKey stPointKey; + stPointKey.m_enType = MPT_ACC; + std::string tag_tmp = it.key().toStdString(); + char * tag = (char*)malloc(tag_tmp.size() + 1); + memset(tag, 0, tag_tmp.size() + 1); + memcpy(tag, tag_tmp.c_str(), tag_tmp.size()); + stPointKey.m_pszTagName = tag; + vecKey.push_back( stPointKey ); + } + + if(vecKey.size() <= 0) + { + LOGERROR("queryDeviceGroupStatistics tag-key is null"); + const char *szMsg = "无有效的key"; + deviceGroupStatResponsedto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + + QDateTime currentDateTime = QDateTime::currentDateTime(); + QDate currentDate = currentDateTime.date(); + QDateTime startOfDay(currentDate, QTime(0, 0, 0)); + + // 获取tsdb连接 + CTsdbConnPtr pTsdbConn = iot_dbms::getOneUseableConn(true); + if ( !pTsdbConn ) + { + LOGERROR("getOneUseableConn() return NULL !"); + return createDtoResponse( Status::CODE_201, deviceGroupStatResponsedto ); + } + + + std::vector *> vecResult; + for ( size_t i=0; i() ); + if ( !getHisSamplePoint(*pTsdbConn, 10000, + vecKey, + startOfDay.toMSecsSinceEpoch(), currentDateTime.toMSecsSinceEpoch(), + NULL, + NULL, + CM_LAST, + 0, FM_NULL_METHOD, + vecResult) ) + { + LOGINFO("queryDeviceGroupStatistics-getHisSamplePoint 查询失败"); + } + + deviceGroupStatdto->data={}; + for (size_t i=0; i* pVecPoint = vecResult.at(i); + auto historyDatadto=historyDataDTO::createShared(); + historyDatadto->tagName=vecKey.at(i).m_pszTagName; + QString key=QString(vecKey.at(i).m_pszTagName); + historyDatadto->unitName=unitMap[tagDataMap[key].unitId]; + historyDatadto->desc=tagDataMap[key].description.toStdString(); + for(size_t l=0; lsize(); l++) + { + const SVarHisSamplePoint& objPoint = pVecPoint->at(l); + + double dVal = 0.0f; + if (typeid(boost::int32_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else if (typeid(boost::float64_t) == objPoint.m_varValue.type()) + dVal = (double)boost::get(objPoint.m_varValue); + else + { + LOGERROR("tag:%s Invalid data type of SVarHisSamplePoint.m_varValue ",vecKey.at(i).m_pszTagName); + } + historyDatadto->value=dVal; + } + deviceGroupStatdto->data->insert(deviceGroupStatdto->data->end(),historyDatadto); + } + + return createDtoResponse( Status::CODE_200, deviceGroupStatResponsedto); +} + + +std::shared_ptr CSimpleController::getCodeByDeviceGroup( + const oatpp::String & deviceGroupTag, + const oatpp::Int32 & page, + const oatpp::Int32 & pageSize + ) +{ + auto deviceGroupPointCodeListdto=deviceGroupPointCodeListDTO::createShared(); + deviceGroupPointCodeListdto->rows={}; + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ ); + QSqlQuery objQuery; + if ( !objDbConn.open()) + { + const char *szMsg = "db open faild"; + LOGERROR( "%s", szMsg ); + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + + //查询单位 + QMap unitMap; + QString strSql="select unit_id,unit_name from dict_unit_info"; + if ( !objDbConn.execute( strSql, objQuery )) + { + + LOGERROR( "getCodeByDeviceGroup(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + while ( objQuery.next()) + { + unitMap[objQuery.value( 0 ).toString().toInt()]=objQuery.value( 1 ).toString().toStdString(); + } + + //查询设备组下的设备 + QStringList devices; + std::string devStdStr(deviceGroupTag->c_str(), deviceGroupTag->size()); + QString deviceGroupCondition=QString("where group_tag_name='%1' ").arg(QString::fromStdString(devStdStr)); + strSql="select tag_name from dev_info "+deviceGroupCondition; + if ( !objDbConn.execute( strSql, objQuery )) + { + LOGERROR( "getCodeByDeviceGroup(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + while ( objQuery.next()) + { + devices.append(objQuery.value( 0 ).toString()); + } + for (int i = 0; i < devices.size(); ++i) { + devices[i] = QString("'%1'").arg(devices[i]); + } + + QString sDevice=devices.join(","); + + + QString sCondition=QString(" where device in (%1) ").arg(sDevice); + + QString sql="SELECT location_id,sub_system,tag_name,description, unit_id,'accuml' AS table_name" + " from accuml "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, unit_id,'analog' AS table_name" + " from analog "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'digital' AS table_name" + " from digital "+sCondition+ + " union " + "SELECT location_id,sub_system,tag_name,description, '' as unit_id,'mix' AS table_name" + " from mix "+sCondition; + + QString cntSql=QString("select count(1) from (%1) as cnt_query").arg(sql); + if ( !objDbConn.execute( cntSql, objQuery )) + { + + LOGERROR( "getCodeByLocation(): 查询错误,SQL语句如下:\n%s", strSql.toUtf8().constData()); + const char *szMsg = "db query faild"; + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + + int totalCnt{0}; + while ( objQuery.next()) + { + totalCnt = objQuery.value( 0 ).toString().toInt(); + } + if( totalCnt == 0) + { + return createDtoResponse( Status::CODE_200, deviceGroupPointCodeListdto ); + } + + deviceGroupPointCodeListdto->total = totalCnt / pageSize + 1; + deviceGroupPointCodeListdto->pageSize = pageSize; + deviceGroupPointCodeListdto->page = page; + + QString pageSql=QString("select location_id,sub_system,tag_name,description, unit_id,table_name from (%1) as page_query limit %2 offset %3 ").arg(sql) + .arg(QString::number(pageSize)).arg(QString::number( pageSize *(page- 1 ))); + if ( !objDbConn.execute( pageSql, objQuery )) + { + LOGERROR( "getCodeByLocation(): 查询错误,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "db query error"; + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + + + while(objQuery.next()) + { + auto pointCodedto= pointCodeDTO::createShared(); + pointCodedto->tagName = objQuery.value("tag_name").toString().toStdString(); + pointCodedto->desc = objQuery.value("description").toString().toStdString(); + pointCodedto->unitName = unitMap[ objQuery.value("unit_id").toString().toInt()]; + + QString tableName=objQuery.value("table_name").toString(); + if(tableName=="analog") + { + pointCodedto->type=EnMeasPiontType::MPT_AI; + }else if(tableName=="accuml") + { + pointCodedto->type=EnMeasPiontType::MPT_DI; + }else if(tableName=="digital") + { + pointCodedto->type=EnMeasPiontType::MPT_MIX; + }else if(tableName=="mix") + { + pointCodedto->type=EnMeasPiontType::MPT_ACC; + }else + { + LOGERROR( "getCodeByLocation(): 查询错误-point-type-miss,SQL语句如下:\n%s", pageSql.toUtf8().constData()); + const char *szMsg = "point type miss"; + deviceGroupPointCodeListdto->message = szMsg; + return createDtoResponse( Status::CODE_201, deviceGroupPointCodeListdto ); + } + + deviceGroupPointCodeListdto->rows->insert(deviceGroupPointCodeListdto->rows->end(),pointCodedto); + } + + return createDtoResponse( Status::CODE_200, deviceGroupPointCodeListdto ); + +} + + +std::shared_ptr CSimpleController::queryDeviceGroupDataSeries( const oatpp::String &strReq) +{ + auto dgResp = deviceGroupDataSeriesReponseDTO::createShared(); + dgResp->rows={}; + auto spReq = getDefaultObjectMapper()->readFromString< oatpp::Object >( strReq ); + if ( !spReq ) + { + LOGERROR( "queryDeviceGroupDataSeries(): 请求解析失败,请求内容:%s", strReq->c_str()); + const char *szMsg = " 请求解析失败"; + dgResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dgResp ); + } + + std::vector vecKey; + + for(auto it = spReq->tags->cbegin(); it != spReq->tags->cend(); ++it) + { + SMeasPointKey stPointKey; + if((*it)->type == MPT_AI) + { + stPointKey.m_enType = MPT_AI; + }else if((*it)->type == MPT_DI) + { + stPointKey.m_enType = MPT_DI; + }else if((*it)->type == MPT_MIX) + { + stPointKey.m_enType = MPT_MIX; + } + stPointKey.m_pszTagName =(*it)->tagName->c_str(); + vecKey.push_back( stPointKey ); + } + std::string stdYearStr(spReq->year->c_str(), spReq->year->size()); + QString sYear=QString::fromStdString(stdYearStr); + std::string stdMonthStr(spReq->month->c_str(), spReq->month->size()); + QString sMonth=QString::fromStdString(stdMonthStr); + std::string stdDayStr(spReq->day->c_str(), spReq->day->size()); + QString sDay=QString::fromStdString(stdDayStr); + std::vector>> allData; + + CTsdbQuery tdbQuery; + auto ret=tdbQuery.queryTagByTimeType(QString("%1-%2-%3").arg(sYear).arg(sMonth).arg(sDay),spReq->timeType,vecKey,allData); + if(!ret) + { + LOGERROR( "queryDeviceGroupDataSeries():query influxdb faild,请求内容:%s", strReq->c_str()); + const char *szMsg = " query influxdb faild"; + dgResp->message = szMsg; + return createDtoResponse( Status::CODE_201, dgResp ); + }; + //列向获取同一个测点的数据 + size_t col=allData[0].size(); + size_t row=allData.size(); + + + for(int i=0;itagName= spReq->tags[i]->tagName; + unitdto->data={}; + for(int j=0;jdata->insert(unitdto->data->end(),allData[j][i].second); + } + + dgResp->rows->insert(dgResp->rows->end(),unitdto); + } + + return createDtoResponse( Status::CODE_200, dgResp ); + +} + +} +} + + diff --git a/platform/src/service/web_server/module_statistics/CSimpleController.h b/platform/src/service/web_server/module_statistics/CSimpleController.h new file mode 100644 index 00000000..a05d29ee --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CSimpleController.h @@ -0,0 +1,68 @@ +#pragma once + +#include "oatpp/core/macro/component.hpp" +#include "oatpp/web/server/api/ApiController.hpp" + + +#include OATPP_CODEGEN_BEGIN( ApiController ) +namespace web_server { +namespace module_statistics{ + class CSimpleController: public oatpp::web::server::api::ApiController + { + public: + CSimpleController( OATPP_COMPONENT(std::shared_ptr,objectMapper) ) + : oatpp::web::server::api::ApiController( objectMapper ) + {} + + ~CSimpleController() + {} + + public: + /** + * @brief location统计查询 + */ + ENDPOINT("GET", "/stats/locationStatistics", queryLocationStatistics, + QUERY( String, filterStr,"filterStr",""), + QUERY( Int32, locationId,"locationId",0) + ); + /** + * @brief 获取location的测点标签 + */ + ENDPOINT("GET", "/stats/getCodeByLocation", getCodeByLocation, + QUERY( String, filterStr,"filterStr",""), + QUERY( Int32, locationId,"locationId",0), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + + /** + * @brief 获取location的测点序列数据 + */ + ENDPOINT("POST", "/stats/locationDataSeries", queryLocationDataSeries, BODY_STRING( String, strReq )) ; + + /** + * @brief 设备统计查询 + */ + ENDPOINT("GET", "/stats/deviceGroupStatistics", queryDeviceGroupStatistics, + QUERY( String, filterStr,"filterStr",""), + QUERY( String, deviceGroupTag,"deviceGroupTag","") + ); + + /** + * @brief 获取deviceGroup的测点标签 + */ + ENDPOINT("GET", "/stats/getCodeByDeviceGroup", getCodeByDeviceGroup, + QUERY( String, deviceGroupTag,"deviceGroupTag",""), + QUERY( Int32, page,"page",1), + QUERY( Int32, pageSize,"pageSize",30) + ); + + /** + * @brief 获取deviceGroup的测点序列数据 + */ + ENDPOINT("POST", "/stats/deviceGroupDataSeries", queryDeviceGroupDataSeries, BODY_STRING( String, strReq )) ; + + }; +} +} +#include OATPP_CODEGEN_END( ApiController ) diff --git a/platform/src/service/web_server/module_statistics/CTsdbQuery.cpp b/platform/src/service/web_server/module_statistics/CTsdbQuery.cpp new file mode 100644 index 00000000..dedc6601 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CTsdbQuery.cpp @@ -0,0 +1,197 @@ +#include "CTsdbQuery.h" +#include "QPair" +#include "QDateTime" +#include "public/pub_logger_api/logger.h" +#include "dbms/db_his_query_api/DbHisQueryApi.h" + +using namespace iot_dbms; +namespace web_server { + +namespace module_statistics { +CTsdbQuery::CTsdbQuery() +{ + m_pTsdbConn = iot_dbms::getOneUseableConn(true); +} + +CTsdbQuery::~CTsdbQuery() +{ + +} + +bool CTsdbQuery::queryTagByTimeType(QString timeStr,int timeType,const std::vector& vecMpKey, std::vector>>& allData) +{ + QDate date=QDate::fromString(timeStr,"yyyy-MM-dd"); + QPairtime_temp; + QList> timeList; + switch (timeType) { + case TimeType::YEAR: + { + //从1月-12月 + QDateTime date_time; + for (int i = 1; i <= 12; i++) + { + //取每月1号0时作为查询点 + date_time.setDate(QDate(date.year(), i, 1)); + date_time.setTime(QTime(0, 0, 0, 0)); + time_temp.first = date_time.addSecs(-5 * 30); + time_temp.second = date_time.addSecs(5 * 30); + timeList.append(time_temp); + } + + //时间段的起始时间 + date_time.setDate(QDate(date.year(), 1, 1)); + date_time.setTime(QTime(0, 0, 0, 0)); + time_temp.first = date_time; + + //时间段的结束时间 + date_time.setDate(QDate(date.year(), 12, date.daysInMonth())); + date_time.setTime(QTime(23, 59, 59, 999)); + time_temp.second = date_time; + } + break; + case TimeType::MONTH: + { + //从1号到本月最后一天 + QDateTime date_time; + for (int i = 1; i <= date.daysInMonth(); i++) + { + date_time.setDate(QDate(date.year(), date.month(), i)); + date_time.setTime(QTime(0, 0, 0, 0)); + time_temp.first = date_time.addSecs(-5 * 30); + time_temp.second = date_time.addSecs(5 * 30); + timeList.append(time_temp); + } + + //时间段的起始时间 + date_time.setDate(QDate(date.year(), date.month(), 1)); + date_time.setTime(QTime(0, 0, 0, 0)); + time_temp.first = date_time; + + //时间段的结束时间 + date_time.setDate(QDate(date.year(), date.month(), date.daysInMonth())); + date_time.setTime(QTime(23, 59, 59, 999)); + time_temp.second = date_time; + } + break; + case TimeType::DAY: + { + //从0时到23时 + QDateTime date_time; + for (int i = 0; i < 24; i++) + { + date_time.setDate(date); + date_time.setTime(QTime(i, 0, 0, 0)); + time_temp.first = date_time.addSecs(-5 * 30); + time_temp.second = date_time.addSecs(5 * 30); + timeList.append(time_temp); + } + + //时间段的起始时间 + date_time.setDate(date); + date_time.setTime(QTime(0, 0, 0, 0)); + time_temp.first = date_time; + + //时间段的结束时间 + date_time.setDate(date); + date_time.setTime(QTime(23, 59, 59, 999)); + time_temp.second = date_time; + } + break; + default: + LOGERROR( "queryTagByTimeType(): is bad timeType"); + return false; + } + + qint64 start = 0; //查询开始时间 + qint64 end = 0; //查询结束时间 + int length = timeList.length(); //时间列表长度 + bool ret = false; + for(int row = 0; row < length; row++) + { + start =timeList[row].first.toMSecsSinceEpoch(); + end = timeList[row].second.toMSecsSinceEpoch(); + std::vector>data; + data.resize(vecMpKey.size()); + ret = queryTagByPeriod(start, end, vecMpKey, data); + if (ret) + { + allData.push_back(data); + } + else + { + return false; + } + } + + + return true; + +} + +void CTsdbQuery::parseResult(const std::vector& vecMpKey,const std::vector *> vecResult,std::vector> &record) +{ + for (size_t nIndex(0); nIndex < vecResult.size(); nIndex++) + { + if (vecResult.at(nIndex)->size() == 0) + { + record[nIndex].first = INVALID_VS; + record[nIndex].second = -1; + } + else + { + record[nIndex].first = VALID_VS; + if (vecMpKey.at(nIndex).m_enType == MPT_AI || vecMpKey.at(nIndex).m_enType == MPT_ACC) + { + record[nIndex].second =vecResult.at(nIndex)->at(0).m_uniValue.m_float64Val; + } + else + { + record[nIndex].second = vecResult.at(nIndex)->at(0).m_uniValue.m_int32Val; + } + } + } +} + +bool CTsdbQuery::queryTagByPeriod(qint64 startTime, qint64 endTime, const std::vector &vecMpKey, std::vector > &record) +{ + + std::vector *> vecResult; + + for (size_t nIndex(0); nIndex < vecMpKey.size(); nIndex++) + { + vecResult.push_back(new std::vector()); + } + + std::vector vecNotStatusHave(vecMpKey.size()); + for (size_t nIndex(0); nIndex *>::iterator res = vecResult.begin(); + while (res != vecResult.end()) + { + delete (*res); + ++res; + } + + return true; + +} + + + + + +} +} + diff --git a/platform/src/service/web_server/module_statistics/CTsdbQuery.h b/platform/src/service/web_server/module_statistics/CTsdbQuery.h new file mode 100644 index 00000000..e1147ecb --- /dev/null +++ b/platform/src/service/web_server/module_statistics/CTsdbQuery.h @@ -0,0 +1,42 @@ +#ifndef CTSDBQUERY_H +#define CTSDBQUERY_H + +#include "tsdb_api/TsdbApi.h" +#include "dbms/db_his_query_api/DbHisQueryBase.h" +#include "QPair" + +using namespace iot_dbms; +namespace web_server { + +namespace module_statistics { + +#define STAUS_NOT_HAVE 4 +enum TimeType +{ + DAY=1, + MONTH, + YEAR +}; +enum VALUE_STATUS { INVALID_VS = 0, VALID_VS=1}; + +class CTsdbQuery +{ +public: + CTsdbQuery(); + ~CTsdbQuery(); + + bool queryTagByTimeType(QString timeStr,int timeType,const std::vector& vecMpKey, std::vector>>& allData); + void parseResult(const std::vector& vecMpKey,const std::vector *> vecResult,std::vector> &record); + bool queryTagByPeriod(qint64 startTime, qint64 endTime,const std::vector& vecMpKey,std::vector>& record); + +private: + CTsdbConnPtr m_pTsdbConn; + +}; + +} +} + + + +#endif // CTSDBQUERY_H diff --git a/platform/src/service/web_server/module_statistics/DTOs.hpp b/platform/src/service/web_server/module_statistics/DTOs.hpp new file mode 100644 index 00000000..20455ec4 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/DTOs.hpp @@ -0,0 +1,167 @@ +#pragma once + +#include "oatpp/core/macro/codegen.hpp" +#include "oatpp/core/Types.hpp" +#include +#include OATPP_CODEGEN_BEGIN( DTO ) + +namespace web_server +{ + namespace module_statistics + { + /** + * Data Transfer Object. Object containing fields only. + * Used in API for serialization/deserialization and validation + */ + + class historyDataDTO: public oatpp::DTO + { + DTO_INIT(historyDataDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD( Float64, value ); + DTO_FIELD( Int32, status ); + DTO_FIELD(String, unitName ); + }; + + class locationStatDTO: public oatpp::DTO + { + DTO_INIT( locationStatDTO, DTO ) + DTO_FIELD(String, locationName ); + DTO_FIELD( Int32, id ); + DTO_FIELD( String, tagName ); + DTO_FIELD(List> , data ); + }; + + + class locationStatResponseDTO: public oatpp::DTO + { + DTO_INIT(locationStatResponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(Object , data ); + }; + + struct TagTuple { + int unitId; + QString description; + }; + + class pointCodeDTO:public oatpp::DTO + { + DTO_INIT( pointCodeDTO, DTO ) + DTO_FIELD(String, tagName ); + DTO_FIELD(String, desc ); + DTO_FIELD(String, unitName ); + DTO_FIELD( Int32, type ); + }; + + class locationPointCodeListDTO: public oatpp::DTO + { + DTO_INIT( locationPointCodeListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); + }; + + class locationDataSeriesRequestUnitDTO: public oatpp::DTO + { + DTO_INIT( locationDataSeriesRequestUnitDTO, DTO ) + DTO_FIELD( Int32, type ) = 0; + DTO_FIELD( String, tagName ); + }; + + + class locationDataSeriesRequestDTO: public oatpp::DTO + { + DTO_INIT( locationDataSeriesRequestDTO, DTO ) + DTO_FIELD( String, year ); + DTO_FIELD( String, month ); + DTO_FIELD( String, day ); + DTO_FIELD( Int32, timeType ); + DTO_FIELD( Int32, locationId ); + DTO_FIELD(List> , tags ); + }; + + class dataSeriesUnitDTO: public oatpp::DTO + { + DTO_INIT( dataSeriesUnitDTO, DTO ) + DTO_FIELD( String, tagName ); + DTO_FIELD( List, data ); + }; + + class locationDataSeriesReponseDTO: public oatpp::DTO + { + DTO_INIT( locationDataSeriesReponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(List> , rows ); + }; + + + class deviceGroupStatDTO: public oatpp::DTO + { + DTO_INIT( deviceGroupStatDTO, DTO ) + DTO_FIELD( String, deviceTag); + DTO_FIELD(List> , data ); + }; + + + class deviceGroupStatResponseDTO: public oatpp::DTO + { + DTO_INIT(deviceGroupStatResponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(Object , data ); + }; + + + + class deviceGroupPointCodeListDTO: public oatpp::DTO + { + DTO_INIT( deviceGroupPointCodeListDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD( Int32, total ); + DTO_FIELD( Int32, page ); + DTO_FIELD( Int32, pageSize ); + DTO_FIELD(List> , rows ); + }; + + + class deviceGroupDataSeriesRequestUnitDTO: public oatpp::DTO + { + DTO_INIT( deviceGroupDataSeriesRequestUnitDTO, DTO ) + DTO_FIELD( Int32, type ) = 0; + DTO_FIELD( String, tagName ); + }; + + + class deviceGroupDataSeriesRequestDTO: public oatpp::DTO + { + DTO_INIT( deviceGroupDataSeriesRequestDTO, DTO ) + DTO_FIELD( String, year ); + DTO_FIELD( String, month ); + DTO_FIELD( String, day ); + DTO_FIELD( Int32, timeType ); + DTO_FIELD( Int32, locationId ); + DTO_FIELD(List> , tags ); + }; + + + class deviceGroupDataSeriesReponseDTO: public oatpp::DTO + { + DTO_INIT( deviceGroupDataSeriesReponseDTO, DTO ) + DTO_FIELD( Int32, code ) = 200; + DTO_FIELD( String, message ); + DTO_FIELD(List> , rows ); + }; + } +} + + + +#include OATPP_CODEGEN_END( DTO ) diff --git a/platform/src/service/web_server/module_statistics/module_statistics.pro b/platform/src/service/web_server/module_statistics/module_statistics.pro new file mode 100644 index 00000000..3c866872 --- /dev/null +++ b/platform/src/service/web_server/module_statistics/module_statistics.pro @@ -0,0 +1,41 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2024-07-25T13:58:24 +# 该模块为web提供统计功能的模块 +#------------------------------------------------- + +QT += sql + +#module.pri中已指定编译为静态库,生成路径在编译的临时目录 +TARGET = module_statistics +TEMPLATE = lib + + + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + CModule.cpp \ + CSimpleController.cpp \ + CTsdbQuery.cpp + +HEADERS += \ + CModule.h \ + CSimpleController.h \ + DTOs.hpp \ + CTsdbQuery.h + +#静态库,不要连接,统一在server中连接 +#LIBS += + +#------------------------------------------------------------------- +#所有web_server的模块应包含此pri,无需包含common.pri +MODULE_PRI=$$PWD/../module.pri +exists($$MODULE_PRI) { + include($$MODULE_PRI) +}else { + error("FATAL error: can not find module.pri") +} diff --git a/platform/src/service/web_server/module_trend/CController.cpp b/platform/src/service/web_server/module_trend/CController.cpp index 6ea3e94e..c811e36f 100644 --- a/platform/src/service/web_server/module_trend/CController.cpp +++ b/platform/src/service/web_server/module_trend/CController.cpp @@ -254,7 +254,7 @@ bool CController::getDeviceGroupInfoByLocationId( iot_dbms::CDbApi& objDb, oatpp auto pData = CDto_response_stationLocationMS::createShared(); pData->code = objQuery.value(0).toString().toStdString(); pData->treeCode = pData->code; - pData->name = objQuery.value(1).toString().split(".").last().toStdString(); + pData->name = objQuery.value(1).toString().toStdString(); pData->treePCode = objQuery.value(2).toString().toStdString(); pData->type = objQuery.value(3).toString().toStdString(); sDeviceGroupTagName = sDeviceGroupTagName + "'" + QString(pData->code->c_str()) + "',"; @@ -310,7 +310,7 @@ bool CController::getDeviceInfoByDeviceGroupTagName( iot_dbms::CDbApi& objDb, oa auto pData = CDto_response_stationLocationMS::createShared(); pData->code = objQuery.value(0).toString().toStdString(); pData->treeCode = pData->code; - pData->name = objQuery.value(1).toString().split(".").last().toStdString(); + pData->name = objQuery.value(1).toString().toStdString(); pData->treePCode = objQuery.value(2).toString().toStdString(); pData->type = objQuery.value(3).toString().toStdString(); sDeviceTagName = sDeviceTagName + "'" + QString(pData->code->c_str()) + "',"; @@ -348,7 +348,7 @@ bool CController::getYMInfoByDeviceTagName( iot_dbms::CDbApi& objDb, oatpp::data auto pData = CDto_response_stationLocationMS::createShared(); pData->code = objQuery.value(0).toString().toStdString(); pData->treeCode = pData->code; - pData->name = objQuery.value(1).toString().split(".").last().toStdString(); + pData->name = objQuery.value(1).toString().toStdString(); pData->treePCode = objQuery.value(2).toString().toStdString(); pData->type = objQuery.value(3).toString().toStdString(); pData->sname = objQuery.value(4).toString().toStdString(); @@ -386,7 +386,7 @@ bool CController::getYCInfoByDeviceTagName( iot_dbms::CDbApi& objDb, oatpp::data auto pData = CDto_response_stationLocationMS::createShared(); pData->code = objQuery.value(0).toString().toStdString(); pData->treeCode = pData->code; - pData->name = objQuery.value(1).toString().split(".").last().toStdString(); + pData->name = objQuery.value(1).toString().toStdString(); pData->treePCode = objQuery.value(2).toString().toStdString(); pData->type = objQuery.value(3).toString().toStdString(); pData->sname = objQuery.value(4).toString().toStdString(); diff --git a/platform/src/service/web_server/server/GlobalMng.cpp b/platform/src/service/web_server/server/GlobalMng.cpp index a219b060..567a127c 100644 --- a/platform/src/service/web_server/server/GlobalMng.cpp +++ b/platform/src/service/web_server/server/GlobalMng.cpp @@ -20,6 +20,9 @@ #include "../module_general/ModuleGeneral.hpp" #include "../module_realTimeData/CModule.h" #include "../module_trend/CModule.h" +#include "../module_app/ModuleApp.h" +#include "../module_statistics/CModule.h" +#include "../module_operate/CModule.h" #include "GlobalMng.h" @@ -146,6 +149,33 @@ bool CGlobalMng::init( const std::string &strAppName ) return false; } + ptrModule = module_app::CModuleApp::create(); + if ( ptrModule->init()) + m_vecModules.push_back( ptrModule ); + else + { + LOGERROR( "module_app failed to init" ); + return false; + } + + ptrModule = module_statistics::CModule::create(); + if ( ptrModule->init()) + m_vecModules.push_back( ptrModule ); + else + { + LOGERROR( "module_app failed to init" ); + return false; + } + + ptrModule = module_operate::CModule::create(); + if ( ptrModule->init()) + m_vecModules.push_back( ptrModule ); + else + { + LOGERROR( "module_app failed to init" ); + return false; + } + //< todo 其他组件 } diff --git a/platform/src/service/web_server/server/WebServer.cpp b/platform/src/service/web_server/server/WebServer.cpp index 071d4676..e1d819a4 100644 --- a/platform/src/service/web_server/server/WebServer.cpp +++ b/platform/src/service/web_server/server/WebServer.cpp @@ -13,6 +13,7 @@ #include "pub_logger_api/logger.h" #include "pub_utility_api/SingleProcInstance.h" #include "pub_utility_api/FileUtil.h" +#include "pub_utility_api/I18N.h" #include "net_msg_bus_api/MsgBusApi.h" #include "tsdb_api/TsdbApi.h" @@ -115,6 +116,16 @@ bool CWebServer::start( int argc, char *argv[], int & /*nStatus*/) return false; } + //< 初始化翻译 + if (iot_public::initI18N("/web_server_bi/translate", "web_server_bi")) + { + LOGDEBUG(I18N_C("I18N output test:\n This is src hardcode. \n int = [%d] , str = [%s]\n"), 123, "test"); + } + else + { + LOGWARN("国际化初始化失败!"); + } + //< 业务初始化,加载配置等 if ( !m_ptrGlobalMng->init( strAppName )) { diff --git a/platform/src/service/web_server/server/auth/AuthInterceptor.cpp b/platform/src/service/web_server/server/auth/AuthInterceptor.cpp index 0399323c..c35d6462 100644 --- a/platform/src/service/web_server/server/auth/AuthInterceptor.cpp +++ b/platform/src/service/web_server/server/auth/AuthInterceptor.cpp @@ -4,14 +4,15 @@ #include "oatpp/core/macro/component.hpp" #include "oatpp/web/protocol/http/outgoing/ResponseFactory.hpp" #include "oatpp/network/tcp/server/ConnectionProvider.hpp" -#include "pub_utility_api/FileUtil.h" -#include "pub_utility_api/CommonConfigParse.h" + #include "AuthInterceptor.h" #include "boost/uuid/random_generator.hpp" #include "boost/regex.hpp" +#include #include +#include using namespace web_server::auth; @@ -56,65 +57,45 @@ static void generateUuidBase64(std::string &strOut) strOut.shrink_to_fit(); } - -//获取地址访问白名单 -bool getAddrAlwayAllow(std::string &strAddrAllow) -{ - iot_public::CCommonConfigParse objCfgParse; - if(objCfgParse.load(iot_public::CFileUtil::getPathOfCfgFile("web_server.xml"))==iotFailed) - { - LOGDEBUG("AuthInterceptor::getAddrAlawyAllow() web_server.xml load fail .\n"); - return false; - } - if(objCfgParse.getStringValue("web_server","addr_allow",strAddrAllow) != iotSuccess) - { - strAddrAllow=""; - return false; - } - LOGDEBUG("AuthInterceptor::AddrAlwayAllow=[%s] .\n",strAddrAllow.c_str()); - - return true; -} - -bool isAddrAlwayAllow(const std::string&strAddress) -{ - std::string strAddrAllow = ""; - - if(false == getAddrAlwayAllow(strAddrAllow)) - { - return false; //失败白名单失效 - } - int nPos = strAddrAllow.find(strAddress) ; - if( nPos < 0 ) //没有找到 - { - LOGDEBUG("isAddrAlawyAllow::strAddress=[%s] .\n",strAddress.c_str()); - return false; - } - - return true; -} - // 路径白名单 -bool isPathAlwaysAllow(const std::string& path ) +bool AuthInterceptor::isPathAlwaysAllow(const std::string& path ) { - boost::regex loginWsRegex("^\\/login$"); // std::regex alarmCntWsRegex("^\\/alarmCountWebsocket$"); // std::regex alarmWsRegex("^\\/alarmWebsocket$"); // std::regex hisEvtWsRegex("^\\/historyEvent$"); // std::regex realtimeWsRegex("^\\/realTimeDataWebsocket$"); - if ( boost::regex_match(path, boost::regex(loginWsRegex))) +// if ( std::regex_match(path, std::regex(alarmCntWsRegex)) // || std::regex_match(path, std::regex(alarmWsRegex)) // || std::regex_match(path, std::regex(hisEvtWsRegex)) // || std::regex_match(path, std::regex(realtimeWsRegex))) +// { +// return true; +// } + int ivalue; + std::string pathAllow; + std::string pathWsRegex ; + confirm.getIntValue("Allow", "Num", ivalue); + for (int i = 1;i > mapLockedDb = std::map >(); + +bool isUsernameLocked(const std::string &name) +{ + + if( mapLockedDb.find(name) == mapLockedDb.end() ) + { + mapLockedDb.emplace(name,std::make_pair(0,0) ); + return false; + } + else + { + + bool isExpired = QDateTime::currentMSecsSinceEpoch() > ( mapLockedDb[name].second + 300 * 1000 ) ;// 300ms + bool isOverRetryTimes = mapLockedDb[name].first > 5; + if( !isExpired && isOverRetryTimes ) + { + return true; + } + else if( isExpired ) + { + mapLockedDb[name].first = 0; + return false; + } + } + + if(mapLockedDb.size() > 10000) + { + mapLockedDb.clear(); + } + + return false; +} + std::shared_ptr AuthInterceptor::intercept(const std::shared_ptr &request) { auto routes = request->getStartingLine().path.std_str(); @@ -162,11 +178,15 @@ std::shared_ptrgetConnection()->getInputStreamContext().getProperties().get(oatpp::network::tcp::server::ConnectionProvider::ExtendedConnection::PROPERTY_PEER_ADDRESS); std::string port = request->getConnection()->getInputStreamContext().getProperties().get(oatpp::network::tcp::server::ConnectionProvider::ExtendedConnection::PROPERTY_PEER_PORT); - // << 地址白名单判断,白名单内IP不判断权限。但是不能影响正常的WEB访问 - if( isAddrAlwayAllow(address) && !isPathAlwaysAllow(routes)) //在白名单内 && 不是登录操作,直接返回,不校验权限 - { - return nullptr; - } + // 配置文件允许的连接不拦截 +// if( isPathAlwaysAllow(routes) ) +// { +// return nullptr; +// } +// else +// { +// throw oatpp::web::protocol::http::HttpError(oatpp::web::protocol::http::Status::CODE_401, "Unauthorized", {}); +// } if( isPathAlwaysBlock(routes) ) { @@ -188,6 +208,22 @@ std::shared_ptrdateTime = m_rdbUtil.getCurrentDateTime(); + loginFail->content = "账户已锁定, 请稍后重试"; + OATPP_COMPONENT( std::shared_ptr, spMapper ); + const auto && json = spMapper->writeToString(loginFail); + LOGINFO("Username Locked, address:[%s], port:[%s],username:[%s]",address.c_str(), port.c_str(),username->c_str()); + return oatpp::web::protocol::http::outgoing::ResponseFactory::createResponse( oatpp::web::protocol::http::Status::CODE_200, json ); + } + auto loginSucc = LoginSuccDto::createShared(); bool ret = m_rdbUtil.isPermOk(username,password); @@ -199,6 +235,9 @@ std::shared_ptrputHeader("Set-Cookie",std::string("id=") + id + ";Path=/"); + response->putHeader("token",std::string("id=") + id + ";Path=/"); if(!m_ptrSessionApiImpl->addSession(id,username,password,loginSucc->groupList[0])) { @@ -249,7 +289,6 @@ std::shared_ptrputHeader("Set-Cookie", ""); + response->putHeader("token", ""); LOGINFO("Logout address:[%s], port:[%s]",address.c_str(), port.c_str()); return response; @@ -298,7 +338,11 @@ bool AuthInterceptor::init() LOGERROR("rdbUtil failed to init!"); return false; } + if (confirm.load("../../data/config/", "pathallow.xml") == iotFailed) + { + LOGDEBUG("pathallow.xml error"); + return true; + } + LOGDEBUG("pathallow.xml ok"); return true; } - - diff --git a/platform/src/service/web_server/server/auth/AuthInterceptor.h b/platform/src/service/web_server/server/auth/AuthInterceptor.h index 306ca759..0e4aa9f8 100644 --- a/platform/src/service/web_server/server/auth/AuthInterceptor.h +++ b/platform/src/service/web_server/server/auth/AuthInterceptor.h @@ -9,6 +9,8 @@ #include "SesssionApiImpl.h" #include "pub_logger_api/logger.h" #include "AuthRdbUtil.h" +#include "pub_utility_api/CommonConfigParse.h" +using namespace iot_public; namespace web_server { namespace auth @@ -22,9 +24,11 @@ public: std::shared_ptr intercept(const std::shared_ptr& request) override; bool init(); + bool isPathAlwaysAllow(const std::string& path ); + private: - + CCommonConfigParse confirm; CSesssionApiImplPtr m_ptrSessionApiImpl = getSessionApiImplInstance(); CAuthRdbUtil m_rdbUtil; }; diff --git a/platform/src/service/web_server/server/auth/SesssionApiImpl.cpp b/platform/src/service/web_server/server/auth/SesssionApiImpl.cpp index 8930647c..a6701673 100644 --- a/platform/src/service/web_server/server/auth/SesssionApiImpl.cpp +++ b/platform/src/service/web_server/server/auth/SesssionApiImpl.cpp @@ -406,12 +406,6 @@ iot_service::CPermMngApiPtr CSesssionApiImpl::getCurPermApi(const std::shared_pt bool CSesssionApiImpl::isSessionValid(const std::string &sessionId) { - static std::set setAllowedId = {"kbdct","kehua","ganyuhangsb","iwantquit","kangbidasb","kehuasb"}; - if(setAllowedId.find(sessionId) != setAllowedId.end()) // 加入白名单验证 - { - return true; - } - iot_service::CPermMngApiPtr pPermMngApi = getCurPermApi(sessionId); if( nullptr == pPermMngApi ) { diff --git a/platform/src/service/web_server/server/server.pro b/platform/src/service/web_server/server/server.pro index 23336481..a9af20f6 100644 --- a/platform/src/service/web_server/server/server.pro +++ b/platform/src/service/web_server/server/server.pro @@ -17,7 +17,7 @@ TEMPLATE = app TARGET = web_server #连接模块静态库 -LIBS += -lmodule_alarm -lmodule_general -lmodule_realTimeData -lmodule_user -lmodule_trend +LIBS += -lmodule_alarm -lmodule_general -lmodule_realTimeData -lmodule_user -lmodule_trend -lmodule_app -lmodule_operate -lmodule_statistics #oatpp-websocket要写在oatpp之前,否则连接器报错 LIBS += -loatpp-websocket -loatpp @@ -26,12 +26,13 @@ if(CONFIG(enable_oatpp_zlib)) { LIBS += -loatpp-zlib -lz } -LIBS += -lboost_regex -lboost_chrono -lboost_system -lboost_program_options -lboost_date_time -lboost_thread -llog4cplus \ +LIBS += -lboost_regex -lboost_chrono -lboost_system -lboost_program_options -lboost_date_time -lboost_thread -llog4cplus -lboost_locale \ -lpub_logger_api -lpub_utility_api -lpub_sysinfo_api \ -lsys_proc_mng_api -lsys_node_mng_api -ldb_api_ex -ltsdb_api -lrdb_api -lrdb_net_api \ -lnet_msg_bus_api -lalarm_server_api -ldp_chg_data_api -lperm_mng_api \ -ldb_his_query_api + win32{ LIBS += -lbcrypt } diff --git a/platform/src/service/web_server/web_server.pro b/platform/src/service/web_server/web_server.pro index fa64d8b1..15dd8c61 100644 --- a/platform/src/service/web_server/web_server.pro +++ b/platform/src/service/web_server/web_server.pro @@ -1,13 +1,17 @@ TEMPLATE = subdirs -WEB_MODULES = module_alarm \ +WEB_MODULES = \ + module_alarm \ module_general \ module_realTimeData \ module_user \ - module_trend + module_trend \ + module_app -SUBDIRS += $$WEB_MODULES server +SUBDIRS += $$WEB_MODULES server \ + module_statistics \ + module_operate #不用CONFIG += ordered方案,改为depends,模块可以并行编译 server.depends = $$WEB_MODULES diff --git a/platform/src/service/web_server_bi/include/FileApi.h b/platform/src/service/web_server_bi/include/FileApi.h index a874a36e..5c4511c2 100644 --- a/platform/src/service/web_server_bi/include/FileApi.h +++ b/platform/src/service/web_server_bi/include/FileApi.h @@ -83,6 +83,19 @@ public: const QByteArray &baContent, iot_dbms::CDbApi *pDbApi = nullptr,qint64 *nUploadTime = nullptr); + /** + * 上传3D模型接口:保存文件,记录数据库 + * 接口使用QT的数据类型:1、方便使用;2、依托QT的COW机制,带来更好的性能 + * @param [in] strParentCode 父节点编码,前端传入,22位随机ID + * @param [in] strGroup 文件组名称,最后没有路径分隔符"/",示例:config/1/json + * @param [in] strOriginalName 原始文件名,包括扩展名,示例:colorConfig.json + * @param [in] baContent 文件内容 + * @param [in] nCategory 目录类别 + * @param [in] pDbApi 如果不为空,则直接使用此数据库连接,内部无需新建数据库连接,降低开销 + * @return bool 成功还是失败 + */ + static bool uploadModel( const QString &strParentCode,const QString &strGroup, const QString &strOriginalName, + int nCategory,const QByteArray &baContent, iot_dbms::CDbApi *pDbApi = nullptr); /** * 根据path更新文件 @@ -130,6 +143,9 @@ public: */ static bool readFileByPath( const QString &strPath, QByteArray &baContent ); + + static bool readFileByFileNameAndGroup(const QString &strFileName,const QString &strFileGroup, QByteArray &baContent ); + }; } //< namespace web_server_bi diff --git a/platform/src/service/web_server_bi/module_file/CController.cpp b/platform/src/service/web_server_bi/module_file/CController.cpp index 98081bd5..3f9d824f 100644 --- a/platform/src/service/web_server_bi/module_file/CController.cpp +++ b/platform/src/service/web_server_bi/module_file/CController.cpp @@ -11,22 +11,21 @@ using namespace oatpp; using namespace web_server_bi::module_file; namespace multipart = oatpp::web::mime::multipart; -#define MAX_FILE_SIZE 1024l * 1024l * 50l // 最大文件大小 50MB 基本上全景图片一亿像素保证质量的上限 +#define MAX_FILE_SIZE 1024l * 1024l * 100l // 最大文件大小 50MB 基本上全景图片一亿像素保证质量的上限 // assume that the default id of tenant is 1 -const QString &cn_fileGroupImage = QStringLiteral ( "config/1/image" ); -const QString &cn_fileGroupJSON = QStringLiteral ( "config/1/json" ); -const QString &cn_fileGroupDefault = QStringLiteral ( "config/1" ); - - -const char* cn_contentTypeJPEG = "image/jpeg"; -const char* cn_contentTypePNG = "image/png"; -const char* cn_contentTypeGIF = "image/gif"; -const char* cn_contentTypeJSON = "application/json"; +const QString &cn_fileGroupImage = QStringLiteral("config/1/image"); +const QString &cn_fileGroupJSON = QStringLiteral("config/1/json"); +const QString &cn_fileGroupDefault = QStringLiteral("config/1"); +const char *cn_contentTypeJPEG = "image/jpeg"; +const char *cn_contentTypePNG = "image/png"; +const char *cn_contentTypeGIF = "image/gif"; +const char *cn_contentTypeJSON = "application/json"; +const char *cn_contentTypeOctetSteam = "application/octet-stream"; std::shared_ptr -web_server_bi::module_file::CController::uploadFile( const std::shared_ptr &request ) +web_server_bi::module_file::CController::uploadFile(const std::shared_ptr &request) { /* Prepare multipart container. */ auto multipart = std::make_shared(request->getHeaders()); @@ -35,7 +34,7 @@ web_server_bi::module_file::CController::uploadFile( const std::shared_ptrtransferBody(&multipartReader); @@ -44,65 +43,61 @@ web_server_bi::module_file::CController::uploadFile( const std::shared_ptrgetNamedPart("file"); auto spResp = CUploadFileResp::createShared(); - if(!file) + if (!file) { - const std::string strMsg = I18N( "无效的请求参数,文件为空" ); + const std::string strMsg = I18N("无效的请求参数,文件为空"); spResp->code = 400; - LOGERROR( "uploadFile():%s", strMsg.c_str()); + LOGERROR("uploadFile():%s", strMsg.c_str()); spResp->message = strMsg; - return createDtoResponse( Status::CODE_400, spResp ); + return createDtoResponse(Status::CODE_400, spResp); } - // content -> file->getPayload()->getInMemoryData()->c_str() // content-type -> file->getHeader(Header::CONTENT_TYPE)->c_str() // fileName -> file->getFilename()->c_str() // fileSize -> file->getPayload()->getInMemoryData()->size() - QString strFileGroup,strFileName = file->getFilename()->c_str(); + QString strFileGroup, strFileName = file->getFilename()->c_str(); qint64 uploadTime; - if( file->getHeader(Header::CONTENT_TYPE) == cn_contentTypeJPEG - || file->getHeader(Header::CONTENT_TYPE) == cn_contentTypePNG - || file->getHeader(Header::CONTENT_TYPE) == cn_contentTypeGIF ) + if (file->getHeader(Header::CONTENT_TYPE) == cn_contentTypeJPEG || file->getHeader(Header::CONTENT_TYPE) == cn_contentTypePNG || file->getHeader(Header::CONTENT_TYPE) == cn_contentTypeGIF) { strFileGroup = cn_fileGroupImage; } - if( file->getHeader(Header::CONTENT_TYPE ) == cn_contentTypeJSON ) + if (file->getHeader(Header::CONTENT_TYPE) == cn_contentTypeJSON) { strFileGroup = cn_fileGroupJSON; } - - strFileName = CFileApi::uploadFile( strFileGroup , - strFileName, - QByteArray(file->getPayload()->getInMemoryData()->c_str(),(int)( file->getPayload()->getInMemoryData()->size() ) ), - nullptr, - &uploadTime); - if ( strFileName.isEmpty()) + strFileName = CFileApi::uploadFile(strFileGroup, + strFileName, + QByteArray(file->getPayload()->getInMemoryData()->c_str(), (int)(file->getPayload()->getInMemoryData()->size())), + nullptr, + &uploadTime); + if (strFileName.isEmpty()) { - const std::string strMsg = I18N( "保存文件失败" ); - LOGERROR( "uploadFile():%s", strMsg.c_str()); + const std::string strMsg = I18N("保存文件失败"); + LOGERROR("uploadFile():%s", strMsg.c_str()); spResp->code = 500; spResp->message = strMsg; - return createDtoResponse( Status::CODE_500, spResp ); + return createDtoResponse(Status::CODE_500, spResp); } spResp->data = COneFile::createShared(); - QString strExt,strId; + QString strExt, strId; int extIndex; - if( ( extIndex = strFileName.lastIndexOf(".")) != -1) + if ((extIndex = strFileName.lastIndexOf(".")) != -1) { - strId = strFileName.left( extIndex ); - strExt = strFileName.mid(extIndex,-1); + strId = strFileName.left(extIndex); + strExt = strFileName.mid(extIndex, -1); } else { - const std::string strMsg = I18N( "服务器内部错误,文件名错误" ); + const std::string strMsg = I18N("服务器内部错误,文件名错误"); spResp->code = 502; - LOGERROR( "uploadFile():%s", strMsg.c_str()); + LOGERROR("uploadFile():%s", strMsg.c_str()); spResp->message = strMsg; - return createDtoResponse( Status::CODE_502, spResp ); + return createDtoResponse(Status::CODE_502, spResp); } spResp->data->ext = strExt.toStdString(); @@ -112,161 +107,360 @@ web_server_bi::module_file::CController::uploadFile( const std::shared_ptrdata->id = strId.toStdString(); spResp->data->fileGroup = strFileGroup.toStdString(); spResp->data->uploadTime = uploadTime; - spResp->data->url = CFileApi::getUrl(strFileGroup,strFileName).toStdString(); + spResp->data->url = CFileApi::getUrl(strFileGroup, strFileName).toStdString(); spResp->data->status = 0; spResp->code = 200; spResp->message = cn_strSuccess; - LOGINFO("upload file:%s,fileSize:%zu",file->getFilename()->c_str(), file->getPayload()->getInMemoryData()->size() ); - return createDtoResponse( Status::CODE_200, spResp ); + LOGINFO("upload file:%s,fileSize:%zu", file->getFilename()->c_str(), file->getPayload()->getInMemoryData()->size()); + return createDtoResponse(Status::CODE_200, spResp); } +std::shared_ptr +web_server_bi::module_file::CController::upLoadModel(const std::shared_ptr &request) +{ + /* Prepare multipart container. */ + auto multipart = std::make_shared(request->getHeaders()); + /* Create multipart reader. */ + multipart::Reader multipartReader(multipart.get()); + + /* Configure to read part with name "file" into memory */ + multipartReader.setPartReader("file", multipart::createInMemoryPartReader(MAX_FILE_SIZE /* max-data-size */)); + + /* Read multipart body */ + request->transferBody(&multipartReader); + + /* Print value of "file" */ + auto file = multipart->getNamedPart("file"); + + auto spResp = CUploadModelResp::createShared(); + if (!file) + { + const std::string strMsg = I18N("无效的请求参数,文件为空"); + spResp->code = 400; + LOGERROR("uploadFile():%s", strMsg.c_str()); + spResp->message = strMsg; + return createDtoResponse(Status::CODE_400, spResp); + } + + // content -> file->getPayload()->getInMemoryData()->c_str() + // content-type -> file->getHeader(Header::CONTENT_TYPE)->c_str() + // fileName -> file->getFilename()->c_str() + // fileSize -> file->getPayload()->getInMemoryData()->size() + + QString strFileGroup, strParentCode, strFileName = file->getFilename()->c_str(); + int nCategory; + bool bRc = false; + + // 解析POST参数 + { + strFileGroup = request->getQueryParameter("fileGroup").getValue("").c_str(); + nCategory = QString(request->getQueryParameter("category").getValue("").c_str()).toInt(&bRc); + strParentCode = request->getQueryParameter("parentCode").getValue("").c_str(); + } + + if (!bRc) + { + // 返回失败 + const std::string strMsg = I18N("无效的请求参数,category错误"); + spResp->code = 400; + LOGERROR("upLoadModel():%s", strMsg.c_str()); + spResp->message = strMsg; + return createDtoResponse(Status::CODE_400, spResp); + } + + if (file->getHeader(Header::CONTENT_TYPE) != cn_contentTypeOctetSteam) + { + // 返回失败 + const std::string strMsg = I18N("无效的请求参数,contentType应为application/octet-stream"); + spResp->code = 400; + LOGERROR("upLoadModel():%s", strMsg.c_str()); + spResp->message = strMsg; + return createDtoResponse(Status::CODE_400, spResp); + } + + iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_WRITE ); + if ( !objDbConn.open()) + { + const std::string strMsg = I18N("数据库连接建立失败"); + LOGERROR("upLoadModel():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + // content filegroup category parentCode + bool result = CFileApi::uploadModel(strParentCode, + strFileGroup, + strFileName, + nCategory, + QByteArray(file->getPayload()->getInMemoryData()->c_str(), (int)(file->getPayload()->getInMemoryData()->size())), + &objDbConn); + if (!result) + { + const std::string strMsg = I18N("保存模型失败"); + LOGERROR("upLoadModel():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + spResp->code = 200; + spResp->message = cn_strSuccess; + LOGINFO("uploadModel :%s,fileSize:%zu", file->getFilename()->c_str(), file->getPayload()->getInMemoryData()->size()); + return createDtoResponse(Status::CODE_200, spResp); +} std::shared_ptr -web_server_bi::module_file::CController::getFileByPath( const std::shared_ptr &request ) +web_server_bi::module_file::CController::uploadByString(const std::shared_ptr &request) { - String strPath = request->getQueryParameter( "path" ); - if ( strPath.get() == nullptr || strPath->empty()) + auto spResp = CUploadFileResp::createShared(); + + auto multipart = std::make_shared(request->getHeaders()); + multipart::Reader multipartReader(multipart.get()); + multipartReader.setPartReader("fileGroup", multipart::createInMemoryPartReader(1024l /* max-data-size */)); + multipartReader.setPartReader("fileName", multipart::createInMemoryPartReader(1024l /* max-data-size */)); + multipartReader.setPartReader("str", multipart::createInMemoryPartReader(1024l * 50l /* max-data-size */)); + request->transferBody(&multipartReader); + auto objFileGroup = multipart->getNamedPart("fileGroup"); + auto objFileName = multipart->getNamedPart("fileName"); + auto objStr = multipart->getNamedPart("str"); + + QString strFileGroup, strFileName, strContent; + strFileGroup = objFileGroup->getPayload()->getInMemoryData()->c_str(); + strFileName = objFileName->getPayload()->getInMemoryData()->c_str(); + strContent = objStr->getPayload()->getInMemoryData()->c_str(); + + +// LOGERROR("body is %s",request->readBodyToString()->c_str() ); + +// QUrlQuery objUrlQuery( QUrl::fromPercentEncoding( request->readBodyToString()->c_str() ) ); +// strFileGroup = objUrlQuery.queryItemValue("fileGroup"); +// strFileName = objUrlQuery.queryItemValue("fileName"); +// strContent = objUrlQuery.queryItemValue("str"); + +// strFileGroup = request->getQueryParameter("fileGroup").getValue("").c_str(); +// strFileName = request->getQueryParameter("fileName").getValue("").c_str(); +// strContent = request->getQueryParameter("str").getValue("").c_str(); + + + if( strFileGroup.isEmpty() ) { - const std::string strMsg = I18N( "无效的请求参数" ); - LOGERROR( "getFileByPath():%s", strMsg.c_str()); - return createResponse( Status::CODE_400, strMsg ); + const std::string strMsg = I18N("fileGroup参数为空"); + LOGERROR("uploadByString():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + if( strFileName.isEmpty() ) + { + const std::string strMsg = I18N("fileName参数为空"); + LOGERROR("uploadByString():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + if( strContent.isEmpty() ) + { + const std::string strMsg = I18N("str为空"); + LOGERROR("uploadByString():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + qint64 uploadTime; + QString strSavedFileName = CFileApi::uploadFile(strFileGroup, + strFileName, + strContent.toUtf8(), + nullptr, + &uploadTime); + if (strSavedFileName.isEmpty()) + { + const std::string strMsg = I18N("保存文件失败"); + LOGERROR("uploadFile():%s", strMsg.c_str()); + spResp->code = 500; + spResp->message = strMsg; + return createDtoResponse(Status::CODE_500, spResp); + } + + spResp->data = COneFile::createShared(); + + QString strExt, strId; + int extIndex; + if ((extIndex = strSavedFileName.lastIndexOf(".")) != -1) + { + strId = strSavedFileName.left(extIndex); + strExt = strSavedFileName.mid(extIndex, -1); + } + else + { + const std::string strMsg = I18N("服务器内部错误,文件名错误"); + spResp->code = 502; + LOGERROR("uploadFile():%s", strMsg.c_str()); + spResp->message = strMsg; + return createDtoResponse(Status::CODE_502, spResp); + } + + spResp->data->ext = strExt.toStdString(); + spResp->data->path = (strFileGroup + "/" + strSavedFileName).toStdString(); + spResp->data->size = strContent.size() / 1024.0; + spResp->data->name = strFileName.toStdString(); + spResp->data->id = strId.toStdString(); + spResp->data->fileGroup = strFileGroup.toStdString(); + spResp->data->uploadTime = uploadTime; + spResp->data->url = CFileApi::getUrl(strFileGroup, strSavedFileName).toStdString(); + spResp->data->status = 0; + + spResp->code = 200; + spResp->message = cn_strSuccess; + LOGINFO("uploadByString file:%s,fileSize:%zu", strFileName.toStdString().c_str(), strContent.size()); + return createDtoResponse(Status::CODE_200, spResp);} + +std::shared_ptr +web_server_bi::module_file::CController::getFileByPath(const std::shared_ptr &request) +{ + String strPath = request->getQueryParameter("path"); + if (strPath.get() == nullptr || strPath->empty()) + { + const std::string strMsg = I18N("无效的请求参数"); + LOGERROR("getFileByPath():%s", strMsg.c_str()); + return createResponse(Status::CODE_400, strMsg); } strPath = QUrl::fromPercentEncoding(strPath->c_str()).toStdString(); - //TODO 图片特殊处理 -// String strWidth = request->getQueryParameter( "w" ); -// String strHeight = request->getQueryParameter( "h" ); -// String strQuality = request->getQueryParameter( "q" ); + // TODO 图片特殊处理 + // String strWidth = request->getQueryParameter( "w" ); + // String strHeight = request->getQueryParameter( "h" ); + // String strQuality = request->getQueryParameter( "q" ); QByteArray baContent; - if( !CFileApi::readFileByPath(strPath->c_str(),baContent ) ) + if (!CFileApi::readFileByPath(strPath->c_str(), baContent)) { - const std::string strMsg = I18N( "读取文件失败" ); - LOGERROR( "getFileByPath():%s", strMsg.c_str()); - return createResponse( Status::CODE_500, strMsg ); + const std::string strMsg = I18N("读取文件失败"); + LOGERROR("getFileByPath():%s", strMsg.c_str()); + return createResponse(Status::CODE_500, strMsg); } // Content-Type 处理 - QString strExt,strFilePath = strPath->c_str(); + QString strExt, strFilePath = strPath->c_str(); int extIndex; - if( ( extIndex = strFilePath.lastIndexOf(".")) != -1) + if ((extIndex = strFilePath.lastIndexOf(".")) != -1) { strExt = strFilePath.right(extIndex + 1); } - auto response = createResponse( Status::CODE_200, baContent.toStdString() ); - if( strExt == "json") + auto response = createResponse(Status::CODE_200, baContent.toStdString()); + if (strExt == "json") { - response->putHeader("Content-Type",cn_contentTypeJSON); + response->putHeader("Content-Type", cn_contentTypeJSON); } - else if( strExt == "png" - || strExt == "gif" - || strExt == "jpg" - || strExt == "jpeg") + else if (strExt == "png" || strExt == "gif" || strExt == "jpg" || strExt == "jpeg") { - response->putHeader("Content-Type",QString("image/%1").arg(strExt).toStdString()); + response->putHeader("Content-Type", QString("image/%1").arg(strExt).toStdString()); } return response; } std::shared_ptr -web_server_bi::module_file::CController::getFileByNameAndGroup( const std::shared_ptr &request ) +web_server_bi::module_file::CController::getFileByNameAndGroup(const std::shared_ptr &request) { - String strFileGroup = request->getQueryParameter( "fileGroup" ); - if ( strFileGroup.get() == nullptr || strFileGroup->empty()) + String strFileGroup = request->getQueryParameter("fileGroup"); + if (strFileGroup.get() == nullptr || strFileGroup->empty()) { strFileGroup = "others"; } strFileGroup = QUrl::fromPercentEncoding(strFileGroup->c_str()).toStdString(); - - String strFileName = request->getQueryParameter( "fileName" ); - if ( strFileName.get() == nullptr || strFileName->empty()) + String strFileName = request->getQueryParameter("fileName"); + if (strFileName.get() == nullptr || strFileName->empty()) { - const std::string strMsg = I18N( "无效的请求参数" ); - LOGERROR( "getFileByNameAndGroup():%s", strMsg.c_str()); - return createResponse( Status::CODE_400, strMsg ); + const std::string strMsg = I18N("无效的请求参数"); + LOGERROR("getFileByNameAndGroup():%s", strMsg.c_str()); + return createResponse(Status::CODE_400, strMsg); } strFileName = QUrl::fromPercentEncoding(strFileName->c_str()).toStdString(); - String strPath = strFileGroup + "/" + strFileName; - //TODO 图片特殊处理 -// String strWidth = request->getQueryParameter( "w" ); -// String strHeight = request->getQueryParameter( "h" ); -// String strQuality = request->getQueryParameter( "q" ); + // TODO 图片特殊处理 + // String strWidth = request->getQueryParameter( "w" ); + // String strHeight = request->getQueryParameter( "h" ); + // String strQuality = request->getQueryParameter( "q" ); QByteArray baContent; - if( !CFileApi::readFileByPath(strPath->c_str(),baContent ) ) + if (!CFileApi::readFileByPath(strPath->c_str(), baContent)) { - const std::string strMsg = I18N( "读取文件失败" ); - LOGERROR( "getFileByNameAndGroup():%s", strMsg.c_str()); - return createResponse( Status::CODE_500, strMsg ); + if (!CFileApi::readFileByFileNameAndGroup(strFileName->c_str(),strFileGroup->c_str(), baContent)) + { + const std::string strMsg = I18N("读取文件失败"); + LOGERROR("getFileByNameAndGroup():%s", strMsg.c_str()); + return createResponse(Status::CODE_500, strMsg); + } } + + // Content-Type 处理 - QString strExt,strFilePath = strPath->c_str(); + QString strExt, strFilePath = strPath->c_str(); int extIndex; - if( ( extIndex = strFilePath.lastIndexOf(".")) != -1) + if ((extIndex = strFilePath.lastIndexOf(".")) != -1) { strExt = strFilePath.right(extIndex + 1); } - auto response = createResponse( Status::CODE_200, baContent.toStdString() ); - if( strExt == "json") + auto response = createResponse(Status::CODE_200, baContent.toStdString()); + if (strExt == "json") { - response->putHeader("Content-Type",cn_contentTypeJSON); + response->putHeader("Content-Type", cn_contentTypeJSON); } - else if( strExt == "png" - || strExt == "gif" - || strExt == "jpg" - || strExt == "jpeg") + else if (strExt == "png" || strExt == "gif" || strExt == "jpg" || strExt == "jpeg") { - response->putHeader("Content-Type",QString("image/%1").arg(strExt).toStdString()); + response->putHeader("Content-Type", QString("image/%1").arg(strExt).toStdString()); } return response; } std::shared_ptr -web_server_bi::module_file::CController::getContentByPath( const std::shared_ptr &request ) +web_server_bi::module_file::CController::getContentByPath(const std::shared_ptr &request) { - String strPath = request->getQueryParameter( "path" ); + String strPath = request->getQueryParameter("path"); auto spResp = CGetFileResp::createShared(); - if ( strPath.get() == nullptr || strPath->empty()) + if (strPath.get() == nullptr || strPath->empty()) { - const std::string strMsg = I18N( "无效的请求参数" ); - LOGERROR( "getFileByPath():%s", strMsg.c_str()); + const std::string strMsg = I18N("无效的请求参数"); + LOGERROR("getFileByPath():%s", strMsg.c_str()); spResp->message = strMsg; spResp->code = 400; - return createDtoResponse( Status::CODE_400, spResp ); + return createDtoResponse(Status::CODE_400, spResp); } strPath = QUrl::fromPercentEncoding(strPath->c_str()).toStdString(); - //TODO 图片特殊处理 -// String strWidth = request->getQueryParameter( "w" ); -// String strHeight = request->getQueryParameter( "h" ); -// String strQuality = request->getQueryParameter( "q" ); + // TODO 图片特殊处理 + // String strWidth = request->getQueryParameter( "w" ); + // String strHeight = request->getQueryParameter( "h" ); + // String strQuality = request->getQueryParameter( "q" ); QByteArray baContent; - if( !CFileApi::readFileByPath(strPath->c_str(),baContent ) ) + if (!CFileApi::readFileByPath(strPath->c_str(), baContent)) { - const std::string strMsg = I18N( "读取文件失败" ); - LOGERROR( "getContentFileByPath():%s", strMsg.c_str()); + const std::string strMsg = I18N("读取文件失败"); + LOGERROR("getContentFileByPath():%s", strMsg.c_str()); spResp->message = strMsg; spResp->code = 500; - return createDtoResponse( Status::CODE_500, spResp ); + return createDtoResponse(Status::CODE_500, spResp); } // Content-Type 处理 - QString strExt,strFilePath = strPath->c_str(); + QString strExt, strFilePath = strPath->c_str(); int extIndex; - if( ( extIndex = strFilePath.lastIndexOf(".")) != -1) + if ((extIndex = strFilePath.lastIndexOf(".")) != -1) { strExt = strFilePath.right(extIndex + 1); } @@ -275,17 +469,14 @@ web_server_bi::module_file::CController::getContentByPath( const std::shared_ptr spResp->message = cn_strSuccess; spResp->data = baContent.toStdString(); - auto response = createDtoResponse( Status::CODE_200, spResp ); - if( strExt == "json") + auto response = createDtoResponse(Status::CODE_200, spResp); + if (strExt == "json") { - response->putHeader("Content-Type",cn_contentTypeJSON); + response->putHeader("Content-Type", cn_contentTypeJSON); } - else if( strExt == "png" - || strExt == "gif" - || strExt == "jpg" - || strExt == "jpeg") + else if (strExt == "png" || strExt == "gif" || strExt == "jpg" || strExt == "jpeg") { - response->putHeader("Content-Type",QString("image/%1").arg(strExt).toStdString()); + response->putHeader("Content-Type", QString("image/%1").arg(strExt).toStdString()); } return response; @@ -295,8 +486,8 @@ std::shared_ptr web_server_bi::module_file::CController::getSystemTime() { QString resp = QString("{\"code\":200,\"message\":\"%1\",\"data\":%2}") - .arg(cn_strSuccess.c_str()) - .arg(QDateTime::currentMSecsSinceEpoch()); + .arg(cn_strSuccess.c_str()) + .arg(QDateTime::currentMSecsSinceEpoch()); - return createResponse( Status::CODE_200, resp.toStdString()); + return createResponse(Status::CODE_200, resp.toStdString()); } diff --git a/platform/src/service/web_server_bi/module_file/CController.h b/platform/src/service/web_server_bi/module_file/CController.h index fbcf2aea..dca48019 100644 --- a/platform/src/service/web_server_bi/module_file/CController.h +++ b/platform/src/service/web_server_bi/module_file/CController.h @@ -28,18 +28,45 @@ public: public: + /** + * @brief 上传文件 + */ ENDPOINT( "POST", "/api-common/config/uploadFile",uploadFile, REQUEST( std::shared_ptr, request ) ); + /** + * @brief 上传3d模型 + */ + ENDPOINT( "POST", "/api-common/config/upLoadModel",upLoadModel, + REQUEST( std::shared_ptr, request ) ); + + /** + * @brief 通过字符串上传配置文件 + */ + ENDPOINT( "POST", "/api-file/file/upload/uploadByString",uploadByString, + REQUEST( std::shared_ptr, request ) ); + + /** + * @brief 通过路径获取文件 + */ ENDPOINT( "GET", "/api-file/file/get/getFileByPath", getFileByPath, REQUEST( std::shared_ptr, request ) ); + /** + * @brief 通过分组和文件名获取文件 + */ ENDPOINT( "GET", "/api-file/file/get/getFileByNameAndGroup", getFileByNameAndGroup, REQUEST( std::shared_ptr, request ) ); + /** + * @brief 通过路径获取文件内容 + */ ENDPOINT( "GET", "/api-file/file/get/getContentByPath", getContentByPath, REQUEST( std::shared_ptr, request ) ); + /** + * @brief 获取系统时间 + */ ENDPOINT( "GET", "/api-sys/getSystemTime", getSystemTime ); }; diff --git a/platform/src/service/web_server_bi/module_file/CDTO.h b/platform/src/service/web_server_bi/module_file/CDTO.h index 3bc48050..9317d651 100644 --- a/platform/src/service/web_server_bi/module_file/CDTO.h +++ b/platform/src/service/web_server_bi/module_file/CDTO.h @@ -35,6 +35,14 @@ class CUploadFileResp : public oatpp::DTO DTO_FIELD( Object < COneFile >, data ); }; +class CUploadModelResp : public oatpp::DTO +{ + DTO_INIT( CUploadModelResp, DTO ); + DTO_FIELD( Int32, code ); + DTO_FIELD( String, message ); + DTO_FIELD( Object < COneFile >, data ); +}; + class CGetFileResp : public oatpp::DTO { DTO_INIT( CGetFileResp, DTO ); diff --git a/platform/src/service/web_server_bi/module_file/CModule.cpp b/platform/src/service/web_server_bi/module_file/CModule.cpp index 8fb9612e..55aeccd0 100644 --- a/platform/src/service/web_server_bi/module_file/CModule.cpp +++ b/platform/src/service/web_server_bi/module_file/CModule.cpp @@ -4,6 +4,7 @@ #include "oatpp/web/server/HttpRouter.hpp" #include "CController.h" #include "CModule.h" +#include "SyncthingMngThread.h" #include "pub_sysinfo_api/SysInfoApi.h" @@ -20,6 +21,46 @@ bool CModule::init() OATPP_COMPONENT( std::shared_ptr, router, "simpleRouter" ); router->addController( std::make_shared()); + bool isSingleNode = false; + { + iot_public::CSysInfoInterfacePtr ptrSysInfo; + if ( iot_public::createSysInfoInstance( ptrSysInfo ) == false ) + { + LOGFATAL( "createSysInfoInstance() return false !" ); + return false; + } + + //< 获取本机域ID和主机名 + { + iot_public::SNodeInfo stLocalNodeInfo; + if ( iotSuccess != ptrSysInfo->getLocalNodeInfo( stLocalNodeInfo )) + { + LOGFATAL( "getLocalNodeInfo() failed !" ); + return false; + } + + if( "127.0.0.1" == stLocalNodeInfo.strNic1Addr) + { + isSingleNode = true; + } + } + + } + if( !isSingleNode ) + { + m_ptrSyncthingMngThread = boost::make_shared(); + if ( m_ptrSyncthingMngThread == nullptr ) + { + LOGERROR( "cannot syncthingmngthread class" ); + return false; + } + + if ( false == m_ptrSyncthingMngThread->init()) + { + LOGERROR( "cannot initialize syncthingmngthread class " ); + return false; + } + } return true; } @@ -39,6 +80,12 @@ bool CModule::clean() //< todo 貌似没有 addController 的逆操作 //< todo 清理业务资源 + if ( m_ptrSyncthingMngThread != nullptr ) + { + m_ptrSyncthingMngThread->quit(); + m_ptrSyncthingMngThread.reset(); + } + return true; } diff --git a/platform/src/service/web_server_bi/module_file/CModule.h b/platform/src/service/web_server_bi/module_file/CModule.h index b1c8727c..0905e26a 100644 --- a/platform/src/service/web_server_bi/module_file/CModule.h +++ b/platform/src/service/web_server_bi/module_file/CModule.h @@ -2,6 +2,8 @@ #include "../include/BaseModule.h" +class SyncthingMngThread; +typedef boost::shared_ptr SyncthingMngThreadPtr; namespace web_server_bi { namespace module_file { @@ -16,6 +18,7 @@ public: bool redundantSwitch( bool bMaster, bool bSlave ) override; bool clean() override; static boost::shared_ptr create(); + SyncthingMngThreadPtr m_ptrSyncthingMngThread = nullptr; }; diff --git a/platform/src/service/web_server_bi/module_file/SyncthingMngThread.cpp b/platform/src/service/web_server_bi/module_file/SyncthingMngThread.cpp new file mode 100644 index 00000000..9719afd5 --- /dev/null +++ b/platform/src/service/web_server_bi/module_file/SyncthingMngThread.cpp @@ -0,0 +1,342 @@ +#include "SyncthingMngThread.h" + +#include "oatpp/web/client/HttpRequestExecutor.hpp" +#include "oatpp/network/tcp/client/ConnectionProvider.hpp" + +#include "oatpp/core/macro/component.hpp" + +#include "oatpp/parser/json/mapping/ObjectMapper.hpp" + +#include "pub_logger_api/logger.h" +#include "../include/ServerApi.h" +#include "pub_utility_api/FileUtil.h" + +#include "MessageChannel.h" + +#include "rapidjson/document.h" +#include "Common.h" +#include +#include +#include +#include + +#define SYNCTHING_GUI_APIKEY EMS_DEFAULT_PASSWD + + +SyncthingMngThread::SyncthingMngThread() : iot_public::CTimerThreadBase( "SyncthingMngThread", 1000 ) +{ + m_strSyncthingHomePath = iot_public::CFileUtil::getSimplePath( iot_public::CFileUtil::getCurModuleDir() + "../../data/syncthing_home").c_str(); + m_strWebserverDataPath = iot_public::CFileUtil::getSimplePath(iot_public::CFileUtil::getCurModuleDir() + "../../data/web_server_files"); + +} + + +SyncthingMngThread::~SyncthingMngThread() +{ + if(!stopSyncthing()) + { + LOGERROR("cannot stop syncthing"); + } +} + +bool SyncthingMngThread::init() +{ + if(!stopSyncthing()) + { + LOGERROR("cannot stop syncthing"); + return false; + } + + if( !startSyncthing() ) + { + LOGERROR("cannot start syncthing "); + return false; + } + if( m_comm.addSub(web_server_bi::getServerApi()->getRunAppInfo().nAppId,CH_WEB_FILE_SYNCTHING_BROADCAST) ) + { + LOGINFO( "订阅通道:%d[CH_WEB_FILE_SYNCTHING_BROADCAST]成功", CH_WEB_FILE_SYNCTHING_BROADCAST ); + } + else + { + LOGERROR( "订阅通道:%d[CH_WEB_FILE_SYNCTHING_BROADCAST]失败", CH_WEB_FILE_SYNCTHING_BROADCAST ); + return false; + } + + { + OATPP_COMPONENT( std::shared_ptr, objectMapper ); + + auto connectionProvider = oatpp::network::tcp::client::ConnectionProvider::createShared({"127.0.0.1", 8384}); + auto requestExecutor = oatpp::web::client::HttpRequestExecutor::createShared(connectionProvider); + m_client = CSynctingRestOp::createShared(requestExecutor, objectMapper); + } + + resume(); + return true; +} + +int SyncthingMngThread::beforeExecute() +{ + m_runAppInfo = web_server_bi::getServerApi()->getRunAppInfo(); + + int cnt = 0; + while(!getDeviceId()) + { + LOGERROR("cannot get device id,retryCnt:%d",cnt); + QThread::msleep(500); + if(++cnt > 20) + { + LOGERROR("beyond limited times to get device id, stop syncthing"); + stopSyncthing(); + return iotFailed; + } + } + return iotSuccess; +} + +bool SyncthingMngThread::startSyncthing() +{ + QString syncthingPath = iot_public::CFileUtil::getPathOfBinFile("syncthing").c_str(); + + QStringList args; + args << QString("--home=%1").arg(m_strSyncthingHomePath) + << QString("--gui-apikey=%1").arg(SYNCTHING_GUI_APIKEY) +#ifdef OS_WINDOWS + << "--no-console" +#endif + << "--no-browser" + << "--no-default-folder" + << "--no-upgrade"; + + if( !QProcess::startDetached(syncthingPath,args)) + { + LOGERROR("cannot start detached syncthing srv!"); + return false; + } + + return true; +} + +bool SyncthingMngThread::stopSyncthing() +{ + QString syncthingPath = iot_public::CFileUtil::getPathOfBinFile("syncthing").c_str(); + + QStringList args; + args << "cli" + << QString("--home=%1").arg(m_strSyncthingHomePath) + << "operations" + << "shutdown"; + + QProcess syncthing; + + syncthing.start(syncthingPath, args); + if (!syncthing.waitForStarted()) + { + LOGERROR("cannot start syncthing cli tool to terminate syncthing srv."); + return false; + } + + if (!syncthing.waitForFinished()) + { + LOGERROR("cannot terminate syncthing cli tool."); + return false; + } + return true; +} + +void SyncthingMngThread::broadcast() +{ + + iot_net::CMbMessage msg; + msg.setData( m_strHandshake.c_str(), m_strHandshake.size() ); + msg.setSubject(m_runAppInfo.nAppId,CH_WEB_FILE_SYNCTHING_BROADCAST); + + if(!m_comm.sendMsgToDomain(msg)){ + LOGERROR("cannot send broadcast msg"); + } +} + + +void SyncthingMngThread::genSyncthingCfg() +{ + // 生成对象 + oatpp::List> devices = oatpp::List>::createShared(); + { + auto currentDevie = CDeviceDTO::createShared(); + currentDevie->deviceID = m_strDeviceId; + devices->insert( devices->end(),currentDevie); + + for(auto it = m_mapDeviceId.begin(); it != m_mapDeviceId.end(); ++it) + { + auto OneDevice = CDeviceDTO::createShared(); + OneDevice->deviceID = it->first; + devices->insert( devices->end(),OneDevice); + } + } + + oatpp::List> folders = oatpp::List>::createShared(); + { + auto oneFolder = CFolderDTO::createShared(); + oneFolder->id = "web_server_files"; + oneFolder->path = m_strWebserverDataPath; + + for(auto it = m_mapDeviceId.begin(); it != m_mapDeviceId.end(); ++it) + { + auto oneDevice = CFolderDeivceDTO::createShared(); + oneDevice->deviceId = it->first; + oneFolder->devices->insert( oneFolder->devices->end(),oneDevice); + } + folders->insert(folders->end(),oneFolder); + } + + OATPP_COMPONENT(std::shared_ptr,objectMapper); + + auto devicesJson = objectMapper->writeToString(devices); + auto folderJson = objectMapper->writeToString(folders); + + char retryCnt = 0; + bool isRequestCorrent = false; + while(!isRequestCorrent && retryCnt < 60){ + try{ + // 先设置devices,再设置folder + auto code = m_client->putDevices(SYNCTHING_GUI_APIKEY,devicesJson)->getStatusCode(); + if( code != 200) + { + LOGERROR("cannot put devices of syncthing! code:[%d]",code); + return ; + } + + code = m_client->putFolders(SYNCTHING_GUI_APIKEY,folderJson)->getStatusCode(); + if( code != 200) + { + LOGERROR("cannot put folders of syncthing! code:[%d]",code); + return ; + } + if(retryCnt != 0) + { + LOGINFO("genSyncthingCfg done! total retry cnt:%d",retryCnt); + } + isRequestCorrent = true; + }catch(const std::exception &exc){ + LOGINFO("catch exception:%s,retry cnt:[%d]",exc.what(),retryCnt); + ++retryCnt; + QThread::msleep(500); // 500 * 60 最多30秒钟 + continue; + } + + } +} + +void SyncthingMngThread::deleteDevice(const std::string &deviceId) +{ + auto code = m_client->deleteDevice(SYNCTHING_GUI_APIKEY,deviceId)->getStatusCode(); + if( code != 200) + { + LOGERROR("cannot delete deviceId:[%s]! code:[%d]",deviceId.c_str(),code); + return ; + } +} + +bool SyncthingMngThread::getDeviceId() +{ + QString syncthingPath = iot_public::CFileUtil::getPathOfBinFile("syncthing").c_str(); + + QStringList args; + args << QString("--home=%1").arg(m_strSyncthingHomePath) + << "--device-id"; + + QProcess syncthing; + + syncthing.start(syncthingPath, args); + if (!syncthing.waitForStarted()){ + LOGERROR("cannot start syncthing srv to get device id"); + return false; + } + + if (!syncthing.waitForFinished()){ + LOGERROR("cannot terminate syncthing srv to get device id"); + return false; + } + + if( syncthing.exitCode() != 0) + { + LOGERROR("cannot terminate syncthing srv to get device id"); + return false; + } + + m_strDeviceId = syncthing.readAll().toStdString(); + m_strDeviceId = QString(m_strDeviceId.c_str()).trimmed().toStdString(); + LOGINFO("current syncthing deviceId is %s",m_strDeviceId.c_str()); + + m_strHandshake = QString("{\"DEVICE_ID\":\"%1\"}").arg(m_strDeviceId.c_str()).toStdString(); + + return true; +} + +void SyncthingMngThread::execute() +{ + broadcast(); + + iot_net::CMbMessage objMsg; + bool bNeedRefresh = false; + std::list listDeviceId; + + while( m_comm.recvMsg(objMsg, 0 ) ) + { + const std::string strRcvData((char *) objMsg.getDataPtr(), objMsg.getDataSize()); + using namespace rapidjson; + Document d; + d.Parse(strRcvData.c_str()); + if ( d.HasParseError() ) + { + continue; + } + + Value& s = d["DEVICE_ID"]; + if( !s.IsString() ) + { + continue; + } + + std::string device_id = s.GetString(); + if( device_id == m_strDeviceId) + { + continue; + } + else + { + listDeviceId.push_back(device_id); + if(m_mapDeviceId.find(device_id) == m_mapDeviceId.end()) + { + LOGINFO("device id:[%s] added!",device_id.c_str()); + bNeedRefresh = true; + } + } + } + + for(auto it = listDeviceId.begin(); it != listDeviceId.end(); ++it) + { + m_mapDeviceId[*it] = 5; + } + + for(auto it = m_mapDeviceId.begin(); it != m_mapDeviceId.end(); ) + { + it->second -= 1; + if( it->second <= 0 ) + { + LOGINFO("device id:[%s] removed!",it->first.c_str()); + deleteDevice(it->first); + it = m_mapDeviceId.erase(it); + bNeedRefresh = true; + } + else + { + ++it; + } + } + + if( bNeedRefresh ) + { + genSyncthingCfg(); + } +} + diff --git a/platform/src/service/web_server_bi/module_file/SyncthingMngThread.h b/platform/src/service/web_server_bi/module_file/SyncthingMngThread.h new file mode 100644 index 00000000..6626ee2b --- /dev/null +++ b/platform/src/service/web_server_bi/module_file/SyncthingMngThread.h @@ -0,0 +1,50 @@ +#ifndef SYNCTHINGMNGTHREAD_H +#define SYNCTHINGMNGTHREAD_H + +#include "pub_utility_api/TimerThreadBase.h" +#include +#include +#include "net_msg_bus_api/CMbCommunicator.h" +#include "pub_sysinfo_api/SysInfoBase.h" + +#include "SyncthingRestOp.hpp" + +class SyncthingMngThread : public iot_public::CTimerThreadBase +{ +public: + + SyncthingMngThread(); + + ~SyncthingMngThread(); + + int beforeExecute() override; + void execute() override; + + bool init(); + +private: + bool startSyncthing(); + bool stopSyncthing(); + + void broadcast(); + void genSyncthingCfg(); + void deleteDevice(const std::string& deviceId); + bool getDeviceId(); + + std::string m_strDeviceId; + std::string m_strHandshake; + + QString m_strSyncthingHomePath; + std::string m_strWebserverDataPath; + + std::map m_mapDeviceId; + iot_net::CMbCommunicator m_comm; + iot_public::SRunAppInfo m_runAppInfo; + std::shared_ptr m_client; + +}; + +typedef boost::shared_ptr SyncthingMngThreadPtr; + + +#endif // SYNCTHINGMNGTHREAD_H diff --git a/platform/src/service/web_server_bi/module_file/SyncthingRestDTO.hpp b/platform/src/service/web_server_bi/module_file/SyncthingRestDTO.hpp new file mode 100644 index 00000000..22d9fa2c --- /dev/null +++ b/platform/src/service/web_server_bi/module_file/SyncthingRestDTO.hpp @@ -0,0 +1,115 @@ +#pragma once + +#include "oatpp/core/Types.hpp" +#include "oatpp/core/macro/codegen.hpp" + +#include OATPP_CODEGEN_BEGIN( DTO ) + + + +class COneFile : public oatpp::DTO +{ + DTO_INIT( COneFile, DTO ); + DTO_FIELD( String, ext ); +// DTO_FIELD( String, uid ); + DTO_FIELD( String, path ); + DTO_FIELD( Int32, size ); + DTO_FIELD( String, name ); +// DTO_FIELD( String, businessId ); +// DTO_FIELD( String, remark ); + DTO_FIELD( String, id ); + DTO_FIELD( String, fileGroup ); + DTO_FIELD( Int64, uploadTime ); + DTO_FIELD( String, url ); + DTO_FIELD( Int32, status ); +}; + + +class CUploadFileResp : public oatpp::DTO +{ + DTO_INIT( CUploadFileResp, DTO ); + DTO_FIELD( Int32, code ); + DTO_FIELD( String, message ); + DTO_FIELD( Object < COneFile >, data ); +}; + +class CGetFileResp : public oatpp::DTO +{ + DTO_INIT( CGetFileResp, DTO ); + DTO_FIELD( Int32, code ); + DTO_FIELD( String, message ); + DTO_FIELD( String, data ); +}; + + +//{ +//"deviceID": "F46QWSG-SYDYEUL-PVCODDC-QXMANDQ-VYP76DQ-L2CLSHN-LBQAJJE-XTK6VQV", +//"name": "centosyh1", +//"addresses": [ +// "dynamic" +//], +//"compression": "metadata", +//"certName": "", +//"introducer": false, +//"skipIntroductionRemovals": false, +//"introducedBy": "", +//"paused": false, +//"allowedNetworks": [], +//"autoAcceptFolders": false, +//"maxSendKbps": 0, +//"maxRecvKbps": 0, +//"ignoredFolders": [], +//"maxRequestKiB": 0, +//"untrusted": false, +//"remoteGUIPort": 0 +//} + + +class CDeviceDTO : public oatpp::DTO +{ + DTO_INIT( CDeviceDTO, DTO ); + DTO_FIELD( String, deviceID ) = ""; + DTO_FIELD( String, name ) = ""; + DTO_FIELD( List, addresses ) = {"dynamic"}; + DTO_FIELD( String, compression ) = "metadata"; + DTO_FIELD( String, certName ) = ""; + DTO_FIELD( Boolean, introducer ) = false; + DTO_FIELD( Boolean, skipIntroductionRemovals ) = false; + DTO_FIELD( String, introducedBy ) = ""; + DTO_FIELD( Boolean, paused ) = false; + DTO_FIELD( List, allowedNetworks ) = {}; + DTO_FIELD( Boolean, autoAcceptFolders ) = false; + DTO_FIELD( Int32, maxSendKbps ) = 0; + DTO_FIELD( Int32, maxRecvKbps ) = 0; + DTO_FIELD( List, ignoredFolders ) = {}; + DTO_FIELD( Int32, maxRequestKiB ) = 0; + DTO_FIELD( Boolean, untrusted ) = false; + DTO_FIELD( Int32, remoteGUIPort ) = 0; +}; + + +class CFolderDeivceDTO : public oatpp::DTO +{ + DTO_INIT( CFolderDeivceDTO, DTO ); + DTO_FIELD( String, deviceId ) = ""; + DTO_FIELD( String, introducedBy ) = ""; + DTO_FIELD( String, encryptionPassword ) = ""; +}; + +// 其他属性忽略了,有需要再加 +class CFolderDTO : public oatpp::DTO +{ + DTO_INIT( CFolderDTO, DTO ); + DTO_FIELD( String, id ) = ""; + DTO_FIELD( String, path ) = ""; + DTO_FIELD( List >, devices ) = {}; + +}; + + + + + + + +#include OATPP_CODEGEN_END( DTO ) diff --git a/platform/src/service/web_server_bi/module_file/SyncthingRestOp.hpp b/platform/src/service/web_server_bi/module_file/SyncthingRestOp.hpp new file mode 100644 index 00000000..c61a2bfb --- /dev/null +++ b/platform/src/service/web_server_bi/module_file/SyncthingRestOp.hpp @@ -0,0 +1,23 @@ +#ifndef SYNCTHINGRESTOP_HPP +#define SYNCTHINGRESTOP_HPP + +#include + +#include "oatpp/web/client/ApiClient.hpp" +#include "oatpp/core/macro/codegen.hpp" + +class CSynctingRestOp : public oatpp::web::client::ApiClient { +#include OATPP_CODEGEN_BEGIN(ApiClient) + + API_CLIENT_INIT(CSynctingRestOp) + + API_CALL("PUT", "rest/config/devices", putDevices,HEADER(String, guiApiKey, "X-API-Key"),BODY_STRING( String,devices) ) + API_CALL("PUT", "rest/config/folders", putFolders,HEADER(String, guiApiKey, "X-API-Key"),BODY_STRING(String,folders) ) + API_CALL("DELETE", "rest/config/devices/{deviceId}", deleteDevice,HEADER(String, guiApiKey, "X-API-Key"), PATH(String, deviceId)) + + + +#include OATPP_CODEGEN_END(ApiClient) +}; + +#endif // SYNCTHINGRESTOP_HPP diff --git a/platform/src/service/web_server_bi/module_file/module_file.pro b/platform/src/service/web_server_bi/module_file/module_file.pro index 476b0458..c8e51370 100644 --- a/platform/src/service/web_server_bi/module_file/module_file.pro +++ b/platform/src/service/web_server_bi/module_file/module_file.pro @@ -10,10 +10,14 @@ HEADERS += \ CController.h \ CDTO.h \ CModule.h \ + SyncthingMngThread.h \ + SyncthingRestOp.hpp \ + SyncthingRestDTO.hpp SOURCES += \ CModule.cpp \ CController.cpp \ + SyncthingMngThread.cpp #静态库,不要连接,统一在server中连接 diff --git a/platform/src/service/web_server_bi/module_model/CController.cpp b/platform/src/service/web_server_bi/module_model/CController.cpp index e5230cc5..e4b22a0e 100644 --- a/platform/src/service/web_server_bi/module_model/CController.cpp +++ b/platform/src/service/web_server_bi/module_model/CController.cpp @@ -563,7 +563,27 @@ CController::getPointsByDeviceCode( const String& deviceCode, const String& poin // 查询测点信息 QSqlQuery objQuery; - QString sSql = ""; + QString sSql = QString("select t2.TAG_NAME from dev_info as t1 " + " left join sys_model_sub_system_info as t2 " + " on t1.SUB_SYSTEM = t2.SUB_SYSTEM_ID " + " where t1.TAG_NAME='%1';").arg(deviceCode.get()->c_str()); + if ( !objDb.execute(sSql,objQuery) ) + { + pPoint->code = 500; + pPoint->message = "查询关系库表 " + sTableName.toStdString() + " 失败"; + LOGERROR("%s",pPoint->message->c_str()); + return createDtoResponse( Status::CODE_200, pPoint ); + } + QString sub_system_tag; + while ( objQuery.next() ) + { + sub_system_tag = objQuery.value(0).toString(); + } + QString location_tag = QString(deviceCode->c_str()).split('.')[0]; + + objQuery.clear(); + sSql.clear(); + if ( bDigital ) sSql = QString("select tag_name,description,state_text_name from %1 where device='%2'").arg(sTableName).arg(deviceCode.get()->c_str()); else @@ -582,6 +602,7 @@ CController::getPointsByDeviceCode( const String& deviceCode, const String& poin pData->tagCode = sTableName.toStdString() + "." + objQuery.value(0).toString().toStdString() + ".value"; //pData->tagCode = objQuery.value(0).toString().toStdString(); pData->tagName = objQuery.value(1).toString().toStdString(); + pData->details = (location_tag + "." + sub_system_tag).toStdString(); pData->name = pData->tagName; pData->coefficient = 1; pData->pointType = std::stoi(pointType.get()->c_str(),nullptr,0); diff --git a/platform/src/service/web_server_bi/module_page/Common.cpp b/platform/src/service/web_server_bi/module_page/Common.cpp index 05fe1aa3..bbc797b7 100644 --- a/platform/src/service/web_server_bi/module_page/Common.cpp +++ b/platform/src/service/web_server_bi/module_page/Common.cpp @@ -18,6 +18,7 @@ namespace module_page //< 云平台中规则为config/租户id/文件类型,我们不区分租户,假定租户id为1 const QString &cn_strJsonFileGrp = QStringLiteral( "config/1/json" ); +const QString &cn_str3DFileGrp = QStringLiteral( "3D" ); //< 存数据库时将 full 换成 short,响应前端时把 short 换成 full,目的: //< 1、数据库中不存文件接口,以防接口改名,老工程无法兼容 @@ -65,7 +66,18 @@ QString fillOnePrimitive( const QSqlQuery &objQuery, dto::COnePrimitive::Wrapper strTemp = objQuery.value( WebPrimitiveCol::content_path ).toString(); if ( !strTemp.isEmpty()) - spOut->contentPath = CFileApi::getUrl( cn_strJsonFileGrp, strTemp ).toStdString(); + { + QString fileGrp; + if( spOut->category == 6) + { + fileGrp = cn_str3DFileGrp; + } + else + { + fileGrp = cn_strJsonFileGrp; + } + spOut->contentPath = CFileApi::getUrl( fileGrp, strTemp ).toStdString(); + } strTemp = objQuery.value( WebPrimitiveCol::icon_info ).toString(); if ( !strTemp.isEmpty()) diff --git a/platform/src/service/web_server_bi/module_page/Common.hpp b/platform/src/service/web_server_bi/module_page/Common.hpp index 7c437d09..0a9af2ab 100644 --- a/platform/src/service/web_server_bi/module_page/Common.hpp +++ b/platform/src/service/web_server_bi/module_page/Common.hpp @@ -22,6 +22,7 @@ namespace module_page { extern const QString &cn_strJsonFileGrp; +extern const QString &cn_str3DFileGrp; extern const QString &cn_strIconPathShort; extern const QString cn_strIconPathFull; diff --git a/platform/src/service/web_server_bi/module_page/SimpleCtrlPage.cpp b/platform/src/service/web_server_bi/module_page/SimpleCtrlPage.cpp index de2adfe4..b98e9812 100644 --- a/platform/src/service/web_server_bi/module_page/SimpleCtrlPage.cpp +++ b/platform/src/service/web_server_bi/module_page/SimpleCtrlPage.cpp @@ -465,7 +465,7 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) } //< 是否显示区域 - if ( spRootPage->showArea.get() != nullptr && spRootPage->showArea != 0 ) + if ( spRootPage->showArea.get() != nullptr && ( nReqPageType == 1 || spRootPage->showArea != 0 ) ) { //< location strSql = "SELECT location_id,description,plocation_id FROM sys_model_location_info"; @@ -492,7 +492,11 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) mapAllPage.insert( strId, spOneData ); //< todo 当前未判权限,只有有权限的才加入 spRespData - spRespData->push_back( spOneData ); + if( nReqPageType != 1 ) // 3d时跳过 + { + spRespData->push_back( spOneData ); + } + } } else @@ -517,7 +521,11 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) mapAllPage.insert( strId, spOneData ); //< todo 当前未判权限,只有有权限的才加入 spRespData - spRespData->push_back( spOneData ); + if( nReqPageType != 1 ) // 3d时跳过 + { + spRespData->push_back( spOneData ); + } + } } else @@ -533,6 +541,9 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) const QString strId = objQuery.value( WebPageCol::id ).toString(); const QString strAreaCode = objQuery.value( WebPageCol::area_code ).toString(); + LOGERROR("strId:%s,strAreaCode:%s",strId.toStdString().c_str(),strAreaCode.toStdString().c_str() ); + + auto itMap = mapAllPage.find( strAreaCode ); if ( itMap == mapAllPage.end()) @@ -545,6 +556,7 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) } else if ( itMap.value()->pageId.get() != nullptr && !( itMap.value()->pageId->empty())) { + auto &spOneData = itMap.value(); QString strDelId, strDelPageName; @@ -573,6 +585,11 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) else { fillOnePage( objQuery, itMap.value()); + if( nReqPageType == 1) + { + spRespData->push_back( itMap.value() ); + } + } } } @@ -610,6 +627,7 @@ CSimpleCtrlPage::selectList( const std::shared_ptr &spRequest ) //< 查找游离页面 for ( auto const &spOneData:vecNonAreaPage ) { + LOGERROR("check here"); if ( spOneData->parentCode.get() == nullptr || spOneData->parentCode->empty() || !mapAllPage.contains( spOneData->parentCode->c_str())) { diff --git a/platform/src/service/web_server_bi/module_page/SimpleCtrlPrimitive.cpp b/platform/src/service/web_server_bi/module_page/SimpleCtrlPrimitive.cpp index 0eb9c6a4..4db70aff 100644 --- a/platform/src/service/web_server_bi/module_page/SimpleCtrlPrimitive.cpp +++ b/platform/src/service/web_server_bi/module_page/SimpleCtrlPrimitive.cpp @@ -736,7 +736,19 @@ CSimpleCtrlPrimitive::updateById( const std::shared_ptr &spRequ spOneData->primitiveName = strCurPrimitiveName.toStdString(); if ( !strCurContentPath.isEmpty()) - spOneData->contentPath = CFileApi::getUrl( cn_strJsonFileGrp, strCurContentPath ).toStdString(); + { + + QString fileGrp; + if( nCurCategory == 6) + { + fileGrp = cn_str3DFileGrp; + } + else + { + fileGrp = cn_strJsonFileGrp; + } + spOneData->contentPath = CFileApi::getUrl( fileGrp, strCurContentPath ).toStdString(); + } if ( !strCurIconInfo.isEmpty()) //< 将iconPath内容还原,详见常量定义注释 diff --git a/platform/src/service/web_server_bi/server/FileApi.cpp b/platform/src/service/web_server_bi/server/FileApi.cpp index 164cf2bd..b77398c7 100644 --- a/platform/src/service/web_server_bi/server/FileApi.cpp +++ b/platform/src/service/web_server_bi/server/FileApi.cpp @@ -184,6 +184,60 @@ QString CFileApi::uploadFile(const QString &strGroup, const QString &strOriginal return strDestFileName; } +bool CFileApi::uploadModel(const QString &strParentCode, const QString &strGroup, const QString &strOriginalName, int nCategory, const QByteArray &baContent, iot_dbms::CDbApi *pDbApi ) +{ + // 其他参数检查交给uploadFile检查 + + iot_dbms::CDbApi * usefulDbApi; + std::shared_ptr ptrDbApi; + if( pDbApi != nullptr) + { + if( !pDbApi->isOpen()) + { + return false; + } + usefulDbApi = pDbApi; + } + else + { + ptrDbApi = std::make_shared( DB_CONN_MODEL_WRITE ); + usefulDbApi = ptrDbApi.get(); + if( !usefulDbApi ) + { + LOGERROR("cannot get useful DbApi"); + return false; + } + if( !usefulDbApi->open() ) + { + LOGERROR("cannot open database"); + return false; + } + } + + QString strFileName = CFileApi::uploadFile( strGroup, strOriginalName, baContent, + usefulDbApi ); + if ( strFileName.isEmpty()) + { + LOGERROR( "uploadModel():保存文件失败"); + return false; + } + + + QByteArray baId = CFileApi::generateRandomId(); + const qint64 nTimeNow = QDateTime::currentMSecsSinceEpoch(); + + bool ret = usefulDbApi->insert( "web_primitive", + {"id", "category", "primitive_name", "content_path", "icon_info", + "parent_code", "param", "create_time"}, + {baId, nCategory, strOriginalName, strFileName, + //< 将iconPath内容缩短,详见常量定义注释 + "", + strParentCode, "", nTimeNow} ); + + + return ret; +} + bool CFileApi::updateFileByPath( const QString &strPath, const QString *pOriginalName, const QByteArray *pContent, iot_dbms::CDbApi *pDbApi ) { @@ -424,4 +478,47 @@ bool CFileApi::readFileByPath( const QString &strPath, QByteArray &baContent ) return true; } +bool CFileApi::readFileByFileNameAndGroup(const QString &strFileName, const QString &strFileGroup, QByteArray &baContent) +{ + // 从数据库查询组合文件组和文件的最大版本号,如果查询到,返回文件内容,如果没有,返回false + iot_dbms::CDbApi dbapi = iot_dbms::CDbApi(DB_CONN_MODEL_READ); + if(!dbapi.open()) + { + LOGERROR("cannot open database"); + } + + QString sSql = QString("select max(revision),id,ext from web_files where name='%1' and file_group='%2' and status=0;") + .arg(strFileName).arg(strFileGroup); + QSqlQuery objQuery; + if ( !dbapi.execute(sSql,objQuery) ) + { + LOGERROR("cannot query table web_files about max revision on name:%s, file_group:%s",strFileName.toStdString().c_str(), strFileGroup.toStdString().c_str()); + return false; + } + if( !objQuery.next() ) + { + return false; + } + else + { + if(!objQuery.isNull(0)) + { + + QString filePath = strFileGroup + "/" + objQuery.value(1).toString() + objQuery.value(2).toString(); + if(!readFileByPath(filePath,baContent)) + { + LOGERROR("readFileByFileNameAndGroup:cannot read file:%s",filePath.toStdString().c_str()); + return false; + } + return true; + } + else + { + LOGERROR("sql result is null:%s",sSql.toStdString().c_str()); + return false; + } + } + +} + } //< namespace web_server_bi