[ref]同步

This commit is contained in:
shi_jq 2025-03-13 10:13:07 +08:00
parent 0777279524
commit fbfa28fc2e
75 changed files with 2325 additions and 210 deletions

View File

@ -18,7 +18,7 @@
#include "CAcsCardMng.h"
namespace iot_application
namespace iot_app
{
CAcsCardMng::CAcsCardMng(CAcsDeviceApiImpl *pParent)
@ -237,4 +237,4 @@ void CAcsCardMng::onSetCardCfgFinish(bool bSuccess)
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -17,7 +17,7 @@ typedef unsigned long DWORD;
typedef unsigned int DWORD;
#endif
namespace iot_application
namespace iot_app
{
class CAcsDeviceApiImpl;
@ -55,4 +55,4 @@ private:
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -14,7 +14,7 @@
#include "CAcsDeviceApiImplFactory.h"
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
namespace iot_application
namespace iot_app
{
CAcsDeviceApi::CAcsDeviceApi() :
@ -114,4 +114,4 @@ bool CAcsDeviceApi::enableListenEvents(bool bEnable)
return m_pImpl->enableListenEvents(bEnable);
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -12,7 +12,7 @@
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
namespace iot_application
namespace iot_app
{
CAcsDeviceApi::CAcsDeviceApi() :
@ -74,4 +74,4 @@ bool CAcsDeviceApi::enableListenEvents(bool /*bEnable*/)
return false;
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -18,7 +18,7 @@
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
#include "CAcsDeviceApiImpl.h"
namespace iot_application
namespace iot_app
{
CAcsDeviceApiImpl::CAcsDeviceApiImpl(CAcsDeviceApi *pParent) :
@ -199,14 +199,14 @@ bool CAcsDeviceApiImpl::setUserInfoToDevice(const std::list<CUserInfo> &listUser
delete m_pListUserInfo;
m_pListUserInfo = new std::list<CUserInfo>(listUserInfo);
//< 先将结果全部设为false
for (std::list<iot_application::CUserInfo>::iterator itUser = m_pListUserInfo->begin();
for (std::list<iot_app::CUserInfo>::iterator itUser = m_pListUserInfo->begin();
m_pListUserInfo->end() != itUser; ++itUser)
{
itUser->m_bSetCarSuccess = false;
itUser->m_bSetFaceSuccess = false;
std::list<iot_application::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
for (std::list<iot_application::CFingerprintInfo>::iterator itFp = listFp.begin();
std::list<iot_app::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
for (std::list<iot_app::CFingerprintInfo>::iterator itFp = listFp.begin();
listFp.end() != itFp; ++itFp)
{
itFp->m_bSetSuccess = false;
@ -463,4 +463,4 @@ bool CAcsDeviceApiImpl::enableListenEvents(bool bEnable)
return true;
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -20,7 +20,7 @@ typedef unsigned long DWORD;
typedef unsigned int DWORD;
#endif
namespace iot_application
namespace iot_app
{
class CAcsDeviceApi;
@ -82,4 +82,4 @@ private:
CAcsFingerprintMng m_objFpMng;
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -16,7 +16,7 @@
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
#include "CAcsDeviceApiImplFactory.h"
namespace iot_application
namespace iot_app
{
#ifdef OS_WINDOWS
@ -294,4 +294,4 @@ void CAcsDeviceApiImplFactory::destoryAcsDeviceApiImpl(CAcsDeviceApiImpl **ppObj
releaseGlobal();
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -17,7 +17,7 @@
#include "CAcsDeviceApiImpl.h"
namespace iot_application
namespace iot_app
{
class CAcsDeviceApi;
@ -49,4 +49,4 @@ private:
static std::set<CAcsDeviceApiImpl *> m_setInstance;
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -19,7 +19,7 @@
#include "CAcsFaceMng.h"
namespace iot_application
namespace iot_app
{
CAcsFaceMng::CAcsFaceMng(CAcsDeviceApiImpl *pParent)
@ -435,4 +435,4 @@ void CAcsFaceMng::onSetFaceCfgFinish(bool bSuccess)
//< 无需再启动后续步骤
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -17,7 +17,7 @@ typedef unsigned long DWORD;
typedef unsigned int DWORD;
#endif
namespace iot_application
namespace iot_app
{
class CAcsFaceMng
@ -59,4 +59,4 @@ private:
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -18,7 +18,7 @@
#include "CAcsDeviceApiImpl.h"
#include "CAcsFingerprintMng.h"
namespace iot_application
namespace iot_app
{
CAcsFingerprintMng::CAcsFingerprintMng(CAcsDeviceApiImpl *pParent)
@ -507,4 +507,4 @@ void CAcsFingerprintMng::onSetFpCfgFinish(bool bSuccess)
}
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -17,7 +17,7 @@ typedef unsigned long DWORD;
typedef unsigned int DWORD;
#endif
namespace iot_application
namespace iot_app
{
class CAcsDeviceApiImpl;
@ -63,4 +63,4 @@ private:
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -18,7 +18,7 @@ HEADERS += $$PWD/../../../include/application/app_bio_identify/acs_device_api/Ac
$$PWD/../../../include/application/app_bio_identify/acs_device_api/CAcsDeviceApi.h \
# 当前海康sdk只有X86版本
contains(QMAKE_HOST.arch, x86_64){
contains(QMAKE_HOST.arch, x86_64) : !linux-aarch64*{
HEADERS += CAcsDeviceApiImpl.h \
CAcsDeviceApiImplFactory.h \

View File

@ -9,7 +9,7 @@
#include "BisCommon.h"
namespace iot_application
namespace iot_app
{
} //< namespace iot_application
} //< namespace iot_app

View File

@ -9,9 +9,9 @@
#pragma once
namespace iot_application
namespace iot_app
{
} //< namespace iot_application
} //< namespace iot_app

View File

@ -37,7 +37,7 @@
#include "CAcsWorkThread.h"
#include "CAcsDevice.h"
namespace iot_application
namespace iot_app
{
CAcsDevice::CAcsDevice(CAcsWorkThread *pParent, const char *szTagName,
@ -73,7 +73,7 @@ void CAcsDevice::handleFingerprintInfo(bool bSuccess, size_t nDataLen, const cha
LOGERROR("handleFingerprintInfo(): 服务程序不应运行至此处,检查程序!");
}
void CAcsDevice::handleSetUserInfoResult(const std::list<iot_application::CUserInfo> &listUserInfo, void *pUserData)
void CAcsDevice::handleSetUserInfoResult(const std::list<iot_app::CUserInfo> &listUserInfo, void *pUserData)
{
(void) listUserInfo;
(void) pUserData;
@ -345,4 +345,4 @@ void CAcsDevice::processStateMachine()
}
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -15,12 +15,12 @@
#include "net_msg_bus_api/MsgBusApi.h"
#include "app_bio_identify/acs_device_api/CAcsDeviceApi.h"
namespace iot_application
namespace iot_app
{
class CAcsWorkThread;
class CAcsDevice : private iot_application::CAcsDeviceApi
class CAcsDevice : private iot_app::CAcsDeviceApi
{
public:
CAcsDevice(CAcsWorkThread *pParent, const char *szTagName,
@ -70,7 +70,7 @@ private:
void handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
void handleSetUserInfoResult(const std::list<iot_application::CUserInfo> &listUserInfo, void *pUserData) override;
void handleSetUserInfoResult(const std::list<iot_app::CUserInfo> &listUserInfo, void *pUserData) override;
void handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData) override;
@ -104,5 +104,5 @@ private:
typedef boost::shared_ptr<CAcsDevice> CAcsDevicePtr;
} //< namespace iot_application
} //< namespace iot_app

View File

@ -37,7 +37,7 @@
#include "CAcsWorkThread.h"
namespace iot_application
namespace iot_app
{
CAcsWorkThread::CAcsWorkThread() :
@ -276,5 +276,5 @@ void CAcsWorkThread::handleOneMbMsg()
}
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -17,7 +17,7 @@
#include "CAcsDevice.h"
namespace iot_application
namespace iot_app
{
class CAcsWorkThread : private iot_public::CTimerThreadBase
@ -59,5 +59,5 @@ private:
std::map<std::string, CAcsDevicePtr> m_mapAcsDevice;
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -22,7 +22,7 @@
#define BIS_PROC_NAME "app_bio_identify_srv"
namespace iot_application
namespace iot_app
{
CBioIdentifySrv::CBioIdentifySrv()
@ -346,5 +346,5 @@ int CBioIdentifySrv::getDomainID() const
return m_nDomainID;
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -14,7 +14,7 @@
#include "CBisRedunSw.h"
namespace iot_application
namespace iot_app
{
class CBioIdentifySrv : public iot_public::CBaseService, iot_sys::CProcessQuitInterface
@ -63,5 +63,5 @@ private:
iot_sys::CRedundantMngInterfacePtr m_ptrRedundantMng;
};
} //< namespace iot_application
} //< namespace iot_app

View File

@ -11,9 +11,9 @@
#include "CBisRedunSw.h"
extern iot_application::CBioIdentifySrv *g_pBioIdentifySrv;
extern iot_app::CBioIdentifySrv *g_pBioIdentifySrv;
namespace iot_application
namespace iot_app
{
CBisRedunSw::CBisRedunSw()
@ -43,5 +43,5 @@ int CBisRedunSw::redundantSwitch(bool bMaster, bool bSlave)
return iotSuccess;
}
} //< namespace iot_application
} //< namespace iot_app

View File

@ -13,7 +13,7 @@
#include "CAcsWorkThread.h"
namespace iot_application
namespace iot_app
{
class CBisRedunSw : public ::iot_sys::CRedundantSwitchInterface
@ -32,5 +32,5 @@ private:
typedef boost::shared_ptr<CBisRedunSw> CCBisRedunSwPtr;
} //< namespace iot_application
} //< namespace iot_app

View File

@ -9,11 +9,11 @@
#include "CBioIdentifySrv.h"
iot_application::CBioIdentifySrv *g_pBioIdentifySrv = nullptr;
iot_app::CBioIdentifySrv *g_pBioIdentifySrv = nullptr;
int main(int argc, char *argv[])
{
iot_application::CBioIdentifySrv objApp;
iot_app::CBioIdentifySrv objApp;
g_pBioIdentifySrv = &objApp;
return objApp.main(argc, argv);
}

View File

@ -4,7 +4,7 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
using namespace iot_application;
using namespace iot_app;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow)
@ -12,7 +12,7 @@ MainWindow::MainWindow(QWidget *parent)
ui->setupUi(this);
qRegisterMetaType<std::string>("std::string");
qRegisterMetaType<std::list<iot_application::CUserInfo>>("std::list<iot_application::CUserInfo>");
qRegisterMetaType<std::list<iot_app::CUserInfo>>("std::list<iot_app::CUserInfo>");
qRegisterMetaType<size_t>("size_t");
connect(this, SIGNAL(faceInfoFinish(bool, std::string, void * )),
@ -21,8 +21,8 @@ MainWindow::MainWindow(QWidget *parent)
connect(this, SIGNAL(fingerprintInfoFinish(bool, std::string, void * )),
this, SLOT(on_fingerprintInfoFinish(bool, std::string, void * )));
connect(this, SIGNAL(setUserInfoFinish(std::list<iot_application::CUserInfo>, void * )),
this, SLOT(on_setUserInfoFinish(std::list<iot_application::CUserInfo>, void * )));
connect(this, SIGNAL(setUserInfoFinish(std::list<iot_app::CUserInfo>, void * )),
this, SLOT(on_setUserInfoFinish(std::list<iot_app::CUserInfo>, void * )));
connect(this, SIGNAL(identificationEvent(bool, int, size_t, const char *)),
this, SLOT(on_identificationEvent(bool, int, size_t, const char *)));
@ -49,7 +49,7 @@ void MainWindow::handleFingerprintInfo(bool bSuccess, size_t nDataLen, const cha
emit fingerprintInfoFinish(bSuccess, strData, pUserData);
}
void MainWindow::handleSetUserInfoResult(const std::list<iot_application::CUserInfo> &listUserInfo, void *pUserData)
void MainWindow::handleSetUserInfoResult(const std::list<iot_app::CUserInfo> &listUserInfo, void *pUserData)
{
emit setUserInfoFinish(listUserInfo, pUserData);
}
@ -131,13 +131,13 @@ void MainWindow::on_fingerprintInfoFinish(bool bSuccess, std::string strData, vo
}
}
void MainWindow::on_setUserInfoFinish(std::list<iot_application::CUserInfo> listUserInfo, void *pUserData)
void MainWindow::on_setUserInfoFinish(std::list<iot_app::CUserInfo> listUserInfo, void *pUserData)
{
(void) pUserData;
bool bSuccess = true;
for (std::list<iot_application::CUserInfo>::const_iterator itUser = listUserInfo.cbegin();
for (std::list<iot_app::CUserInfo>::const_iterator itUser = listUserInfo.cbegin();
listUserInfo.cend() != itUser; ++itUser)
{
if (!itUser->m_bSetCarSuccess)
@ -157,8 +157,8 @@ void MainWindow::on_setUserInfoFinish(std::list<iot_application::CUserInfo> list
itUser->m_strName.c_str()));
}
const std::list<iot_application::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
for (std::list<iot_application::CFingerprintInfo>::const_iterator itFp = listFp.cbegin();
const std::list<iot_app::CFingerprintInfo> &listFp = itUser->m_listFingerprint;
for (std::list<iot_app::CFingerprintInfo>::const_iterator itFp = listFp.cbegin();
listFp.cend() != itFp; ++itFp)
{
if (!itFp->m_bSetSuccess)
@ -187,7 +187,7 @@ void MainWindow::on_identificationEvent(bool bPass, int nUserID, size_t nPicData
void MainWindow::on_btnLogin_clicked()
{
if (logInToDevice("192.168.79.135", 8000, "admin", "kbdct@0755"))
if (logInToDevice("192.168.79.135", 8000, "admin", EMS_DEFAULT_PASSWD))
{
QMessageBox::information(this, "", "登录成功!");
}

View File

@ -12,7 +12,7 @@ class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow, private iot_application::CAcsDeviceApi
class MainWindow : public QMainWindow, private iot_app::CAcsDeviceApi
{
Q_OBJECT
@ -25,7 +25,7 @@ private:
void handleFingerprintInfo(bool bSuccess, size_t nDataLen, const char *pData, void *pUserData) override;
void handleSetUserInfoResult(const std::list<iot_application::CUserInfo> &listUserInfo, void *pUserData) override;
void handleSetUserInfoResult(const std::list<iot_app::CUserInfo> &listUserInfo, void *pUserData) override;
void handleIdentificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData) override;
@ -34,7 +34,7 @@ signals:
void fingerprintInfoFinish(bool bSuccess, std::string strData, void *pUserData);
void setUserInfoFinish(std::list<iot_application::CUserInfo> listUserInfo, void *pUserData);
void setUserInfoFinish(std::list<iot_app::CUserInfo> listUserInfo, void *pUserData);
void identificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData);
@ -44,7 +44,7 @@ private slots:
void on_fingerprintInfoFinish(bool bSuccess, std::string strData, void *pUserData);
void on_setUserInfoFinish(std::list<iot_application::CUserInfo> listUserInfo, void *pUserData);
void on_setUserInfoFinish(std::list<iot_app::CUserInfo> listUserInfo, void *pUserData);
void on_identificationEvent(bool bPass, int nUserID, size_t nPicDataLen, const char *pPicData);

View File

@ -5,8 +5,19 @@
*/
#include "boost/filesystem.hpp"
//< 屏蔽xml_parser编译告警
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-copy"
#endif
#include "boost/property_tree/xml_parser.hpp"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "common/Common.h"
#include "pub_logger_api/logger.h"
#include "pub_utility_api/FileUtil.h"

View File

@ -50,6 +50,8 @@ CFbdGrpWorkThread::CFbdGrpWorkThread( CFbdUtilPtr ptrFbdUtil, const SFbdGroupInf
m_stGrpInfo( stGrpInfo )
{
//< 其他成员变量已在头文件设置初值
setDiagram(m_stGrpInfo.m_nId);
setDiagOptCmdApi();
}
@ -66,6 +68,10 @@ CFbdGrpWorkThread::~CFbdGrpWorkThread()
m_mapDllHandle.clear();
m_ptrFbdUtil.reset();
if( m_ptrDiagOptCmd != nullptr )
{
m_ptrDiagOptCmd->removeGroup(m_vecDiagram);
}
delete m_pMbComm;
m_pMbComm = nullptr;
}
@ -83,6 +89,10 @@ void CFbdGrpWorkThread::execute()
it.second->calculate();
}
m_nLastRunFbdUtc = iot_public::getUTCTimeMsec();
if( m_ptrDiagOptCmd != nullptr )
{
m_ptrDiagOptCmd->trigerSendMessage(m_vecDiagram);
}
}
//< 接收并响应调试消息
@ -334,5 +344,21 @@ int CFbdGrpWorkThread::resetModule( bool bMaster )
return iotSuccess;
}
int CFbdGrpWorkThread::setDiagram(const int groupId)
{
return m_ptrFbdUtil->getDiagramNameFromDB(groupId,m_vecDiagram);
}
int CFbdGrpWorkThread::setDiagOptCmdApi()
{
m_ptrDiagOptCmd = getFbdDiagOptCmdApi();
if ( m_ptrDiagOptCmd == nullptr )
{
LOGERROR( "获取Diagram数据接口单例失败" );
return iotFailed;
}
return iotSuccess;
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -11,6 +11,7 @@
#include "app_fbd/fbd_common/BaseModule.h"
#include "FbdUtil.h"
#include "app_fbd/fbd_common/FbdDiagOptCmdApi.h"
namespace iot_app
{
@ -70,6 +71,18 @@ private:
*/
int resetModule( bool bMaster );
/**
@brief 线
@param int groupId
@return iotSuccess,
*/
int setDiagram(const int groupId);
/**
@brief
@return iotSuccess,
*/
int setDiagOptCmdApi();
private:
struct SModInfoOrder
{
@ -91,7 +104,20 @@ private:
inline bool operator<( const SModInfoOrder &rhs ) const
{
return (( m_nLevel < rhs.m_nLevel ) || (( m_nLevel == rhs.m_nLevel ) && m_stModKey < rhs.m_stModKey ));
//< 先按图排序,同一张图按层级排序,同一层级按模块名排序
if(m_stModKey.m_strDiagName != rhs.m_stModKey.m_strDiagName)
{
return m_stModKey.m_strDiagName < rhs.m_stModKey.m_strDiagName;
}
else if(m_nLevel != rhs.m_nLevel)
{
return m_nLevel < rhs.m_nLevel;
}
else
{
return m_stModKey.m_strModName < rhs.m_stModKey.m_strModName;
}
//return (( m_nLevel < rhs.m_nLevel ) || (( m_nLevel == rhs.m_nLevel ) && m_stModKey < rhs.m_stModKey ));
}
};
@ -110,6 +136,9 @@ private:
std::map<std::string, PluginApiFunc> m_mapDllHandle; //< 本组加载的动态库
std::map<SModInfoOrder, CBaseModulePtr> m_mapFuncPtr; //< 本组管理的所有模块对应的对象
std::vector<std::string> m_vecDiagram;//本组管理的图表名
CFbdDiagOptCmdApiPtr m_ptrDiagOptCmd; //< Diagram数据接口
};
typedef boost::shared_ptr<CFbdGrpWorkThread> CFbdGrpWorkThreadPtr;

View File

@ -287,7 +287,7 @@ bool CFbdServerApp::initialize()
//< 初始化翻译
if ( iot_public::initI18N( "/app_fbd/translate", "app_fbd" ))
{
LOGDEBUG( I18N_C( "I18N test\n This is src hardcode. \n int = [%d] , str = [%s]\n" ), 123, "test" );
//LOGDEBUG( I18N_C( "I18N test\n This is src hardcode. \n int = [%d] , str = [%s]\n" ), 123, "test" );
}
else
{

View File

@ -460,5 +460,38 @@ int CFbdUtil::getGroupDataFromDB( const std::vector<SFbdGroupInfo> &vecGrpInfo,
return iotSuccess;
}
int CFbdUtil::getDiagramNameFromDB(const int groupId, std::vector<std::string> &vecDiagramName)
{
//< 析构时会自动关闭连接
iot_dbms::CDbApi objDbConn( DB_CONN_MODEL_READ );
if ( !objDbConn.open())
{
LOGERROR( "打开数据库失败" );
return iotFailed;
}
LOGINFO( "数据库地址=[%s],名称=[%s]", objDbConn.getCurrentDbPara().getHostName().toUtf8().data(),
objDbConn.getCurrentDbPara().getDatabaseName().toUtf8().data());
const QString strCol = objDbConn.addQuoteMarks( "NAME" )+ "," + objDbConn.addQuoteMarks( "ENABLE" );
const QString strSql=QString( "SELECT %1 FROM %2 WHERE %3 = %4 " )
.arg( strCol )
.arg( objDbConn.addQuoteMarks( "FBD_DIAGRAM" ))
.arg( objDbConn.addQuoteMarks( "GROUP_ID" ))
.arg( groupId );
QSqlQuery objQuery;
if ( !objDbConn.execute( strSql, objQuery ))
{
LOGERROR( "查询错误SQL语句如下\n%s", strSql.toUtf8().constData());
return iotFailed;
}
while (objQuery.next()) {
std::string strDiagName = objQuery.value( "NAME" ).toString().toStdString();
vecDiagramName.push_back(strDiagName);
}
return iotSuccess;
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -60,11 +60,19 @@ public:
@brief fbd组的相关配置信息
@param vecGrpInfo FBD组列表
@param mapGrpData FBD组相关信息
@param vecDiagramName FBD组正在运行的图表名
@return iotSuccess,
*/
static int getGroupDataFromDB( const std::vector<SFbdGroupInfo> &vecGrpInfo,
GrpIdToDataInfoMAP &mapGrpData );
GrpIdToDataInfoMAP &mapGrpData);
/**
@brief fbd组的相关配置信息
@param vecdiagram id
@param mapGrpData
@return iotSuccess,
*/
static int getDiagramNameFromDB( const int groupId,std::vector<std::string> &vecDiagramName );
inline int getFbdGroupInfoList( std::vector<SFbdGroupInfo> &vecGrpInfo )
{

View File

@ -115,14 +115,14 @@ void CPointSubThread::execute()
//< 使用接收消息控制运行间隔
m_nRunPeriodMsec = 0;
LOGINFO( "接客啦,干劲十足!" );
LOGINFO( "完成初始化,开始准备接收消息" );
}
}
else
{
if ( cn_nIdleRunPeriod != m_nRunPeriodMsec )
{
LOGINFO( "人问津,消极怠工..." );
LOGINFO( "任务处理,进入空闲模式" );
m_nRunPeriodMsec = cn_nIdleRunPeriod;
}
return;
@ -140,7 +140,7 @@ void CPointSubThread::execute()
return;
}
++m_nLoopBeforClear;
LOGINFO( "无人问津,怠工前周期计数[%d]", m_nLoopBeforClear );
LOGTRACE( "无任务处理,空闲周期计数[%d]", m_nLoopBeforClear );
}
else
{

View File

@ -92,13 +92,13 @@ void CAlarmCltThread::execute()
//< 使用接收消息控制运行间隔
m_nRunPeriodMsec = 0;
LOGINFO( "接客啦,干劲十足!" );
LOGINFO( "完成初始化,开始准备接收消息" );
}
else
{
if ( cn_nIdleRunPeriod != m_nRunPeriodMsec )
{
LOGINFO( "人问津,消极怠工..." );
LOGINFO( "任务处理,进入空闲模式" );
m_nRunPeriodMsec = cn_nIdleRunPeriod;
}
return;
@ -116,7 +116,7 @@ void CAlarmCltThread::execute()
return;
}
++m_nLoopBeforClear;
LOGINFO( "人问津,怠工前周期计数[%d]", m_nLoopBeforClear );
LOGINFO( "任务处理,空闲周期计数[%d]", m_nLoopBeforClear );
}
else
{

View File

@ -79,6 +79,8 @@ CFbdDiagDataImpl::CFbdDiagDataImpl()
m_pMutexModInputTable = new boost::shared_mutex;
m_pMutexModOutputTable = new boost::shared_mutex;
m_pMutexModPropTable = new boost::shared_mutex;
m_pMutexGlobalVarMap = new boost::shared_mutex;
}
@ -98,6 +100,9 @@ CFbdDiagDataImpl::~CFbdDiagDataImpl()
delete m_pMutexModPropTable;
m_pMutexModPropTable = nullptr;
delete m_pMutexGlobalVarMap;
m_pMutexGlobalVarMap = nullptr;
}
@ -386,6 +391,163 @@ int CFbdDiagDataImpl::setAlarmValByKey( const SFbdValueKey &stValueKey, const SF
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;
}
/***********************************************************************************************/

View File

@ -62,6 +62,30 @@ public:
//< 见基类说明
int setAlarmValByKey( const SFbdValueKey &stValueKey, const SFbdAlarmValue &stValAndSta ) override;
//< 见基类说明
int getGlobalNumericValByKey( const std::string &strVarName, SFbdNumericValue &stValAndSta ) const override;
//< 见基类说明
int setGlobalNumericValByKey( const std::string &strVarName,const SFbdNumericValue &stValAndSta ) override;
//< 见基类说明
int regGlobalNumericValByKey( const std::string &strVarName,const SFbdNumericValue &stValAndSta ) override;
//< 见基类说明
int unregGlobalNumericVar(const std::string &strVarName) override;
//< 见基类说明
int getGlobalStringValByKey( const std::string &strVarName,SFbdStringValue &stValAndSta ) const override;
//< 见基类说明
int setGlobalStringValByKey( const std::string &strVarName,const SFbdStringValue &stValAndSta ) override;
//< 见基类说明
int regGlobalStringValByKey( const std::string &strVarName,const SFbdStringValue &stValAndSta ) override;
//< 见基类说明
int unregGlobalStringVar(const std::string &strVarName) override;
/***********************************************************************************************/
@ -94,6 +118,9 @@ private:
SFbdModInputPtrContainer m_objModInputTable;
SFbdModOutputPtrContainer m_objModOutputTable;
SFbdModPropertyPtrContainer m_objModPropTable;
boost::shared_mutex *m_pMutexGlobalVarMap{nullptr};
GlobalVarHashMAP m_mapGlobalVar; //存储全局变量
};
typedef boost::shared_ptr<CFbdDiagDataImpl> CFbdDiagDataImplPtr;

View File

@ -18,7 +18,7 @@
//#include "boost/multi_index/hashed_index.hpp"
#include "boost/multi_index/ordered_index.hpp"
//#include "boost/multi_index/sequenced_index.hpp"
#include "boost/unordered_map.hpp"
#include "app_fbd/fbd_common/FbdDiagDataStruct.h"
namespace iot_app
@ -274,5 +274,7 @@ struct SFbdGroupData
std::vector<SFbdModPropertyPtr> m_vecPtrModProp;
};
typedef boost::unordered_map<std::string,boost::any> GlobalVarHashMAP;
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,402 @@
/*********************************************************************************
* @file FbdDiagOptCmdImpl.cpp
* @brief Diagram
* @author caodingfa
* @version 1.0
* @date 2024/10/23
**********************************************************************************/
#include "boost/weak_ptr.hpp"
#include "FbdDiagOptCmdImpl.h"
#include "common/Common.h"
#include "pub_utility_api/CharUtil.h"
#include "pub_logger_api/logger.h"
#include "common/MessageChannel.h"
#include "app_fbd/fbd_common/FbdSysInfoApi.h"
#include "pub_utility_api/TimeUtil.h"
#include <boost/format.hpp>
using namespace iot_public;
using namespace iot_net;
using namespace std;
namespace iot_app
{
namespace app_fbd
{
static const int cn_nIdleRunPeriod = 1000; //< 空闲时的运行周期
static const int CN_CB_SIZE = 100; //< 每个图元环形缓冲区的大小
static const int ASYNC_CACHE_SIZE = 2000; //< 异步缓冲区
//< 弱指针,观察者模式
static boost::weak_ptr<CFbdDiagOptCmdImpl> g_wpSingleton;
//< 保护 g_wpSingleton
static boost::mutex g_mutexSingleton;
//< 获取单例
FBD_COMMON_API CFbdDiagOptCmdApiPtr getFbdDiagOptCmdApi()
{
CFbdDiagOptCmdImplPtr 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<CFbdDiagOptCmdImpl>();
if ( iotSuccess == spInst->initialize())
{
g_wpSingleton = spInst;
return spInst;
}
return nullptr;
}
/***********************************************************************************************/
CFbdDiagOptCmdImpl::CFbdDiagOptCmdImpl()
:iot_public::CTimerThreadBase("控制命令反馈",0), //依赖消息总线的超时
m_pMbComm(NULL),
m_pPublisherMbComm(NULL)
{
}
CFbdDiagOptCmdImpl::~CFbdDiagOptCmdImpl()
{
CTimerThreadBase::quit();
if(m_pMbComm != NULL)
{
delete m_pMbComm;
m_pMbComm = NULL;
}
if(m_pPublisherMbComm != NULL)
{
delete m_pPublisherMbComm;
m_pPublisherMbComm = NULL;
}
}
void CFbdDiagOptCmdImpl::execute()
{
{
//< 读锁正常情况不会出现m_pMbComm为NULL时线程还运行的情况
boost::mutex::scoped_lock lock(m_objResourceMutex);
if(m_pMbComm == NULL)
{
LOGERROR( "通讯器指针为空,非预期,检查程序!" );
return; //< 正常情况不会进入此处
}
}
iot_net::CMbMessage objMsg;
while ( m_pMbComm->recvMsg( objMsg, 100 ))
{
SOptCtrlReplyPtr ptrOptRep = boost::make_shared<SOptCtrlReply>();
const std::string strMsg(( const char * ) objMsg.getDataPtr(), objMsg.getDataSize());
if ( !COptCtrlReply::parse( strMsg, *ptrOptRep ))
{
LOGERROR( "反馈命令解析失败" );
continue;
}
putMsgToCache(ptrOptRep);
}
}
int CFbdDiagOptCmdImpl::initialize()
{
m_strHostName = getFbdSysInfoApi()->getCurrentRunAppInfo().strLocalNodeName;
if(m_strHostName.empty())
{
LOGERROR("CFbdDiagOptCmdImpl 获取本节点名失败");
return iotFailed;
}
m_pPublisherMbComm = new CMbCommunicator;
if(m_pPublisherMbComm == NULL)
{
LOGERROR("CFbdDiagOptCmdImpl 创建发布者消息总线通信器失败");
return iotFailed;
}
return iotSuccess;
}
bool CFbdDiagOptCmdImpl::subOptCtrlReplyTopic(const string &strInstName)
{
if(strInstName.empty())
{
LOGERROR("CFbdDiagOptCmdImpl 订阅命令反馈通道失败,实例名为空");
return false;
}
boost::mutex::scoped_lock lock(m_objResourceMutex);
if(NULL == m_pMbComm)
{
m_pMbComm = new CMbCommunicator;
if(m_pMbComm == NULL)
{
LOGERROR("CFbdDiagOptCmdImpl 创建消息总线通信器失败");
return false;
}
//< 必须订阅所有专业,因为可能控制其他专业的测点
if(!m_pMbComm->addSub(0,CH_OPT_TO_HMI_OPTCMD_UP))
{
LOGERROR("CFbdDiagOptCmdImpl订阅通道失败,appId=0,chanId=CH_OPT_TO_HMI_OPTCMD_UP");
return false;
}
//< 同时激活线程
CTimerThreadBase::m_nRunPeriodMsec = 0;
CTimerThreadBase::resume();
}
//< 建立该图元的缓冲区
if(m_mapOptCtrlReply.count(strInstName) == 0)
{
boost::circular_buffer<SOptCtrlReplyPtr> cb(CN_CB_SIZE);
m_mapOptCtrlReply[strInstName].swap(cb);
}
return true;
}
bool CFbdDiagOptCmdImpl::unsubOptCtrlReplyTopic(const string &strInstName)
{
boost::mutex::scoped_lock lock(m_objResourceMutex);
m_mapOptCtrlReply.erase(strInstName);
if(m_mapOptCtrlReply.empty())
{
CTimerThreadBase::suspend(); //< 先挂起线程,防止多线程访问修改公共变量
CTimerThreadBase::m_nRunPeriodMsec = cn_nIdleRunPeriod;
//< 没有订阅的图元,则销毁通信器,同时挂起线程
delete m_pMbComm;
m_pMbComm = NULL;
LOGINFO("CFbdDiagOptCmdImpl 无图元订阅命令反馈通道,销毁通信器");
}
return true;
}
SOptCtrlReplyPtr CFbdDiagOptCmdImpl::getOptCtrlReply(const string &strInstName)
{
boost::mutex::scoped_lock lock(m_objResourceMutex);
auto iter = m_mapOptCtrlReply.find(strInstName);
if(iter == m_mapOptCtrlReply.end())
{
return NULL;
}
boost::circular_buffer<SOptCtrlReplyPtr> &buf = iter->second;
if(buf.empty())
{
return NULL;
}
SOptCtrlReplyPtr ptrReply = buf.front();
buf.pop_front();
return ptrReply;
}
bool CFbdDiagOptCmdImpl::sendOptCtrReqToDomain(CMbMessage &msgSend, const int nDomainID)
{
boost::mutex::scoped_lock lock(m_objResourceMutex);
if(m_pMbComm == NULL)
{
LOGERROR("CFbdDiagOptCmdImpl 消息总线通信器未初始化");
return false;
}
if(!m_pMbComm->sendMsgToDomain( msgSend, nDomainID ))
{
LOGERROR("CFbdDiagOptCmdImpl 发送控制请求报文失败");
return false;
}
return true;
}
string CFbdDiagOptCmdImpl::getMbCommName()
{
boost::mutex::scoped_lock lock(m_objResourceMutex);
if(NULL == m_pMbComm)
{
return "";
}
return m_pMbComm->getName();
}
void CFbdDiagOptCmdImpl::putMsgToCache(const SOptCtrlReplyPtr ptrReply)
{
if(ptrReply->stHead.strHostName != m_strHostName)
{
return; //非本节点消息
}
boost::mutex::scoped_lock lock(m_objResourceMutex);
auto iter = m_mapOptCtrlReply.find(ptrReply->stHead.strInstName);
if(iter == m_mapOptCtrlReply.end())
{
return; //无图元订阅
}
boost::circular_buffer<SOptCtrlReplyPtr> &buf = iter->second;
buf.push_back(ptrReply);
}
bool CFbdDiagOptCmdImpl::pushOptCtrlMessageCache(SOptCtrlRequest msgSend,const std::string diagName,const int nAppId)
{
boost::mutex::scoped_lock lock(m_objAsyncResourceMutex);
std::string strDomainAndApp = boost::str(boost::format("%d-%d") % msgSend.stHead.nDstDomainID % nAppId);
if(m_optCtrlMessageCache.count(diagName)==0)
{
m_optCtrlMessageCache[diagName][strDomainAndApp]=msgSend;
}
else
{
if(0!=m_optCtrlMessageCache[diagName].count(strDomainAndApp))
{
auto ctrl=msgSend.vecOptCtrlQueue[0];
SOptCtrlRequest& existMessage=m_optCtrlMessageCache[diagName][strDomainAndApp];
existMessage.vecOptCtrlQueue.push_back(ctrl);
checkOptCtrlMessageSize(existMessage);
}
else
{
m_optCtrlMessageCache[diagName][strDomainAndApp]=msgSend;
}
}
return true;
}
bool CFbdDiagOptCmdImpl::trigerSendMessage(const std::vector<std::string> vecDiagName)
{
{
boost::mutex::scoped_lock lock(m_objAsyncResourceMutex);
sendOptCtrlMessage(vecDiagName);
}
return true;
}
bool CFbdDiagOptCmdImpl::removeGroup(const std::vector<std::string> vecDiagName)
{
boost::mutex::scoped_lock lock(m_objAsyncResourceMutex);
for (auto it = vecDiagName.begin(); it != vecDiagName.end(); ++it) {
if(0!=m_optCtrlMessageCache.count(*it))
{
m_optCtrlMessageCache.erase(*it);
}
}
return true;
}
bool CFbdDiagOptCmdImpl::sendMsgToDomainByPublishCommunicator(CMbMessage &msgSend, const int nDomainID)
{
return m_pPublisherMbComm->sendMsgToDomain( msgSend, nDomainID);
}
void CFbdDiagOptCmdImpl::checkOptCtrlMessageSize(SOptCtrlRequest &request)
{
if(request.vecOptCtrlQueue.size()>ASYNC_CACHE_SIZE)
{
request.vecOptCtrlQueue.erase(request.vecOptCtrlQueue.begin());
}
}
void CFbdDiagOptCmdImpl::sendOptCtrlMessage(const std::vector<std::string> vecDiagName)
{
for (auto it = vecDiagName.begin(); it != vecDiagName.end(); ++it) {
if(0!=m_optCtrlMessageCache.count(*it))
{
auto& ctrlMessageMap=m_optCtrlMessageCache[*it];
for(auto itMessage = ctrlMessageMap.begin(); itMessage !=ctrlMessageMap.end(); ++itMessage)
{
//修正表头信息进行发送
SOptCtrlRequest& request=itMessage->second;
std::string strDomainAndApp=itMessage->first;
request.stHead.strSrcTag = "CFbdDiagOptCmdImpl_Async";
request.stHead.nUserID = 1; //< 用户ID默认1 管理员
request.stHead.nUserGroupID = 1; //< 用户组ID默认1 管理员
request.stHead.nOptTime =iot_public::getUTCTimeMsec();
request.stHead.strCommName = getAsyncMbCommName();
std::string res = COptCtrlRequest::generate( request );
if (res.empty())
{
LOGERROR( "生成控制报文失败。time=[%d]", request.stHead.nOptTime);
continue;
}
int nDstDomainId=0;
int nAppId=0;
size_t pos = strDomainAndApp.find('-');
if (pos != std::string::npos)
{
nDstDomainId = std::stoi(strDomainAndApp.substr(0, pos));
nAppId = std::stoi(strDomainAndApp.substr(pos + 1));
}
iot_net::CMbMessage objMsg( res, nAppId,
CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_WITHOUT_RESP );
if(!m_pPublisherMbComm->sendMsgToDomain( objMsg, nDstDomainId))
{
LOGERROR("CFbdDiagOptCmdImpl_Async 发送控制请求报文失败,消息依旧会被清空 %s",res.data());
}
else
{
LOGDEBUG("CFbdDiagOptCmdImpl_Async 发送控制请求报文成功 %s",res.data());
}
//清空队列消息
request.vecOptCtrlQueue.clear();
}
}
}
}
string CFbdDiagOptCmdImpl::getAsyncMbCommName()
{
if(NULL == m_pPublisherMbComm)
{
return "";
}
return m_pPublisherMbComm->getName();
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,93 @@
/*********************************************************************************
* @file FbdDiagOptCmdImpl.h
* @brief Diagram
* @author caodingfa
* @version 1.0
* @date 2024/10/23
**********************************************************************************/
#pragma once
#include "app_fbd/fbd_common/FbdDiagOptCmdApi.h"
#include "pub_utility_api/TimerThreadBase.h"
#include <set>
#include "boost/circular_buffer.hpp"
#include "boost/unordered_map.hpp"
namespace iot_app
{
namespace app_fbd
{
//< 先简单处理,只针对控制服务的反馈通道做处理
class CFbdDiagOptCmdImpl final : public CFbdDiagOptCmdApi,public iot_public::CTimerThreadBase
{
public:
CFbdDiagOptCmdImpl();
~CFbdDiagOptCmdImpl() override;
/************************************************************/
//< CTimerThreadBase相关
void execute() override;
/************************************************************/
/**
@brief
@return iotSuccess,
*/
int initialize();
//< 见基类说明
bool subOptCtrlReplyTopic(const std::string &strInstName) override;
//< 见基类说明
bool unsubOptCtrlReplyTopic(const std::string &strInstName) override;
//< 见基类说明
SOptCtrlReplyPtr getOptCtrlReply(const std::string &strInstName) override;
//< 见基类说明
bool sendOptCtrReqToDomain(iot_net::CMbMessage &msgSend, const int nDomainID) override;
//< 见基类说明
std::string getMbCommName() override;
//< 见基类说明
bool pushOptCtrlMessageCache(SOptCtrlRequest msgSend,const std::string diagName,const int nAppId) override;
//< 见基类说明
//直接发送
bool trigerSendMessage(const std::vector<std::string> vecDiagName) override;
//< 见基类说明
//工作线程析构时调用
bool removeGroup(const std::vector<std::string> vecDiagName)override;
//< 见基类说明
//只处理发布消息
bool sendMsgToDomainByPublishCommunicator(iot_net::CMbMessage &msgSend, const int nDomainID )override;
private:
void putMsgToCache(const SOptCtrlReplyPtr ptrReply);
void checkOptCtrlMessageSize(SOptCtrlRequest& request);
void sendOptCtrlMessage(const std::vector<std::string> vecDiagName);
std::string getAsyncMbCommName();
typedef boost::unordered_map<std::string,SOptCtrlRequest> optCtrlMessageMap;//<dstDomainID-appId,消息类型>//头部相同的消息
private:
iot_net::CMbCommunicator *m_pMbComm;
boost::mutex m_objResourceMutex;
std::string m_strHostName;
boost::unordered_map<std::string,boost::circular_buffer<SOptCtrlReplyPtr> > m_mapOptCtrlReply;
boost::mutex m_objAsyncResourceMutex;//异步控制资源锁
boost::unordered_map<std::string,optCtrlMessageMap> m_optCtrlMessageCache;//待发送的消息<图表名,消息队列>
iot_net::CMbCommunicator *m_pPublisherMbComm;//只负责发布消息的通讯器
};
typedef boost::shared_ptr<CFbdDiagOptCmdImpl> CFbdDiagOptCmdImplPtr;
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -66,7 +66,7 @@ int CAlarmDataMng::getLastAlarm( SFbdAlarmInfo &stAlmOutput ) const
int CAlarmDataMng::getAlarmAfter( const SFbdAlarmInfo &stPosition, std::vector<SFbdAlarmInfo> &vecOutput,
SFbdAlarmInfo &stLastAlm ) const
SFbdAlarmInfo &stLastAlm, const bool bIncludeBeforeStartup /*= false*/ ) const
{
vecOutput.clear();
@ -104,7 +104,7 @@ int CAlarmDataMng::getAlarmAfter( const SFbdAlarmInfo &stPosition, std::vector<S
for ( ; indexSeq.cend() != itSeq; ++itSeq )
{
//< 非启动前产生的历史告警
if ( !itSeq->m_bIsExpired )
if (bIncludeBeforeStartup || !itSeq->m_bIsExpired )
vecOutput.emplace_back( itSeq->m_ptrAlmInfo );
}

View File

@ -69,7 +69,7 @@ public:
//< 见基类说明
int getAlarmAfter( const SFbdAlarmInfo &stPosition, std::vector<SFbdAlarmInfo> &vecOutput,
SFbdAlarmInfo &stLastAlm ) const;
SFbdAlarmInfo &stLastAlm, const bool bIncludeBeforeStartup = false ) const;
//< 见基类说明
int getAlarmByUuid( const std::string &strUuidBase64, SFbdAlarmInfo &stOutput ) const;

View File

@ -80,9 +80,9 @@ int CFbdAlarmCltImpl::getLastAlarm( SFbdAlarmInfo &stAlmOutput ) const
int CFbdAlarmCltImpl::getAlarmAfter( const SFbdAlarmInfo &stPosition, std::vector<SFbdAlarmInfo> &vecOutput,
SFbdAlarmInfo &stLastAlm ) const
SFbdAlarmInfo &stLastAlm,const bool bIncludeBeforeStartup/* = false*/ ) const
{
return m_objAlarmDataMng.getAlarmAfter( stPosition, vecOutput, stLastAlm );
return m_objAlarmDataMng.getAlarmAfter( stPosition, vecOutput, stLastAlm, bIncludeBeforeStartup );
}

View File

@ -40,7 +40,7 @@ public:
//< 见基类说明
int getAlarmAfter( const SFbdAlarmInfo &stPosition, std::vector<SFbdAlarmInfo> &vecOutput,
SFbdAlarmInfo &stLastAlm ) const override;
SFbdAlarmInfo &stLastAlm,const bool bIncludeBeforeStartup = false ) const override;
//< 见基类说明
int getAlarmByUuid( const std::string &strUuidBase64, SFbdAlarmInfo &stOutput ) const override;

View File

@ -15,6 +15,9 @@ HEADERS += \
../../../include/application/app_fbd/fbd_common/FbdDiagDataStruct.h \
../../../include/application/app_fbd/fbd_common/FbdPointSubApi.h \
../../../include/application/app_fbd/fbd_common/FbdSysInfoApi.h \
../../../include/application/app_fbd/fbd_common/FbdDiagOptCmdApi.h \
../../../include/service/operate_server_api/JsonMessageStruct.h \
../../../include/service/operate_server_api/JsonOptCommand.h \
alarm_client/AlarmDataMng.h \
alarm_client/FbdAlarmCltImpl.h \
alarm_client/ItlAlmDataMng.h \
@ -22,9 +25,11 @@ HEADERS += \
FbdDiagDataImpl.h \
FbdDiagDataStructPrivate.h \
FbdPointSubImpl.h \
FbdSysInfoImpl.h
FbdSysInfoImpl.h \
FbdDiagOptCmdImpl.h
SOURCES += \
../../../include/service/operate_server_api/JsonOptCommand.cpp \
alarm_client/AlarmDataMng.cpp \
alarm_client/FbdAlarmCltImpl.cpp \
alarm_client/ItlAlmDataMng.cpp \
@ -32,12 +37,13 @@ SOURCES += \
FbdDiagDataImpl.cpp \
FbdDiagDataStructPrivate.cpp \
FbdPointSubImpl.cpp \
FbdSysInfoImpl.cpp
FbdSysInfoImpl.cpp \
FbdDiagOptCmdImpl.cpp
LIBS += -lboost_system -lboost_chrono -lboost_date_time -llog4cplus -lprotobuf \
-lpub_logger_api -lrdb_api -lpub_sysinfo_api -lpub_utility_api -ldp_chg_data_api -ldata_process_api \
-lalarm_server_api
-lalarm_server_api -lnet_msg_bus_api
include($$PWD/../../../idl_files/idl_files.pri)

View File

@ -17,6 +17,7 @@ namespace app_fbd
CAntiShake::CAntiShake()
: m_nLastValue( 0 ),
m_eDelayMode(AntiShakeDelayMode_Min),
m_lChangeTimeMsec( 0L ),
m_ptrDiagData( nullptr )
{
@ -50,12 +51,72 @@ int CAntiShake::init( const SFbdModKey &stModuleKey, const std::string & )
return iotFailed;
}
//2.获取延迟输出模式
std::string strDelayMode = "";
if (iotSuccess != m_ptrDiagData->getModProperty(stModuleKey,"DelayMode",strDelayMode))
{
LOGERROR( "获取模块[%s]的DelayMode属性参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
try
{
boost::algorithm::trim(strDelayMode);
int nDelayMode = boost::lexical_cast<int>(strDelayMode);
if(nDelayMode <= AntiShakeDelayMode_Min || nDelayMode >= AntiShakeDelayMode_Max)
{
LOGERROR( "转换模块[%s]的DelayMode属性参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
m_eDelayMode = (AntiShakeDelayMode)nDelayMode;
}
catch ( const std::exception &e )
{
LOGERROR( "模块[%s]参数格式非法Err\n%s", m_stModKey.toString().c_str(), e.what());
return iotFailed;
}
LOGINFO( "[%s]加载成功", m_stModKey.toString().c_str());
return iotSuccess;
}
int CAntiShake::calculate()
{
switch (m_eDelayMode) {
case AntiShakeDelayMode_OutWhenInvalid:
return calcMode_OutWhenInvalid();
case AntiShakeDelayMode_OutWhenValid:
return calcMode_OutWhenValid();
default:
break;
}
return iotSuccess;
}
int CAntiShake::reset( const bool /*bMaster*/ )
{
m_lChangeTimeMsec = 0;
SFbdNumericValue stOutput( 0, CN_FBD_STATUS_Invalid );
return m_ptrDiagData->setNumericValByKey( m_stOutputKey, stOutput );
}
int CAntiShake::clean()
{
return reset( false );
}
boost::shared_ptr<CAntiShake> CAntiShake::create()
{
return boost::make_shared<CAntiShake>();
}
int CAntiShake::calcMode_OutWhenValid()
{
SFbdNumericValue stInput1( 0, CN_FBD_STATUS_Invalid );
SFbdNumericValue stInput2( 0, CN_FBD_STATUS_Invalid );
@ -114,25 +175,51 @@ int CAntiShake::calculate()
return iotSuccess;
}
int CAntiShake::reset( const bool /*bMaster*/ )
int CAntiShake::calcMode_OutWhenInvalid()
{
m_lChangeTimeMsec = 0;
SFbdNumericValue stOutput( 0, CN_FBD_STATUS_Invalid );
SFbdNumericValue stInput( 0, CN_FBD_STATUS_Invalid ); //输入值
SFbdNumericValue stTimeout( 0, CN_FBD_STATUS_Invalid ); //延迟时间
return m_ptrDiagData->setNumericValByKey( m_stOutputKey, stOutput );
}
//< 获取输入参数值和状态
if ( iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKey1, stInput ) ||
iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKey2, stTimeout ))
{
LOGERROR( "获取模块[%s]的输入参数失败", m_stModKey.toString().c_str());
return iotFailed;
}
//< 判断输入参数的状态是否有效,有效则直接写输出
if ( stInput.m_nStatus == CN_FBD_STATUS_Valid)
{
m_lChangeTimeMsec = iot_public::getMonotonicMsec();
return m_ptrDiagData->setNumericValByKey( m_stOutputKey, stInput );
}
int CAntiShake::clean()
{
return reset( false );
}
//< 下面的代码都是基于输入值无效的情况下的运算,上面已经将有效的情况拦截了
if ( m_lChangeTimeMsec == 0 ) //< 启动后第一次,先将输出值设置为无效,同时开始计时
{
SFbdNumericValue stOutputTemp( 0, CN_FBD_STATUS_Invalid );
if ( iotSuccess != m_ptrDiagData->setNumericValByKey( m_stOutputKey, stOutputTemp ))
{
LOGERROR( "首次计算,写模块[%s]输出值失败", m_stModKey.toString().c_str());
return iotFailed;
}
m_lChangeTimeMsec = iot_public::getMonotonicMsec();
}
else
{
int64 lCurTime = iot_public::getMonotonicMsec();
boost::shared_ptr<CAntiShake> CAntiShake::create()
{
return boost::make_shared<CAntiShake>();
//< 判断是否超时输出
if (( lCurTime - m_lChangeTimeMsec ) > static_cast<int>(stTimeout.m_dValue))
{
m_lChangeTimeMsec = lCurTime;
return m_ptrDiagData->setNumericValByKey(m_stOutputKey, stInput);
}
}
return iotSuccess;
}
} //< namespace app_fbd

View File

@ -14,6 +14,13 @@ namespace iot_app
namespace app_fbd
{
enum AntiShakeDelayMode{
AntiShakeDelayMode_Min = -1, //无效值,用来判断枚举下限
AntiShakeDelayMode_OutWhenInvalid = 0, //输入值无效时延迟输出无效0
AntiShakeDelayMode_OutWhenValid, //输入值有效时输出
AntiShakeDelayMode_Max //枚举最大值,用来判断枚举上限
};
/* @brief 延迟输出模块,实现:当某值持续规定时间后输出,如果在时间内又发生了变化,重新计时 */
class CAntiShake final : public CBaseModule
{
@ -32,14 +39,22 @@ public:
// Factory method
static boost::shared_ptr<CAntiShake> create();
private:
//对应模式AntiShakeDelayMode_Valid当输入值有效时滤掉值抖动也就是值不变保持一段时间才输出
int calcMode_OutWhenValid();
//对应模式AntiShakeDelayMode_Invalid当输入值无效时延迟输出0且状态值为无效
int calcMode_OutWhenInvalid();
private:
int m_nLastValue; //< 上一次值
AntiShakeDelayMode m_eDelayMode; //延迟输出模式
int64 m_lChangeTimeMsec; //< 记录值改变时间
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
SFbdValueKey m_stInKey1; //< 输入1 key
SFbdValueKey m_stInKey2; //< 输入2 key
SFbdValueKey m_stInKey1; //< 输入1 key 输入值
SFbdValueKey m_stInKey2; //< 输入2 key 延迟时间
SFbdValueKey m_stOutputKey; //< 输出参数
SFbdModKey m_stModKey; //< 模块标识

View File

@ -45,6 +45,13 @@ int CAoCtrl::init( const SFbdModKey &stModuleKey, const std::string & )
return iotFailed;
}
m_ptrOptCmdApi = getFbdDiagOptCmdApi();
if( m_ptrOptCmdApi == nullptr )
{
LOGERROR( "获取控制反馈接口单例失败" );
return iotFailed;
}
//1.解析配置
if ( iotSuccess != initCtrlParam())
{
@ -84,30 +91,12 @@ int CAoCtrl::calculate()
{
//< 接收消息总线消息
{
if ( nullptr == m_pMbComm )
while (true)
{
LOGERROR( "通讯器指针为空,非预期,检查程序!" );
return iotFailed;
}
iot_net::CMbMessage objMsg;
while ( m_pMbComm->recvMsg( objMsg, 0 ))
{
COptCtrlReply objParse;
SOptCtrlReplyPtr ptrOptRep = boost::make_shared<SOptCtrlReply>();
const std::string strMsg(( const char * ) objMsg.getDataPtr(), objMsg.getDataSize());
if ( !objParse.parse( strMsg, *ptrOptRep ))
SOptCtrlReplyPtr ptrOptRep = m_ptrOptCmdApi->getOptCtrlReply(m_stModKey.toString());
if(ptrOptRep == NULL)
{
LOGERROR( "反馈命令解析失败" );
continue;
}
if ( ptrOptRep->stHead.strInstName != m_stModKey.toString() ||
ptrOptRep->stHead.strHostName != getFbdSysInfoApi()->getCurrentRunAppInfo().strLocalNodeName )
{
//< 非本进程的反馈,丢弃
continue;
break;
}
const auto itMap = m_mapCmdOfPnt.find( ptrOptRep->stHead.strKeyIdTag );
@ -225,16 +214,18 @@ int CAoCtrl::reset( const bool bMaster )
int nRet = iotSuccess;
if ( bMaster )
{
if ( nullptr == m_pMbComm )
m_pMbComm = new iot_net::CMbCommunicator;
//< 必须订阅所有专业,因为可能控制其他专业的测点
m_pMbComm->addSub( 0, CH_OPT_TO_HMI_OPTCMD_UP );
if(m_ptrOptCmdApi != NULL)
{
m_ptrOptCmdApi->subOptCtrlReplyTopic(m_stModKey.toString());
}
}
else
{
delete m_pMbComm;
m_pMbComm = nullptr;
if(m_ptrOptCmdApi != NULL)
{
m_ptrOptCmdApi->unsubOptCtrlReplyTopic(m_stModKey.toString());
}
}
m_mapCmdOfPnt.clear(); //< 清空命令
@ -247,11 +238,9 @@ int CAoCtrl::clean()
{
int nRet = reset( false );
m_ptrOptCmdApi.reset();
m_ptrDiagData.reset();
delete m_pMbComm;
m_pMbComm = nullptr;
return nRet;
}
@ -356,7 +345,7 @@ void CAoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
stReq.stHead.nAppID = stRunAppInfo.nAppId;
stReq.stHead.strHostName = stRunAppInfo.strLocalNodeName;
stReq.stHead.strInstName = m_stModKey.toString();
stReq.stHead.strCommName = m_pMbComm->getName();
stReq.stHead.strCommName = m_ptrOptCmdApi->getMbCommName();
stReq.stHead.nUserID = 1; //< 用户ID默认1 管理员
stReq.stHead.nUserGroupID = 1; //< 用户组ID默认1 管理员
stReq.stHead.nOptTime = stCmd.lSendUtcMsec;
@ -367,8 +356,7 @@ void CAoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
stCtrlReq.bIsDeviceOccupy = true;
stReq.vecOptCtrlQueue.push_back( stCtrlReq );
COptCtrlRequest objGen;
stCmd.strLastSendJsonReq = objGen.generate( stReq );
stCmd.strLastSendJsonReq = COptCtrlRequest::generate( stReq );
if ( stCmd.strLastSendJsonReq.empty())
{
LOGERROR( "生成控制报文失败。KeyIdTag=[%s]", stCtrlReq.strKeyIdTag.c_str());
@ -378,7 +366,8 @@ void CAoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
iot_net::CMbMessage objMsg( stCmd.strLastSendJsonReq, stCmd.nAppId,
CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_DOWN );
if ( m_pMbComm->sendMsgToDomain( objMsg, stCmd.nDstDomainId ))
if(m_ptrOptCmdApi->sendOptCtrReqToDomain(objMsg,stCmd.nDstDomainId))
{
stCmd.setResult( true, "发送控制命令成功", eSuccessState );
LOGINFO( "发送控制命令到域[%d],应用[%d]成功KeyIdTag=[%s],控制目标值[%lf]",
@ -419,9 +408,8 @@ void CAoCtrl::waitCtrlRep( SCmdOfOnePnt &stCmdOfOnePnt, const ECmdState eSuccess
if ( ptrRep->stHead.nOptTime != stCurrentCmd.lSendUtcMsec )
{
COptCtrlReply objParse;
LOGINFO( "时间不一致,忽略,收到的回复消息如下:\n%s",
objParse.generate( *ptrRep ).c_str());
COptCtrlReply::generate( *ptrRep ).c_str());
continue;
}

View File

@ -16,6 +16,7 @@
#include "operate_server_api/JsonOptCommand.h"
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
#include "app_fbd/fbd_common/FbdDiagOptCmdApi.h"
namespace iot_app
{
@ -140,9 +141,8 @@ private:
int parseKeyIdTag( const std::string &strKeyIdTag, SCtrlCmd &stCtrlCmd );
private:
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
iot_net::CMbCommunicator *m_pMbComm{nullptr}; //< 消息总线通信器
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
CFbdDiagOptCmdApiPtr m_ptrOptCmdApi; //< 控制服务接口
SFbdModKey m_stModKey; //< 模块标识

View File

@ -0,0 +1,103 @@
#include "AVG.h"
#include "pub_utility_api/TimeUtil.h"
using namespace iot_public;
namespace iot_app
{
namespace app_fbd
{
CAVG::CAVG()
:m_bIngoreInvalidValue(true),
m_nCalcPeriod(900),
m_dSum(0.0)
{
}
CAVG::~CAVG()
{
}
int CAVG::init(const SBaseCalcParam &stParam)
{
m_bIngoreInvalidValue = stParam.bIngoreInvalidValue;
m_nCalcPeriod = stParam.nCalcPeriod;
return iotSuccess;
}
int CAVG::calculate(const SFbdNumericValue &stInput,SFbdNumericValue &stOutput)
{
int64 lCurTime = getMonotonicMsec();
if(m_bIngoreInvalidValue)
{
if(isValidOfStatus(stInput.m_nStatus))
{
insertValue(lCurTime,stInput.m_dValue); //只有有效值参与计算
}
}
else
{
insertValue(lCurTime,stInput.m_dValue); //忽略状态
}
size_t nIdx = 0;
while(nIdx < m_dequeTime.size())
{
if(lCurTime - m_dequeTime[nIdx] > m_nCalcPeriod * MSEC_PER_SEC)
{
m_dSum -= m_dequeValue[nIdx];
nIdx++;
}
else
{
break; //碰到未超时的跳出
}
}
//删除超时的部分
for(size_t i = 0; i < nIdx; i++)
{
m_dequeTime.pop_front();
m_dequeValue.pop_front();
}
//求平均值
if(m_dequeValue.empty())
{
stOutput.m_dValue = 0.0;
}
else
{
stOutput.m_dValue = m_dSum / m_dequeValue.size();
}
stOutput.m_nStatus = CN_FBD_STATUS_Valid;
return iotSuccess;
}
int CAVG::reset(const bool /*bMaster*/)
{
m_dequeValue.clear();
m_dequeTime.clear();
m_dSum = 0.0;
return iotSuccess;
}
void CAVG::insertValue(const int64 &lCurTime, const double &dValue)
{
m_dequeValue.push_back(dValue);
m_dequeTime.push_back(lCurTime);
m_dSum += dValue;
}
} //app_fbd
} //iot_app

View File

@ -0,0 +1,35 @@
#pragma once
#include "BaseCalcInterface.h"
#include <deque>
namespace iot_app
{
namespace app_fbd
{
class CAVG : public CBaseCalcInterface
{
public:
CAVG();
virtual ~CAVG();
virtual int init(const SBaseCalcParam &stParam);
virtual int calculate(const SFbdNumericValue &stInput,SFbdNumericValue &stOutput);
virtual int reset( const bool bMaster );
private:
void insertValue(const int64 &lCurTime, const double &dValue);
private:
bool m_bIngoreInvalidValue; //忽略无效值
int m_nCalcPeriod; //滑窗计算周期,单位秒
double m_dSum; //所有数据之和
std::deque<int64> m_dequeTime; //用来存储时间,判断数据是否过期与m_dequeValue一一对应
std::deque<double> m_dequeValue; //用来存储输入值
};
typedef boost::shared_ptr<CAVG> CAVGPtr;
} //app_fbd
} //iot_app

View File

@ -0,0 +1,29 @@
#pragma once
#include "app_fbd/fbd_common/BaseModule.h"
namespace iot_app
{
namespace app_fbd
{
typedef struct _SBaseCalcParam
{
bool bIngoreInvalidValue; //忽略无效值
int nCalcPeriod; //滑窗计算周期,单位秒
}SBaseCalcParam,*PSBaseCalcParam;
class CBaseCalcInterface
{
public:
virtual ~CBaseCalcInterface() = default;
virtual int init(const SBaseCalcParam &stParam) = 0;
virtual int calculate(const SFbdNumericValue &stInput,SFbdNumericValue &stOutput) = 0;
virtual int reset( const bool bMaster ) = 0;
};
typedef boost::shared_ptr<CBaseCalcInterface> CBaseCalcInterfacePtr;
} //app_fbd
} //iot_app

View File

@ -0,0 +1,176 @@
/**
@file AntiShake.cpp
@brief
@author
*/
#include "boost/make_shared.hpp"
#include "BasePeriodCalc.h"
#include "pub_logger_api/logger.h"
#include "pub_utility_api/TimeUtil.h"
#include "AVG.h"
namespace iot_app
{
namespace app_fbd
{
CBasePeriodCalc::CBasePeriodCalc()
: m_eCalcMode(CalcMode_Min),
m_bFirstOutput(true),
m_ptrCalc(NULL),
m_ptrDiagData( nullptr )
{
}
CBasePeriodCalc::~CBasePeriodCalc()
{
clean();
m_ptrCalc.reset();
m_ptrDiagData.reset();
}
int CBasePeriodCalc::init( const SFbdModKey &stModuleKey, const std::string & )
{
m_stModKey = stModuleKey;
m_ptrDiagData = getFbdDiagDataApi();
if ( m_ptrDiagData == nullptr )
{
LOGERROR( "获取Diagram数据接口单例失败" );
return iotFailed;
}
//1.获取输入、输出参数
if ( iotSuccess != m_ptrDiagData->getValKeyByModInput( stModuleKey, 1, m_stInKey1 ) ||
iotSuccess != m_ptrDiagData->getValKeyByModOutput( stModuleKey, 1, m_stOutputValueKey ) ||
iotSuccess != m_ptrDiagData->getValKeyByModOutput( stModuleKey, 2, m_stOutputChangedKey ))
{
LOGERROR( "获取模块[%s]的输入输出参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
//2.获取属性参数
std::string strCalcPeriod; //滑窗周期
std::string strCalcMode; //计算模式
std::string strIngoreInvalideValue; //忽略无效值
if (iotSuccess != m_ptrDiagData->getModProperty(stModuleKey,"CalcPeriod",strCalcPeriod) ||
iotSuccess != m_ptrDiagData->getModProperty(stModuleKey,"CalcMode",strCalcMode) ||
iotSuccess != m_ptrDiagData->getModProperty(stModuleKey,"IngoreInvalidValue",strIngoreInvalideValue) )
{
LOGERROR( "获取模块[%s]的属性参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
try
{
boost::algorithm::trim(strCalcPeriod);
boost::algorithm::trim(strCalcMode);
boost::algorithm::trim(strIngoreInvalideValue);
m_stBaseParam.nCalcPeriod = boost::lexical_cast<int>(strCalcPeriod);
m_stBaseParam.bIngoreInvalidValue = boost::lexical_cast<int>(strIngoreInvalideValue) != 0;
int nCalcMode = boost::lexical_cast<int>(strCalcMode);
if(nCalcMode <= CalcMode_Min || nCalcMode >= CalcMode_Max)
{
LOGERROR( "转换模块[%s]的属性参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
m_eCalcMode = (CalcMode)nCalcMode;
}
catch ( const std::exception &e )
{
LOGERROR( "模块[%s]参数格式非法Err\n%s", m_stModKey.toString().c_str(), e.what());
return iotFailed;
}
//创建计算实例
if(iotSuccess != createCalcInstance())
{
return iotFailed;
}
LOGINFO( "[%s]加载成功", m_stModKey.toString().c_str());
return iotSuccess;
}
int CBasePeriodCalc::calculate()
{
SFbdNumericValue stInput( 0, CN_FBD_STATUS_Invalid );
SFbdNumericValue stOutputValue( 0, CN_FBD_STATUS_Invalid );
SFbdNumericValue stOutputChanged( 0, CN_FBD_STATUS_Valid );
//< 获取输入参数值和状态
if ( iotSuccess != m_ptrDiagData->getNumericValByKey(m_stInKey1, stInput) )
{
LOGERROR( "获取模块[%s]的输入参数失败", m_stModKey.toString().c_str());
}
else
{
m_ptrCalc->calculate(stInput,stOutputValue);
}
if(m_stOutputValue != stOutputValue || m_bFirstOutput)
{
//第一次输出,或者值发生变化,则触发是否变化
stOutputChanged.m_dValue = 1;
m_ptrDiagData->setNumericValByKey(m_stOutputValueKey,stOutputValue);
m_bFirstOutput = false;
m_stOutputValue = stOutputValue;
}
m_ptrDiagData->setNumericValByKey(m_stOutputChangedKey,stOutputChanged);
return iotSuccess;
}
int CBasePeriodCalc::reset( const bool bMaster )
{
m_bFirstOutput = true;
if(m_ptrCalc != NULL)
{
m_ptrCalc->reset(bMaster);
}
SFbdNumericValue stOutput( 0, CN_FBD_STATUS_Invalid );
m_ptrDiagData->setNumericValByKey( m_stOutputValueKey, stOutput );
m_ptrDiagData->setNumericValByKey( m_stOutputChangedKey, stOutput );
return iotSuccess;
}
int CBasePeriodCalc::clean()
{
return reset( false );
}
boost::shared_ptr<CBasePeriodCalc> CBasePeriodCalc::create()
{
return boost::make_shared<CBasePeriodCalc>();
}
int CBasePeriodCalc::createCalcInstance()
{
if(m_eCalcMode == CalcMode_AVG)
{
m_ptrCalc = boost::make_shared<CAVG>();
}
if(m_ptrCalc != NULL && iotSuccess == m_ptrCalc->init(m_stBaseParam))
{
LOGINFO("模块[%s]创建计算类成功,mode=%d",m_stModKey.toString().c_str(),m_eCalcMode);
return iotSuccess;
}
LOGERROR("模块[%s]创建计算类失败,mode=%d",m_stModKey.toString().c_str(),m_eCalcMode);
return iotFailed;
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,68 @@
/**
@file AntiShake.h
@brief
@author
*/
#pragma once
#include "boost/dll/alias.hpp"
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
#include "BaseCalcInterface.h"
namespace iot_app
{
namespace app_fbd
{
enum CalcMode{
CalcMode_Min = -1, //无效值,用来判断枚举下限
CalcMode_AVG = 0, //平均值
CalcMode_Max //枚举最大值,用来判断枚举上限
};
/* @brief 延迟输出模块,实现:当某值持续规定时间后输出,如果在时间内又发生了变化,重新计时 */
class CBasePeriodCalc final : public CBaseModule
{
public:
CBasePeriodCalc();
~CBasePeriodCalc() override;
int init( const SFbdModKey &stModuleKey, const std::string &strExtraParam ) override;
int calculate() override;
int reset( const bool bMaster ) override;
int clean() override;
// Factory method
static boost::shared_ptr<CBasePeriodCalc> create();
private:
//创建计算类
int createCalcInstance();
private:
CalcMode m_eCalcMode; //计算方式
bool m_bFirstOutput; //是否第一次输出,用来防止计算结果与默认值一致时无法输出的情况
SBaseCalcParam m_stBaseParam; //计算相关参数
CBaseCalcInterfacePtr m_ptrCalc; //计算实例
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
SFbdValueKey m_stInKey1; //< 输入1 key 输入值
SFbdValueKey m_stOutputValueKey; //< 输出参数
SFbdValueKey m_stOutputChangedKey; //< 输出是否变化
SFbdNumericValue m_stOutputValue; //输出值
SFbdModKey m_stModKey; //< 模块标识
};
BOOST_DLL_ALIAS(
CBasePeriodCalc::create, // 要导出的函数
create_plugin // 将导出函数重命名,最终调用者访问此函数名
)
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,35 @@
QT -= core gui
CONFIG -= qt
TEMPLATE = lib
TARGET = base_period_calc
# Input
HEADERS += \
BasePeriodCalc.h \
AVG.h \
BaseCalcInterface.h
SOURCES += \
BasePeriodCalc.cpp \
AVG.cpp
LIBS += -lboost_system -lboost_chrono
LIBS += -lpub_logger_api -llog4cplus -lnet_msg_bus_api -lrdb_api -lfbd_common
#-------------------------------------------------------------------
COMMON_PRI=$$PWD/../../../../common.pri
exists($$COMMON_PRI) {
include($$COMMON_PRI)
}else {
error("FATAL error: can not find common.pri")
}
#为了统一将fbd_module下所有dll生成到规定目录
FBD_MODULE_PRI=$$PWD/../fbd_module.pri
exists($$FBD_MODULE_PRI) {
include($$FBD_MODULE_PRI)
}else {
error("FATAL error: can not find fbd_module.pri")
}

View File

@ -45,6 +45,13 @@ int CDoCtrl::init( const SFbdModKey &stModuleKey, const std::string & )
return iotFailed;
}
m_ptrOptCmdApi = getFbdDiagOptCmdApi();
if( m_ptrOptCmdApi == nullptr )
{
LOGERROR( "获取控制反馈接口单例失败" );
return iotFailed;
}
//1.解析配置
if ( iotSuccess != initCtrlParam())
{
@ -84,30 +91,12 @@ int CDoCtrl::calculate()
{
//< 接收消息总线消息
{
if ( nullptr == m_pMbComm )
while(true)
{
LOGERROR( "通讯器指针为空,非预期,检查程序!" );
return iotFailed;
}
iot_net::CMbMessage objMsg;
while ( m_pMbComm->recvMsg( objMsg, 0 ))
{
COptCtrlReply objParse;
SOptCtrlReplyPtr ptrOptRep = boost::make_shared<SOptCtrlReply>();
const std::string strMsg(( const char * ) objMsg.getDataPtr(), objMsg.getDataSize());
if ( !objParse.parse( strMsg, *ptrOptRep ))
SOptCtrlReplyPtr ptrOptRep = m_ptrOptCmdApi->getOptCtrlReply(m_stModKey.toString());
if(ptrOptRep == NULL)
{
LOGERROR( "反馈命令解析失败" );
continue;
}
if ( ptrOptRep->stHead.strInstName != m_stModKey.toString() ||
ptrOptRep->stHead.strHostName != getFbdSysInfoApi()->getCurrentRunAppInfo().strLocalNodeName )
{
//< 非本进程的反馈,丢弃
continue;
break;
}
const auto itMap = m_mapCmdOfPnt.find( ptrOptRep->stHead.strKeyIdTag );
@ -227,16 +216,18 @@ int CDoCtrl::reset( const bool bMaster )
int nRet = iotSuccess;
if ( bMaster )
{
if ( nullptr == m_pMbComm )
m_pMbComm = new iot_net::CMbCommunicator;
//< 必须订阅所有专业,因为可能控制其他专业的测点
m_pMbComm->addSub( 0, CH_OPT_TO_HMI_OPTCMD_UP );
if(m_ptrOptCmdApi != NULL)
{
m_ptrOptCmdApi->subOptCtrlReplyTopic(m_stModKey.toString());
}
}
else
{
delete m_pMbComm;
m_pMbComm = nullptr;
if(m_ptrOptCmdApi != NULL)
{
m_ptrOptCmdApi->unsubOptCtrlReplyTopic(m_stModKey.toString());
}
}
m_mapCmdOfPnt.clear(); //< 清空命令
@ -249,11 +240,9 @@ int CDoCtrl::clean()
{
int nRet = reset( false );
m_ptrOptCmdApi.reset();
m_ptrDiagData.reset();
delete m_pMbComm;
m_pMbComm = nullptr;
return nRet;
}
@ -358,7 +347,7 @@ void CDoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
stReq.stHead.nAppID = stRunAppInfo.nAppId;
stReq.stHead.strHostName = stRunAppInfo.strLocalNodeName;
stReq.stHead.strInstName = m_stModKey.toString();
stReq.stHead.strCommName = m_pMbComm->getName();
stReq.stHead.strCommName = m_ptrOptCmdApi->getMbCommName();
stReq.stHead.nUserID = 1; //< 用户ID默认1 管理员
stReq.stHead.nUserGroupID = 1; //< 用户组ID默认1 管理员
stReq.stHead.nOptTime = stCmd.lSendUtcMsec;
@ -369,8 +358,7 @@ void CDoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
stCtrlReq.bIsDeviceOccupy = true;
stReq.vecOptCtrlQueue.push_back( stCtrlReq );
COptCtrlRequest objGen;
stCmd.strLastSendJsonReq = objGen.generate( stReq );
stCmd.strLastSendJsonReq = COptCtrlRequest::generate( stReq );
if ( stCmd.strLastSendJsonReq.empty())
{
LOGERROR( "生成控制报文失败。KeyIdTag=[%s]", stCtrlReq.strKeyIdTag.c_str());
@ -380,7 +368,7 @@ void CDoCtrl::sendCtrlCmd( SCtrlCmd &stCmd, const ECmdState eSuccessState, const
iot_net::CMbMessage objMsg( stCmd.strLastSendJsonReq, stCmd.nAppId,
CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_DOWN );
if ( m_pMbComm->sendMsgToDomain( objMsg, stCmd.nDstDomainId ))
if ( m_ptrOptCmdApi->sendOptCtrReqToDomain(objMsg,stCmd.nDstDomainId) )
{
stCmd.setResult( true, "发送控制命令成功", eSuccessState );
LOGINFO( "发送控制命令到域[%d],应用[%d]成功KeyIdTag=[%s],控制目标值[%lf]",
@ -421,9 +409,8 @@ void CDoCtrl::waitCtrlRep( SCmdOfOnePnt &stCmdOfOnePnt, const ECmdState eSuccess
if ( ptrRep->stHead.nOptTime != stCurrentCmd.lSendUtcMsec )
{
COptCtrlReply objParse;
LOGINFO( "时间不一致,忽略,收到的回复消息如下:\n%s",
objParse.generate( *ptrRep ).c_str());
COptCtrlReply::generate( *ptrRep ).c_str());
continue;
}

View File

@ -16,6 +16,7 @@
#include "operate_server_api/JsonOptCommand.h"
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
#include "app_fbd/fbd_common/FbdDiagOptCmdApi.h"
namespace iot_app
{
@ -140,7 +141,8 @@ private:
int parseKeyIdTag( const std::string &strKeyIdTag, SCtrlCmd &stCtrlCmd );
private:
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
CFbdDiagOptCmdApiPtr m_ptrOptCmdApi; //< 控制服务接口
iot_net::CMbCommunicator *m_pMbComm{nullptr}; //< 消息总线通信器

View File

@ -16,5 +16,6 @@ SUBDIRS += anti_shake \
mux \
pnt_input \
pnt_output \
global_output \
global_input \
base_period_calc

View File

@ -0,0 +1,163 @@
/**
@file GlobalInput.cpp
@brief
@author
*/
#include "GlobalInput.h"
#include "boost/make_shared.hpp"
#include "pub_logger_api/logger.h"
#include "pub_utility_api/CharUtil.h"
#include "pub_utility_api/TimeUtil.h"
#include "fbd_designer/fbd_block/BlockDefine.h"
namespace iot_app
{
namespace app_fbd
{
CGlobalInput::CGlobalInput()
: m_nVarDataType(0),
m_ptrDiagData( nullptr )
{
}
CGlobalInput::~CGlobalInput()
{
clean();
m_ptrDiagData.reset();
}
int CGlobalInput::init( const SFbdModKey &stModuleKey, const std::string &strExtraParam )
{
boost::ignore_unused_variable_warning(strExtraParam);
m_stModKey = stModuleKey;
m_ptrDiagData = getFbdDiagDataApi();
if ( m_ptrDiagData == nullptr )
{
LOGERROR( "获取Diagram数据接口单例失败" );
return iotFailed;
}
std::string strVarDataType;
//< 1.先获取参数信息,获取数据类型和是否启用了使能引脚
if(iotSuccess != m_ptrDiagData->getModProperty(m_stModKey,"VarName",m_strVarName) ||
iotSuccess != m_ptrDiagData->getModProperty(m_stModKey,"VarDataType",strVarDataType))
{
LOGERROR( "获取模块[%s]属性失败", m_stModKey.toString().c_str());
return iotFailed;
}
if(m_strVarName.empty())
{
LOGERROR( "模块[%s]变量名为空", m_stModKey.toString().c_str());
return iotFailed;
}
try
{
m_nVarDataType = boost::lexical_cast<int>(strVarDataType);
}
catch ( const std::exception &e )
{
LOGERROR( "模块[%s]参数格式非法Err\n%s", m_stModKey.toString().c_str(), e.what());
return iotFailed;
}
if(m_nVarDataType != E_PORTDATA_BOOL && m_nVarDataType != E_PORTDATA_INT &&
m_nVarDataType != E_PORTDATA_FLOAT && m_nVarDataType != E_PORTDATA_STRING)
{
LOGERROR("模块[%s]数据类型非法,仅支持数值型和字符串类型", m_stModKey.toString().c_str());
return iotFailed;
}
//< 2.获取输出参数
if ( iotSuccess != m_ptrDiagData->getValKeyByModOutput( stModuleKey, 1, m_stOutKeyValue ) )
{
LOGERROR( "获取模块[%s]的输出参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
LOGINFO( "[%s]加载成功", m_stModKey.toString().c_str());
return iotSuccess;
}
int CGlobalInput::calculate()
{
switch (m_nVarDataType)
{
case E_PORTDATA_INT:
case E_PORTDATA_FLOAT:
case E_PORTDATA_BOOL:
return calcNumericValue();
case E_PORTDATA_STRING:
return calcStringValue();
default:
break;
}
return iotSuccess;
}
int CGlobalInput::calcNumericValue()
{
//失败默认输出无效值0
SFbdNumericValue stOutput( 0, CN_FBD_STATUS_Invalid );
if(iotSuccess != m_ptrDiagData->getGlobalNumericValByKey(m_strVarName,stOutput))
{
//< 出错则将值设置为无效状态
LOGERROR( "获取模块[%s]输入参数[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
}
if(iotSuccess != m_ptrDiagData->setNumericValByKey(m_stOutKeyValue,stOutput))
{
LOGERROR( "设置模块[%s]的设置输出[%s]值失败", m_stModKey.toString().c_str(),
m_stOutKeyValue.toString().c_str());
return iotFailed;
}
return iotSuccess;
}
int CGlobalInput::calcStringValue()
{
//失败默认输出无效值 空字符串
SFbdStringValue stOutput( "", CN_FBD_STATUS_Invalid );
if(iotSuccess != m_ptrDiagData->getGlobalStringValByKey(m_strVarName,stOutput))
{
//< 出错则将值设置为无效状态
LOGERROR( "获取模块[%s]输入参数[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
}
if(iotSuccess != m_ptrDiagData->setStringValByKey(m_stOutKeyValue,stOutput))
{
LOGERROR( "设置模块[%s]的设置输出[%s]值失败", m_stModKey.toString().c_str(),
m_stOutKeyValue.toString().c_str());
return iotFailed;
}
return iotSuccess;
}
int CGlobalInput::reset( const bool /*bMaster*/ )
{
return iotSuccess;
}
int CGlobalInput::clean()
{
return reset( false );
}
boost::shared_ptr<CGlobalInput> CGlobalInput::create()
{
return boost::make_shared<CGlobalInput>();
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,64 @@
/**
@file GlobalInput.h
@brief
@author
*/
#pragma once
#include "boost/dll/alias.hpp"
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
namespace iot_app
{
namespace app_fbd
{
/* @brief 全局变量输入类 */
class CGlobalInput final : public CBaseModule
{
public:
CGlobalInput();
virtual ~CGlobalInput() override;
int init( const SFbdModKey &stModuleKey, const std::string &strExtraParam ) override;
int calculate() override;
int reset( const bool bMaster ) override;
int clean() override;
// Factory method
static boost::shared_ptr<CGlobalInput> create();
private:
/**
@brief
@return iotSuccess,
*/
int calcNumericValue();
/**
@brief
@return iotSuccess,
*/
int calcStringValue();
private:
std::string m_strVarName; //< 变量名
int m_nVarDataType; //< 变量数据类型
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
SFbdModKey m_stModKey; //< 模块标识
SFbdValueKey m_stOutKeyValue; //< 输出参数1, 值
};
BOOST_DLL_ALIAS(
CGlobalInput::create, // 要导出的函数
create_plugin // 将导出函数重命名,最终调用者访问此函数名
)
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,35 @@
QT -= core gui
CONFIG -= qt
TEMPLATE = lib
TARGET = global_input
# Input
HEADERS += \
GlobalInput.h
SOURCES += \
GlobalInput.cpp
LIBS += -lboost_system -lboost_chrono
LIBS += -lpub_logger_api -llog4cplus -lfbd_common
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")
}
#为了统一将fbd_module下所有dll生成到规定目录
FBD_MODULE_PRI=$$PWD/../fbd_module.pri
exists($$FBD_MODULE_PRI) {
include($$FBD_MODULE_PRI)
}else {
error("FATAL error: can not find fbd_module.pri")
}

View File

@ -0,0 +1,303 @@
/**
@file GlobalOutput.cpp
@brief
@author
*/
#include "GlobalOutput.h"
#include "boost/make_shared.hpp"
#include "pub_logger_api/logger.h"
#include "pub_utility_api/CharUtil.h"
#include "pub_utility_api/TimeUtil.h"
#include "fbd_designer/fbd_block/BlockDefine.h"
namespace iot_app
{
namespace app_fbd
{
CGlobalOutput::CGlobalOutput()
: m_nVarDataType(0),
m_bHasEnableInput(false),
m_bIsRegist(false),
m_ptrDiagData( nullptr )
{
}
CGlobalOutput::~CGlobalOutput()
{
clean();
m_ptrDiagData.reset();
}
int CGlobalOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtraParam )
{
boost::ignore_unused_variable_warning(strExtraParam);
m_stModKey = stModuleKey;
m_ptrDiagData = getFbdDiagDataApi();
if ( m_ptrDiagData == nullptr )
{
LOGERROR( "获取Diagram数据接口单例失败" );
return iotFailed;
}
std::string strHasEnableInput;
std::string strVarDataType;
//< 1.先获取参数信息,获取数据类型和是否启用了使能引脚
if(iotSuccess != m_ptrDiagData->getModProperty(m_stModKey,"VarName",m_strVarName) ||
iotSuccess != m_ptrDiagData->getModProperty(m_stModKey,"HasEnableInput",strHasEnableInput) ||
iotSuccess != m_ptrDiagData->getModProperty(m_stModKey,"VarDataType",strVarDataType))
{
LOGERROR( "获取模块[%s]属性失败", m_stModKey.toString().c_str());
return iotFailed;
}
if(m_strVarName.empty())
{
LOGERROR( "模块[%s]变量名为空", m_stModKey.toString().c_str());
return iotFailed;
}
try
{
m_bHasEnableInput = boost::lexical_cast<int>(strHasEnableInput) != 0;
m_nVarDataType = boost::lexical_cast<int>(strVarDataType);
}
catch ( const std::exception &e )
{
LOGERROR( "模块[%s]参数格式非法Err\n%s", m_stModKey.toString().c_str(), e.what());
return iotFailed;
}
if(m_nVarDataType != E_PORTDATA_BOOL && m_nVarDataType != E_PORTDATA_INT &&
m_nVarDataType != E_PORTDATA_FLOAT && m_nVarDataType != E_PORTDATA_STRING)
{
LOGERROR("模块[%s]数据类型非法,仅支持数值型和字符串类型", m_stModKey.toString().c_str());
return iotFailed;
}
//< 2.获取输入、输出参数
if ( iotSuccess != m_ptrDiagData->getValKeyByModInput( stModuleKey, 1, m_stInKeyValue ) ||
(m_bHasEnableInput && (iotSuccess != m_ptrDiagData->getValKeyByModInput(stModuleKey, 2, m_stInKeyEnable))) )
{
LOGERROR( "获取模块[%s]的输入输出参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
//< 3.查看变量是否已经存在,防止不同的全局变量重名,暂时只是日志提醒
if(!registGlobalVariable())
{
LOGERROR("模块[%s]注册全局变量[%s]失败", stModuleKey.toString().c_str(),m_strVarName.c_str());
return iotFailed;
}
LOGINFO( "[%s]加载成功", m_stModKey.toString().c_str());
return iotSuccess;
}
int CGlobalOutput::calculate()
{
if(!isEnableOutput())
{
return iotSuccess;
}
switch (m_nVarDataType)
{
case E_PORTDATA_INT:
case E_PORTDATA_FLOAT:
case E_PORTDATA_BOOL:
return calcNumericValue();
case E_PORTDATA_STRING:
return calcStringValue();
default:
break;
}
return iotSuccess;
}
bool CGlobalOutput::isEnableOutput()
{
if(!m_bHasEnableInput)
{
return true; //没有使能引脚,默认输出
}
SFbdNumericValue stInValEnable;
if ( iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKeyEnable, stInValEnable ))
{
LOGERROR( "获取模块[%s]的输入 使能 的值失败", m_stModKey.toString().c_str());
return false;
}
if(!isValidOfStatus(stInValEnable.m_nStatus))
{
return false; //< 状态无效,禁用输出
}
bool bEnableOutput = (0 != static_cast<int>(stInValEnable.m_dValue));
return bEnableOutput;
}
bool CGlobalOutput::registGlobalVariable()
{
int nRegResult = iotSuccess;
if(m_nVarDataType == E_PORTDATA_STRING) //前面做了类型合法性判断,此处不再精准判断
{
SFbdStringValue stInitValue( "", CN_FBD_STATUS_Invalid );
nRegResult = m_ptrDiagData->regGlobalStringValByKey(m_strVarName,stInitValue);
}
else
{
SFbdNumericValue stInitValue( 0, CN_FBD_STATUS_Invalid );
nRegResult = m_ptrDiagData->regGlobalNumericValByKey(m_strVarName,stInitValue);
}
if(nRegResult == iotSuccess)
{
LOGINFO("模块[%s]的全局变量[%s]注册成功", m_stModKey.toString().c_str(),m_strVarName.c_str());
m_bIsRegist = true;
return true;
}
else if(nRegResult == iotFBDErr_GlobalVarAlreadyExist)
{
LOGWARN("模块[%s]的全局变量[%s]已经存在", m_stModKey.toString().c_str(),m_strVarName.c_str());
//不设置m_bIsRegist为true本着谁注册谁销毁的原则处理
return true;
}
else if(nRegResult == iotFBDErr_GlobalVarTypeMismatch)
{
LOGERROR("模块[%s]的全局变量[%s]已经存在且数据类型不匹配", m_stModKey.toString().c_str(),m_strVarName.c_str());
return false;
}
else
{
LOGERROR("模块[%s]的全局变量[%s]注册失败", m_stModKey.toString().c_str(),m_strVarName.c_str());
return false;
}
}
bool CGlobalOutput::unregistGlobalVariable()
{
int nRegResult = iotSuccess;
if(m_nVarDataType == E_PORTDATA_STRING) //前面做了类型合法性判断,此处不再精准判断
{
nRegResult = m_ptrDiagData->unregGlobalStringVar(m_strVarName);
}
else
{
nRegResult = m_ptrDiagData->unregGlobalNumericVar(m_strVarName);
}
if(iotSuccess != nRegResult)
{
LOGERROR("模块[%s]的全局变量[%s]取消注册失败", m_stModKey.toString().c_str(),m_strVarName.c_str());
return false;
}
m_bIsRegist = false;
LOGINFO("模块[%s]的全局变量[%s]取消注册成功", m_stModKey.toString().c_str(),m_strVarName.c_str());
return true;
}
int CGlobalOutput::calcNumericValue()
{
//使能,同时状态有效,则输出计算
SFbdNumericValue stInput( 0, CN_FBD_STATUS_Invalid );
if ( iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKeyValue, stInput ))
{
//< 出错则将值设置为无效状态
LOGERROR( "获取模块[%s]输入参数[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
}
if(iotSuccess != m_ptrDiagData->setGlobalNumericValByKey(m_strVarName,stInput))
{
LOGERROR( "设置模块[%s]的变量[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
return iotFailed;
}
return iotSuccess;
}
int CGlobalOutput::calcStringValue()
{
//使能,同时状态有效,则输出计算
SFbdStringValue stInput( "", CN_FBD_STATUS_Invalid );
if ( iotSuccess != m_ptrDiagData->getStringValByKey( m_stInKeyValue, stInput ))
{
//< 出错则将值设置为无效状态
LOGERROR( "获取模块[%s]输入参数[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
}
if(iotSuccess != m_ptrDiagData->setGlobalStringValByKey(m_strVarName,stInput))
{
LOGERROR( "设置模块[%s]的变量[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
return iotFailed;
}
return iotSuccess;
}
int CGlobalOutput::reset( const bool /*bMaster*/ )
{
if(m_strVarName.empty() || m_ptrDiagData == nullptr)
{
return iotSuccess;
}
//主备切换时,暂时将值设置为无效值
int nRet = iotSuccess;
SFbdNumericValue stVal(0,CN_FBD_STATUS_Invalid);
SFbdStringValue stStrVal("",CN_FBD_STATUS_Invalid);
switch (m_nVarDataType)
{
case E_PORTDATA_INT:
case E_PORTDATA_FLOAT:
case E_PORTDATA_BOOL:
nRet = m_ptrDiagData->setGlobalNumericValByKey(m_strVarName,stVal);
break;
case E_PORTDATA_STRING:
nRet = m_ptrDiagData->setGlobalStringValByKey(m_strVarName,stStrVal);
break;
default:
break;
}
if(nRet != iotSuccess)
{
LOGERROR("主备切换时设置模块[%s]的变量[%s]值失败", m_stModKey.toString().c_str(),
m_strVarName.c_str());
}
return iotSuccess;
}
int CGlobalOutput::clean()
{
if(m_bIsRegist)
{
unregistGlobalVariable();
}
return reset( false );
}
boost::shared_ptr<CGlobalOutput> CGlobalOutput::create()
{
return boost::make_shared<CGlobalOutput>();
}
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,86 @@
/**
@file GlobalOutput.h
@brief
@author
*/
#pragma once
#include "boost/dll/alias.hpp"
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
namespace iot_app
{
namespace app_fbd
{
/* @brief 全局变量输出类 */
class CGlobalOutput final : public CBaseModule
{
public:
CGlobalOutput();
virtual ~CGlobalOutput() override;
int init( const SFbdModKey &stModuleKey, const std::string &strExtraParam ) override;
int calculate() override;
int reset( const bool bMaster ) override;
int clean() override;
// Factory method
static boost::shared_ptr<CGlobalOutput> create();
private:
/**
@brief
@return true,false
*/
bool isEnableOutput();
/**
@brief
@return true,false
*/
bool registGlobalVariable();
/**
@brief
@return true,false
*/
bool unregistGlobalVariable();
/**
@brief
@return iotSuccess,
*/
int calcNumericValue();
/**
@brief
@return iotSuccess,
*/
int calcStringValue();
private:
std::string m_strVarName; //< 变量名
int m_nVarDataType; //< 变量数据类型
bool m_bHasEnableInput; //< 是否启用了使能引脚0禁用1启用
bool m_bIsRegist; //< 变量是否已经注册,用于识别是否需要取消注册
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
SFbdModKey m_stModKey; //< 模块标识
SFbdValueKey m_stInKeyValue; //< 输入参数1, 值
SFbdValueKey m_stInKeyEnable; //< 输入参数2, 是否使能
};
BOOST_DLL_ALIAS(
CGlobalOutput::create, // 要导出的函数
create_plugin // 将导出函数重命名,最终调用者访问此函数名
)
} //< namespace app_fbd
} //< namespace iot_app

View File

@ -0,0 +1,35 @@
QT -= core gui
CONFIG -= qt
TEMPLATE = lib
TARGET = global_output
# Input
HEADERS += \
GlobalOutput.h
SOURCES += \
GlobalOutput.cpp
LIBS += -lboost_system -lboost_chrono
LIBS += -lpub_logger_api -llog4cplus -lfbd_common
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")
}
#为了统一将fbd_module下所有dll生成到规定目录
FBD_MODULE_PRI=$$PWD/../fbd_module.pri
exists($$FBD_MODULE_PRI) {
include($$FBD_MODULE_PRI)
}else {
error("FATAL error: can not find fbd_module.pri")
}

View File

@ -54,7 +54,7 @@ int CAnd::calc( const std::vector<SFbdNumericValue> &vecInput,
SFbdNumericValue &stOutput )
{
int nValue = static_cast<int>(vecInput[0].m_dValue);
stOutput.m_nStatus = CN_FBD_STATUS_Valid;
stOutput.m_nStatus = vecInput[0].m_nStatus;
for ( size_t i = 1; i < vecInput.size(); ++i )
{

View File

@ -45,7 +45,7 @@ int COr::calc( const std::vector<SFbdNumericValue> &vecInput,
SFbdNumericValue &stOutput )
{
int nValue = static_cast<int>(vecInput[0].m_dValue);
stOutput.m_nStatus = CN_FBD_STATUS_Valid;
stOutput.m_nStatus = vecInput[0].m_nStatus;
for ( size_t i = 1; i < vecInput.size(); ++i )
{

View File

@ -32,6 +32,8 @@ CPntInput::~CPntInput()
int CPntInput::init( const SFbdModKey &stModuleKey, const std::string & )
{
m_strInputKeyId = "";
m_strIsOutputKeyId = "";
m_stModKey = stModuleKey;
m_ptrDiagData = getFbdDiagDataApi();
@ -50,16 +52,25 @@ int CPntInput::init( const SFbdModKey &stModuleKey, const std::string & )
//< 获取参数
{
std::string strInputKeyId;
if ( iotSuccess != m_ptrDiagData->getModProperty( stModuleKey, "InputKeyId", strInputKeyId ))
if ( iotSuccess != m_ptrDiagData->getModProperty( stModuleKey, "InputKeyId", m_strInputKeyId ))
{
LOGERROR( "获取模块[%s]属性失败", m_stModKey.toString().c_str());
return iotFailed;
}
if ( iotSuccess != splitLongKeyIdTag( strInputKeyId, m_stPntInfo ))
int nRet = m_ptrDiagData->getModProperty( stModuleKey, "IsOutputKeyId", m_strIsOutputKeyId );
if ( nRet == iotSuccess && m_strIsOutputKeyId == "1" )
{
LOGERROR( "解析测点信息失败.KeyIdTag=[%s]", strInputKeyId.c_str());
if ( iotSuccess != m_ptrDiagData->getValKeyByModOutput( stModuleKey, 2, m_stOutputKey2 ))
{
LOGERROR( "获取模块[%s]的输入输出参数失败", stModuleKey.toString().c_str());
return iotFailed;
}
}
if ( iotSuccess != splitLongKeyIdTag( m_strInputKeyId, m_stPntInfo ))
{
LOGERROR( "解析测点信息失败.KeyIdTag=[%s]", m_strInputKeyId.c_str());
return iotFailed;
}
@ -98,6 +109,7 @@ int CPntInput::init( const SFbdModKey &stModuleKey, const std::string & )
int CPntInput::calculate()
{
SFbdNumericValue stOutput( 0, CN_FBD_STATUS_Invalid );
SFbdStringValue stOutput2( m_strInputKeyId, CN_FBD_STATUS_Invalid );
double dInValue = 0.0;
int nInStatus = 0;
@ -107,9 +119,12 @@ int CPntInput::calculate()
if ( m_ptrPointSub->isValidOfPntSta( m_nPntType, nInStatus ))
{
stOutput.m_nStatus = CN_FBD_STATUS_Valid;
stOutput2.m_nStatus = CN_FBD_STATUS_Valid;
}
}
if ( m_strIsOutputKeyId == "1" )
m_ptrDiagData->setStringValByKey( m_stOutputKey2, stOutput2 );
return m_ptrDiagData->setNumericValByKey( m_stOutputKey, stOutput );
}

View File

@ -45,6 +45,10 @@ private:
SLongKeyIdTagInfo m_stPntInfo; //< 输入测点信息
SFbdValueKey m_stOutputKey; //< 输出key
SFbdValueKey m_stOutputKey2; //< 第二个输出的key
std::string m_strInputKeyId; // 测点串
std::string m_strIsOutputKeyId; // 是否输出测点串
};
BOOST_DLL_ALIAS(

View File

@ -33,6 +33,7 @@ CPntOutput::CPntOutput()
m_nInValidPntStatus( 0 ),
m_nSendIntervalMsec( 5000 ),
m_lLastSendTimeMsec( 0L ),
m_bEnableWhenStatusInvalid(false),
m_ptrDiagData( nullptr )
{
}
@ -55,6 +56,7 @@ int CPntOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtra
}
m_ptrDiagData = getFbdDiagDataApi();
m_ptrOptCmdApi = getFbdDiagOptCmdApi();
if ( m_ptrDiagData == nullptr )
{
LOGERROR( "获取Diagram数据接口单例失败" );
@ -62,7 +64,8 @@ int CPntOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtra
}
//1.获取输入、输出参数
if ( iotSuccess != m_ptrDiagData->getValKeyByModInput( stModuleKey, 1, m_stInKey1 ))
if ( iotSuccess != m_ptrDiagData->getValKeyByModInput( stModuleKey, 1, m_stInKey1 ) ||
iotSuccess != m_ptrDiagData->getValKeyByModInput( stModuleKey, 2, m_stInKeyEnable) )
{
LOGERROR( "获取模块[%s]的输入输出参数失败", stModuleKey.toString().c_str());
return iotFailed;
@ -71,7 +74,10 @@ int CPntOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtra
//< 获取参数
{
std::string strOutputKeyId;
if ( iotSuccess != m_ptrDiagData->getModProperty( stModuleKey, "OutputKeyId", strOutputKeyId ))
std::string strEnableWhenInvalid;
if ( iotSuccess != m_ptrDiagData->getModProperty( stModuleKey, "OutputKeyId", strOutputKeyId) ||
iotSuccess != m_ptrDiagData->getModProperty(m_stModKey, "EnableWhenInvalid", strEnableWhenInvalid) )
{
LOGERROR( "获取模块[%s]属性失败", m_stModKey.toString().c_str());
return iotFailed;
@ -88,6 +94,16 @@ int CPntOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtra
LOGERROR( "解析模块[%s]关联的测点[%s]信息失败", stModuleKey.toString().c_str(), m_stPntInfo.strOriginalKey.c_str());
return iotFailed;
}
try
{
m_bEnableWhenStatusInvalid = boost::lexical_cast<int>(strEnableWhenInvalid) != 0;
}
catch ( const std::exception &e )
{
LOGERROR( "模块[%s]参数格式非法Err\n%s", m_stModKey.toString().c_str(), e.what());
return iotFailed;
}
}
LOGINFO( "[%s]加载成功", m_stModKey.toString().c_str());
@ -97,6 +113,21 @@ int CPntOutput::init( const SFbdModKey &stModuleKey, const std::string &strExtra
int CPntOutput::calculate()
{
SFbdNumericValue stInValEnable;
if ( iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKeyEnable, stInValEnable ))
{
LOGERROR( "获取模块[%s]的输入 使能 的值失败", m_stModKey.toString().c_str());
return iotFailed;
}
//不使能直接返回,使能且需要判断状态是否有效时才进行状态的判断
if ( 0 == static_cast<int>(stInValEnable.m_dValue) ||
(!m_bEnableWhenStatusInvalid && !isValidOfStatus(stInValEnable.m_nStatus)))
{
return iotSuccess;//不使能,直接返回
}
//使能,同时状态有效,则输出计算
SFbdNumericValue stInput( 0, CN_FBD_STATUS_Invalid );
if ( iotSuccess != m_ptrDiagData->getNumericValByKey( m_stInKey1, stInput ))
@ -106,6 +137,9 @@ int CPntOutput::calculate()
m_stInKey1.toString().c_str());
}
sendToDP( stInput );
/*
//< 到定时周期,或者与上次值发生变化
int64 lCurTime = iot_public::getMonotonicMsec();
if ( lCurTime - m_lLastSendTimeMsec > m_nSendIntervalMsec || stInput != m_stLastValAndSta )
@ -114,7 +148,7 @@ int CPntOutput::calculate()
m_lLastSendTimeMsec = lCurTime;
m_stLastValAndSta = stInput;
}
*/
return iotSuccess;
}
@ -253,7 +287,7 @@ int CPntOutput::sendMsg( const std::string &strMsg )
iot_idl::MT_OPT_SET_CAL_DATA_DOWN );
objMsg.setPara1( m_nDomainIdOfPnt ); //TODO:需要填写吗?
if ( !m_objCommunicator.sendMsgToDomain( objMsg, m_nDomainIdOfPnt )) //< 发送到测点所在域
if ( !m_ptrOptCmdApi->sendMsgToDomainByPublishCommunicator(objMsg, m_nDomainIdOfPnt )) //< 发送到测点所在域
{
LOGERROR( "模块[%s]发送消息到域[%d]-应用[%d]失败",
m_stModKey.toString().c_str(), m_nDomainIdOfPnt, m_nAppIdOfPnt );

View File

@ -12,6 +12,7 @@
#include "app_fbd/fbd_common/BaseModule.h"
#include "app_fbd/fbd_common/FbdDiagDataApi.h"
#include "app_fbd/fbd_common/FbdPointSubApi.h"
#include "app_fbd/fbd_common/FbdDiagOptCmdApi.h"
namespace iot_app
{
@ -72,6 +73,7 @@ private:
uint32 m_nInValidPntStatus; //< 测点无效状态位
int m_nSendIntervalMsec; //< 数据断面发送间隔
int64 m_lLastSendTimeMsec; //< 最后一次发送时间
bool m_bEnableWhenStatusInvalid; //当使能值(输入参数2)的状态无效时是否继续输出0不输出1输出
CFbdDiagDataApiPtr m_ptrDiagData; //< Diagram数据接口
@ -80,9 +82,10 @@ private:
SLongKeyIdTagInfo m_stPntInfo; //< 输出测点信息
SFbdValueKey m_stInKey1; //< 输入参数1
SFbdValueKey m_stInKeyEnable; //< 输入参数2是否使能
SFbdNumericValue m_stLastValAndSta; //< 记录上一次的值
iot_net::CMbCommunicator m_objCommunicator; //< 通信器
CFbdDiagOptCmdApiPtr m_ptrOptCmdApi; //< opt服务接口
};
BOOST_DLL_ALIAS(

View File

@ -3,8 +3,18 @@
#include <map>
//< 屏蔽xml_parser编译告警
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-copy"
#endif
#include "boost/property_tree/xml_parser.hpp"
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#include "boost/typeof/typeof.hpp"
#include "boost/filesystem.hpp"

View File

@ -8,6 +8,7 @@
#include <QDateTime>
#include <public/pub_sysinfo_api/SysInfoApi.h>
#include "db_api_ex/CDbApi.h"
#include "pub_widget/MessageBox.h"
QString getMethodStr(const QString& method){
if(method == "smtp"){
@ -33,15 +34,17 @@ QString getResult(int result){
}
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
CustomUiMainWindow(parent),
ui(new Ui::MainWindow)
{
setAutoLayout(true);
ui->setupUi(this);
ui->tableWidget_pushHis->verticalHeader()->hide();
refreshHis();
setWindowIcon( QIcon( ":push_debug.ico" ) );
setWindowTitle( QObject::tr("推送服务调试") );
setWindowTitle( QObject::tr("推送服务调试工具") );
connect(ui->pushButton_sendMail,&QPushButton::clicked,this,&MainWindow::sendMail_clicked);
connect(ui->pushButton_bbiot_send,&QPushButton::clicked,this,&MainWindow::sendBbiot_clicked);
@ -72,7 +75,7 @@ void MainWindow::sendMail_clicked()
|| QString::number(ui->spinBox_port->value()) == ""
)
{
QMessageBox::information(this,"提示","检查是否输入参数为空");
N_MessageBox::information(this,"提示","检查是否输入参数为空");
return;
}
@ -103,9 +106,9 @@ void MainWindow::sendMail_clicked()
if(!m_objComm.sendMsgToDomain(msg)){
QMessageBox::information(this,"提示","发送失败");
N_MessageBox::information(this,"提示","发送失败");
}else{
QMessageBox::information(this,"提示","发送成功");
N_MessageBox::information(this,"提示","发送成功");
}
@ -122,7 +125,7 @@ void MainWindow::sendBbiot_clicked()
|| ui->lineEdit_bbiot_content->text() == ""
)
{
QMessageBox::information(this,"提示","检查是否输入参数为空");
N_MessageBox::information(this,"提示","检查是否输入参数为空");
return;
}
@ -151,9 +154,9 @@ void MainWindow::sendBbiot_clicked()
if(!m_objComm.sendMsgToDomain(msg)){
QMessageBox::information(this,"提示","发送失败");
N_MessageBox::information(this,"提示","发送失败");
}else{
QMessageBox::information(this,"提示","发送成功");
N_MessageBox::information(this,"提示","发送成功");
}
}
@ -164,7 +167,7 @@ void MainWindow::refreshHis()
iot_dbms::CDbApi DbReadApi(DB_CONN_MODEL_READ);
if(!DbReadApi.open())
{
QMessageBox::information(this,"提示","无法连接数据库");
N_MessageBox::information(this,"提示","无法连接数据库");
return;
}
@ -204,7 +207,7 @@ void MainWindow::refreshHis()
void MainWindow::emptyHis()
{
if ( QMessageBox::question(this,"提示","是否删除历史?") == QMessageBox::No)
if ( N_MessageBox::question(this,"提示","是否删除历史?") != QMessageBox::Ok)
{
return ;
}
@ -212,16 +215,16 @@ void MainWindow::emptyHis()
iot_dbms::CDbApi DbReadApi(DB_CONN_MODEL_WRITE);
if(!DbReadApi.open())
{
QMessageBox::information(this,"提示","无法连接数据库");
N_MessageBox::information(this,"提示","无法连接数据库");
return;
}
if(DbReadApi.deleteRow("push_his"))
{
QMessageBox::information(this,"提示","删除成功");
N_MessageBox::information(this,"提示","删除成功");
ui->tableWidget_pushHis->setRowCount(0);
}else{
QMessageBox::information(this,"提示","删除失败");
N_MessageBox::information(this,"提示","删除失败");
}
}

View File

@ -3,12 +3,13 @@
#include <QMainWindow>
#include "net_msg_bus_api/CMbCommunicator.h"
#include "pub_widget/CustomMainWindow.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
class MainWindow : public CustomUiMainWindow
{
Q_OBJECT

View File

@ -1,14 +1,48 @@
#include <QApplication>
#include <QApplication>
#include "common/QtAppGlobalSet.h"
#include "net_msg_bus_api/MsgBusApi.h"
#include "MainWindow.h"
#include "pub_utility_api/FileStyle.h"
#include "pub_widget/PubWidgetInit.h"
void loadStyle()
{
QString qss = QString();
std::string strFullPath = iot_public::CFileStyle::getPathOfStyleFile("public.qss","zh","light");
QFile qssfile1(QString::fromStdString(strFullPath));
qssfile1.open(QFile::ReadOnly);
if (qssfile1.isOpen())
{
qss += QLatin1String(qssfile1.readAll());
qssfile1.close();
}
strFullPath = iot_public::CFileStyle::getPathOfStyleFile("linkage_server_tool.qss","zh","light");
QFile qssfile2(QString::fromStdString(strFullPath));
qssfile2.open(QFile::ReadOnly);
if (qssfile2.isOpen())
{
qss += QLatin1String(qssfile2.readAll());
qssfile2.close();
}
if (!qss.isEmpty())
{
qApp->setStyleSheet(qss);
}
iot_public::installTranslator("zh");
}
int main(int argc, char *argv[])
{
iot_common::doQtAppGlobalSet();
QApplication a(argc, argv);
loadStyle();
iot_net::initMsgBus("push_debug","");
int result;
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -32,7 +32,7 @@ HEADERS += \
FORMS += \
MainWindow.ui
LIBS += -lnet_msg_bus_api -lpub_sysinfo_api -lprotobuf -ldb_api_ex
LIBS += -lnet_msg_bus_api -lpub_sysinfo_api -lprotobuf -ldb_api_ex -lpub_widget -lpub_utility_api
include($$PWD/../../idl_files/idl_files.pri)