通过支持AT指令集的手机发送短消息(源代码)

本文章的版权声明:
1)任何的编程爱好者、网友可以以非商业目的下载并使用下面的源代码。
2)使用了下面全部或部分代码的朋友请注明出处:http://blog.csdn.net/dfman
3)保留对商业用途的版权

具体做法是这样的:1)买一款支持AT指令集的手机,我买的是西门子;2)买与手机配套的数据线,使手机可以与计算机串口相链接;3)当然你要有SIM/UIM卡;4)按下面的算法编写程序;5)剩下的就是收发短信了。

这个class是整个工程的一部分,不敢保证代码完整,但是可以保证算法和思路完整。

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 );
 }
}

posted @ 2009-03-23 11:14  scgw  阅读(608)  评论(0编辑  收藏  举报