华辉中间件项目(代码服务器上没有,用杨成电脑的源代码上传的)

Agent.cpp 15KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605
  1. #include "StdAfx.h"
  2. #include "Agent.h"
  3. #include "Config.h"
  4. #include "SLogic.h"
  5. #include "AcdCore.h"
  6. #include "MsgCenter.h"
  7. #include "NetworkAcd.h"
  8. #include "Exten.h"
  9. CAgent::CAgent(UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID, UINT a_AgentType, UINT a_PostProcessingTime)
  10. {
  11. // 网络属性
  12. CNetworkAcd::GetInstance().getAgentLinkInfo(a_AgentID, m_AgentIp, m_AgentPort);
  13. // 基本属性
  14. m_AgentID = a_AgentID;
  15. m_Exten = a_ExtID;
  16. m_GroupID = a_GroupID;
  17. m_AgentType = (AGENT_TYPE)a_AgentType;
  18. m_State = AGENT_STATE_UNKNOWN;
  19. m_AssoExtState = INNER_STATE_FREE;
  20. m_IsRepose = false;
  21. m_bFirstQueue = true;
  22. // 业务属性
  23. m_AnswerCount = 0;
  24. m_ReposeCount = 0;
  25. m_TimeFree = 0;
  26. m_TimeRepos = 0;
  27. m_TimeTalk = 0;
  28. m_TimePostProcessing = (a_PostProcessingTime == 0) ? CConfig::postProcessingTime() : a_PostProcessingTime;
  29. // 定时器初始化
  30. m_PollTimer.SetTimedEvent(this, &CAgent::__onTimerPoll);
  31. m_PollTimer.Start(1000);
  32. // 通知统计模块座席签入
  33. __reportLogin();
  34. // 添加消息可供视图刷新
  35. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (const PARAM)m_AgentID);
  36. }
  37. CAgent::CAgent(UINT a_AgentID, UINT a_ExtID, LPCTSTR a_GroupID, UINT a_AgentType, const CAgentProperty& AgentProperty)
  38. {
  39. // 网络属性
  40. CNetworkAcd::GetInstance().getAgentLinkInfo(a_AgentID, m_AgentIp, m_AgentPort);
  41. // 基本属性
  42. m_AgentID = a_AgentID;
  43. m_Exten = a_ExtID;
  44. m_GroupID = a_GroupID;
  45. m_AgentType = (AGENT_TYPE)a_AgentType;
  46. m_State = AGENT_STATE_UNKNOWN;
  47. m_AssoExtState = INNER_STATE_FREE;
  48. m_IsRepose = false;
  49. // 业务属性
  50. m_AnswerCount = AgentProperty.m_AnswerCount;
  51. m_ReposeCount = AgentProperty.m_ReposeCount;
  52. m_TimeFree = AgentProperty.m_TimeFree;
  53. m_TimeRepos = AgentProperty.m_TimeRepos;
  54. m_TimeTalk = AgentProperty.m_TimeTalk;
  55. m_TimePostProcessing = (AgentProperty.m_TimePostProcessing == 0) ? CConfig::postProcessingTime() : AgentProperty.m_TimePostProcessing;
  56. // 定时器初始化
  57. m_PollTimer.SetTimedEvent(this, &CAgent::__onTimerPoll);
  58. m_PollTimer.Start(1000);
  59. // 通知统计模块座席签入
  60. __reportLogin();
  61. // 添加消息可供视图刷新
  62. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (const PARAM)m_AgentID);
  63. }
  64. CAgent::~CAgent(void)
  65. {
  66. m_PollTimer.StopSafely();
  67. m_AgentTimer.StopSafely();
  68. }
  69. /*****************************************************************
  70. **【函数名称】 __reportLogin
  71. **【函数功能】 签出统计通知
  72. **【参数】
  73. **【返回值】
  74. ****************************************************************/
  75. void CAgent::__reportLogin()
  76. {
  77. // 通知统计模块 REP_EVENT_LOGIN
  78. T_EvtLogIn repLogin = { 0 };
  79. repLogin.nAgentID = m_AgentID;
  80. repLogin.nExtID = m_Exten;
  81. repLogin.nAgentType = m_AgentType;
  82. lstrcpy(repLogin.szGroup, m_GroupID);
  83. lstrcpy(repLogin.szAgentIP, m_AgentIp);
  84. CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_LOGIN, &repLogin);
  85. }
  86. /*****************************************************************
  87. **【函数名称】 __reportLogout
  88. **【函数功能】 签出统计通知
  89. **【参数】 HostAgent: 签出当前座席的主控座席
  90. **【返回值】
  91. ****************************************************************/
  92. void CAgent::__reportLogout(const UINT HostAgent)
  93. {
  94. if (m_State == AGENT_STATE_REPOSE)
  95. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  96. if (m_State == AGENT_STATE_POST_PROCESSING)
  97. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  98. // 通知统计模块 REP_EVENT_LOGOUT
  99. T_EvtLogout repLogout = { 0 };
  100. repLogout.nLogoutHost = HostAgent;
  101. repLogout.nTimeFree = m_TimeFree;
  102. repLogout.nTimeRepose = m_TimeRepos;
  103. repLogout.nTimeTalk = m_TimeTalk;
  104. repLogout.nAnswerCount = m_AnswerCount;
  105. repLogout.nReposeCount = m_ReposeCount;
  106. CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_LOGOUT, &repLogout);
  107. }
  108. /*****************************************************************
  109. **【函数名称】 __onStatusUpdate
  110. **【函数功能】 座席状态变更通知
  111. **【参数】
  112. **【返回值】
  113. ****************************************************************/
  114. void CAgent::__onStatusUpdate(AGENT_STATE State, bool StartFlag)
  115. {
  116. T_EvtStatus EvtStatus;
  117. EvtStatus.State = State;
  118. EvtStatus.StartFlag = StartFlag;
  119. CSLogic::GetInstance().onSEvent(m_AgentID, REP_EVENT_STATE, &EvtStatus);
  120. }
  121. /*****************************************************************
  122. **【函数名称】 __reportStatus
  123. **【函数功能】 通知各方座席当前状态
  124. **【参数】
  125. **【返回值】
  126. ****************************************************************/
  127. void CAgent::__reportStatus(void)
  128. {
  129. // 通知OCX座席当前状态
  130. CPduEntity Cmd(PDU_CMD_ACD_AGENT_STATE);
  131. Cmd.SetDataUInt(0, m_Exten);
  132. Cmd.SetDataUInt(1, m_AgentID);
  133. Cmd.SetDataUInt(2, m_State);
  134. //CNetworkAcd::GetInstance().send2Agent(m_AgentID, &Cmd);
  135. CNetworkAcd::GetInstance().send2Server(&Cmd);
  136. // 添加消息可供视图刷新
  137. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (PARAM)m_AgentID);
  138. }
  139. /*****************************************************************
  140. **【函数名称】 __reportStatus
  141. **【函数功能】 通知各方座席当前状态
  142. **【参数】
  143. **【返回值】
  144. ych 2018.5.17
  145. ****************************************************************
  146. void CAgent::__reportStatus(void)
  147. {
  148. CExten* pExten = CAcdCore::GetInstance().getExtenCtrl().getExten(m_Exten); // 获取指定分机
  149. if (pExten == NULL)
  150. {
  151. // 显示日志 ych 2018.5.17
  152. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_ERROR, _T("{CAgent::__reportStatus}: pExten指针为NULL"));
  153. return;
  154. }
  155. if (m_AgentID !=0 && m_AgentID == pExten->assoAgent())
  156. {
  157. CPduEntity Cmd(PDU_CMD_CTI_LINE_STATE);
  158. Cmd.SetDataUInt(0, pExten->GetID());
  159. Cmd.SetDataUInt(1, pExten->GetState());
  160. Cmd.SetDataULong(2, pExten->GetCallId());
  161. Cmd.SetDataUInt(3, pExten->GetAssoAgent());
  162. Cmd.SetDataString(4, pExten->GetCallerNum());
  163. Cmd.SetDataString(5, pExten->GetCalleeNum());
  164. Cmd.SetDataString(6, pExten->GetDataBind());
  165. Cmd.SetDataUInt(7, pExten->GetPeerLineType());
  166. Cmd.SetDataUInt(8, pExten->GetInfoEx());
  167. Cmd.SetDataUInt(9, pExten->GetFinalExt());
  168. Cmd.SetDataUInt(10, pExten->GetOpType());
  169. Cmd.SetDataUInt(11, 0);
  170. Cmd.SetDataUInt(12, m_State);
  171. //CNetworkAcd::GetInstance().send2Agent(m_AssoAgent, &Cmd);
  172. CNetworkAcd::GetInstance().send2Server(&Cmd);
  173. // 显示日志 ych 2018.5.17
  174. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CAgent::__reportStatus}: 返回线路及座席状态"));
  175. // 添加消息可供视图刷新
  176. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_STATE_UPDAET, (PARAM)m_AgentID);
  177. }
  178. }*/
  179. /*****************************************************************
  180. **【函数名称】 __onTimerPoll
  181. **【函数功能】 轮询定时器处理
  182. **【参数】
  183. **【返回值】
  184. ****************************************************************/
  185. void CAgent::__onTimerPoll(void)
  186. {
  187. if (m_State == AGENT_STATE_FREE)
  188. m_TimeFree++;
  189. else if (m_State == AGENT_STATE_BUSY)
  190. m_TimeTalk++;
  191. if (m_IsRepose)
  192. m_TimeRepos++;
  193. }
  194. /*****************************************************************
  195. **【函数名称】 __onTimerPostProcessing
  196. **【函数功能】 话后处理时长定时器处理
  197. **【参数】
  198. **【返回值】
  199. ****************************************************************/
  200. void CAgent::__onTimerPostProcessing(void)
  201. {
  202. if (m_State == AGENT_STATE_POST_PROCESSING)
  203. {
  204. setState(AGENT_STATE_FREE);
  205. }
  206. }
  207. /*****************************************************************
  208. **【函数名称】 __onTimerLock
  209. **【函数功能】 座席被锁定超时处理
  210. **【参数】
  211. **【返回值】
  212. ****************************************************************/
  213. void CAgent::__onTimerLock(void)
  214. {
  215. if (m_State == AGENT_STATE_REQUESTED)
  216. {
  217. setState(AGENT_STATE_FREE, true);
  218. }
  219. }
  220. /*****************************************************************
  221. **【函数名称】 __setTimer
  222. **【函数功能】 设立定时器
  223. **【参数】
  224. **【返回值
  225. ****************************************************************/
  226. void CAgent::__setTimer(UINT TimmerId, UINT Elapse)
  227. {
  228. if (TimmerId == TIMER_POST_PROCESSING)
  229. {
  230. m_AgentTimer.StopSafely();
  231. m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerPostProcessing);
  232. m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT);
  233. }
  234. else if (TimmerId == TIMER_LOCK_PERIOD)
  235. {
  236. m_AgentTimer.StopSafely();
  237. m_AgentTimer.SetTimedEvent(this, &CAgent::__onTimerLock);
  238. m_AgentTimer.Start(Elapse, false, true, WT_EXECUTEDEFAULT);
  239. }
  240. else
  241. {
  242. ASSERT(FALSE);
  243. }
  244. }
  245. /*****************************************************************
  246. **【函数名称】 __killTimer
  247. **【函数功能】 删除定时器
  248. **【参数】
  249. **【返回值
  250. ****************************************************************/
  251. void CAgent::__killTimer(UINT TimmerId)
  252. {
  253. m_AgentTimer.Stop();
  254. }
  255. /*****************************************************************
  256. **【函数名称】 release
  257. **【函数功能】 清理资源
  258. **【参数】 HostAgent: 主控制坐席工号
  259. **【返回值】
  260. ****************************************************************/
  261. void CAgent::release(UINT HostAgent)
  262. {
  263. m_PollTimer.StopSafely();
  264. m_AgentTimer.StopSafely();
  265. // 设置状态为注销
  266. setState(AGENT_STATE_LOGOUT);
  267. // 通知统计模块 REP_EVENT_LOGOUT
  268. __reportLogout(HostAgent);
  269. // 关闭Agent端SOCKET连接
  270. CNetworkAcd::GetInstance().shutDownAgentLink(m_AgentID);
  271. // 添加消息可供视图刷新
  272. CMsgCenter::GetInstance().pushMsg(ACD_MSG_AGENT_LOGOUT, (const PARAM)m_AgentID);
  273. }
  274. /*****************************************************************
  275. **【函数名称】 setState
  276. **【函数功能】 设置座席状态
  277. **【参数】 a_AgentState:座席当前逻辑状态
  278. **【返回值】
  279. ****************************************************************/
  280. BOOL CAgent::setState(AGENT_STATE a_AgentState, bool IsForce/* = false*/)
  281. {
  282. CSingleLock Locker(&m_Cs4Lock, TRUE);
  283. switch (a_AgentState)
  284. {
  285. case AGENT_STATE_BUSY: // 通话
  286. {
  287. switch (m_State)
  288. {
  289. case AGENT_STATE_BUSY:
  290. return TRUE;
  291. break;
  292. case AGENT_STATE_REQUESTED:
  293. __killTimer(TIMER_LOCK_PERIOD);
  294. break;
  295. case AGENT_STATE_POST_PROCESSING:
  296. {
  297. __killTimer(TIMER_POST_PROCESSING);
  298. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  299. }
  300. break;
  301. case AGENT_STATE_REPOSE:
  302. {
  303. m_IsRepose = false;
  304. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  305. }
  306. break;
  307. case AGENT_STATE_LOGOUT:
  308. return FALSE;
  309. break;
  310. }
  311. __onStatusUpdate(AGENT_STATE_BUSY, true);
  312. m_State = AGENT_STATE_BUSY;
  313. }
  314. break;
  315. case AGENT_STATE_REPOSE: // 小休
  316. {
  317. switch (m_State)
  318. {
  319. case AGENT_STATE_REPOSE:
  320. return TRUE;
  321. break;
  322. case AGENT_STATE_POST_PROCESSING:
  323. {
  324. __killTimer(TIMER_POST_PROCESSING);
  325. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  326. }
  327. break;
  328. case AGENT_STATE_BUSY:
  329. case AGENT_STATE_LOGOUT:
  330. case AGENT_STATE_REQUESTED:
  331. return FALSE;
  332. break;
  333. }
  334. m_ReposeCount++;
  335. m_IsRepose = true;
  336. m_State = AGENT_STATE_REPOSE;
  337. // 统计小休开始
  338. __onStatusUpdate(AGENT_STATE_REPOSE, true);
  339. }
  340. break;
  341. case AGENT_STATE_POST_PROCESSING: // 话后处理
  342. {
  343. switch (m_State)
  344. {
  345. case AGENT_STATE_POST_PROCESSING:
  346. return TRUE;
  347. break;
  348. case AGENT_STATE_BUSY:
  349. __onStatusUpdate(AGENT_STATE_BUSY, false);
  350. break;
  351. case AGENT_STATE_FREE:
  352. case AGENT_STATE_REPOSE:
  353. case AGENT_STATE_REQUESTED:
  354. case AGENT_STATE_LOGOUT:
  355. return FALSE;
  356. break;
  357. }
  358. // 统计话后处理开始
  359. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, true);
  360. m_State = AGENT_STATE_POST_PROCESSING;
  361. if (m_TimePostProcessing > 0)
  362. __setTimer(TIMER_POST_PROCESSING, m_TimePostProcessing * 1000); // 启动话后处理定时器
  363. }
  364. break;
  365. case AGENT_STATE_FREE: // 空闲
  366. {
  367. switch (m_State)
  368. {
  369. case AGENT_STATE_FREE:
  370. return TRUE;
  371. break;
  372. case AGENT_STATE_BUSY:
  373. {
  374. if (IsForce)
  375. __onStatusUpdate(AGENT_STATE_BUSY, false);
  376. else
  377. return FALSE;
  378. }
  379. break;
  380. case AGENT_STATE_POST_PROCESSING:
  381. {
  382. __killTimer(TIMER_POST_PROCESSING);
  383. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  384. }
  385. break;
  386. case AGENT_STATE_REPOSE:
  387. {
  388. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  389. m_IsRepose = false;
  390. }
  391. break;
  392. case AGENT_STATE_REQUESTED:
  393. {
  394. if (IsForce)
  395. __killTimer(TIMER_LOCK_PERIOD);
  396. else
  397. return FALSE;
  398. }
  399. break;
  400. case AGENT_STATE_LOGOUT:
  401. return FALSE;
  402. break;
  403. }
  404. m_State = m_IsRepose ? AGENT_STATE_REPOSE : AGENT_STATE_FREE;
  405. }
  406. break;
  407. case AGENT_STATE_REQUESTED: // 被请求
  408. {
  409. ASSERT(m_State == AGENT_STATE_FREE);
  410. switch (m_State)
  411. {
  412. case AGENT_STATE_REQUESTED:
  413. case AGENT_STATE_BUSY:
  414. case AGENT_STATE_REPOSE:
  415. case AGENT_STATE_POST_PROCESSING:
  416. case AGENT_STATE_LOGOUT:
  417. return FALSE;
  418. break;
  419. }
  420. __setTimer(TIMER_LOCK_PERIOD, CConfig::agentLockedPeriod() * 1000); // 被请求超时处理定时器
  421. m_State = AGENT_STATE_REQUESTED;
  422. }
  423. break;
  424. default:
  425. {
  426. switch (m_State)
  427. {
  428. case AGENT_STATE_BUSY:
  429. __onStatusUpdate(AGENT_STATE_BUSY, false);
  430. break;
  431. case AGENT_STATE_POST_PROCESSING:
  432. {
  433. __killTimer(TIMER_POST_PROCESSING);
  434. __onStatusUpdate(AGENT_STATE_POST_PROCESSING, false);
  435. }
  436. break;
  437. case AGENT_STATE_REPOSE:
  438. {
  439. m_IsRepose = false;
  440. __onStatusUpdate(AGENT_STATE_REPOSE, false);
  441. }
  442. break;
  443. case AGENT_STATE_REQUESTED:
  444. __killTimer(TIMER_LOCK_PERIOD);
  445. break;
  446. }
  447. m_State = a_AgentState;
  448. }
  449. break;
  450. } // end switch
  451. // 通知座席当前状态变化
  452. __reportStatus();
  453. return TRUE;
  454. }
  455. /*****************************************************************
  456. **【函数名称】 onAssoExtStatusUpdated
  457. **【函数功能】 关联分机状态更新的处理函数
  458. **【参数】 a_ExtState:分机当前状态
  459. Param:附加参数
  460. **【返回值】
  461. ****************************************************************/
  462. void CAgent::onAssoExtStatusUpdated(INNER_STATE a_ExtState, PARAM Param /*= NULL*/)
  463. {
  464. CPduEntity * pCmd = (CPduEntity *)Param;
  465. m_AssoExtState = a_ExtState;
  466. switch (a_ExtState)
  467. {
  468. case INNER_STATE_ALERTING:
  469. {
  470. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE || m_State == AGENT_STATE_REQUESTED)
  471. setState(AGENT_STATE_FREE, true);
  472. }
  473. break;
  474. case INNER_STATE_RING_BACK:
  475. {
  476. if (m_State == AGENT_STATE_POST_PROCESSING || m_State == AGENT_STATE_REPOSE || m_State == AGENT_STATE_REQUESTED)
  477. setState(AGENT_STATE_FREE, true);
  478. }
  479. break;
  480. case INNER_STATE_TALKING:
  481. {
  482. if (pCmd == NULL || pCmd->GetDataUInt(10) != PDU_CMD_AGENT_MONI_REPLACE) // 如果是代接操作则不记录应答次数
  483. m_AnswerCount++; // 累计应答计数
  484. setState(AGENT_STATE_BUSY, true);
  485. }
  486. break;
  487. case INNER_STATE_FREE:
  488. {
  489. if (m_State == AGENT_STATE_BUSY)
  490. {
  491. ASSERT(pCmd != NULL);
  492. // 关联线路为非内线,最后通话分机为当前分机,则需要进行话后处理
  493. if (pCmd != NULL && pCmd->GetDataUInt(7) != DEV_RES_TYPE_EXT && pCmd->GetDataUInt(9) == m_Exten)
  494. setState(AGENT_STATE_POST_PROCESSING);
  495. else
  496. setState(AGENT_STATE_FREE, true);
  497. }
  498. else if (m_State == AGENT_STATE_UNKNOWN || m_State == AGENT_STATE_REQUESTED)
  499. setState(AGENT_STATE_FREE, true);
  500. }
  501. break;
  502. default:
  503. {
  504. if (m_State == AGENT_STATE_UNKNOWN)
  505. setState(AGENT_STATE_FREE);
  506. }
  507. break;
  508. }
  509. }
  510. /*****************************************************************
  511. **【函数名称】 lock
  512. **【函数功能】 锁定座席
  513. **【参数】
  514. **【返回值】
  515. ****************************************************************/
  516. BOOL CAgent::lock(void)
  517. {
  518. if (isFree())
  519. return setState(AGENT_STATE_REQUESTED);
  520. else
  521. return FALSE;
  522. }
  523. void CAgent::GetAgentProperty(CAgentProperty& AgentProperty)
  524. {
  525. AgentProperty.m_AnswerCount = m_AnswerCount;
  526. AgentProperty.m_ReposeCount = m_ReposeCount;
  527. AgentProperty.m_TimeFree = m_TimeFree;
  528. AgentProperty.m_TimePostProcessing = m_TimePostProcessing;
  529. AgentProperty.m_TimeRepos = m_TimeRepos;
  530. AgentProperty.m_TimeTalk = m_TimeTalk;
  531. }
  532. bool CAgent::queueJump()
  533. {
  534. if (m_bFirstQueue) {
  535. m_bFirstQueue = false;
  536. return true;
  537. }
  538. else
  539. {
  540. return false;
  541. }
  542. }