2026-01-13 17:48:19 +08:00

266 lines
7.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

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

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