驻马店视频中间件项目,与标准版stand区分

AcdCore.cpp 32KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. #include "StdAfx.h"
  2. #include "AcdCore.h"
  3. #include "Config.h"
  4. #include "Agent.h"
  5. #include "Exten.h"
  6. #include "NetworkAcd.h"
  7. #include "MsgCenter.h"
  8. #include "../Public/Auth/AuthMgr.h"
  9. #include "../Public/DaemonClient/DaemonClient.h"
  10. #include "SoftAuther.h"
  11. SINGLETON_IMPLEMENT(CAcdCore)
  12. CAcdCore::CAcdCore(void) : m_SubjectRepository(&m_AgentOffice, &m_ExtenCtrl, &m_QueueMgr)
  13. {
  14. //AllocConsole();//为当前的窗口程序申请一个Console窗口
  15. //freopen("CONOUT$", "w+", stdout);
  16. }
  17. CAcdCore::~CAcdCore(void)
  18. {
  19. }
  20. /*****************************************************************
  21. **【函数名称】 __onAgentStateUpdated
  22. **【函数功能】 座席状态变化事件响应
  23. **【参数】 AgentId: 座席工号
  24. ExtId: 分机号
  25. Status: 座席当前状态
  26. **【返回值】
  27. ****************************************************************/
  28. void CAcdCore::__onAgentStateUpdated( UINT AgentId )
  29. {
  30. CAgent* pAgent = m_AgentOffice.getAgentById(AgentId);
  31. if(pAgent == NULL)
  32. return;
  33. AGENT_STATE State = pAgent->state();
  34. // 通知事件订阅
  35. m_SubjectRepository.onAgentStateUpdated(pAgent->id(), pAgent->assoExten(), State);
  36. // 如果有座席变为空闲,通知来电队列刷新排队
  37. if(State == AGENT_STATE_FREE)
  38. m_QueueMgr.onAgentFree(pAgent);
  39. }
  40. /*****************************************************************
  41. **【函数名称】 __onPhoneStateUpdated
  42. **【函数功能】 分机状态变化事件响应
  43. **【参数】 AgentId: 座席工号
  44. ExtId: 分机号
  45. Status: 座席当前状态
  46. **【返回值】
  47. ****************************************************************/
  48. void CAcdCore::__onPhoneStateUpdated( UINT ExtenId )
  49. {
  50. CExten* pExten = m_ExtenCtrl.getExten(ExtenId);
  51. if(pExten == NULL)
  52. return;
  53. // 通知事件订阅
  54. m_SubjectRepository.onPhoneStateUpdated(pExten->assoAgent(), pExten->id(), pExten->state());
  55. // 2022-09-01 驻马店 保存分机号,坐席状态
  56. m_DepttelextOffice.UpdateDepttelext(pExten->id(), pExten->state());
  57. }
  58. /*****************************************************************
  59. **【函数名称】 __onQueueStateUpdated
  60. **【函数功能】 排队状态变化事件响应
  61. **【参数】 Count: 等待排队的呼叫数量
  62. **【返回值】
  63. ****************************************************************/
  64. void CAcdCore::__onQueueStateUpdated( UINT QueueNo )
  65. {
  66. UINT Count = m_QueueMgr.callCount(QueueNo);
  67. // 通知事件订阅
  68. m_SubjectRepository.onQueueStateUpdated(QueueNo, Count);
  69. }
  70. /*****************************************************************
  71. **【函数名称】 __removeAgent
  72. **【函数功能】 关闭指定座席
  73. **【参数】 AgentId: 要关闭座席的工号
  74. ExtId: 要关闭座席的分机号
  75. HostAgent: 主控制坐席工号
  76. **【返回值】
  77. ****************************************************************/
  78. void CAcdCore::__removeAgent( UINT AgentId, UINT ExtId, UINT HostAgent )
  79. {
  80. if(!m_AgentOffice.isAgentExisted(AgentId))
  81. return;
  82. // 清空对应的座席信息
  83. m_ExtenCtrl.setAssoAgent(ExtId, 0); // 清除关联分机
  84. m_SubjectRepository.clearObserver(AgentId); // 清除订阅信息
  85. m_AgentOffice.removeAgent(AgentId, HostAgent); // 清除对应座席
  86. }
  87. /*****************************************************************
  88. **【函数名称】 __onCmdAgentReg
  89. **【函数功能】 PDU注册命令
  90. **【参数】 a_pCmd: PDU命令内容
  91. **【返回值】
  92. ****************************************************************/
  93. void CAcdCore::__onCmdAgentReg( CPduEntity* a_pCmd )
  94. {
  95. if(a_pCmd->GetLocalDevType() == PDU_DEV_TYPE_AGENT) // 仅处理座席注册
  96. {
  97. // 获取发送方的IP
  98. CString PeerIp = _T("");
  99. CNetworkAcd::GetInstance().getPduSource(a_pCmd, PeerIp);
  100. // 是否为相同主机的座席重复签入
  101. UINT AgentId = a_pCmd->GetLocalDevId();
  102. if(m_AgentOffice.isAgentExisted(AgentId, PeerIp))
  103. {
  104. //关闭原座席
  105. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%ld]重复登录, IP Address = %s"), AgentId, PeerIp);
  106. __removeAgent(AgentId, m_AgentOffice.getAgentAssoExten(AgentId), 0);
  107. } // end if
  108. // 查找当前座席是否已注册
  109. if(m_AgentOffice.isAgentExisted(AgentId))
  110. a_pCmd->SetDataBool(0, false);
  111. else
  112. a_pCmd->SetDataBool(0, true);
  113. // 返回执行结果
  114. a_pCmd->SetToExecReturn();
  115. CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  116. } // end if
  117. else if (a_pCmd->GetLocalDevType()==PDU_DEV_TYPE_SERVER)
  118. {
  119. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("-------------------Server已连接---------------------------"));
  120. a_pCmd->SetToExecReturn();
  121. a_pCmd->SetDataBool(0, true);
  122. CInterfaceWindow::getIocpCommInstance()->Send(a_pCmd, PDU_DEV_TYPE_SERVER, 0);
  123. }
  124. }
  125. /*****************************************************************
  126. **【函数名称】 __onCmdAgentDial
  127. **【函数功能】 处理呼叫相关的命令
  128. **【参数】 a_pCmd: PDU命令内容
  129. **【返回值】
  130. ****************************************************************/
  131. void CAcdCore::__onCmdAgentDial( CPduEntity* a_pCmd )
  132. {
  133. if(a_pCmd->GetIsExecReturn()) // CTI -> Agent 的返回命令
  134. {
  135. UINT DestDevId = a_pCmd->GetDataUInt(2);
  136. //CNetworkAcd::GetInstance().send2Agent(DestDevId, a_pCmd);
  137. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  138. }
  139. else // Agent -> CTI 的请求命令
  140. {
  141. CString DestNum = _T("");
  142. CString CmdHint = _T("");
  143. UINT AgentId = a_pCmd->GetDataUInt(2);
  144. switch(a_pCmd->GetCmdType())
  145. {
  146. case PDU_CMD_AGENT_TRANSTALK: // 座席转移
  147. {
  148. CmdHint = _T("座席转移");
  149. DestNum = a_pCmd->GetDataString(3);
  150. }
  151. break;
  152. case PDU_CMD_AGENT_THREETALK: // 三方会议
  153. {
  154. CmdHint = _T("座席三方");
  155. DestNum = a_pCmd->GetDataString(3);
  156. }
  157. break;
  158. case PDU_CMD_AGENT_CONSULTATION_CALL: // 协商呼叫
  159. {
  160. CmdHint = _T("座席协商");
  161. DestNum = a_pCmd->GetDataString(4);
  162. }
  163. break;
  164. case PDU_CMD_AGENT_MAKECALL: // 坐席外呼
  165. {
  166. CmdHint = _T("座席呼叫");
  167. DestNum = a_pCmd->GetDataString(4);
  168. // 如果主叫座席分机非空闲或摘机拨号,禁止呼出
  169. INNER_STATE ExtStatus = m_ExtenCtrl.getExtenState(a_pCmd->GetDataUInt(1));
  170. if (ExtStatus != INNER_STATE_FREE || ExtStatus == INNER_STATE_INIT)
  171. {
  172. a_pCmd->SetToExecReturn();
  173. a_pCmd->SetDataBool(0, false);
  174. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  175. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  176. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%ld]请求呼叫失败, 关联分机非空闲"), AgentId);
  177. return; // 不再向CTI转发
  178. } // end if
  179. if(!m_AgentOffice.setAgentState4Calling(AgentId))
  180. {
  181. a_pCmd->SetToExecReturn();
  182. a_pCmd->SetDataBool(0, false);
  183. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  184. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  185. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%u]请求呼叫失败, 座席状态异常或已被锁定"), AgentId);
  186. return; // 不再向CTI转发
  187. }
  188. }
  189. break;
  190. } // end switch
  191. if(!CConfig::isMatchCallPrefix(DestNum)) // 呼叫分机
  192. {
  193. if (false == m_ExtenCtrl.isExtenExisted(atoi(DestNum))) // 分机号不存在
  194. {
  195. a_pCmd->SetToExecReturn();
  196. a_pCmd->SetDataBool(0, false);
  197. // CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  198. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  199. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 请求呼叫分机 %s 失败,分机号不存在"), DestNum);
  200. return; // 不再向CTI转发
  201. }
  202. // 查找要呼叫的分机座席工号
  203. UINT DestAgentId = m_ExtenCtrl.getAssoAgent(atoi(DestNum));
  204. if(m_AgentOffice.isAgentExisted(DestAgentId) && !m_AgentOffice.lockAgent(DestAgentId)) // 被叫叫座席非空闲
  205. {
  206. a_pCmd->SetToExecReturn();
  207. a_pCmd->SetDataBool(0, false);
  208. // CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  209. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  210. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%u]请求呼叫失败, 目标座席[%u]非空闲,[%d]"), AgentId, DestAgentId, m_AgentOffice.getAgentState(DestAgentId));
  211. return; // 不再向CTI转发
  212. }
  213. } // end if
  214. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%s], Agent = %lu, Exten = %lu, Dest Number = %s"),
  215. CmdHint, AgentId, a_pCmd->GetDataUInt(1), DestNum);
  216. CNetworkAcd::GetInstance().send2Cti(a_pCmd);
  217. } // end if
  218. }
  219. /*****************************************************************
  220. **【函数名称】 __onCmdAgentLogin
  221. **【函数功能】 座席签入命令
  222. **【参数】 a_pCmd: PDU命令内容
  223. **【返回值】
  224. ****************************************************************/
  225. void CAcdCore::__onCmdAgentLogin( CPduEntity* a_pCmd )
  226. {
  227. // 得到座席签入信息
  228. UINT ExtId = a_pCmd->GetDataUInt(1);
  229. UINT AgentId = a_pCmd->GetDataUInt(2);
  230. CString Group = a_pCmd->GetDataString(3);
  231. UINT AgentType = a_pCmd->GetDataUInt(4);
  232. UINT TimePostProcessing = a_pCmd->GetDataUInt(5);
  233. // 显示日志
  234. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL,
  235. _T("{Core}: AGENT -> ACD, CMD = [座席签入], Agent = %lu, Exten = %lu, Group = %s, Type = %lu"), AgentId, ExtId, Group, AgentType);
  236. // 校验
  237. bool IsSucceed = false;
  238. if(!CNetworkAcd::GetInstance().isCtiConnected()) // CTI是否已连接
  239. {
  240. a_pCmd->SetDataBool(0, false);
  241. a_pCmd->SetDataUInt(6, LOGIN_ERR_NO_CTI);
  242. }
  243. //#ifndef _DEBUG
  244. else if(m_AgentOffice.getAgentCount() >= m_Auther.GetAgentCount()) //ACD 授权数量验证
  245. {
  246. a_pCmd->SetDataBool(0, false);
  247. a_pCmd->SetDataUInt(6, LOGIN_ERR_AUTH_FAILED);
  248. }
  249. //#endif
  250. else if(!m_ExtenCtrl.isExtenExisted(ExtId)) // 查找要签入的分机是否存在
  251. {
  252. a_pCmd->SetDataBool(0, false);
  253. a_pCmd->SetDataUInt(6, LOGIN_ERR_NO_EXT);
  254. }
  255. else if(m_ExtenCtrl.isExtenUsed(ExtId)) // 分机是否已被占用
  256. {
  257. //a_pCmd->SetDataBool(0, false);
  258. //a_pCmd->SetDataUInt(6, LOGIN_ERR_BIND_EXT);
  259. UINT AgentID = m_ExtenCtrl.getAssoAgent(ExtId);
  260. __removeAgent(AgentID, ExtId, AgentID);
  261. a_pCmd->SetDataBool(0, true);
  262. IsSucceed = true;
  263. }
  264. else // 可以签入
  265. {
  266. a_pCmd->SetDataBool(0, true);
  267. IsSucceed = true;
  268. } // end if
  269. // 如果签入执行成功
  270. if(IsSucceed)
  271. {
  272. // 生成座席实例
  273. INNER_STATE ExtStatus = m_ExtenCtrl.getExtenState(ExtId);
  274. if(!m_AgentOffice.insertAgent(AgentId, ExtId, Group, AgentType, TimePostProcessing, ExtStatus))
  275. {
  276. a_pCmd->SetDataBool(0, false);
  277. a_pCmd->SetDataUInt(6, LOGIN_ERR_BIND_AGENT);
  278. }
  279. else
  280. {
  281. // 通知CTI座席已签入
  282. CNetworkAcd::GetInstance().send2Cti(a_pCmd);
  283. CPduEntity pdu(PDU_CMD_AGENT_RESET);
  284. pdu.SetDataUInt(1,a_pCmd->GetDataUInt(1));
  285. pdu.SetDataUInt(2,a_pCmd->GetDataUInt(2));
  286. CNetworkAcd::GetInstance().send2Cti(&pdu);
  287. // 建立分机与座席的关联
  288. m_ExtenCtrl.setAssoAgent(ExtId, AgentId);
  289. }
  290. } // end if
  291. // 返回签入执行结果
  292. a_pCmd->SetToExecReturn();
  293. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  294. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  295. }
  296. /*****************************************************************
  297. **【函数名称】 __onCmdAgentLogout
  298. **【函数功能】 座席签出命令
  299. **【参数】 a_pCmd: PDU命令内容
  300. **【返回值】
  301. ****************************************************************/
  302. void CAcdCore::__onCmdAgentLogout( CPduEntity* a_pCmd )
  303. {
  304. // 得到座席信息
  305. UINT ExtId = a_pCmd->GetDataUInt(1);
  306. UINT AgentId = a_pCmd->GetDataUInt(2);
  307. // 显示日志
  308. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席签出], Agent = %lu, Exten = %lu"), AgentId, ExtId);
  309. // ych 2018.5.16
  310. // m_AgentOffice.setAgentState(AgentId, AGENT_STATE_LOGOUT);
  311. if (m_AgentOffice.setAgentState(AgentId, AGENT_STATE_LOGOUT))
  312. {
  313. a_pCmd->SetDataBool(0, true);
  314. }
  315. else
  316. {
  317. a_pCmd->SetDataBool(0, false);
  318. //tj 通知Server
  319. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  320. return;
  321. }
  322. // 通知CTI座席签出
  323. CNetworkAcd::GetInstance().send2Cti(a_pCmd);
  324. //tj 通知Server
  325. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  326. // 清空对应的座席信息
  327. Sleep(100);
  328. __removeAgent(AgentId, ExtId, AgentId);
  329. }
  330. /*****************************************************************
  331. **【函数名称】 __onCmdAgentSetState
  332. **【函数功能】 主动设置座席状态
  333. **【参数】 a_pCmd: PDU命令内容
  334. **【返回值】
  335. ****************************************************************/
  336. void CAcdCore::__onCmdAgentSetState( CPduEntity* a_pCmd )
  337. {
  338. // 得到座席信息
  339. UINT AgentId = a_pCmd->GetDataUInt(2);
  340. AGENT_STATE State = static_cast<AGENT_STATE>(a_pCmd->GetDataUInt(3));
  341. // 显示日志
  342. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席状态设置], Agent = %lu, State = %d"), AgentId, State);
  343. // 设置座席逻辑状态
  344. if(m_AgentOffice.setAgentState(AgentId, State))
  345. a_pCmd->SetDataBool(0, true);
  346. else
  347. a_pCmd->SetDataBool(0, false);
  348. // 返回执行结果
  349. a_pCmd->SetToExecReturn();
  350. //CNetworkAcd::GetInstance().send2Agent(a_pCmd->GetLocalDevId(), a_pCmd);
  351. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  352. }
  353. /*****************************************************************
  354. **【函数名称】 __onCmdAgentSubscribe
  355. **【函数功能】 订阅管理
  356. **【参数】 a_pCmd: PDU命令内容
  357. **【返回值】
  358. ****************************************************************/
  359. void CAcdCore::__onCmdAgentSubscribe( CPduEntity* a_pCmd )
  360. {
  361. UINT AgentId = a_pCmd->GetDataUInt(2);
  362. SUBJECT_TYPE Type = static_cast<SUBJECT_TYPE>(a_pCmd->GetDataUInt(4));
  363. int PduType;
  364. // 订阅管理
  365. switch(a_pCmd->GetCmdType())
  366. {
  367. case PDU_CMD_AGENT_SUBSCRIBE: // 事件订阅
  368. PduType = 1;
  369. m_SubjectRepository.registObserver(AgentId, Type, a_pCmd->GetDataInt(3));
  370. break;
  371. case PDU_CMD_AGENT_CANCEL_SUBSCRIBE:// 取消订阅
  372. PduType = 2;
  373. m_SubjectRepository.removeObserver(AgentId, Type, a_pCmd->GetDataInt(3));
  374. break;
  375. } // end switch
  376. // 显示日志
  377. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席订阅], Agent = %lu, mode(1-订阅 2-取消) = %d, Type = %d"),
  378. AgentId, PduType, Type);
  379. }
  380. /*****************************************************************
  381. **【函数名称】 __onCmdAgentForceLogout
  382. **【函数功能】 强制签出指定座席
  383. **【参数】 a_pCmd: PDU命令内容
  384. **【返回值】
  385. ****************************************************************/
  386. void CAcdCore::__onCmdAgentForceLogout( CPduEntity* a_pCmd )
  387. {
  388. // 得到主控座席和受控座席信息
  389. UINT HostAgentId = a_pCmd->GetDataUInt(2);
  390. UINT TargetAgentId = a_pCmd->GetDataUInt(4);
  391. // 显示日志
  392. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席强制签出], Agent = %lu, TargetAgent = %lu"), HostAgentId, TargetAgentId);
  393. // 座席是否已签入
  394. if(!m_AgentOffice.isAgentExisted(TargetAgentId))
  395. {
  396. a_pCmd->SetDataBool(0, false);
  397. // 坐席不存在的情况下对坐席操作的错误日志
  398. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 强制坐席[%d]签出失败, 坐席[%d]未签入"), TargetAgentId, TargetAgentId);
  399. }
  400. else
  401. {
  402. // 通知被签出座席
  403. //CNetworkAcd::GetInstance().send2Agent(TargetAgentId, a_pCmd);
  404. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  405. UINT TargetExtId = m_AgentOffice.getAgentAssoExten(TargetAgentId);
  406. // 发送重置命令到CTI
  407. CPduEntity cmd(PDU_CMD_AGENT_RESET);
  408. cmd.SetDataUInt(1, TargetExtId);
  409. cmd.SetDataUInt(2, TargetAgentId);
  410. CNetworkAcd::GetInstance().send2Cti(&cmd);
  411. a_pCmd->SetDataBool(0, true);
  412. // 关闭座席
  413. __removeAgent(TargetAgentId, TargetExtId, HostAgentId);
  414. } // end if
  415. // 返回执行结果
  416. a_pCmd->SetToExecReturn();
  417. CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
  418. }
  419. /*****************************************************************
  420. **【函数名称】 __onCmdAgentMonControl
  421. **【函数功能】 班长电话控制
  422. **【参数】 a_pCmd: PDU命令内容
  423. **【返回值】
  424. ****************************************************************/
  425. void CAcdCore::__onCmdAgentMonControl( CPduEntity* a_pCmd )
  426. {
  427. if(!a_pCmd->GetIsExecReturn()) // OCX发出的命令
  428. {
  429. // 得到主控座席和受控座席信息
  430. UINT HostAgentId = a_pCmd->GetDataUInt(2);
  431. UINT TargetAgentId = a_pCmd->GetDataUInt(4);
  432. // 显示日志
  433. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%d](班长控制), Agent = %lu, TargetAgent = %lu"),
  434. a_pCmd->GetCmdType(), HostAgentId, TargetAgentId);
  435. // 确定目标座席已签入
  436. if(!m_AgentOffice.isAgentExisted(TargetAgentId))
  437. {
  438. // 添加坐席不存在的情况下对坐席操作的错误日志
  439. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 班长[%d]对坐席[%d]执行[%d]控制失败, 目标坐席未签入"),
  440. HostAgentId, TargetAgentId, a_pCmd->GetCmdType());
  441. // 返回执行结果
  442. a_pCmd->SetDataBool(0, false);
  443. a_pCmd->SetToExecReturn();
  444. //CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
  445. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  446. return;
  447. }
  448. // 确保班长座席状态空闲
  449. if (!m_AgentOffice.setAgentState(HostAgentId, AGENT_STATE_FREE))
  450. {
  451. // 添加坐席不存在的情况下对坐席操作的错误日志
  452. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 班长[%d]对坐席[%d]执行[%d]控制失败, 班长状态非空闲"),
  453. HostAgentId, TargetAgentId, a_pCmd->GetCmdType());
  454. a_pCmd->SetDataBool(0, false);
  455. a_pCmd->SetToExecReturn();
  456. // CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
  457. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  458. return;
  459. }
  460. // 转发命令到CTI
  461. a_pCmd->SetDataUInt(3, m_AgentOffice.getAgentAssoExten(TargetAgentId));
  462. CNetworkAcd::GetInstance().send2Cti(a_pCmd);
  463. }
  464. else // CTI的执行结果返回
  465. {
  466. //CNetworkAcd::GetInstance().send2Agent(a_pCmd->GetDataUInt(2), a_pCmd);
  467. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  468. } // end if
  469. }
  470. /*****************************************************************
  471. **【函数名称】 __onCmdAgentForceState
  472. **【函数功能】 强制座席状态控制
  473. **【参数】 a_pCmd PDU命令内容
  474. **【返回值】
  475. ****************************************************************/
  476. void CAcdCore::__onCmdAgentForceState( CPduEntity* a_pCmd )
  477. {
  478. // 得到主控座席和受控座席信息
  479. UINT HostAgentId = a_pCmd->GetDataUInt(2);
  480. UINT TargetAgentId = a_pCmd->GetDataUInt(4);
  481. AGENT_STATE State = static_cast<AGENT_STATE>(a_pCmd->GetDataUInt(5));
  482. // 显示日志
  483. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席强制状态转换], Agent = %lu, TargetAgent = %lu, State = %d"),
  484. HostAgentId, TargetAgentId, State);
  485. // 座席是否已签入
  486. if(!m_AgentOffice.isAgentExisted(TargetAgentId))
  487. {
  488. a_pCmd->SetDataBool(0, false);
  489. // 添加坐席不存在的情况下对坐席操作的错误日志
  490. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 对坐席[%d]执行强制状态转换失败, 目标坐席没有签入"), TargetAgentId);
  491. }
  492. else
  493. {
  494. // 改变受控座席状态
  495. if(m_AgentOffice.setAgentState(TargetAgentId, State))
  496. a_pCmd->SetDataBool(0, true);
  497. else
  498. a_pCmd->SetDataBool(0, false);
  499. } // end if
  500. // 返回执行结果
  501. a_pCmd->SetToExecReturn();
  502. //CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
  503. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  504. }
  505. /*****************************************************************
  506. **【函数名称】 __onCmdCtiExtenInfo
  507. **【函数功能】 内线分机状态变化命令
  508. **【参数】 a_pCmd: PDU命令内容
  509. **【返回值】
  510. ****************************************************************/
  511. void CAcdCore::__onCmdCtiExtenInfo( CPduEntity* a_pCmd )
  512. {
  513. UINT ExtID = a_pCmd->GetDataUInt(0);
  514. UINT State = a_pCmd->GetDataUInt(1);
  515. UINT Agentid = m_ExtenCtrl.getAssoAgent(ExtID); // 坐席工号
  516. if(State == INNER_STATE_REMOVE)
  517. {
  518. if (ExtID != 0)
  519. {
  520. if (Agentid != 0)
  521. __removeAgent(Agentid, ExtID, 0); // 迁出坐席
  522. //删除分机
  523. m_ExtenCtrl.removeExten(ExtID);
  524. }
  525. }
  526. else
  527. {
  528. // 显示日志
  529. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [线路状态信息], Exten = %lu, State = %lu"), ExtID, State);
  530. // 通知分机管理类
  531. m_ExtenCtrl.onExtenStateUpdated(a_pCmd);
  532. if (Agentid != 0)
  533. {
  534. m_AgentOffice.onExtenStateUpdated(Agentid, a_pCmd); // 通知座席管理类。报坐席和分机状态
  535. }
  536. }
  537. }
  538. /*****************************************************************
  539. **【函数名称】 __onCmdCtiRecord
  540. **【函数功能】 CTI通知座席录音信息
  541. **【参数】 a_pCmd: PDU命令内容
  542. **【返回值】
  543. ****************************************************************/
  544. void CAcdCore::__onCmdCtiRecord( CPduEntity* a_pCmd )
  545. {
  546. UINT Exten = a_pCmd->GetDataUInt(0);
  547. // 显示日志
  548. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [录音信息], Exten = %lu, CallId = %lu, FileName = %s"),
  549. Exten, a_pCmd->GetDataULong(1), a_pCmd->GetDataString(2));
  550. // 通过分机号查找对应的座席工号
  551. UINT AgentId = m_ExtenCtrl.getAssoAgent(Exten);
  552. if(AgentId != 0) // 有关联座席
  553. {
  554. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  555. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  556. }
  557. else // 录音未通知日志
  558. {
  559. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 录音信息[%s]未通知到坐席, 座席未签入"), a_pCmd->GetDataString(2));
  560. } // end if
  561. }
  562. /*****************************************************************
  563. **【函数名称】 __onCmdCtiDevCall
  564. **【函数功能】 CTI通知座席物理外呼信息
  565. **【参数】 a_pCmd: PDU命令内容
  566. **【返回值】
  567. ****************************************************************/
  568. void CAcdCore::__onCmdCtiDevCall( CPduEntity* a_pCmd )
  569. {
  570. UINT AgentId = a_pCmd->GetDataUInt(2);
  571. // 显示日志
  572. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [外呼信息], Exten = %lu, Agent = %lu, CallId = %lu, Number = %s"),
  573. a_pCmd->GetDataUInt(1), AgentId, a_pCmd->GetDataULong(3), a_pCmd->GetDataString(4));
  574. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  575. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  576. }
  577. /*****************************************************************
  578. **【函数名称】 __onCmdCtiTrunkUsage
  579. **【函数功能】 CTI通知呼叫任务中继利用率
  580. **【参数】 a_pCmd: PDU命令内容
  581. **【返回值】
  582. ****************************************************************/
  583. void CAcdCore::__onCmdCtiTrunkUsage( CPduEntity* a_pCmd )
  584. {
  585. UINT TaskId = a_pCmd->GetDataUInt(0);
  586. UINT Usage = a_pCmd->GetDataUInt(1);
  587. m_SubjectRepository.onTrunkUsageUpdated(TaskId, Usage);
  588. }
  589. /*****************************************************************
  590. **【函数名称】 __onCmdIvrQueue
  591. **【函数功能】 排队管理操作
  592. **【参数】 a_pCmd: PDU命令内容
  593. **【返回值】
  594. ****************************************************************/
  595. void CAcdCore::__onCmdIvrQueue( CPduEntity* a_pCmd )
  596. {
  597. PDU_CMD_TYPE CmdType = a_pCmd->GetCmdType();
  598. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [%d](来电排队)"), CmdType);
  599. switch(CmdType)
  600. {
  601. case PDU_CMD_IVR_WANT_AGENT: // IVR请求座席
  602. {
  603. m_QueueMgr.onQueueAsking(a_pCmd);
  604. }
  605. break;
  606. case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队
  607. {
  608. m_QueueMgr.onQueueContinue(a_pCmd);
  609. }
  610. break;
  611. case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
  612. {
  613. m_QueueMgr.onQueueCancel(a_pCmd);
  614. }
  615. break;
  616. case PDU_CMD_CTI_ACD_QUEUE_PAUSE: // CTI通知ACD暂停排队
  617. {
  618. m_QueueMgr.onQueuePause(a_pCmd);
  619. }
  620. break;
  621. } // end switch
  622. }
  623. /*****************************************************************
  624. **【函数名称】 __onCmdNeed2Forward
  625. **【函数功能】 处理Agent与CTI相与转发的命令
  626. **【参数】 a_pCmd: PDU命令内容
  627. **【返回值】
  628. ****************************************************************/
  629. void CAcdCore::__onCmdNeed2Forward( CPduEntity* a_pCmd )
  630. {
  631. if(a_pCmd->GetIsExecReturn()) // CTI -> Agent 的返回命令
  632. {
  633. UINT AgentId = a_pCmd->GetDataUInt(2);
  634. //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
  635. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  636. }
  637. else // Agent -> CTI 的请求命令
  638. {
  639. CNetworkAcd::GetInstance().send2Cti(a_pCmd);
  640. } // end if
  641. }
  642. void CAcdCore::__onCmdDataSendToAgent(CPduEntity * a_pCmd)
  643. {
  644. int count = a_pCmd->GetDataUInt(0);
  645. if (a_pCmd->GetCmdType() == PDU_CMD_CTI_TRUNKUSE_COUNT)
  646. {
  647. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}:收到中继利用数量: %d"),count);
  648. }
  649. else if (a_pCmd->GetCmdType() == PDU_CMD_IVR_WAITER_COUNT)
  650. {
  651. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}:收到等待数量: %d"),count);
  652. }
  653. std::vector<int> VecAgentID = m_AgentOffice.getAgentIDAll();
  654. bool isSuccess = CNetworkAcd::GetInstance().send2Server(a_pCmd);
  655. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}: 通知[%d][%s],当前数量:%d"), a_pCmd->GetCmdType(), isSuccess ? "成功" : "失败", count);
  656. }
  657. void CAcdCore::__onCmdGetAgentList(CPduEntity * a_pCmd)
  658. {
  659. CString szAgentList;
  660. m_AgentOffice.getAllAgentStateList(szAgentList);
  661. int t_agent_id = a_pCmd->GetDataUInt(1);
  662. if (!pushAgentList(t_agent_id, szAgentList.GetBuffer(0))) // 如果rcf失败在使用原来参数传递
  663. {
  664. if (szAgentList.GetLength() >= 512)
  665. {
  666. szAgentList = szAgentList.Left(511);
  667. ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("ACD -> HP-SERVER,坐席[%lu]获取坐席列表字符超出被截取 "), a_pCmd->GetDataUInt(1));
  668. }
  669. a_pCmd->SetDataString(2, szAgentList);
  670. }
  671. szAgentList.ReleaseBuffer();
  672. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  673. }
  674. void CAcdCore::__onCmdAgentReqExten(CPduEntity * a_pCmd)
  675. {
  676. uint32_t extenId;
  677. std::string pwd;
  678. bool ret = m_VideoOffice.findVideoExten(extenId,pwd);
  679. a_pCmd->SetDataBool(0, ret);
  680. a_pCmd->SetDataUInt(2, extenId);
  681. a_pCmd->SetDataString(3, CString(pwd.c_str()));
  682. std::cout << "{CAcdCore}" << extenId << "-" << pwd << std::endl;
  683. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  684. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "获取到的分机[%d][%s]", a_pCmd->GetDataUInt(2),a_pCmd->GetDataString(3));
  685. }
  686. void CAcdCore::__onCmdAgentReqAgent(CPduEntity * a_pCmd)
  687. {
  688. uint32_t agentId;
  689. uint32_t extenId;
  690. bool ret = m_AgentOffice.getFreeAgent(agentId,extenId);
  691. a_pCmd->SetDataBool(0, ret);
  692. a_pCmd->SetDataUInt(2, extenId);
  693. std::cout << agentId << "-" << extenId << std::endl;
  694. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  695. }
  696. void CAcdCore::__onCmdAgentRecoverAgent(CPduEntity * a_pCmd)
  697. {
  698. uint32_t extenId = a_pCmd->GetDataUInt(2);
  699. m_VideoOffice.recoverVideoExten(extenId);
  700. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  701. }
  702. void CAcdCore::__onCmdExtStateList(CPduEntity * a_pCmd)
  703. {
  704. std::string extStateList = m_DepttelextOffice.GetAllDeptTelext();
  705. pushZmdExtenStateList(extStateList);
  706. CNetworkAcd::GetInstance().send2Server(a_pCmd);
  707. }
  708. /*****************************************************************
  709. **【函数名称】 stage1Start
  710. **【函数功能】 第一阶段启动
  711. **【参数】
  712. **【返回值】
  713. ****************************************************************/
  714. bool CAcdCore::stage1Start( void )
  715. {
  716. // 连接配置数据库
  717. if(!IOtlConnection::getInstance()->Connect())
  718. {
  719. AfxMessageBox(STR_ERR_CORE_INIT_DB);
  720. return false;
  721. }
  722. // 加载配置
  723. if(!CConfig::load())
  724. {
  725. IOtlConnection::getInstance()->Disconnect();
  726. AfxMessageBox(STR_ERR_CORE_INIT_CFG);
  727. return false;
  728. }
  729. // 加载视频使用账号
  730. if (!m_VideoOffice.initVideoExten())
  731. {
  732. IOtlConnection::getInstance()->Disconnect();
  733. AfxMessageBox("加载视频账号配置信息失败");
  734. return false;
  735. }
  736. // 加载分机号部门信息失败
  737. if (!m_DepttelextOffice.InitDepttelext())
  738. {
  739. IOtlConnection::getInstance()->Disconnect();
  740. AfxMessageBox("加载分机部门信息失败");
  741. return false;
  742. }
  743. std::cout << m_DepttelextOffice.GetAllDeptTelext() << std::endl;
  744. return true;
  745. }
  746. /*****************************************************************
  747. **【函数名称】 stage2Start
  748. **【函数功能】 第二阶段启动
  749. **【参数】 ErrInfo: 出错信息
  750. **【返回值】
  751. ****************************************************************/
  752. bool CAcdCore::stage2Start( void )
  753. {
  754. // 建立网络通讯
  755. if(!CNetworkAcd::GetInstance().init())
  756. {
  757. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_ERROR, _T("%s"), STR_ERR_CORE_INIT_NETWORK);
  758. return false;
  759. }
  760. //#ifndef _DEBUG
  761. m_Auther.InitAutherData("C://Windows//mshy.dll");
  762. // m_Auther.__setTimer(86400000); //一天
  763. m_Auther.__setTimer(10000);
  764. //#endif
  765. CMsgCenter::GetInstance().regist(ACD_MSG_AGENT_STATE_UPDAET, this);
  766. CMsgCenter::GetInstance().regist(ACD_MSG_EXTEN_STATE_UPDATE, this);
  767. CMsgCenter::GetInstance().regist(ACD_MSG_QUEUE_UPDATE, this);
  768. CDaemonClient::GetInstance().doWork();
  769. return true;
  770. }
  771. void CAcdCore::reloadAuther()
  772. {
  773. m_Auther.InitAutherData("C://Windows//mshy.dll");
  774. }
  775. /*****************************************************************
  776. **【函数名称】 exit
  777. **【函数功能】 退出ACD
  778. **【参数】
  779. **【返回值】
  780. ****************************************************************/
  781. void CAcdCore::exit( void )
  782. {
  783. CNetworkAcd::GetInstance().release();
  784. m_QueueMgr.clear();
  785. m_AgentOffice.close();
  786. m_ExtenCtrl.removeExten();
  787. m_VideoOffice.close();
  788. IOtlConnection::getInstance()->Disconnect();
  789. }
  790. /*****************************************************************
  791. **【函数名称】 onNetLinkDown
  792. **【函数功能】 连接断开后续处理
  793. **【参数】
  794. **【返回值】
  795. ****************************************************************/
  796. void CAcdCore::onNetLinkDown( PduLinkContent linkContent )
  797. {
  798. if(linkContent.nFarType == PDU_DEV_TYPE_CTI) // 对CTI的处理
  799. {
  800. m_AgentOffice.clearAgent(); // 清空所有座席信息
  801. m_ExtenCtrl.removeExten(); // 清空所有分机信息
  802. m_QueueMgr.clear(); // 清空所有来电排队信息
  803. }
  804. else if(linkContent.nFarType == PDU_DEV_TYPE_AGENT) // 对Agent的处理
  805. {
  806. // 清空对应的座席信息
  807. UINT AssoExten = m_AgentOffice.getAgentAssoExten(linkContent.nFarId);
  808. __removeAgent(linkContent.nFarId, AssoExten, 0);
  809. } // end if
  810. }
  811. /*****************************************************************
  812. **【函数名称】 onRecvCommand
  813. **【函数功能】 PDU命令到达事件处理
  814. **【参数】
  815. **【返回值】
  816. ****************************************************************/
  817. void CAcdCore::onRecvCommand( CPduEntity* a_pPduEntity )
  818. {
  819. PDU_CMD_TYPE Type = a_pPduEntity->GetCmdType();
  820. ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, "OnHp-ServermsgRecmsg.PDU_TYPE= %d ", Type);
  821. switch(a_pPduEntity->GetCmdType())
  822. {
  823. case PDU_CMD_CTI_LINE_STATE: // CTI通知分机信息
  824. __onCmdCtiExtenInfo(a_pPduEntity);
  825. break;
  826. case PDU_CMD_CTI_ACD_TRUNK_USAGE: // CTI通知呼叫任务中继利用率
  827. __onCmdCtiTrunkUsage(a_pPduEntity);
  828. break;
  829. case PDU_CMD_AGENT_SETSTATE: // 设置座席状态
  830. __onCmdAgentSetState(a_pPduEntity);
  831. break;
  832. case PDU_CMD_IVR_WANT_AGENT: // IVR请求座席
  833. case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队
  834. case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
  835. case PDU_CMD_CTI_ACD_QUEUE_PAUSE: // CTI通知ACD暂停排队
  836. __onCmdIvrQueue(a_pPduEntity);
  837. break;
  838. case PDU_CMD_AGENT_RESET: // 座席重置
  839. case PDU_CMD_AGENT_ANSWER: // 座席应答
  840. case PDU_CMD_AGENT_HOLD: // 保持
  841. case PDU_CMD_AGENT_TAKEBACK: // 接回
  842. case PDU_CMD_AGENT_HANGUP: // 座席挂机
  843. case PDU_CMD_AGENT_CANCEL: // 坐席取消操作
  844. case PDU_CMD_AGENT_FAX: // 收发传真
  845. case PDU_CMD_AGENT_TURN_TO_IVR: // 转IVR
  846. case PDU_CMD_AGENT_CONFIRM_TRANSFER: // 确认转移
  847. case PDU_CMD_AGENT_MUTE: // 静音
  848. __onCmdNeed2Forward(a_pPduEntity);
  849. break;
  850. case PDU_CMD_AGENT_TRANSTALK: // 座席转移
  851. case PDU_CMD_AGENT_THREETALK: // 单步会议
  852. case PDU_CMD_AGENT_MAKECALL: // 坐席外呼
  853. case PDU_CMD_AGENT_CONSULTATION_CALL: // 协商呼叫
  854. __onCmdAgentDial(a_pPduEntity);
  855. break;
  856. case PDU_CMD_AGENT_MONI_LISTEN: // 监听
  857. case PDU_CMD_AGENT_MONI_INSERT: // 强插
  858. case PDU_CMD_AGENT_MONI_CUT: // 强拆
  859. case PDU_CMD_AGENT_MONI_REPLACE: // 代接
  860. case PDU_CMD_AGENT_MONI_INTERCEPT: // 强截
  861. __onCmdAgentMonControl(a_pPduEntity);
  862. break;
  863. case PDU_CMD_AGENT_MONI_FORCE_STATE: // 班长强制状态控制
  864. __onCmdAgentForceState(a_pPduEntity);
  865. break;
  866. case PDU_CMD_AGENT_MONI_FORCE_LOGOUT: // 强制签出
  867. __onCmdAgentForceLogout(a_pPduEntity);
  868. break;
  869. case PDU_CMD_AGENT_SUBSCRIBE: // 事件订阅
  870. case PDU_CMD_AGENT_CANCEL_SUBSCRIBE: // 取消订阅
  871. __onCmdAgentSubscribe(a_pPduEntity);
  872. break;
  873. case PDU_CMD_REG: // 注册命令
  874. __onCmdAgentReg(a_pPduEntity);
  875. break;
  876. case PDU_CMD_AGENT_LOGIN: // 座席签入
  877. __onCmdAgentLogin(a_pPduEntity);
  878. break;
  879. case PDU_CMD_AGENT_LOGOUT: // 座席签出
  880. __onCmdAgentLogout(a_pPduEntity);
  881. break;
  882. case PDU_CMD_CTI_DEV_CALL: // Cti通知物理外呼结果
  883. __onCmdCtiDevCall(a_pPduEntity);
  884. break;
  885. case PDU_CMD_CTI_RECORD: // CTI通知座席录音信息
  886. __onCmdCtiRecord(a_pPduEntity);
  887. break;
  888. case PDU_CMD_IVR_WAITER_COUNT: //向Agent转发的数据
  889. __onCmdDataSendToAgent(a_pPduEntity);
  890. break;
  891. case PDU_CMD_AGENT_GET_AGENTLIST:
  892. __onCmdGetAgentList(a_pPduEntity);
  893. break;
  894. case PDU_CMD_AGENT_VIDEO_REQ_EXTEN: // 请求注册视频分机号
  895. __onCmdAgentReqExten(a_pPduEntity);
  896. break;
  897. case PDU_CMD_AGENT_VIDEO_REQ_AGENT: // 请求空闲坐席
  898. __onCmdAgentReqAgent(a_pPduEntity);
  899. break;
  900. case PDU_CMD_AGENT_VIDEO_RECOVER_EXTEN: // 释放请求的视频分机号
  901. __onCmdAgentRecoverAgent(a_pPduEntity);
  902. break;
  903. case PDU_CMD_EXTEN_STATE_LIST_ZMD: // 分机状态列表
  904. __onCmdExtStateList(a_pPduEntity);
  905. break;
  906. default:
  907. return;
  908. } // end switch
  909. }
  910. /*****************************************************************
  911. **【函数名称】 onMessage
  912. **【函数功能】 系统消息处理
  913. **【参数】
  914. **【返回值】
  915. *****************************************************************/
  916. void CAcdCore::onMessage( UINT MsgType, const PARAM lpContent )
  917. {
  918. switch(MsgType)
  919. {
  920. case ACD_MSG_AGENT_STATE_UPDAET:
  921. __onAgentStateUpdated((UINT)lpContent);
  922. break;
  923. case ACD_MSG_EXTEN_STATE_UPDATE:
  924. __onPhoneStateUpdated((UINT)lpContent);
  925. break;
  926. case ACD_MSG_QUEUE_UPDATE:
  927. __onQueueStateUpdated((UINT)lpContent);
  928. break;
  929. }
  930. }