⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hwmobile.cpp

📁 短信收发的程序源代码。能自动检测手机是否连接好
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	}
	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 + -