#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; }