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

📄 sms.cpp

📁 手机USB线接到PC机上模拟串口发短信
💻 CPP
字号:
#include "stdafx.h"
#include "SMS.h"
#include "smsdef.h"

CSMSException::CSMSException()
{
	m_dwErrorCode		= 0;
	m_sErrorDescribe	= _T("");
}

CSMSException::~CSMSException()
{
}

void CSMSException::SetCode( DWORD dwCode )
{
	m_dwErrorCode		= dwCode;
}

void CSMSException::SetDescribe( LPCTSTR lpszDescribe )
{
	m_sErrorDescribe	= lpszDescribe;	
}

DWORD CSMSException::GetCode()
{
	return m_dwErrorCode;
}

CString	CSMSException::GetDescribe()
{
	return m_sErrorDescribe;
}

CSMS::CSMS()
{
	m_bInitOK	    =   FALSE;
	m_hComDev		=	NULL									;
	m_hReadEvent	=	CreateEvent( NULL, TRUE, FALSE, NULL )	;
	m_hWriteEvent	=	CreateEvent( NULL, TRUE, FALSE, NULL )	;
	m_bAsyncComm	=	TRUE									;
	m_nKeepTime		=	7*24									;
	m_nMaxLength	=	140										;
	m_sAreaCode		=	_T("86")								;
	m_sSmsCenter	=	_T("13800591500");						;
	m_exp			=	new CSMSException						;
	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof( SECURITY_ATTRIBUTES );
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;
	m_hEventOfUsing	=	CreateEvent( &sa, TRUE, TRUE, _T("CSms CanUse Event") );
}

CSMS::~CSMS()
{
    if( m_hComDev != NULL )
		CloseHandle( m_hComDev );
	if( m_hReadEvent != NULL )
		CloseHandle( m_hReadEvent );
	if( m_hWriteEvent != NULL )
		CloseHandle( m_hWriteEvent );
	
	if( m_exp != NULL )
		delete			m_exp;
}

void CSMS::SetSmsParam( int nComPort, int nKeepTime, int nMaxLength, LPCSTR sAereCode, LPCSTR sSmsCenter )
{
	CString str;
	str.Format("COM%d", nComPort);
	m_sCom = str;
	
	m_nKeepTime		= nKeepTime;
	m_nMaxLength	= nMaxLength;
	m_sAreaCode		= sAereCode;
	m_sSmsCenter	= sSmsCenter;
}

void CSMS::SetSmsParam( LPCSTR sCom, int nKeepTime, int nMaxLength, LPCSTR sAereCode, LPCSTR sSmsCenter )
{
	m_sCom = sCom;	
	m_nKeepTime		= nKeepTime;
	m_nMaxLength	= nMaxLength;
	m_sAreaCode		= sAereCode;
	m_sSmsCenter	= sSmsCenter;
}

DWORD CSMS::Init( BOOL bAsyncComm )
{
	m_bAsyncComm = bAsyncComm;
	m_bInitOK = FALSE;
	__try
	{
		Lock();
		ComOpen();
		InitSms();
		m_bInitOK = TRUE;
	}
	__finally
	{
 		Unlock();
	}
	return CODE_SUCCESS;
}

DWORD CSMS::InitSms()
{
	CString str;

	AsyncComWrite( "ATEV1\r" );

	str = _T("AT+CPAS\r");
	AsyncComWrite( str );
	AsyncComRead( str );
	if( str.Find( "+CPAS: 3" ) >= 0||str.Find( "+CPAS: 4" ) >= 0 )
	{
		m_exp->SetCode( CODE_PHONE_BUSY );
		CString strError;
		strError.Format("%s[%s]", NOTE_PHONE_BUSY, str);
		m_exp->SetDescribe( strError );	
		throw m_exp;
	}
	else if( str.Find( "+CPAS: 1" ) >= 0 )
	{
		m_exp->SetCode( CODE_PHONE_UNAVAILABLE );
		CString strError;
		strError.Format("%s[%s]", NOTE_PHONE_UNAVAILABLE, str);
		m_exp->SetDescribe( strError );	
		//m_exp->SetDescribe( NOTE_PHONE_UNAVAILABLE );
		throw m_exp;
	}
	else if( str.Find( "+CPAS: 2" ) >= 0 )
	{
		m_exp->SetCode( CODE_CONNECT_PHONE_ERROR );
		CString strError;
		strError.Format("%s[%s]", NOTE_CONNECT_PHONE_ERROR, str);
		m_exp->SetDescribe( strError );	
		//m_exp->SetDescribe( NOTE_CONNECT_PHONE_ERROR );
		throw m_exp;
	}
	else if( str.Find( "+CPAS: 5" ) >= 0 )
	{
		m_exp->SetCode( CODE_LOW_FUNCTION );
		CString strError;
		strError.Format("%s[%s]", NOTE_LOW_FUNCTION, str);
		m_exp->SetDescribe( strError );	
		//m_exp->SetDescribe( NOTE_LOW_FUNCTION );
		throw m_exp;
	}
	else if( str.Find( "+CPAS: 0" ) < 0 )
	{
		m_exp->SetCode( CODE_UNKNOW_ERROR );
		CString strError;
		strError.Format("%s[%s]", NOTE_UNKNOW_ERROR, str);
		m_exp->SetDescribe( strError );	
		//m_exp->SetDescribe( NOTE_UNKNOW_ERROR );
		throw m_exp;
	}

	str.Format( _T("AT+CSCA=\"+%s%s\",145\r"), m_sAreaCode, m_sSmsCenter );
	PurgeComm(m_hComDev, PURGE_RXCLEAR | PURGE_TXCLEAR );
	AsyncComWrite( str );
	AsyncComRead( str );
	if( str.Find( "OK" ) < 0 )
	{
		m_exp->SetCode( CODE_INIT_PHONE_ERROR );
		CString strError;
		strError.Format("%s[%s]", NOTE_INIT_PHONE_ERROR, str);
		m_exp->SetDescribe( strError );
		throw m_exp;
	}
	
	str = _T("AT+CMGF=1\r");
	PurgeComm(m_hComDev, PURGE_RXCLEAR | PURGE_TXCLEAR );
	AsyncComWrite( str );
	AsyncComRead( str );
	if( str.Find( "OK" ) < 0 )
	{
		m_exp->SetCode( CODE_INIT_PHONE_ERROR );
		CString strError;
		strError.Format("%s[%s]", NOTE_INIT_PHONE_ERROR, str);
		m_exp->SetDescribe( strError );
		throw m_exp;
	}
	
	str.Format( _T("AT+CSMP=17,%d,0,8\r"),SetVPH( m_nKeepTime ));
	PurgeComm(m_hComDev, PURGE_RXCLEAR | PURGE_TXCLEAR );
	AsyncComWrite( str );
	AsyncComRead( str );
	if( str.Find( "OK" ) < 0 )
	{
		m_exp->SetCode( CODE_INIT_PHONE_ERROR );
		CString strError;
		strError.Format("%s[%s]", NOTE_INIT_PHONE_ERROR, str);
		m_exp->SetDescribe( strError );
		throw m_exp;
	}

	return CODE_SUCCESS;
}

DWORD CSMS::SendShortMessage( LPCSTR sRcver,LPCSTR sShortMessage )
{
	DWORD ret;
	try
	{
		Lock();
		ret = _SendShortMessage( sRcver, sShortMessage );
	}
	catch(...)
	{
		Unlock();
		throw;
	}
	Unlock();
	return ret;
}

DWORD CSMS::_SendShortMessage( LPCSTR sRcver, LPCSTR sShortMessage )
{
	CString			str = "", sMsg, sToSend;
	CStringArray	saMsg;	

	if( !m_bInitOK )
		InitSms();

	sMsg			= sShortMessage;
	sToSend			= _T("");
	BOOL bCharacter	= FALSE;
	int nCount = 0;			//djq_020814 add计算英文字符的数目
	//djq_020814 note
	//由于在手机实现中如果AT+CMGF=1时,英文字符实际上也是同汉字一样算一个字
	//所以必须注意140个实际上是英文字符一个算两个
	while( !sMsg.IsEmpty() )
	{
		unsigned char c = sMsg.GetAt(0);
		if( c >= 128 )
		{
			bCharacter = TRUE;
			sToSend += sMsg.Mid(0,2);
			sMsg.Delete(0,2);
		}
		else
		{
			bCharacter = FALSE;
			sToSend += sMsg.GetAt(0);
			sMsg.Delete(0);
			nCount++;
		}
		
		if( sMsg.IsEmpty() )
			saMsg.Add( sToSend );
		else if( sToSend.GetLength()+nCount > m_nMaxLength )					//djq_020814 chg 
		{
			if( bCharacter )
			{
				sMsg = sToSend.Mid( sToSend.GetLength() -2, 2 ) + sMsg;
				sToSend.Delete( sToSend.GetLength()-2, 2 );			
			}
			else
			{
				sMsg.Insert( 0, sToSend.GetAt( sToSend.GetLength()-1 ) );
				sToSend.Delete( sToSend.GetLength()-1 );
			}
			saMsg.Add( sToSend );
			sToSend		= _T("(续)");
			nCount = 0;
		}
	}
	int nSmsCount = saMsg.GetSize();			//djq_020522 发送的条数
	while( saMsg.GetSize() )
	{
		str = _T("AT+CPAS\r");
		PurgeComm(m_hComDev, PURGE_RXCLEAR | PURGE_TXCLEAR );
		AsyncComWrite( str );
		AsyncComRead( str );
		if( str.Find( "+CPAS: 3" ) >= 0||str.Find( "+CPAS: 4" ) >= 0 )
		{
			m_exp->SetCode( CODE_PHONE_BUSY );
			CString strError;
			strError.Format("%s[%s]", NOTE_PHONE_BUSY, str);
			m_exp->SetDescribe( strError );	
			throw m_exp;
		}
		else if( str.Find( "+CPAS: 1" ) >= 0 )
		{
			m_exp->SetCode( CODE_PHONE_UNAVAILABLE );
			CString strError;
			strError.Format("%s[%s]", NOTE_PHONE_UNAVAILABLE, str);
			m_exp->SetDescribe( strError );	
			throw m_exp;
		}
		else if( str.Find( "+CPAS: 2" ) >= 0 )
		{
			m_exp->SetCode( CODE_CONNECT_PHONE_ERROR );
			CString strError;
			strError.Format("%s[%s]", NOTE_CONNECT_PHONE_ERROR, str);
			m_exp->SetDescribe( strError );	
			throw m_exp;
		}
		else if( str.Find( "+CPAS: 5" ) >= 0 )
		{
			m_exp->SetCode( CODE_LOW_FUNCTION );
			CString strError;
			strError.Format("%s[%s]", NOTE_LOW_FUNCTION, str);
			m_exp->SetDescribe( strError );	
			throw m_exp;
		}
		else if( str.Find( "+CPAS: 0" ) < 0 )
		{
			m_exp->SetCode( CODE_CONNECT_PHONE_ERROR );
			CString strError;
			strError.Format("%s[%s]", NOTE_CONNECT_PHONE_ERROR, str);
			m_exp->SetDescribe( strError );	
			throw m_exp;
		}
	
		str.Format( _T("AT+CMGS=\"+%s%s\",145\r"), m_sAreaCode, sRcver );
		PurgeComm(m_hComDev, PURGE_RXCLEAR | PURGE_TXCLEAR );
		AsyncComWrite( str );
		//str.Format( _T("%s\x1A"), saMsg.GetAt(0) );
		str.Format( _T("%s\x1A"),DoUniCode( (LPCTSTR)(saMsg.GetAt(0)) ) );
		AsyncComWrite( str );
		AsyncComRead( str );

		if( str.Find( _T("OK") ) < 0 )
		{//发送失败
			m_exp->SetCode( CODE_SEND_SM_ERROR );
			CString strError;
			strError.Format("%s[%s]", NOTE_SEND_SM_ERROR, str);
			m_exp->SetDescribe( strError );
			throw m_exp;
		}

		saMsg.RemoveAt(0);
	}
	return nSmsCount;
	//return CODE_SUCCESS;
}

BOOL CSMS::CanUse()
{
	return TRUE;
	DWORD ret;
	ret = WaitForSingleObject( m_hEventOfUsing, 0 );
	return ret == WAIT_OBJECT_0;
}

DWORD CSMS::WaitForCanUse( DWORD dwMilliseconds )
{
	return WaitForSingleObject( m_hEventOfUsing, dwMilliseconds );
}

void CSMS::Lock()
{
	return;
	if( !CanUse() )
	{
		m_exp->SetCode( CODE_PHONE_BUSY );
		m_exp->SetDescribe( NOTE_PHONE_BUSY );
		throw m_exp;
	}
	ResetEvent( m_hEventOfUsing );
}

void CSMS::Unlock()
{
	return;
	SetEvent( m_hEventOfUsing );
}

BOOL CSMS::ComOpen()
{
	CString			strPort;
	DCB				dcb;
    COMMTIMEOUTS	CommTimeOuts;
	DWORD			dwOpenFlag;

	if( m_hComDev		!= (HANDLE) -1 )
		CloseHandle( m_hComDev		);
	if( m_hReadEvent	!= (HANDLE) -1 )
		CloseHandle( m_hReadEvent	);
	if( m_hWriteEvent	!= (HANDLE) -1 )
		CloseHandle( m_hWriteEvent	);

	m_hReadEvent	=	CreateEvent( NULL, TRUE, FALSE, NULL );
	m_hWriteEvent	=	CreateEvent( NULL, TRUE, FALSE, NULL );	
	
	strPort.Format( _T("%s"),m_sCom );
	if( m_bAsyncComm )
		dwOpenFlag = FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED;
	else
		dwOpenFlag = 0; 

	m_hComDev = CreateFile(	 strPort,
		                     GENERIC_READ|GENERIC_WRITE,
		                     0,
							 NULL,
							 OPEN_EXISTING,
							 dwOpenFlag,
							 NULL );

	if ( m_hComDev == ( HANDLE )-1 )
	{
		m_exp->SetCode( CODE_COM_OPEN_ERROR );
		m_exp->SetDescribe( _T("打开端口") + strPort + _T("失败") );
		throw m_exp;
	}
    
	SetupComm( m_hComDev, 5*1024, 5*1024 );
	GetCommState( m_hComDev,&dcb );
	dcb.BaudRate = 9600;
	dcb.ByteSize = DATABITS_8;
	dcb.fParity = 1;
	dcb.Parity = NOPARITY;
	dcb.EvtChar = '\xD';
    SetCommState( m_hComDev,&dcb );

	if( m_bAsyncComm )
	{//异步
		CommTimeOuts.ReadIntervalTimeout			= MAXDWORD;
		CommTimeOuts.ReadTotalTimeoutConstant		= 0;
		CommTimeOuts.ReadTotalTimeoutMultiplier		= 0;
		CommTimeOuts.WriteTotalTimeoutConstant		= 1000;
		CommTimeOuts.WriteTotalTimeoutMultiplier	= 0;
	}
	else
	{//同步
		CommTimeOuts.ReadIntervalTimeout			= MAXDWORD;
		CommTimeOuts.ReadTotalTimeoutConstant		= 1000;
		CommTimeOuts.ReadTotalTimeoutMultiplier		= 0;
		CommTimeOuts.WriteTotalTimeoutConstant		= 1000;
		CommTimeOuts.WriteTotalTimeoutMultiplier	= 0;
	}
	SetCommTimeouts( m_hComDev,&CommTimeOuts );
    
	DWORD dwStoredFlags;
	dwStoredFlags = EV_RXFLAG;
	SetCommMask( m_hComDev, dwStoredFlags );

	return CODE_SUCCESS;
}

DWORD CSMS::AsyncComWrite ( LPCTSTR lpszWrite )
{
	COMSTAT		ComStat;
	DWORD		dwErrorFlags;
	DWORD		dwLength;
	BOOL		bState;
	OVERLAPPED	opWrite;
	CString		strPort;
	strPort.Format( _T("%s"),m_sCom );

	memset( &opWrite, 0, sizeof( OVERLAPPED ) );
	opWrite.hEvent	=	m_hWriteEvent;
	PurgeComm(m_hComDev, PURGE_TXCLEAR | PURGE_RXCLEAR );
	ClearCommError(m_hComDev, &dwErrorFlags, &ComStat);
	bState=WriteFile(m_hComDev,lpszWrite,strlen(lpszWrite),&dwLength,&opWrite);
	if(!bState)
	{
		if(GetLastError()==ERROR_IO_PENDING)
			GetOverlappedResult(m_hComDev,&opWrite,&dwLength,TRUE);// 等待
		else
		{
			m_exp->SetCode( CODE_WRITE_TO_COM_ERROR );
			m_exp->SetDescribe( _T("写端口") + strPort + _T("失败") );
			throw m_exp;
		}
	}
	return CODE_SUCCESS;
}

DWORD CSMS::AsyncComRead( CString &strRead )
{
	COMSTAT		ComStat;
	DWORD		dwErrorFlags;
	OVERLAPPED	opRead;
	DWORD		dwWantRead, dwRealRead;
	CString		strPort;
	char		szBuf[512];
	
	strPort.Format( _T("%s"),m_sCom );
	memset( &opRead, 0, sizeof( OVERLAPPED ) );
	opRead.hEvent	=	m_hReadEvent;
	memset( szBuf, 0, 512 );
	ClearCommError(m_hComDev, &dwErrorFlags, &ComStat);
	dwRealRead	= 0;
	dwWantRead	= 512;
	
	OVERLAPPED	op;
	memset( &op, 0, sizeof(op) );
	op.hEvent = NULL;
	DWORD	  dwFlag;
	dwFlag = EV_RXFLAG;
	op.hEvent = CreateEvent( NULL, FALSE, FALSE, NULL );

	SetCommMask( m_hComDev, EV_RXFLAG );
	strRead = "";
	while( strRead.Find("OK") < 0 && strRead.Find("ERROR") < 0  )
	{
		WaitCommEvent( m_hComDev, &dwFlag, &op );
		if( WaitForSingleObject( op.hEvent, SEND_TIMEOUT*1000 ) != WAIT_OBJECT_0 )
		{
			m_exp->SetCode( CODE_READ_COM_TIMEOUT );
			m_exp->SetDescribe( _T("读端口") + strPort + _T("超时") );
			throw m_exp;
		}
		ClearCommError(m_hComDev, &dwErrorFlags, &ComStat);
		ReadFile(m_hComDev,szBuf,ComStat.cbInQue,&dwRealRead,&opRead);		
		GetOverlappedResult(m_hComDev,&opRead,&dwRealRead,TRUE);
		strRead += szBuf;
		memset( szBuf, 0, 512 );
	}

	CloseHandle( op.hEvent );
	return CODE_SUCCESS;
}

DWORD CSMS::SyncComWrite( CString &strWrite )
{
	DWORD	dwWritedCount;
	CString	strPort;
	strPort.Format( _T("%s"),m_sCom );
	if( !WriteFile( m_hComDev,
					(LPCVOID)strWrite,
					strWrite.GetLength(),
					&dwWritedCount,
					NULL ) ){
		m_exp->SetCode( CODE_WRITE_TO_COM_ERROR );
		m_exp->SetDescribe( _T("写端口") + strPort + _T("失败") );
		throw m_exp;
	}
	
	return CODE_SUCCESS;
}

DWORD CSMS::SyncComRead( CString	&strRead )
{
	DWORD	lReadCount = 0;
	char	szBuf[1024];
	CString  strPort;
	
	strPort.Format( _T("%s"),m_sCom );
	memset( szBuf, 0, 1024 );
	if( !ReadFile( m_hComDev,
			  szBuf,
			  1203,
			  &lReadCount,
			  NULL ) ){
		m_exp->SetCode( CODE_READ_FROM_COM_ERROR );
		m_exp->SetDescribe( _T("读端口") + strPort + _T("失败") );
		throw m_exp;
	}
	
	strRead = szBuf;
	return CODE_SUCCESS;
}

CString CSMS::DoUniCode( LPCTSTR lpszSource )
{
	CString str;
	char temp[512],buffer[256];
	int i,nLength;
	unsigned short uTemp[256];
	strcpy( buffer,lpszSource );
	nLength = MultiByteToWideChar( 936,MB_COMPOSITE,buffer,-1,uTemp,255 );
	memset( temp,0,sizeof(temp) );
	for ( i = 0; i < nLength; i ++ ) {
		if ( uTemp[i] == 0 ) break;
		sprintf( temp+strlen(temp),"%04X",(int)uTemp[i] );
	}
	
	str = temp;
	return str;
}

int CSMS::SetVPH(int nHour)	
{//保留时间编码 
	int nResult;
	if ( nHour > 10584 ) nHour = 10584;
	if ( nHour >= 5*7*24 )	{			
		nResult = nHour/(24*7)+192;
	}else if ( nHour >= 48 ) {
		if( nHour >720 ) nHour = 720;
		nResult = nHour/24+166;
	}else if ( nHour >= 13 ) {
		if( nHour >24 )  nHour = 24;
		nResult = (nHour-12)*2+143;
	}else if ( nHour >= 0 ) {
		if( nHour==0 ) nResult = 0;
		else nResult = nHour*12-1;
	}
    return nResult;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -