📄 hwmobile.cpp
字号:
szAns[nLen] = '\0';
}
return bRet;
}
/********************************************************************************
* Function Type : protected
* Parameter : lpszData - 要写的字符串
* Return Value : >=0 - 写出去的字节数
* -1 - COM got way
* Description : 往串口写数据
*********************************************************************************/
int CHwMobile::Write(char *szData)
{
if ( !szData || strlen(szData) < 1 )
return 0;
int nLen = (int)strlen ( szData );
#ifdef _DEBUG
if ( strcmp ( szData, "AT\r" ) != 0 )
{
// TRACE ( _T("手机模块发送命令 [ %d bytes ]: %s\n"), nLen, GetCompatibleString(szData,FALSE) );
}
#endif
int nRet = 0;
char szOneSendPkt[32] = {0};
int nSentBytes = 0, nRemainBytes = nLen;
while ( nRemainBytes > 0 )
{
int nMinLength = MIN ( sizeof(szOneSendPkt), nRemainBytes );
memcpy ( szOneSendPkt, szData+nSentBytes, nMinLength );
int nRetTemp = CHwCOM::Write ( szOneSendPkt, nMinLength );
if ( nRetTemp != nMinLength )
{
nRet = nRetTemp;
break;
}
nSentBytes += nMinLength;
nRemainBytes -= nMinLength;
nRet = nSentBytes;
if ( nRemainBytes > 0 ) Sleep ( 10 );
}
return HandleCOMRW ( nRet );
}
/********************************************************************************
* Function Type : protected
* Parameter : data - 读数据缓冲
* size - 要读的字节数
* Return Value : >=0 - 读到的字节数
* -1 - COM got way
* Description : 从串口中读数据
*********************************************************************************/
int CHwMobile::Read(char *data, int size)
{
int nRet = HandleCOMRW ( CHwCOM::Read ( data, size ) );
if ( nRet <= 0 )
{
return nRet;
}
// TRACE ( "Read data from GSM module : %s\n", data );
// 正在读的时候收到了短信
char *p = strstr ( data, "+CMT:" );
if ( p )
{
int nTempBufSize = nRet + 1;
char *pHeadData = new char[nTempBufSize+1];
char *pTailData = new char[nTempBufSize+1];
if ( pHeadData && pTailData )
{
memset ( pHeadData, 0, nTempBufSize+1 );
memset ( pTailData, 0, nTempBufSize+1 );
int nHeadLen = (int)((ULONGLONG)p-(ULONGLONG)data);
memcpy ( pHeadData, data, nHeadLen ); // 将 "+CMT:" 之前的数据先复制下来
memcpy ( pTailData, p, MIN(nTempBufSize,nRet-nHeadLen) );
// 将从 "+CMT:" 开始后面的数据做为新短信来处理,处理剩下的数据会保存到 pTailData 中
gsmReadMessageContent ( "+CMT:", pTailData, nTempBufSize );
// 将 "+CMT:" 之前的数据和处理新短信后剩下的数据合起来就是本次读到的数据
memset ( data, 0, size );
nRet = 0;
int nLen = MIN(nHeadLen,size);
memcpy ( data, pHeadData, nLen );
data += nLen;
nRet += nLen;
int nTailLen = (int)strlen ( pTailData );
nLen = MIN(nTailLen,size-nLen);
memcpy ( data, pTailData, nLen );
nRet += nLen;
}
else
{
memset ( data, 0, size );
nRet = 0;
}
if ( pHeadData ) delete[] pHeadData;
if ( pTailData ) delete[] pTailData;
}
// 正在读的时候有新来电
nRet = HandleNewIncoming ( data, nRet );
return nRet;
}
int CHwMobile::HandleCOMRW(int nRet)
{
if ( nRet < 0 )
{
CloseCOM ();
if ( nRet == -1 )
{
Log ( L_WARNING | L_OUT_UI, _T("Device [COM%d] {got way}"), m_nComNO );
m_csCurPhoneBookName.Empty ();
m_bInitMobileLastRes = -1;
}
else if ( nRet == -2 )
{
Log ( L_WARNING | L_OUT_UI, _T("SMS Module be removed") );
m_csCurPhoneBookName.Empty ();
m_bInitMobileLastRes = -1;
}
// 将短信中心号码清除掉,等手机再次接上来的时候可以重新获取中心号码
// 以防止用户更换不同提供商的sim卡而发不了短信。
m_csSMSC = _T("");
}
return nRet;
}
//
// 发送短消息,仅发送命令
// 输入: pSrc - 源PDU参数指针
// return : 发送结果
//
int CHwMobile::gsmSendMessage ( SM_PARAM *pSrc )
{
int nPduLength=0; // PDU串长度
int nSmscLength=0; // SMSC串长度
int nLength=0; // 串口收到的数据长度
char cmd[1024]={0}; // 命令串
char pdu[4096]={0}; // PDU串
char ans[1024]={0}; // 应答串
nPduLength = gsmEncodePdu ( pSrc, pdu, sizeof(pdu) ); // 根据PDU参数,编码PDU串
strcat(pdu, "\x01a"); // 以Ctrl-Z结束
gsmString2Bytes ( pdu, (BYTE *)&nSmscLength, 2, sizeof(nSmscLength) ); // 取PDU串中的SMSC信息长度
nSmscLength++; // 加上长度字节本身
// 命令中的长度,不包括SMSC信息长度,以数据字节计
sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength); // 生成命令
// 先输出命令串
// Log ( L_VERBOSE, "SMS Module Send Command : %s\n", GetCompatibleString(cmd,FALSE) );
if ( Write ( cmd ) < 1 )
return GSM_ERR;
// 根据能否找到"\r\n> "决定成功与否
// 得到肯定回答
if ( !ReadResponse ( "\r\n> ", FALSE ) )
return GSM_ERR;
// 就继续输出PDU串
// Log ( L_VERBOSE, "SMS Module Send Command : %s\n", GetCompatibleString(pdu,FALSE) );
if ( Write ( pdu ) < 1 )
return GSM_ERR;
char szAns[MAX_COM_BUFSIZE+1] = {0};
if ( ReadResponse ( "OK\r\n", FALSE, szAns, MAX_COM_BUFSIZE ) )
return GSM_OK;
if ( strstr ( szAns, "+CMS ERROR" ) )
return GSM_ERR;
return GSM_UNKNOWN; // 应该再次发送
}
//
// 发送一条短信
//
BOOL CHwMobile::SendOneSMSPkt ( SM_PARAM *pSMSend )
{
ASSERT ( pSMSend );
if ( strlen(pSMSend->TP_UD_Byte) < 1 )
return FALSE;
int nRes = GSM_UNKNOWN;
HwDbgLog ( L_DEBUG, _T("要发送 %d 字节的短信"), strlen(pSMSend->TP_UD_Byte) );
// 最多重试 3 次
int i=0;
for ( ; i<3; i++ )
{
nRes = gsmSendMessage ( pSMSend );
if ( nRes == GSM_UNKNOWN )
{
Sleep ( 100 ); // 休息一下再试
}
else
{
break;
}
}
TRACE ( _T("发送短信给 [ %s ] - %d 字节 [ %s ] 完成\n"), pSMSend->TPA, strlen(pSMSend->TP_UD_Byte), pSMSend->TP_UD_Byte );
BOOL bRet = FALSE;
if ( nRes==GSM_OK )
{
HwDbgLog ( L_DEBUG, _T("Retry %d times"), i );
SMSBeep ( FALSE );
bRet = TRUE;
}
Log ( bRet?L_VERBOSE:L_WARNING, _T("Send SMS to [%s] %s, SMSC : %s"), GetCompatibleString(pSMSend->TPA,FALSE),
(bRet?_T("successfully"):_T("failed")), GetCompatibleString(pSMSend->SCA,FALSE) );
return bRet;
}
//
// 处理新来电信息, 处理完以后剩下的数据由 data 返回,返回值为剩下的字节数
//
int CHwMobile::HandleNewIncoming(char *data, int size)
{
if ( size < 20 ) return size;
if ( !data ) return 0;
CString csData = GetCompatibleString(data,FALSE);
CString csRingFlag = _T("RING\r\n\r\n+CLIP: ");
while ( TRUE )
{
int nEndPos_Left = csData.Find ( csRingFlag, 0 );
int nDeletePos = nEndPos_Left;
if ( nEndPos_Left < 0 ) break;
nEndPos_Left += csRingFlag.GetLength();
int nEndPos_Right = csData.Find ( _T("\r\n"), nEndPos_Left );
if ( nEndPos_Right < 0 ) nEndPos_Right = csData.GetLength()-1;
if ( nEndPos_Right <= nEndPos_Left ) break;
else nEndPos_Right += 2;
CString csOneRingInfo = csData.Mid ( nEndPos_Left, nEndPos_Right-nEndPos_Left );
csData.Delete ( nDeletePos, nEndPos_Right-nDeletePos );
// 取到来电显示号码,交给外部模块处理
int nCallerIDEndPos = csOneRingInfo.Find ( _T("\""), 1 );
if ( nCallerIDEndPos < 0 ) nCallerIDEndPos = csOneRingInfo.GetLength() - 1;
static CString csCallerID_Last;
static time_t tLastTime = 0;
CString csCallerID = csOneRingInfo.Mid ( 1, nCallerIDEndPos-1 );
if ( csCallerID_Last != csCallerID || difftime(time(NULL),tLastTime) > 60 )
{
if ( m_Proc_IncomingFromGSM ) m_Proc_IncomingFromGSM ( csCallerID );
csCallerID_Last = csCallerID;
tLastTime = time(NULL);
}
}
memset ( data, 0, size );
CMultiByteString ( csData, STRING_IS_SOFTCODE, data, size-1 );
return (int)strlen(data);
}
//
// 读取短信内容,读到的短信将在函数 HandleRecvSMS() 中处理,命令已经发送
// 过了,或者不需要发送读取短信的命令,只是在等待接收。
// 如果在读取短信的时候收到“RING”命令说明有来电,进入来电处理模块
//
BOOL CHwMobile::gsmReadMessageContent ( const char *szSMSFlag, char *szSupplement/*=NULL*/, const int nSupplementSize/*=0*/ )
{
ASSERT ( szSMSFlag );
// 计算 SMS 缓冲尺寸
int nSMSSize = MAX_COM_BUFSIZE;
int nSupplementLen = 0;
if ( szSupplement )
{
nSupplementLen = (int)strlen ( szSupplement );
}
if ( nSMSSize <= nSupplementLen )
nSMSSize = nSupplementLen+MAX_COM_BUFSIZE;
// 根据计算的尺寸,从 CString 中取内存
CString csSMS;
char *pSMS = new char[nSMSSize+1];
if ( !pSMS ) return FALSE;
memset ( pSMS, 0, nSMSSize+1 );
int nSMSDataLen = 0;
if ( szSupplement )
{
strncpy ( pSMS, szSupplement, nSMSSize );
ASSERT ( nSupplementLen < nSMSSize );
nSMSDataLen += nSupplementLen;
}
while ( nSupplementLen > 0 || GetCommInputBuffLen () > (int)strlen ( szSMSFlag ) )
{
int nRet = CHwCOM::Read ( pSMS+nSMSDataLen, MAX_COM_BUFSIZE-nSMSDataLen );
if ( nSupplementLen > 0 || nRet > 0 )
{
nSMSDataLen += nRet;
nSMSDataLen = HandleNewIncoming ( pSMS, nSMSDataLen );
// Log ( L_DEBUG, "Received SMS %d bytes data :\r\n%s", nSMSDataLen, GetCompatibleString(pSMS,FALSE) );
int nHandleCount = gsmParseMessage ( szSMSFlag, pSMS, nSMSDataLen );
if ( nHandleCount > 0 )
{
ASSERT ( nHandleCount < nSMSSize );
int nMoveLen = nSMSDataLen - nHandleCount;
ASSERT ( nMoveLen <= (int)(nSMSSize-nHandleCount) );
memmove ( pSMS, pSMS+nHandleCount, nMoveLen );
pSMS[nMoveLen] = '\0';
nSMSDataLen = nMoveLen;
}
}
else
{
break;
}
nSupplementLen = 0;
}
// 把处理后剩下的数据拷贝给调用者
if ( szSupplement && nSupplementSize > 0 )
{
strncpy ( szSupplement, pSMS, nSupplementSize );
}
for ( int i=0; i<m_UIntAry_NeedDelSMS.GetSize(); i++ )
{
//#ifndef _DEBUG
// 将收走的短信删除掉
gsmDeleteSMS ( m_UIntAry_NeedDelSMS.GetAt(i) );
//#endif
}
m_UIntAry_NeedDelSMS.RemoveAll ();
delete[] pSMS;
pSMS = NULL;
return TRUE;
}
//
// 分析短信,分析出来的短信将在函数 HandleRecvSMS() 中处理, 返回处理了多少个字节
//
int CHwMobile::gsmParseMessage ( IN const char *szSMSFlag, IN char *szRecvedData, int nRecvedDataLen )
{
ASSERT ( szRecvedData );
int nHandleBytes = 0;
// 循环分析所有短信
while ( nRecvedDataLen-nHandleBytes > (int)strlen(szSMSFlag) )
{
SM_PARAM SMRecv = {0};
int nRet = gsmParseOneMessage ( szSMSFlag, szRecvedData+nHandleBytes, nRecvedDataLen-nHandleBytes, &SMRecv );
if ( strlen ( SMRecv.TP_UD_Byte ) > 0 )
{
HandleRecvSMS ( &SMRecv );
}
if ( nRet > 0 )
{
nHandleBytes += nRet;
}
else
{
break;
}
}
return nHandleBytes;
}
//
// 分析一条短信,返回处理了多少个字节
//
int CHwMobile::gsmParseOneMessage ( IN const char *szSMSFlag, IN char *szRecvedData, int nRecvedDataLen, OUT SM_PARAM *pSMRecv )
{
ASSERT ( szSMSFlag && szRecvedData );
memset ( pSMRecv, 0, sizeof(SM_PARAM) );
if ( nRecvedDataLen < 4 ) return 0;
char *ptr = szRecvedData;
int nHandleCount = 0;
if ( (ptr = strstr ( ptr, szSMSFlag )) == NULL )
return 0;
ptr += strlen ( szSMSFlag ); // 跳过命令标志, 定位到序号
if ( ptr - szRecvedData > nRecvedDataLen )
return 0;
int nIndex = 0;
sscanf ( ptr, "%d", &nIndex ); // 读取序号
pSMRecv->index = nIndex;
// 找下一行
if ( (ptr = strstr ( ptr, "\r\n")) == NULL )
return 0;
// 跳过"\r\n", 定位到PDU
ptr += 2;
if ( ptr - szRecvedData > nRecvedDataLen )
return 0;
nHandleCount += (int)( (ULONGLONG)ptr-(ULONGLONG)szRecvedData );
// PDU串解码
int nPduBytes = nRecvedDataLen-nHandleCount;
int nRet = gsmDecodePdu ( ptr, nPduBytes, pSMRecv );
if ( nRet == -1 ) // 数据不够
return 0;
else if ( nRet == -2 || strlen(pSMRecv->TP_UD_Byte) < 1 ) // 非法的数据
{
CString csIllegal = GetCompatibleString(ptr,FALSE);
csIllegal = csIllegal.Left ( nPduBytes );
Log ( L_WARNING, _T("SMS module received illegal data : %s"), csIllegal );
}
ASSERT ( nPduBytes < nRecvedDataLen-nHandleCount );
nHandleCount += nPduBytes;
return nHandleCount;
}
BOOL CHwMobile::HandleRecvSMS(SM_PARAM *pSMRecv)
{
ASSERT ( pSMRecv );
// 收到的短信应该要删除,所以将它的序号添加到数组中
m_UIntAry_NeedDelSMS.Add ( pSMRecv->index );
SMSBeep ( TRUE );
return TRUE;
}
//
// 将时间戳字符串转为标准的时间格式
//
char* CHwMobile::Convert_SCTS2Standard(char *szSCTS, char *szStandardTime, int nSize)
{
ASSERT ( szSCTS && strlen(szSCTS) >= 14 );
ASSERT ( szStandardTime && nSize > 19 );
char *pSrc = szSCTS;
char *pDst = szStandardTime;
for ( int i=0; i<6; i++ )
{
char *pConn = ( (i==0)?"20": ((i==3)?" ": ((i>3)?":":"-") ) );
strcpy ( pDst, pConn );
pDst += strlen(pConn);
memcpy ( pDst, pSrc, 2 );
pSrc += 2;
pDst += 2;
}
return szStandardTime;
}
//
// 将标准的时间格式转为时间戳字符串
//
char* CHwMobile::Convert_Standard2SCTS(char *szStandardTime, char *szSCTS, int nSize)
{
ASSERT ( szStandardTime && strlen(szStandardTime) == 19 );
ASSERT ( szSCTS && nSize >= 16 );
CString csSCTS = GetCompatibleString(szStandardTime,FALSE);
if ( csSCTS.GetLength() >= 2 )
csSCTS.Delete ( 0, 2 );
if ( csSCTS.GetLength() >= 1 )
csSCTS.Delete ( 2, 1 );
if ( csSCTS.GetLength() >= 1 )
csSCTS.Delete ( 4, 1 );
if ( csSCTS.GetLength() >= 1 )
csSCTS.Delete ( 6, 1 );
if ( csSCTS.GetLength() >= 1 )
csSCTS.Delete ( 8, 1 );
if ( csSCTS.GetLength() >= 1 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -