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

📄 gmodem.cpp

📁 GmsModemDll Gms ModemDll 关于GPRS MODEM的AT命令集合
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// 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 + -