From 2e1b3bc130b6c08c6982150b9c7cc3d2e2ff86cf Mon Sep 17 00:00:00 2001 From: shi_jq Date: Tue, 12 Nov 2024 10:30:59 +0800 Subject: [PATCH] =?UTF-8?q?[A]=E5=A2=9E=E5=8A=A0sqlserver=20=E6=8F=92?= =?UTF-8?q?=E5=85=A5=EF=BC=8C=20=E7=BB=99=E9=B8=A6=E5=8E=82=E7=94=B5?= =?UTF-8?q?=E5=8A=9B=E7=9B=91=E6=8E=A7=E5=AE=9A=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 13 + product/src/fes/protocol/protocol.pro | 3 +- .../protocol/sqlserver_s/DataProcThread.cpp | 483 ++++++++++++++++++ .../fes/protocol/sqlserver_s/DataProcThread.h | 80 +++ .../fes/protocol/sqlserver_s/SqlServer.cpp | 339 ++++++++++++ .../src/fes/protocol/sqlserver_s/SqlServer.h | 36 ++ .../fes/protocol/sqlserver_s/sqlserver_s.pro | 33 ++ 7 files changed, 986 insertions(+), 1 deletion(-) create mode 100644 .gitignore create mode 100644 product/src/fes/protocol/sqlserver_s/DataProcThread.cpp create mode 100644 product/src/fes/protocol/sqlserver_s/DataProcThread.h create mode 100644 product/src/fes/protocol/sqlserver_s/SqlServer.cpp create mode 100644 product/src/fes/protocol/sqlserver_s/SqlServer.h create mode 100644 product/src/fes/protocol/sqlserver_s/sqlserver_s.pro diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9d2e913d --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +log/**/*.log +product/src/**/*.pro.user +product/src/temp/* +product/src/**/Makefile.Debug +product/src/**/Makefile +product/windows10_debug/*.pdb +product/src/**/Makefile.Release +product/src/**/.qmake.stash +product/windows10_debug/*.lib +product/windows10_debug/*.ilk +product/windows10_debug/*.exp +product/windows10_debug/*.dll +product/windows10_debug/*.exe diff --git a/product/src/fes/protocol/protocol.pro b/product/src/fes/protocol/protocol.pro index fad80241..6f528236 100644 --- a/product/src/fes/protocol/protocol.pro +++ b/product/src/fes/protocol/protocol.pro @@ -45,7 +45,8 @@ SUBDIRS += \ fesdatarecv \ modbus_tcpV3 \ iec104V2 \ - ad104s + ad104s \ + sqlserver_s win32-msvc* { diff --git a/product/src/fes/protocol/sqlserver_s/DataProcThread.cpp b/product/src/fes/protocol/sqlserver_s/DataProcThread.cpp new file mode 100644 index 00000000..78f94ae0 --- /dev/null +++ b/product/src/fes/protocol/sqlserver_s/DataProcThread.cpp @@ -0,0 +1,483 @@ +/* + @file DataProcThread.cpp + @brief 数据处理线程类。 + @history + */ +#include +#include "DataProcThread.h" +#include "pub_utility_api/CommonConfigParse.h" +#include "pub_utility_api/I18N.h" +#include +#include + +using namespace kbd_public; + +DataProcThread::DataProcThread(CFesBase *ptrCFesBase, + CFesChanPtr ptrCFesChan, + const vector vecAppParam): + CTimerThreadBase("DataProcThread", 500,0,true) +{ + m_ptrCFesChan = ptrCFesChan; + m_ptrCFesBase = ptrCFesBase; + m_ptrCurrentChan = ptrCFesChan; + m_ptrCFesRtu = GetRtuDataByChanData(m_ptrCFesChan); + + m_timerCountReset = 10; + m_timerCount = 0; + + if ((m_ptrCFesChan == NULL) || (m_ptrCFesRtu == NULL)) + { + return; + } + + m_ptrCFesChan->SetLinkStatus(CN_FesChanConnect); + m_ptrCFesChan->SetComThreadRunFlag(CN_FesRunFlag); + m_ptrCFesChan->SetChangeFlag(CN_FesChanUnChange); + m_ptrCFesChan->SetDataThreadRunFlag(CN_FesRunFlag); + m_ptrCFesBase->WriteRtuSatus(m_ptrCFesRtu, CN_FesRtuComDown); + //2020-03-03 thxiao 不需要数据变化 + m_ptrCFesRtu->SetFwAiChgStop(1); + m_ptrCFesRtu->SetFwDiChgStop(1); + m_ptrCFesRtu->SetFwDDiChgStop(1); + m_ptrCFesRtu->SetFwMiChgStop(1); + m_ptrCFesRtu->SetFwAccChgStop(1); + + int found = 0; + if(vecAppParam.size()>0) + { + for (size_t i = 0; i < vecAppParam.size(); i++) + { + if(m_ptrCFesRtu->m_Param.RtuNo == vecAppParam[i].RtuNo) + { + m_AppData = vecAppParam[i]; + found = 1; + break; + } + } + } + if(!found) + InitConfigParam();//配置文件读取失败,取默认配置 +} + +DataProcThread::~DataProcThread() +{ + quit();//在调用quit()前,系统会调用beforeQuit(); + m_ptrCFesBase->WriteRtuSatus(m_ptrCFesRtu, CN_FesRtuComDown); + LOGDEBUG("DataProcThread::~DataProcThread() ChanNo=%d 退出", m_ptrCFesChan->m_Param.ChanNo); +} + +/** + * @brief DataProcThread::beforeExecute + * + */ +int DataProcThread::beforeExecute() +{ + return kbdSuccess; +} + +/* + @brief DataProcThread::execute + + */ +void DataProcThread::execute() +{ + //读取网络事件 + if (m_timerCount++ >= m_timerCountReset) + m_timerCount = 0;// 1sec is ready + + m_ptrCurrentChan = GetCurrentChanData(m_ptrCFesChan); + if(m_ptrCurrentChan== NULL) + return; + + //处理数据 + handlData(); + + + //LOGDEBUG("DataProcThread::execute() end"); +} + +/* + @brief 执行quit函数前的处理 + */ +void DataProcThread::beforeQuit() +{ + m_ptrCFesChan->SetComThreadRunFlag(CN_FesStopFlag); + m_ptrCFesChan->SetChangeFlag(CN_FesChanUnChange); + m_ptrCFesChan->SetDataThreadRunFlag(CN_FesStopFlag); + m_ptrCFesChan->SetLinkStatus(CN_FesChanDisconnect); + + LOGDEBUG("DataProcThread::beforeQuit() "); +} + +/** + * @brief DataProcThread::InitConfigParam + * Hcmqtts 初始化配置参数 + * @return 成功返回kbdSuccess,失败返回kbdFailed + */ +int DataProcThread::InitConfigParam() +{ + if((m_ptrCFesChan == NULL)||(m_ptrCFesRtu==NULL)) + return kbdFailed; + + m_AppData.db_name = "iscs_db"; + m_AppData.table_name = "HistoryGenerallyVariable"; + m_AppData.user_name = "sa"; + m_AppData.password = "sa"; + + return kbdSuccess; +} + +void DataProcThread::TimerProcess() +{ + //定时更新本FES数据 + m_ptrCFesBase->UpdateFesAiValue(m_ptrCFesRtu); + m_ptrCFesBase->UpdateFesDiValue(m_ptrCFesRtu); + m_ptrCFesBase->UpdateFesAccValue(m_ptrCFesRtu); + m_ptrCFesBase->UpdateFesMiValue(m_ptrCFesRtu); + + //定时读取遥控命令响应缓冲区,及时清除队列释放空间,不对遥控成败作处理 + if (m_ptrCFesRtu->GetFwDoRespCmdNum() > 0) + { + SFesFwDoRespCmd retCmd; + m_ptrCFesRtu->ReadFwDoRespCmd(1, &retCmd); + } + + if (m_ptrCFesRtu->GetFwAoRespCmdNum() > 0) + { + SFesFwAoRespCmd retCmd; + m_ptrCFesRtu->ReadFwAoRespCmd(1, &retCmd); + } +} + +QSqlDatabase DataProcThread::getSqlServerClient(SServerAppConfigParam ¶) +{ + QSqlDatabase db= QSqlDatabase::addDatabase("QODBC"); + QString dsn=QString("DRIVER={SQL Server};SERVER=%1;DATABASE=%2;UID=%3;PWD=%4").arg(QString::fromStdString(m_ptrCFesChan->m_Param.NetRoute[0].NetDesc)) + .arg(QString::fromStdString(para.db_name)) + .arg(QString::fromStdString(para.user_name)) + .arg(QString::fromStdString(para.password)); + db.setDatabaseName(dsn); + return db; +} + +int DataProcThread::handlData() +{ + //获取当前使用的rtu + m_ptrCFesRtu=GetRtuDataByRtuNo(m_AppData.RtuNo); + + //判断是否到了周期时间 + if(m_mapLastUpateTime.contains(m_AppData.RtuNo)) + { + auto& lastTime=m_mapLastUpateTime[m_AppData.RtuNo]; + if(getUTCTimeSec()-lastTimem_Param.NetRoute[0].NetDesc, + db.lastError().text().toStdString().c_str()); + return kbdFailed; + } + + QString sql=" INSERT INTO %1 (VariableName, Time, Value) " + " VALUES ('%2', '%3', %4);"; + + + bool isHandle1 = handleAiData(m_ptrCFesRtu,db,sql); + bool isHandle2 = handleDiData(m_ptrCFesRtu,db,sql); + bool isHandle3 = handleMixData(m_ptrCFesRtu,db,sql); + bool isHandle4 = handleAccData(m_ptrCFesRtu,db,sql); + + db.close(); + + if(isHandle1 || isHandle2 || isHandle3 || isHandle4) + { + m_mapLastUpateTime[m_AppData.RtuNo]=getUTCTimeSec(); + } + + return kbdSuccess; +} + +bool DataProcThread::handleAiData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql) +{ + bool ret = false; + QSqlQuery query(db); + SFesFwAi *pFwAi; + double fvalue; + auto fmtTime=getFormatTime(); + int errorTime = 0; + for (int aiPoint = 0; aiPoint < ptrRtu->m_MaxFwAiPoints; aiPoint++) + { + pFwAi = m_ptrCFesRtu->m_pFwAi + aiPoint; + //bool aivalNormalFlag = 1; + if((pFwAi->Status & CN_FesValueUpdate) != CN_FesValueUpdate) + { + //LOGDEBUG("DataProcThread data value[%d] status [%d]",pFwAi->Value, pFwAi->Status); + continue; + //aivalNormalFlag = 0; + } + + std::string tagname = pFwAi->PointDesc; + fvalue = pFwAi->Value*pFwAi->Coeff + pFwAi->Base; + QString fmtVal=formatToPrecision(fvalue); + QString tableName=QString::fromStdString(m_AppData.table_name); + double value=fmtVal.toDouble(); + QString tagName=QString::fromStdString(tagname); + + //sql更新 + auto sql=QString(templateSql).arg(tableName).arg(tagName).arg(fmtTime).arg(value); + std::string sqlStr = sql.toStdString(); + if(!query.exec(sql)) + { + LOGERROR("DataProcThread.cpp sql faild info %s", sqlStr.c_str()); + + if(errorTime > 5) + { + ret = true; + break; + } + errorTime++; + continue; + } + else + { + LOGDEBUG("DataProcThread.cpp sql ok info %s", sqlStr.c_str()); + } + + ShowChanData(sql); + ret = true; + } + + + + return ret; +} + +bool DataProcThread::handleDiData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql) +{ + bool ret = false; + QSqlQuery query(db); + SFesFwDi *pFwDi; + int yxbit; + auto fmtTime=getFormatTime(); + int errorTime = 0; + for (int diPoint = 0; diPoint < m_ptrCFesRtu->m_MaxFwDiPoints; diPoint++) + { + pFwDi = m_ptrCFesRtu->m_pFwDi + diPoint; + //bool divalNormalFlag = 1; + if((pFwDi->Status & CN_FesValueUpdate) != CN_FesValueUpdate) + { + //LOGDEBUG("DataProcThread data value[%d] status [%d]",pFwDi->Value, pFwDi->Status); + continue; + //divalNormalFlag = 0; + } + std::string tagname = pFwDi->PointDesc; + yxbit = pFwDi->Value & 0x01; + + QString tableName=QString::fromStdString(m_AppData.table_name); + QString tagName=QString::fromStdString(tagname); + + //sql更新 + auto sql=QString(templateSql).arg(tableName).arg(tagName).arg(fmtTime).arg(yxbit); + std::string sqlStr = sql.toStdString(); + if(!query.exec(sql)) + { + + LOGERROR("DataProcThread.cpp sql faild info %s", sqlStr.c_str()); + if(errorTime > 5) + { + ret = true; + break; + } + errorTime++; + continue; + } + else + { + LOGDEBUG("DataProcThread.cpp sql ok info %s", sqlStr.c_str()); + } + + ShowChanData(sql); + ret = true; + } + + return ret; + +} + +bool DataProcThread::handleAccData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql) +{ + bool ret = false; + QSqlQuery query(db); + double fvalue; + SFesFwAcc *pFwAcc; + auto fmtTime=getFormatTime(); + int errorTime = 0; + for (int accPoint = 0; accPoint < ptrRtu->m_MaxFwAccPoints; accPoint++) + { + pFwAcc = m_ptrCFesRtu->m_pFwAcc + accPoint; + // 判断点值是否正常 + //bool accvalNormalFlag = 1; + if((pFwAcc->Status & CN_FesValueUpdate) != CN_FesValueUpdate) + { + //LOGDEBUG("DataProcThread data value[%d] status [%d]",pFwAcc->Value, pFwAcc->Status); + return false; + //accvalNormalFlag = 0; + } + std::string tagname = pFwAcc->PointDesc; + fvalue = pFwAcc->Value*pFwAcc->Coeff + pFwAcc->Base; + QString fmtVal=formatToPrecision(fvalue); + QString tableName=QString::fromStdString(m_AppData.table_name); + double value=fmtVal.toDouble(); + QString tagName=QString::fromStdString(tagname); + + //sql更新 + auto sql=QString(templateSql).arg(tableName).arg(tagName).arg(fmtTime).arg(value); + std::string sqlStr = sql.toStdString(); + if(!query.exec(sql)) + { + LOGERROR("DataProcThread.cpp sql faild info %s", sqlStr.c_str()); + if(errorTime > 5) + { + ret = true; + break; + } + errorTime++; + continue; + } + else + { + LOGDEBUG("DataProcThread.cpp sql ok info %s", sqlStr.c_str()); + } + + ShowChanData(sql); + ret = true; + } + + return ret; +} + + +bool DataProcThread::handleMixData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql) +{ + bool ret = false; + QSqlQuery query(db); + double fvalue; + SFesFwMi *pFwMi; + auto fmtTime=getFormatTime(); + int errorTime = 0; + for (int miPoint = 0; miPoint < ptrRtu->m_MaxFwMiPoints; miPoint++) + { + pFwMi = m_ptrCFesRtu->m_pFwMi + miPoint; + //bool mivalNormalFlag = 1; + if((pFwMi->Status & CN_FesValueUpdate) != CN_FesValueUpdate) + { + //LOGDEBUG("DataProcThread data value[%d] status [%d]",pFwMi->Value, pFwMi->Status); + continue; + //mivalNormalFlag = 0; + } + std::string tagname = pFwMi->PointDesc; + fvalue = pFwMi->Value*pFwMi->Coeff + pFwMi->Base; + QString fmtVal=formatToPrecision(fvalue); + QString tableName=QString::fromStdString(m_AppData.table_name); + double value=fmtVal.toDouble(); + QString tagName=QString::fromStdString(tagname); + + //sql更新 + auto sql=QString(templateSql).arg(tableName).arg(tagName).arg(fmtTime).arg(value); + std::string sqlStr = sql.toStdString(); + if(!query.exec(sql)) + { + + LOGERROR("DataProcThread.cpp sql faild info %s", sqlStr.c_str()); + if(errorTime > 5) + { + ret = true; + break; + } + errorTime++; + continue; + } + else + { + LOGDEBUG("DataProcThread.cpp sql ok info %s", sqlStr.c_str()); + } + + ShowChanData(sql); + + ret = true; + + } + + return ret; +} + +QString DataProcThread::formatToPrecision(double dvalue) +{ + std::ostringstream oss;//保留3位小数 + oss << std::fixed << std::setprecision(3) << dvalue; + std::string result = oss.str(); + size_t found = result.find_last_not_of('0');//去掉多余的0和点 + if (found != std::string::npos) + { + if (result[found] == '.') + result.erase(found); + else + result.erase(found + 1); + } + + return QString::fromStdString(result); +} + +void DataProcThread::ShowChanData(QString &sendData) +{ + //将sql传给通道报文显示 + std::string sqlStr = sendData.toStdString(); + const char* host = m_ptrCFesChan->m_Param.NetRoute[0].NetDesc; + + // 使用 snprintf 来计算格式化后字符串的大小(不包括 null 终止符) + size_t neededSize = snprintf(nullptr, 0, "sqlserver host: %s, sql: %s", host, sqlStr.c_str()) + 1; // +1 for null terminator + + // 为字符串分配合适大小的缓冲区 + char* slog = new char[neededSize]; // 动态分配缓冲区 + + // 使用 sprintf_s 填充数据 + sprintf_s(slog, neededSize, "sqlserver host: %s, sql: %s", host, sqlStr.c_str()); + + ShowChanStrData(m_ptrCFesChan->m_Param.ChanNo, slog, CN_SFesSimComFrameTypeSend); + + // 使用完后释放动态分配的内存 + delete[] slog; +} + +QString DataProcThread::getFormatTime() +{ + // 获取当前时间 + auto now = std::chrono::system_clock::now(); + std::time_t now_c = std::chrono::system_clock::to_time_t(now); + + // 转换为 tm 结构,便于操作时间字段 + std::tm* currentTime = std::localtime(&now_c); + + // 将分钟和秒归零 + currentTime->tm_min = 0; + currentTime->tm_sec = 0; + currentTime->tm_sec = currentTime->tm_sec+m_AppData.second_offset; + auto timeValue=std::mktime(currentTime); + + + std::ostringstream oss; + oss << std::put_time(std::localtime(&timeValue), "%Y-%m-%d %H:%M:%S"); + std::string res=oss.str(); + + return QString::fromStdString(res); +} + diff --git a/product/src/fes/protocol/sqlserver_s/DataProcThread.h b/product/src/fes/protocol/sqlserver_s/DataProcThread.h new file mode 100644 index 00000000..fb46fff3 --- /dev/null +++ b/product/src/fes/protocol/sqlserver_s/DataProcThread.h @@ -0,0 +1,80 @@ +/* + @file DataProcThread.h + @date 2022-01-05 +*/ +#pragma once + +#include "FesDef.h" +#include "FesBase.h" +#include "ProtocolBase.h" +#include +#include +#include +#include + +using namespace kbd_public; + +typedef struct{ + int RtuNo; //rtu号 + std::string db_name; //数据库名 + std::string table_name; //表名 + std::string user_name; //用户名 + std::string password; //密码 + int interval_time; //间隔多久写入一次 (秒) + int second_offset; +}SServerAppConfigParam; + +class DataProcThread : public CTimerThreadBase,CProtocolBase +{ +public: + DataProcThread(CFesBase *ptrCFesBase, + CFesChanPtr ptrCFesChan, + const vector vecAppParam); + virtual ~DataProcThread(); + + /* + @brief 执行execute函数前的处理 + */ + virtual int beforeExecute(); + /* + @brief 业务处理函数,必须继承实现自己的业务逻辑 + */ + virtual void execute(); + + virtual void beforeQuit(); + + CFesBase* m_ptrCFesBase; + CFesChanPtr m_ptrCFesChan; //主通道数据区。如果存在备通道,每次发送接收数据时需要得到当前使用的通道数据 + CFesRtuPtr m_ptrCFesRtu; //当前使用RTU数据区, 每个通道对应一个RTU数据,所以不需要轮询处理。 + CFesChanPtr m_ptrCurrentChan; //当前使用通道数据区。如果存在备通,每次发送接收数据时需要得到当前使用的通道数据 + SServerAppConfigParam m_AppData; //内部应用数据结构 + QMap m_mapLastUpateTime; // + +private: + int m_timerCount; + int m_timerCountReset; + + int InitConfigParam(); + + void TimerProcess(); + + void SendSoeDataFrame(); + + + QSqlDatabase getSqlServerClient(SServerAppConfigParam& para); + + int handlData(); + + bool handleAiData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql); + bool handleDiData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql); + bool handleMixData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql); + bool handleAccData(CFesRtuPtr ptrRtu,QSqlDatabase& db,QString& templateSql); + + QString formatToPrecision(double dvalue); + void ShowChanData(QString& sendData); + QString getFormatTime(); + +}; + +typedef boost::shared_ptr DataProcThreadPtr; + diff --git a/product/src/fes/protocol/sqlserver_s/SqlServer.cpp b/product/src/fes/protocol/sqlserver_s/SqlServer.cpp new file mode 100644 index 00000000..202d8a51 --- /dev/null +++ b/product/src/fes/protocol/sqlserver_s/SqlServer.cpp @@ -0,0 +1,339 @@ +/* + @file MdbTcpSer.cpp + @brief MdbTcpSer规约处理主程序 + @author JACKYWU + @date 2019-05-07 + @history + 2020-01-19 thxiao ReadConfigParam()修改了原有的读取方式,不再受RTUNO的限制。 + 2020-02-13 thxiao ReadConfigParam()需要使用m_ptrCFesBase,所以改为SetBaseAddr()处调用 + 2020-02-18 thxiao GetProtocolInfo()通道的本地端口号固定为自定义参数4 + 2020-03-31 thxiao 完善退出不成功问题。 + 2023-02-24 thxiao + 1、改为统一配置文件modbus_tcp_s.xml,以便配置工具可以正常打开。 + 2、双点DI,特殊处理 + + */ +#include "SqlServer.h" +#include "pub_utility_api/CommonConfigParse.h" + +using namespace kbd_public; + +CSqlServer server; + +int EX_SetBaseAddr(void *address) +{ + server.SetBaseAddr(address); + return kbdSuccess; +} + +int EX_SetProperty(int FesStatus) +{ + server.SetProperty(FesStatus); + return kbdSuccess; +} + +int EX_OpenChan(int MainChanNo,int ChanNo,int OpenFlag) +{ + server.OpenChan(MainChanNo,ChanNo,OpenFlag); + return kbdSuccess; +} + +int EX_CloseChan(int MainChanNo,int ChanNo,int CloseFlag) +{ + server.CloseChan(MainChanNo,ChanNo,CloseFlag); + return kbdSuccess; +} + +int EX_ChanTimer(int ChanNo) +{ + server.ChanTimer(ChanNo); + return kbdSuccess; +} + +int EX_ExitSystem(int flag) +{ + LOGDEBUG("CSqlServer EX_ExitSystem() start"); + server.ExitSystem(flag); + LOGDEBUG("CSqlServer EX_ExitSystem() end"); + return kbdSuccess; +} +CSqlServer::CSqlServer() +{ + //ReadConfigParam(); + m_ptrCFesBase = nullptr; + m_ProtocolId = 0; +} + +CSqlServer::~CSqlServer() +{ +} + + +int CSqlServer::SetBaseAddr(void *address) +{ + if (m_ptrCFesBase == NULL) + { + m_ptrCFesBase = (CFesBase *)address; + ReadConfigParam(); + } + return kbdSuccess; +} + +int CSqlServer::SetProperty(int IsMainFes) +{ + if(m_ptrCDataProc) + { + if(IsMainFes != 0) + { + m_ptrCDataProc->resume(); + } + else + { + m_ptrCDataProc->suspend(); + } + + } + + LOGDEBUG("CSqlServer::SetProperty IsMainFes:%d",IsMainFes); + return kbdSuccess; +} + +/** + * @brief CSqlServer::OpenChan 根据OpenFlag,打开通道线程或数据处理线程。 + * @param MainChanNo 主通道号 + * @param ChanNo 当前通道号 + * @param OpenFlag 打开标志 1:打开通道线程 2:打开数据处理线程 3:打开通道线程和数据处理线程 + * @return 成功:kbdSuccess 失败:kbdFailed + */ +int CSqlServer::OpenChan(int MainChanNo,int ChanNo,int OpenFlag) +{ + CFesChanPtr ptrMainFesChan; + CFesChanPtr ptrFesChan; + + if (m_ptrCFesBase == NULL) + return kbdFailed; + + if((ptrMainFesChan = GetChanDataByChanNo(MainChanNo))==NULL) + return kbdFailed; + if((ptrFesChan = GetChanDataByChanNo(ChanNo))==NULL) + return kbdFailed; + + if ((OpenFlag == CN_FesChanThread_Flag) || (OpenFlag == CN_FesChanAndDataThread_Flag)) + { + switch (ptrFesChan->m_Param.CommType) + { + case CN_FesTcpClient: + case CN_FesTcpServer: + break; + default: + LOGERROR("CSqlServer EX_OpenChan() ChanNo:%d CommType=%d is not TCP SERVER/Client!", ptrFesChan->m_Param.ChanNo, ptrFesChan->m_Param.CommType); + return kbdFailed; + } + } + + if(m_ptrCDataProc != nullptr) + { + + } + + if((OpenFlag==CN_FesDataThread_Flag)||(OpenFlag==CN_FesChanAndDataThread_Flag)) + { + if (ptrMainFesChan->m_DataThreadRun == CN_FesStopFlag) + { + //open chan thread + m_ptrCDataProc = boost::make_shared(m_ptrCFesBase,ptrMainFesChan,m_vecAppParam); + if (m_ptrCDataProc == NULL) + { + LOGERROR("CSqlServer EX_OpenChan() ChanNo:%d create DataProcThread error!",ptrFesChan->m_Param.ChanNo); + return kbdFailed; + } + LOGDEBUG("CSqlServer EX_OpenChan() ChanNo:%d create DataProcThread ok!", ptrFesChan->m_Param.ChanNo); + m_ptrCDataProc->resume(); //start Data THREAD + } + } + return kbdSuccess; +} + +/** + * @brief CSqlServer::CloseChan 根据OpenFlag,关闭通道线程或数据处理线程。 + * @param MainChanNo 主通道号 + * @param ChanNo 当前通道号 + * @param OpenFlag 关闭标志 1:关闭通道线程 2:关闭数据处理线程 3:关闭通道线程和数据处理线程 + * @return 成功:kbdSuccess 失败:kbdFailed + */ +int CSqlServer::CloseChan(int MainChanNo,int ChanNo,int CloseFlag) +{ + CFesChanPtr ptrMainFesChan; + CFesChanPtr ptrFesChan; + + if (m_ptrCFesBase == NULL) + return kbdFailed; + + if((ptrMainFesChan = GetChanDataByChanNo(MainChanNo))==NULL) + return kbdFailed; + if((ptrFesChan = GetChanDataByChanNo(ChanNo))==NULL) + return kbdFailed; + + LOGDEBUG("CSqlServer::CloseChan MainChanNo=%d chanNo=%d m_ComThreadRun=%d m_DataThreadRun=%d", + MainChanNo, + ChanNo, + ptrFesChan->m_ComThreadRun, + ptrMainFesChan->m_DataThreadRun); + + if((CloseFlag==CN_FesDataThread_Flag)||(CloseFlag==CN_FesChanAndDataThread_Flag)) + { + if (ptrMainFesChan->m_DataThreadRun == CN_FesRunFlag) + { + m_ptrCDataProc->suspend(); + m_ptrCDataProc->quit(); + m_ptrCDataProc =NULL; + } + } + return kbdSuccess; +} + +/** + * @brief CSqlServer::ChanTimer + * 通道定时器,主通道会定时调用 + * @param MainChanNo 主通道号 + * @return + */ +int CSqlServer::ChanTimer(int MainChanNo) +{ + boost::ignore_unused_variable_warning(MainChanNo); + + //把命令缓冲时间间隔到的命放到发送命令缓冲区 + return kbdSuccess; +} + +int CSqlServer::ExitSystem(int flag) +{ + boost::ignore_unused_variable_warning(flag); + + if(m_ptrCDataProc != NULL) + { + m_ptrCDataProc->suspend(); + m_ptrCDataProc->quit(); + m_ptrCDataProc = NULL; + } + + return kbdSuccess; +} + +/** + * @brief CSqlServer::ReadConfigParam + * 读取MdbTcpSer配置文件 + * @return 成功返回kbdSuccess,失败返回kbdFailed + */ +int CSqlServer::ReadConfigParam() +{ + CCommonConfigParse config; + char strRtuNo[48]; + SServerAppConfigParam param; + int items,i,j; + CFesChanPtr ptrChan; //CHAN数据区 + CFesRtuPtr ptrRTU; + std::string strvalue; + int ivalue; + + if (m_ptrCFesBase == NULL) + return kbdFailed; + + m_ProtocolId = m_ptrCFesBase->GetProtocolID((char*)"sqlserver_s"); + if (m_ProtocolId == -1) + { + LOGDEBUG("ReadConfigParam ProtoclID error"); + return kbdFailed; + } + LOGINFO("sqlserver_s ProtoclID=%d", m_ProtocolId); + + if (config.load("../../data/fes/", "sqlserver_s.xml") == kbdFailed) + { + LOGDEBUG("sqlserver_s load sqlserver_s.xml error"); + return kbdSuccess; + } + LOGDEBUG("sqlserver_s load sqlserver_s.xml ok"); + + for (i = 0; i < m_ptrCFesBase->m_vectCFesChanPtr.size(); i++) + { + ptrChan = m_ptrCFesBase->m_vectCFesChanPtr[i]; + if ((ptrChan->m_Param.Used == 1) && (m_ProtocolId == ptrChan->m_Param.ProtocolId)) + { + //found RTU + for (j = 0; j < m_ptrCFesBase->m_vectCFesRtuPtr.size(); j++) + { + ptrRTU = m_ptrCFesBase->m_vectCFesRtuPtr[j]; + if (ptrRTU->m_Param.Used && (ptrRTU->m_Param.ChanNo == ptrChan->m_Param.ChanNo)) + { + memset(&strRtuNo[0], 0, sizeof(strRtuNo)); + sprintf(strRtuNo, "RTU%d", ptrRTU->m_Param.RtuNo); + + param.RtuNo = ptrRTU->m_Param.RtuNo; + items = 0; + param.db_name = "iscs_db"; + strvalue.clear(); + if (config.getStringValue(strRtuNo, "db_name", strvalue) == kbdSuccess) + { + param.db_name = strvalue; + } + items++; + + param.interval_time = 3000; + if (config.getIntValue(strRtuNo, "interval_time", ivalue) == kbdSuccess) + { + param.interval_time = ivalue; + items++; + } + items++; + + param.table_name = "HistoryGenerallyVariable"; + strvalue.clear(); + if (config.getStringValue(strRtuNo, "table_name", strvalue) == kbdSuccess) + { + param.table_name = strvalue; + } + items++; + + + + param.password="relyez@2019"; + strvalue.clear(); + if (config.getStringValue(strRtuNo, "password", strvalue) == kbdSuccess) + { + param.password = strvalue; + } + items++; + + + param.user_name="sa"; + strvalue.clear(); + if (config.getStringValue(strRtuNo, "user_name", strvalue) == kbdSuccess) + { + param.user_name = strvalue; + } + items++; + + param.second_offset=0; + if (config.getIntValue(strRtuNo, "second_offset", ivalue) == kbdSuccess) + { + param.second_offset = ivalue; + } + items++; + + + + if (items > 0)//对应的RTU有配置项 + { + m_vecAppParam.push_back(param); + } + } + } + } + } + return kbdSuccess; + +} + + + + diff --git a/product/src/fes/protocol/sqlserver_s/SqlServer.h b/product/src/fes/protocol/sqlserver_s/SqlServer.h new file mode 100644 index 00000000..31730d04 --- /dev/null +++ b/product/src/fes/protocol/sqlserver_s/SqlServer.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include "Export.h" +#include "FesDef.h" +#include "FesBase.h" +#include "ProtocolBase.h" +#include "DataProcThread.h" + +extern "C" PROTOCOLBASE_API int EX_SetBaseAddr(void *Address); +extern "C" PROTOCOLBASE_API int EX_SetProperty(int FesStatus); +extern "C" PROTOCOLBASE_API int EX_OpenChan(int MainChanNo,int ChanNo,int OpenFlag); +extern "C" PROTOCOLBASE_API int EX_CloseChan(int MainChanNo,int ChanNo,int CloseFlag); +extern "C" PROTOCOLBASE_API int EX_ChanTimer(int MainChanNo); +extern "C" PROTOCOLBASE_API int EX_ExitSystem(int flag); + +class PROTOCOLBASE_API CSqlServer : public CProtocolBase +{ +public: + CSqlServer(); + ~CSqlServer(); + + CFesBase* m_ptrCFesBase; //CProtocolBase类中定义 + int SetBaseAddr(void *address); + int SetProperty(int IsMainFes); + int OpenChan(int MainChanNo,int ChanNo,int OpenFlag); + int CloseChan(int MainChanNo,int ChanNo,int CloseFlag); + int ChanTimer(int MainChanNo); + int ExitSystem(int flag); + int ReadConfigParam(); +private: + int m_ProtocolId; + + vector m_vecAppParam; + DataProcThreadPtr m_ptrCDataProc; +}; + diff --git a/product/src/fes/protocol/sqlserver_s/sqlserver_s.pro b/product/src/fes/protocol/sqlserver_s/sqlserver_s.pro new file mode 100644 index 00000000..33eb4dff --- /dev/null +++ b/product/src/fes/protocol/sqlserver_s/sqlserver_s.pro @@ -0,0 +1,33 @@ +QT += core sql + + + +TARGET = sqlserver_s +TEMPLATE = lib + +SOURCES += \ + DataProcThread.cpp \ + SqlServer.cpp + +HEADERS += \ + DataProcThread.h \ + SqlServer.h + +INCLUDEPATH += ../../include/ + +LIBS += -lboost_system -lboost_thread -lboost_locale -lboost_chrono -lboost_date_time +LIBS += -lpub_utility_api -lpub_logger_api -llog4cplus -lprotocolbase +LIBS += -lprotobuf -lboost_locale -lboost_regex + + +DEFINES += PROTOCOLBASE_API_EXPORTS +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") +} +