MiddleWares_YiHe 郑州颐和医院随访系统中间件

IvrFlowHolder.cpp 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #include "StdAfx.h"
  2. #include "IvrFlowHolder.h"
  3. #include "IvrFlow.h"
  4. #include "CtiCore.h"
  5. #include "TaskMgr.h"
  6. #include "Inc/CallDetailInc.h"
  7. #include "StatisticsMgr.h"
  8. #include "NetworkCti.h"
  9. #include "LogicLine.h"
  10. #include "LineHolder.h"
  11. SINGLETON_IMPLEMENT(CIvrFlowHolder)
  12. CIvrFlowHolder::CIvrFlowHolder(void)
  13. {
  14. }
  15. CIvrFlowHolder::~CIvrFlowHolder(void)
  16. {
  17. }
  18. /*****************************************************************
  19. **【函数名称】 __procCallInReturn
  20. **【函数功能】 处理CallIn命令返回
  21. **【参数】 PduEntity:消息实体
  22. **【返回值】
  23. ****************************************************************/
  24. void CIvrFlowHolder::__procCallInReturn( CPduEntity &PduEntity )
  25. {
  26. // 显示日志
  27. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL,_T("IVR->CTI, CMD = return[CallIn], \
  28. IVR = %d, Line = %d, CallerNum = %s, CalleeNum = %s, IsSuccess = %d"),
  29. PduEntity.GetDataInt(1),
  30. PduEntity.GetDataUInt(5),
  31. PduEntity.GetDataString(3),
  32. PduEntity.GetDataString(4),
  33. PduEntity.GetDataBool(0));
  34. // 转发给IvrFlow
  35. __transmitToIvrFlow(PduEntity);
  36. }
  37. /*****************************************************************
  38. **【函数名称】 __procTurnIvrReturn
  39. **【函数功能】 处理转Ivr命令返回
  40. **【参数】 PduEntity: 消息实体
  41. **【返回值】
  42. ****************************************************************/
  43. void CIvrFlowHolder::__procTurnIvrReturn( CPduEntity &PduEntity )
  44. {
  45. // 显示日志
  46. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL,_T("IVR->CTI, Cmd = return[TurnIVR], \
  47. IVR = %d, Line = %d, CallerNum = %s, CalleeNum = %s, IsSuccess = %d"),
  48. PduEntity.GetDataInt(1),
  49. PduEntity.GetDataUInt(5),
  50. PduEntity.GetDataString(3),
  51. PduEntity.GetDataString(4),
  52. PduEntity.GetDataBool(0));
  53. // 如果IVR不存在,通知Task转IVR失败
  54. if(PduEntity.GetDataInt(1) == -1)
  55. CTaskMgr::GetInstance().onTaskPduMsg(PduEntity.GetDataUInt(5), PduEntity);
  56. else
  57. __transmitToIvrFlow(PduEntity);
  58. }
  59. /*****************************************************************
  60. **【函数名称】 __transmitToIvrFlow
  61. **【函数功能】 命令转发给IvrFlow
  62. **【参数】 PduEntity: 消息实体
  63. **【返回值】
  64. ****************************************************************/
  65. void CIvrFlowHolder::__transmitToIvrFlow( CPduEntity &PduEntity )
  66. {
  67. // 根据IvrId获取Ivr对象
  68. CIvrFlow *pIvrFlow = getFlowByIvrId(PduEntity.GetDataInt(1));
  69. if(pIvrFlow == NULL)
  70. {
  71. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_ERROR, _T("{IvrFlowHolder}: 向IVR转发命令时定位不到IvrFlow,IVR = %d"), PduEntity.GetDataInt(1));
  72. if (PDU_CMD_CTI_IVR_CALLIN == PduEntity.GetCmdType()) // 通知IVR外线来电消息返回,注:只有该类型添加的第二个字段数据其值为CallID
  73. {
  74. // 统计找不到IVR流程资源造成的呼入失败记录
  75. T_EvtError repInfo;
  76. memset(&repInfo, 0, sizeof(repInfo));
  77. repInfo.nErrorType = REP_ERROR_IVRFLOW;
  78. CStatisticsMgr::GetInstance().onCallDetail(PduEntity.GetDataULong(2), REP_EVENT_ERROR, PduEntity.GetDataUInt(5), &repInfo);
  79. }
  80. // 命令返回失败
  81. if(PduEntity.GetIsExecReturn()) return;
  82. PduEntity.SetToExecReturn();
  83. PduEntity.SetDataBool(0, false);
  84. CNetworkCti::GetInstance().send2IVR(PduEntity);
  85. }
  86. else
  87. {
  88. PDU_CMD_TYPE CmdType = PduEntity.GetCmdType();
  89. if (PDU_CMD_IVR_WANT_AGENT == CmdType)
  90. {
  91. // 在处理ACD相关消息时,添加判断是否与ACD正常连接,若没有正常连接则与ACD相关的操作数据记录为呼损数据。
  92. if (!CNetworkCti::GetInstance().isACDConnected())
  93. {
  94. // 显示日志
  95. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING,_T("{IvrFlowHolder}: 执行来电排队操作失败,ACD未连接到系统,或ACD未启动!"));
  96. // 统计ACD未启动造成呼入失败记录
  97. T_EvtError repInfo;
  98. memset(&repInfo, 0, sizeof(repInfo));
  99. repInfo.nErrorType = REP_ERROR_ACD;
  100. CStatisticsMgr::GetInstance().onCallDetail(PduEntity.GetDataULong(2), REP_EVENT_ERROR, PduEntity.GetDataInt(5), &repInfo);
  101. }
  102. }
  103. pIvrFlow->onPduMessage(PduEntity);
  104. }
  105. }
  106. /*****************************************************************
  107. **【函数名称】 __procDevOpCallIn
  108. **【函数功能】 处理底层设备外线呼入
  109. **【参数】 DevOpInfo: 底层操作数据
  110. **【返回值】
  111. ****************************************************************/
  112. void CIvrFlowHolder::__procDevOpCallIn( EventDevOperation &DevOpInfo )
  113. {
  114. T_EvtError repInfo;
  115. memset(&repInfo, 0, sizeof(repInfo));
  116. // 获取线路类指针
  117. CLogicLine *pLogicLine = CLineHolder::GetInstance().getLogicLine(DevOpInfo.nLineId);
  118. if(pLogicLine == NULL) return;
  119. if(pLogicLine->type() != DEV_RES_TYPE_TRUNK && pLogicLine->type() != DEV_RES_TYPE_VOIP)
  120. {
  121. repInfo.nErrorType = REP_ERROR_SYSTEM;
  122. CStatisticsMgr::GetInstance().onCallDetail(pLogicLine->callId(), REP_EVENT_ERROR, DevOpInfo.nLineId, &repInfo);
  123. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING,_T("{IvrFlowHolder}: 外线呼入通知IVR时检测到线路类型非外线, Line Id = %u, type = %u"),
  124. pLogicLine->lineId(), pLogicLine->type());
  125. }
  126. // 判断IVR是否断开连接,如果断开连接则作为外线呼入失败记录
  127. if (!CNetworkCti::GetInstance().isIVRConnected())
  128. {
  129. // 显示日志
  130. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING,_T("{IvrFlowHolder}: 外线呼入通知IVR失败,IVR未连接到系统,或IVR未启动"));
  131. // 统计IVR未启动造成呼入失败记录
  132. repInfo.nErrorType = REP_ERROR_IVR;
  133. CStatisticsMgr::GetInstance().onCallDetail(pLogicLine->callId(), REP_EVENT_ERROR, DevOpInfo.nLineId, &repInfo);
  134. }
  135. else
  136. {
  137. // 通知IVR程序外线来电
  138. CPduEntity CmdCallIn(PDU_CMD_CTI_IVR_CALLIN);
  139. CmdCallIn.SetDataULong(2, pLogicLine->callId());
  140. CmdCallIn.SetDataString(3, DevOpInfo.szCallerNum);
  141. CmdCallIn.SetDataString(4, DevOpInfo.szCalleeNum);
  142. CmdCallIn.SetDataUInt(5, DevOpInfo.nLineId);
  143. CNetworkCti::GetInstance().send2IVR(CmdCallIn);
  144. }
  145. }
  146. void CIvrFlowHolder::__procDevPlayDtmf(EventDevOperation &DevOpInfo)
  147. {
  148. ;
  149. }
  150. /*****************************************************************
  151. **【函数名称】 createIvrFlow
  152. **【函数功能】 创建IvrFlow
  153. **【参数】
  154. **【返回值】
  155. ****************************************************************/
  156. void CIvrFlowHolder::createIvrFlow( int IvrFlowNum )
  157. {
  158. for(int i = 0; i < IvrFlowNum; i++)
  159. {
  160. CIvrFlow *pIvrFlow = new CIvrFlow(i);
  161. m_IvrFlowMap.SetAt(i, pIvrFlow);
  162. }
  163. }
  164. /*****************************************************************
  165. **【函数名称】 destroyIvrFlow
  166. **【函数功能】 销毁IvrFlow
  167. **【参数】
  168. **【返回值】
  169. ****************************************************************/
  170. void CIvrFlowHolder::destroyIvrFlow( void )
  171. {
  172. UINT Key = 0;
  173. CIvrFlow *pIvrFlow = NULL;
  174. POSITION pos = m_IvrFlowMap.GetStartPosition();
  175. while (pos != NULL)
  176. {
  177. m_IvrFlowMap.GetNextAssoc(pos, Key, pIvrFlow);
  178. if (pIvrFlow != NULL)
  179. {
  180. delete pIvrFlow;
  181. pIvrFlow = NULL;
  182. }
  183. } // end while
  184. m_IvrFlowMap.RemoveAll();
  185. }
  186. /*****************************************************************
  187. **【函数名称】 onPduMessage
  188. **【函数功能】 Pdu命令处理接口
  189. **【参数】 PduEntity:消息实体
  190. **【返回值】
  191. ***************************************************************/
  192. void CIvrFlowHolder::onPduMessage( CPduEntity &PduEntity )
  193. {
  194. switch(PduEntity.GetCmdType())
  195. {
  196. case PDU_CMD_CTI_IVR_CALLIN: // CallIn命令返回
  197. __procCallInReturn(PduEntity);
  198. break;
  199. case PDU_CMD_CTI_IVR_TURNIVR: // 转Ivr命令
  200. __procTurnIvrReturn(PduEntity);
  201. break;
  202. default: // 命令转发给IvrFlow
  203. __transmitToIvrFlow(PduEntity);
  204. break;
  205. }
  206. }
  207. /*****************************************************************
  208. **【函数名称】 onDevMessage
  209. **【函数功能】 底层设备事件
  210. **【参数】 EvtType 消息事件类型
  211. lpContent 消息内容
  212. **【返回值】
  213. ****************************************************************/
  214. void CIvrFlowHolder::onDevMessage( EventDevOperation &DevOpInfo )
  215. {
  216. switch(DevOpInfo.nOpType)
  217. {
  218. case DEV_OP_CALL_IN:
  219. __procDevOpCallIn(DevOpInfo);
  220. break;
  221. default:
  222. break;
  223. }
  224. }
  225. /*****************************************************************
  226. **【函数名称】 onIvrDisconnect
  227. **【函数功能】 处理Ivr连接断开
  228. **【参数】
  229. **【返回值】
  230. ****************************************************************/
  231. void CIvrFlowHolder::onIvrDisconnect(void)
  232. {
  233. UINT nIndex;
  234. CIvrFlow *pIvrFlow = NULL;
  235. POSITION pos = m_IvrFlowMap.GetStartPosition();
  236. // 循环遍历结束所有Ivrflow
  237. while(pos != NULL)
  238. {
  239. m_IvrFlowMap.GetNextAssoc(pos, nIndex, pIvrFlow);
  240. if(pIvrFlow == NULL) continue;
  241. // 向关联线路发送挂机命令
  242. if(pIvrFlow->assoLineId() != -1)
  243. CCtiCore::GetInstance().getDevLink().exec(-1, LINE_OP_HANG_UP, pIvrFlow->assoLineId(), NULL);
  244. // Ivrflow重置
  245. pIvrFlow->resetFlow();
  246. }
  247. }
  248. /*****************************************************************
  249. **【函数名称】 getFlowByIvrId
  250. **【函数功能】 通过IvrId获取关联的IVR流程
  251. **【参数】 IvrId: IVR ID
  252. **【返回值】 CIvrFlow对象
  253. ****************************************************************/
  254. CIvrFlow* CIvrFlowHolder::getFlowByIvrId( int IvrId )
  255. {
  256. CIvrFlow *pIvrFlow = NULL;
  257. m_IvrFlowMap.Lookup(IvrId, pIvrFlow);
  258. return pIvrFlow;
  259. }
  260. /*****************************************************************
  261. **【函数名称】 getFlowByLineId
  262. **【函数功能】 通过线路号获取关联的IVR流程
  263. **【参数】 LineId: 线路号
  264. **【返回值】 CIvrFlow对象
  265. ****************************************************************/
  266. CIvrFlow* CIvrFlowHolder::getFlowByLineId( int LineId )
  267. {
  268. UINT nIndex;
  269. CIvrFlow *pIvrFlow = NULL;
  270. POSITION pos = m_IvrFlowMap.GetStartPosition();
  271. while(pos != NULL)
  272. {
  273. m_IvrFlowMap.GetNextAssoc(pos, nIndex, pIvrFlow);
  274. if(pIvrFlow != NULL && pIvrFlow->assoLineId() == LineId)
  275. return pIvrFlow;
  276. }
  277. return NULL;
  278. }