📄 mobilecontrol.cpp
字号:
BOOL bInternationalMobileNO = TRUE;
ENUM_ERROR_TYPE eErrorType = ENUM_ERROR_TYPE_SUCCESS;
if ( ENUM_ERROR_TYPE_SUCCESS != StandardMobileNO ( csReceiverMobileNO, &bInternationalMobileNO ) )
{
Log ( L_WARNING, _T("Standard MobileNO failed") );
}
// 发送短信前做分条处理
ASSERT ( szSMSContent_Byte && strlen(szSMSContent_Byte) > 0 );
CStringArray *pAryStr = PartMessengerOrSMSText ( GetCompatibleString(szSMSContent_Byte,FALSE), 0, TRUE, NULL, NULL );
if ( !pAryStr ) return ENUM_ERROR_TYPE_PARAMETER;
for ( int i=0; i<pAryStr->GetSize(); i++ )
{
CString csTextOne = pAryStr->GetAt ( i );
csTextOne.TrimLeft(); csTextOne.TrimRight();
ENUM_ERROR_TYPE eErrorTypeTemp = SendOnePartSMS ( eMobileSMSType, csReceiverMobileNO, bInternationalMobileNO,
CMultiByteString(csTextOne).GetBuffer(), dwSMSSenderID_Sender, Proc_SendSMSEnd, wParam, lParam );
if ( eErrorTypeTemp != ENUM_ERROR_TYPE_SUCCESS )
{
eErrorType = eErrorTypeTemp;
}
}
pAryStr->RemoveAll();
delete pAryStr;
return eErrorType;
}
ENUM_ERROR_TYPE CMobileControl::InfillSMParam (
OUT SM_PARAM &SmParam,
IN CString csReceiverMobileNO // 接收者手机号
)
{
memset ( &SmParam, 0, sizeof(SM_PARAM) );
if ( !m_nInitOK ) return ENUM_ERROR_TYPE_NoneMobile;
GetSMSCNO ();
if ( m_csSMSC.GetLength() <= MIN_MOBILENO_LENGTH )
{
Log ( L_ERROR, _T("SMSC Error, Cancel send SMS to [%s]"), csReceiverMobileNO );
return ENUM_ERROR_TYPE_ConfigNotRight;
}
CString csSMSC = m_csSMSC;
// 填充短消息结构
StandardMobileNOHead ( csSMSC );
CMultiByteString ( csSMSC, STRING_IS_SOFTCODE, SmParam.SCA, sizeof(SmParam.SCA) );
CMultiByteString ( csReceiverMobileNO, STRING_IS_SOFTCODE, SmParam.TPA, sizeof(SmParam.TPA) );
SmParam.TP_PID = 0;
return ENUM_ERROR_TYPE_SUCCESS;
}
//
// 发送短信,过长的短信,这个模块不会处理,请在调用前先处理
//
ENUM_ERROR_TYPE CMobileControl::SendOnePartSMS (
ENUM_MOBILESMSTYPE eMobileSMSType,
LPCTSTR lpszReceiverMobileNO, // 接收者手机号
BOOL bInternationalMobileNO,
char* szSMSContent_Byte, // 单字节短信内容
DWORD dwSMSSenderID_Sender/*=INVALID_SMSSenderID*/, // 发送者的 PM 号码
FUNC_SendSMSEnd Proc_SendSMSEnd/*=NULL*/, // 发送完成时通过该回调函数来通知请求者
WPARAM wParam/*=NULL*/,
LPARAM lParam/*=NULL*/
)
{
if ( !szSMSContent_Byte || strlen(szSMSContent_Byte) <= 0 )
return ENUM_ERROR_TYPE_INVALID_DATA;
// 完全相同(短信内容和接收者手机号相同)的短信在 SAME_SMS_INTERVAL_TIMELONG 秒内不允许发送
// 防止短信炸弹,也防止 UDP 通信时收到重发的短信包
#ifndef _DEBUG
static CString csReceiverMobileNO_Last, csSMSContent_Last;
static time_t tTimeLast = 0;
if ( csReceiverMobileNO_Last == lpszReceiverMobileNO &&
csSMSContent_Last == szSMSContent_Byte )
{
if ( difftime ( time(NULL), tTimeLast ) < SAME_SMS_INTERVAL_TIMELONG )
{
return ENUM_ERROR_TYPE_RepeatedRequest;
}
}
csReceiverMobileNO_Last = GET_SAFE_STRING ( lpszReceiverMobileNO );
csSMSContent_Last = GET_SAFE_STRING ( szSMSContent_Byte );
tTimeLast = time(NULL);
#endif
// 队列是否满了?
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() > MAX_SMSQUEUE_NUM )
{
m_CSFor_SMSSendQueue.Unlock ();
return ENUM_ERROR_TYPE_BufferQueueFill;
}
m_CSFor_SMSSendQueue.Unlock ();
// 创建一个队列节点
t_SMS_SendQueue SMS_SendQueue;
memset ( &SMS_SendQueue, 0, sizeof(t_SMS_SendQueue) );
SMS_SendQueue.dwSMSSenderID_Sender = dwSMSSenderID_Sender;
SMS_SendQueue.Proc_SendSMSEnd = Proc_SendSMSEnd;
SMS_SendQueue.wParam = wParam;
SMS_SendQueue.lParam = lParam;
SMS_SendQueue.eMobileSMSType = eMobileSMSType;
ENUM_ERROR_TYPE eErrorType = InfillSMParam ( SMS_SendQueue.sm, GET_SAFE_STRING(lpszReceiverMobileNO) );
strncpy ( SMS_SendQueue.sm.TP_UD_Byte, szSMSContent_Byte, COUNT(SMS_SendQueue.sm.TP_UD_Byte) );
SMS_SendQueue.sm.bInternationalMobileNO = bInternationalMobileNO;
if ( eErrorType != ENUM_ERROR_TYPE_SUCCESS )
return eErrorType;
// 做服务器运行时,将要发送的短信包添加到队列中
BOOL bRes = TRUE;
if ( m_bRunAsServer )
{
m_CSFor_SMSSendQueue.Lock ();
m_Ary_SMS_SendQueue.Add ( SMS_SendQueue );
m_CSFor_SMSSendQueue.Unlock ();
// 然后通知手机工作线程
ASSERT ( m_hEvt_SMSSendQueue && m_hEvt_SMSSendQueue != INVALID_HANDLE_VALUE );
::SetEvent ( m_hEvt_SMSSendQueue );
}
// 单机版时直接发送短信
else
{
bRes = SendOneSMSQueue ( SMS_SendQueue );
}
return ( bRes ? ENUM_ERROR_TYPE_SUCCESS : ENUM_ERROR_TYPE_SendSMSFailed );
}
//
// 发送短信队列里的短信
//
BOOL CMobileControl::SendSMSQueue ()
{
ASSERT ( m_bRunAsServer );
// 发送队列里的一条短消息
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
{
m_CSFor_SMSSendQueue.Unlock ();
return TRUE;
}
t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
t_SMS_SendQueue SMS_SendQueue;
memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
m_Ary_SMS_SendQueue.RemoveAt ( 0 );
m_CSFor_SMSSendQueue.Unlock ();
BOOL bRes = SendOneSMSQueue ( SMS_SendQueue );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
return TRUE;
else
{
m_CSFor_SMSSendQueue.Lock ();
// 还有短信需要发送
if ( m_Ary_SMS_SendQueue.GetSize() > 0 )
{
::SetEvent ( m_hEvt_SMSSendQueue );
}
m_CSFor_SMSSendQueue.Unlock ();
}
return TRUE;
}
BOOL CMobileControl::AppTextToSMSContent ( SM_PARAM &sm, LPCTSTR lpszAppText, int &nFreeCharNum, BOOL bAddToHead )
{
ASSERT ( lpszAppText );
int nAppTextTotalCharNum = 0;
ParseSMSContentAttr ( CMultiByteString(lpszAppText).GetBuffer(), &nAppTextTotalCharNum );
if ( nAppTextTotalCharNum < nFreeCharNum )
{
CString csTD_UD_Byte = GetCompatibleString(sm.TP_UD_Byte,FALSE);
if ( bAddToHead ) csTD_UD_Byte.Insert ( 0, lpszAppText );
else csTD_UD_Byte += lpszAppText;
CMultiByteString ( csTD_UD_Byte, STRING_IS_SOFTCODE, sm.TP_UD_Byte, sizeof(sm.TP_UD_Byte) );
nFreeCharNum -= nAppTextTotalCharNum;
return TRUE;
}
return FALSE;
}
BOOL CMobileControl::SendOneSMSQueue ( t_SMS_SendQueue &SMS_SendQueue )
{
ASSERT ( m_nInitOK );
ASSERT ( m_pMobileParameter );
ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
{
if ( SMS_SendQueue.Proc_SendSMSEnd )
{
SMS_SendQueue.Proc_SendSMSEnd ( ENUM_ERROR_TYPE_SysTerminate,
&SMS_SendQueue.sm, SMS_SendQueue.wParam, SMS_SendQueue.lParam );
}
return FALSE;
}
int nTotalCharNum = 0, nFreeCharNum = 0, nTP_DCS = 0;
int nOneSMSByteCount = ParseSMSContentAttr ( SMS_SendQueue.sm.TP_UD_Byte,
&nTotalCharNum, &nFreeCharNum, &nTP_DCS );
SMS_SendQueue.sm.TP_DCS = nTP_DCS;
ASSERT ( nFreeCharNum >= 0 );
CString csSMSContent;
// 发送以“#howa!#”开头的短信,不附加短信头和尾
if ( strstr(SMS_SendQueue.sm.TP_UD_Byte,"#howa!#") == SMS_SendQueue.sm.TP_UD_Byte )
{
Log ( L_VERBOSE, _T("Not append SMS head and tail") );
char TP_UD_Byte_Temp[ONE_SMS_TEXT_LENGTH+1] = {0};
memset ( SMS_SendQueue.sm.TP_UD_Byte, 0, sizeof(SMS_SendQueue.sm.TP_UD_Byte) );
strcpy ( TP_UD_Byte_Temp, &SMS_SendQueue.sm.TP_UD_Byte[7] );
strcpy ( SMS_SendQueue.sm.TP_UD_Byte, TP_UD_Byte_Temp );
csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE);
}
// 附加短信“#760815# [短信内容] Sent by "callgle" ”
else
{
csSMSContent = GetCompatibleString(SMS_SendQueue.sm.TP_UD_Byte,FALSE);
if ( AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSTail, nFreeCharNum, FALSE ) )
{
AppTextToSMSContent ( SMS_SendQueue.sm, m_csSMSHead, nFreeCharNum, TRUE );
}
}
BOOL bRet = FALSE;
CStringArray StrAry_MobileNO;
ASSERT ( m_pMobileParameter );
bRet = SendOneSMSPkt ( &(SMS_SendQueue.sm) );
StrAry_MobileNO.Add ( SimplifyMobileNO(GetCompatibleString(SMS_SendQueue.sm.TPA,FALSE)) );
if ( SMS_SendQueue.Proc_SendSMSEnd )
{
SMS_SendQueue.Proc_SendSMSEnd ( bRet?ENUM_ERROR_TYPE_SUCCESS:ENUM_ERROR_TYPE_SendSMSFailed,
&(SMS_SendQueue.sm), SMS_SendQueue.wParam, SMS_SendQueue.lParam );
}
if ( bRet && m_pdwSentSMSCount )
{
(*m_pdwSentSMSCount) ++;
}
// 将发送完的短信保存到数据库
for ( int i=0; i<StrAry_MobileNO.GetSize(); i++ )
{
/* m_pHwMysql_PMMsg->SaveSMSToHistoryRecord (
SMS_SendQueue.dwSMSSenderID_Sender,
StrAry_MobileNO.GetAt(i),
SMS_SendQueue.eMobileSMSType,
ENUM_SMSOrientation_Send,
(bRet?ENUM_BOOL_TRUE:ENUM_BOOL_FALSE),
NULL,
csSMSContent );*/ //u
}
return bRet;
}
void CMobileControl::ClearSendQueue ()
{
// 还有短信需要发送
while ( TRUE )
{
m_CSFor_SMSSendQueue.Lock ();
if ( m_Ary_SMS_SendQueue.GetSize() <= 0 )
{
m_CSFor_SMSSendQueue.Unlock ();
break;
}
t_SMS_SendQueue &SMS_SendQueue_Refer = m_Ary_SMS_SendQueue.GetAt ( 0 );
t_SMS_SendQueue SMS_SendQueue;
memcpy ( &SMS_SendQueue, &SMS_SendQueue_Refer, sizeof(t_SMS_SendQueue) );
m_Ary_SMS_SendQueue.RemoveAt ( 0 );
m_CSFor_SMSSendQueue.Unlock ();
SendOneSMSQueue ( SMS_SendQueue );
}
}
BOOL CMobileControl::HandleRecvSMS(SM_PARAM *pSMRecv)
{
ASSERT ( pSMRecv );
if ( GetMobileStatus() == ENUM_ERROR_TYPE_MobileDisable )
{
Log ( L_WARNING, _T("Discard recevied SMS [%s : %s], because Mobile mobule disable"),
GetCompatibleString(pSMRecv->TPA,FALSE), GetCompatibleString(pSMRecv->TP_UD_Byte,FALSE) );
return FALSE;
}
if ( !CHwMobile::HandleRecvSMS ( pSMRecv ) )
return FALSE;
CString csTemp = SimplifyMobileNO ( GetCompatibleString(pSMRecv->TPA,FALSE) );
CMultiByteString ( csTemp, STRING_IS_SOFTCODE, pSMRecv->TPA, sizeof(pSMRecv->TPA) );
ASSERT ( m_Proc_ReceivedSMS );
return m_Proc_ReceivedSMS ( pSMRecv, m_wParam, m_lParam );
}
//
// 读最新收到的短信
//
BOOL CMobileControl::ReadNewSMS ()
{
if ( !m_bRecvSMSEnable ) return TRUE;
if ( HANDLE_IS_VALID(m_hEvt_IsBusy) &&
::WaitForSingleObject(m_hEvt_IsBusy,0)==WAIT_OBJECT_0 )
return TRUE;
ASSERT ( m_nInitOK );
// 系统要退出了
if ( ::WaitForSingleObject ( m_hEvt_TerminateSys, 0 ) == WAIT_OBJECT_0 )
return TRUE;
ASSERT ( m_handleCOM && m_handleCOM!=INVALID_HANDLE_VALUE );
if ( !QueryDeviceExist () )
{
return FALSE;
}
// 收短信通知
return gsmReadMessageContent ( "+CMT:" );
}
//
// 读取手机中已经存在的所有短信
//
BOOL CMobileControl::ReadExistSMSInMobile()
{
if ( !m_bRecvSMSEnable ) return TRUE;
if ( Write ( "AT+CMGL=4\r" ) < 1 )
return FALSE;
if ( !WaitForDataToRead ( 2, 5*WAIT_DATA_TIMEOUT ) )
return FALSE;
return gsmReadMessageContent ( "+CMGL:" );
}
//
// 读取手机所有电话本。
// 注意:及时删除返回的指针
//
t_Ary_PhoneBook* CMobileControl::ReadPhoneBook()
{
t_Ary_PhoneBook *pAry_PhoneBook = new t_Ary_PhoneBook;
if ( !pAry_PhoneBook )
{
::AfxThrowMemoryException ();
return NULL;
}
pAry_PhoneBook->SetSize ( 0, 10*sizeof(t_PhoneBook) );
if ( !gsmReadPhoneBook ( _T("SM"), pAry_PhoneBook ) )
return pAry_PhoneBook;
if ( !gsmReadPhoneBook ( _T("ME"), pAry_PhoneBook ) )
return pAry_PhoneBook;
return pAry_PhoneBook;
}
LPCTSTR CMobileControl::GetObjectName()
{
return _T("Mobile control module");
}
//
// 检测字符串 lpszStr 的是否以字符串 lpszHead1 或 lpszHead2 或 lpszHead3 开头
//
LPCTSTR CMobileControl::CheckHeadStr ( LPCTSTR lpszStr, LPCTSTR lpszHead1, LPCTSTR lpszHead2, LPCTSTR lpszHead3 )
{
if ( !lpszStr || !lpszHead1 || lstrlen(lpszStr) <= 0 )
return NULL;
if ( strstr_hw ( lpszStr, lpszHead1 ) == lpszStr )
return lpszHead1;
if ( lpszHead2 && strstr_hw ( lpszStr, lpszHead2 ) == lpszStr )
return lpszHead2;
if ( lpszHead3 && strstr_hw ( lpszStr, lpszHead3 ) == lpszStr )
return lpszHead3;
return NULL;
}
//
// 根据 Callgle 手机短信协议解析收到的短信
// return : -----------------------------------------------------------
// 1 : 成功
// 其他数据 : 发生错误
// -2 : 在本函数处理已经结束,不需要再处理
// 注意:
// 要及时删除 *ppStrAry_GroupName_Recver 和 *ppStrAry_SMSSenderID_Recver 指针
//
int CMobileControl::ParseSMSRecved (
IN LPCTSTR lpszSMSContent,
IN LPCTSTR lpszSenderMobileNO,
OUT CStringArray **ppStrAry_GroupName_Recver,
// 接收短信者名字或PM帐号,如果是输入控制命令时,这里存放了操作指令和控制命令
OUT CStringArray **ppStrAry_SMSSenderID_Recver,
OUT TCHAR *tchSMSContent,
int nSMSContentSize,
BOOL &bRequireEchoSMS,
LPCTSTR lpszSendTime
)
{
m_csPartString = _T("");
bRequireEchoSMS = FALSE;
// 无效的短信内容,所以我也返回一个无效的消息类型
if ( !lpszSMSContent || lstrlen(lpszSMSContent) < 2 )
return -1;
int nRet = -1;
ENUM_MOBILESMSTYPE eMobileSMSType = ENUM_MOBILESMSTYPE_Invalid;
CString csSMSContent = GET_SAFE_STRING ( lpszSMSContent );
CString csSMSContent_Org = csSMSContent;
BOOL bMultiSplitSMS = FALSE;
// 以三个'?'开头的短信表示该短信是分多次发送过来的,需要将前面的三个'?'去掉
if ( csSMSContent.GetLength() > 3 && csSMSContent.GetAt(0)=='?' &&
csSMSContent.GetAt(1)=='?' && csSMSContent.GetAt(2)=='?' )
{
bMultiSplitSMS = TRUE;
while ( !csSMSContent.IsEmpty() && csSMSContent.GetAt(0) == '?' )
csSMSContent.Delete ( 0, 1 );
csSMSContent_Org = csSMSContent;
if ( !m_csMultiSplitSMSHead.IsEmpty() && !CheckHeadStr ( csSMSContent, _T("#"), _T("#"), _T("…") ) )
csSMSContent.Insert ( 0, m_csMultiSplitSMSHead );
}
else
{
m_csMultiSplitSMSHead = "";
}
// 非普通短信,而是一个控制命令,处理后的控制命令保存在 “tchSMSContent” 中
LPCTSTR pStr = CheckHeadStr ( csSMSContent, _T("%"), _T("%"), _T("
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -