本文章的版权声明:
1)任何的编程爱好者、网友可以以非商业目的下载并使用下面的源代码。
2)使用了下面全部或部分代码的朋友请注明出处:http://blog.csdn.net/dfman
3)保留对商业用途的版权
具体做法是这样的:1)买一款支持AT指令集的手机,我买的是西门子;2)买与手机配套的数据线,使手机可以与计算机串口相链接;3)当然你要有SIM/UIM卡;4)按下面的算法编写程序;5)剩下的就是收发短信了。
这个class是整个工程的一部分,不敢保证代码完整,但是可以保证算法和思路完整。整个工程可能还包括SMPP/SGIP/CMPP的源代码,如有需要,请来信相我索要:t1p2@sina.com。我没有其他的邮箱。
typedef struct _SMS_Recv //收到信息的通知结构
{
long lMsgType; //短信类型:MSGTYPE_SMS 或 MSGTYPE_REPORT
char szSmsc[32]; //短信中心
char szSender[32]; //发送者号码,如果lMsgType==MSGTYPE_REPORT,则是状态报告的目标手机号码
char szTime[32]; //发送时间
char szMsg[512]; //信息内容
}SMS_Recv;
// 短消息队列缓冲池
struct ShortMsgPool {
HANDLE hSMPHaveData;
HANDLE hSMPIDLE;
DWORD dwSize;
char *pData;
};
// 发送短消息缓冲池
struct SubmitPool {
HANDLE hSPDeliver;
HANDLE hSPIDLE;
DWORD dwSize;
char *pData;
};
// 接收短消息缓冲池
struct DeliverPool {
HANDLE hDPDeliver; // 投递请求的事件句柄
HANDLE hDPIDLE; // 表示缓冲池空的事件句柄
DWORD dwSize; // 请求数据的大小,以字节为单位
char *pData; // 请求数据存放的缓冲区
};
class CGSMPhone
{
public:
long GetRecvNum(){ return( m_dwSMNumberInPool ); }
long GetMobileName( char* pName );
long GetSMContent( void ){ return( m_dwSMContent == 0 ? -1 : m_dwSMContent ); }
long GetShortMsg( SMS_Recv * pSms );
long GetShortMsg2( char *pNo, char *pMsg, char *pTime );
long Send( char *pNo, char *pMsg, BOOL bReport, BOOL bHandFree, BOOL bAsyn );
bool Close();
bool Open( int nPort = 1, int nBaud = 19200 );
bool IsOpened( void ){ return( m_bOpened ); }
void DeliverThread();
void SubmitThread();
CGSMPhone();
virtual ~CGSMPhone();
HWND m_hWnd;
DWORD m_dwTimeout;
CString m_strSMCenter;
protected:
DWORD Deliver( char *&pData );
DWORD Submit ( char *szBuffer, DWORD dwLen );
DWORD PDUEncodeEng( char *pMsg, char *&pResultData );
DWORD PDUEncodeChn( char *pMsg, char *&pResultData );
DWORD PDUDecodeEng( char *pMsg, char *&pResultData );
DWORD PDUDecodeChn( char *pMsg, char *&pResultData );
char* NumberEncode( char *pPhoneNumber );
bool NumberDecode ( char *szNumber, int nLen );
void Str2StrArr( CString strTemp, CStringArray &sa, char cDelimiter );
DWORD ReadStringFromComm( char *szBuffer, DWORD dwBufLen );
DWORD ReadComm( char *szBuffer, DWORD dwBufLen );
bool WriteComm( const char *buffer, DWORD size );
bool FreeShortMsgPool( void );
bool FreeDeliverPool ( void );
bool FreeSubmitPool ( void );
bool CreateShortMsgPool( DWORD dwNum );
bool CreateDeliverPool ( DWORD dwNum );
bool CreateSubmitPool ( DWORD dwNum );
SubmitPool* m_pSPool;
HANDLE* m_phSPDeliver;
HANDLE* m_phSPIDLE;
DeliverPool* m_pDPool;
HANDLE* m_phDPDeliver;
HANDLE* m_phDPIDLE;
ShortMsgPool* m_pSMPool;
HANDLE* m_phSMPHaveData;
HANDLE* m_phSMPIDLE;
HANDLE m_hSystemExit;
HANDLE m_hIDComDev;
LONG m_dwSMNumberInPool;
DWORD m_dwThreadPoolNum;
DWORD m_dwSMContentPoolNum;
DWORD m_dwSMContent;
bool m_bOpened;
bool m_bStarted;
OVERLAPPED m_Overlapped;
CRITICAL_SECTION m_csComm;
CString m_strCommBuffer;
CString m_strMobileName;
};
#include "GSMPhone.h"
#include <process.h>
void SubmitThreadFun( LPVOID lpParam )
{
CGSMPhone* pGSMPhone = (CGSMPhone*)lpParam;
pGSMPhone->SubmitThread();
}
void DeliverThreadFun( LPVOID lpParam )
{
CGSMPhone* pGSMPhone = (CGSMPhone*)lpParam;
pGSMPhone->DeliverThread();
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGSMPhone::CGSMPhone()
{
m_hIDComDev = NULL;
m_hSystemExit = NULL;
m_hWnd = NULL;
m_bOpened = false;
m_bStarted = false;
m_dwTimeout = 5;
m_dwThreadPoolNum = 5;
m_dwSMContent = 0;
m_dwSMNumberInPool = 0;
m_strSMCenter = "";
m_strCommBuffer = "";
m_strMobileName = "";
// hDDeliver = CreateEvent( NULL,FALSE,FALSE,NULL );
}
CGSMPhone::~CGSMPhone()
{
}
bool CGSMPhone::CreateSubmitPool(DWORD dwNum)
{
try {
m_pSPool = new SubmitPool[dwNum+1];
m_phSPDeliver = new HANDLE[dwNum+1];
m_phSPIDLE = new HANDLE[dwNum+1];
for( DWORD dw = 0; dw < dwNum; dw ++ ) {
m_phSPDeliver[dw] = m_pSPool[dw].hSPDeliver = CreateEvent( NULL,FALSE,FALSE,NULL );
m_phSPIDLE[dw] = m_pSPool[dw].hSPIDLE = CreateEvent( NULL,FALSE,TRUE,NULL );
}
m_phSPDeliver[dw] = m_phSPIDLE[dw] = m_hSystemExit;
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::FreeSubmitPool()
{
try {
for( DWORD dwCount = 0; dwCount < m_dwThreadPoolNum; dwCount ++ ) {
CloseHandle( m_pSPool[dwCount].hSPDeliver );
m_pSPool[dwCount].hSPDeliver = NULL;
CloseHandle( m_pSPool[dwCount].hSPIDLE );
m_pSPool[dwCount].hSPIDLE = NULL;
}
delete [] m_phSPDeliver;
m_phSPDeliver = NULL;
delete [] m_phSPIDLE;
m_phSPDeliver = NULL;
delete [] m_pSPool;
m_pSPool = NULL;
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::CreateDeliverPool(DWORD dwNum)
{
try {
m_pDPool = new DeliverPool[dwNum+1];
m_phDPDeliver = new HANDLE[dwNum+1];
m_phDPIDLE = new HANDLE[dwNum+1];
for( DWORD dw = 0; dw < dwNum; dw ++ ) {
m_phDPDeliver[dw] = m_pDPool[dw].hDPDeliver = CreateEvent( NULL,FALSE,FALSE,NULL );
m_phDPIDLE[dw] = m_pDPool[dw].hDPIDLE = CreateEvent( NULL,FALSE,TRUE,NULL );
}
m_phDPDeliver[dw] = m_phDPIDLE[dw] = m_hSystemExit;
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::FreeDeliverPool()
{
try {
for( DWORD dwCount = 0; dwCount < m_dwThreadPoolNum; dwCount ++ ) {
CloseHandle( m_pDPool[dwCount].hDPDeliver );
m_pDPool[dwCount].hDPDeliver = NULL;
CloseHandle( m_pDPool[dwCount].hDPIDLE );
m_pDPool[dwCount].hDPIDLE = NULL;
}
delete [] m_phDPDeliver;
m_phDPDeliver = NULL;
delete [] m_phDPIDLE;
m_phDPDeliver = NULL;
delete [] m_pDPool;
m_pDPool = NULL;
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::CreateShortMsgPool(DWORD dwNum)
{
try {
m_pSMPool = new ShortMsgPool[dwNum];
m_phSMPHaveData = new HANDLE[dwNum];
m_phSMPIDLE = new HANDLE[dwNum];
for( DWORD dw = 0; dw < dwNum; dw ++ ) {
m_phSMPHaveData[dw] = m_pSMPool[dw].hSMPHaveData = CreateEvent( NULL,FALSE,FALSE,NULL );
m_phSMPIDLE[dw] = m_pSMPool[dw].hSMPIDLE = CreateEvent( NULL,FALSE,TRUE,NULL );
}
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::FreeShortMsgPool()
{
try {
for( DWORD dwCount = 0; dwCount < m_dwSMContentPoolNum; dwCount ++ ) {
CloseHandle( m_pSMPool[dwCount].hSMPHaveData );
m_pSMPool[dwCount].hSMPHaveData = NULL;
CloseHandle( m_pSMPool[dwCount].hSMPIDLE );
m_pSMPool[dwCount].hSMPIDLE = NULL;
}
delete [] m_phSMPHaveData;
m_phSMPHaveData = NULL;
delete [] m_phSMPIDLE;
m_phSMPIDLE = NULL;
delete [] m_pSMPool;
m_pSMPool = NULL;
}
catch( ... ) {
return( false );
}
return( true );
}
bool CGSMPhone::WriteComm(const char *buffer, DWORD size)
{
if( m_bOpened == FALSE ) return( false );
DWORD dwBytesSent = 0;
BOOL bResult = TRUE;
EnterCriticalSection( &m_csComm );
bResult = WriteFile( m_hIDComDev, buffer, size, &dwBytesSent, &m_Overlapped );
LeaveCriticalSection( &m_csComm );
if( !bResult ) {
if( ( GetLastError() == ERROR_IO_PENDING ) ) {
if( WaitForSingleObject( m_Overlapped.hEvent, 1000 ) == WAIT_OBJECT_0 ) {
GetOverlappedResult( m_hIDComDev, &m_Overlapped, &dwBytesSent, FALSE );
if( dwBytesSent == size ) {
Sleep( 100 );
return( true );
}
}
}
}
else {
Sleep( 100 );
return( true );
}
return( false );
}
DWORD CGSMPhone::ReadComm(char *szBuffer, DWORD dwBufLen)
{
BOOL bResult = TRUE;
DWORD dwEvtMask = 0;
DWORD dwError = 0;
DWORD dwBytesRead = 0;
COMSTAT comstat;
EnterCriticalSection( &m_csComm );
ClearCommError( m_hIDComDev, &dwError, &comstat);
if( comstat.cbInQue == 0 ) {
LeaveCriticalSection( &m_csComm );
return( 0 );
}
dwBytesRead = comstat.cbInQue;
bResult = ReadFile( m_hIDComDev, szBuffer, dwBytesRead, &dwBytesRead, &m_Overlapped );
LeaveCriticalSection( &m_csComm );
if( !bResult ) {
if( GetLastError() == ERROR_IO_PENDING ) {
Sleep( 100 );
WaitForSingleObject( m_Overlapped.hEvent, 2000 );
GetOverlappedResult( m_hIDComDev, &m_Overlapped, &dwBytesRead, FALSE );
}
}
Sleep( 200 );
return( dwBytesRead );
}
DWORD CGSMPhone::ReadStringFromComm(char *szBuffer, DWORD dwBufLen)
{
char szBuf[1024];
DWORD dwRet = 0;
while( 1 ) {
Sleep( 100 );
memset( szBuf, 0, 1024 );
dwRet = ReadComm( szBuf, 1024 );
if( dwRet > 0 ) {
m_strCommBuffer += szBuf;
if( m_strCommBuffer.Find( "OK" ) == -1 ) continue;
if( m_strCommBuffer.Find( '\r' ) > 0 ) break;
}
else {
break;
}
}
if( !m_strCommBuffer.IsEmpty() ) {
int nFirst = m_strCommBuffer.Find( "OK" );
if( nFirst > 0 ) {
int nNext = m_strCommBuffer.Find( '\r', nFirst );
if( nNext > 0 ) {
int nStrLen = nNext + 1;
strncpy( szBuffer, (LPCTSTR)m_strCommBuffer, nStrLen );
if( m_strCommBuffer.GetLength() > nStrLen ) {
m_strCommBuffer = m_strCommBuffer.Right( m_strCommBuffer.GetLength() - nStrLen );
}
else {
m_strCommBuffer.Empty();
}
return( (DWORD)nStrLen );
}
}
nFirst = m_strCommBuffer.Find( "+CMTI:" );
if( nFirst > 0 ) {
int nNext = m_strCommBuffer.Find( '\r', nFirst );
if( nNext > 0 ) {
int nStrLen = nNext + 1;
strncpy( szBuffer, (LPCTSTR)m_strCommBuffer, nStrLen );
if( m_strCommBuffer.GetLength() > nStrLen ) {
m_strCommBuffer = m_strCommBuffer.Right( m_strCommBuffer.GetLength() - nStrLen );
}
else {
m_strCommBuffer.Empty();
}
return( (DWORD)nStrLen );
}
}
nFirst = m_strCommBuffer.Find( ">" );
if( nFirst > 0 ) {
int nNext = m_strCommBuffer.Find( ' ', nFirst );
if( nNext > 0 ) {
int nStrLen = nNext + 1;
strncpy( szBuffer, (LPCTSTR)m_strCommBuffer, nStrLen );
if( m_strCommBuffer.GetLength() > nStrLen ) {
m_strCommBuffer = m_strCommBuffer.Right( m_strCommBuffer.GetLength() - nStrLen );
}
else {
m_strCommBuffer.Empty();
}
return( (DWORD)nStrLen );
}
}
}
return( 0 );
}
DWORD CGSMPhone::Submit(char *szBuffer, DWORD dwLen)
{
try {
DWORD dwWaitRet = WaitForMultipleObjects( m_dwThreadPoolNum + 1, m_phSPIDLE, FALSE, INFINITE );
if( dwWaitRet == WAIT_OBJECT_0 + m_dwThreadPoolNum ) return( 0 );
m_pSPool[dwWaitRet].pData = new char[dwLen];
CopyMemory( m_pSPool[dwWaitRet].pData, szBuffer, dwLen );
m_pSPool[dwWaitRet].dwSize = dwLen;
SetEvent( m_pSPool[dwWaitRet].hSPDeliver );
}
catch( ... ) {
return( 0 );
}
return( dwLen );
}
DWORD CGSMPhone::Deliver(char *&pData)
{
try {
DWORD dwWaitRet = WaitForMultipleObjects( m_dwThreadPoolNum + 1, m_phDPDeliver, FALSE, m_dwTimeout * 1000 );
if( dwWaitRet == WAIT_OBJECT_0 + m_dwThreadPoolNum ) return( 0 );
if( dwWaitRet != WAIT_TIMEOUT ) {
DWORD dwDataLen = m_pDPool[dwWaitRet].dwSize;
pData = new char[dwDataLen + 1];
ZeroMemory( pData, dwDataLen + 1 );
CopyMemory( pData, m_pDPool[dwWaitRet].pData, dwDataLen );
delete [] m_pDPool[dwWaitRet].pData;
SetEvent( m_pDPool[dwWaitRet].hDPIDLE );
return( dwDataLen );
}
}
catch( ... ) {
return( 0 );
}
return( 0 );
}
void CGSMPhone::SubmitThread()
{
while( 1 ) {
try {
DWORD dwWaitRet = WaitForMultipleObjects( m_dwThreadPoolNum + 1, m_phSPDeliver, FALSE, INFINITE );
if( dwWaitRet == WAIT_OBJECT_0 + m_dwThreadPoolNum ) break;
int n = 0;
while( 1 ) {
if( WriteComm( m_pSPool[dwWaitRet].pData, m_pSPool[dwWaitRet].dwSize ) ) break;
if( (n ++) == 5 ) break;
Sleep( 1000 );
}
delete [] m_pSPool[dwWaitRet].pData;
SetEvent( m_pSPool[dwWaitRet].hSPIDLE );
Sleep( 200 );
}
catch( ... ) {
break;
}
}
}
void CGSMPhone::DeliverThread()
{
while( 1 ) {
try {
char szBuffer[1024] = {0};
DWORD dwReadRet = ReadStringFromComm( szBuffer, 1024 );
if( dwReadRet > 0 ) {
char* pFirst; char* pNext;
if( strstr( szBuffer, "+CMTI:" ) != NULL ) {
pFirst = strchr( szBuffer, ',' );
pFirst ++;
if( pFirst != NULL ) {
pNext = strchr( pFirst, '\r' );
if( pNext != NULL ) {
int len = pNext - pFirst;
if( len <= 0 ) continue;
char szCmd[30] = {0};
memcpy( szCmd, "AT+CMGR=", 8 );
memcpy( szCmd + 8, pFirst, len );
szCmd[8+len] = '\r';
Submit( szCmd, len + 9 );
}
}
}
else if( strstr( szBuffer, "AT+CMGR" ) != NULL ) {
pFirst = strchr( szBuffer, '=' );
pFirst ++;
if( pFirst != NULL ) {
pNext = strchr( pFirst, '\n' );
if( pNext != NULL ) {
int len = pNext - pFirst;
if( len <= 0 ) continue;
char szCmd[30] = {0};
memcpy( szCmd, "AT+CMGD=", 8 );
memcpy( szCmd + 8, pFirst, len );
szCmd[8+len] = '\r';
Submit( szCmd, len + 9 );
}
}
pNext = strstr( szBuffer, "+CMGR:" );
if( pNext != NULL ) {
pFirst = strchr( pNext, '\n' );
while( pFirst[0] == '\r' || pFirst[0] == '\n' ) pFirst ++;
if( pFirst != NULL ) {
pNext = strchr( pFirst, '\r' );
if( pNext != NULL ) {
pNext[0] = '\0';
DWORD dwWaitRet = WaitForMultipleObjects( m_dwSMContentPoolNum, m_phSMPIDLE, FALSE, 1000 );
if( dwWaitRet != WAIT_TIMEOUT ) {
DWORD dwMsgLen = strlen( pFirst );
m_pSMPool[dwWaitRet].pData = new char[dwMsgLen];
CopyMemory( m_pSMPool[dwWaitRet].pData, pFirst, dwMsgLen );
m_pSMPool[dwWaitRet].dwSize = dwMsgLen;
SetEvent( m_pSMPool[dwWaitRet].hSMPHaveData );
InterlockedIncrement( &m_dwSMNumberInPool );
if( m_hWnd != NULL )
::SendMessage( m_hWnd, PHONE_SMS_RECV, 0, 0 );
}
else {
if( m_hWnd != NULL )
::SendMessage( m_hWnd, PHONE_SMS_RECV_BUF_OVERFLOW, 0, 0 );
}
}
}
}
}
else if( strstr( szBuffer, "AT+" ) != NULL ) {
DWORD dwWaitRet = WaitForMultipleObjects( m_dwThreadPoolNum + 1, m_phDPIDLE, FALSE, 1000 );
if( dwWaitRet == WAIT_OBJECT_0 + m_dwThreadPoolNum ) break;
if( dwWaitRet != WAIT_TIMEOUT ) {
m_pDPool[dwWaitRet].pData = new char[dwReadRet];
CopyMemory( m_pDPool[dwWaitRet].pData, szBuffer, dwReadRet );
m_pDPool[dwWaitRet].dwSize = dwReadRet;
SetEvent( m_pDPool[dwWaitRet].hDPDeliver );
}
}
}
}
catch( ... ) {
break;
}
if( WaitForSingleObject( m_hSystemExit, 0 ) != WAIT_TIMEOUT ) return;
}
}
bool CGSMPhone::NumberDecode(char *szNumber, int len)
{
if( len == 0 || szNumber == NULL ) return( false );
char c;
for( int n = 0; n < len; n += 2 ) {
c = szNumber[n];
szNumber[n] = szNumber[n+1];
szNumber[n+1] = c;
}
return( true );
}
char* CGSMPhone::NumberEncode(char *pPhoneNumber)
{
char* szData;
szData = new char[40];
memset( szData, 0, 40 );
if( pPhoneNumber[0] == '+' ) {
memcpy( szData, pPhoneNumber+1, strlen(pPhoneNumber) - 1 );
}
else {
memcpy( szData, pPhoneNumber, strlen(pPhoneNumber) );
}
if( strlen( szData ) % 2 != 0 ) {
szData[strlen(szData)] = 'F';
}
char c;
for( int n = 0; n < int(strlen(szData)); n += 2 ) {
c = szData[n];
szData[n] = szData[n+1];
szData[n+1] = c;
}
return szData;
}
DWORD CGSMPhone::PDUDecodeChn(char *pMsg, char *&pResultData)
{
if( pMsg == NULL ) return( 0 );
int len = strlen( pMsg );
if( len % 2 != 0 ) return( 0 );
LPWSTR lpszW = new WCHAR[len/2+1];
memset( lpszW, 0, len + 2 );
BYTE* p = (BYTE *)lpszW;
int i = 0, j = 0;
char szTemp[3] = {0};
while( i < len ) {
if( j % 2 ) {
strncpy( szTemp, pMsg + i - 2, 2 );
}
else {
strncpy( szTemp, pMsg + i + 2, 2 );
}
sscanf( szTemp, "%x", &p[j++] );
i += 2;
}
len = j;
pResultData = new char[len + 1];
memset( pResultData, 0, len + 1 );
WideCharToMultiByte( CP_ACP, 0, lpszW, -1, pResultData, len, NULL, FALSE );
delete [] lpszW;
return( len );
}
DWORD CGSMPhone::PDUDecodeEng(char *pMsg, char *&pResultData)
{
if( pMsg == NULL ) return( 0 );
int len = strlen( pMsg );
if( len % 2 != 0 ) return( 0 );
char psz[3] = {0};
BYTE b;
int i = 0, j = 0;
BYTE* pTemp;
pTemp = new BYTE[len / 2];
memset( pTemp, 0, len / 2 );
while( i < len ) {
strncpy( psz, pMsg + i, 2 );
sscanf( psz, "%x", &b );
pTemp[j++] = b;
i += 2;
}
len = j; i = 0; j = 0;
pResultData = new char[len+20];
memset( pResultData, 0, len+20 );
char* pCur = pResultData;
while( i < len ) {
if( i == 0 ) {
pCur[0] = pTemp[i] & 0x7F;
}
else {
pCur[0] = ( pTemp[i] << j | pTemp[i-1] >> (8 - j) ) & 0x7F;
}
pCur ++;
i += 1;
j = ( j + 1 ) % 8;
if( j == 0 ) i --;
}
pCur[0] = pTemp[i-1] >> (8 - j);
delete [] pTemp;
return( pCur - pResultData );
}
DWORD CGSMPhone::PDUEncodeChn(char *pMsg, char *&pResultData)
{
int nLen = MultiByteToWideChar(CP_ACP, 0, pMsg, -1, NULL, NULL);
LPWSTR lpszW = new WCHAR[nLen];
MultiByteToWideChar(CP_ACP, 0, pMsg, -1, lpszW, nLen);
DWORD dwResultSize = (nLen-1)*sizeof(WCHAR)*2;
pResultData = new char[dwResultSize];
char szTemp[3] = {0};
for( int i = 0, j = 0; j < nLen-1; j++ ) {
sprintf( szTemp, "%.2X", HIBYTE(lpszW[j]) );
CopyMemory( pResultData + i, szTemp, 2 );
i += 2;
sprintf( szTemp, "%.2X", LOBYTE(lpszW[j]) );
CopyMemory( pResultData + i, szTemp, 2 );
i += 2;
}
delete [] lpszW;
return( dwResultSize / 2 );
}
DWORD CGSMPhone::PDUEncodeEng(char *pMsg, char *&pResultData)
{
if( pMsg == NULL ) return( 0 );
int nMsgLen = strlen( pMsg );
pResultData = new char[nMsgLen * 2];
memset( pResultData, 0, nMsgLen * 2 );
char* pCur = pResultData;
int i = 0, j = 0;
while( i < nMsgLen ) {
if( i < nMsgLen )
sprintf( pCur, "%.2X", BYTE(pMsg[i] >> j | pMsg[i+1] << ( 7 - j )) );
else
sprintf( pCur, "%.2X", BYTE(pMsg[i] >> j) );
pCur += 2;
i ++;
j = ( j + 1 ) % 7;
if( j == 0 ) i ++;
}
return( pCur - pResultData );
}
void CGSMPhone::Str2StrArr(CString strTemp, CStringArray &sa, char cDelimiter)
{
sa.RemoveAll();
for( ;; ) {
int nPos;
if( ( nPos = strTemp.Find( cDelimiter ) ) != -1 ) {
sa.Add( strTemp.Left( nPos ) );
strTemp = strTemp.Mid( nPos + 1 );
}
else {
if( !strTemp.IsEmpty() ) sa.Add( strTemp );
break;
}
}
}
bool CGSMPhone::Open(int nPort, int nBaud)
{
char szPort[15];
wsprintf( szPort, "COM%d", nPort );
m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == NULL ) return( false );
memset( &m_Overlapped, 0, sizeof( OVERLAPPED ) );
m_Overlapped.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
DCB dcb;
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_Overlapped.hEvent == NULL ) {
DWORD dwError = GetLastError();
if( m_Overlapped.hEvent != NULL ) CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
return( false );
}
m_bOpened = true;
InitializeCriticalSection( &m_csComm );
Sleep( 2000 );
char szBuffer[1024] = {0};
DWORD dwRet = 0;
try {
sprintf( szBuffer, "AT\r" );
WriteComm( szBuffer, 3 );
Sleep( 200 );
memset( szBuffer, 0, 1024 );
if( ReadStringFromComm( szBuffer, 1024 ) == 0 ) {
CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
DeleteCriticalSection( &m_csComm );
return( false );
}
memset( szBuffer, 0, 1024 );
sprintf( szBuffer, "AT&F E1\r" );
WriteComm( szBuffer, 8 );
Sleep( 200 );
memset( szBuffer, 0, 1024 );
if( ReadStringFromComm( szBuffer, 1024 ) == 0 ) {
CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
DeleteCriticalSection( &m_csComm );
return( false );
}
memset( szBuffer, 0, 1024 );
sprintf( szBuffer, "AT+CNMI=1,1,0,2,1\r" );
WriteComm( szBuffer, 18 );
Sleep( 200 );
memset( szBuffer, 0, 1024 );
if( ReadStringFromComm( szBuffer, 1024 ) == 0 ) {
CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
DeleteCriticalSection( &m_csComm );
return( false );
}
memset( szBuffer, 0, 1024 );
sprintf( szBuffer, "AT+CPMS?\r" );
WriteComm( szBuffer, 9 );
Sleep( 200 );
memset( szBuffer, 0, 1024 );
dwRet = ReadStringFromComm( szBuffer, 1024 );
if( dwRet > 0 ) {
char* pDest = strstr( szBuffer, "+CPMS:" );
if( pDest != NULL ) {
CString strTemp = CString( pDest + 7, 15 );
CStringArray saTemp;
Str2StrArr( strTemp, saTemp, ',' );
if( saTemp.GetSize() > 3 ) m_dwSMContent = atoi( saTemp.GetAt( 2 ) );
}
}
if( m_dwSMContent > 0 && m_dwSMContent < 50 ) {
m_dwSMContentPoolNum = m_dwSMContent;
}
else {
m_dwSMContentPoolNum = 30;
}
memset( szBuffer, 0, 1024 );
sprintf( szBuffer, "AT+CGMM\r" );
WriteComm( szBuffer, 8 );
Sleep( 200 );
memset( szBuffer, 0, 1024 );
if( ReadStringFromComm( szBuffer, 1024 ) > 0 ) {
char* pFirst = strchr( szBuffer, '\r' );
char* pNext = NULL;
while( pFirst[0] == '\r' || pFirst[0] == '\n' ) pFirst ++;
if( pFirst != NULL )
pNext = strchr( pFirst, '\r' );
if( pNext != NULL ) pNext[0] = '\0';
m_strMobileName = pFirst;
}
}
catch( ... ) {
CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
DeleteCriticalSection( &m_csComm );
return( false );
}
m_hSystemExit = CreateEvent( NULL, TRUE, FALSE, NULL );
CreateSubmitPool( m_dwThreadPoolNum );
CreateDeliverPool( m_dwThreadPoolNum );
CreateShortMsgPool( m_dwSMContentPoolNum );
_beginthread( (void (__cdecl*)(void *))SubmitThreadFun,0,this );
_beginthread( (void (__cdecl*)(void *))DeliverThreadFun,0,this );
m_bStarted = true;
// OutputDebugString( "Start OK." );
return( m_bStarted );
}
bool CGSMPhone::Close()
{
SetEvent( m_hSystemExit );
Sleep( 1200 );
CloseHandle( m_hSystemExit );
CloseHandle( m_Overlapped.hEvent );
CloseHandle( m_hIDComDev );
DeleteCriticalSection( &m_csComm );
FreeSubmitPool();
FreeDeliverPool();
FreeShortMsgPool();
return( true );
}
long CGSMPhone::Send(char *pNo, char *pMsg, BOOL bReport, BOOL bHandFree, BOOL bAsyn)
{
if( IsOpened() == false ) return( -4 );
if( pNo == NULL ) return( -5 );
if( pMsg == NULL ) return( -5 );
if( m_strSMCenter.IsEmpty() ) return( -1 );
char szSendBuf[1024] = {0};
char szTemp[20] = {0};
char* pReceiveData = NULL;
int len = 0;
sprintf( szSendBuf, "AT+CMGS=60\r\n" );
Submit( szSendBuf, strlen(szSendBuf) );
memset( szSendBuf, 0, 1024 );
DWORD dwRet = Deliver( pReceiveData );
if( dwRet == 0 || strstr( pReceiveData, ">" ) == NULL ) {
return( -5 );
}
delete [] pReceiveData;
pReceiveData = NULL;
char* p = NumberEncode( (char*)(LPCTSTR)m_strSMCenter );
// sprintf( szTemp, "%.2X", strlen( p ) );
memcpy( szSendBuf+len, "0891", 4 );// 91代表国际、ISDN/电话号码,没有必要选取其他的值
len += 4;
if( strncmp( p, "68", 2 ) != 0 ) {
if( strlen( p ) != 12 ) return( -5 );
memcpy( szSendBuf+len, "68", 2 );
len += 2;
}
else {
if( strlen( p ) != 14 ) return( -5 );
}
memcpy( szSendBuf+len, p, strlen( p ) );
len += strlen( p );
delete [] p;
memcpy( szSendBuf+len, "1100", 4 );// 文件头字节,具体有很多设置,没有特别必要选取其他值
len += 4;
sprintf( szTemp, "%.2X", strlen( pNo ) );
memcpy( szSendBuf+len, szTemp, 2 );
len += 2;
memcpy( szSendBuf+len, "81", 2 );// 未知、ISDN/电话号码,没有必要选取其他值
len += 2;
p = NumberEncode( pNo );
memcpy( szSendBuf+len, p, strlen( p ) );
len += strlen( p );
delete [] p;
if( bHandFree ) {// 00代表TP_PID值, 18或08代表TP_DCS,A7代表短消息保存24小时
memcpy( szSendBuf+len, "0018A7", 6 );
}
else {
memcpy( szSendBuf+len, "0008A7", 6 );
}
len += 6;
DWORD dw = PDUEncodeChn( pMsg, p );
sprintf( szTemp, "%.2X", dw );
memcpy( szSendBuf+len, szTemp, 2 );
len += 2;
memcpy( szSendBuf+len, p, dw * 2 );
len += dw * 2;
delete [] p;
szSendBuf[len] = 0x1A;// 1A代表短消息结束
len += 1;
memcpy( szSendBuf+len, "\r", 1 );
len += 1;
Submit( szSendBuf, len );
dwRet = Deliver( pReceiveData );
if( dwRet > 0 ) {
if( strstr( pReceiveData, szSendBuf ) != NULL ) {
if( m_hWnd != NULL )
::SendMessage( m_hWnd, PHONE_SMS_SUB, 0, 0 );
return( len );
}
delete [] pReceiveData;
pReceiveData = NULL;
}
return( 0 );
}
long CGSMPhone::GetShortMsg(SMS_Recv *pSms)
{
if( m_bStarted == false ) return( -1 );
DWORD dwWaitRet = WaitForMultipleObjects( m_dwSMContentPoolNum, m_phSMPHaveData, FALSE, 1000 );
if( dwWaitRet != WAIT_TIMEOUT ) {
DWORD dwMsgLen = m_pSMPool[dwWaitRet].dwSize;
char* pszBuffer;
pszBuffer = new char[dwMsgLen + 1];
ZeroMemory( pszBuffer, dwMsgLen + 1 );
CopyMemory( pszBuffer, m_pSMPool[dwWaitRet].pData, dwMsgLen );
delete [] m_pSMPool[dwWaitRet].pData;
SetEvent( m_pSMPool[dwWaitRet].hSMPIDLE );
InterlockedDecrement( &m_dwSMNumberInPool );
int len = 0;
char* p = pszBuffer;
char szTemp[1024] = {0};
bool bEng = false;
ZeroMemory( pSms, sizeof( SMS_Recv ) );
pSms->lMsgType = MSGTYPE_SMS;
CopyMemory( szTemp, p, 2 );
int nNumLen = atoi( szTemp );
p += 2;
if( nNumLen <= 16 ) {
CopyMemory( pSms->szSmsc, p, nNumLen * 2 );
NumberDecode( pSms->szSmsc, nNumLen * 2 );
if( pSms->szSmsc[nNumLen * 2 - 1] == 'F' ) pSms->szSmsc[nNumLen * 2 - 1] = '\0';
}
p += nNumLen * 2;
p += 4;
NumberDecode( p, 16 );
CopyMemory( pSms->szSender, "+", 1 );
CopyMemory( pSms->szSender + 1, p + 2, 13 );
p += 16;
if( strncmp( p, "0000", 4 ) ) bEng = true;
p += 4;
NumberDecode( p, 10 );
sprintf( pSms->szTime, "20%.2s.%.2s.%.2s %.2s:%.2s", p, p + 2, p + 4, p + 6, p + 8 );
p += 10;
p += 4;
CopyMemory( szTemp, p, 2 );
int nMsgLen = atoi( szTemp );
p += 2;
char* pMsg = NULL;
if( bEng ) {
len = PDUDecodeEng( p, pMsg );
}
else {
len = PDUDecodeChn( p, pMsg );
}
CopyMemory( pSms->szMsg, pMsg, len );
delete [] pszBuffer;
return( 0 );
}
return( -1 );
}
long CGSMPhone::GetShortMsg2(char *pNo, char *pMsg, char *pTime)
{
if( m_bStarted == false ) return( -1 );
DWORD dwWaitRet = WaitForMultipleObjects( m_dwSMContentPoolNum, m_phSMPHaveData, FALSE, 1000 );
if( dwWaitRet != WAIT_TIMEOUT ) {
DWORD dwMsgLen = m_pSMPool[dwWaitRet].dwSize;
char* pszBuffer;
pszBuffer = new char[dwMsgLen + 1];
ZeroMemory( pszBuffer, dwMsgLen + 1 );
CopyMemory( pszBuffer, m_pSMPool[dwWaitRet].pData, dwMsgLen );
delete [] m_pSMPool[dwWaitRet].pData;
SetEvent( m_pSMPool[dwWaitRet].hSMPIDLE );
InterlockedDecrement( &m_dwSMNumberInPool );
int len = 0;
char* p = pszBuffer;
char szTemp[1024] = {0};
bool bEng = false;
CopyMemory( szTemp, p, 2 );
int nNumLen = atoi( szTemp );
p += nNumLen * 2;
p += 6;
NumberDecode( p, 16 );
ZeroMemory( pNo, 15 );
CopyMemory( pNo, "+", 1 );
CopyMemory( pNo + 1, p + 2, 13 );
p += 18;
if( strncmp( p, "00", 4 ) == 0 ) bEng = true;
p += 2;
NumberDecode( p, 10 );
ZeroMemory( pTime, 17 );
sprintf( pTime, "20%.2s.%.2s.%.2s %.2s:%.2s", p, p + 2, p + 4, p + 6, p + 8 );
p += 10;
p += 4;
CopyMemory( szTemp, p, 2 );
int nMsgLen = atoi( szTemp );
p += 2;
char* pResult = NULL;
if( bEng ) {
len = PDUDecodeEng( p, pResult );
}
else {
len = PDUDecodeChn( p, pResult );
}
if( len > 0 ) {
ZeroMemory( pMsg, len + 1 );
CopyMemory( pMsg, pResult, len );
delete [] pResult;
}
delete [] pszBuffer;
return( 0 );
}
return( -1 );
}
long CGSMPhone::GetMobileName(char *pName)
{
if( m_strMobileName.IsEmpty() ) {
return( -1 );
}
else {
ZeroMemory( pName, m_strMobileName.GetLength() + 1 );
CopyMemory( pName, (LPCTSTR)m_strMobileName, m_strMobileName.GetLength() );
return( 0 );
}
}