📄 hwmobile.cpp
字号:
}
if ( nSMSSize <= nSupplementLen )
nSMSSize = nSupplementLen+MAX_COM_BUFSIZE;
// 根据计算的尺寸,从 CString 中取内存
CString csSMS;
char *pSMS = csSMS.GetBuffer ( nSMSSize+1 );
ASSERT ( pSMS );
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;
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 ();
csSMS.ReleaseBuffer ();
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 += ( ptr-szRecvedData );
// PDU串解码
int nPduBytes = nRecvedDataLen-nHandleCount;
int nRet = gsmDecodePdu ( ptr, nPduBytes, pSMRecv );
if ( nRet == -1 ) // 数据不够
return 0;
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 nTimeSize)
{
ASSERT ( szSCTS && strlen(szSCTS) >= 14 );
ASSERT ( szStandardTime && nTimeSize > 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;
}
BOOL CHwMobile::gsmDeleteSMS ( int nIndex )
{
char szCMD[256] = {0};
hwSnprintf ( szCMD, sizeof(szCMD), "AT+CMGD=%d\r", nIndex );
if ( Write ( szCMD ) < 1 ) return FALSE;
if ( ReadResponse ( "OK\r\n" ) )
return TRUE;
return FALSE;
}
//
// 选择电话本
//
BOOL CHwMobile::gsmSelectPhoneBook ( LPCTSTR lpszPhoneBookName )
{
DbgLog ( L_DEBUG, "选择电话本 [%s]", lpszPhoneBookName );
// 两次选择电话本的时间间隔必须大于 SELECT_PHONEBOOK_INTVERVAL 秒
static time_t tStartTime = time(NULL);
while ( !TimeIntervalArrived ( tStartTime, SELECT_PHONEBOOK_INTVERVAL ) )
Sleep ( 100 );
// 选择电话本
char szCmd[256] = {0};
sprintf ( szCmd, "AT+CPBS=\"%s\"\r", GET_SAFE_STRING(lpszPhoneBookName) );
if ( Write ( szCmd ) < 1 )
return FALSE;
if ( !ReadResponse ( "OK\r\n" ) )
return FALSE;
return TRUE;
}
//
// 读一个电话本
// “SM” SIM 卡电话本
// “FD” 固定拨号电话本
// “DC” 最近拨号电话本
// “MC” 最近来电未接电话本
// “RC” 最近来电已接电话本
// “ME” 手机电话本
//
BOOL CHwMobile::gsmReadPhoneBook ( LPCTSTR lpszPhoneBookName, t_Ary_PhoneBook *pAry_PhoneBook)
{
ASSERT ( pAry_PhoneBook );
if ( !gsmSelectPhoneBook ( lpszPhoneBookName ) )
return FALSE;
int nStoreStartPos = 0;
int nStoreEndPos = 0;
int nMaxPhoneNOSize = 0;
int nMaxInfoSize = 0;
int nMaxRecSize = 0;
if ( !gmsGetPhoneBookInfo (
nStoreStartPos,
nStoreEndPos,
nMaxPhoneNOSize,
nMaxInfoSize,
nMaxRecSize ) )
return FALSE;
DbgLog ( L_DEBUG, " [%s].nStoreEndPos = %d", lpszPhoneBookName, nStoreEndPos );
// 发送“读”当前选择电话本所有电话纪录的 AT 指令
char szCMD[256] = {0};
hwSnprintf ( szCMD, sizeof(szCMD), "AT+CPBR=%d,%d\r", nStoreStartPos, nStoreEndPos );
if ( Write ( szCMD ) < 1 ) return FALSE;
// 取回所有读到的电话纪录
int nMaxRecNum = nStoreEndPos - nStoreStartPos + 1;
gsmGetAllPhoneBookRec ( nMaxRecSize, nMaxRecNum, lpszPhoneBookName, pAry_PhoneBook );
return TRUE;
}
//
// 获取电话本的基本信息
//
BOOL CHwMobile::gmsGetPhoneBookInfo (
int &nStoreStartPos,
int &nStoreEndPos,
int &nMaxPhoneNOSize,
int &nMaxInfoSize,
int &nMaxRecSize
)
{
if ( Write ( "AT+CPBR=?\r" ) < 1 )
return FALSE;
if ( !WaitForDataToRead ( 10, WAIT_GSM_DATA_TIME_SLOW ) )
return FALSE;
char szRead[MAX_COM_BUFSIZE] = {0};
int nReadLen = Read ( szRead, sizeof(szRead) );
char *pStr = strstr ( szRead, "+CPBR: (" );
if ( !pStr ) return FALSE;
pStr += 8;
if ( pStr - szRead >= nReadLen )
return FALSE;
sscanf ( pStr, "%d", &nStoreStartPos ); // 电话本起始位置
pStr = strstr ( pStr, "-" );
pStr += 1;
if ( pStr - szRead >= nReadLen )
return FALSE;
sscanf ( pStr, "%d", &nStoreEndPos ); // 电话本结束位置
pStr = strstr ( pStr, ")," );
pStr += 2;
if ( pStr - szRead >= nReadLen )
return FALSE;
sscanf ( pStr, "%d", &nMaxPhoneNOSize ); // 电话号码最大长度
pStr = strstr ( pStr, "," );
pStr += 1;
if ( pStr - szRead >= nReadLen )
return FALSE;
sscanf ( pStr, "%d", &nMaxInfoSize ); // 相关信息最大长度
nMaxRecSize = nMaxPhoneNOSize + // 一条纪录的最大长度
nMaxInfoSize + 30;
return TRUE;
}
//
// 获取所有电话本纪录
//
BOOL CHwMobile::gsmGetAllPhoneBookRec ( int nMaxRecSize, int nMaxRecNum, LPCTSTR lpszPhoneBookName, OUT t_Ary_PhoneBook *pAry_PhoneBook )
{
ASSERT ( pAry_PhoneBook );
// 读所有电话本纪录,结果存入 pAry_PhoneBook 数组中
if ( !WaitForDataToRead ( 10, WAIT_GSM_DATA_TIME_SLOW ) )
return FALSE;
// 要一次全部读入到内存来,否则可能会漏掉一些纪录,为什么会这样我也不知道。
const int nDataBufferSize = nMaxRecSize * ( nMaxRecNum + 5 );
char *pPhoneBookData = new char[nDataBufferSize+1];
if ( !pPhoneBookData )
{
::AfxThrowMemoryException();
return FALSE;
}
memset ( pPhoneBookData, 0, nDataBufferSize+1 );
int nRet = Read ( pPhoneBookData, nDataBufferSize );
if ( nRet > 0 )
{
char szRemainData[MAX_COM_BUFSIZE+1] = {0};
int nRemainBytes = gsmDecodePhoneBook ( lpszPhoneBookName, pPhoneBookData,
pAry_PhoneBook, szRemainData, MAX_COM_BUFSIZE );
if ( nRemainBytes > 0 )
{
memcpy ( pPhoneBookData, szRemainData, nRemainBytes );
pPhoneBookData[nRemainBytes] = '\0';
}
}
delete[] pPhoneBookData;
return TRUE;
}
//
// 解码所有电话纪录, 返回处理完后剩余的字节数
//
int CHwMobile::gsmDecodePhoneBook (
LPCTSTR lpszPhoneBookName,
char *szPhoneBookRec,
OUT t_Ary_PhoneBook *pAry_PhoneBook,
OUT char *szRemainData, // 处理后剩下的数据放到这里
const int nRemainSize
)
{
ASSERT ( szPhoneBookRec );
CStringArray StrAry;
PartStringAndAddToStrAry ( szPhoneBookRec, StrAry, '\r' );
int nRemainCount = 0;
for ( int i=0; i<StrAry.GetSize(); i++ )
{
CString csTemp = StrAry.GetAt ( i );
t_PhoneBook PhoneBook;
memset ( &PhoneBook, 0, sizeof(t_PhoneBook) );
if ( gsmDecodeOnePhoneBook ( csTemp.GetBuffer(0), PhoneBook ) )
{
STRNCPY_SZ ( PhoneBook.szPhoneBookName, lpszPhoneBookName );
pAry_PhoneBook->Add ( PhoneBook );
// DbgLog ( L_DEBUG, "得到电话本纪录如下:\r\nNO.%d - [%s] - %s - %s",
// PhoneBook.nIndex, PhoneBook.szPhoneBookName, PhoneBook.szName, PhoneBook.szPhoneNO );
}
else
{
int nLen = MIN ( csTemp.GetLength(), nRemainSize-nRemainCount );
if ( nLen < 0 ) nLen = 0;
memcpy ( szRemainData, csTemp.GetBuffer(0), nLen );
nRemainCount += nLen;
}
}
return nRemainCount;
}
//
// 解码一条电话纪录
//
BOOL CHwMobile::gsmDecodeOnePhoneBook ( char *szPhoneBookRec, OUT t_PhoneBook &PhoneBook )
{
ASSERT ( szPhoneBookRec );
char *pStr = strstr ( szPhoneBookRec, "+CPBR: " );
if ( !pStr ) return FALSE;
pStr += 7;
CString csTemp;
CStringArray StrAry;
PartStringAndAddToStrAry ( pStr, StrAry, ',' );
if ( StrAry.GetSize() < 4 ) return FALSE;
csTemp = StrAry.GetAt(0); // 序号
PhoneBook.nIndex = atoi ( csTemp );
csTemp = StrAry.GetAt(1); // 电话号码
csTemp.TrimLeft ( "\"" ); csTemp.TrimRight ( "\"" );
STRNCPY_CS ( PhoneBook.szPhoneNO, csTemp );
csTemp = StrAry.GetAt(2); // 类型
csTemp = StrAry.GetAt(3); // 姓名
csTemp.TrimLeft ( "\"" ); csTemp.TrimRight ( "\"" );
int nPos = csTemp.Find ( '\"', 0 );
if ( nPos >= 0 ) csTemp = csTemp.Left ( nPos );
char szName[256] = {0};
STRNCPY_CS ( szName, csTemp );
// UCS2解码
char szTempBuf[1024] = {0};
int nRet = gsmString2Bytes ( szName, (BYTE*)szTempBuf, strlen(szName), sizeof(szTempBuf) ); // 格式转换
gsmDecodeUcs2 ( (BYTE*)szTempBuf, PhoneBook.szName, nRet, sizeof(PhoneBook.szName) ); // 转换到TP-DU
return TRUE;
}
//
// 编码一条电话纪录
// return : 编码后的字节长度
//
int CHwMobile::gsmPhoneBookEncode (
OUT char *szPhoneBookRec,
int nPhoneBookRecSize,
IN LPCTSTR lpszType,
IN t_PhoneBook &PhoneBook
)
{
ASSERT_ADDRESS ( szPhoneBookRec, nPhoneBookRecSize );
ASSERT ( lpszType && strlen(lpszType) > 0 );
memset ( szPhoneBookRec, 0, nPhoneBookRecSize );
// UCS2编码
char szUCS2Name[256] = {0}, szStrName[256] = {0};
int nRet = gsmEncodeUcs2 ( PhoneBook.szName, (BYTE*)szUCS2Name, strlen(PhoneBook.szName), sizeof(szUCS2Name) );
gsmBytes2String ( (BYTE*)szUCS2Name, szStrName, nRet, sizeof(szStrName) );
int nCount = 0;
nCount += hwSnprintf ( szPhoneBookRec+nCount, nPhoneBookRecSize-nCount, "AT+CPBW=,\"%s\",%s,\"%s\"\r",
PhoneBook.szPhoneNO, lpszType, szStrName );
return nCount;
}
//
// 插入一条电话本纪录
//
BOOL CHwMobile::InsertPhoneBook(LPCTSTR lpszName, LPCTSTR lpszPhoneNO, LPCTSTR lpszPhoneBookName)
{
if ( !gsmSelectPhoneBook ( lpszPhoneBookName ) )
return FALSE;
// 获取电话纪录类型
if ( Write ( "AT+CPBW=?\r" ) < 1 ) return FALSE;
if ( !WaitForDataToRead ( 10, WAIT_GSM_DATA_TIME_SLOW ) )
return FALSE;
char szReadBuf[MAX_COM_BUFSIZE+1] = {0};
int nRet = Read ( szReadBuf, MAX_COM_BUFSIZE );
if ( nRet < 10 ) return FALSE;
char *pStr = strstr ( szReadBuf, "+CPBW: (" );
if ( !pStr ) return FALSE;
pStr += 8;
if ( (pStr = strstr ( pStr, "(" )) == NULL )
return FALSE;
pStr += 1;
CString csTypeDesc;
for ( ; *pStr != '\0' && *pStr != ','; pStr++ )
{
if ( pStr-szReadBuf >= MAX_COM_BUFSIZE )
break;
csTypeDesc += *pStr;
}
t_PhoneBook PhoneBook = {0};
memset ( &PhoneBook, 0, sizeof(t_PhoneBook) );
STRNCPY_SZ ( PhoneBook.szName, lpszName );
STRNCPY_SZ ( PhoneBook.szPhoneNO, lpszPhoneNO );
STRNCPY_SZ ( PhoneBook.szPhoneBookName, lpszPhoneBookName );
// 产生插入命令,并将电话纪录插入
char szCMD[256] = {0};
nRet = gsmPhoneBookEncode ( szCMD, sizeof(szCMD), csTypeDesc, PhoneBook );
if ( Write ( szCMD ) < 1 ) return FALSE;
if ( !ReadResponse ( "OK", FALSE ) ) return FALSE;
return TRUE;
}
void CHwMobile::SMSBeep(BOOL bRecv)
{
if ( !m_bSoundPrompt ) return;
DWORD dwFreq_Start = 1000, dwFreq_Interval=800;
DWORD dwDuration = 100;
for ( int i=0; i<5; i++ )
{
Beep ( dwFreq_Start+dwFreq_Interval*( bRecv?(5-i):i ), dwDuration );
}
}
//
// 检测设备是否存在,通过发送命令和读取回应的办法来实现
//
BOOL CHwMobile::QueryDeviceExist()
{
for ( int i=0; ; i++ )
{
if ( QueryExistByRWCmd () )
return TRUE;
if ( i<MAX_RWERROR_TIMES )
::Sleep ( 10 );
else
break;
}
HandleCOMRW ( -2 );
return FALSE;
}
//
// 读写命令来检测设备的存在
//
BOOL CHwMobile::QueryExistByRWCmd()
{
if ( Write("AT\r" ) > 0 &&
ReadResponse ( "OK" ) )
{
return TRUE;
}
return FALSE;
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -