#include "StdAfx.h" #include "NetworkCti.h" #include "LineHolder.h" #include "IvrFlowHolder.h" #include "Logger.h" #include "MsgCenter.h" #include "Config.h" #include "CtiDataDef.h" #include "TaskMgr.h" SINGLETON_IMPLEMENT(CNetworkCti) CNetworkCti::CNetworkCti(void) : m_IsAcdConnected(FALSE), m_IsIvrConnected(FALSE) { } void CNetworkCti::__procRegDevListMsg(CPduEntity & a_PduEntity) { auto devList = a_PduEntity.GetDataString(0); CString dev; dev.Format("|%d|", PDU_DEV_TYPE_IVR); bool newIvrConnected = devList.Find(dev) < 0 ? false : true; dev.Format("|%d|", PDU_DEV_TYPE_ACD); auto newAcdConnected = devList.Find(dev) < 0 ? false : true; if (!m_IsAcdConnected && newAcdConnected) { // acd 连接 // 通知线路类Acd连接成功 CLineHolder::GetInstance().onAcdConnected(); } else if (m_IsAcdConnected && !newAcdConnected) { // acd连接断开 } m_IsAcdConnected = newAcdConnected; if (m_IsIvrConnected && !newIvrConnected) { // ivr掉线 // 通知IvrFlow IVR连接断开 CIvrFlowHolder::GetInstance().onIvrDisconnect(); } else if (!m_IsIvrConnected && newIvrConnected) { // ivr上线 } m_IsIvrConnected = newIvrConnected; } CNetworkCti::~CNetworkCti(void) { } /***************************************************************** **【函数名称】 __procRegMsg **【函数功能】 处理注册命令 **【参数】 a_PduEntity:注册命令 **【返回值】 ****************************************************************/ void CNetworkCti::__procRegMsg(CPduEntity& a_PduEntity) { bool RegResult = false; switch (a_PduEntity.GetLocalDevType()) { case PDU_DEV_TYPE_ACD: RegResult = m_DevAcd.DevId == -1 ? true : false; break; case PDU_DEV_TYPE_IVR: RegResult = m_DevIvr.DevId == -1 ? true : false; break; default: ASSERT(FALSE); break; } // 发送注册结果 a_PduEntity.SetToExecReturn(); a_PduEntity.SetDataBool(0, RegResult); CNetInterface::getNetInstance()->Send(&a_PduEntity, a_PduEntity.GetLocalDevType(), a_PduEntity.GetLocalDevId()); } /***************************************************************** **【函数名称】 __onRegSuccess **【函数功能】 设备注册成功处理函数 **【参数】 linkContent:注册段信息 **【返回值】 ****************************************************************/ void CNetworkCti::__onRegSuccess(const PduLinkContent& linkContent) { switch (linkContent.nFarType) { case PDU_DEV_TYPE_ACD: { // 保存设备信息 m_DevAcd.DevId = linkContent.nLocalId; lstrcpy(m_DevAcd.szIpAddress, linkContent.szFarIp); m_DevAcd.Port = linkContent.nFarPort; m_IsAcdConnected = TRUE; // 通知线路类Acd连接成功 CLineHolder::GetInstance().onAcdConnected(); } break; case PDU_DEV_TYPE_IVR: { // 保存设备信息 m_DevIvr.DevId = linkContent.nLocalId; lstrcpy(m_DevIvr.szIpAddress, linkContent.szFarIp); m_DevIvr.Port = linkContent.nFarPort; m_IsIvrConnected = TRUE; } break; default: ASSERT(FALSE); break; } } /***************************************************************** **【函数名称】 __onDisconnect **【函数功能】 设备连接断开处理函数 **【参数】 linkContent:连接断开端信息 **【返回值】 ****************************************************************/ void CNetworkCti::__onDisconnect(const PduLinkContent& linkContent) { switch (linkContent.nFarType) { case PDU_DEV_TYPE_ACD: { if (m_DevAcd.DevId != linkContent.nLocalId) return; if (strcmp(m_DevAcd.szIpAddress, linkContent.szFarIp) != 0) return; if (m_DevAcd.Port != linkContent.nFarPort) return; memset(&m_DevAcd, 0, sizeof(m_DevAcd)); m_DevAcd.DevId = -1; m_IsAcdConnected = FALSE; } break; case PDU_DEV_TYPE_IVR: { if (m_DevIvr.DevId != linkContent.nLocalId) return; if (strcmp(m_DevIvr.szIpAddress, linkContent.szFarIp) != 0) return; if (m_DevIvr.Port != linkContent.nFarPort) return; memset(&m_DevIvr, 0, sizeof(m_DevIvr)); m_DevIvr.DevId = -1; // 通知IvrFlow IVR连接断开 CIvrFlowHolder::GetInstance().onIvrDisconnect(); m_IsIvrConnected = FALSE; } break; default: break; } } void CNetworkCti::__onHeartMonitorDrop(int devType) { } /***************************************************************** **【函数名称】 OnLinkStateChanged **【函数功能】 连接状态信息变化 **【参数】 **【返回值】 ****************************************************************/ void CNetworkCti::OnLinkStateChanged(const PduLinkContent& linkContent) { // 连接信息日志显示 LOG_LEVEL nLogLevel = LOG_LEVEL_WARNING; CString Msg; switch (linkContent.nLinkState) { case PDU_LINK_STATE_SUCCESSED: break; case PDU_LINK_STATE_FAILED: break; case PDU_LINK_STATE_DISCONNECTED: { Msg = _T("{Net}: Far End Disconnected, "); nLogLevel = LOG_LEVEL_WARNING; __onDisconnect(linkContent); } break; case PDU_LINK_STATE_REG_OK: { Msg = _T("{Net}: Far End Reg OK, "); nLogLevel = LOG_LEVEL_NORMAL; __onRegSuccess(linkContent); } break; case PDU_LINK_STATE_REG_FAILED: { Msg = _T("{Net}: Far End Reg Failed, "); nLogLevel = LOG_LEVEL_WARNING; } break; default: { Msg = _T("{Net}: Unknown Netlink State, "); nLogLevel = LOG_LEVEL_WARNING; } break; } // 通知日志 ILogger::getInstance().log(LOG_CLASS_SOCKET, nLogLevel, _T("%s"), Msg); } /***************************************************************** **【函数名称】 OnRecvCommand **【函数功能】 Pdu命令处理接口 **【参数】 a_pPduEntity:消息实体 **【返回值】 ****************************************************************/ void CNetworkCti::OnRecvCommand(CPduEntity* a_pPduEntity) { ASSERT(a_pPduEntity != NULL); if (a_pPduEntity->GetCmdType() != PDU_CMD_LISTEN) // 心跳命令不打印 { ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_NORMAL, _T("{CNetworkCti}:OnRecvCommand,CmdType=%d,LocalDevType[%d]"), a_pPduEntity->GetCmdType(), a_pPduEntity->GetLocalDevType()); } CWarningPush::getInstance()->heartMonitor(a_pPduEntity->GetLocalDevType(), a_pPduEntity->GetPeerDevType()); switch (a_pPduEntity->GetCmdType()) { case PDU_CMD_REG: // 注册命令 __procRegMsg(*a_pPduEntity); break; case PDU_CMD_DEV_ONLINE_LIST: // 设备在线列表 __procRegDevListMsg(*a_pPduEntity); break; case PDU_CMD_CTI_IVR_CALLIN: // CallIn返回命令 case PDU_CMD_CTI_IVR_TURNIVR: // 转IVR返回命令 case PDU_CMD_IVR_HANGUP: // IVR通知CTI挂机 case PDU_CMD_IVR_END: // IVR通知CTI流程结束 case PDU_CMD_IVR_WANT_AGENT: // IVR通知CTI请求排队(包括ACD返回) case PDU_CMD_IVR_QUEUE_CONTINUE: // IVR通知CTI继续排队(包括ACD返回) case PDU_CMD_IVR_QUEUE_CANCEL: // IVR通知CTI取消排队 case PDU_CMD_IVR_TURN_AGENT: // IVR通知CTI转坐席 case PDU_CMD_IVR_PLAY_DTMF: // IVR通知CTI放音收按键 case PDU_CMD_IVR_CALL_OUT: // IVR通知CTI自动呼叫某个号码 case PDU_CMD_IVR_TURN_OUTLINE: // IVR呼叫转移 case PDU_CMD_IVR_FAX: // IVR通知收发传真 case PDU_CMD_IVR_LEAVE_WORD: // IVR通知留言 CIvrFlowHolder::GetInstance().onPduMessage(*a_pPduEntity); break; case PDU_CMD_LISTEN: return; case PDU_CMD_IVR_WAITER_COUNT: //2019 - 9 - 6 配合4.0acd返回排队人数 { send2ACD(*a_pPduEntity); //发送至ACD int WaiterCount = a_pPduEntity->GetDataUInt(0); // m_WaiterCount.onWaiterCount(WaiterCount); ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "{NetWorkCti}:收到排队数量%d", WaiterCount); } break; default: { __try { CTaskMgr::GetInstance().onPduMessage(*a_pPduEntity); } __except (EXCEPTION_EXECUTE_HANDLER) { ILogger::getInstance().log(LOG_CLASS_BUSI, LOG_LEVEL_WARNING, _T("{CNetworkCti}:OnRecvCommand,CTaskMgr异常,CmdType=%d,mdw5.1.19.1"), a_pPduEntity->GetCmdType()); } break; } break; } } /***************************************************************** **【函数名称】 init **【函数功能】 初始化 **【参数】 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ BOOL CNetworkCti::init() { // 初始化客户端设备信息 memset(&m_DevAcd, 0, sizeof(m_DevAcd)); memset(&m_DevIvr, 0, sizeof(m_DevIvr)); m_DevAcd.DevId = -1; m_DevIvr.DevId = -1; auto pClient = CNetInterface::getNetInstance(); pClient->setLinkStateChanged(std::bind(&CNetworkCti::OnLinkStateChanged, this, std::placeholders::_1)); pClient->setRecvCommand(std::bind(&CNetworkCti::OnRecvCommand, this, std::placeholders::_1)); //2022-08-10 添加设备监听掉线回调, 监听acd,ivr是否掉线 CWarningPush::getInstance()->setHeartDropFuncCB(std::bind(&CNetworkCti::__onHeartMonitorDrop, this, std::placeholders::_1)); //连接ws服务器端 CString Ip = CConfig::GetInstance().wsIP(); int Port = CConfig::GetInstance().wsPort(); if(pClient->CreatePduClient(Ip, Port, PDU_DEV_TYPE_CTI, 1, true)) { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_NORMAL, "{Net}: 连接ws服务端成功,IP=%s,ListenPort = %d", Ip,Port); return TRUE; } else { ILogger::getInstance().log(LOG_CLASS_SOCKET, LOG_LEVEL_ERROR, "{Net}: 连接ws服务端失败,IP=%s,ListenPort = %d", Ip, Port); return FALSE; } return TRUE; } /***************************************************************** **【函数名称】 release **【函数功能】 释放资源 **【参数】 **【返回值】 成功TRUE,失败FALSE ****************************************************************/ void CNetworkCti::release(void) { CNetInterface::getNetInstance()->ClosePduClient(PDU_DEV_TYPE_CTI, 1); } /***************************************************************** **【函数名称】 send2ACD **【函数功能】 发送PDU到ACD **【参数】 a_PduEntity:待发送的PDU **【返回值】 ****************************************************************/ BOOL CNetworkCti::send2ACD(CPduEntity& a_PduEntity) { return CNetInterface::getNetInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_ACD, m_DevAcd.DevId); } /***************************************************************** **【函数名称】 send2IVR **【函数功能】 发送PDU到IVR **【参数】 a_PduEntity:待发送的PDU **【返回值】 ****************************************************************/ BOOL CNetworkCti::send2IVR(CPduEntity& a_PduEntity) { return CNetInterface::getNetInstance()->Send(&a_PduEntity, PDU_DEV_TYPE_IVR, m_DevIvr.DevId); }