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

📄 hwmobile.cpp

📁 基于vc++6.0的收发手机短信、读写手机电话本的平台
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		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 + -