////////////////////////////////////////////////////////////////////////////// ////// ////// ////// 文 件: NoticeQueue.cpp ////// ////// 作 者: sailing ////// ////// 创建时间: 2008-02-23 ////// ////// 说 明: 1、语音通知 ////// ////// 2、短信通知 ////// ////// 3、邮件通知 ////// ////// 修改时间: ////// ////// 修改说明: ////// ////// ////// ////////////////////////////////////////////////////////////////////////////// #pragma once #include "stdafx.h" #include "NoticeQueue.h" #include "Global.h" #include "SysLib.h" #include "shlwapi.h" #define NOTICE_DELAY 35 //通知延时 int g_nAlarmIndex=0;//报警索引,为了在IDE上面确认而设 // 发送通知 typedef struct _SEND_NOTICE { char szDevUID[20]; // 设备Uid int nVarID; // 变量ID char szTel[MAX_TEL_LENGTH + 1]; // 电话号码 char szContect[MAX_NOTICE_CONTENT_LEN + 1]; // 内容 int nAlarmIndex; // 报警索引 SYSTEMTIME time; }SEND_NOTICE, *PSEND_NOTICE; typedef list LIST_SEND_NOTICE; LIST_SEND_NOTICE g_listSendNotice; LIST_SEND_NOTICE g_listSendSms; HANDLE g_hSendNoticeThread = NULL; HANDLE g_hSendSmsThread = NULL; CRITICAL_SECTION g_csVarNotice; // 临界区对ProcessVarNotice过程全局变量进行保护 CRITICAL_SECTION g_csSendNotice; // 临界区在发送线程里对全局变量进行保护 HANDLE g_hDeleteVarSem; // 所有读变量list, 都要等这个信号量,保证变量出队列成功后,才能读 // 删除所有变量 void DeleteAllSendNoticeList(); void DeleteAllSendSmsList(); // 添加变量到語音list void InsertSendNoticeList(char *pDevUid, int nVarID, char *pTel, char *pContent,int nAlarmIndex); //IDE 确认后从語音list删除 int DeleteSendNoticeList( char *pDevUid, int nVarID,int iAlarmIndex ); // 添加变量到短信list void InsertSendSmsList(char *pDevUid, int nVarID, char *pContent,int nAlarmIndex); //IDE 确认后从短信list删除 int DeleteSendSmsList( char *pDevUid, int nVarID,int iAlarmIndex ); static DWORD WINAPI SendNoticeThread(LPVOID lpParameter); static DWORD WINAPI SendSmsThread(LPVOID lpParameter); // 获取报警状态ID对应的意义,用来组织报警内容 for Jesse 091119 INT GetAlarmStatusDesc(char chDevUid[20], int nVarID, int nAlarmStatus, char *pStatusDesc); // // 初始化语音报警模块,创建语音报警线程; // 1.判断是否启用语音报警功能,加载动态库接口函数(PCI and USB); // 2.创建线程,进行实时报警信息获取,发送语音内容; // 3.加载TTS语音库; int InitNotice(void) { // 初始化远程报警通知 if( g_nSendNotice ) { g_hNoticeLibModule = NULL; CHAR strFile[MAX_LIST_LENGTH + 1] = ""; // 类型1 = PCI插槽; if( g_nNoticeCardType == 1 ) { wsprintf(strFile, "%s\\Dll\\Voice.dll", g_strDirectory); g_hNoticeLibModule = ::LoadLibrary(strFile); // 初始化接口函数; if (NULL != g_hNoticeLibModule) { pStoneUDllRegisterVoice = (STONEU_DLLRegisterVoice)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLRegisterVoice"); pStoneUDllUnRegisterVoice = (STONEU_DLLUnRegisterVoice)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLUnRegisterVoice"); pStoneUDllAllocateChannel = (STONEU_DLLAllocateChannel)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLAllocateChannel"); } if( ( NULL != g_hNoticeLibModule ) && ( NULL != pStoneUDllRegisterVoice ) ) { int nRet = pStoneUDllRegisterVoice(g_strDirectory, g_nTTSType); if( nRet != 0 ) { AfxFreeLibrary( g_hNoticeLibModule ); g_hNoticeLibModule = NULL; return 1; } } else { AfxFreeLibrary( g_hNoticeLibModule ); g_hNoticeLibModule = NULL; } } else if( g_nNoticeCardType == 2 ) // 类型2 = USB接口; { wsprintf(strFile, "%s\\Dll\\UsbVoice.dll", g_strDirectory); g_hNoticeLibModule = ::LoadLibrary(strFile); // 初始化接口函数; if( NULL != g_hNoticeLibModule ) { pStoneUDllRegisterVoice = (STONEU_DLLRegisterVoice)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLRegisterVoice"); pStoneUDllUnRegisterVoice = (STONEU_DLLUnRegisterVoice)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLUnRegisterVoice"); pStoneUDllAllocateChannel = (STONEU_DLLAllocateChannel)::GetProcAddress(g_hNoticeLibModule, "STONEU_DLLAllocateChannel"); } if( ( NULL != g_hNoticeLibModule ) && ( NULL != pStoneUDllRegisterVoice ) ) { int nRet = pStoneUDllRegisterVoice(g_strDirectory, g_nTTSType); if( nRet != 0 ) { AfxFreeLibrary( g_hNoticeLibModule ); g_hNoticeLibModule = NULL; return 1; } } else { AfxFreeLibrary( g_hNoticeLibModule ); g_hNoticeLibModule = NULL; } } // 创建语音线程,实时从<报警队列表里>取信息进行语音拨号; DWORD dwThreadId; MTVERIFY( g_hSendNoticeThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendNoticeThread, NULL, 0, &dwThreadId) ); //初始化TTS hTTSModule = NULL; wsprintf(strFile, "%s\\Dll\\TTSDll.dll", g_strDirectory); hTTSModule = ::LoadLibrary(strFile); if (NULL != hTTSModule) { pStoneUDllRegisterTTS = (MySTONEU_DLLRegisterTTS)::GetProcAddress(hTTSModule, "STONEU_DLLRegisterTTS"); pStoneUDllUnRegisterTTS = (MySTONEU_DLLUnRegisterTTS)::GetProcAddress(hTTSModule, "STONEU_DLLUnRegisterTTS"); pStoneUDLLTxtToWav = (MySTONEU_DLLTxtToWav)::GetProcAddress(hTTSModule, "STONEU_DLLTxtToWav"); } if( ( NULL != hTTSModule ) && ( NULL != pStoneUDllRegisterTTS ) ) { if( !pStoneUDllRegisterTTS() ) { FreeLibrary( hTTSModule ); hTTSModule = NULL; } } else { FreeLibrary( hTTSModule ); hTTSModule = NULL; } } //MTVERIFY( g_hDeleteVarSem = CreateEvent(NULL, TRUE, TRUE, "DeleteVarList") ); //InitializeCriticalSection( &g_csVarNotice ); //InitializeCriticalSection( &g_csSendNotice ); return 0; } void UnInitNotice(void) { if( g_hSendNoticeThread ) { //MTVERIFY( SetEvent( g_hDeleteVarSem ) ); MTVERIFY( WaitForSingleObject( g_hSendNoticeThread, INFINITE ) != WAIT_FAILED ); MTVERIFY( CloseHandle(g_hSendNoticeThread) ); g_hSendNoticeThread = NULL; } //DeleteCriticalSection( &g_csVarNotice ); //DeleteCriticalSection( &g_csSendNotice ); // //if( g_hDeleteVarSem ) //{ // MTVERIFY( CloseHandle( g_hDeleteVarSem) ); // g_hDeleteVarSem = NULL; //} if( g_nSendNotice ) { if( ( NULL != g_hNoticeLibModule ) && ( NULL != pStoneUDllUnRegisterVoice ) ) pStoneUDllUnRegisterVoice(); if( ( NULL != hTTSModule ) && ( NULL != pStoneUDllUnRegisterTTS ) ) pStoneUDllUnRegisterTTS(); } DeleteAllSendSmsList(); DeleteAllSendNoticeList(); DeleteAllVarNoticeList(); if (g_hNoticeLibModule != NULL) { ::FreeLibrary(g_hNoticeLibModule); g_hNoticeLibModule = NULL; } if (hTTSModule != NULL) { FreeLibrary(hTTSModule); hTTSModule = NULL; } } // 1.判断是否启用邮件功能 ; // 2.加载动态库接口函数; int InitEmail(char *pSmtpServer, // Smtp服务器 int nSmtpPort, // Smtp端口 int nIsNeed, // 是否需要smtp身份验证 char *pUserAcc, // Email帐号 char *pUserPwd, // Email密码 char *pFromEmailAddr, // 发送人Email地址 int nTimeOut // 超时 ) { g_hEmailLibModule = NULL; CHAR strFile[MAX_LIST_LENGTH + 1] = ""; wsprintf(strFile, "%s\\Dll\\Email.dll", g_strDirectory); g_hEmailLibModule = AfxLoadLibrary(strFile); if (NULL != g_hEmailLibModule) { pEmailDllInit = (EMAIL_DLLInit)::GetProcAddress(g_hEmailLibModule, "EMAIL_DLLInit"); pEmailDllUnInit = (EMAIL_DLLUnInit)::GetProcAddress(g_hEmailLibModule, "EMAIL_DLLUnInit"); pEmailDllSendEmail = (EMAIL_DLLSendEmail)::GetProcAddress(g_hEmailLibModule, "EMAIL_DLLSendEmail"); } if( ( NULL != g_hEmailLibModule ) && ( NULL != pEmailDllInit ) ) { int nRet = pEmailDllInit( g_strDirectory, pSmtpServer, nSmtpPort, nIsNeed, pUserAcc, pUserPwd, pFromEmailAddr, nTimeOut ); if( nRet != 0 ) { AfxFreeLibrary( g_hEmailLibModule ); g_hEmailLibModule = NULL; return 1; } } else { AfxFreeLibrary( g_hEmailLibModule ); g_hEmailLibModule = NULL; } return 0; } int UnInitEmail() { if( NULL != g_hEmailLibModule && NULL != pEmailDllUnInit ) { pEmailDllUnInit(); AfxFreeLibrary( g_hEmailLibModule ); g_hEmailLibModule = NULL; } return 0; } // 1.判断是否启用短信功能; // 2.加载动态库接口函数; // 3.创建线程,实时监测报警动态,发送短信; int InitSms( int nAddr, // 保留,因为短信猫是串口232没有地址 int nCommPort, // 串口号 int nRate, // 波特率 int nDataBit, // 数据位 int nStopBit, // 停止位 int nParity, // 校验位 int nInterval, // 间隔时间 int nNeedLanguageTrans, // 是否需要语言转换 int nMaxChar, // 短信猫一条短信最大支持的字符个数 int nMakeCall) { g_hSmsLibModule = NULL; CHAR strFile[MAX_LIST_LENGTH + 1] = ""; wsprintf(strFile, "%s\\Dll\\sms.dll", g_strDirectory); g_hSmsLibModule = AfxLoadLibrary(strFile); if (NULL != g_hSmsLibModule) { pSmsDllInit = (SMS_DLLInit)::GetProcAddress(g_hSmsLibModule, "SMS_DLLInit"); pSmsDllUnInit = (SMS_DLLUnInit)::GetProcAddress(g_hSmsLibModule, "SMS_DLLUnInit"); pSmsDllSendSms = (SMS_DLLSendSms)::GetProcAddress(g_hSmsLibModule, "SMS_DLLSendSms"); pSmsDllGetCSQ = (SMS_DLLGetCSQ)::GetProcAddress(g_hSmsLibModule, "SMS_DLLGetCSQ"); pSmsDllSetCallBack = (SMS_DLLSetCallBack)::GetProcAddress(g_hSmsLibModule, "SMS_DLLSetCallBack"); } if( ( NULL != g_hSmsLibModule ) && ( NULL != pSmsDllInit ) ) { int nRet = pSmsDllInit(g_strDirectory, nAddr, nCommPort, nRate, nDataBit, nStopBit, nParity, nInterval, nNeedLanguageTrans, nMaxChar, nMakeCall ); if( nRet != 0 ) { pSmsDllInit = NULL; pSmsDllUnInit = NULL; pSmsDllSendSms = NULL; pSmsDllGetCSQ = NULL; AfxFreeLibrary( g_hSmsLibModule ); g_hSmsLibModule = NULL; g_bSuccesOpen = false; return 1; }else g_bSuccesOpen = true; } else { pSmsDllInit = NULL; pSmsDllUnInit = NULL; pSmsDllSendSms = NULL; pSmsDllGetCSQ = NULL; AfxFreeLibrary( g_hSmsLibModule ); g_hSmsLibModule = NULL; } DWORD dwThreadId2; MTVERIFY( g_hSendSmsThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)SendSmsThread,NULL, 0, &dwThreadId2) ); return 0; } int UnInitSms() { if( g_hSendSmsThread ) { MTVERIFY( WaitForSingleObject( g_hSendSmsThread, INFINITE ) != WAIT_FAILED ); MTVERIFY( CloseHandle(g_hSendSmsThread) ); g_hSendSmsThread = NULL; } if( NULL != g_hSmsLibModule && NULL != pSmsDllUnInit ) { pSmsDllUnInit(); AfxFreeLibrary( g_hSmsLibModule ); g_hSmsLibModule = NULL; } return 0; } /////////////////////////////////////////////////////////////////////////////////////////////// // 把短信信息写入TXT,让短信模块读取 INT WriteToTxt(CHAR *pDevUid, int nVarID, CHAR *pContent,int iAlarmIndex ) { CString strMobileTel; char szResultMsg[MAX_MSG_LENGTH + 1] = {0}; int nResult = -1; memset(szResultMsg, 0, sizeof(szResultMsg)); CString sPathName; sPathName.Format( "%s\\Log\\SupportSmsPlatform.txt",g_strDirectory ); CString strTemp; CStdioFile MyFile; if(!MyFile.Open(sPathName,CFile::modeWrite)) MyFile.Open(sPathName,CFile::modeCreate|CFile::modeWrite); for( int i = 0; i < (int)g_vtUserRoleInfo.size(); i++ ) { if( strcmp(g_vtUserRoleInfo[i].szDevUID, pDevUid) == 0 ) { for( int j = 0; j < (int)g_vtUserRoleInfo[i].vtUserInfo.size(); j++ ) { strMobileTel = CString(g_vtUserRoleInfo[i].vtUserInfo[j].szMobileTel); if( strMobileTel.GetLength()!=11 ) continue; //判断是不是手机号码 只根据长度 if( strMobileTel.Compare("") ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); strTemp.Format("%d***%s***%s***%s\n",iAlarmIndex,strTime,strMobileTel,pContent); MyFile.SeekToEnd(); MyFile.WriteString(strTemp); } } } } MyFile.Close(); return 0; } /////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// ////// 函数名称:SendNotice /////// ////// 函数说明:开始语音通知 /////// ////// 参数列表:strTel -- 待通知的电话号码 /////// ////// strContent -- 短信内容 /////// ////// 作 者:sailing /////// ////// 创者时间:2009-02-23 /////// /////////////////////////////////////////////////////////////////////////////////////////////// //INT SendNotice(CHAR *pUid, int nVarID,int nAlarmIndex, CHAR *pTel, CHAR *pContent) //{ // //如果是短信确认关闭报警通知则退出 // if( !g_bAlarmNoticeFlag ) // return -1; // // int nRet = 0; // CString str, strMsg; // str = CString(" ") + pContent; // g_strHintAlarmWelcome + // str = str + g_strHintVoiceEnd; //" 重新请按1,确认请按2,结束请直接挂机"; // if( ( NULL != g_hNoticeLibModule ) && (NULL != pStoneUDllAllocateChannel) ) // { // //strMsg.Format("开始发送语音通知!", pTel); // //AddToPrintQueue( MSG_OK, MSG_NOTICE_MD, (char*)(LPCTSTR)strMsg, strMsg.GetLength() ); // // int nResult = pStoneUDllAllocateChannel( pTel, g_strNoticeTelPre, pUid, nVarID,nAlarmIndex, (char *)(LPCTSTR)str ); // nRet = nResult; // if( nRet != CALL_LOST ) // { // CTime time = CTime::GetCurrentTime(); // CString strTime; // strTime = time.Format("%Y-%m-%d %H:%M:%S"); // CDBInterface::GetInstancePtr()->InsertNoticeRecord( // pTel, // "", // (char *)(LPCTSTR)strTime, // (char *)(LPCTSTR)pContent, // ""); // } // } // return nRet; //} // 发送Sms INT SendSms(CHAR *pDevUid, int nVarID, CHAR *pContent) { LOG4C((LOG_NOTICE,"开始发短信")); CString strMobileTel; char szResultMsg[MAX_MSG_LENGTH + 1] = {0}; int nResult = -1; memset(szResultMsg, 0, sizeof(szResultMsg)); //如果是短信确认关闭报警通知则退出 if( !g_bAlarmNoticeFlag ) { LOG4C((LOG_NOTICE,"报警被确认,停止发短信")); return 0; } //LOG4C((LOG_NOTICE, "g_vtUserRoleInfo.size = %d", g_vtUserRoleInfo.size())); for( int i = 0; i < (int)g_vtUserRoleInfo.size(); i++ ) { //LOG4C((LOG_NOTICE, "g_vtUserRoleInfo[i].szDevUID = %s, pDevUid = %s", g_vtUserRoleInfo[i].szDevUID, pDevUid)); if( strcmp(g_vtUserRoleInfo[i].szDevUID, pDevUid) == 0 ) { //LOG4C((LOG_NOTICE, "g_vtUserRoleInfo[i].vtUserInfo.size = %d", g_vtUserRoleInfo[i].vtUserInfo.size())); for( int j = 0; j < (int)g_vtUserRoleInfo[i].vtUserInfo.size(); j++ ) { strMobileTel = CString(g_vtUserRoleInfo[i].vtUserInfo[j].szMobileTel); //LOG4C((LOG_NOTICE, "strMobileTel = %s", strMobileTel)); if( strMobileTel.Compare("") ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); // 开始通知 if( pSmsDllSendSms != NULL && g_bAlarmNoticeFlag /*&& g_bSuccesOpen*/) { //LogEvent("发送短信,号码:%s, 内容:%s", strTel, pContent); if( strMobileTel.GetLength()!=11 ) continue; //判断是不是手机号码 只根据长度 LOG4C((LOG_NOTICE, "pSmsDllSendSms %s,%s",strMobileTel, pContent )); nResult = pSmsDllSendSms((char *)(LPCTSTR)strMobileTel, pContent, szResultMsg); //LOG4C((LOG_NOTICE, "pSmsDllSendSms nResult = %d",nResult )); if( nResult != 0 ) // 发送失败 { float fCSQ(0.0) ; pSmsDllGetCSQ( fCSQ ); if( fCSQ < 15 )//短信猫信号弱 { CDBInterface::GetInstancePtr()->InsertSmsRecord( "", "", (char *)(LPCTSTR)strTime, "send sms lost,Because the signal is too weak", ""); LOG4C((LOG_NOTICE, "send sms lost,Because the signal is too weak" )); return 0; } //LOG4C((LOG_NOTICE, "send sms lost, tel: %s, content: %s, code: %s", strMobileTel, pContent, szResultMsg)); // 发送失败,重试十次,如果还是失败,则放弃 for( int iReSend = 0; iReSend < 5; iReSend++ ) { nResult = pSmsDllSendSms((char *)(LPCTSTR)strMobileTel, pContent, szResultMsg); if( nResult == 0 ) { CString strTemp = ""; strTemp.Format("The last may be sent lost, again sent: %s", pContent); LOG4C((LOG_NOTICE, "send sms success, tel: %s, content: %s", strMobileTel, pContent)); CDBInterface::GetInstancePtr()->InsertSmsRecord( (char *)(LPCTSTR)strMobileTel, "", (char *)(LPCTSTR)strTime, (char *)(LPCTSTR)strTemp, ""); break; } else { LOG4C((LOG_NOTICE, "send sms lost, tel: %s, content: %s", strMobileTel, pContent)); } Sleep( 100 ); } } else { CDBInterface::GetInstancePtr()->InsertSmsRecord( (char *)(LPCTSTR)strMobileTel, "", (char *)(LPCTSTR)strTime, pContent, ""); LOG4C((LOG_NOTICE, "send sms success, tel: %s, content: %s, code: %s", strMobileTel, pContent, szResultMsg)); } } } } } } return 0; } // 发送Email INT SendEmail(CHAR *pDevUid, int nVarID, CHAR *pContent) { CString strEmail; char szResultMsg[MAX_MSG_LENGTH + 1] = {0}; int nResult = -1; memset( szResultMsg, 0, sizeof(szResultMsg) ); for( int i = 0; i < (int)g_vtUserRoleInfo.size(); i++ ) { if( strcmp(g_vtUserRoleInfo[i].szDevUID, pDevUid) == 0 ) { for( int j = 0; j < (int)g_vtUserRoleInfo[i].vtUserInfo.size(); j++ ) { strEmail = CString(g_vtUserRoleInfo[i].vtUserInfo[j].szEmail); if( strEmail.Compare("") ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); if( pEmailDllSendEmail ) { //LOG4C((LOG_NOTICE, "start send email")); // 开始通知 nResult = pEmailDllSendEmail( (char *)(LPCSTR)strEmail, g_strEmailSubject, pContent, (char *)(LPCTSTR)strTime, szResultMsg ); if( nResult != 0 ) //发送失败 { LOG4C((LOG_NOTICE, "Email to %s, Contect:%s send lost: %s", strEmail, pContent, szResultMsg)); } else { CDBInterface::GetInstancePtr()->InsertEmailRecord( (char *)(LPCTSTR)strEmail, "", (char *)(LPCTSTR)strTime, pContent, ""); //LOG4C((LOG_NOTICE, "Email to %s, Contect:%s send success: %s", strEmail, pContent, szResultMsg)); } } } } } } return 0; } // 添加有管理某个设备所有用户的电话号码和手机号码 void InsertUserTel(VAR_NOTICE *pVarNotice) { CString strTel; int nDevSize = (int)g_vtUserRoleInfo.size(); for( int i = 0; i < nDevSize; i++ ) { // 判断该用户是否具有该设备的报警权限; if( strcmp(g_vtUserRoleInfo[i].szDevUID, pVarNotice->szDevUID) == 0 ) { // 获取该设备 具有接收报警的所有用户; int nUserSize = (int)g_vtUserRoleInfo[i].vtUserInfo.size(); for( int j = 0; j < nUserSize; j++ ) { // 加入电话号码 strTel = CString(g_vtUserRoleInfo[i].vtUserInfo[j].szTel); if( strTel.Compare("") ) { pVarNotice->listTel.insert(pVarNotice->listTel.end(), strTel); //TRACE1("电话号码:%s\r\n", strTel); } //// 加入手机号码 //strTel = CString(g_vtUserRoleInfo[i].vtUserInfo[j].szMobileTel); //if( strTel.Compare("") ) //{ // pVarNotice->listTel.insert(pVarNotice->listTel.end(), strTel); // //TRACE1("手机号码:%s\r\n", strTel); //} } } } } // 更新要发送对象的手机号码 INT UpdateActiveTel( CHAR *pDevUid, CHAR *pStrTel ) { int nSize = g_vtUserRoleInfo.size(); for( int i = 0; i < nSize; i++ ) { if( strcmp(g_vtUserRoleInfo[i].szDevUID, pDevUid) == 0 ) { //g_vtUserTelInfo[i].strActiveTel = pStrTel; } } return 0; } // 报警状态恢复正常处理 void ProcessVarStatusReturnNormal(char *pDevUid, int nVarID, int nAlarmStatus, int nNormalStatus, int nIdenfityTime, int nReDetectTime, int nNormalIsNotice, char *pDevName, char *pVarDesc, double dbData, char *pContent, VAR_NOTICE *pVarNotice, int nUpperLimit, int nLowerLimit ) { if( nNormalIsNotice ) // 恢复正常触发远程报警 { if( g_nSendNotice ) { LIST_TEL::iterator it; CString *pStrTel; for( it = pVarNotice->listTel.begin(); it != pVarNotice->listTel.end(); it++ ) { pStrTel = &(*it); // 加入语音发送list EnterCriticalSection( &g_csVarNotice ); //LOG4C((LOG_NOTICE, "拔打恢复正常电话,号码:%s, 内容:%s", (char *)(LPCTSTR)*pStrTel, pContent)); InsertSendNoticeList(pDevUid, nVarID, (char *)(LPCTSTR)*pStrTel, pContent,g_nAlarmIndex); //pVarNotice->listTel.erase(it); LeaveCriticalSection( &g_csVarNotice ); } } //发送恢复正常信息给客户端 g_pServerSocket[1]->AutoSendAlarmDataToClient( pDevUid,nVarID,1,pContent,dbData,nUpperLimit,nLowerLimit,nNormalStatus,nAlarmStatus,g_nAlarmIndex ); int nDeviceIndex = -1, nVarIndex = -1; BOOL bFind = FindVar(pDevUid, nVarID, nDeviceIndex, nVarIndex); if( bFind == TRUE ) { CDevice *pDev = g_pDevicesManager->m_Devices[nDeviceIndex]; CBaseVar *pBaseVar = pDev->m_Vars[nVarIndex]; EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmNumber = 0; pVarNotice->nLastStatus = nAlarmStatus; pVarNotice->nCallTime = 0; pVarNotice->nSmsTime = 0; LeaveCriticalSection( &g_csVarNotice ); } if( g_nSendSms==1 ) { // 发送短信 InsertSendSmsList( pDevUid, nVarID, pContent,g_nAlarmIndex ); //SendSms(pDevUid, nVarID, pContent); } else if( g_nSendSms==2 )//支持短信平台 { WriteToTxt(pDevUid, nVarID, pContent,g_nAlarmIndex); } if( g_nSendEmail ) { // 发送Email SendEmail(pDevUid, nVarID, pContent); } } g_nAlarmIndex++; if( g_nAlarmIndex>=1000 ) g_nAlarmIndex = 0; CString strTime; CTime tm; tm = CTime::GetCurrentTime(); strTime = tm.Format("%Y-%m-%d %H:%M:%S"); CDBInterface::GetInstancePtr()->InsertWarningRecord(pDevName, pVarDesc, (char *)(LPCTSTR)strTime, nAlarmStatus, dbData, "", pContent); } void ProcessVarAlarm(char *pDevUid, int nVarID, int nAlarmStatus, int nNormalStatus, int nIdenfityTime, int nReDetectTime, int nNormalIsNotice, char *pDevName, char *pVarDesc, double dbData, char *pContent, VAR_NOTICE *pVarNotice, int nUpperLimit, int nLowerLimit ) { if( pVarNotice->nCallTime > g_nNoticeCallTimes - 1 ) // 第一次拔打没算次数, 所以这里减1 { if( pVarNotice->dwReDetectTick == 0 ) { EnterCriticalSection( &g_csVarNotice ); pVarNotice->dwReDetectTick = GetTickCount(); LeaveCriticalSection( &g_csVarNotice ); } // 超过重新检测等待时间,从list中删除该变量 if( GetTickCount() - pVarNotice->dwReDetectTick > (DWORD)(nReDetectTime * 1000 * 60) ) { int nDeviceIndex = -1, nVarIndex = -1; BOOL bFind = FindVar(pDevUid, nVarID, nDeviceIndex, nVarIndex); if( bFind == TRUE ) { CDevice *pDev = g_pDevicesManager->m_Devices[nDeviceIndex]; CBaseVar *pBaseVar = pDev->m_Vars[nVarIndex]; EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmNumber = 0; pBaseVar->m_nAlarmStatus = 0; LeaveCriticalSection( &g_csVarNotice ); } // 从list中删除变量时,要保证其它地方不去取list变量 EnterCriticalSection( &g_csVarNotice ); // ResetEvent时也不允许任何人进来,故此把临界区放在ResetEvent之前。 ResetEvent( g_hDeleteVarSem ); DeleteVarNoticeList(pDevUid, nVarID); SetEvent( g_hDeleteVarSem ); LeaveCriticalSection( &g_csVarNotice ); } return; } //语音通知 if( g_nSendNotice ) { LIST_TEL::iterator it; CString *pStrTel; for( it = pVarNotice->listTel.begin(); it != pVarNotice->listTel.end(); it++ ) { pStrTel = &(*it); // 加入语音发送list EnterCriticalSection( &g_csVarNotice ); //LOG4C((LOG_NOTICE, "拔打报警电话,号码:%s, 内容:%s", (char *)(LPCTSTR)*pStrTel, pContent)); InsertSendNoticeList(pDevUid, nVarID, (char *)(LPCTSTR)*pStrTel, pContent,g_nAlarmIndex); LeaveCriticalSection( &g_csVarNotice ); } } //发送报警信息给客户端 g_pServerSocket[1]->AutoSendAlarmDataToClient( pDevUid,nVarID,0,pContent,dbData,nUpperLimit,nLowerLimit,nNormalStatus,nAlarmStatus,g_nAlarmIndex ); EnterCriticalSection( &g_csVarNotice ); pVarNotice->nCallTime++; LeaveCriticalSection( &g_csVarNotice ); if( pVarNotice->nSmsTime > g_nSmsCallTimes - 1 ) // 第一次发送没算次数, 所以这里减1 { if( g_nSendNotice == 0 ) { if( pVarNotice->dwReDetectTick == 0 ) { EnterCriticalSection( &g_csVarNotice ); pVarNotice->dwReDetectTick = GetTickCount(); LeaveCriticalSection( &g_csVarNotice ); } // 超过重新检测等待时间,从list中删除该变量 if( GetTickCount() - pVarNotice->dwReDetectTick > (DWORD)(nReDetectTime * 1000 * 60) ) { int nDeviceIndex = -1, nVarIndex = -1; BOOL bFind = FindVar(pDevUid, nVarID, nDeviceIndex, nVarIndex); if( bFind == TRUE ) { CDevice *pDev = g_pDevicesManager->m_Devices[nDeviceIndex]; CBaseVar *pBaseVar = pDev->m_Vars[nVarIndex]; EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmNumber = 0; pBaseVar->m_nAlarmStatus = 0; LeaveCriticalSection( &g_csVarNotice ); } // 从list中删除变量时,要保证其它地方不去取list变量 EnterCriticalSection( &g_csVarNotice ); // ResetEvent时也不允许任何人进来,故此把临界区放在ResetEvent之前。 ResetEvent( g_hDeleteVarSem ); DeleteVarNoticeList(pDevUid, nVarID); SetEvent( g_hDeleteVarSem ); LeaveCriticalSection( &g_csVarNotice ); } } return; } //LOG4C((LOG_NOTICE, "send sms:%s", pContent)); //短信通知 if( g_nSendSms==1 ) { // 发送短信,所有用户一次性发完 InsertSendSmsList( pDevUid, nVarID, pContent,g_nAlarmIndex ); //SendSms(pDevUid, nVarID, pContent); } else if( g_nSendSms==2 )//支持短信平台 { WriteToTxt(pDevUid, nVarID, pContent,g_nAlarmIndex); } //邮件通知 if( g_nSendEmail ) { // 发送Email,所有用户一次性发完 SendEmail(pDevUid, nVarID, pContent); } EnterCriticalSection( &g_csVarNotice ); pVarNotice->nSmsTime++; LeaveCriticalSection( &g_csVarNotice ); g_nAlarmIndex++; if( g_nAlarmIndex>=1000 ) g_nAlarmIndex = 0; CString strTime; CTime tm; tm = CTime::GetCurrentTime(); strTime = tm.Format("%Y-%m-%d %H:%M:%S"); CDBInterface::GetInstancePtr()->InsertWarningRecord(pDevName, pVarDesc, (char *)(LPCTSTR)strTime, nAlarmStatus, dbData, "", pContent); } // 处理变量远程报警通知 int ProcessVarNotice(char *pDevUid, int nVarID, int nUpperLimit, int nLowerLimit, int nOffSet, int nAlarmStatus, int nNormalStatus, int nIdenfityTime, int nReDetectTime, int nNormalIsNotice, char *pDevName, char *pVarDesc, double dbData, char *pContent) { VAR_NOTICE *pVarNotice = NULL; pVarNotice = FindVarNoticeList(pDevUid, nVarID); // 查找报警变量是否存在报警列表中,不存在返回NULL,存在返回指针; // == NULL 该报警不存在列表里; if( NULL == pVarNotice ) { // 如果报警状态 与 正常状态不相同 ; if( nAlarmStatus != nNormalStatus ) { CString strTemp = CString(pContent); if( strTemp.Find(g_strHintReturnNormal) != -1 ) { return 0; } VAR_NOTICE tagVarNotice; strcpy(tagVarNotice.szDevUID, pDevUid); tagVarNotice.nVarID = nVarID; tagVarNotice.nResult = 0; tagVarNotice.nCallTime = 0; tagVarNotice.nSmsTime = 0; tagVarNotice.bQueueExist = false; tagVarNotice.dwIdentityTick = GetTickCount(); // 记录辨识时间 tagVarNotice.dwIntervalTick = 0; tagVarNotice.dwReDetectTick = 0; tagVarNotice.nLastStatus = nAlarmStatus; tagVarNotice.bFirstDeal = true; // 添加有权限用户的电话号码和手机号码 InsertUserTel(&tagVarNotice); tagVarNotice.nTelInex = 0; // 加入list,第一次加入不进行任何处理 EnterCriticalSection( &g_csVarNotice ); InsertVarNoticeList(tagVarNotice); LeaveCriticalSection( &g_csVarNotice ); } } else { if( nAlarmStatus == nNormalStatus ) // 正常状态 { // 防止报警恢复正常之后会一直打电话 if( nAlarmStatus == pVarNotice->nLastStatus ) { EnterCriticalSection( &g_csVarNotice ); pVarNotice->nLastStatus = nAlarmStatus; LeaveCriticalSection( &g_csVarNotice ); return 0; } EnterCriticalSection( &g_csVarNotice ); pVarNotice->nLastStatus = nAlarmStatus; LeaveCriticalSection( &g_csVarNotice ); //模拟量才有偏移量 if( nOffSet > 0 )//当偏移量大于0时,判断当前值是否达到偏移量这个条件 { CString strTemp = CString(pContent); //if( strTemp.Find(g_strHintReturnNormal) != -1 )//chn modify { if( dbData <= nUpperLimit - nOffSet || dbData >= nLowerLimit + nOffSet ) { ProcessVarStatusReturnNormal(pDevUid, nVarID, nAlarmStatus, nNormalStatus, nIdenfityTime, nReDetectTime, nNormalIsNotice, pDevName, pVarDesc, dbData, pContent, pVarNotice,nUpperLimit,nLowerLimit ); } } } else { ProcessVarStatusReturnNormal(pDevUid, nVarID, nAlarmStatus, nNormalStatus, nIdenfityTime, nReDetectTime, nNormalIsNotice, pDevName, pVarDesc, dbData, pContent, pVarNotice,nUpperLimit,nLowerLimit ); } } else if( nAlarmStatus != nNormalStatus ) // 报警状态 { //因为第一次加入List不进行任何处理,但状态已经保存,所以要加一个标志来判断一下 if( nAlarmStatus == pVarNotice->nLastStatus && !pVarNotice->bFirstDeal ) { EnterCriticalSection( &g_csVarNotice ); pVarNotice->nLastStatus = nAlarmStatus; LeaveCriticalSection( &g_csVarNotice ); return 0; } pVarNotice->bFirstDeal = false;// EnterCriticalSection( &g_csVarNotice ); pVarNotice->nLastStatus = nAlarmStatus; LeaveCriticalSection( &g_csVarNotice ); if( nOffSet > 0 ) { CString strTemp = CString(pContent); //if( strTemp.Find(g_strHintUpperLimit) != -1 || strTemp.Find(g_strHintLowerLimit) != -1 ) { if( dbData > nUpperLimit + nOffSet || dbData < nLowerLimit - nOffSet ) { ProcessVarAlarm(pDevUid, nVarID, nAlarmStatus, nNormalStatus, nIdenfityTime, nReDetectTime, nNormalIsNotice, pDevName, pVarDesc, dbData, pContent, pVarNotice,nUpperLimit,nLowerLimit ); } } } else { ProcessVarAlarm(pDevUid, nVarID, nAlarmStatus, nNormalStatus, nIdenfityTime, nReDetectTime, nNormalIsNotice, pDevName, pVarDesc, dbData, pContent, pVarNotice,nUpperLimit,nLowerLimit ); } } } return 1; } /////////////////////////////////////////////////////////////////////// // 报警变量list,主要报警处理,防止一直加入通知list中 // 从list中查找变量,没找到返回空,找到返回相应的指针地址 VAR_NOTICE* FindVarNoticeList(char *pDevUid, int nVarID) { VAR_NOTICE* pVarNotice = NULL; LIST_VAR_NOTICE::iterator it; for( it = g_listVarNotice.begin(); it != g_listVarNotice.end(); it++ ) { if( strcmp(it->szDevUID, pDevUid) == 0 && it->nVarID == nVarID ) pVarNotice = &(*it); } return pVarNotice; } // 添加变量到list void InsertVarNoticeList(char *pDevUid, int nVarID) { VAR_NOTICE tagVarNotice; strcpy(tagVarNotice.szDevUID, pDevUid); tagVarNotice.nVarID = nVarID; g_listVarNotice.insert(g_listVarNotice.end(), tagVarNotice); } // 添加变量到list void InsertVarNoticeList(VAR_NOTICE varNotice) { g_listVarNotice.insert(g_listVarNotice.end(), varNotice); } // 从list中移除变量 int DeleteVarNoticeList(char *pDevUid, int nVarID) { int nRet = -1; VAR_NOTICE* pVarNotice = NULL; LIST_VAR_NOTICE::iterator it; for( it = g_listVarNotice.begin(); it != g_listVarNotice.end(); ) { pVarNotice = &(*it); if( strcmp(pVarNotice->szDevUID, pDevUid) == 0 && pVarNotice->nVarID == nVarID ) { g_listVarNotice.erase(it++); nRet = 0; break; } else { it++; } } return nRet; } // 删除所有变量 void DeleteAllVarNoticeList() { LIST_VAR_NOTICE::iterator it; for( it = g_listVarNotice.begin(); it != g_listVarNotice.end(); ) { g_listVarNotice.erase(it++); } } /////////////////////////////////////////////////////////////////////////// // 发送通知list, 和上面的设备变量不同 // 从list中查找变量,没找到返回空,找到返回相应的指针地址 SEND_NOTICE* FindSendNoticeList(char *pDevUid, int nVarID) { SEND_NOTICE* pSendNotice = NULL; LIST_SEND_NOTICE::iterator it; for( it = g_listSendNotice.begin(); it != g_listSendNotice.end(); it++ ) { if( strcmp(it->szDevUID, pDevUid) == 0 && it->nVarID == nVarID ) pSendNotice = &(*it); } return pSendNotice; } // 添加变量到list void InsertSendNoticeList(char *pDevUid, int nVarID, char *pTel, char *pContent,int nAlarmIndex ) { if( pStoneUDLLTxtToWav ) { //生成WAV CString sTemp; sTemp.Format( "%s%s",pContent,g_strHintVoiceEnd ); CString strFileName1; strFileName1.Format("%s\\wav\\temp_%s_%d_%d.wav", g_strDirectory, pDevUid, nVarID,nAlarmIndex ); pStoneUDLLTxtToWav( (char *)(LPCTSTR)sTemp, (char *)(LPCTSTR)strFileName1, g_nTTSType, -3, 100 ); //设置音量,范围是 0 - 100 CString strFileName2; strFileName2.Format("%s\\wav\\temp_%s_%d_%d_IDE.wav", g_strDirectory, pDevUid, nVarID,nAlarmIndex ); pStoneUDLLTxtToWav( pContent, (char *)(LPCTSTR)strFileName2, g_nTTSType, -3, 100 ); //设置音量,范围是 0 - 100 //结束生成 } SEND_NOTICE tagSendNotice; strcpy(tagSendNotice.szDevUID, pDevUid); tagSendNotice.nVarID = nVarID; strcpy(tagSendNotice.szTel, pTel); strcpy(tagSendNotice.szContect, pContent); tagSendNotice.nAlarmIndex = nAlarmIndex; GetLocalTime( &tagSendNotice.time ); EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.insert(g_listSendNotice.end(), tagSendNotice); LeaveCriticalSection( &g_csSendNotice ); } // 从list中移除变量 int DeleteSendNoticeList(char *pDevUid, int nVarID) { int nRet = -1; SEND_NOTICE* pSendNotice = NULL; LIST_SEND_NOTICE::iterator it; for( it = g_listSendNotice.begin(); it != g_listSendNotice.end(); ) { pSendNotice = &(*it); if( strcmp(pSendNotice->szDevUID, pDevUid) == 0 && pSendNotice->nVarID == nVarID ) { EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.erase(it++); LeaveCriticalSection( &g_csSendNotice ); nRet = 0; break; } else { it++; } } return nRet; } // IDE确认后从list中移除变量 int DeleteSendNoticeList( char *pDevUid, int nVarID,int iAlarmIndex ) { int nRet = -1; SEND_NOTICE* pSendNotice = NULL; LIST_SEND_NOTICE::iterator it; for( it = g_listSendNotice.begin(); it != g_listSendNotice.end(); ) { pSendNotice = &(*it); if( strcmp(pSendNotice->szDevUID, pDevUid) == 0 && pSendNotice->nVarID == nVarID && pSendNotice->nAlarmIndex==iAlarmIndex ) { //删除WAV CString strFileName1; strFileName1.Format("%s\\wav\\temp_%s_%d_%d.wav", g_strDirectory, pDevUid, nVarID,iAlarmIndex ); if( PathFileExists(strFileName1) ) DeleteFile( strFileName1 ); CString strFileName2; strFileName2.Format("%s\\wav\\temp_%s_%d_%d_IDE.wav", g_strDirectory, pDevUid, nVarID,iAlarmIndex ); if( PathFileExists(strFileName2) ) DeleteFile( strFileName2 ); //结束删除 LOG4C((LOG_NOTICE, "IDE确认語音 %s %s",pSendNotice->szTel,pSendNotice->szContect)); EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.erase(it++); LeaveCriticalSection( &g_csSendNotice ); } else { it++; } } return nRet; } // 删除所有变量 void DeleteAllSendNoticeList() { #if 0 // 正确使用方法1 std::list< int> List; std::list< int>::iterator itList; for( itList = List.begin(); itList != List.end(); ) { if( WillDelete( *itList) ) { itList = List.erase( itList); } else itList++; } // 正确使用方法2 std::list< int> List; std::list< int>::iterator itList; for( itList = List.begin(); itList != List.end(); ) { if( WillDelete( *itList) ) { List.erase( itList++); } else itList++; } // 错误使用方法1 std::list< int> List; std::list< int>::iterator itList; for( itList = List.begin(); itList != List.end(); itList++) { if( WillDelete( *itList) ) { List.erase( itList); } } // 错误使用方法2 std::list< int> List; std::list< int>::iterator itList; for( itList = List.begin(); itList != List.end(); ) { if( WillDelete( *itList) ) { itList = List.erase( ++itList); } else itList++; } #endif LIST_SEND_NOTICE::iterator it; for( it = g_listSendNotice.begin(); it != g_listSendNotice.end(); ) { g_listSendNotice.erase( it++ ); } } // 添加变量到Sms list void InsertSendSmsList(char *pDevUid, int nVarID, char *pContent,int nAlarmIndex ) { //LOG4C((LOG_NOTICE, "InsertSendSmsList" )); SEND_NOTICE tagSendNotice; strcpy(tagSendNotice.szDevUID, pDevUid); tagSendNotice.nVarID = nVarID; strcpy(tagSendNotice.szTel, ""); strcpy(tagSendNotice.szContect, pContent); tagSendNotice.nAlarmIndex = nAlarmIndex; GetLocalTime( &tagSendNotice.time ); EnterCriticalSection( &g_csSendNotice ); g_listSendSms.insert(g_listSendSms.end(), tagSendNotice); LeaveCriticalSection( &g_csSendNotice ); } // IDE确认后从Sms list中移除变量 int DeleteSendSmsList( char *pDevUid, int nVarID,int iAlarmIndex ) { int nRet = -1; SEND_NOTICE* pSendNotice = NULL; LIST_SEND_NOTICE::iterator it; for( it = g_listSendSms.begin(); it != g_listSendSms.end(); ) { pSendNotice = &(*it); if( strcmp(pSendNotice->szDevUID, pDevUid) == 0 && pSendNotice->nVarID == nVarID && pSendNotice->nAlarmIndex==iAlarmIndex ) { LOG4C((LOG_NOTICE, "IDE确认短信 %s",pSendNotice->szContect)); EnterCriticalSection( &g_csSendNotice ); g_listSendSms.erase(it++); LeaveCriticalSection( &g_csSendNotice ); nRet = 0; break; } else { it++; } } return nRet; } // 删除Sms所有变量 void DeleteAllSendSmsList() { LIST_SEND_NOTICE::iterator it; for( it = g_listSendSms.begin(); it != g_listSendSms.end(); ) { g_listSendSms.erase( it++ ); } } //////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////// ////// 函数名称:SendNotice /////// ////// 函数说明:开始语音通知 /////// ////// 参数列表:strTel -- 待通知的电话号码 /////// ////// strContent -- 短信内容 /////// ////// 作 者:sailing /////// ////// 创者时间:2009-02-23 /////// /////////////////////////////////////////////////////////////////////////////////////////////// // 语音通知. // SendNotice 给语音报警线程调用; INT SendNotice(CHAR *pUid, int nVarID,int nAlarmIndex, CHAR *pTel, CHAR *pContent) { //如果是短信确认关闭报警通知则退出 if( !g_bAlarmNoticeFlag ) return -1; int nRet = 0; CString str, strMsg; str = CString(" ") + pContent; // g_strHintAlarmWelcome + str = str + g_strHintVoiceEnd; //" 重新请按1,确认请按2,结束请直接挂机"; if( ( NULL != g_hNoticeLibModule ) && (NULL != pStoneUDllAllocateChannel) ) { //strMsg.Format("开始发送语音通知!", pTel); //AddToPrintQueue( MSG_OK, MSG_NOTICE_MD, (char*)(LPCTSTR)strMsg, strMsg.GetLength() ); int nResult = pStoneUDllAllocateChannel( pTel, g_strNoticeTelPre, pUid, nVarID,nAlarmIndex, (char *)(LPCTSTR)str ); nRet = nResult; if( nRet != CALL_LOST ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); CDBInterface::GetInstancePtr()->InsertNoticeRecord( pTel, "", (char *)(LPCTSTR)strTime, (char *)(LPCTSTR)pContent, ""); } } return nRet; } // 被语音通知线程调用; // 获取当前语音通知手机用户的数据库表中的索引值 ; int GetTelIndex( char *pDevUid, int nVarID, CString sTel ) { int nRet=-1; if( g_listVarNotice.size()==0 ) { LOG4C((LOG_NOTICE, "g_listVarNotice.size()= %d",g_listVarNotice.size()==0)); return nRet; } VAR_NOTICE* pVarNotice = NULL; LIST_VAR_NOTICE::iterator it; for( it = g_listVarNotice.begin(); it != g_listVarNotice.end(); it++ ) { if( strcmp(it->szDevUID, pDevUid) == 0 && it->nVarID == nVarID ) { pVarNotice = &(*it); break; } } if( pVarNotice ) { LIST_TEL::iterator itTel; CString *pStrTel; for( itTel = pVarNotice->listTel.begin(); itTel != pVarNotice->listTel.end(); itTel++ ) { pStrTel = &(*itTel); nRet++; if( strcmp(sTel, *pStrTel) == 0 ) { break; } } } else LOG4C((LOG_NOTICE, "pVarNotice=NULL g_listVarNotice.size() = %d",g_listVarNotice.size())); return nRet; } // // 语音报警发送,实时监测报警信息线程; // 1.判断当前 <语音通知列表> 是否为空; // 2.获取通知列表第一条记录,进行第一次语音通知. // 3.根据第次语音通知返回的结果判断 // a.返回结果 == 确认当前1条报警,后继该报警记录 语音通知将不对剩下用户发送. // b.返回结果 == 确认当前全部报警记录,后继不再有任何操作. // c.返回结果 == 取消语音通知. DWORD WINAPI SendNoticeThread(LPVOID lpParameter) { // g_listSendNotice:是记录1条报警,所有用户语音通知? // g_listSendNotice:是记录当前所有报警,所有用户语音通知? // 根据下面的运行情况,应该是当前一次性所有存在的报警记录的所有用户的语音通知. do { // 当前报警记录数 > 0 if( g_listSendNotice.size() > 0 ) { SEND_NOTICE *pSendNotice; LIST_SEND_NOTICE::iterator it; it = g_listSendNotice.begin(); pSendNotice = &(*it); CString sCurrentTel; // 从列表里获取的记录不为空; if( pSendNotice ) { SYSTEMTIME st; GetLocalTime( &st ); CTime time1(st); CTime time2(pSendNotice->time); CTimeSpan spantime = time1 - time2; int nSecNum = spantime.GetSeconds() + spantime.GetMinutes()*60 + spantime.GetHours()*60*60; // 报警已发生时间 > 通知延时值 if( nSecNum > NOTICE_DELAY ) { LOG4C((LOG_NOTICE, "开始拨打电话 %s",pSendNotice->szTel)); int nRet = SendNotice(pSendNotice->szDevUID, pSendNotice->nVarID,pSendNotice->nAlarmIndex, pSendNotice->szTel, pSendNotice->szContect); sCurrentTel.Format( "%s",pSendNotice->szTel ); LOG4C((LOG_NOTICE, "结束拨打电话 %s",pSendNotice->szTel)); //删除WAV(在调用 SendNotice时,会生成wav文件) CString strFileName1; strFileName1.Format("%s\\wav\\temp_%s_%d_%d.wav", g_strDirectory, pSendNotice->szDevUID, pSendNotice->nVarID,pSendNotice->nAlarmIndex ); if( PathFileExists(strFileName1) ) DeleteFile( strFileName1 ); CString strFileName2; strFileName2.Format("%s\\wav\\temp_%s_%d_%d_IDE.wav", g_strDirectory, pSendNotice->szDevUID, pSendNotice->nVarID,pSendNotice->nAlarmIndex ); if( PathFileExists(strFileName2) ) DeleteFile( strFileName2 ); //结束删除 // 语音通知结果返回 == 确认当前报警记录通知,后继所有电话手机将不在语音通知该报警记录; if( nRet == CALL_SUCCESS_SINGLE_CONFIRM ) { int nCurrentTelIndex=0,nTelIndex=0; nCurrentTelIndex = GetTelIndex( pSendNotice->szDevUID, pSendNotice->nVarID, sCurrentTel ); EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.erase(it++);//先把当前的报警记录删除 LeaveCriticalSection( &g_csSendNotice ); // 删除当前通知后,通知列表 > 0 if( g_listSendNotice.size() > 0 ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); // 将当前已确认的语音记录插入数据库中 . 这个不是在删除当前报警记录后,if(记录数 > 0)前加入的么?????? // 如果删除当前通知,列表为空,那记录就不插入表了??? CDBInterface::GetInstancePtr()->InsertNoticeRecord( (char *)(LPCTSTR)sCurrentTel, "", (char *)(LPCTSTR)strTime, "config one alert", ""); // 当前报警记录已被确认,所以所有该报警的用户语音通知将取消; // 删除所有该报警记录的用户语音通知; EnterCriticalSection( &g_csSendNotice ); LIST_SEND_NOTICE::iterator itTemp; for( itTemp = g_listSendNotice.begin(); itTemp != g_listSendNotice.end(); ) { nTelIndex = GetTelIndex( itTemp->szDevUID,itTemp->nVarID,itTemp->szTel ); //LOG4C((LOG_NOTICE, "%s,nCurrentTelIndex = %d,%s,nTelIndex=%d ",sCurrentTel,nCurrentTelIndex,itTemp->szTel,nTelIndex )); // 从第一个用户开始发送第一条语音通知,获得nCurrentTelIndex // 在该索引之下的所有用户的索引将大于第一用户索引 nTelIndex > nCurrentTelIndex; // 但是,这样做删除操作好么?安全么? if( nCurrentTelIndexszTel )); g_listSendNotice.erase(itTemp++); } else { break; } } LeaveCriticalSection( &g_csSendNotice ); } } else if( nRet==CALL_SUCCESS_ALL_CONFIRM )// 语音通知结果返回 == 确认全部报警记录通知,当前列表所有报警记录将取消语音通知; { EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.erase(it++);//先把当前的删除 if( g_listSendNotice.size() > 0 ) { CTime time = CTime::GetCurrentTime(); CString strTime; strTime = time.Format("%Y-%m-%d %H:%M:%S"); // 将语音通知插入表. -->这个放在if前好,还是if里好? CDBInterface::GetInstancePtr()->InsertNoticeRecord( (char *)(LPCTSTR)sCurrentTel, "", (char *)(LPCTSTR)strTime, "config all alert", ""); LIST_SEND_NOTICE::iterator itTemp; for( itTemp = g_listSendNotice.begin(); itTemp != g_listSendNotice.end(); ) { LOG4C((LOG_NOTICE, "通知全部已经被确认,跳过号码 %s",itTemp->szTel )); g_listSendNotice.erase(itTemp++); } } LeaveCriticalSection( &g_csSendNotice ); } else if( nRet != CALL_LOST ) { EnterCriticalSection( &g_csSendNotice ); g_listSendNotice.erase(it++); LeaveCriticalSection( &g_csSendNotice ); } } Sleep( 10 * 1000 );//Sleep( 30 * 1000 ); } } }while( WaitForSingleObject(g_hRunObject, 200L) == WAIT_TIMEOUT ); return 0; } // // 短信报警发送,实时监测报警信息线程; // 1.判断当前 <短信通知列表> 是否为空; // 2.循环发送短信通知; DWORD WINAPI SendSmsThread(LPVOID lpParameter) { LOG4C((LOG_NOTICE,"短信线程启动")); do { if( g_listSendSms.size() > 0 ) { //SEND_NOTICE *pSendNotice; // 这个变量有意义么?块局部变量,每次do后都没用了,it++要来何用? LIST_SEND_NOTICE::iterator it; it = g_listSendSms.begin(); //pSendNotice = &(*it); CString sCurrentTel; SYSTEMTIME st; CTime time1;//(st); CTime time2;//(pSendNotice->time); CTimeSpan spantime; if( /*pSendNotice*/ &it) { //LOG4C((LOG_NOTICE, "SendSmsThread size>0" )); GetLocalTime( &st ); time1 = st; time2 = /*pSendNotice->time*/(*it).time; spantime = time1 - time2; int nSecNum = spantime.GetSeconds() + spantime.GetMinutes()*60 + spantime.GetHours()*60*60; if( nSecNum > NOTICE_DELAY ) { //LOG4C((LOG_NOTICE, "SendSmsThread NOTICE_DELAY" )); //SendSms( pSendNotice->szDevUID,pSendNotice->nVarID,pSendNotice->szContect ); SendSms((*it).szDevUID, (*it).nVarID,(*it).szContect); EnterCriticalSection( &g_csSendNotice ); //g_listSendSms.erase(it++); g_listSendSms.erase(it); LeaveCriticalSection( &g_csSendNotice ); } } } /* else LOG4C((LOG_NOTICE,"报警列表 = 0"));*/ }while( WaitForSingleObject(g_hRunObject, 200L) == WAIT_TIMEOUT ); return 0; } int GetVarstatus(double iParaValue, int iUpperLimit, int iLowerLimit, int iNormalState) { int iResult = iNormalState; if ( ( iUpperLimit >0 || iLowerLimit > 0 ) && iUpperLimit > iLowerLimit) { //iResult = (iParaValue >= iUpperLimit || iParaValue <= iLowerLimit); if( iParaValue > iUpperLimit ) { iResult = UPPER_LIMIT_ID; // 上限告警 } if( iParaValue < iLowerLimit ) { iResult = LOWER_LIMIT_ID; // 下限告警 } else { return iResult; } } else if( (int)iParaValue != iNormalState ) { iResult = (int)iParaValue; } return iResult; } // 1.对每个变量进行报警类型获取; // 2. int VarAlarmNotice(CDevice *pDev, CBaseVar *pBaseVar) { // 组织报警内容 CString strContect; char szStatusDesc[MAX_EQUIP_DESC + 1] = {0}; char szStatusID[MAX_ID + 1] = {0}; memset(szStatusDesc, 0, sizeof(szStatusDesc)); if( pBaseVar->m_nWaringLevel == 0 ) return 1; //LOG4C((LOG_NOTICE, "变量名 desc = %s,当前值 %d,上下限 = %d / %d", pBaseVar->m_strDesc, pBaseVar->m_dbData ,pBaseVar->m_nUpperLimit,pBaseVar->m_nLowerLimit)); // 获取变量的报警类型; int nTempStatus = GetVarstatus(pBaseVar->m_dbData, pBaseVar->m_nUpperLimit, pBaseVar->m_nLowerLimit, pBaseVar->m_nNormalState); if( UPPER_LIMIT_ID == nTempStatus ) // 上限告警 { strcpy(szStatusDesc, g_strHintUpperLimit); //LOG4C((LOG_NOTICE, "var desc = %s, %s", pBaseVar->m_strDesc, szStatusDesc)); } else if( LOWER_LIMIT_ID == nTempStatus ) // 下限告警 { strcpy(szStatusDesc, g_strHintLowerLimit); } // 这个else if,如果上面两个有一个成立,下面这个也是有可能成立的; else if( nTempStatus != pBaseVar->m_nNormalState ) { list::iterator it_desc, it_id; if( pBaseVar->m_listStatusDesc.size() > 0 && pBaseVar->m_listStatusID.size() > 0 ) { for( it_desc = pBaseVar->m_listStatusDesc.begin(), it_id = pBaseVar->m_listStatusID.begin(); it_desc != pBaseVar->m_listStatusDesc.end(), it_id != pBaseVar->m_listStatusID.end(); ) { CString strStatusID = (*it_id++).c_str(); CString strStatusDesc = (*it_desc++).c_str(); // 又因为这一步的存在,使得即使本层if成立 之前已经有if成立,也是不会修改报警内容的; if( atoi(strStatusID) == nTempStatus ) { //LOG4C((LOG_NOTICE, "var desc = %s, nTempStatus = %d, StatusID = %d statusdesc = %s, value = %d",pBaseVar->m_strDesc, nTempStatus, atoi(strStatusID), strStatusDesc, (int)pBaseVar->m_dbData)); strcpy(szStatusDesc, (char *)(LPCTSTR)strStatusDesc); //LOG4C((LOG_NOTICE, "szStatusDesc=%s", szStatusDesc)); break; } } } // 如果报警状态描述为空,退出; if( strcmp(szStatusDesc, "") == 0 ) { //LOG4C((LOG_NOTICE, "VarAlarmNotice var = %s nTempStatus = %d NormalState = %d statudesc is null!", pBaseVar->m_strDesc, nTempStatus, pBaseVar->m_nNormalState)); return 1; } } /************************************************************************************************************ 在之前的所有操作,都是获取变量是否存在报警(上下限报警,状态报警等.....); 获取变量的报警信息后,才判断变量<是否报警显示当前值> ***********************************************************************************************************/ if( nTempStatus != pBaseVar->m_nNormalState ) // 报警状态 { // 是否触发远程报警 m_bReserved1 : 报警显示当前值 if( pBaseVar->m_bReserved1 == true ) { // 是否有关联的其它变量; if( pBaseVar->m_strReserved1.Compare("") == 0 ) { strContect.Format("%s%s:%s, %s%d%s ", pDev->m_strReserved1, pBaseVar->m_strDesc, szStatusDesc, g_strHintCurrValue, (int)pBaseVar->m_dbData, pBaseVar->m_strUnit); } else { int nDeviceIndex = -1, nVarIndex = -1; // 查找报警变量联动的变量m_strReserved1; BOOL bFind = FindVar(pBaseVar->m_strVarUID, pBaseVar->m_strReserved1, nDeviceIndex, nVarIndex); if( bFind == FALSE ) { strContect.Format("%s%s:%s, %s%d%s ", pDev->m_strReserved1, pBaseVar->m_strDesc, szStatusDesc, g_strHintCurrValue, (int)pBaseVar->m_dbData, pBaseVar->m_strUnit); } else { CDevice *pDev = g_pDevicesManager->m_Devices[nDeviceIndex]; CBaseVar *pTempBaseVar = pDev->m_Vars[nVarIndex]; strContect.Format("%s%s:%s, %s%d%s ", pDev->m_strReserved1, pBaseVar->m_strDesc, szStatusDesc, g_strHintCurrValue, (int)pTempBaseVar->m_dbData, pBaseVar->m_strUnit); } } } else { strContect.Format("%s%s:%s ", pDev->m_strReserved1, pBaseVar->m_strDesc, szStatusDesc); } if( pBaseVar->m_bExistDatePlan ) { if( pBaseVar->m_dwReturnNormalIdentityTick>0 ) { pBaseVar->m_dwReturnNormalIdentityTick = 0; //LOG4C(( LOG_NOTICE,"var=%s 恢复正常未达到辩识时间条件又收到报警值,放弃加入",pBaseVar->m_strDesc)); } if( pBaseVar->m_dwIdentityTick == 0 && pBaseVar->m_nAlarmStatus!=2 ) { //EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_dwIdentityTick = GetTickCount(); //LeaveCriticalSection( &g_csVarNotice ); //LOG4C((LOG_NOTICE, "var=%s 达到报警条件", pBaseVar->m_strDesc)); } else if( pBaseVar->m_nAlarmStatus==0 ) { //LOG4C((LOG_NOTICE, "var=%s 第一次达到报警条件,不用判断辩识时间,直接加入", pBaseVar->m_strDesc)); ProcessVarNotice( (char *)(LPCTSTR)pBaseVar->m_strVarUID, pBaseVar->m_nVarID, pBaseVar->m_nUpperLimit, pBaseVar->m_nLowerLimit, pBaseVar->m_nOffset, nTempStatus, pBaseVar->m_nNormalState, pBaseVar->m_nIdentifyTime, pBaseVar->m_nReDetectTime, pBaseVar->m_bNormalIsNotice, "", (char *)(LPCTSTR)pBaseVar->m_strDesc, pBaseVar->m_dbData, (char *)(LPCTSTR)strContect ); EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmStatus = 1;//设为第一次报警状态 pBaseVar->m_strContent = strContect; pBaseVar->m_nLastStatus = nTempStatus; pBaseVar->m_dwIdentityTick = 0; LeaveCriticalSection( &g_csVarNotice ); } else if( GetTickCount() - pBaseVar->m_dwIdentityTick > (DWORD)pBaseVar->m_nIdentifyTime * 1000 && pBaseVar->m_nAlarmStatus!=2 ) { LOG4C((LOG_NOTICE, "var=%s 达到报警辩识时间条件,加入", pBaseVar->m_strDesc)); if( 1 == g_nSnmpEnable ) { CString strSetValue; strSetValue.Format("%.1f,A", pBaseVar->m_dbData); CString strTime; CTime tm; tm = CTime::GetCurrentTime(); strTime = tm.Format("%Y-%m-%d %H:%M:%S"); CString strTrapContent = ""; strTrapContent.Format("%s_%s_%s,A", pDev->m_strDeviceName, strTime, strContect); //LOG4C((LOG_NOTICE, "%s", strSetValue)); CString strObjID; strObjID.Format("%s.%d", g_strSnmpObjOid, pBaseVar->m_nVarID); pSnmpDllSetValue( g_strSnmpIP, g_strSnmpField, (char *)(LPCTSTR)strObjID, "str", 1, 300, (char *)(LPCTSTR)strTrapContent ); } if( pBaseVar->m_nAlarmNumber < 10 ) pBaseVar->m_nAlarmNumber++; ProcessVarNotice( (char *)(LPCTSTR)pBaseVar->m_strVarUID, pBaseVar->m_nVarID, pBaseVar->m_nUpperLimit, pBaseVar->m_nLowerLimit, pBaseVar->m_nOffset, nTempStatus, pBaseVar->m_nNormalState, pBaseVar->m_nIdentifyTime, pBaseVar->m_nReDetectTime, pBaseVar->m_bNormalIsNotice, "", (char *)(LPCTSTR)pBaseVar->m_strDesc, pBaseVar->m_dbData, (char *)(LPCTSTR)strContect ); EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmStatus = 2;//设为第二次报警状态 pBaseVar->m_strContent = strContect; pBaseVar->m_nLastStatus = nTempStatus; pBaseVar->m_dwIdentityTick = 0; LeaveCriticalSection( &g_csVarNotice ); } else { #if 0 if( 1 == g_nSnmpEnable ) { if( TRUE == pBaseVar->m_bIsChange ) { CString strSetValue; strSetValue.Format("%.1f", pBaseVar->m_dbData); CString strObjID; strObjID.Format("%s.%d", g_strSnmpObjOid, pBaseVar->m_nVarID); pSnmpDllSetValue( g_strSnmpIP, g_strSnmpField, (char *)(LPCTSTR)strObjID, "str", 1, 300, (char *)(LPCTSTR)strSetValue ); } } #endif } } } else { if( pBaseVar->m_dwIdentityTick>0 ) { pBaseVar->m_dwIdentityTick = 0; //LOG4C(( LOG_NOTICE,"var=%s 报警未达到辩识时间条件又收到正常值,放弃加入",pBaseVar->m_strDesc)); } // m_nAlarmNumber :报警的次数; if( pBaseVar->m_nAlarmNumber >= 1 && pBaseVar->m_nAlarmNumber < 11 ) // 为什么要 < 11呢??? { strContect.Format("%s%s:%s ", pDev->m_strReserved1, pBaseVar->m_strDesc, g_strHintReturnNormal); if( pBaseVar->m_dwReturnNormalIdentityTick == 0 ) { //EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_dwReturnNormalIdentityTick = GetTickCount(); //LeaveCriticalSection( &g_csVarNotice ); //LOG4C((LOG_NOTICE, "var=%s 达到恢复正常条件", pBaseVar->m_strDesc)); } else if( GetTickCount() - pBaseVar->m_dwReturnNormalIdentityTick > (DWORD)pBaseVar->m_nIdentifyTime * 1000 ) { LOG4C((LOG_NOTICE, "var=%s 达到恢复正常辩识时间条件,加入", pBaseVar->m_strDesc)); pBaseVar->m_nAlarmNumber = 0; //回复正常 ProcessVarNotice( (char *)(LPCTSTR)pBaseVar->m_strVarUID, pBaseVar->m_nVarID, pBaseVar->m_nUpperLimit, pBaseVar->m_nLowerLimit, pBaseVar->m_nOffset, nTempStatus, pBaseVar->m_nNormalState, pBaseVar->m_nIdentifyTime, pBaseVar->m_nReDetectTime, pBaseVar->m_bNormalIsNotice, "", (char *)(LPCTSTR)pBaseVar->m_strDesc, pBaseVar->m_dbData, (char *)(LPCTSTR)strContect ); EnterCriticalSection( &g_csVarNotice ); pBaseVar->m_nAlarmStatus = 3;//设为恢复正常状态 pBaseVar->m_strContent = strContect; pBaseVar->m_nLastStatus = nTempStatus; pBaseVar->m_dwReturnNormalIdentityTick = 0; LeaveCriticalSection( &g_csVarNotice ); if( 1 == g_nSnmpEnable ) { CString strSetValue; strSetValue.Format("%.1f,N", pBaseVar->m_dbData); CString strTime; CTime tm; tm = CTime::GetCurrentTime(); strTime = tm.Format("%Y-%m-%d %H:%M:%S"); CString strTrapContent = ""; strTrapContent.Format("%s_%s_%s,N", pDev->m_strDeviceName, strTime, strContect); //LOG4C((LOG_NOTICE, "%s", strTrapContent)); CString strObjID; strObjID.Format("%s.%d", g_strSnmpObjOid, pBaseVar->m_nVarID); pSnmpDllSetValue( g_strSnmpIP, g_strSnmpField, (char *)(LPCTSTR)strObjID, "str", 1, 300, (char *)(LPCTSTR)strTrapContent ); } } } else { #if 0 if( 1 == g_nSnmpEnable ) { if( TRUE == pBaseVar->m_bIsChange ) { CString strSetValue; strSetValue.Format("%.1f", pBaseVar->m_dbData); CString strObjID; strObjID.Format("%s.%d", g_strSnmpObjOid, pBaseVar->m_nVarID); pSnmpDllSetValue( g_strSnmpIP, g_strSnmpField, (char *)(LPCTSTR)strObjID, "str", "str", 1, 300, (char *)(LPCTSTR)strSetValue ); } } #endif } } return 0; }