| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296 |
- #include "StdAfx.h"
- #include "AcdCore.h"
- #include "Config.h"
- #include "Agent.h"
- #include "Exten.h"
- #include "NetworkAcd.h"
- #include "MsgCenter.h"
- #include "../Public/Auth/AuthMgr.h"
- #include "../Public/DaemonClient/DaemonClient.h"
- #include "SoftAuther.h"
- #include "YamlConfig.h"
- #include "SqlWriter.h"
- SINGLETON_IMPLEMENT(CAcdCore)
- CAcdCore::CAcdCore(void) : m_SubjectRepository(&m_AgentOffice, &m_ExtenCtrl, &m_QueueMgr)
- {
- //AllocConsole();//为当前的窗口程序申请一个Console窗口
- //freopen("CONOUT$", "w+", stdout);
- }
- CAcdCore::~CAcdCore(void)
- {
- }
- /*****************************************************************
- **【函数名称】 __onAgentStateUpdated
- **【函数功能】 座席状态变化事件响应
- **【参数】 AgentId: 座席工号
- ExtId: 分机号
- Status: 座席当前状态
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onAgentStateUpdated( UINT AgentId )
- {
- CAgent* pAgent = m_AgentOffice.getAgentById(AgentId);
- if(pAgent == NULL)
- return;
- AGENT_STATE State = pAgent->state();
- // 通知事件订阅
- m_SubjectRepository.onAgentStateUpdated(pAgent->id(), pAgent->assoExten(), State, pAgent->group());
- // 如果有座席变为空闲,通知来电队列刷新排队
- if(State == AGENT_STATE_FREE)
- m_QueueMgr.onAgentFree(pAgent);
- }
- /*****************************************************************
- **【函数名称】 __onPhoneStateUpdated
- **【函数功能】 分机状态变化事件响应
- **【参数】 AgentId: 座席工号
- ExtId: 分机号
- Status: 座席当前状态
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onPhoneStateUpdated( UINT ExtenId )
- {
- CExten* pExten = m_ExtenCtrl.getExten(ExtenId);
- if(pExten == NULL)
- return;
- // 通知事件订阅
- m_SubjectRepository.onPhoneStateUpdated(pExten->assoAgent(), pExten->id(), pExten->state());
- }
- /*****************************************************************
- **【函数名称】 __onQueueStateUpdated
- **【函数功能】 排队状态变化事件响应
- **【参数】 Count: 等待排队的呼叫数量
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onQueueStateUpdated( UINT QueueNo )
- {
- UINT Count = m_QueueMgr.callCount(QueueNo);
-
- // 通知事件订阅
- m_SubjectRepository.onQueueStateUpdated(QueueNo, Count);
- }
- /*****************************************************************
- **【函数名称】 __removeAgent
- **【函数功能】 关闭指定座席
- **【参数】 AgentId: 要关闭座席的工号
- ExtId: 要关闭座席的分机号
- HostAgent: 主控制坐席工号
- **【返回值】
- ****************************************************************/
- void CAcdCore::__removeAgent( UINT AgentId, UINT ExtId, UINT HostAgent )
- {
- if(!m_AgentOffice.isAgentExisted(AgentId))
- return;
- // ych 2018.5.4 安图拷贝
- CAgent* pAgent = m_AgentOffice.getAgentById(AgentId);
- CAgentProperty AgentProperty;
- AgentProperty.pAgent = pAgent;
- pAgent->GetAgentProperty(AgentProperty);
- AgentProperty.m_FirstLogTimeToday = CTime::GetCurrentTime();
- m_AgentOffice.GetAgentPropertyMap().insert(pair<UINT, CAgentProperty>(AgentId, AgentProperty));
- // 清空对应的座席信息
- m_ExtenCtrl.setAssoAgent(ExtId, 0); // 清除关联分机
- m_SubjectRepository.clearObserver(AgentId); // 清除订阅信息
- m_AgentOffice.removeAgent(AgentId, HostAgent); // 清除对应座席
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentReg
- **【函数功能】 PDU注册命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentReg( CPduEntity* a_pCmd )
- {
- if(a_pCmd->GetLocalDevType() == PDU_DEV_TYPE_AGENT) // 仅处理座席注册
- {
- // 获取发送方的IP
- CString PeerIp = _T("");
- // CNetworkAcd::GetInstance().getPduSource(a_pCmd, PeerIp);
- // 是否为相同主机的座席重复签入
- UINT AgentId = a_pCmd->GetLocalDevId();
- if(m_AgentOffice.isAgentExisted(AgentId, PeerIp))
- {
- //关闭原座席
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%ld]重复登录, IP Address = %s"), AgentId, PeerIp);
- __removeAgent(AgentId, m_AgentOffice.getAgentAssoExten(AgentId), 0);
- } // end if
- // 查找当前座席是否已注册
- if(m_AgentOffice.isAgentExisted(AgentId))
- a_pCmd->SetDataBool(0, false);
- else
- a_pCmd->SetDataBool(0, true);
- // 返回执行结果
- a_pCmd->SetToExecReturn();
- CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- } // end if
- else if (a_pCmd->GetLocalDevType()==PDU_DEV_TYPE_SERVER)
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("-------------------Server已连接---------------------------"));
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, true);
- CNetInterface::getNetInstance()->Send(a_pCmd, PDU_DEV_TYPE_SERVER, 0);
- }
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentDial
- **【函数功能】 处理呼叫相关的命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentDial( CPduEntity* a_pCmd )
- {
- if(a_pCmd->GetIsExecReturn()) // CTI -> Agent 的返回命令
- {
- UINT DestDevId = a_pCmd->GetDataUInt(2);
- //CNetworkAcd::GetInstance().send2Agent(DestDevId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- else // Agent -> CTI 的请求命令
- {
- CString DestNum = _T("");
- CString CmdHint = _T("");
- UINT AgentId = a_pCmd->GetDataUInt(2);
- switch(a_pCmd->GetCmdType())
- {
- case PDU_CMD_AGENT_TRANSTALK: // 座席转移
- {
- CString transferType = a_pCmd->GetDataString(5);
- if (transferType == "1") //如果指定技能组转移,直接用以下函数处理
- {
- __onCmdAgentTransferSkillGroup(a_pCmd);
- return;
- }
- CmdHint = _T("座席转移");
- DestNum = a_pCmd->GetDataString(3);
- }
- break;
- case PDU_CMD_AGENT_THREETALK: // 三方会议
- {
- CmdHint = _T("座席三方");
- DestNum = a_pCmd->GetDataString(3);
- }
- break;
- case PDU_CMD_AGENT_CONSULTATION_CALL: // 协商呼叫
- {
- CmdHint = _T("座席协商");
- DestNum = a_pCmd->GetDataString(4);
- }
- break;
- case PDU_CMD_AGENT_MAKECALL: // 坐席外呼
- {
- CmdHint = _T("座席呼叫");
- DestNum = a_pCmd->GetDataString(4);
- // 如果主叫座席分机非空闲或摘机拨号,禁止呼出
- INNER_STATE ExtStatus = m_ExtenCtrl.getExtenState(a_pCmd->GetDataUInt(1));
- if (ExtStatus != INNER_STATE_FREE || ExtStatus == INNER_STATE_INIT)
- {
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, false);
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%ld]请求呼叫失败, 关联分机非空闲"), AgentId);
- return; // 不再向CTI转发
- } // end if
-
- if(!m_AgentOffice.setAgentState4Calling(AgentId))
- {
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, false);
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%u]请求呼叫失败, 座席状态异常或已被锁定"), AgentId);
- return; // 不再向CTI转发
- }
- }
- break;
- } // end switch
- if(!CConfig::isMatchCallPrefix(DestNum)) // 呼叫分机
- {
- if (false == m_ExtenCtrl.isExtenExisted(atoi(DestNum))) // 分机号不存在
- {
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, false);
- // CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 请求呼叫分机 %s 失败,分机号不存在"), DestNum);
- return; // 不再向CTI转发
- }
- // 查找要呼叫的分机座席工号
- UINT DestAgentId = m_ExtenCtrl.getAssoAgent(atoi(DestNum));
- if(m_AgentOffice.isAgentExisted(DestAgentId) && !m_AgentOffice.lockAgent(DestAgentId)) // 被叫叫座席非空闲
- {
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, false);
- // CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
-
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 座席[%u]请求呼叫失败, 目标座席[%u]非空闲,[%d]"), AgentId, DestAgentId, m_AgentOffice.getAgentState(DestAgentId));
- return; // 不再向CTI转发
- }
- } // end if
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%s], Agent = %lu, Exten = %lu, Dest Number = %s"),
- CmdHint, AgentId, a_pCmd->GetDataUInt(1), DestNum);
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- } // end if
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentLogin
- **【函数功能】 座席签入命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentLogin( CPduEntity* a_pCmd )
- {
- // 得到座席签入信息
- UINT ExtId = a_pCmd->GetDataUInt(1);
- UINT AgentId = a_pCmd->GetDataUInt(2);
- CString Group = a_pCmd->GetDataString(3);
- UINT AgentType = a_pCmd->GetDataUInt(4);
- UINT TimePostProcessing = a_pCmd->GetDataUInt(5);
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL,
- _T("{Core}: AGENT -> ACD, CMD = [座席签入], Agent = %lu, Exten = %lu, Group = %s, Type = %lu"), AgentId, ExtId, Group, AgentType);
- // 校验
- bool IsSucceed = false;
- if(!CNetworkAcd::GetInstance().isCtiConnected()) // CTI是否已连接
- {
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetDataUInt(6, LOGIN_ERR_NO_CTI);
- }
- //#ifndef _DEBUG
- else if(m_AgentOffice.getAgentCount() >= (UINT)m_Auther.GetAgentCount()) //ACD 授权数量验证
- {
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetDataUInt(6, LOGIN_ERR_AUTH_FAILED);
- }
- //#endif
- else if(!m_ExtenCtrl.isExtenExisted(ExtId)) // 查找要签入的分机是否存在
- {
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetDataUInt(6, LOGIN_ERR_NO_EXT);
- }
- else if(m_ExtenCtrl.isExtenUsed(ExtId)) // 分机是否已被占用
- {
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetDataUInt(6, LOGIN_ERR_BIND_EXT);
- /*
- UINT AgentID = m_ExtenCtrl.getAssoAgent(ExtId);
- __removeAgent(AgentID, ExtId, AgentID);
- CPduEntity cmd(PDU_CMD_AGENT_LOGOUT); // 2022-01-06 分机被挤掉,告诉被挤坐席迁出
- cmd.SetDataUInt(1, ExtId);
- cmd.SetDataUInt(2, AgentID);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- a_pCmd->SetDataBool(0, true);
- IsSucceed = true;
- */
- }
- else // 可以签入
- {
- a_pCmd->SetDataBool(0, true);
- IsSucceed = true;
- } // end if
- // 如果签入执行成功
- if(IsSucceed)
- {
- // 生成座席实例
- INNER_STATE ExtStatus = m_ExtenCtrl.getExtenState(ExtId);
- if(!m_AgentOffice.insertAgent(AgentId, ExtId, Group, AgentType, TimePostProcessing, ExtStatus))
- {
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetDataUInt(6, LOGIN_ERR_BIND_AGENT);
- }
- else
- {
- // 通知CTI座席已签入
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- CPduEntity pdu(PDU_CMD_AGENT_RESET);
- pdu.SetDataUInt(1,a_pCmd->GetDataUInt(1));
- pdu.SetDataUInt(2,a_pCmd->GetDataUInt(2));
- CNetworkAcd::GetInstance().send2Cti(&pdu);
- // 建立分机与座席的关联
- m_ExtenCtrl.setAssoAgent(ExtId, AgentId);
- }
- } // end if
- // 返回签入执行结果
- a_pCmd->SetToExecReturn();
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentLogout
- **【函数功能】 座席签出命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentLogout( CPduEntity* a_pCmd )
- {
- // 得到座席信息
- UINT ExtId = a_pCmd->GetDataUInt(1);
- UINT AgentId = a_pCmd->GetDataUInt(2);
- UINT Reason = a_pCmd->GetDataUInt(3); // HP-Server自己主动签出坐席 2019-12-3
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席签出], Agent = %lu, Exten = %lu"), AgentId, ExtId);
- // ych 2018.5.16
- // m_AgentOffice.setAgentState(AgentId, AGENT_STATE_LOGOUT);
- if (m_AgentOffice.setAgentState(AgentId, AGENT_STATE_LOGOUT, Reason == 3 ? true : false))
- {
- a_pCmd->SetDataBool(0, true);
- }
- else
- {
- a_pCmd->SetDataBool(0, false);
- //tj 通知Server
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- return;
- }
- // 通知CTI座席签出
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- //tj 通知Server
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- // 清空对应的座席信息
- Sleep(100);
- /*__removeAgent(AgentId, ExtId, AgentId);*/
- __removeAgent(AgentId, ExtId, Reason == 3 ? 3 : AgentId);
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentSetState
- **【函数功能】 主动设置座席状态
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentSetState( CPduEntity* a_pCmd )
- {
- // 得到座席信息
- UINT AgentId = a_pCmd->GetDataUInt(2);
- AGENT_STATE State = static_cast<AGENT_STATE>(a_pCmd->GetDataUInt(3));
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席状态设置], Agent = %lu, State = %d"), AgentId, State);
- // 设置座席逻辑状态
- if(m_AgentOffice.setAgentState(AgentId, State))
- a_pCmd->SetDataBool(0, true);
- else
- a_pCmd->SetDataBool(0, false);
- // 返回执行结果
- a_pCmd->SetToExecReturn();
- //CNetworkAcd::GetInstance().send2Agent(a_pCmd->GetLocalDevId(), a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentSubscribe
- **【函数功能】 订阅管理
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentSubscribe( CPduEntity* a_pCmd )
- {
- UINT AgentId = a_pCmd->GetDataUInt(2);
- SUBJECT_TYPE Type = static_cast<SUBJECT_TYPE>(a_pCmd->GetDataUInt(4));
- int PduType;
- // 订阅管理
- switch(a_pCmd->GetCmdType())
- {
- case PDU_CMD_AGENT_SUBSCRIBE: // 事件订阅
- PduType = 1;
- m_SubjectRepository.registObserver(AgentId, Type, a_pCmd->GetDataInt(3));
- break;
- case PDU_CMD_AGENT_CANCEL_SUBSCRIBE:// 取消订阅
- PduType = 2;
- m_SubjectRepository.removeObserver(AgentId, Type, a_pCmd->GetDataInt(3));
- break;
- } // end switch
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席订阅], Agent = %lu, mode(1-订阅 2-取消) = %d, Type = %d"),
- AgentId, PduType, Type);
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentForceLogout
- **【函数功能】 强制签出指定座席
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentForceLogout( CPduEntity* a_pCmd )
- {
- // 得到主控座席和受控座席信息
- UINT HostAgentId = a_pCmd->GetDataUInt(2);
- UINT TargetAgentId = a_pCmd->GetDataUInt(4);
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席强制签出], Agent = %lu, TargetAgent = %lu"), HostAgentId, TargetAgentId);
- // 座席是否已签入
- if(!m_AgentOffice.isAgentExisted(TargetAgentId))
- {
- a_pCmd->SetDataBool(0, false);
- // 坐席不存在的情况下对坐席操作的错误日志
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 强制坐席[%d]签出失败, 坐席[%d]未签入"), TargetAgentId, TargetAgentId);
- }
- else
- {
- if (m_AgentOffice.setAgentState(TargetAgentId, AGENT_STATE_LOGOUT))
- {
- a_pCmd->SetDataBool(0, true);
- }
- else
- {
- a_pCmd->SetDataBool(0, false);
- }
- UINT TargetExtId = m_AgentOffice.getAgentAssoExten(TargetAgentId);
- // 通知CTI座席签出
- CPduEntity cmd(PDU_CMD_AGENT_LOGOUT);
- cmd.SetDataUInt(1, TargetExtId);
- cmd.SetDataUInt(2, TargetAgentId);
- CNetworkAcd::GetInstance().send2Cti(&cmd);
- // 关闭座席
- __removeAgent(TargetAgentId, TargetExtId, HostAgentId);
- } // end if
- // 返回执行结果
- a_pCmd->SetToExecReturn();
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentMonControl
- **【函数功能】 班长电话控制
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentMonControl( CPduEntity* a_pCmd )
- {
- if(!a_pCmd->GetIsExecReturn()) // OCX发出的命令
- {
- // 得到主控座席和受控座席信息
- UINT HostAgentId = a_pCmd->GetDataUInt(2);
- UINT TargetAgentId = a_pCmd->GetDataUInt(4);
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%d](班长控制), Agent = %lu, TargetAgent = %lu"),
- a_pCmd->GetCmdType(), HostAgentId, TargetAgentId);
- // 确定目标座席已签入
- if(!m_AgentOffice.isAgentExisted(TargetAgentId))
- {
- // 添加坐席不存在的情况下对坐席操作的错误日志
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 班长[%d]对坐席[%d]执行[%d]控制失败, 目标坐席未签入"),
- HostAgentId, TargetAgentId, a_pCmd->GetCmdType());
- // 返回执行结果
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetToExecReturn();
- //CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- return;
- }
- // 确保班长座席状态空闲
- if (!m_AgentOffice.setAgentState(HostAgentId, AGENT_STATE_FREE))
- {
- // 添加坐席不存在的情况下对坐席操作的错误日志
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 班长[%d]对坐席[%d]执行[%d]控制失败, 班长状态非空闲"),
- HostAgentId, TargetAgentId, a_pCmd->GetCmdType());
- a_pCmd->SetDataBool(0, false);
- a_pCmd->SetToExecReturn();
- // CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- return;
- }
- // 转发命令到CTI
- a_pCmd->SetDataUInt(3, m_AgentOffice.getAgentAssoExten(TargetAgentId));
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- }
- else // CTI的执行结果返回
- {
- //CNetworkAcd::GetInstance().send2Agent(a_pCmd->GetDataUInt(2), a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- } // end if
- }
- /*****************************************************************
- **【函数名称】 __onCmdAgentForceState
- **【函数功能】 强制座席状态控制
- **【参数】 a_pCmd PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdAgentForceState( CPduEntity* a_pCmd )
- {
- // 得到主控座席和受控座席信息
- UINT HostAgentId = a_pCmd->GetDataUInt(2);
- UINT TargetAgentId = a_pCmd->GetDataUInt(4);
- AGENT_STATE State = static_cast<AGENT_STATE>(a_pCmd->GetDataUInt(5));
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [座席强制状态转换], Agent = %lu, TargetAgent = %lu, State = %d"),
- HostAgentId, TargetAgentId, State);
- // 座席是否已签入
- if(!m_AgentOffice.isAgentExisted(TargetAgentId))
- {
- a_pCmd->SetDataBool(0, false);
- // 添加坐席不存在的情况下对坐席操作的错误日志
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 对坐席[%d]执行强制状态转换失败, 目标坐席没有签入"), TargetAgentId);
- }
- else
- {
- // 改变受控座席状态
- if(m_AgentOffice.setAgentState(TargetAgentId, State))
- a_pCmd->SetDataBool(0, true);
- else
- a_pCmd->SetDataBool(0, false);
- } // end if
- // 返回执行结果
- a_pCmd->SetToExecReturn();
- //CNetworkAcd::GetInstance().send2Agent(HostAgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 __onCmdCtiExtenInfo
- **【函数功能】 内线分机状态变化命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdCtiExtenInfo( CPduEntity* a_pCmd )
- {
- UINT ExtID = a_pCmd->GetDataUInt(0);
- UINT State = a_pCmd->GetDataUInt(1);
- UINT Agentid = m_ExtenCtrl.getAssoAgent(ExtID); // 坐席工号
- if(State == INNER_STATE_REMOVE)
- {
- if (ExtID != 0)
- {
- if (Agentid != 0)
- __removeAgent(Agentid, ExtID, 0); // 迁出坐席
- //删除分机
- m_ExtenCtrl.removeExten(ExtID);
- }
- }
- else
- {
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [线路状态信息], Exten = %lu, State = %lu,ActionID = %d,TrunkNum = %s"), ExtID, State,a_pCmd->GetDataInt(11),a_pCmd->GetDataString(13));
- // 通知分机管理类
- m_ExtenCtrl.onExtenStateUpdated(a_pCmd);
- if (Agentid != 0)
- {
- m_AgentOffice.onExtenStateUpdated(Agentid, a_pCmd); // 通知座席管理类。报坐席和分机状态
- }
- }
- }
- /*****************************************************************
- **【函数名称】 __onCmdCtiRecord
- **【函数功能】 CTI通知座席录音信息
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdCtiRecord( CPduEntity* a_pCmd )
- {
- UINT Exten = a_pCmd->GetDataUInt(0);
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [录音信息], Exten = %lu, CallId = %lu, FileName = %s"),
- Exten, a_pCmd->GetDataULong(1), a_pCmd->GetDataString(2));
- // 通过分机号查找对应的座席工号
- UINT AgentId = m_ExtenCtrl.getAssoAgent(Exten);
- if(AgentId != 0) // 有关联座席
- {
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- else // 录音未通知日志
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{Core}: 录音信息[%s]未通知到坐席, 座席未签入"), a_pCmd->GetDataString(2));
- } // end if
- }
- /*****************************************************************
- **【函数名称】 __onCmdCtiDevCall
- **【函数功能】 CTI通知座席物理外呼信息
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdCtiDevCall( CPduEntity* a_pCmd )
- {
- UINT AgentId = a_pCmd->GetDataUInt(2);
- // 显示日志
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [外呼信息], Exten = %lu, Agent = %lu, CallId = %lu, Number = %s"),
- a_pCmd->GetDataUInt(1), AgentId, a_pCmd->GetDataULong(3), a_pCmd->GetDataString(4));
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- /*****************************************************************
- **【函数名称】 __onCmdCtiTrunkUsage
- **【函数功能】 CTI通知呼叫任务中继利用率
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdCtiTrunkUsage( CPduEntity* a_pCmd )
- {
- UINT TaskId = a_pCmd->GetDataUInt(0);
- UINT Usage = a_pCmd->GetDataUInt(1);
- m_SubjectRepository.onTrunkUsageUpdated(TaskId, Usage);
- }
- /*****************************************************************
- **【函数名称】 __onCmdIvrQueue
- **【函数功能】 排队管理操作
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdIvrQueue( CPduEntity* a_pCmd )
- {
- PDU_CMD_TYPE CmdType = a_pCmd->GetCmdType();
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: CTI -> ACD, CMD = [%d](来电排队)"), CmdType);
- switch(CmdType)
- {
- case PDU_CMD_IVR_WANT_AGENT: // IVR请求座席
- {
- m_QueueMgr.onQueueAsking(a_pCmd);
- }
- break;
- case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队
- {
- m_QueueMgr.onQueueContinue(a_pCmd);
- }
- break;
- case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
- {
- m_QueueMgr.onQueueCancel(a_pCmd);
- }
- break;
- case PDU_CMD_CTI_ACD_QUEUE_PAUSE: // CTI通知ACD暂停排队
- {
- m_QueueMgr.onQueuePause(a_pCmd);
- }
- break;
- } // end switch
- // 2022-04-02 呼入电话在对应坐席组的排队位置
- m_QueueMgr.onUpdateCallIndex();
- // 发送技能组排队情况
- __onCmdAgentSkillGroupWaitCount();
- }
- /*****************************************************************
- **【函数名称】 __onCmdNeed2Forward
- **【函数功能】 处理Agent与CTI相与转发的命令
- **【参数】 a_pCmd: PDU命令内容
- **【返回值】
- ****************************************************************/
- void CAcdCore::__onCmdNeed2Forward( CPduEntity* a_pCmd )
- {
- if(a_pCmd->GetIsExecReturn()) // CTI -> Agent 的返回命令
- {
- UINT AgentId = a_pCmd->GetDataUInt(2);
- //CNetworkAcd::GetInstance().send2Agent(AgentId, a_pCmd);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- else // Agent -> CTI 的请求命令
- {
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- } // end if
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%d], Agent = %lu, Exten = %lu"),
- a_pCmd->GetCmdType(), a_pCmd->GetDataUInt(2), a_pCmd->GetDataUInt(1));
- }
- void CAcdCore::__onCmdDataSendToAgent(CPduEntity * a_pCmd)
- {
- int count = a_pCmd->GetDataUInt(0);
- if (a_pCmd->GetCmdType() == PDU_CMD_CTI_TRUNKUSE_COUNT)
- {
- m_TrunkCount = count;
- m_TrunkCount = a_pCmd->GetDataUInt(1); // 当前中继呼入数量
- m_ExtCallOutCount = a_pCmd->GetDataUInt(2); // 当前外呼数量
- AgentRingCount = a_pCmd->GetDataUInt(3); // 当前坐席振铃数量
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}:收到中继利用数量: %d"),count);
- }
- else if (a_pCmd->GetCmdType() == PDU_CMD_IVR_WAITER_COUNT)
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}:收到等待数量: %d"),count);
- m_WaitCount = count;
- CString curDay;
- CTime tm;
- tm = CTime::GetCurrentTime();
- int curHour = tm.GetHour();
- std::cout << curHour << std::endl;
- if ((9 <= curHour && curHour < 11) ||(14 == curHour ))
- {
- auto curTime = tm.Format("%Y-%m-%d %H:%M:%S");
- CString sql;
- sql.Format("insert into rep_wait_count(Count,UpdateTime) values(%d,'%s')", count, curTime);
- CSqlWriter::GetInstance().addSql(sql);
- std::cout << sql.GetBuffer(0) << std::endl;
- }
- }
- bool isSuccess = CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{Core}: 通知[%d][%s],当前数量:%d"), a_pCmd->GetCmdType(), isSuccess ? "成功" : "失败", count);
- }
- void CAcdCore::__onCmdGetAgentList(CPduEntity * a_pCmd)
- {
- CString szAgentList;
- m_AgentOffice.getAllAgentStateList(szAgentList);
- int t_agent_id = a_pCmd->GetDataUInt(1);
- if (!pushAgentList(t_agent_id, szAgentList.GetBuffer(0))) // 如果rcf失败在使用原来参数传递
- {
- if (szAgentList.GetLength() >= 512)
- {
- szAgentList = szAgentList.Left(511);
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_WARNING, _T("ACD -> HP-SERVER,坐席[%lu]获取坐席列表字符超出被截取 "), a_pCmd->GetDataUInt(1));
- }
- a_pCmd->SetDataString(2, szAgentList);
- }
- szAgentList.ReleaseBuffer();
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- void CAcdCore::__onCmdMonitor(CPduEntity * a_pCmd)
- {
- // 返回监控执行结果
- a_pCmd->SetToExecReturn();
- int WaiteCallCount = m_QueueMgr.callCount();
- int AgentLoginCount = m_AgentOffice.getAgentCount();
- int AgentSpeakCount = 0;
- int AgentOnlineCount = 0;
- int AgentReposeCount = 0;
- m_AgentOffice.GetCurAgentCount(AgentSpeakCount, AgentOnlineCount, AgentReposeCount);
- char strValue[PDU_MAX_DATA_BUF_LEN] = { 0 };
- sprintf_s(strValue, "%d|%d|%d|%d", AgentSpeakCount, AgentOnlineCount, AgentReposeCount, WaiteCallCount);
- a_pCmd->SetDataString(2, strValue);
- a_pCmd->SetDataBool(0, true);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- }
- void CAcdCore::__onCmdAgentDetail(CPduEntity * a_pCmd)
- {
- // 返回坐席详情执行结果
- a_pCmd->SetToExecReturn();
- int ringCount = 0;
- m_AgentOffice.GetCurAgentCount(AgentSpeakCount, AgentOnlineCount, AgentReposeCount, AgentFreeCount, AgentProcessingCount, ringCount);
- //AgentRingCount = ringCount;
- char strValue[PDU_MAX_DATA_BUF_LEN] = { 0 };
- sprintf_s(strValue, "%d|%d|%d|%d|%d|%d|%d|%d|%d", AgentSpeakCount, AgentOnlineCount, AgentReposeCount, m_WaitCount, AgentFreeCount, AgentProcessingCount, AgentRingCount, m_ExtCallOutCount, m_TrunkCount);
- a_pCmd->SetDataString(2, strValue);
- a_pCmd->SetDataBool(0, true);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- m_LoginCount = AgentOnlineCount;
- m_TalkingCount = AgentSpeakCount;
- }
- void CAcdCore::__onCmdUpdateAgentCount()
- {
- static time_t lastTime = time(NULL);
- static bool isFirst = true;
- int64_t timesamp = time(NULL) - lastTime;
- std::cout << timesamp << std::endl;
- if (timesamp >= (5 * 60) || isFirst)
- {
- CString sql;
- sql.Format("update rep_service set Checkin=%d,Conversation=%d", m_LoginCount, m_TalkingCount);
- CSqlWriter::GetInstance().addSql(sql);
- lastTime = time(NULL);
- isFirst = false;
- }
- }
- void CAcdCore::__onCmdAgentTransferSkillGroup(CPduEntity * a_pCmd)
- {
- UINT ExtenId = 0;
- UINT AgentId = 0;
- CString QueueNo = a_pCmd->GetDataString(3);
- if (!m_QueueMgr.GetFreeAgent(atoi(QueueNo), AgentId, ExtenId)) // 没有获取到指定技能组的空闲坐席
- {
- a_pCmd->SetDataBool(0, false);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL,"[%s][%d]获取坐席失败",__FUNCTION__,__LINE__ );
- }
- else
- {
- if (!m_AgentOffice.lockAgent(AgentId)) // 被叫叫座席非空闲
- {
- a_pCmd->SetToExecReturn();
- a_pCmd->SetDataBool(0, false);
- CNetworkAcd::GetInstance().send2Server(a_pCmd);
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "[%s][%d]锁定坐席失败", __FUNCTION__, __LINE__);
- return; // 不再向CTI转发
- }
- CString DestNum;
- DestNum.Format("%lu", ExtenId);
- a_pCmd->SetDataString(3, DestNum);
- ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, _T("{Core}: AGENT -> ACD, CMD = [%s], Agent = %lu, Exten = %lu, Dest Number = [%s][%lu][%lu]"),
- "指定技能组转移", a_pCmd->GetDataUInt(2), a_pCmd->GetDataUInt(1), QueueNo, AgentId, ExtenId);
- CNetworkAcd::GetInstance().send2Cti(a_pCmd);
- }
- }
- void CAcdCore::__onCmdAgentSkillGroupWaitCount()
- {
- CPduEntity cmd(PDU_CMD_AGENT_SKILL_GROUP_WAIT_COUNT);
- cmd.SetDataString(0, m_QueueMgr.waitCount());
- CNetworkAcd::GetInstance().send2Server(&cmd);
- }
- void CAcdCore::__onCallInAgent(CPduEntity * a_pCmd)
- {
- if (a_pCmd->GetCmdType() != PDU_CMD_CTI_LINE_STATE) // 只处理分机状态信息
- return;
- UINT ExtID = a_pCmd->GetDataUInt(0);
- UINT State = a_pCmd->GetDataUInt(1);
- CString Callee = a_pCmd->GetDataString(5);
- CString ExtIDStr;
- ExtIDStr.Format("%d",ExtID);
- static std::map<CString, GroupTalking> groupCount;
- CExten* pExten = m_ExtenCtrl.getExten(ExtID);
- if (pExten != NULL && ExtIDStr == Callee) // 被叫号码=当前分机号时,说明当前分机是被叫
- {
- if (pExten->GetPeerLineType() != DEV_RES_TYPE_EXT && State == INNER_STATE_TALKING)
- {
- UINT Agentid = pExten->assoAgent();// 坐席工号
- auto pAgent = m_AgentOffice.getAgentById(Agentid);
- if (pAgent != NULL)
- {
- CString groupId = pAgent->group();
- auto it = groupCount.find(groupId);
- if (it != groupCount.end())
- {
- it->second.add(ExtID);
- CString str;
- str.Format("%s|%d", groupId,it->second.count());
- std::string ss;
- ss = str.GetBuffer(0);
- pushRedis(ss);
-
- }
- else
- {
- GroupTalking gTalking;
- gTalking.add(ExtID);
- groupCount[groupId] = gTalking;
- CString str;
- str.Format("%s|%d", groupId, it->second.count());
- std::string ss;
- ss = str.GetBuffer(0);
- pushRedis(ss);
- }
- }
- }
- }
- if (State == INNER_STATE_REMOVE || State == INNER_STATE_FREE) // 话机移除或空闲
- {
- std::vector<std::string> vecs;
- auto it = groupCount.begin();
- while (it != groupCount.end())
- {
- it->second.del(ExtID);
- CString str;
- str.Format("%s|%d", it->first, it->second.count());
- std::string ss;
- ss = str.GetBuffer(0);
- vecs.emplace_back(ss);
- ++it;
- }
- if(!vecs.empty())
- pushRedis(vecs);
- }
- }
- /*****************************************************************
- **【函数名称】 stage1Start
- **【函数功能】 第一阶段启动
- **【参数】
- **【返回值】
- ****************************************************************/
- bool CAcdCore::stage1Start( void )
- {
- // 连接配置数据库
- if(!IOtlConnection::getInstance()->Connect())
- {
- AfxMessageBox(STR_ERR_CORE_INIT_DB);
- return false;
- }
- // 加载配置
- if(!CConfig::load())
- {
- IOtlConnection::getInstance()->Disconnect();
- AfxMessageBox(STR_ERR_CORE_INIT_CFG);
- return false;
- }
- return true;
- }
- /*****************************************************************
- **【函数名称】 stage2Start
- **【函数功能】 第二阶段启动
- **【参数】 ErrInfo: 出错信息
- **【返回值】
- ****************************************************************/
- bool CAcdCore::stage2Start( void )
- {
- // 建立网络通讯
- if(!CNetworkAcd::GetInstance().init())
- {
- ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_ERROR, _T("%s"), STR_ERR_CORE_INIT_NETWORK);
- return false;
- }
- //#ifndef _DEBUG
- m_Auther.InitAutherData("C://Windows//mshy.dll");
- // m_Auther.__setTimer(86400000); //一天
- m_Auther.__setTimer(10000);
- //#endif
- CMsgCenter::GetInstance().regist(ACD_MSG_AGENT_STATE_UPDAET, this);
- CMsgCenter::GetInstance().regist(ACD_MSG_EXTEN_STATE_UPDATE, this);
- CMsgCenter::GetInstance().regist(ACD_MSG_QUEUE_UPDATE, this);
- CDaemonClient::GetInstance().doWork();
- return true;
- }
- void CAcdCore::reloadAuther()
- {
- m_Auther.InitAutherData("C://Windows//mshy.dll");
- }
- /*****************************************************************
- **【函数名称】 exit
- **【函数功能】 退出ACD
- **【参数】
- **【返回值】
- ****************************************************************/
- void CAcdCore::exit(void)
- {
- CNetworkAcd::GetInstance().release();
- m_QueueMgr.clear();
- m_AgentOffice.close();
- m_ExtenCtrl.removeExten();
- IOtlConnection::getInstance()->Disconnect();
- }
- /*****************************************************************
- **【函数名称】 onNetLinkDown
- **【函数功能】 连接断开后续处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CAcdCore::onNetCtiLinkDown()
- {
- m_AgentOffice.clearAgent(); // 清空所有座席信息
- m_ExtenCtrl.removeExten(); // 清空所有分机信息
- m_QueueMgr.clear(); // 清空所有来电排队信息
- }
- void CAcdCore::onNetHpServerLinkDown()
- {
- // 清空对应的座席信息
- CString agentList;
- m_AgentOffice.getAllAgentStateList(agentList);
- std::string agentListStr;
- agentListStr = agentList.GetBuffer(0);
- agentList.ReleaseBuffer();
- try {
- std::list<std::string> agentVec;
- boost::split(agentVec, agentListStr, boost::is_any_of("|"));
- std::vector<std::string> agentExtVec;
- for (auto agentStr : agentVec) {
- agentExtVec.clear();
- boost::split(agentExtVec, agentStr, boost::is_any_of(","));
- if (agentExtVec.size() >= 2) {
- __removeAgent(atoi(agentExtVec[0].c_str()), atoi(agentExtVec[1].c_str()), 0);
- }
- }
- }
- catch (const std::exception&) {
- }
- }
- void CAcdCore::onNetLinkDown( PduLinkContent linkContent )
- {
- if(linkContent.nFarType == PDU_DEV_TYPE_CTI) // 对CTI的处理
- {
- m_AgentOffice.clearAgent(); // 清空所有座席信息
- m_ExtenCtrl.removeExten(); // 清空所有分机信息
- m_QueueMgr.clear(); // 清空所有来电排队信息
- }
- else if(linkContent.nFarType == PDU_DEV_TYPE_AGENT) // 对Agent的处理
- {
- // 清空对应的座席信息
- UINT AssoExten = m_AgentOffice.getAgentAssoExten(linkContent.nFarId);
- __removeAgent(linkContent.nFarId, AssoExten, 0);
- } // end if
- }
- /*****************************************************************
- **【函数名称】 onRecvCommand
- **【函数功能】 PDU命令到达事件处理
- **【参数】
- **【返回值】
- ****************************************************************/
- void CAcdCore::onRecvCommand( CPduEntity* a_pPduEntity )
- {
- switch(a_pPduEntity->GetCmdType())
- {
- case PDU_CMD_MONITOR_START: // ych 2018.6.4 商丘监控添加命令
- __onCmdMonitor(a_pPduEntity);
- break;
- case PDU_CMD_CTI_LINE_STATE: // CTI通知分机信息
- {
- __onCmdCtiExtenInfo(a_pPduEntity);
- __onCallInAgent(a_pPduEntity); // 2022-01-27 市民呼入到坐席的通话中的每个坐席组数量
- }
- break;
- case PDU_CMD_CTI_ACD_TRUNK_USAGE: // CTI通知呼叫任务中继利用率
- __onCmdCtiTrunkUsage(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_SETSTATE: // 设置座席状态
- __onCmdAgentSetState(a_pPduEntity);
- break;
- case PDU_CMD_IVR_WANT_AGENT: // IVR请求座席
- case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队
- case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
- case PDU_CMD_CTI_ACD_QUEUE_PAUSE: // CTI通知ACD暂停排队
- __onCmdIvrQueue(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_RESET: // 座席重置
- case PDU_CMD_AGENT_ANSWER: // 座席应答
- case PDU_CMD_AGENT_HOLD: // 保持
- case PDU_CMD_AGENT_TAKEBACK: // 接回
- case PDU_CMD_AGENT_HANGUP: // 座席挂机
- case PDU_CMD_AGENT_CANCEL: // 坐席取消操作
- case PDU_CMD_AGENT_FAX: // 收发传真
- case PDU_CMD_AGENT_TURN_TO_IVR: // 转IVR
- case PDU_CMD_AGENT_CONFIRM_TRANSFER: // 确认转移
- case PDU_CMD_AGENT_MUTE: // 静音
- case PDU_CMD_AGENT_THREETALK_TAKEBACK: // 单步会议接回主叫
- case PDU_CMD_AGENT_SEND_DTMF: // 2022-01-12 坐席发送按键
- __onCmdNeed2Forward(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_TRANSTALK: // 座席转移
- case PDU_CMD_AGENT_THREETALK: // 单步会议
- case PDU_CMD_AGENT_MAKECALL: // 坐席外呼
- case PDU_CMD_AGENT_CONSULTATION_CALL: // 协商呼叫
- __onCmdAgentDial(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_MONI_LISTEN: // 监听
- case PDU_CMD_AGENT_MONI_INSERT: // 强插
- case PDU_CMD_AGENT_MONI_CUT: // 强拆
- case PDU_CMD_AGENT_MONI_REPLACE: // 代接
- case PDU_CMD_AGENT_MONI_INTERCEPT: // 强截
- __onCmdAgentMonControl(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_MONI_FORCE_STATE: // 班长强制状态控制
- __onCmdAgentForceState(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_MONI_FORCE_LOGOUT: // 强制签出
- __onCmdAgentForceLogout(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_SUBSCRIBE: // 事件订阅
- case PDU_CMD_AGENT_CANCEL_SUBSCRIBE: // 取消订阅
- __onCmdAgentSubscribe(a_pPduEntity);
- break;
- case PDU_CMD_REG: // 注册命令
- __onCmdAgentReg(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_LOGIN: // 座席签入
- __onCmdAgentLogin(a_pPduEntity);
- // 发送技能组排队情况 2021-11-26
- __onCmdAgentSkillGroupWaitCount();
- break;
- case PDU_CMD_AGENT_LOGOUT: // 座席签出
- __onCmdAgentLogout(a_pPduEntity);
- break;
- case PDU_CMD_CTI_DEV_CALL: // Cti通知物理外呼结果
- __onCmdCtiDevCall(a_pPduEntity);
- break;
- case PDU_CMD_CTI_RECORD: // CTI通知座席录音信息
- __onCmdCtiRecord(a_pPduEntity);
- break;
- case PDU_CMD_CTI_TRUNKUSE_COUNT: // 中继使用数量
- case PDU_CMD_IVR_WAITER_COUNT: //向Agent转发的数据
- __onCmdDataSendToAgent(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_GET_AGENTLIST:
- __onCmdGetAgentList(a_pPduEntity);
- break;
- case PDU_CMD_AGENT_DETAIL:
- __onCmdAgentDetail(a_pPduEntity);
- break;
- default:
- return;
- } // end switch
- switch (a_pPduEntity->GetCmdType())
- {
- case PDU_CMD_CTI_LINE_STATE: // CTI通知分机信息
- case PDU_CMD_AGENT_SETSTATE: // 设置座席状态
- case PDU_CMD_IVR_WANT_AGENT: // IVR请求座席
- case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队
- case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队
- case PDU_CMD_CTI_ACD_QUEUE_PAUSE: // CTI通知ACD暂停排队
- case PDU_CMD_AGENT_MONI_FORCE_STATE: // 班长强制状态控制
- case PDU_CMD_AGENT_MONI_FORCE_LOGOUT: // 强制签出
- case PDU_CMD_AGENT_LOGIN: // 座席签入
- case PDU_CMD_AGENT_LOGOUT: // 座席签出
- case PDU_CMD_CTI_TRUNKUSE_COUNT: // 中继使用数量
- case PDU_CMD_IVR_WAITER_COUNT: //向Agent转发的数据
- {
- CPduEntity cmd(PDU_CMD_AGENT_DETAIL);
- cmd.SetDataInt(1, 0);
- __onCmdAgentDetail(&cmd);
- __onCmdUpdateAgentCount();
- }
- break;
- } // end switch
- }
- /*****************************************************************
- **【函数名称】 onMessage
- **【函数功能】 系统消息处理
- **【参数】
- **【返回值】
- *****************************************************************/
- void CAcdCore::onMessage( UINT MsgType, const PARAM lpContent )
- {
- switch(MsgType)
- {
- case ACD_MSG_AGENT_STATE_UPDAET:
- __onAgentStateUpdated((UINT)lpContent);
- break;
- case ACD_MSG_EXTEN_STATE_UPDATE:
- __onPhoneStateUpdated((UINT)lpContent);
- break;
- case ACD_MSG_QUEUE_UPDATE:
- __onQueueStateUpdated((UINT)lpContent);
- break;
- }
- }
|