📄 gmodem.cpp
字号:
// GModem.cpp: implementation of the CGModem class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GModem.h"
#include "common.h"
#include <fstream> //support file oparetion
using namespace std;
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGModem::CGModem()
{
//Create signal Object
for(int i=0; i<RESPONSE_LIST_SM+1; i++)
{
m_responseEvent[i]=CreateEvent(NULL,FALSE,FALSE,"");
}
}
CGModem::~CGModem()
{
}
//Initilize static Attribute
int CGModem::m_iCurrentIndex=0;
BOOL CGModem::m_fIsLinked=FALSE;
HANDLE CGModem::m_responseEvent[RESPONSE_LIST_SM+1]={NULL};
CStringArray CGModem::m_commandSet;
LsComm::CComPort CGModem::m_ComPort;
CString CGModem::m_sErrorDesp;
STRU_SMS CGModem::m_readSm;
UINT CGModem::m_nMessageID=0;
HWND CGModem::m_hMessageWnd=NULL;
/*****************************************************************************
* Class : CGModem
* Function : LinkModem
* Description: Initilize the com
* Parameters : nCom:the number of com
* Return :
******************************************************************************/
BOOL CGModem::LinkModem(UINT nCom)
{
try
{
m_fIsLinked=FALSE; //not linked
m_ComPort.Open(nCom,LsComm::CComPort::AutoReceiveBySignal,57600);
m_ComPort.SetReceiveFunc((FOnReceiveData)CGModem::OnReceiveData,this);
CString sCommand; //Command string
sCommand="AT+CMEE=2\r"; //Get more error information
ExecCmd(sCommand); //Execute AT Comamnd
//Wait OK response
int iResult=-1;
iResult=WaitAnswer(1000); //Wait the TE return OK in 1s Timeout
if(RESPONSE_OK!=iResult)
{
//Error description
m_sErrorDesp="Can not link the GMS modem";
//Close Com for link again
Close();
return FALSE;
}
//---------------------------------------------------------------
//Set default Sending SM mode
sCommand="AT+CMGF=0\r"; //UDP Mode
ExecCmd(sCommand);
//Wait OK response
iResult=-1; //Given a invalid value
iResult=WaitAnswer(1000); //Wait the TE return OK in 1s Timeout
if(RESPONSE_OK!=iResult)
{
m_sErrorDesp="Execute "+sCommand+" fail."+m_sErrorDesp;
return FALSE;
}
m_currentMode=UDP; //Modify the Current Sending mode
//---------------------------------------------------------------
sCommand="AT+CNMI=1,1,0,0,1\r"; //register indicate when a new SM received
ExecCmd(sCommand);
//Wait OK response
iResult=-1; //Given a invalid value
iResult=WaitAnswer(1000); //Wait the TE return OK in 1s Timeout
if(RESPONSE_OK!=iResult)
{
m_sErrorDesp="Execute "+sCommand+" fail.\r"+m_sErrorDesp;
return FALSE;
}
m_fIsLinked=TRUE; //It have already linked TE
}
catch(...)
{
m_nError=GMODEM_OPEN_COMM_FAIL;
m_sErrorDesp="Initializing port error. The Port is opened or is not exist.";
return FALSE;
}
return m_fIsLinked;
}
/*****************************************************************************
* Class : CGModem
* Function : GetError
* Description: if API execute fail, invoking this will get the Error description
* Parameters : error--the pointer of error description buffer, MAX_SIZE=256
* Return :
******************************************************************************/
UINT CGModem::GetError(LPSTR error)
{
strcpy(error,m_sErrorDesp);
return m_nError;
}
/*****************************************************************************
* Class : CGModem
* Function : SendSms
* Description: Send a Short message by AT command
We do not catch error and check the config for efficiency.
Before you invoke the function to send SM, Be sure the config
is OK.
* Parameters : destAddr-- the mobile number who recive the SM(be sure it is right)
* userData-- the content of SM
* nSmsFormat-- UDP in UDP Mode (default)
* TEXT in TEXT Mode
* Return : Send Succeed return TRUE, or return FALSE
******************************************************************************/
BOOL CGModem::SendSm(LPCTSTR destAddr, LPCTSTR userData, UINT nSmsFormat/*=UDP*/)
{
if(!m_fIsLinked) //not linked modem
{
m_sErrorDesp="Not linked modem.Before you send SM, you must link modem";
return FALSE;
}
int iResult=-1;
switch(nSmsFormat)
{
case UDP ://default sending mode
{
UINT nDataLength=0;
CString sData=CreatePduSms(destAddr,userData,&nDataLength);
CString sCommand;
if(UDP!=m_currentMode)
{
//Set default Sending SM mode
sCommand="AT+CMGF=0\r"; //UDP Mode
ExecCmd(sCommand);
//Wait OK response
iResult=-1; //Given a invalid value
iResult=WaitAnswer(1000); //Wait the TE return OK in 1s Timeout
if(RESPONSE_OK!=iResult)
{
m_sErrorDesp="Execute "+sCommand+" fail.";
return FALSE;
}
m_currentMode=UDP; //Modify the Current Sending mode
}
sCommand.Format("AT+CMGS=%d\r",nDataLength);
ExecCmd(sCommand);
iResult=WaitSingleAnswer(RESPONSE_INPUT/*'>'*/,1000);
if(RESPONSE_INPUT!=iResult)
{
m_sErrorDesp="Can not get input prompt(>), Send SM Fail";
return FALSE;
}
sCommand=sData;
//the end character
char ctrl_z=26;
sCommand+=ctrl_z;
int iSize=m_commandSet.GetSize();
ExecCmd(sCommand);
//Wait the result
iResult=WaitSingleAnswer(RESPONSE_SEND_SM, 10*1000);
if(RESPONSE_SEND_SM!=iResult)
{
//send fail
return FALSE;
}
return TRUE;
}
case TEXT:
{
//ensure sending data only contains acs2
CString sCommand;
if(TEXT!=m_currentMode)
{
//Set default Sending SM mode
sCommand="AT+CMGF=1\r"; //UDP Mode
ExecCmd(sCommand);
//Wait OK response
iResult=-1; //Given a invalid value
iResult=WaitAnswer(1000); //Wait the TE return OK in 1s Timeout
if(RESPONSE_OK!=iResult)
{
m_sErrorDesp="Execute "+sCommand+" fail.";
return FALSE;
}
m_currentMode=TEXT; //Modify the Current Sending mode
}
sCommand.Format("AT+CMGS=\"%s\"\r",destAddr);
ExecCmd(sCommand);
iResult=WaitSingleAnswer(RESPONSE_INPUT/*'>'*/,1000);
if(RESPONSE_INPUT!=iResult)
{
m_sErrorDesp="Can not Get '>', Send SM Fail";
return FALSE;
}
sCommand=userData;
int length=sCommand.GetLength();
if(length>140) //保证140个英文字符以内
{
sCommand=sCommand.Left(140);
}
//add end
char ctrl_z=26;
sCommand+=ctrl_z;
ExecCmd(sCommand);
//Wait the result
iResult=WaitSingleAnswer(RESPONSE_SEND_SM, 10*1000);
if(RESPONSE_SEND_SM!=iResult)
{
//send fail
return FALSE;
}
return TRUE;
}
default:
{
AfxMessageBox("SendSm fucntion the 3rd para error");
ASSERT(FALSE); //no possible
}
}
return TRUE;
}
/*****************************************************************************
* Class : CGModem
* Function : HandleResponse
* Description: Handle the answer string
* Parameters : sDestAddr: the phone number who receive the SM
* userData: the content of the sm
* nDataLength: the length of the PDU exclude the CSCA
* Return :
******************************************************************************/
CString CGModem::CreatePduSms(CString sDestAddr,CString userData, UINT *nDataLength)
{
CString sResult;
sResult="00"; //无指定短信中心号码,按CSCA 号码
sResult+="1100"; //固定格式
//13位的电话号码,目的地址
sResult+="0D91";
char sNO[20];
memset(sNO,0,sizeof(sNO));
strcpy(sNO,sDestAddr);
//经过BCD编码的电话号码
sResult+=to_BCD(sNO,sDestAddr.GetLength());
sResult+="00"; //TP-PID,固定格式
sResult+="08"; //TP-DCS,UCS2编码方式
sResult+="A7"; //TP-Validity-Period,有效期
//添加数据, 先转化为UCS2
//最多54个中文的字符
char sMS[160];
strcpy(sMS,userData);
int length=userData.GetLength();
userData=to_UCS2(sMS,userData.GetLength());
length=userData.GetLength();
CString sLetter;
//把UCS2的字符值转化成数字型
for(int i=0; i<userData.GetLength();i++)
{
sLetter+=Int2HexString((BYTE)userData.GetAt(i));
}
sResult+=Int2HexString(sLetter.GetLength()/2);
sResult+=sLetter;
sResult.MakeUpper();
sResult.TrimLeft();
*nDataLength=sResult.GetLength()/2-1;
return sResult;
}
/*****************************************************************************
* Class : CGModem
* Function : HandleResponse
* Description: Handle the answer string
* Parameters : sResponse: the answer followed by AT command
* Return :
******************************************************************************/
void CGModem::HandleResponse(CString sResponse)
{
//add to command set
COleDateTime now=COleDateTime::GetCurrentTime();
CString sNow=now.Format("[%m-%d %H:%M:%S");
sNow.Format("%s$:%d]",sNow,m_commandSet.GetSize()+1);
m_commandSet.Add(sNow+sResponse);
int iPos=-1;
//---------------------------------------------------------
//Get '>',then notify the waiting thread
iPos=sResponse.Find(">");
if(-1!=iPos)
{
SetEvent(m_responseEvent[RESPONSE_INPUT]);
return;
}
//---------------------------------------------------------
//when receive 'SMGS', notify the waiting thread
iPos=sResponse.Find("CMGS");
if(-1!=iPos)
{
SetEvent(m_responseEvent[RESPONSE_SEND_SM]);
return;
}
//read sm----------------------------------------------------
//find the "CMGR"'s position
iPos=sResponse.Find("+CMGR:");
if(-1!=iPos)
{
sResponse=sResponse.Right(sResponse.GetLength()-iPos-1);
//when use CNMI, a new sm came, then read sm. The result TE returned is different
//from only using 'ReadSm' fucntion. so, it'is required.
iPos=sResponse.Find("CMGR");
if(-1!=iPos)
{
sResponse=sResponse.Right(sResponse.GetLength()-iPos-1);
}
//Get the nProperty
int nProperty;
iPos=sResponse.Find(",");
nProperty=atoi((const char *)sResponse.Mid(iPos-1,1));
//Get the length of UDP data
int iPosBegin=iPos; //Get first ',''s Position
iPosBegin++; //Jump first ',';
iPosBegin++;
iPos=sResponse.Find("\r");
int length;
length=atoi(sResponse.Mid(iPosBegin,iPos-iPosBegin));
if(0==length)
{
//Fail, Sm is not exist.
::ZeroMemory(&m_readSm,sizeof(m_readSm));
SetEvent(m_responseEvent[RESPONSE_READ_SM]);
return;
}
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
//警号:
//字符长度如果长度大于126,程序出错,系统无法正常的工作。
//原因,未知。是系统最大的需要改进的地方.
//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
const int MAX_LENGTH=122;
if(length>MAX_LENGTH)
{
length=MAX_LENGTH;
}
//the data of udp
iPos+=2; //jump "\n";
//固定的短信中心地址长度18
sResponse=sResponse.Right(sResponse.GetLength()-iPos);
sResponse=sResponse.Left(18+length*2);
if(sResponse.GetLength()==0)
{
::ZeroMemory(&m_readSm,sizeof(m_readSm));
SetEvent(m_responseEvent[RESPONSE_READ_SM]);
return;
}
m_readSm=ResolvePduSm(sResponse,length,nProperty,m_iCurrentIndex);
SetEvent(m_responseEvent[RESPONSE_READ_SM]);
return;
}
//---------------------------------------------------------
//when reveive 'OK' , notify the waiting thread
iPos=sResponse.Find("OK");
if(-1!=iPos)
{
SetEvent(m_responseEvent[RESPONSE_OK]);
//When read SM, It will return OK. the Next can't Get Data
return;
}
//Error handle---------------------------------------------------------
//when reveive '+CMS ERROR:' , notify the waiting thread
iPos=sResponse.Find("+CMS ERROR:");
if(-1!=iPos)
{
//get more error information
iPos=sResponse.Find(":");
m_sErrorDesp=sResponse.Right(sResponse.GetLength()-iPos-1);
SetEvent(m_responseEvent[RESPONSE_ERROR]);
return;
}
iPos=sResponse.Find("+CME ERROR:");
if(-1!=iPos)
{
//Get more error informaiton
iPos=sResponse.Find(":");
m_sErrorDesp=sResponse.Right(sResponse.GetLength()-iPos-1);
SetEvent(m_responseEvent[RESPONSE_ERROR]);
return;
}
//---------------------------------------------------------
//when new SM recieved, read and delete the SM
iPos=sResponse.Find("+CMTI:");
if(-1!=iPos)
{
OnReceiveSm(sResponse);
return;
}
}
/*****************************************************************************
* Class : CGModem
* Function : OnReceiveSm
* Description: Automation Receive sm by CMTI echo
* Parameters : CMTI string
* Return :
******************************************************************************/
void CGModem::OnReceiveSm(CString sNewSm)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -