升龙物业 老版本 ocx IPO, 加密狗 转值班电话

IvrFlowHolder.cpp 9.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. /*****************************************************************
  147. **【函数名称】 createIvrFlow
  148. **【函数功能】 创建IvrFlow
  149. **【参数】
  150. **【返回值】
  151. ****************************************************************/
  152. void CIvrFlowHolder::createIvrFlow( int IvrFlowNum )
  153. {
  154. for(int i = 0; i < IvrFlowNum; i++)
  155. {
  156. CIvrFlow *pIvrFlow = new CIvrFlow(i);
  157. m_IvrFlowMap.SetAt(i, pIvrFlow);
  158. }
  159. }
  160. /*****************************************************************
  161. **【函数名称】 destroyIvrFlow
  162. **【函数功能】 销毁IvrFlow
  163. **【参数】
  164. **【返回值】
  165. ****************************************************************/
  166. void CIvrFlowHolder::destroyIvrFlow( void )
  167. {
  168. UINT Key = 0;
  169. CIvrFlow *pIvrFlow = NULL;
  170. POSITION pos = m_IvrFlowMap.GetStartPosition();
  171. while(pos != NULL)
  172. {
  173. m_IvrFlowMap.GetNextAssoc(pos, Key, pIvrFlow);
  174. if(pIvrFlow != NULL)
  175. delete pIvrFlow;
  176. } // end while
  177. m_IvrFlowMap.RemoveAll();
  178. }
  179. /*****************************************************************
  180. **【函数名称】 onPduMessage
  181. **【函数功能】 Pdu命令处理接口
  182. **【参数】 PduEntity:消息实体
  183. **【返回值】
  184. ***************************************************************/
  185. void CIvrFlowHolder::onPduMessage( CPduEntity &PduEntity )
  186. {
  187. switch(PduEntity.GetCmdType())
  188. {
  189. case PDU_CMD_CTI_IVR_CALLIN: // CallIn命令返回
  190. __procCallInReturn(PduEntity);
  191. break;
  192. case PDU_CMD_CTI_IVR_TURNIVR: // 转Ivr命令
  193. __procTurnIvrReturn(PduEntity);
  194. break;
  195. default: // 命令转发给IvrFlow
  196. __transmitToIvrFlow(PduEntity);
  197. break;
  198. }
  199. }
  200. /*****************************************************************
  201. **【函数名称】 onDevMessage
  202. **【函数功能】 底层设备事件
  203. **【参数】 EvtType 消息事件类型
  204. lpContent 消息内容
  205. **【返回值】
  206. ****************************************************************/
  207. void CIvrFlowHolder::onDevMessage( EventDevOperation &DevOpInfo )
  208. {
  209. switch(DevOpInfo.nOpType)
  210. {
  211. case DEV_OP_CALL_IN:
  212. __procDevOpCallIn(DevOpInfo);
  213. break;
  214. default:
  215. break;
  216. }
  217. }
  218. /*****************************************************************
  219. **【函数名称】 onIvrDisconnect
  220. **【函数功能】 处理Ivr连接断开
  221. **【参数】
  222. **【返回值】
  223. ****************************************************************/
  224. void CIvrFlowHolder::onIvrDisconnect(void)
  225. {
  226. UINT nIndex;
  227. CIvrFlow *pIvrFlow = NULL;
  228. POSITION pos = m_IvrFlowMap.GetStartPosition();
  229. // 循环遍历结束所有Ivrflow
  230. while(pos != NULL)
  231. {
  232. m_IvrFlowMap.GetNextAssoc(pos, nIndex, pIvrFlow);
  233. if(pIvrFlow == NULL) continue;
  234. // 向关联线路发送挂机命令
  235. if(pIvrFlow->assoLineId() != -1)
  236. CCtiCore::GetInstance().getDevLink().exec(-1, LINE_OP_HANG_UP, pIvrFlow->assoLineId(), NULL);
  237. // Ivrflow重置
  238. pIvrFlow->resetFlow();
  239. }
  240. }
  241. /*****************************************************************
  242. **【函数名称】 getFlowByIvrId
  243. **【函数功能】 通过IvrId获取关联的IVR流程
  244. **【参数】 IvrId: IVR ID
  245. **【返回值】 CIvrFlow对象
  246. ****************************************************************/
  247. CIvrFlow* CIvrFlowHolder::getFlowByIvrId( int IvrId )
  248. {
  249. CIvrFlow *pIvrFlow = NULL;
  250. m_IvrFlowMap.Lookup(IvrId, pIvrFlow);
  251. return pIvrFlow;
  252. }
  253. /*****************************************************************
  254. **【函数名称】 getFlowByLineId
  255. **【函数功能】 通过线路号获取关联的IVR流程
  256. **【参数】 LineId: 线路号
  257. **【返回值】 CIvrFlow对象
  258. ****************************************************************/
  259. CIvrFlow* CIvrFlowHolder::getFlowByLineId( int LineId )
  260. {
  261. UINT nIndex;
  262. CIvrFlow *pIvrFlow = NULL;
  263. POSITION pos = m_IvrFlowMap.GetStartPosition();
  264. while(pos != NULL)
  265. {
  266. m_IvrFlowMap.GetNextAssoc(pos, nIndex, pIvrFlow);
  267. if(pIvrFlow != NULL && pIvrFlow->assoLineId() == LineId)
  268. return pIvrFlow;
  269. }
  270. return NULL;
  271. }