2025-03-13 10:13:07 +08:00

748 lines
22 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.

/******************************************************************************//**
* @file FbdDiagDataImpl.cpp
* @brief 功能块图Diagram数据接口实现
* @author yikenan
* @version 1.0
* @date 2020/12/7
**********************************************************************************/
//< 屏蔽Protobuf编译告警
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4100)
#endif
#include "FBD.pb.h"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "boost/weak_ptr.hpp"
#include "app_fbd/fbd_common/FbdSysInfoApi.h"
#include "FbdDiagDataImpl.h"
namespace iot_app
{
namespace app_fbd
{
//< 弱指针,观察者模式
static boost::weak_ptr<CFbdDiagDataImpl> g_wpSingleton;
//< 保护 g_wpSingleton
static boost::mutex g_mutexSingleton;
//< 获取单例
FBD_COMMON_API CFbdDiagDataApiPtr getFbdDiagDataApi()
{
CFbdDiagDataImplPtr spInst = g_wpSingleton.lock();
if ( nullptr != spInst )
return spInst;
boost::mutex::scoped_lock lock( g_mutexSingleton );
spInst = g_wpSingleton.lock();
if ( nullptr != spInst )
return spInst;
spInst = boost::make_shared<CFbdDiagDataImpl>();
if ( iotSuccess == spInst->initialize())
{
g_wpSingleton = spInst;
return spInst;
}
return nullptr;
}
/***********************************************************************************************/
CFbdDiagDataImpl::CFbdDiagDataImpl()
: m_pRdbTableMng( nullptr )
{
m_pMutexModInfoTable = new boost::shared_mutex;
m_pMutexModInputTable = new boost::shared_mutex;
m_pMutexModOutputTable = new boost::shared_mutex;
m_pMutexModPropTable = new boost::shared_mutex;
m_pMutexGlobalVarMap = new boost::shared_mutex;
}
CFbdDiagDataImpl::~CFbdDiagDataImpl()
{
delete m_pRdbTableMng;
m_pRdbTableMng = nullptr;
delete m_pMutexModInfoTable;
m_pMutexModInfoTable = nullptr;
delete m_pMutexModInputTable;
m_pMutexModInputTable = nullptr;
delete m_pMutexModOutputTable;
m_pMutexModOutputTable = nullptr;
delete m_pMutexModPropTable;
m_pMutexModPropTable = nullptr;
delete m_pMutexGlobalVarMap;
m_pMutexGlobalVarMap = nullptr;
}
int CFbdDiagDataImpl::initialize()
{
if ( nullptr == m_pRdbTableMng )
{
CFbdSysInfoApiPtr ptrSysInfo = getFbdSysInfoApi();
if ( nullptr == ptrSysInfo || ptrSysInfo->getCurrentRunAppInfo().strAppName.empty())
{
LOGERROR( "initialize(): 系统信息非预期,检查程序!" );
return iotFailed;
}
m_pRdbTableMng = new iot_dbms::CRdbTableMng( getFbdSysInfoApi()->getCurrentRunAppInfo().strAppName );
}
if ( nullptr == m_pRdbTableMng || nullptr == m_pMutexModInfoTable || nullptr == m_pMutexModInputTable
|| nullptr == m_pMutexModOutputTable || nullptr == m_pMutexModPropTable )
{
LOGERROR( "initialize(): 空指针,非预期,检查程序!" );
return iotFailed;
}
return iotSuccess;
}
int CFbdDiagDataImpl::getModProperty( const SFbdModPropKey &stPropertyKey, std::string &strValue ) const
{
strValue.clear();
if ( !stPropertyKey.isValid())
{
LOGERROR( "getModProperty(): 无效的输入 stPropertyKey返回失败" );
return iotFailed;
}
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModInfoTable );
const auto &indexKey = m_objModPropTable.get<SFbdModProperty_Key>();
const auto it = indexKey.find( stPropertyKey );
if ( indexKey.end() == it )
{
LOGERROR( "getModProperty(): m_objModPropTable 中未找到记录 Key=[%s]",
stPropertyKey.toString().c_str());
return iotFailed;
}
strValue = ( *it )->m_strValue;
return iotSuccess;
}
int CFbdDiagDataImpl::getValKeyByModInput( const SFbdModInputKey &stInputKey, SFbdValueKey &stValueKey ) const
{
stValueKey.m_ptrModOutput = nullptr;
if ( !stInputKey.isValid())
{
LOGERROR( "getValKeyByModInput(): 无效的输入 stInputKey返回失败" );
return iotFailed;
}
SFbdModOutputKey stOutputKey;
{
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModInputTable );
const auto &indexKey = m_objModInputTable.get<SFbdModInput_Key>();
const auto it = indexKey.find( stInputKey );
if ( indexKey.end() == it )
{
LOGERROR( "getValKeyByModInput(): m_objModInputTable 中未找到记录 Key=[%s]",
stInputKey.toString().c_str());
return iotFailed;
}
stOutputKey = ( *it )->m_stOutputKey;
}
{
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const auto &indexKey = m_objModOutputTable.get<SFbdModOutput_Key>();
const auto it = indexKey.find( stOutputKey );
if ( indexKey.end() == it )
{
LOGERROR( "getValKeyByModInput(): m_objModOutputTable 中未找到记录 Key=[%s]",
stOutputKey.toString().c_str());
return iotFailed;
}
stValueKey.m_bWriteable = false;
stValueKey.m_ptrModOutput = *it;
}
if ( stValueKey.isValid())
return iotSuccess;
LOGERROR( "getValKeyByModInput(): 无效的输出,检查程序!" );
return iotFailed;
}
int CFbdDiagDataImpl::getValKeyByModOutput( const SFbdModOutputKey &stOutputKey, SFbdValueKey &stValueKey ) const
{
stValueKey.m_ptrModOutput = nullptr;
if ( !stOutputKey.isValid())
{
LOGERROR( "getValKeyByModOutput(): 无效的输入 stOutputKey返回失败" );
return iotFailed;
}
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const auto &indexKey = m_objModOutputTable.get<SFbdModOutput_Key>();
const auto it = indexKey.find( stOutputKey );
if ( indexKey.end() == it )
{
LOGERROR( "getValKeyByModOutput(): m_objModOutputTable 中未找到记录 Key=[%s]",
stOutputKey.toString().c_str());
return iotFailed;
}
stValueKey.m_bWriteable = true;
stValueKey.m_ptrModOutput = *it;
if ( stValueKey.isValid())
return iotSuccess;
LOGERROR( "getValKeyByModOutput(): 无效的输出,检查程序!" );
return iotFailed;
}
int CFbdDiagDataImpl::getNumericValByKey( const SFbdValueKey &stValueKey, SFbdNumericValue &stValAndSta ) const
{
stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid;
if ( !stValueKey.isValid())
{
LOGERROR( "getNumericValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const SFbdNumericValue *pValue =
boost::any_cast<SFbdNumericValue>( &( stValueKey.m_ptrModOutput->m_anyOutputValue ));
if ( nullptr == pValue )
{
LOGERROR( "getNumericValByKey(): 类型不一致key=[%s],type=[%s]",
stValueKey.toString().c_str(),
stValueKey.m_ptrModOutput->m_anyOutputValue.type().name());
return iotFailed;
}
stValAndSta = *pValue;
return iotSuccess;
}
int CFbdDiagDataImpl::setNumericValByKey( const SFbdValueKey &stValueKey, const SFbdNumericValue &stValAndSta )
{
if ( !stValueKey.isValid())
{
LOGERROR( "setNumericValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
if ( !stValueKey.m_bWriteable )
{
LOGERROR( "setNumericValByKey(): 非可写 Key" );
return iotFailed;
}
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::getStringValByKey( const SFbdValueKey &stValueKey, SFbdStringValue &stValAndSta ) const
{
stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid;
if ( !stValueKey.isValid())
{
LOGERROR( "getStringValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const SFbdStringValue *pValue =
boost::any_cast<SFbdStringValue>( &( stValueKey.m_ptrModOutput->m_anyOutputValue ));
if ( nullptr == pValue )
{
LOGERROR( "getStringValByKey(): 类型不一致key=[%s],type=[%s]",
stValueKey.toString().c_str(),
stValueKey.m_ptrModOutput->m_anyOutputValue.type().name());
return iotFailed;
}
stValAndSta = *pValue;
return iotSuccess;
}
int CFbdDiagDataImpl::setStringValByKey( const SFbdValueKey &stValueKey, const SFbdStringValue &stValAndSta )
{
if ( !stValueKey.isValid())
{
LOGERROR( "setStringValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
if ( !stValueKey.m_bWriteable )
{
LOGERROR( "setStringValByKey(): 非可写 Key" );
return iotFailed;
}
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::getAlarmValByKey( const SFbdValueKey &stValueKey, SFbdAlarmValue &stValAndSta ) const
{
stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid;
if ( !stValueKey.isValid())
{
LOGERROR( "getAlarmValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const SFbdAlarmValue *pValue =
boost::any_cast<SFbdAlarmValue>( &( stValueKey.m_ptrModOutput->m_anyOutputValue ));
if ( nullptr == pValue )
{
LOGERROR( "getAlarmValByKey(): 类型不一致key=[%s],type=[%s]",
stValueKey.toString().c_str(),
stValueKey.m_ptrModOutput->m_anyOutputValue.type().name());
return iotFailed;
}
stValAndSta = *pValue;
return iotSuccess;
}
int CFbdDiagDataImpl::setAlarmValByKey( const SFbdValueKey &stValueKey, const SFbdAlarmValue &stValAndSta )
{
if ( !stValueKey.isValid())
{
LOGERROR( "setAlarmValByKey(): 无效的输入 stValueKey返回失败" );
return iotFailed;
}
if ( !stValueKey.m_bWriteable )
{
LOGERROR( "setAlarmValByKey(): 非可写 Key" );
return iotFailed;
}
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
stValueKey.m_ptrModOutput->m_anyOutputValue = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::getGlobalNumericValByKey(const std::string &strVarName, SFbdNumericValue &stValAndSta) const
{
stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid;
//< 读锁
boost::shared_lock<boost::shared_mutex> lock(*m_pMutexGlobalVarMap);
auto iter = m_mapGlobalVar.find(strVarName);
if(iter == m_mapGlobalVar.end())
{
return iotFailed;
}
const SFbdNumericValue *pValue = boost::any_cast<SFbdNumericValue>(&(iter->second));
if ( nullptr == pValue )
{
LOGERROR( "getGlobalNumericValByKey(): 类型不一致key=[%s],type=[%s]",
strVarName.c_str(),
iter->second.type().name());
return iotFailed;
}
stValAndSta = *pValue;
return iotSuccess;
}
int CFbdDiagDataImpl::setGlobalNumericValByKey(const std::string &strVarName, const SFbdNumericValue &stValAndSta)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter == m_mapGlobalVar.end())
{
return iotFailed;
}
iter->second = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::regGlobalNumericValByKey(const std::string &strVarName, const SFbdNumericValue &stValAndSta)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter != m_mapGlobalVar.end())
{
LOGINFO( "regGlobalNumericValByKey 变量[%s]已经存在",strVarName.c_str() );
//检查类型是否一致
if(iter->second.type() != typeid(SFbdNumericValue))
{
LOGERROR( "regGlobalNumericValByKey(): 类型不一致key=[%s],type=[%s]",
strVarName.c_str(),
iter->second.type().name());
return iotFBDErr_GlobalVarTypeMismatch;
}
return iotFBDErr_GlobalVarAlreadyExist;
}
m_mapGlobalVar[strVarName] = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::unregGlobalNumericVar(const std::string &strVarName)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter != m_mapGlobalVar.end())
{
m_mapGlobalVar.erase(iter);
}
return iotSuccess;
}
int CFbdDiagDataImpl::getGlobalStringValByKey(const std::string &strVarName, SFbdStringValue &stValAndSta) const
{
stValAndSta.m_nStatus = CN_FBD_STATUS_Invalid;
//< 读锁
boost::shared_lock<boost::shared_mutex> lock(*m_pMutexGlobalVarMap);
auto iter = m_mapGlobalVar.find(strVarName);
if(iter == m_mapGlobalVar.end())
{
return iotFailed;
}
const SFbdStringValue *pValue = boost::any_cast<SFbdStringValue>(&(iter->second));
if ( nullptr == pValue )
{
LOGERROR( "getGlobalStringValByKey(): 类型不一致key=[%s],type=[%s]",
strVarName.c_str(),
iter->second.type().name());
return iotFailed;
}
stValAndSta = *pValue;
return iotSuccess;
}
int CFbdDiagDataImpl::setGlobalStringValByKey(const std::string &strVarName, const SFbdStringValue &stValAndSta)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter == m_mapGlobalVar.end())
{
return iotFailed;
}
iter->second = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::regGlobalStringValByKey(const std::string &strVarName, const SFbdStringValue &stValAndSta)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter != m_mapGlobalVar.end())
{
LOGINFO( "regGlobalStringValByKey 变量[%s]已经存在",strVarName.c_str() );
//检查类型是否一致
if(iter->second.type() != typeid(SFbdStringValue))
{
LOGERROR( "regGlobalStringValByKey(): 类型不一致key=[%s],type=[%s]",
strVarName.c_str(),
iter->second.type().name());
return iotFBDErr_GlobalVarTypeMismatch;
}
return iotFBDErr_GlobalVarAlreadyExist;
}
m_mapGlobalVar[strVarName] = stValAndSta;
return iotSuccess;
}
int CFbdDiagDataImpl::unregGlobalStringVar(const std::string &strVarName)
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lock( *m_pMutexGlobalVarMap );
auto iter = m_mapGlobalVar.find(strVarName);
if(iter != m_mapGlobalVar.end())
{
m_mapGlobalVar.erase(iter);
}
return iotSuccess;
}
/***********************************************************************************************/
int CFbdDiagDataImpl::getAllGroupInfo( std::vector<SFbdGroupInfo> &vecGrpInfo ) const
{
static const std::string strTableName = CN_TN_FbdGroup;
iot_dbms::CRdbTableMngLockGuard lock( *m_pRdbTableMng, strTableName );
if ( !m_pRdbTableMng->selectAllColumnNoCondition( strTableName, vecGrpInfo ))
{
LOGERROR( "getAllGroupInfo(): 从RDB获取FBD组信息失败" );
return iotFailed;
}
return iotSuccess;
}
int CFbdDiagDataImpl::getModuleInfoByGroup( const int nFbdGrpId, std::vector<SFbdModInfo> &vecModuleInfo ) const
{
vecModuleInfo.clear();
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModInfoTable );
const auto &indexGrpId = m_objModInfoTable.get<SFbdModInfo_GrpId>();
const size_t nCount = indexGrpId.count( nFbdGrpId );
if ( 0 == nCount )
{
//< 允许空组,不作为错误
LOGWARN( "getModuleInfoByGroup(): m_objModInfoTable 中未找到记录 GroupId=[%d],返回成功", nFbdGrpId );
return iotSuccess;
}
//< 预先分配空间,避免频繁内存移动
vecModuleInfo.reserve( nCount + 1 );
const auto pairRange = indexGrpId.equal_range( nFbdGrpId );
for ( auto it = pairRange.first; pairRange.second != it; ++it )
{
vecModuleInfo.emplace_back( **it );
}
return iotSuccess;
}
int CFbdDiagDataImpl::deleteAllDataByGroup( const int nFbdGrpId )
{
LOGINFO( "deleteAllDataByGroup(): 开始删除组 GrpId=[%d]", nFbdGrpId );
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModInfo( *m_pMutexModInfoTable );
auto &indexGrpId = m_objModInfoTable.get<SFbdModInfo_GrpId>();
const auto pairModInfo = indexGrpId.equal_range( nFbdGrpId );
if ( pairModInfo.first == pairModInfo.second )
{
LOGWARN( "deleteAllDataByGroup(): m_objModInfoTable 中未找到记录 GroupId=[%d],返回成功", nFbdGrpId );
return iotSuccess;
}
//< 按图名删除其他表中的记录
{
//< 用于图名去重
std::set<std::string> setDiagName;
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModInput( *m_pMutexModInputTable );
boost::unique_lock<boost::shared_mutex> lockModOutput( *m_pMutexModOutputTable );
boost::unique_lock<boost::shared_mutex> lockModProp( *m_pMutexModPropTable );
auto &indexDiagName_Input = m_objModInputTable.get<SFbdModInput_DiagName>();
auto &indexDiagName_Output = m_objModOutputTable.get<SFbdModOutput_DiagName>();
auto &indexDiagName_Prop = m_objModPropTable.get<SFbdModProperty_DiagName>();
for ( auto itModInfo = pairModInfo.first; pairModInfo.second != itModInfo; ++itModInfo )
{
const std::string &strDiagName = ( *itModInfo )->getDiagName();
if ( setDiagName.count( strDiagName ) != 0 )
{
continue; //< 剔除重复的图名
}
setDiagName.insert( strDiagName );
indexDiagName_Input.erase( strDiagName );
indexDiagName_Output.erase( strDiagName );
indexDiagName_Prop.erase( strDiagName );
}
}
//< 删除 ModInfoTable 中的记录
indexGrpId.erase( nFbdGrpId );
return iotSuccess;
}
int CFbdDiagDataImpl::insertAllDataByGroup( const SFbdGroupInfo &stGrpInfo, const SFbdGroupData &stGrpData )
{
LOGINFO( "insertAllDataByGroup(): 开始插入组 Id=[%d], BusinessType=[%d], Name=[%s], Desc=[%s]",
stGrpInfo.m_nId, stGrpInfo.m_nBusinessType, stGrpInfo.m_szName, stGrpInfo.m_szDesc );
//< m_objModInfoTable
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModInfo( *m_pMutexModInfoTable );
for ( const auto &ptrModInfo : stGrpData.m_vecPtrModInfo )
{
const auto &pairRc = m_objModInfoTable.insert( ptrModInfo );
if ( !pairRc.second )
{
LOGERROR( "insertAllDataByGroup(): 向 m_objModInfoTable 插入失败 mod_key=[%s]",
ptrModInfo->m_stModKey.toString().c_str());
}
}
}
//< m_objModInputTable
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModInput( *m_pMutexModInputTable );
for ( const auto &ptrModInput : stGrpData.m_vecPtrModInput )
{
const auto &pairRc = m_objModInputTable.insert( ptrModInput );
if ( !pairRc.second )
{
LOGERROR( "insertAllDataByGroup(): 向 m_objModInputTable 插入失败 Key=[%s]",
ptrModInput->m_stInputKey.toString().c_str());
}
}
}
//< m_objModOutputTable
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModOutput( *m_pMutexModOutputTable );
for ( const auto &ptrModOutput : stGrpData.m_vecPtrModOutput )
{
const auto &pairRc = m_objModOutputTable.insert( ptrModOutput );
if ( !pairRc.second )
{
LOGERROR( "insertAllDataByGroup(): 向 m_objModOutputTable 插入失败 Key=[%s]",
ptrModOutput->m_stOutputKey.toString().c_str());
}
}
}
//< m_objModPropTable
{
//< 写锁
boost::unique_lock<boost::shared_mutex> lockModProp( *m_pMutexModPropTable );
for ( const auto &ptrModProp : stGrpData.m_vecPtrModProp )
{
const auto &pairRc = m_objModPropTable.insert( ptrModProp );
if ( !pairRc.second )
{
LOGERROR( "insertAllDataByGroup(): 向 m_objModPropTable 插入失败 Key=[%s]",
ptrModProp->m_stPropKey.toString().c_str());
}
}
}
return iotSuccess;
}
int CFbdDiagDataImpl::getDebugResponse( const iot_idl::SFBDDebugRequest &objReq,
iot_idl::SFBDDebugResponse &objRep )
{
const std::string &strDiagName = objReq.sdiagramname();
objRep.set_ngroupid( objReq.ngroupid());
objRep.set_sdiagramname( strDiagName );
int nStatus;
//< 读锁
boost::shared_lock<boost::shared_mutex> lock( *m_pMutexModOutputTable );
const auto &indexDiagName = m_objModOutputTable.get<SFbdModOutput_DiagName>();
const auto pairModOutput = indexDiagName.equal_range( strDiagName );
for ( auto it = pairModOutput.first; it != pairModOutput.second; ++it )
{
const SFbdModOutput &stModOutput = *( *it );
auto pDbgData = objRep.add_vecblock();
pDbgData->set_sinstancename( stModOutput.m_stOutputKey.m_stModKey.m_strModName );
pDbgData->set_noutportindex( stModOutput.m_stOutputKey.m_nOutputIndex );
stModOutput.getValueString( nStatus, *( pDbgData->mutable_svalue()));
pDbgData->set_nvalid( nStatus );
}
return iotSuccess;
}
} //< namespace app_fbd
} //< namespace iot_app