diff --git a/product/src/fes/protocol/iec62541_client/IEC62541.cpp b/product/src/fes/protocol/iec62541_client/IEC62541.cpp new file mode 100644 index 00000000..16f73eec --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/IEC62541.cpp @@ -0,0 +1,265 @@ +#include "IEC62541.h" +#include "pub_utility_api/I18N.h" +#include "pub_utility_api/CharUtil.h" +#include "pub_utility_api/CommonConfigParse.h" +using namespace iot_public; + +CIEC62541 g_iec62541; +bool g_IEC62541IsMainFes = false; +bool g_IEC62541ChanelRun = true; +int EX_SetBaseAddr(void *address) +{ + g_iec62541.SetBaseAddr(address); + return iotSuccess; +} + +int EX_SetProperty(int FesStatus) +{ + g_iec62541.SetProperty(FesStatus); + return iotSuccess; +} + +int EX_OpenChan(int MainChanNo,int ChanNo,int OpenFlag) +{ + g_iec62541.OpenChan(MainChanNo,ChanNo,OpenFlag); + return iotSuccess; +} + +int EX_CloseChan(int MainChanNo,int ChanNo,int CloseFlag) +{ + g_iec62541.CloseChan(MainChanNo,ChanNo,CloseFlag); + return iotSuccess; +} + + +int EX_ChanTimer(int ChanNo) +{ + g_iec62541.ChanTimer(ChanNo); + return iotSuccess; +} + +int EX_ExitSystem(int flag) +{ + boost::ignore_unused_variable_warning(flag); + g_IEC62541ChanelRun = false;//使所有的线程退出。 + return iotSuccess; +} + + + +CIEC62541::CIEC62541():m_ProtocolId(-1),m_ptrCFesBase(NULL) +{ + +} + +CIEC62541::~CIEC62541() +{ + m_vecDataThreadPtr.clear(); +} + +int CIEC62541::SetBaseAddr(void *address) +{ + if (m_ptrCFesBase == NULL) + { + m_ptrCFesBase = (CFesBase *)address; + } + + //规约映射表初始化 + if(m_ptrCFesBase != NULL) + { + m_ptrCFesBase->ProtocolRtuInitByParam1((char*)"iec62541_client"); + ReadConfigParam(); //加载配置文件中的RTU配置参数 + } + return iotSuccess; +} +int CIEC62541::SetProperty(int IsMainFes) +{ + g_IEC62541IsMainFes = (IsMainFes == 1); + LOGDEBUG("CIEC61850::SetProperty g_IEC62541IsMainFes:%d",IsMainFes); + return iotSuccess; +} + +/** + * @brief CIEC62541::OpenChan + * 根据OpenFlag,打开通道线程或数据处理线程。 + * @param MainChanNo 主通道号 + * @param ChanNo 当前通道号 + * @param OpenFlag 打开标志 1:打开通道线程 2:打开数据处理线程 3:打开通道线程和数据处理线程 + * @return 成功:iotSuccess 失败:iotFailed + */ +int CIEC62541::OpenChan(int MainChanNo, int ChanNo, int OpenFlag) +{ + CFesChanPtr ptrMainFesChan = GetChanDataByChanNo(MainChanNo); + CFesChanPtr ptrFesChan = GetChanDataByChanNo(ChanNo); + + if(ptrMainFesChan == NULL || ptrFesChan == NULL) + { + return iotFailed; + } + +// if((OpenFlag==CN_FesChanThread_Flag)||(OpenFlag==CN_FesChanAndDataThread_Flag)) +// { +// } + + if((OpenFlag==CN_FesDataThread_Flag)||(OpenFlag==CN_FesChanAndDataThread_Flag)) + { + if (ptrMainFesChan->m_DataThreadRun == CN_FesStopFlag) + { + //找到就用配置文件中配置,找不到就用构造函数默认参数 + fes_iec62541_client::SIEC62541AppConfParam stRtuConfParam; + auto iterConfig = m_mapConfMap.find(ptrMainFesChan->m_Param.ChanNo); + if(iterConfig != m_mapConfMap.end()) + { + stRtuConfParam = iterConfig->second; + } + + //open chan thread + fes_iec62541_client::CIEC62541DataProcThreadPtr ptrThread = + boost::make_shared(m_ptrCFesBase,ptrMainFesChan,stRtuConfParam); + + if (ptrThread == NULL) + { + LOGERROR("CIEC62541 EX_OpenChan() ChanNo:%d create CIEC62541DataProcThread error!",ptrFesChan->m_Param.ChanNo); + return iotFailed; + } + + m_vecDataThreadPtr.push_back(ptrThread); + ptrThread->resume(); //start Data THREAD + } + } + + // 因为使用的sdk的连接,所以直接将通信状态设置为run + ptrMainFesChan->SetComThreadRunFlag(CN_FesRunFlag); + + return iotSuccess; +} + +/** + * @brief CIEC62541::CloseChan + * 根据OpenFlag,关闭通道线程或数据处理线程。 + * @param MainChanNo 主通道号 + * @param ChanNo 当前通道号 + * @param OpenFlag 关闭标志 1:关闭通道线程 2:关闭数据处理线程 3:关闭通道线程和数据处理线程 + * @return 成功:iotSuccess 失败:iotFailed + */ +int CIEC62541::CloseChan(int MainChanNo, int ChanNo, int CloseFlag) +{ + CFesChanPtr ptrMainFesChan = GetChanDataByChanNo(MainChanNo); + CFesChanPtr ptrFesChan = GetChanDataByChanNo(ChanNo); + + if(ptrMainFesChan == NULL || ptrFesChan == NULL) + { + return iotFailed; + } + + //虽然本协议使用sdk,不是自己管理连接,但是需要执行SetComThreadRunFlag(CN_FesStopFlag),否则冗余状态变化时,无法重新打开通道 + if ((CloseFlag == CN_FesChanThread_Flag) || (CloseFlag == CN_FesChanAndDataThread_Flag)) + { + ptrFesChan->SetComThreadRunFlag(CN_FesStopFlag); + LOGINFO("ChanNo=%d ptrFesChan->SetComThreadRunFlag(CN_FesStopFlag)", ptrFesChan->m_Param.ChanNo); + } + + if((CloseFlag==CN_FesDataThread_Flag)||(CloseFlag==CN_FesChanAndDataThread_Flag)) + { + if (ptrMainFesChan->m_DataThreadRun == CN_FesRunFlag) + { + //close data thread + ClearDataProcThreadByChanNo(MainChanNo); + } + } + + return iotSuccess; +} + +/** + * @brief CIEC62541::ChanTimer + * 通道定时器,主通道会定时调用 + * @param MainChanNo 主通道号 + * @return + */ +int CIEC62541::ChanTimer(int MainChanNo) +{ + boost::ignore_unused_variable_warning(MainChanNo); + //把命令缓冲时间间隔到的命放到发送命令缓冲区 + return iotSuccess; +} + +void CIEC62541::ClearDataProcThreadByChanNo(int nChanNo) +{ + for(auto it = m_vecDataThreadPtr.begin(); it != m_vecDataThreadPtr.end();it++) + { + const fes_iec62541_client::CIEC62541DataProcThreadPtr &ptrThread = *it; + if(ptrThread->getChannelNo() == nChanNo) + { + m_vecDataThreadPtr.erase(it); + LOGINFO("CIEC62541::ClearDataProcThreadByChanNo %d ok",nChanNo); + break; + } + } +} + + +int CIEC62541::ReadConfigParam() +{ + if (m_ptrCFesBase == NULL) + return iotFailed; + + m_ProtocolId = m_ptrCFesBase->GetProtocolID((char*)"iec62541_client"); + if (m_ProtocolId == -1) + { + LOGERROR("ReadConfigParam() ProtoclID=iec62541_client error"); + return iotFailed; + } + + LOGINFO("iec62541_client ProtoclID=%d",m_ProtocolId); + + CCommonConfigParse config; + fes_iec62541_client::SIEC62541AppConfParam defaultRtuParam; + CFesChanPtr ptrChan = NULL; //CHAN数据区 + CFesRtuPtr ptrRTU = NULL; + + if (config.load("../../data/fes/", "iec62541_client.xml") == iotFailed) + { + LOGWARN("iec62541 load iec62541_client.xml error"); + return iotSuccess; + } + + LOGINFO("iec62541 load iec62541_client.xml ok"); + + + for (size_t nChanIdx = 0; nChanIdx < m_ptrCFesBase->m_vectCFesChanPtr.size(); nChanIdx++) + { + ptrChan = m_ptrCFesBase->m_vectCFesChanPtr[nChanIdx]; + if(ptrChan->m_Param.Used != 1 || m_ProtocolId != ptrChan->m_Param.ProtocolId) + { + continue; + } + + //found RTU + for (size_t nRtuIdx = 0; nRtuIdx < m_ptrCFesBase->m_vectCFesRtuPtr.size(); nRtuIdx++) + { + ptrRTU = m_ptrCFesBase->m_vectCFesRtuPtr[nRtuIdx]; + if (!ptrRTU->m_Param.Used || (ptrRTU->m_Param.ChanNo != ptrChan->m_Param.ChanNo)) + { + continue; + } + + fes_iec62541_client::SIEC62541AppConfParam param = defaultRtuParam; + string strRtuName = "RTU" + IntToString(ptrRTU->m_Param.RtuNo); + parseRtuConfig(config,strRtuName,param); + + m_mapConfMap[ptrRTU->m_Param.ChanNo] = param; + } + + } + return iotSuccess; + +} + +int CIEC62541::parseRtuConfig(CCommonConfigParse &configParse,const std::string &strRtuName,fes_iec62541_client::SIEC62541AppConfParam &stParam) +{ + LOGDEBUG("CIEC62541:解析RTU参数,RTU=%s",strRtuName.c_str()); + //找到就用配置文件,找不到就用构造函数中的值 + + return iotSuccess; +} diff --git a/product/src/fes/protocol/iec62541_client/IEC62541.h b/product/src/fes/protocol/iec62541_client/IEC62541.h new file mode 100644 index 00000000..ce7abe42 --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/IEC62541.h @@ -0,0 +1,59 @@ +#pragma once +#include "FesDef.h" +#include "FesBase.h" +#include "ProtocolBase.h" +#include "IEC62541DataProcThread.h" +#include "pub_utility_api/CommonConfigParse.h" + + +extern "C" PROTOCOLBASE_API int EX_SetBaseAddr(void *Address); +extern "C" PROTOCOLBASE_API int EX_SetProperty(int FesStatus); +extern "C" PROTOCOLBASE_API int EX_OpenChan(int MainChanNo,int ChanNo,int OpenFlag); +extern "C" PROTOCOLBASE_API int EX_CloseChan(int MainChanNo,int ChanNo,int CloseFlag); +extern "C" PROTOCOLBASE_API int EX_ChanTimer(int MainChanNo); +extern "C" PROTOCOLBASE_API int EX_ExitSystem(int flag); + + + +class PROTOCOLBASE_API CIEC62541 : public CProtocolBase +{ +public: + CIEC62541(); + virtual ~CIEC62541(); + + int SetBaseAddr(void *address); + int SetProperty(int IsMainFes); + int OpenChan(int MainChanNo,int ChanNo,int OpenFlag); + int CloseChan(int MainChanNo,int ChanNo,int CloseFlag); + int ChanTimer(int MainChanNo); + +private: + /** + * @brief 销毁指定通道资源 + * + * @param nChanNo 通道号 + */ + void ClearDataProcThreadByChanNo(int nChanNo); + + /** + * @brief 加载协议配置文件 data/fes/iec61850_clientV3 + * + * @return 成功返回iotSuccess,失败返回iotFailed + */ + int ReadConfigParam(); + /** + * @brief 解析RTU对应的参数,没有特殊配置时,使用默认参数 + * + * @param configParse 文件解析类,已经加载完了配置 + * @param strRtuName 要解析的RtuName,其实就是RTU+号 + * @param stParam 返回的参数 + * @return 成功返回iotSuccess,失败返回iotFailed + */ + int parseRtuConfig(CCommonConfigParse &configParse,const std::string &strRtuName, fes_iec62541_client::SIEC62541AppConfParam &stParam); + +private: + int m_ProtocolId; //本协议的ID + CFesBase* m_ptrCFesBase; //CProtocolBase类中定义 + fes_iec62541_client::CIEC62541DataProcThreadPtrSeq m_vecDataThreadPtr; //存放所有本协议的线程处理指针 + boost::unordered_map m_mapConfMap; //存储RTU对应的配置参数 +}; diff --git a/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.cpp b/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.cpp new file mode 100644 index 00000000..6ae32475 --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.cpp @@ -0,0 +1,1639 @@ +#include "IEC62541DataProcThread.h" +#include +#include +#include "FesMessage.pb.h" +#include "pub_utility_api/I18N.h" + +using namespace iot_idl; +extern bool g_IEC62541IsMainFes; +extern bool g_IEC62541ChanelRun; + +namespace fes_iec62541_client { + +CIEC62541DataProcThread::CIEC62541DataProcThread(CFesBase *ptrCFesBase, const CFesChanPtr &ptrChan, const fes_iec62541_client::SIEC62541AppConfParam &stConfParam) +:CTimerThreadBase("IEC62541DataProcThread",100,0,true), + m_ptrCFesBase(ptrCFesBase), + m_ptrFesChan(ptrChan), + m_ptrCurChan(NULL), + m_ptrCurRtu(NULL), + m_stRtuParam(stConfParam), + m_bReady(true), + m_cntReadNodeId(0) +{ + + m_ptrUAClient=NULL; + m_ptrCurChan = ptrChan; + m_ptrCurRtu = GetRtuDataByChanData(m_ptrCurChan); + init(); +} + +CIEC62541DataProcThread::~CIEC62541DataProcThread() +{ + if(m_ptrUAClient) + { + UA_Client_delete(m_ptrUAClient); + m_ptrUAClient=NULL; + } + + for (size_t i = 0; i < m_cntReadNodeId; ++i) { + UA_ReadValueId* nodeId = &m_ptrReadNodeIds[i]; + UA_NodeId_clear(&(nodeId->nodeId)); + + } + + m_ptrFesChan->SetDataThreadRunFlag(CN_FesStopFlag); + +} + +int CIEC62541DataProcThread::beforeExecute() +{ + return iotSuccess; +} + + +void CIEC62541DataProcThread::execute() +{ + if(!g_IEC62541IsMainFes) + { + LOGTRACE("CIEC62541DataProcThread ChanNo=%d do nothing ,due to is not main fes", m_ptrCurChan->m_Param.ChanNo); + return; + } + + if(!m_bReady) + { + LOGTRACE("CIEC62541DataProcThread ChanNo=%d not ready ,check log which has record err", m_ptrCurChan->m_Param.ChanNo); + return; + } + if(!m_bConnected) + { + if(iotSuccess!=initClient()) + { + m_ptrCurRtu->WriteRtuSatus(CN_FesRtuComDown); + LOGERROR("CIEC62541DataProcThread ChanNo=%d reconnect failed ", m_ptrCurChan->m_Param.ChanNo); + return; + } + } + UA_StatusCode status = UA_Client_run_iterate(m_ptrUAClient, 100); // most wait 100 ms + if (status != UA_STATUSCODE_GOOD) { + if(iotSuccess!=initClient()) + { + m_ptrCurRtu->WriteRtuSatus(CN_FesRtuComDown); + LOGERROR("CIEC62541DataProcThread ChanNo=%d reconnect failed ", m_ptrCurChan->m_Param.ChanNo); + return; + } + } + + handleCommand(); + + batchRequestData(); + +} + +void CIEC62541DataProcThread::beforeQuit() +{ + +} + +int CIEC62541DataProcThread::init() +{ + initClient(); + initReadNodeIds(); + + m_ptrFesChan->SetDataThreadRunFlag(CN_FesRunFlag); + return iotSuccess; +} + +int CIEC62541DataProcThread::initClient() +{ + if(m_ptrUAClient) + { + UA_Client_delete(m_ptrUAClient); + m_ptrUAClient=NULL; + } + UA_ClientConfig *config=new UA_ClientConfig(); + UA_ClientConfig_setDefault(config); + m_ptrUAClient = UA_Client_newWithConfig(config); + std::string serverIp=m_ptrCurChan->m_Param.NetRoute[0].NetDesc; + int port=m_ptrCurChan->m_Param.NetRoute[0].PortNo; + config->timeout=1000; + std::ostringstream oss; + oss << serverIp <<":"<< port; + std::string resultUrl = oss.str(); // opc.tcp://192.168.3.17:4840 + + UA_StatusCode status=UA_Client_connect(m_ptrUAClient,resultUrl.c_str()); + if(status!=UA_STATUSCODE_GOOD) + { + UA_Client_delete(m_ptrUAClient); + m_ptrUAClient=NULL; + m_bConnected=false; + std::string statusMessage = getStatusMessage(status); + LOGERROR("CIEC62541DataProcThread ChanNo=%d initClient faild to connect(%s) err(%s)", m_ptrCurChan->m_Param.ChanNo,resultUrl.c_str(),statusMessage.c_str()); + return iotFailed; + } + + m_bConnected=true; + LOGINFO("CIEC62541DataProcThread ChanNo=%d connect %s ok", m_ptrCurChan->m_Param.ChanNo,resultUrl.c_str()); + return iotSuccess; +} + +string CIEC62541DataProcThread::getStatusMessage(UA_StatusCode status) +{ + std::ostringstream oss; + oss <<" statusCode("<< status <<")"<<" statusDesc("<< UA_StatusCode_name(status)<<")"; + return oss.str(); +} + +int CIEC62541DataProcThread::handleCommand() +{ + DoCmdProcess(m_ptrCurRtu); + AoCmdProcess(m_ptrCurRtu); + MoCmdProcess(m_ptrCurRtu); + return iotSuccess; +} + +int CIEC62541DataProcThread::batchRequestData() +{ + UA_ReadRequest request; + UA_ReadRequest_init(&request); + request.nodesToRead = m_ptrReadNodeIds.get(); + request.nodesToReadSize = m_cntReadNodeId; + + UA_ReadResponse response = UA_Client_Service_read(m_ptrUAClient, request); + if (response.responseHeader.serviceResult != UA_STATUSCODE_GOOD != UA_STATUSCODE_GOOD || response.resultsSize == 0) { + std::string statusMessage = getStatusMessage(response.responseHeader.serviceResult); + LOGERROR("CIEC62541DataProcThread ChanNo=%d request faild err(%s)", m_ptrCurChan->m_Param.ChanNo,statusMessage.c_str()); + UA_ReadResponse_clear(&response); + return iotFailed; + } + + procDiData(response); + procAiData(response); + procMiData(response); + procAccData(response); + + UA_ReadResponse_clear(&response); + return iotSuccess; +} + + + +void CIEC62541DataProcThread::initReadNodeIds() +{ + boost::container::map mapStringNodeIdInit;//string,guid + + boost::container::map mapNumNodeIdInit; + + boost::container::map mapStringNodeIdIndex;//string,guid + + boost::container::map mapNumNodeIdIndex; + + + + SFesAi *pAi=NULL; + for (int aiPoint = 0; aiPoint < m_ptrCurRtu->m_MaxAiPoints; aiPoint++) + { + pAi = m_ptrCurRtu->m_pAi + aiPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pAi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + if(pAi->Param2==UA_NODEIDTYPE_NUMERIC) + { + mapNumNodeIdInit.emplace(strNsNode,false); + } + else + { + mapStringNodeIdInit.emplace(strNsNode,false); + } + + + } + + SFesDi *pDi=NULL; + for (int diPoint = 0; diPoint < m_ptrCurRtu->m_MaxDiPoints; diPoint++) + { + pDi = m_ptrCurRtu->m_pDi + diPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pDi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + if(pDi->Param2==UA_NODEIDTYPE_NUMERIC) + { + mapNumNodeIdInit.emplace(strNsNode,false); + } + else + { + mapStringNodeIdInit.emplace(strNsNode,false); + } + } + + SFesMi *pMi=NULL; + for (int miPoint = 0; miPoint < m_ptrCurRtu->m_MaxMiPoints; miPoint++) + { + pMi = m_ptrCurRtu->m_pMi + miPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pMi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + if(pMi->Param2==UA_NODEIDTYPE_NUMERIC) + { + mapNumNodeIdInit.emplace(strNsNode,false); + } + else + { + mapStringNodeIdInit.emplace(strNsNode,false); + } + } + + SFesAcc *pAcc=NULL; + for (int accPoint = 0; accPoint < m_ptrCurRtu->m_MaxAccPoints; accPoint++) + { + pAcc = m_ptrCurRtu->m_pAcc + accPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pAcc->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + if(pAcc->Param2==UA_NODEIDTYPE_NUMERIC) + { + mapNumNodeIdInit.emplace(strNsNode,false); + } + else + { + mapStringNodeIdInit.emplace(strNsNode,false); + } + } + + m_cntReadNodeId=mapNumNodeIdInit.size()+mapStringNodeIdInit.size(); + + m_ptrReadNodeIds=boost::make_shared(m_cntReadNodeId); + + + int64 indexReadNodeId=0; + + pAi=NULL; + for (int aiPoint = 0; aiPoint < m_ptrCurRtu->m_MaxAiPoints; aiPoint++) + { + pAi = m_ptrCurRtu->m_pAi + aiPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pAi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + + + if(pAi->Param2==UA_NODEIDTYPE_NUMERIC) + { + + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(mapNumNodeIdInit[strNsNode])) + { + if(mapNumNodeIdIndex.count(strNsNode)>0) + { + m_indexMapAI.emplace(aiPoint,mapNumNodeIdIndex[strNsNode]); + } + } + + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(!mapNumNodeIdInit[strNsNode])) + { + initNumericNodeId(indexReadNodeId,aiPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapAI); + indexReadNodeId++; + } + } + else + { + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(mapStringNodeIdInit[strNsNode])) + { + if(mapStringNodeIdIndex.count(strNsNode)>0) + { + m_indexMapAI.emplace(aiPoint,mapStringNodeIdIndex[strNsNode]); + } + } + + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(!mapStringNodeIdInit[strNsNode])) + { + + if(pAi->Param2==UA_NODEIDTYPE_STRING) + { + + initStringNodeId(indexReadNodeId,aiPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapAI); + indexReadNodeId++; + } + else if(pAi->Param2==UA_NODEIDTYPE_GUID) + { + initGUIDNodeId(indexReadNodeId,aiPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapAI); + indexReadNodeId++; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d not Implement nodeIdType(%d) on aipoint-no(%d) ", m_ptrCurChan->m_Param.ChanNo,pAi->Param2,aiPoint); + } + + } + } + + + + } + + + pDi=NULL; + for (int diPoint = 0; diPoint < m_ptrCurRtu->m_MaxDiPoints; diPoint++) + { + pDi = m_ptrCurRtu->m_pDi + diPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pDi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + + + if(pDi->Param2==UA_NODEIDTYPE_NUMERIC) + { + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(mapNumNodeIdInit[strNsNode])) + { + if(mapNumNodeIdIndex.count(strNsNode)>0) + { + m_indexMapDI.emplace(diPoint,mapNumNodeIdIndex[strNsNode]); + } + } + + + + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(!mapNumNodeIdInit[strNsNode])) + { + initNumericNodeId(indexReadNodeId,diPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapDI); + indexReadNodeId++; + } + + } + else + { + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(mapStringNodeIdInit[strNsNode])) + { + if(mapStringNodeIdIndex.count(strNsNode)>0) + { + m_indexMapDI.emplace(diPoint,mapStringNodeIdIndex[strNsNode]); + } + } + + + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(!mapStringNodeIdInit[strNsNode])) + { + + if(pDi->Param2==UA_NODEIDTYPE_STRING) + { + initStringNodeId(indexReadNodeId,diPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapDI); + indexReadNodeId++; + } + else if(pDi->Param2==UA_NODEIDTYPE_GUID) + { + initGUIDNodeId(indexReadNodeId,diPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapDI); + indexReadNodeId++; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d not Implement nodeIdType(%d) on dipoint-no(%d) ", m_ptrCurChan->m_Param.ChanNo,pDi->Param2,diPoint); + } + + } + } + + + } + + pMi=NULL; + for (int miPoint = 0; miPoint < m_ptrCurRtu->m_MaxMiPoints; miPoint++) + { + pMi = m_ptrCurRtu->m_pMi + miPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pMi->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + + + if(pMi->Param2==UA_NODEIDTYPE_NUMERIC) + { + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(mapNumNodeIdInit[strNsNode])) + { + if(mapNumNodeIdIndex.count(strNsNode)>0) + { + m_indexMapMI.emplace(miPoint,mapNumNodeIdIndex[strNsNode]); + } + } + + + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(!mapNumNodeIdInit[strNsNode])) + { + + initNumericNodeId(indexReadNodeId,miPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapMI); + indexReadNodeId++; + } + + } + else + { + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(mapStringNodeIdInit[strNsNode])) + { + if(mapStringNodeIdIndex.count(strNsNode)>0) + { + m_indexMapMI.emplace(miPoint,mapStringNodeIdIndex[strNsNode]); + } + } + + + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(!mapStringNodeIdInit[strNsNode])) + { + + if(pMi->Param2==UA_NODEIDTYPE_STRING) + { + + initStringNodeId(indexReadNodeId,miPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapMI); + + indexReadNodeId++; + } + else if(pMi->Param2==UA_NODEIDTYPE_GUID) + { + initGUIDNodeId(indexReadNodeId,miPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapMI); + indexReadNodeId++; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d not Implement nodeIdType(%d) on mipoint-no(%d) ", m_ptrCurChan->m_Param.ChanNo,pMi->Param2,miPoint); + } + + } + } + + + } + + + pAcc=NULL; + for (int accPoint = 0; accPoint < m_ptrCurRtu->m_MaxAccPoints; accPoint++) + { + pAcc = m_ptrCurRtu->m_pAcc + accPoint; + std::string nsStr; + std::string nodeIdStr; + if(iotFailed==getNodeIdByString(pAcc->szResParam1,nsStr,nodeIdStr)) + { + continue; + } + std::string strNsNode=nsStr+"-"+nodeIdStr; + + + if(pAcc->Param2==UA_NODEIDTYPE_NUMERIC) + { + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(mapNumNodeIdInit[strNsNode])) + { + if(mapNumNodeIdIndex.count(strNsNode)>0) + { + m_indexMapACC.emplace(accPoint,mapNumNodeIdIndex[strNsNode]); + } + } + + + + if(mapNumNodeIdInit.count(strNsNode)>0 + &&(!mapNumNodeIdInit[strNsNode])) + { + initNumericNodeId(indexReadNodeId,accPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapACC); + indexReadNodeId++; + } + + } + else + { + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(mapStringNodeIdInit[strNsNode])) + { + if(mapStringNodeIdIndex.count(strNsNode)>0) + { + m_indexMapACC.emplace(accPoint,mapStringNodeIdIndex[strNsNode]); + } + } + + + if(mapStringNodeIdInit.count(strNsNode)>0 + &&(!mapStringNodeIdInit[strNsNode])) + { + + if(pAcc->Param2==UA_NODEIDTYPE_STRING) + { + + initStringNodeId(indexReadNodeId,accPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapACC); + indexReadNodeId++; + } + else if(pAcc->Param2==UA_NODEIDTYPE_GUID) + { + initGUIDNodeId(indexReadNodeId,accPoint,strNsNode,nsStr,nodeIdStr,mapNumNodeIdInit,mapNumNodeIdIndex,m_indexMapACC); + indexReadNodeId++; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d not Implement nodeIdType(%d) on accpoint-no(%d) ", m_ptrCurChan->m_Param.ChanNo,pAcc->Param2,accPoint); + } + + } + } + + + } + + + +} + +int CIEC62541DataProcThread::getNodeIdByString(const string& tagStr,std::string& namespaceIndex,std::string& nodeId) +{ + + size_t pos = tagStr.find('!'); + if(pos != std::string::npos) + { + nodeId = tagStr.substr(pos + 1); + std::string preStr = tagStr.substr(0, pos); + + size_t pos2 = tagStr.find('['); + + if(pos2!=std::string::npos) + { + namespaceIndex=preStr.substr(0, pos2); + } + else + { + namespaceIndex=preStr; + } + + + return iotSuccess; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d get bad tagStr(%s) ,due to not find (!) ", m_ptrCurChan->m_Param.ChanNo,tagStr.c_str()); + return iotFailed; + } + + +} + +void CIEC62541DataProcThread::initStringNodeId(int64 indexReadNodeId, int64 pointNo,string &strNsNode,string &nsStr, string &nodeIdStr, boost::container::map &mapStringNodeIdInit, + boost::container::map &mapStringNodeIdIndex, boost::container::map& indexMap) +{ + UA_ReadValueId* tmp=&m_ptrReadNodeIds[indexReadNodeId]; + UA_ReadValueId_init(tmp); + m_ptrReadNodeIds[indexReadNodeId].attributeId = UA_ATTRIBUTEID_VALUE; + m_ptrReadNodeIds[indexReadNodeId].nodeId = UA_NODEID_STRING_ALLOC(atoi(nsStr.c_str()), nodeIdStr.c_str()); + mapStringNodeIdInit[strNsNode]=true; + + indexMap.emplace(pointNo,indexReadNodeId); + mapStringNodeIdIndex.emplace(strNsNode,indexReadNodeId); +} + +void CIEC62541DataProcThread::initGUIDNodeId(int64 indexReadNodeId, int64 pointNo, string &strNsNode, string &nsStr, string &nodeIdStr, boost::container::map &mapStringNodeIdInit, boost::container::map &mapStringNodeIdIndex, boost::container::map &indexMap) +{ + UA_ReadValueId* tmp=&m_ptrReadNodeIds[indexReadNodeId]; + UA_ReadValueId_init(tmp); + m_ptrReadNodeIds[indexReadNodeId].attributeId = UA_ATTRIBUTEID_VALUE; + m_ptrReadNodeIds[indexReadNodeId].nodeId = UA_NODEID_GUID(atoi(nsStr.c_str()), UA_GUID(nodeIdStr.c_str())); + mapStringNodeIdInit[strNsNode]=true; + + indexMap.emplace(pointNo,indexReadNodeId); + mapStringNodeIdIndex.emplace(strNsNode,indexReadNodeId); + indexReadNodeId++; +} + +void CIEC62541DataProcThread::procDiData(UA_ReadResponse &response) +{ + SFesDi *pDi=NULL; + SFesRtuDiValue* DiValue=new SFesRtuDiValue[m_ptrCurRtu->m_MaxDiPoints]; + SFesChgDi* ChgDi=new SFesChgDi[m_ptrCurRtu->m_MaxDiPoints]; + int ChgCount = 0 , ValueCount = 0; + uint64 mSec; + mSec = getUTCTimeMsec(); + for (int diPoint = 0; diPoint < m_ptrCurRtu->m_MaxDiPoints; diPoint++) + { + int64 resultIndex=m_indexMapDI[diPoint]; + UA_DataValue* result = &response.results[resultIndex]; + pDi = m_ptrCurRtu->m_pDi + diPoint; + std::vector indexVec; + getDataIndex(pDi->szResParam1,indexVec); + double resultValue; + DataType dataType=static_cast(pDi->Param1); + if(result->hasSourceTimestamp) + { + mSec=result->sourceTimestamp; + } + else{ + if(result->hasServerTimestamp) + { + mSec=result->serverTimestamp; + } + } + + uint32 valueStatus=CN_FesValueUpdate; + if(!result->hasValue) + { + valueStatus|=CN_FesValueInvaild; + } + + + + if(iotSuccess==getValue(result,indexVec,dataType,resultValue)) + { + if(resultValue != pDi->Value) + { + memcpy(ChgDi[ChgCount].TableName,pDi->TableName,CN_FesMaxTableNameSize); + memcpy(ChgDi[ChgCount].ColumnName,pDi->ColumnName,CN_FesMaxColumnNameSize); + memcpy(ChgDi[ChgCount].TagName,pDi->TagName,CN_FesMaxTagSize); + ChgDi[ChgCount].Value = resultValue; + ChgDi[ChgCount].Status = valueStatus; + ChgDi[ChgCount].time = mSec; + ChgDi[ChgCount].RtuNo = m_ptrCurRtu->m_Param.RtuNo; + ChgDi[ChgCount].PointNo = pDi->PointNo; + ChgCount++; + } + DiValue[diPoint].PointNo = diPoint; + DiValue[diPoint].Status = valueStatus; + DiValue[diPoint].time = mSec; + DiValue[diPoint].Value = resultValue; + ValueCount++; + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d dipoint-no(%d)(%s) can not get the value", m_ptrCurChan->m_Param.ChanNo,pDi->PointNo,&(pDi->TagName[0])); + + } + } + + if(ChgCount>0) + { + m_ptrCFesBase->WriteChgDiValue(m_ptrCurRtu,ChgCount,&ChgDi[0]); + LOGTRACE("CIEC62541DataProcThread ChanNo=%d WriteChgDiValue ChgCount = %d",m_ptrCurChan->m_Param.ChanNo,ChgCount); + + } + + if( ValueCount > 0 ) + { + m_ptrCurRtu->WriteRtuDiValue(ValueCount, &DiValue[0]); + } + + delete[] DiValue; + DiValue=NULL; + + delete[] ChgDi; + ChgDi=NULL; +} + +void CIEC62541DataProcThread::procAiData(UA_ReadResponse &response) +{ + SFesAi *pAi=NULL; + SFesRtuAiValue* AiValue=new SFesRtuAiValue[m_ptrCurRtu->m_MaxAiPoints]; + SFesChgAi* ChgAi=new SFesChgAi[m_ptrCurRtu->m_MaxAiPoints]; + uint64 mSec; + mSec = getUTCTimeMsec(); + for (int aiPoint = 0; aiPoint < m_ptrCurRtu->m_MaxAiPoints; aiPoint++) + { + int64 resultIndex=m_indexMapAI[aiPoint]; + UA_DataValue* result = &response.results[resultIndex]; + pAi = m_ptrCurRtu->m_pAi + aiPoint; + std::vector indexVec; + getDataIndex(pAi->szResParam1,indexVec); + double resultValue; + DataType dataType=static_cast(pAi->Param1); + if(result->hasSourceTimestamp) + { + mSec=result->sourceTimestamp; + } + else{ + if(result->hasServerTimestamp) + { + mSec=result->serverTimestamp; + } + } + + uint32 valueStatus=CN_FesValueUpdate; + if(!result->hasValue) + { + valueStatus|=CN_FesValueInvaild; + } + + + + + if(iotSuccess==getValue(result,indexVec,dataType,resultValue)) + { + + AiValue[aiPoint].PointNo = aiPoint; + AiValue[aiPoint].Status = valueStatus; + AiValue[aiPoint].time = mSec; + AiValue[aiPoint].Value = resultValue; + + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d dipoint-no(%d)(%s) can not get the value", m_ptrCurChan->m_Param.ChanNo,pAi->PointNo,&(pAi->TagName[0])); + + } + } + int ChgCount = 0; + m_ptrCurRtu->WriteRtuAiValueAndRetChg(m_ptrCurRtu->m_MaxAiPoints, &AiValue[0], &ChgCount, &ChgAi[0]); + LOGTRACE("CIEC62541DataProcThread ChanNo=%d WriteRtuAiValueAndRetChg ChgCount = %d",m_ptrCurChan->m_Param.ChanNo,ChgCount); + if(ChgCount>0) + { + m_ptrCFesBase->WriteChgAiValue(m_ptrCurRtu, ChgCount, &ChgAi[0]); + ChgCount = 0; + } + + + delete[] AiValue; + AiValue=NULL; + + delete[] ChgAi; + ChgAi=NULL; + +} + +void CIEC62541DataProcThread::procMiData(UA_ReadResponse &response) +{ + SFesMi *pMi=NULL; + SFesRtuMiValue* MiValue=new SFesRtuMiValue[m_ptrCurRtu->m_MaxMiPoints]; + SFesChgMi* ChgMi=new SFesChgMi[m_ptrCurRtu->m_MaxMiPoints]; + uint64 mSec; + mSec = getUTCTimeMsec(); + for (int miPoint = 0; miPoint < m_ptrCurRtu->m_MaxMiPoints; miPoint++) + { + int64 resultIndex=m_indexMapMI[miPoint]; + UA_DataValue* result = &response.results[resultIndex]; + pMi = m_ptrCurRtu->m_pMi + miPoint; + std::vector indexVec; + getDataIndex(pMi->szResParam1,indexVec); + double resultValue; + DataType dataType=static_cast(pMi->Param1); + if(result->hasSourceTimestamp) + { + mSec=result->sourceTimestamp; + } + else{ + if(result->hasServerTimestamp) + { + mSec=result->serverTimestamp; + } + } + + uint32 valueStatus=CN_FesValueUpdate; + if(!result->hasValue) + { + valueStatus|=CN_FesValueInvaild; + } + + + if(iotSuccess==getValue(result,indexVec,dataType,resultValue)) + { + + MiValue[miPoint].PointNo = miPoint; + MiValue[miPoint].Status = valueStatus; + MiValue[miPoint].time = mSec; + MiValue[miPoint].Value = resultValue; + + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d mipoint-no(%d)(%s) can not get the value", m_ptrCurChan->m_Param.ChanNo,pMi->PointNo,&(pMi->TagName[0])); + + } + } + int ChgCount = 0; + m_ptrCurRtu->WriteRtuMiValueAndRetChg(m_ptrCurRtu->m_MaxMiPoints, &MiValue[0], &ChgCount, &ChgMi[0]); + LOGTRACE("CIEC62541DataProcThread ChanNo=%d WriteRtuMiValueAndRetChg ChgCount = %d",m_ptrCurChan->m_Param.ChanNo,ChgCount); + if(ChgCount>0) + { + m_ptrCFesBase->WriteChgMiValue(m_ptrCurRtu, ChgCount, &ChgMi[0]); + ChgCount = 0; + } + + + delete[] MiValue; + MiValue=NULL; + + delete[] ChgMi; + ChgMi=NULL; +} + +void CIEC62541DataProcThread::procAccData(UA_ReadResponse &response) +{ + SFesAcc *pAcc=NULL; + SFesRtuAccValue* AccValue=new SFesRtuAccValue[m_ptrCurRtu->m_MaxAccPoints]; + SFesChgAcc* ChgAcc=new SFesChgAcc[m_ptrCurRtu->m_MaxAccPoints]; + uint64 mSec; + mSec = getUTCTimeMsec(); + for (int accPoint = 0; accPoint < m_ptrCurRtu->m_MaxAccPoints; accPoint++) + { + int64 resultIndex=m_indexMapACC[accPoint]; + UA_DataValue* result = &response.results[resultIndex]; + pAcc = m_ptrCurRtu->m_pAcc + accPoint; + std::vector indexVec; + getDataIndex(pAcc->szResParam1,indexVec); + double resultValue; + DataType dataType=static_cast(pAcc->Param1); + if(result->hasSourceTimestamp) + { + mSec=result->sourceTimestamp; + } + else{ + if(result->hasServerTimestamp) + { + mSec=result->serverTimestamp; + } + } + + uint32 valueStatus=CN_FesValueUpdate; + if(!result->hasValue) + { + valueStatus|=CN_FesValueInvaild; + } + + + + if(iotSuccess==getValue(result,indexVec,dataType,resultValue)) + { + + AccValue[accPoint].PointNo = accPoint; + AccValue[accPoint].Status = valueStatus; + AccValue[accPoint].time = mSec; + AccValue[accPoint].Value = resultValue; + + } + else + { + LOGERROR("CIEC62541DataProcThread ChanNo=%d mipoint-no(%d)(%s) can not get the value", m_ptrCurChan->m_Param.ChanNo,pAcc->PointNo,&(pAcc->TagName[0])); + + } + } + int ChgCount = 0; + m_ptrCurRtu->WriteRtuAccValueAndRetChg(m_ptrCurRtu->m_MaxMiPoints, &AccValue[0], &ChgCount, &ChgAcc[0]); + LOGTRACE("CIEC62541DataProcThread ChanNo=%d WriteRtuAccValueAndRetChg ChgCount = %d",m_ptrCurChan->m_Param.ChanNo,ChgCount); + if(ChgCount>0) + { + m_ptrCFesBase->WriteChgAccValue(m_ptrCurRtu, ChgCount, &ChgAcc[0]); + ChgCount = 0; + } + + + delete[] AccValue; + AccValue=NULL; + + delete[] ChgAcc; + ChgAcc=NULL; +} + +int CIEC62541DataProcThread::getValue(const UA_DataValue* dataValue,const std::vector& indexVec,DataType dataType,double& result) +{ + if (UA_Variant_isScalar(&(dataValue->value))) + { + switch (dataType) { + case SByte: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_SBYTE])) + { + int8_t pre= *(UA_SByte*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Int16: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT16])) + { + int16_t pre= *(UA_Int16*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Int32: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT32])) + { + int32_t pre= *(UA_Int32*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Int64: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT64])) + { + int64_t pre= *(UA_Int64*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Byte: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_BYTE])) + { + uint8_t pre= *(UA_Byte*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt16: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT16])) + { + uint16_t pre= *(UA_UInt16*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt32: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT32])) + { + uint32_t pre= *(UA_UInt32*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt64: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT64])) + { + uint64_t pre= *(UA_UInt64*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Float: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_FLOAT])) + { + float pre= *(UA_Float*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Double: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_DOUBLE])) + { + double pre= *(UA_Double*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + case Boolean: + if(UA_Variant_hasScalarType(&(dataValue->value),&UA_TYPES[UA_TYPES_BOOLEAN])) + { + bool pre= *(UA_Boolean*)dataValue->value.data; + result= static_cast(pre); + return iotSuccess; + } + break; + default: + return iotFailed; + break; + } + + } + else + { + int64 offset=0; + calculateIndex(dataValue,indexVec,offset); + switch (dataType) { + case SByte: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_SBYTE])) + { + int8_t pre= *((UA_SByte*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Int16: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT16])) + { + int16_t pre= *((UA_Int16*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Int32: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT32])) + { + int32_t pre= *((UA_Int32*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Int64: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_INT64])) + { + int64_t pre= *((UA_Int64*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Byte: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_BYTE])) + { + uint8_t pre= *((UA_Byte*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt16: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT16])) + { + uint16_t pre= *((UA_UInt16*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt32: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT32])) + { + uint32_t pre= *((UA_UInt32*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case UInt64: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_UINT64])) + { + uint64_t pre= *((UA_UInt64*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Float: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_FLOAT])) + { + float pre= *((UA_Float*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Double: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_DOUBLE])) + { + double pre= *((UA_Double*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + case Boolean: + if(UA_Variant_hasArrayType(&(dataValue->value),&UA_TYPES[UA_TYPES_BOOLEAN])) + { + bool pre= *((UA_Boolean*)dataValue->value.data+offset); + result= static_cast(pre); + return iotSuccess; + } + break; + default: + return iotFailed; + break; + } + + } + + return iotFailed; + +} + +int CIEC62541DataProcThread::calculateIndex(const UA_DataValue *dataValue, const std::vector &indexVec, int64 &resultOffset) +{ + + size_t index = 0; + size_t factor = 1; + UA_UInt32 *arrayDimensions=dataValue->value.arrayDimensions; + + for (size_t i = indexVec.size() - 1; i >= 0; --i) { + index += indexVec[i] * factor; + factor =factor*(*(arrayDimensions+1)); + } + + resultOffset=index; + return iotSuccess; + +} + +bool CIEC62541DataProcThread::getDataIndex(const string &tagStr, std::vector &indexVec) +{ + size_t pos = tagStr.find('!'); + if(pos != std::string::npos) + { + std::string preStr = tagStr.substr(0, pos); + + size_t start = preStr.find('['); + size_t end = preStr.find(']'); + + if(start != std::string::npos&&end != std::string::npos) + { + std::string numbersStr = preStr.substr(start + 1, end - start - 1); + std::stringstream ss(numbersStr); + std::string number; + while (std::getline(ss, number, ',')) { + indexVec.push_back(std::stoi(number)); + } + } + else + { + return false; + } + } + + return true; + +} + +void CIEC62541DataProcThread::AoCmdProcess(CFesRtuPtr ptrRtu) +{ + + + enum {BUF_SIZE = 20}; + SFesRxAoCmd arrCmd[BUF_SIZE]; + int nCmdCount = ptrRtu->ReadRxAoCmd(BUF_SIZE,&arrCmd[0]); //为了让缓冲区指令尽快执行 + + for(int i = 0; i < nCmdCount; i++) + { + + SFesTxAoCmd retCmd; + SFesAo *pAo = NULL; + SFesRxAoCmd& cmd=arrCmd[i]; + strcpy(retCmd.TableName, cmd.TableName); + strcpy(retCmd.ColumnName, cmd.ColumnName); + strcpy(retCmd.TagName, cmd.TagName); + strcpy(retCmd.RtuName, cmd.RtuName); + retCmd.CtrlDir = cmd.CtrlDir; + retCmd.RtuNo = cmd.RtuNo; + retCmd.PointID = cmd.PointID; + retCmd.FwSubSystem = cmd.FwSubSystem; + retCmd.FwRtuNo = cmd.FwRtuNo; + retCmd.FwPointNo = cmd.FwPointNo; + retCmd.SubSystem = cmd.SubSystem; + retCmd.CtrlActType = cmd.CtrlActType; + + pAo = GetFesAoByPointNo(m_ptrCurRtu, cmd.PointID); + + if(pAo == NULL) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + //return failed to scada + retCmd.retStatus = CN_ControlPointErr; + sprintf(retCmd.strParam, I18N_C("遥调失败!找不到遥调点")); + m_ptrCFesBase->WritexAoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调失败!RtuNo:%d 找不到遥调点:%d", getRtuNo(), cmd.PointID); + return; + } + + if (cmd.CtrlActType != CN_ControlExecute) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + retCmd.retStatus = CN_ControlFailed; + sprintf(retCmd.strParam, I18N_C("遥调控制命令错误!")); + m_ptrCFesBase->WritexAoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调控制命令错误! RtuNo:%d 遥调点:%d CtrlActType=%d", getRtuNo(), cmd.PointID,cmd.CtrlActType); + return; + } + + + //< 系数和量程的合法性在初始化时已经校验 + float fValue = (cmd.fValue - pAo->Base) / pAo->Coeff; + if((fValue < pAo->MinRange) || (fValue > pAo->MaxRange)) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + retCmd.retStatus = CN_ControlPointErr; //return failed to scada + sprintf(retCmd.strParam, I18N_C("遥调失败!设置值超出量程")); + m_ptrCFesBase->WritexAoRespCmdBuf(1, &retCmd); + } + + LOGINFO("CIEC62541:遥调失败,设置值超出量程!RtuNo:%d 遥调点:%d",getRtuNo(), cmd.PointID); + return; + } + + UA_WriteValue* tmp; + UA_WriteValue_init(tmp); + tmp->attributeId=UA_ATTRIBUTEID_VALUE; + buildNodeId(pAo->Param2,pAo->szResParam1,tmp->nodeId); + std::string resultIndex; + if(hasDataIndex(pAo->szResParam1,resultIndex)) + { + tmp->indexRange=UA_STRING_ALLOC(resultIndex.c_str()); + } + else + { + tmp->indexRange=UA_STRING_ALLOC(""); + } + + tmp->value.hasValue=true; + buildValue(pAo->Param1,fValue,tmp->value.value); + tmp->value.hasStatus=true; + tmp->value.status=UA_STATUSCODE_GOOD; + + BatchRequest(tmp,1,"AoCmdProcess"); + UA_WriteValue_delete(tmp); + + } + +} + +void CIEC62541DataProcThread::DoCmdProcess(CFesRtuPtr ptrRtu) +{ + enum {BUF_SIZE = 20}; + SFesRxDoCmd arrCmd[BUF_SIZE]; + int nCmdCount = ptrRtu->ReadRxDoCmd(BUF_SIZE,&arrCmd[0]); //为了让缓冲区指令尽快执行 + + for(int i = 0; i < nCmdCount; i++) + { + + SFesTxDoCmd retCmd; + SFesDo *pDo = NULL; + SFesRxDoCmd& cmd=arrCmd[i]; + strcpy(retCmd.TableName, cmd.TableName); + strcpy(retCmd.ColumnName, cmd.ColumnName); + strcpy(retCmd.TagName, cmd.TagName); + strcpy(retCmd.RtuName, cmd.RtuName); + retCmd.CtrlDir = cmd.CtrlDir; + retCmd.RtuNo = cmd.RtuNo; + retCmd.PointID = cmd.PointID; + retCmd.FwSubSystem = cmd.FwSubSystem; + retCmd.FwRtuNo = cmd.FwRtuNo; + retCmd.FwPointNo = cmd.FwPointNo; + retCmd.SubSystem = cmd.SubSystem; + retCmd.CtrlActType = cmd.CtrlActType; + + pDo = GetFesDoByPointNo(m_ptrCurRtu, cmd.PointID); + + if(pDo == NULL) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + //return failed to scada + retCmd.retStatus = CN_ControlPointErr; + sprintf(retCmd.strParam, I18N_C("遥调失败!找不到遥调点")); + m_ptrCFesBase->WritexDoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调失败!RtuNo:%d 找不到遥调点:%d", getRtuNo(), cmd.PointID); + return; + } + + if (cmd.CtrlActType != CN_ControlExecute) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + retCmd.retStatus = CN_ControlFailed; + sprintf(retCmd.strParam, I18N_C("遥调控制命令错误!")); + m_ptrCFesBase->WritexDoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调控制命令错误! RtuNo:%d 遥调点:%d CtrlActType=%d", getRtuNo(), cmd.PointID,cmd.CtrlActType); + return; + } + + + + int doValue = cmd.iValue; + + UA_WriteValue* tmp; + UA_WriteValue_init(tmp); + tmp->attributeId=UA_ATTRIBUTEID_VALUE; + buildNodeId(pDo->Param2,pDo->szResParam1,tmp->nodeId); + std::string resultIndex; + if(hasDataIndex(pDo->szResParam1,resultIndex)) + { + tmp->indexRange=UA_STRING_ALLOC(resultIndex.c_str()); + } + else + { + tmp->indexRange=UA_STRING_ALLOC(""); + } + + tmp->value.hasValue=true; + buildValue(pDo->Param1,doValue,tmp->value.value); + tmp->value.hasStatus=true; + tmp->value.status=UA_STATUSCODE_GOOD; + + BatchRequest(tmp,1,"DoCmdProcess"); + UA_WriteValue_delete(tmp); + + } + +} + +void CIEC62541DataProcThread::MoCmdProcess(CFesRtuPtr ptrRtu) +{ + enum {BUF_SIZE = 20}; + SFesRxMoCmd arrCmd[BUF_SIZE]; + int nCmdCount = ptrRtu->ReadRxMoCmd(BUF_SIZE,&arrCmd[0]); //为了让缓冲区指令尽快执行 + + for(int i = 0; i < nCmdCount; i++) + { + + SFesTxMoCmd retCmd; + SFesMo *pMo = NULL; + SFesRxMoCmd& cmd=arrCmd[i]; + strcpy(retCmd.TableName, cmd.TableName); + strcpy(retCmd.ColumnName, cmd.ColumnName); + strcpy(retCmd.TagName, cmd.TagName); + strcpy(retCmd.RtuName, cmd.RtuName); + retCmd.CtrlDir = cmd.CtrlDir; + retCmd.RtuNo = cmd.RtuNo; + retCmd.PointID = cmd.PointID; + retCmd.FwSubSystem = cmd.FwSubSystem; + retCmd.FwRtuNo = cmd.FwRtuNo; + retCmd.FwPointNo = cmd.FwPointNo; + retCmd.SubSystem = cmd.SubSystem; + retCmd.CtrlActType = cmd.CtrlActType; + + pMo = GetFesMoByPointNo(m_ptrCurRtu, cmd.PointID); + + if(pMo == NULL) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + //return failed to scada + retCmd.retStatus = CN_ControlPointErr; + sprintf(retCmd.strParam, I18N_C("遥调失败!找不到遥调点")); + m_ptrCFesBase->WritexMoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调失败!RtuNo:%d 找不到遥调点:%d", getRtuNo(), cmd.PointID); + return; + } + + if (cmd.CtrlActType != CN_ControlExecute) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + retCmd.retStatus = CN_ControlFailed; + sprintf(retCmd.strParam, I18N_C("遥调控制命令错误!")); + m_ptrCFesBase->WritexMoRespCmdBuf(1, &retCmd); + } + + LOGERROR("CIEC62541:遥调控制命令错误! RtuNo:%d 遥调点:%d CtrlActType=%d", getRtuNo(), cmd.PointID,cmd.CtrlActType); + return; + } + + + //< 系数和量程的合法性在初始化时已经校验 + float fValue = (cmd.iValue - pMo->Base) / pMo->Coeff; + if((fValue < pMo->MinRange) || (fValue > pMo->MaxRange)) + { + if(cmd.TagtState != CTRL_TYPE_NWAIT_ACK) + { + retCmd.retStatus = CN_ControlPointErr; //return failed to scada + sprintf(retCmd.strParam, I18N_C("遥调失败!设置值超出量程")); + m_ptrCFesBase->WritexMoRespCmdBuf(1, &retCmd); + } + + LOGINFO("CIEC62541:遥调失败,设置值超出量程!RtuNo:%d 遥调点:%d",getRtuNo(), cmd.PointID); + return; + } + + UA_WriteValue* tmp; + UA_WriteValue_init(tmp); + tmp->attributeId=UA_ATTRIBUTEID_VALUE; + buildNodeId(pMo->Param2,pMo->szResParam1,tmp->nodeId); + std::string resultIndex; + if(hasDataIndex(pMo->szResParam1,resultIndex)) + { + tmp->indexRange=UA_STRING_ALLOC(resultIndex.c_str()); + } + else + { + tmp->indexRange=UA_STRING_ALLOC(""); + } + + tmp->value.hasValue=true; + buildValue(pMo->Param1,fValue,tmp->value.value); + tmp->value.hasStatus=true; + tmp->value.status=UA_STATUSCODE_GOOD; + + BatchRequest(tmp,1,"MoCmdProcess"); + UA_WriteValue_delete(tmp); + + } + +} + +bool CIEC62541DataProcThread::hasDataIndex(const string &tagStr, string &resultIndex) +{ + size_t pos = tagStr.find('!'); + if(pos != std::string::npos) + { + std::string preStr = tagStr.substr(0, pos); + + size_t start = preStr.find('['); + size_t end = preStr.find(']'); + + if(start != std::string::npos&&end != std::string::npos) + { + resultIndex = preStr.substr(start + 1, end - start - 1); + } + else + { + return false; + } + } + + return true; +} + +int CIEC62541DataProcThread::buildNodeId(int nodeIdType, const string &tagStr, UA_NodeId &nodeId) +{ + string strNodeId=""; + string namespaceIndex="0"; + size_t pos = tagStr.find('!'); + if(pos != std::string::npos) + { + strNodeId = tagStr.substr(pos + 1); + std::string preStr = tagStr.substr(0, pos); + + size_t pos2 = tagStr.find('['); + + if(pos2!=std::string::npos) + { + namespaceIndex=preStr.substr(0, pos2); + } + else + { + namespaceIndex=preStr; + } + + if(nodeIdType==UA_NODEIDTYPE_NUMERIC) + { + nodeId=UA_NODEID_NUMERIC(atoi(namespaceIndex.c_str()), atoi(strNodeId.c_str())); + } + else if(nodeIdType==UA_NODEIDTYPE_STRING) + { + nodeId=UA_NODEID_STRING_ALLOC(atoi(namespaceIndex.c_str()), strNodeId.c_str()); + }else if(nodeIdType==UA_NODEIDTYPE_GUID) + { + nodeId=UA_NODEID_GUID(atoi(namespaceIndex.c_str()), UA_GUID(strNodeId.c_str())); + }else + { + LOGERROR("COpcUaDataProcThread ChanNo=%d get bad tagStr(%s) ,nodeIdType is not imple ", m_ptrFesChan->m_Param.ChanNo,tagStr.c_str()); + return iotFailed; + } + + return iotSuccess; + } + else + { + LOGERROR("COpcUaDataProcThread ChanNo=%d get bad tagStr(%s) ,due to not find (!) ", m_ptrFesChan->m_Param.ChanNo,tagStr.c_str()); + return iotFailed; + } +} + +int CIEC62541DataProcThread::buildValue(int dataType, double curValue, UA_Variant &value) +{ + UA_Variant_init(&value); + DataType enumDataType=static_cast(dataType); + switch (enumDataType) { + case SByte:{ + UA_SByte val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_SBYTE]); + break; + } + case Int16:{ + UA_Int16 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_INT16]); + break; + } + + case Int32:{ + UA_Int32 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_INT32]); + break; + } + + case Int64:{ + UA_Int64 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_INT64]); + break; + } + + case Byte:{ + UA_Byte val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_BYTE]); + break; + } + + case UInt16:{ + UA_UInt16 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_UINT16]); + break; + } + + case UInt32:{ + UA_UInt32 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_UINT32]); + break; + } + + case UInt64:{ + UA_UInt64 val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_UINT64]); + break; + } + + case Float:{ + UA_Float val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_FLOAT]); + break; + } + + case Double:{ + UA_Variant_setScalarCopy(&value, &curValue, &UA_TYPES[UA_TYPES_DOUBLE]); + break; + } + + case Boolean:{ + UA_Boolean val = static_cast(curValue); + UA_Variant_setScalarCopy(&value, &val, &UA_TYPES[UA_TYPES_BOOLEAN]); + break; + } + + default: + LOGERROR("CIEC62541DataProcThread ChanNo=%d DataType(%d) not imple ", m_ptrFesChan->m_Param.ChanNo,(int)enumDataType); + return iotFailed; + break; + } + + + return iotSuccess; +} + +void CIEC62541DataProcThread::BatchRequest(UA_WriteValue *ptrWriteValue, size_t writeSize, string strFlag) +{ + UA_WriteRequest request; + UA_WriteRequest_init(&request); + request.nodesToWrite =ptrWriteValue; + request.nodesToWriteSize = writeSize; + + UA_WriteResponse response=UA_Client_Service_write(m_ptrUAClient,request); + if(response.responseHeader.serviceResult!=UA_STATUSCODE_GOOD||response.resultsSize == 0) + { + std::string statusMessage = getStatusMessage(response.responseHeader.serviceResult); + LOGERROR("CIEC62541DataProcThread ChanNo=%d (%s) writeRequest faild err(%s)", m_ptrFesChan->m_Param.ChanNo,strFlag.c_str(),statusMessage.c_str()); + } + + UA_WriteResponse_clear(&response); +} + +void CIEC62541DataProcThread::initNumericNodeId(int64 indexReadNodeId,int64 pointNo, string &strNsNode,string &nsStr, string &nodeIdStr, + boost::container::map &mapNumNodeIdInit, boost::container::map &mapNumNodeIdIndex, boost::container::map& indexMap) +{ + + UA_ReadValueId* tmp=&m_ptrReadNodeIds[indexReadNodeId]; + UA_ReadValueId_init(tmp); + m_ptrReadNodeIds[indexReadNodeId].attributeId = UA_ATTRIBUTEID_VALUE; + m_ptrReadNodeIds[indexReadNodeId].nodeId = UA_NODEID_NUMERIC(atoi(nsStr.c_str()), atoi(nodeIdStr.c_str())); + mapNumNodeIdInit[strNsNode]=true; + indexMap.emplace(pointNo,indexReadNodeId); + mapNumNodeIdIndex.emplace(strNsNode,indexReadNodeId); +} + + + +int CIEC62541DataProcThread::getChannelNo() +{ + return m_ptrFesChan->m_Param.ChanNo; +} +int CIEC62541DataProcThread::getRtuNo() +{ + return m_ptrCurRtu->m_Param.RtuNo; +} + +} + + + + diff --git a/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.h b/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.h new file mode 100644 index 00000000..46487666 --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/IEC62541DataProcThread.h @@ -0,0 +1,122 @@ +#pragma once + +#include "FesDef.h" +#include "FesBase.h" +#include "ProtocolBase.h" +#include "IEC62541common.h" +#include "open62541/client.h" +#include "open62541/client_highlevel.h" +#include "open62541/client_config_default.h" +#include "open62541/config.h" +#include "boost/container/map.hpp" + +namespace fes_iec62541_client { +class CIEC62541DataProcThread : public CTimerThreadBase,CProtocolBase +{ +public: + CIEC62541DataProcThread(CFesBase *ptrCFesBase,const CFesChanPtr &ptrChan,const SIEC62541AppConfParam &stConfParam); + virtual ~CIEC62541DataProcThread(); + + /* + @brief 执行execute函数前的处理 + */ + virtual int beforeExecute(); + /* + @brief 业务处理函数,必须继承实现自己的业务逻辑 + */ + virtual void execute(); + + virtual void beforeQuit(); + +public: + /** + * @brief 初始化 + * + * @return 成功返回iotSuccess + */ + int init(); + + /** + * @brief 获取当前通道号 + * + * @return 返回通道号 + */ + int getChannelNo(); + int getRtuNo(); + + +private: + CFesBase* m_ptrCFesBase; + CFesChanPtr m_ptrFesChan; //主通道数据区。如果存在备通道,每次发送接收数据时需要得到当前使用的通道数据 + CFesChanPtr m_ptrCurChan; //当前使用通道数据区。如果存在备通,每次发送接收数据时需要得到当前使用的通道数据 + CFesRtuPtr m_ptrCurRtu; //当前使用RTU数据区,本协议每个通道对应一个RTU数据,所以不需要轮询处理。 + + SIEC62541AppData m_AppData; //协议内部数据结构 + SIEC62541AppConfParam m_stRtuParam; //Rtu配置参数 + + + UA_Client *m_ptrUAClient; + bool m_bReady; + bool m_bConnected; + + size_t m_cntReadNodeId; + boost::shared_ptr m_ptrReadNodeIds; + + boost::container::map m_indexMapDI;//<采集表索引,m_readNodeIds索引> + boost::container::map m_indexMapAI;//<采集表索引,m_readNodeIds索引> + boost::container::map m_indexMapMI;//<采集表索引,m_readNodeIds索引> + boost::container::map m_indexMapACC;//<采集表索引,m_readNodeIds索引> + +private: + int initClient(); + std::string getStatusMessage(UA_StatusCode status); + + //先处理命令 + int handleCommand(); + + //批量请求数据 + int batchRequestData(); + void initReadNodeIds(); + + int getNodeIdByString(const string& tagStr,std::string& namespaceIndex,std::string& nodeId); + + + void initNumericNodeId(int64 indexReadNodeId,int64 pointNo,string &strNsNode,std::string& nsStr,std::string& nodeIdStr,boost::container::map& mapNumNodeIdInit, + boost::container::map& mapNumNodeIdIndex,boost::container::map& indexMap); + + void initStringNodeId(int64 indexReadNodeId,int64 pointNo,string &strNsNode,std::string& nsStr,std::string& nodeIdStr,boost::container::map& mapStringNodeIdInit, + boost::container::map& mapStringNodeIdIndex,boost::container::map& indexMap); + + void initGUIDNodeId(int64 indexReadNodeId,int64 pointNo,string &strNsNode,std::string& nsStr,std::string& nodeIdStr,boost::container::map& mapStringNodeIdInit, + boost::container::map& mapStringNodeIdIndex,boost::container::map& indexMap); + + + void procDiData(UA_ReadResponse& response); + void procAiData(UA_ReadResponse& response); + void procMiData(UA_ReadResponse& response); + void procAccData(UA_ReadResponse& response); + + int getValue(const UA_DataValue* value,const std::vector& indexVec,DataType dataType,double& result); + + + int calculateIndex(const UA_DataValue* value,const std::vector& indexVec,int64& resultOffset); + + bool getDataIndex(const string& tagStr,std::vector& indexVec); + + void AoCmdProcess(CFesRtuPtr ptrRtu); + void DoCmdProcess(CFesRtuPtr ptrRtu); + void MoCmdProcess(CFesRtuPtr ptrRtu); + + bool hasDataIndex(const string &tagStr, string &resultIndex); + int buildNodeId(int nodeIdType, const string &tagStr,UA_NodeId& nodeId); + int buildValue(int dataType, double curValue, UA_Variant &value); + + + void BatchRequest(UA_WriteValue *ptrWriteValue, size_t writeSize, std::string strFlag); + +}; + + +typedef boost::shared_ptr CIEC62541DataProcThreadPtr; +typedef std::vector CIEC62541DataProcThreadPtrSeq; +} diff --git a/product/src/fes/protocol/iec62541_client/IEC62541common.h b/product/src/fes/protocol/iec62541_client/IEC62541common.h new file mode 100644 index 00000000..a4bb16d6 --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/IEC62541common.h @@ -0,0 +1,52 @@ +#pragma once +#include "FesDef.h" +#include "FesBase.h" +#include "open62541/client.h" +#include + + + +const int CN_IEC62541_MaxProcDataNum = 500; + +namespace fes_iec62541_client { + + +enum DataType +{ + SByte=1, + Int16, + Int32, + Int64, + Byte, + UInt16, + UInt32, + UInt64, + Float, + Double, + Boolean, + //String, + //Datetime +}; + + +class CIEC62541DataProcThread; +typedef struct _SIEC62541AppConfParam +{ + _SIEC62541AppConfParam() + { + + } + +}SIEC62541AppConfParam,*P_SIEC62541AppConfParam; + + +typedef struct _SIEC62541AppData +{ + _SIEC62541AppData() + { + + } + +}SIEC62541AppData,*P_SIEC62541AppData; + +} diff --git a/product/src/fes/protocol/iec62541_client/iec62541_client.pro b/product/src/fes/protocol/iec62541_client/iec62541_client.pro new file mode 100644 index 00000000..9a032ff4 --- /dev/null +++ b/product/src/fes/protocol/iec62541_client/iec62541_client.pro @@ -0,0 +1,41 @@ +# ARM板上资源有限,不会与云平台混用,不编译 +message("Compile only in x86 environment") +# requires(contains(QMAKE_HOST.arch, x86_64)) +requires(!contains(QMAKE_HOST.arch, aarch64):!linux-aarch64*) + +QT -= core gui +CONFIG -= qt + +TARGET = iec62541_client +TEMPLATE = lib + +SOURCES += \ + IEC62541.cpp \ + IEC62541DataProcThread.cpp + + +HEADERS += \ + IEC62541.h \ + IEC62541DataProcThread.h \ + IEC62541common.h + + +INCLUDEPATH += ../../include/ +INCLUDEPATH += ../../include/open62541 + +LIBS += -lboost_system -lboost_thread -lboost_locale -lboost_chrono +LIBS += -lpub_utility_api -lpub_logger_api -llog4cplus -lprotocolbase -lrdb_api +LIBS += -lopen62541 -lhal-shared + +DEFINES += PROTOCOLBASE_API_EXPORTS +include($$PWD/../../../idl_files/idl_files.pri) + + +#------------------------------------------------------------------- +COMMON_PRI=$$PWD/../../../common.pri +exists($$COMMON_PRI) { + include($$COMMON_PRI) +}else { + error("FATAL error: can not find common.pri") +} +