多数据源中间件标准版1.0

IvrFlow.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. #include "StdAfx.h"
  2. #include "IvrFlow.h"
  3. #include "CellBase.h"
  4. #include "FlowTemplate.h"
  5. #include "MsgCenter.h"
  6. #include "NetworkIvr.h"
  7. #include "CellTimer.h"
  8. IMPLEMENT_DYNAMIC(CIvrFlow, CWnd)
  9. CIvrFlow::CIvrFlow(int Id) : m_Id(Id), m_State(IVR_FLOW_STATE_FREE), m_IsHangUp(false), m_IsNetLinkUp(false), m_AssoCallId(0), m_pFlowTemplate(NULL), m_pCurrentCell(NULL)
  10. {
  11. CreateEx(0, AfxRegisterWndClass(CS_GLOBALCLASS), "", 0, 0, 0, 0, 0, 0, 0);
  12. }
  13. CIvrFlow::~CIvrFlow(void)
  14. {
  15. __release();
  16. DestroyWindow();
  17. }
  18. BEGIN_MESSAGE_MAP(CIvrFlow, CWnd)
  19. ON_WM_TIMER()
  20. END_MESSAGE_MAP()
  21. /*****************************************************************
  22. **【函数名称】 __release
  23. **【函数功能】 释放资源
  24. **【参数】
  25. **【返回值】
  26. ****************************************************************/
  27. void CIvrFlow::__release( void )
  28. {
  29. if(m_pCurrentCell != NULL)
  30. __deleteCurrentCell();
  31. m_VarTable.RemoveAll();
  32. }
  33. /*****************************************************************
  34. **【函数名称】 __clearFlow
  35. **【函数功能】 流程结束时对流程进行清理
  36. **【参数】
  37. **【返回值】
  38. ****************************************************************/
  39. void CIvrFlow::__clearFlow( void )
  40. {
  41. m_AssoCallId = 0;
  42. m_IsHangUp = false;
  43. m_State = IVR_FLOW_STATE_FREE;
  44. __release();
  45. CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_STATE_UPDAET, reinterpret_cast<const PARAM>(m_Id));
  46. CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_CELL_UPDATE, reinterpret_cast<const PARAM>(m_Id));
  47. if(m_IsNetLinkUp && m_pFlowTemplate != NULL && m_pFlowTemplate->type() == FLOW_AUTO)
  48. start();
  49. }
  50. /*****************************************************************
  51. **【函数名称】 __onTimerTimeOut
  52. **【函数功能】 流程节点最大执行时间超时处理函数
  53. **【参数】
  54. **【返回值】
  55. ****************************************************************/
  56. void CIvrFlow::__onTimerTimeOut( void )
  57. {
  58. ASSERT(m_pCurrentCell != NULL);
  59. ASSERT(m_pFlowTemplate != NULL);
  60. if(m_pFlowTemplate->type() != FLOW_SUB) // 执行子流程时不上报流程结束
  61. {
  62. CPduEntity cmdFlowEnd(PDU_CMD_IVR_END);
  63. cmdFlowEnd.SetDataInt(1, m_Id);
  64. CNetworkIvr::GetInstance().send(cmdFlowEnd);
  65. }
  66. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{FLow}: 节点[%s]超过最大执行时间, 流程[%d]将被释放"), m_pCurrentCell->name(), m_Id);
  67. __clearFlow();
  68. }
  69. /*****************************************************************
  70. **【函数名称】 __onNextCellNull
  71. **【函数功能】 当下个节点为空的处理
  72. **【参数】
  73. **【返回值】
  74. ****************************************************************/
  75. void CIvrFlow::__onNextCellNull( int NullCellPos )
  76. {
  77. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{FLow}: 查找节点[%d]失败, 流程[%d]将被释放"), NullCellPos, m_Id);
  78. CPduEntity CmdHangUp(PDU_CMD_IVR_HANGUP);
  79. CmdHangUp.SetDataInt(1, m_Id);
  80. CNetworkIvr::GetInstance().send(CmdHangUp);
  81. __clearFlow();
  82. }
  83. /*****************************************************************
  84. **【函数名称】 __deleteCurrentCell
  85. **【函数功能】 删除当前节点
  86. **【参数】
  87. **【返回值】
  88. ****************************************************************/
  89. void CIvrFlow::__deleteCurrentCell( void )
  90. {
  91. ASSERT(m_pCurrentCell != NULL);
  92. if(m_pCurrentCell->maxWaitingTime() > 0)
  93. KillTimer((long)m_pCurrentCell);
  94. delete m_pCurrentCell;
  95. m_pCurrentCell = NULL;
  96. }
  97. /*****************************************************************
  98. **【函数名称】 start
  99. **【函数功能】 开始执行流程
  100. **【参数】 pFlowTemp: 流程模板
  101. **【返回值】 下一个节点编号
  102. ****************************************************************/
  103. int CIvrFlow::start( CFlowTemplate* pFlowTemp /*= NULL*/, int StartPos/* = 1*/ )
  104. {
  105. if(pFlowTemp != NULL)
  106. m_pFlowTemplate = pFlowTemp;
  107. if(m_pFlowTemplate == NULL)
  108. {
  109. ASSERT(FALSE);
  110. return CELL_OP_ERROR;
  111. }
  112. CString CellName = "";
  113. switch(m_pFlowTemplate->type())
  114. {
  115. case FLOW_NORMAL:
  116. case FLOW_SUB:
  117. CellName = CELL_NAME_START;
  118. break;
  119. case FLOW_AUTO:
  120. CellName = CELL_NAME_TIMER;
  121. break;
  122. }
  123. int Pos = m_pFlowTemplate->getCellPos(CellName);
  124. if(Pos < 1)
  125. {
  126. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 执行流程[%d]时未找到起始节点, Template = %s"), m_Id, m_pFlowTemplate->name());
  127. return CELL_OP_ERROR;
  128. }
  129. Pos = (StartPos == 1) ? Pos : StartPos;
  130. m_State = IVR_FLOW_STATE_RUN;
  131. CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_STATE_UPDAET, reinterpret_cast<const PARAM>(m_Id));
  132. // 如果是自动流程,但是还未连接至CTI则等待,直到连至CTI后执行
  133. if(m_pFlowTemplate->type() == FLOW_AUTO && !m_IsNetLinkUp)
  134. {
  135. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Flow}: 自动流程[%d]挂起, 等候与CTI连接, Template = %s"), m_Id, m_pFlowTemplate->name());
  136. return CELL_OP_WAIT_FOR;
  137. }
  138. return next(Pos);
  139. }
  140. /*****************************************************************
  141. **【函数名称】 next
  142. **【函数功能】 执行流程下一结点
  143. **【参数】 NextPos:下一结点编号
  144. **【返回值】 后一个节点编号
  145. ****************************************************************/
  146. int CIvrFlow::next( int NextPos )
  147. {
  148. ASSERT(m_pFlowTemplate != NULL);
  149. if(m_pFlowTemplate == NULL)
  150. {
  151. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 执行流程[%d]后续节点时,流程模板为空"), m_Id);
  152. return CELL_OP_ERROR;
  153. }
  154. int NextCellPos = NextPos;
  155. m_pCurrentCell = m_pFlowTemplate->findCell(NextCellPos);
  156. if(m_pCurrentCell == NULL)
  157. {
  158. __onNextCellNull(NextCellPos);
  159. return NextCellPos;
  160. }
  161. while(m_pCurrentCell != NULL)
  162. {
  163. m_pCurrentCell->assoIvrFlow() = this;
  164. CMsgCenter::GetInstance().pushMsg(IVR_MSG_FLOW_CELL_UPDATE, reinterpret_cast<const PARAM>(m_Id));
  165. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]开始执行节点[%s]"), m_Id, m_pCurrentCell->name());
  166. NextCellPos = m_pCurrentCell->operate();
  167. if(NextCellPos > 0)
  168. {
  169. __deleteCurrentCell();
  170. m_pCurrentCell = m_pFlowTemplate->findCell(NextCellPos);
  171. if(m_pCurrentCell == NULL)
  172. {
  173. __onNextCellNull(NextCellPos);
  174. break;
  175. }
  176. }
  177. else if(NextCellPos == CELL_OP_END)
  178. {
  179. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]执行模板[%s]结束"), m_Id, m_pFlowTemplate->name());
  180. __clearFlow();
  181. break;
  182. }
  183. else if(NextCellPos == CELL_OP_WAIT_FOR)
  184. {
  185. if(m_pCurrentCell->maxWaitingTime() > 0)
  186. SetTimer(reinterpret_cast<long>(m_pCurrentCell), m_pCurrentCell->maxWaitingTime() * 1000, NULL);
  187. break;
  188. }
  189. else if(NextCellPos == CELL_OP_ERROR)
  190. {
  191. CPduEntity cmdIVREnd(PDU_CMD_IVR_END);
  192. cmdIVREnd.SetDataInt(1, m_Id);
  193. if(!CNetworkIvr::GetInstance().send(cmdIVREnd))
  194. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时发生异常, 且通知Cti失败, 流程将被释放"), m_Id, m_pCurrentCell->name());
  195. else
  196. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时发生异常, 已成功通知Cti, 流程将被释放"), m_Id, m_pCurrentCell->name());
  197. __clearFlow();
  198. break;
  199. }
  200. else if(NextCellPos == CELL_OP_SEND_ERROR)
  201. {
  202. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]执行节点[%s]时, 向Cti传送数据失败, 流程将被释放"), m_Id, m_pCurrentCell->name());
  203. __clearFlow();
  204. break;
  205. }
  206. }
  207. return NextCellPos;
  208. }
  209. /*****************************************************************
  210. **【函数名称】 procPdu
  211. **【函数功能】 处理PDU消息
  212. **【参数】 pPduEntity:PDU消息
  213. **【返回值】 下一个节点编号
  214. ****************************************************************/
  215. int CIvrFlow::procPdu( CPduEntity* pPduEntity )
  216. {
  217. ASSERT(pPduEntity != NULL);
  218. bool HangupFlag = false;
  219. if(pPduEntity->GetCmdType() == PDU_CMD_CTI_IVR_HANGUP && !pPduEntity->GetIsExecReturn())
  220. HangupFlag = true;
  221. if(m_pCurrentCell != NULL)
  222. {
  223. int NextCellPos = m_pCurrentCell->onOpResultReturn(pPduEntity);
  224. if(HangupFlag)
  225. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]收到挂机消息, 流程当前节点为[%s], Note = %s, 下一节点[%d]"),
  226. m_Id, m_pCurrentCell->name(), m_pCurrentCell->note(), NextCellPos);
  227. else
  228. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]收到节点操作的返回结果, 流程当前节点为[%s], Note = %s, 下一节点[%d]"),
  229. m_Id, m_pCurrentCell->name(), m_pCurrentCell->note(), NextCellPos);
  230. if(NextCellPos > 0) // NextCellPos为可用的下一结点编号
  231. {
  232. __deleteCurrentCell();
  233. return next(NextCellPos);
  234. }
  235. else if(NextCellPos == CELL_OP_WAIT_FOR)
  236. {
  237. if(HangupFlag) m_IsHangUp = true;
  238. return CELL_OP_WAIT_FOR;
  239. }
  240. else if(NextCellPos == CELL_OP_END)
  241. {
  242. ASSERT(FALSE);
  243. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Flow}: 流程[%d]执行模板[%s]结束"), m_Id, m_pFlowTemplate->name());
  244. __clearFlow();
  245. return CELL_OP_END;
  246. }
  247. else // CELL_OP_ERROR或者CELL_OP_SEND_ERROR的情况
  248. {
  249. __clearFlow();
  250. return CELL_OP_ERROR;
  251. }
  252. }
  253. else
  254. {
  255. if(HangupFlag)
  256. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]收到挂机消息, 但是当前执行节点为空, 流程将被释放"), m_Id);
  257. else
  258. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Flow}: 流程[%d]收到节点操作的返回结果, 但是执行节点却为空, 流程将被释放"), m_Id);
  259. __clearFlow();
  260. return CELL_OP_ERROR;
  261. }
  262. }
  263. /*****************************************************************
  264. **【函数名称】 onNetLinkUpdated
  265. **【函数功能】 响应网络链接成功或断开事件
  266. **【参数】 IsConnect:网络链接成功或断开
  267. **【返回值】
  268. ****************************************************************/
  269. void CIvrFlow::onNetLinkUpdated( bool IsConnect )
  270. {
  271. m_IsNetLinkUp = IsConnect;
  272. if(!IsConnect)
  273. {
  274. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 网络中断流程[%d]将被释放"), m_Id);
  275. __clearFlow();
  276. }
  277. else
  278. {
  279. if(m_pFlowTemplate != NULL && m_pFlowTemplate->type() == FLOW_AUTO)
  280. {
  281. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("{Flow}: 网络连接成功自动流程[%d]将启动"), m_Id);
  282. start();
  283. }
  284. }
  285. }
  286. /*****************************************************************
  287. **【函数名称】 addVar
  288. **【函数功能】 添加系统变量
  289. **【参数】 VarName: 变量名称
  290. VarValue: 变量值
  291. **【返回值】
  292. ****************************************************************/
  293. void CIvrFlow::addVar( const CString& VarName, const CString& VarValue )
  294. {
  295. m_VarTable.SetAt(VarName, VarValue);
  296. }
  297. /*****************************************************************
  298. **【函数名称】 findVarValue
  299. **【函数功能】 查找系统变量
  300. **【参数】 VarName:变量名称
  301. VarValue:变量值
  302. **【返回值】 true:查找到,false:未查找到
  303. ****************************************************************/
  304. bool CIvrFlow::findVarValue( const CString& VarName, CString& VarValue )
  305. {
  306. if(m_VarTable.Lookup(VarName, VarValue))
  307. return true;
  308. else
  309. return false;
  310. }
  311. /*****************************************************************
  312. **【函数名称】 replaceVar
  313. **【函数功能】 根据流程中的变量对指定字符串进行替换
  314. **【参数】 Src: 要进行替换的字符串
  315. Dst: 替换完成的字符串
  316. **【返回值】 成功true,失败false
  317. ****************************************************************/
  318. bool CIvrFlow::replaceVar( const CString& Src, CString& Dst )
  319. {
  320. Dst = Src;
  321. int Begin = 0;
  322. while( (Begin = Dst.Find(VAR_REF_START_FLAG, Begin)) != -1)
  323. {
  324. int End = Dst.Find(VAR_REF_END_FLAG, Begin);
  325. if(End != -1 && (End - Begin) > 2) // 可以取其中的变量
  326. {
  327. CString ValName = Dst.Mid(Begin + 2, End - Begin - 2);
  328. CString ValValue = _T("");
  329. // 将变量替换为具体值
  330. if( findVarValue(ValName, ValValue))
  331. Dst.Replace((VAR_REF_START_FLAG + ValName + VAR_REF_END_FLAG), ValValue);
  332. else
  333. return false;
  334. } // end if
  335. else
  336. {
  337. return false;
  338. }
  339. } // end while
  340. return true;
  341. }
  342. /*****************************************************************
  343. **【函数名称】 copyVar
  344. **【函数功能】 复制目标流程的系统变量
  345. **【参数】 DestFlow:目标流程
  346. **【返回值】
  347. ****************************************************************/
  348. void CIvrFlow::copyVar( CIvrFlow& DestFlow )
  349. {
  350. const VarTable::CPair* pPair = DestFlow.m_VarTable.PGetFirstAssoc();
  351. while(pPair != NULL)
  352. {
  353. m_VarTable.SetAt(pPair->key, pPair->value);
  354. DestFlow.m_VarTable.PGetNextAssoc(pPair);
  355. }
  356. }
  357. /*****************************************************************
  358. **【函数名称】 setFlowInfo
  359. **【函数功能】 保存流程信息
  360. **【参数】 CallId: 呼叫标识
  361. TrunkId: 外线Id
  362. CallerNum:主叫号码
  363. CalleeNum: 被叫号码
  364. **【返回值】
  365. ****************************************************************/
  366. void CIvrFlow::setFlowInfo( ULONG CallId, UINT TrunkId, const CString& CallerNum, const CString& CalleeNum )
  367. {
  368. m_AssoCallId = CallId;
  369. // 给系统变量呼叫标识赋值
  370. CString Data = "";
  371. Data.Format(_T("%lu"), CallId);
  372. addVar(SYSTEM_VAR_CALLID, Data);
  373. // 给系统变量外线号赋值
  374. Data.Format(_T("%u"), TrunkId);
  375. addVar(SYSTEM_VAR_OUTLINEID, Data);
  376. // 给系统变量主叫号码赋值
  377. addVar(SYSTEM_VAR_CALLER, CallerNum);
  378. // 给系统变量被叫号码赋值
  379. addVar(SYSTEM_VAR_CALLEE, CalleeNum);
  380. }
  381. /*****************************************************************
  382. **【函数名称】 setFlowInfo
  383. **【函数功能】 保存流程信息
  384. **【参数】 CallId: 呼叫标识
  385. TrunkId: 外线Id
  386. TaskId: 预测任务ID
  387. OpType: 操作类型
  388. CallerNum:主叫号码
  389. CalleeNum: 被叫号码
  390. **【返回值】
  391. ****************************************************************/
  392. void CIvrFlow::setFlowInfo( ULONG CallId, UINT TrunkId, int TaskId, UINT OpType, const CString& CallerNum, const CString& CalleeNum )
  393. {
  394. setFlowInfo(CallId, TrunkId, CallerNum, CalleeNum);
  395. CString Data;
  396. Data.Format(_T("%d"), TaskId);
  397. addVar(SYSTEM_VAR_PRE_CALL_ID, Data);
  398. Data.Format(_T("%u"), OpType);
  399. addVar(SYSTEM_VAR_PRE_CALL_TYPE, Data);
  400. }
  401. /*****************************************************************
  402. **【函数名称】 setFlowAssoData
  403. **【函数功能】 设置流程随路数据
  404. **【参数】 AssoData: 随路数据
  405. **【返回值】
  406. ****************************************************************/
  407. void CIvrFlow::setFlowAssoData( CString AssoData )
  408. {
  409. CString DataInfo = "";
  410. CString DataName = "";
  411. CString DataValue = "";
  412. while(!AssoData.IsEmpty())
  413. {
  414. int nIndex = AssoData.Find("|");
  415. if(nIndex == -1)
  416. {
  417. DataInfo = AssoData;
  418. AssoData.Empty();
  419. }
  420. else
  421. {
  422. DataInfo = AssoData.Left(nIndex);
  423. AssoData = AssoData.Right(AssoData.GetLength() - nIndex - 1);
  424. }
  425. // 解析单个随路数据
  426. int Falg = DataInfo.Find(":");
  427. if(Falg == -1)
  428. continue;
  429. // 获取变量名
  430. DataName = DataInfo.Left(Falg);
  431. if(DataName.IsEmpty())
  432. continue;
  433. // 获取变量值
  434. DataValue = DataInfo.Right(DataInfo.GetLength() - Falg - 1);
  435. // 添加进随路数据
  436. this->addVar(DataName, DataValue);
  437. }
  438. }
  439. /*****************************************************************
  440. **【函数名称】 OnTimer
  441. **【函数功能】 定时器响应函数
  442. **【参数】 nIDEvent: 定时器ID
  443. **【返回值】
  444. ****************************************************************/
  445. void CIvrFlow::OnTimer( UINT_PTR nIDEvent )
  446. {
  447. KillTimer(nIDEvent);
  448. if(m_pCurrentCell != NULL && nIDEvent == reinterpret_cast<long>(m_pCurrentCell))
  449. __onTimerTimeOut();
  450. CWnd::OnTimer(nIDEvent);
  451. }
  452. /*****************************************************************
  453. **【函数名称】 onTimeUp
  454. **【函数功能】 定时器节点时间到
  455. **【参数】
  456. **【返回值】
  457. ****************************************************************/
  458. void CIvrFlow::onTimerTimeUp( int NextPos )
  459. {
  460. if(m_pCurrentCell->name() == CELL_NAME_TIMER)
  461. {
  462. __deleteCurrentCell();
  463. next(NextPos);
  464. }
  465. }