416 lines
18 KiB
C++
416 lines
18 KiB
C++
#include "DownloadTimetable.h"
|
||
#include "pub_logger_api/logger.h"
|
||
#include "pub_utility_api/I18N.h"
|
||
#include "pub_utility_api/TimeUtil.h"
|
||
#include "pub_utility_api/CharUtil.h"
|
||
#include "common/MessageChannel.h"
|
||
#include "ParamMng.h"
|
||
|
||
using namespace std;
|
||
using namespace iot_public;
|
||
using namespace kbd_app;
|
||
// using namespace iot_net;
|
||
// using namespace iot_dbms;
|
||
|
||
kbd_app::CDownloadTimetable::CDownloadTimetable(const iot_public::SRunAppInfo &stRunAppInfo,
|
||
const CParamMngPtr &ptrParamMng,
|
||
const CTimetableMsgBusMngPtr &ptrMsgMng,
|
||
const CBasicOperationPtr &ptrBasicOpt)
|
||
:m_stRunAppInfo(stRunAppInfo),
|
||
m_ptrParamMng(ptrParamMng),
|
||
m_ptrMsgMng(ptrMsgMng),
|
||
m_ptrBasicOpt(ptrBasicOpt)
|
||
{
|
||
}
|
||
|
||
kbd_app::CDownloadTimetable::~CDownloadTimetable()
|
||
{
|
||
m_ptrBasicOpt.reset();
|
||
m_ptrMsgMng.reset();
|
||
m_ptrParamMng.reset();
|
||
}
|
||
|
||
/* @brief 处理下载命令 */
|
||
void kbd_app::CDownloadTimetable::handleDownloadCmd(STimetableCmd &stCmd)
|
||
{
|
||
ETimetableCmdState eTemp = ETimetableCmdState_Invalid;
|
||
while (eTemp != stCmd.eState)
|
||
{
|
||
eTemp = stCmd.eState;
|
||
switch (stCmd.eState)
|
||
{
|
||
case ETimetableCmdState_Start:
|
||
case ETimetableCmdState_CheckFlag: //< 检查时间表控制相关标识
|
||
checkFlag(stCmd, ETimetableCmdState_WaitSync, ETimetableCmdState_Complete);
|
||
break;
|
||
case ETimetableCmdState_WaitSync: //< 等待在线修改的内容已经同步到内存表中
|
||
waitSyncTimetableInfo(stCmd, ETimetableCmdState_SendCustomCmdMsg, ETimetableCmdState_Complete);
|
||
break;
|
||
case ETimetableCmdState_SendCustomCmdMsg:
|
||
sendDownloadCmd(stCmd, ETimetableCmdState_WaitCustomRep, ETimetableCmdState_Complete);
|
||
break;
|
||
case ETimetableCmdState_WaitCustomRep:
|
||
waitDownloadResponse(stCmd, ETimetableCmdState_SetDCFFlag, ETimetableCmdState_Complete);
|
||
break;
|
||
case ETimetableCmdState_SetDCFFlag: //< 设置下载相关标志位
|
||
setDownloadFlag(stCmd, ETimetableCmdState_VerifyVesion, ETimetableCmdState_Complete);
|
||
break;
|
||
// case ETimetableCmdState_WaitDCFRep:
|
||
// waitDownloadFlagRep(stCmd, ETimetableCmdState_VerifyVesion, ETimetableCmdState_Complete);
|
||
// break;
|
||
case ETimetableCmdState_VerifyVesion:
|
||
verifyVersion(stCmd, ETimetableCmdState_Complete, ETimetableCmdState_Complete);
|
||
break;
|
||
case ETimetableCmdState_Complete:
|
||
downloadCompleted(stCmd);
|
||
break;
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* @brief 检查DCF、URF、RRF标识 */
|
||
void kbd_app::CDownloadTimetable::checkFlag(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
string strErrMsg;
|
||
if (kbdSuccess == m_ptrBasicOpt->checkFlag(stCmd, strErrMsg))
|
||
{
|
||
stCmd.setResult(true, strErrMsg, eSuccessState);
|
||
}
|
||
else
|
||
{
|
||
stCmd.setResult(false, strErrMsg, eFailState);
|
||
}
|
||
}
|
||
|
||
/* @brief 等待关系库中的配置同步到内存库 */
|
||
void kbd_app::CDownloadTimetable::waitSyncTimetableInfo(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
/* @brief 仅手动下载命令需要检查时间表是否已经更新到内存表中 */
|
||
if (stCmd.eCmdType != ETimetableCmdType_ManualDownload)
|
||
{
|
||
stCmd.setResult(true, "", eSuccessState);
|
||
return;
|
||
}
|
||
|
||
int64 lCurTimeMsec = getUTCTimeMsec();
|
||
if (lCurTimeMsec - stCmd.lCmdBeginTimeMsec > stCmd.nTimeoutMsec)
|
||
{
|
||
LOGERROR("等待时间表同步超时.LocationId=[%d],TimetableId=[%d]", stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(false, I18N("时间表下载命令执行超时"), eFailState);
|
||
return;
|
||
}
|
||
|
||
int nTimetableVersion = m_ptrBasicOpt->getTimetableVersion(stCmd.nLocationId, stCmd.nTimetableId);
|
||
if (nTimetableVersion != CN_InvalidTimetableVersion &&
|
||
nTimetableVersion == stCmd.nTimetableVersion)
|
||
{
|
||
LOGINFO("等待在线修改时间表信息成功");
|
||
stCmd.setResult(true, "", eSuccessState);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* @brief 发送下载命令消息 */
|
||
void kbd_app::CDownloadTimetable::sendDownloadCmd(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
stCmd.lCurCmdTimeMsec = getUTCTimeMsec();
|
||
string strMsg;
|
||
if (!makeDownloadMsg(stCmd, strMsg))
|
||
{
|
||
stCmd.setResult(false, I18N("生成控制命令失败"), eFailState);
|
||
return;
|
||
}
|
||
|
||
if (m_ptrMsgMng->sendMsgToMsgBus(strMsg, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_COMMON_DOWN, CN_InvalidDomainId, m_stRunAppInfo.strLocalNodeName))
|
||
{
|
||
stCmd.setResult(true, I18N("发送时间表下载命令成功"), eSuccessState);
|
||
LOGINFO("发送下载命令成功.AppId=[%d],CH=[%d],MT=[%d],CmdType=[%d],LocationId=[%d],TimetableId=[%d]",
|
||
m_stRunAppInfo.nAppId, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_COMMON_DOWN,
|
||
stCmd.eCmdType, stCmd.nLocationId, stCmd.nTimetableId);
|
||
}
|
||
else
|
||
{
|
||
stCmd.setResult(false, I18N("发送时间表下载命令失败"), eFailState);
|
||
LOGERROR("发送下载命令失败.AppId=[%d],CH=[%d],MT=[%d],CmdType=[%d],LocationId=[%d],TimetableId=[%d]",
|
||
m_stRunAppInfo.nAppId, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_COMMON_DOWN,
|
||
stCmd.eCmdType, stCmd.nLocationId, stCmd.nTimetableId);
|
||
}
|
||
}
|
||
|
||
/* @brief 生成下载命令报文 */
|
||
bool kbd_app::CDownloadTimetable::makeDownloadMsg(const STimetableCmd &stCmd, std::string &strMsg)
|
||
{
|
||
vector<STableTimetableInfo> vecInfo;
|
||
if (kbdSuccess != m_ptrBasicOpt->getTimetableDetail(stCmd.nLocationId, stCmd.nTimetableId, vecInfo)
|
||
|| vecInfo.empty())
|
||
{
|
||
LOGERROR("获取时间表信息失败.LocationId=[%d],TimetableId=[%d]", stCmd.nLocationId, stCmd.nTimetableId);
|
||
return false;
|
||
}
|
||
|
||
STableCtrlParam stCtrlParam;
|
||
if (!m_ptrParamMng->getCtrlParamByLocationId(stCmd.nLocationId, stCtrlParam))
|
||
{
|
||
LOGERROR("获取控制参数信息失败。LocationId=[%d]", stCmd.nLocationId);
|
||
return false; //< 命令填充到缓冲区时已经进行了判断,必然存在此车站的配置,所以正常不会进入此分支
|
||
}
|
||
|
||
SOptCustCtrlRequest stCustomCmd;
|
||
stCustomCmd.stHead.strSrcTag = CN_ProcName_TimetableServer;
|
||
stCustomCmd.stHead.nSrcDomainID = m_stRunAppInfo.nDomainId;
|
||
stCustomCmd.stHead.nDstDomainID = m_stRunAppInfo.nDomainId;
|
||
stCustomCmd.stHead.nAppID = m_stRunAppInfo.nAppId;
|
||
stCustomCmd.stHead.strHostName = m_stRunAppInfo.strLocalNodeName;
|
||
stCustomCmd.stHead.strInstName = CN_ProcName_TimetableServer;
|
||
stCustomCmd.stHead.strCommName = m_ptrMsgMng->getCommunicatorName();
|
||
stCustomCmd.stHead.nUserID = stCmd.nUserId;
|
||
stCustomCmd.stHead.nUserGroupID = stCmd.nUserGrpId;
|
||
stCustomCmd.stHead.nOptTime = stCmd.lCurCmdTimeMsec;
|
||
stCustomCmd.strKeyIdTag = stCtrlParam.szCtrlKeyIdTag;
|
||
|
||
SOptCustCtrlQueue stKV;
|
||
stKV.strKeyName = KEY_CMD_TYPE;
|
||
stKV.strKeyValue = CMD_TYPE_DOWNLOAD;
|
||
stCustomCmd.vecOptCustCtrlQueue.push_back(stKV);
|
||
|
||
stKV.strKeyName = KEY_TIMETABLE_ID;
|
||
stKV.strKeyValue = IntToString(stCmd.nTimetableId);
|
||
stCustomCmd.vecOptCustCtrlQueue.push_back(stKV);
|
||
|
||
stKV.strKeyName = KEY_TIMETABLE_VERSION;
|
||
stKV.strKeyValue = IntToString(stCmd.nTimetableVersion);
|
||
stCustomCmd.vecOptCustCtrlQueue.push_back(stKV);
|
||
|
||
for (size_t i = 0; i < vecInfo.size(); ++i)
|
||
{
|
||
STableTimetableInfo &stInfo = vecInfo[i];
|
||
stKV.strKeyName = KEY_MODE_BEGIN_TIME;
|
||
stKV.strKeyValue = stInfo.stKey.szBeginTime;
|
||
stCustomCmd.vecOptCustCtrlQueue.push_back(stKV);
|
||
|
||
STableModeDef stModeInfo;
|
||
if (kbdSuccess != m_ptrBasicOpt->getModeInfo(stInfo.stKey.nLocationId, stInfo.nCraftId, stInfo.nModeId, stModeInfo))
|
||
{
|
||
LOGERROR("获取模式号失败.LocationId=[%d],CraftId=[%d],ModeId=[%d]",
|
||
stInfo.stKey.nLocationId, stInfo.nCraftId, stInfo.nModeId);
|
||
return false;
|
||
}
|
||
|
||
stKV.strKeyName = KEY_MODE_NO;
|
||
stKV.strKeyValue = IntToString(stModeInfo.stKey.nModeNo);
|
||
stCustomCmd.vecOptCustCtrlQueue.push_back(stKV);
|
||
}
|
||
|
||
COptCustCtrlRequest objReq;
|
||
strMsg = objReq.generate(stCustomCmd);
|
||
if (strMsg.empty())
|
||
{
|
||
LOGERROR("生成控制命令失败");
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
|
||
/* @brief 检查下载命令反馈结果 */
|
||
void kbd_app::CDownloadTimetable::waitDownloadResponse(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
int64 lCurTimeMsec = getUTCTimeMsec();
|
||
if (lCurTimeMsec - stCmd.lCmdBeginTimeMsec > stCmd.nTimeoutMsec)
|
||
{
|
||
LOGERROR("时间表下载命令[%d]执行超时.LocationId=[%d],TimetableId=[%d]", stCmd.eCmdType,
|
||
stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(false, I18N("时间表下载命令执行超时"), eFailState);
|
||
return;
|
||
}
|
||
|
||
STableCtrlParam stCtrlParam;
|
||
if (!m_ptrParamMng->getCtrlParamByLocationId(stCmd.nLocationId, stCtrlParam))
|
||
{
|
||
LOGERROR("获取控制参数信息失败。LocationId=[%d]", stCmd.nLocationId);
|
||
stCmd.setResult(false, I18N("获取控制参数信息失败"), eFailState);
|
||
return; //< 命令填充到缓冲区时已经进行了判断,必然存在此车站的配置,所以正常不会进入此分支
|
||
}
|
||
|
||
//检查反馈,是否执行成功
|
||
string strKeyIdTag = stCtrlParam.szCtrlKeyIdTag; //< 开始已经判断,本车站参数配置必然存在
|
||
STimetableCmdKey stKey(strKeyIdTag, stCmd.lCurCmdTimeMsec);
|
||
|
||
SOptCustCtrlReply stRep;
|
||
if (m_ptrParamMng->getCustomRepMsgByKey(stKey, stRep))
|
||
{
|
||
if (stRep.stHead.nIsSuccess == 1)
|
||
{
|
||
LOGINFO("接收到下载命令[%d]执行成功反馈.LocationId=[%d],TimetableId=[%d]",
|
||
stCmd.eCmdType, stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(true, "", eSuccessState);
|
||
}
|
||
else
|
||
{
|
||
LOGERROR("接收到下载命令[%d]执行失败反馈.LocationId=[%d],TimetableId=[%d],Error=[%s]",
|
||
stCmd.eCmdType, stCmd.nLocationId, stCmd.nTimetableId, stRep.stHead.strResultStr.c_str());
|
||
stCmd.setResult(false, stRep.stHead.strResultStr, eFailState);
|
||
}
|
||
}
|
||
}
|
||
|
||
/* @brief 设置下载完成标识DCF */
|
||
void kbd_app::CDownloadTimetable::setDownloadFlag(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
stCmd.lCurCmdTimeMsec = getUTCTimeMsec();
|
||
|
||
STableCtrlParam stCtrlParam;
|
||
if (!m_ptrParamMng->getCtrlParamByLocationId(stCmd.nLocationId, stCtrlParam))
|
||
{
|
||
LOGERROR("获取控制参数信息失败。LocationId=[%d]", stCmd.nLocationId);
|
||
stCmd.setResult(false, I18N("获取控制参数信息失败"), eFailState);
|
||
return; //< 命令填充到缓冲区时已经进行了判断,必然存在此车站的配置,所以正常不会进入此分支
|
||
}
|
||
|
||
SOptCtrlRequest stReq;
|
||
stReq.stHead.strSrcTag = CN_ProcName_TimetableServer;
|
||
stReq.stHead.nSrcDomainID = m_stRunAppInfo.nDomainId;
|
||
stReq.stHead.nDstDomainID = m_stRunAppInfo.nDomainId;
|
||
stReq.stHead.nAppID = m_stRunAppInfo.nAppId;
|
||
stReq.stHead.strHostName = m_stRunAppInfo.strLocalNodeName;
|
||
stReq.stHead.strInstName = CN_ProcName_TimetableServer;
|
||
stReq.stHead.strCommName = m_ptrMsgMng->getCommunicatorName();
|
||
stReq.stHead.nUserID = stCmd.nUserId;
|
||
stReq.stHead.nUserGroupID = stCmd.nUserGrpId;
|
||
stReq.stHead.nOptTime = stCmd.lCurCmdTimeMsec;
|
||
|
||
SOptCtrlReqQueue stCtrlReq;
|
||
stCtrlReq.strKeyIdTag = stCtrlParam.szDCFTag;
|
||
stCtrlReq.dTargetValue = 1;
|
||
stCtrlReq.bIsDeviceOccupy = true;
|
||
stReq.vecOptCtrlQueue.push_back(stCtrlReq);
|
||
|
||
COptCtrlRequest objGen;
|
||
string strMsg = objGen.generate(stReq);
|
||
if (strMsg.empty())
|
||
{
|
||
LOGERROR("生成控制报文失败。KeyIdTag=[%s]", stCtrlReq.strKeyIdTag.c_str());
|
||
stCmd.setResult(false, I18N("生成控制报文失败"), eFailState);
|
||
return;
|
||
}
|
||
|
||
if (m_ptrMsgMng->sendMsgToMsgBus(strMsg, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_DOWN, CN_InvalidDomainId, m_stRunAppInfo.strLocalNodeName))
|
||
{
|
||
stCmd.setResult(true, I18N("发送时间表下载标志置位命令成功"), eSuccessState);
|
||
LOGINFO("发送时间表下载标志置位命令成功.AppId=[%d],CH=[%d],MT=[%d],CmdType=[%d],LocationId=[%d],TimetableId=[%d],KeyIdTag=[%s]",
|
||
m_stRunAppInfo.nAppId, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_DOWN, stCmd.eCmdType,
|
||
stCmd.nLocationId, stCmd.nTimetableId, stCtrlReq.strKeyIdTag.c_str());
|
||
}
|
||
else
|
||
{
|
||
stCmd.setResult(false, I18N("发送时间表下载标志置位命令失败"), eFailState);
|
||
LOGERROR("发送时间表下载标志置位命令失败.AppId=[%d],CH=[%d],MT=[%d],CmdType=[%d],LocationId=[%d],TimetableId=[%d],KeyIdTag=[%s]",
|
||
m_stRunAppInfo.nAppId, CH_HMI_TO_OPT_OPTCMD_DOWN, MT_OPT_AUTO_CTRL_DOWN, stCmd.eCmdType,
|
||
stCmd.nLocationId, stCmd.nTimetableId, stCtrlReq.strKeyIdTag.c_str());
|
||
}
|
||
|
||
}
|
||
|
||
/* @brief 等待设置下载完成标识DCF的命令反馈 */
|
||
void kbd_app::CDownloadTimetable::waitDownloadFlagRep(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
int64 lCurTimeMsec = getUTCTimeMsec();
|
||
if (lCurTimeMsec - stCmd.lCmdBeginTimeMsec > stCmd.nTimeoutMsec)
|
||
{
|
||
LOGERROR("时间表下载标志置位命令控制超时.LocationId=[%d],TimetableId=[%d]", stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(false, I18N("时间表下载标志置位命令控制超时"), eFailState);
|
||
return;
|
||
}
|
||
|
||
STableCtrlParam stCtrlParam;
|
||
if (!m_ptrParamMng->getCtrlParamByLocationId(stCmd.nLocationId, stCtrlParam))
|
||
{
|
||
LOGERROR("获取控制参数信息失败。LocationId=[%d]", stCmd.nLocationId);
|
||
stCmd.setResult(false, I18N("获取控制参数信息失败"), eFailState);
|
||
return; //< 命令填充到缓冲区时已经进行了判断,必然存在此车站的配置,所以正常不会进入此分支
|
||
}
|
||
|
||
//检查反馈,是否执行成功
|
||
STimetableCmdKey stKey(stCtrlParam.szDCFTag, stCmd.lCurCmdTimeMsec);
|
||
SOptCtrlReply stRep;
|
||
if (m_ptrParamMng->getPntRepMsgByKey(stKey, stRep))
|
||
{
|
||
if (stRep.stHead.nIsSuccess == 1)
|
||
{
|
||
LOGINFO("接收到下载标志置位命令成功反馈.LocationId=[%d],TimetableId=[%d]",
|
||
stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(true, "", eSuccessState);
|
||
}
|
||
else
|
||
{
|
||
LOGERROR("接收到下载标志置位命令失败反馈.LocationId=[%d],TimetableId=[%d],Error=[%s]",
|
||
stCmd.nLocationId, stCmd.nTimetableId, stRep.stHead.strResultStr.c_str());
|
||
stCmd.setResult(false, I18N("时间表下载标志置位失败"), eFailState);
|
||
}
|
||
}
|
||
}
|
||
|
||
void kbd_app::CDownloadTimetable::verifyVersion(STimetableCmd &stCmd,
|
||
const ETimetableCmdState eSuccessState,
|
||
const ETimetableCmdState eFailState)
|
||
{
|
||
int64 lCurTimeMsec = getUTCTimeMsec();
|
||
if (lCurTimeMsec - stCmd.lCmdBeginTimeMsec > stCmd.nTimeoutMsec)
|
||
{
|
||
LOGERROR("等待时间表最新的时间表ID和Version超时.预期:LocationId=[%d],TimetableId=[%d],TimetableVersion=[%d]",
|
||
stCmd.nLocationId, stCmd.nTimetableId, stCmd.nTimetableVersion);
|
||
stCmd.setResult(false, I18N("时间表下载校验超时"), eFailState);
|
||
return;
|
||
}
|
||
|
||
//检查正在运行的时间表ID和版本号,是否跟下载的一致
|
||
int nTimetableId = CN_InvalidTimetableId;
|
||
int nTimetableVersion = CN_InvalidTimetableVersion;
|
||
if (!m_ptrBasicOpt->getRunTimetableIdAndVersion(stCmd.nLocationId, nTimetableId, nTimetableVersion))
|
||
{
|
||
//LOGERROR("获取当前正在运行的时间表ID和版本号失败");
|
||
//获取失败,继续重试,靠超时失败
|
||
return;
|
||
}
|
||
|
||
if (nTimetableId == stCmd.nTimetableId && nTimetableVersion == stCmd.nTimetableVersion)
|
||
{
|
||
LOGINFO("时间表下载成功.LocationId=[%d],TimetableId=[%d]", stCmd.nLocationId, stCmd.nTimetableId);
|
||
stCmd.setResult(true, I18N("时间表下载成功"), eSuccessState);
|
||
return;
|
||
}
|
||
}
|
||
|
||
/* @brief 下载命令完成后的处理 */
|
||
void kbd_app::CDownloadTimetable::downloadCompleted(STimetableCmd &stCmd)
|
||
{
|
||
//TODO:产生事件
|
||
if (stCmd.bIsSuccess)
|
||
{
|
||
LOGINFO("时间表下载成功.LocationId=[%d],TimetableId=[%d],ResultDesc=[%s]",
|
||
stCmd.nLocationId, stCmd.nTimetableId, stCmd.strResultDesc.c_str());
|
||
}
|
||
else
|
||
{
|
||
LOGERROR("时间表下载失败.LocationId=[%d],TimetableId=[%d],ResultDesc=[%s]",
|
||
stCmd.nLocationId, stCmd.nTimetableId, stCmd.strResultDesc.c_str());
|
||
}
|
||
|
||
m_ptrBasicOpt->sendResponse(stCmd);
|
||
}
|