266 lines
7.8 KiB
C++
266 lines
7.8 KiB
C++
#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<fes_iec62541_client::CIEC62541DataProcThread>(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;
|
||
}
|