// GPRS.cpp: implementation of the CGPRS class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GPRS.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CGPRS::CGPRS()
{
ResetGlobalVarial();
}
CGPRS::~CGPRS()
{
if (pCeSerial->IsPortOpen() == TRUE)
{
pCeSerial->ClosePort();
}
if (pCeSerial)
delete pCeSerial;
}
/*******************************************************************************************
函数名称: ResetGlobalVarial
描 述: 复位一些全局变量为默认值
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
void CGPRS::ResetGlobalVarial(void)
{
bSendATCmd = FALSE; /* 当前不处于发送命令状态 */
m_RespCnt = 0;
m_strRespBuf = _T("");
ResetEvent(m_ATCmdRespEvent); /* 复位 GPRS 响应事件*/
}
/*******************************************************************************************
函数名称: GPRS_Init
描 述: GPRS 模块初始化函数
输入参数: LPCTSTR Port : 串口号, 如 "COM1:"
int BaudRate : 串口波特率, 如 115200
DWORD UserParam: 用户传递到该类中的参数
输出参数: 无
返 回: TRUE: 成功 FALSE: 失败
********************************************************************************************/
BOOL CGPRS:: GPRS_Init(LPCTSTR Port, int BaudRate, DWORD UserParam)
{
BOOL ret;
DWORD Trycount = 2;
do{ /* 尝试初始化 GPRS, 最多尝试两次 */
Trycount--;
pCeSerial = new CCeSerial;
ret = pCeSerial->OpenPort(Port, BaudRate, 8, ONESTOPBIT, NOPARITY, TRUE, TRUE, (DWORD)this);
if (ret == FALSE) /* 打开串口, 数据位为8,停止位为1,无校验位 */
{
delete pCeSerial;
return FALSE;
}
pCeSerial->OnCommRecv = OnCommRecv; /* 串口接收成功回调函数 */
m_UserParam = UserParam; /* 保存用户传进来的参数 */
m_ATCmdRespEvent = CreateEvent(NULL, TRUE, FALSE, NULL); /* 创建 GPRS 响应事件 */
GPRS_SendATCmd(_T("AT")); /* 尝试模块是否处于激活状态 */
GPRS_WaitResponseOK();
GPRS_SendATCmd(_T("AT")); /* 尝试模块是否处于激活状态 */
GPRS_WaitResponseOK();
GPRS_SendATCmd(_T("AT$NOSLEEP=1")); /* 禁止模块进入睡眠模式 */
ret = GPRS_WaitResponseOK();
if (ret == FALSE)
{
delete pCeSerial;
if (Trycount == 0) return FALSE;
}
else
Trycount = 0;
}while(Trycount > 0);
GPRS_SendATCmd(_T("AT+CREG=1"));
ret = GPRS_WaitResponseOK();
if (ret == FALSE)
return FALSE;
GPRS_SendATCmd(_T("AT+CLIP=1")); /* 设置来电显示 */
ret = GPRS_WaitResponseOK();
if (ret == FALSE)
return FALSE;
GPRS_SendATCmd(_T("AT+CMGF=1")); /* 设置为文本模式 */
ret = GPRS_WaitResponseOK();
if (ret == FALSE)
return FALSE;
GPRS_SendATCmd(_T("AT+CSCS=\"GSM\"")); /* 设置字符集 */
ret = GPRS_WaitResponseOK();
if (ret == FALSE)
return FALSE;
//GPRS_SendATCmd(_T("AT+CSMP=17,168,0,0")); /* 设置文本模式参数 */
//ret = GPRS_WaitResponseOK();
//if (ret == FALSE)
// return FALSE;
return TRUE;
}
/*******************************************************************************************
函数名称: OnCommRecv
描 述: 串口接收成功回调函数, 当串口正确接收到数据时, 该函数将被调用
输入参数: CString strCmd: 命令字
输出参数: DWORD UserParam : 用户传递的参数, 通常为CGPRS类的一个对象的指针
BYTE *buf : 串口接收数据缓冲
DWORD buflen : 串口接收到的数据长度
返 回: 无
********************************************************************************************/
void CALLBACK CGPRS::OnCommRecv(DWORD UserParam, BYTE *buf, DWORD buflen)
{
CGPRS *pGPRS = (CGPRS *)UserParam;
CString strTmp = _T("");
LPTSTR pStr = strTmp.GetBuffer(buflen);
MultiByteToWideChar(CP_ACP, 0, (char *)buf, buflen, pStr, buflen); /* 将接收到的数据转换为 Unicode 编码 */
strTmp.ReleaseBuffer();
if (pGPRS->bSendATCmd == TRUE)
{ /* 之前用户发送了 AT 指令 */
pGPRS->m_strRespBuf.Insert(pGPRS->m_RespCnt, strTmp); /* 保存数据 */
SetEvent(pGPRS->m_ATCmdRespEvent);
return;
}
if ((strTmp.Find(_T("RING")) >= 0) ||
(strTmp.Find(_T("ring")) >= 0))
{ /* 有电话打进来 */
CString strCallNum = pGPRS->GPRS_GetTheCallNum(strTmp);
pGPRS->OnGPRSRecv(pGPRS->m_UserParam, GPRS_STATUS_RECEIVE_CALL,strCallNum);
}
if ((strTmp.Find(_T("NO CARRIER")) >= 0) ||
(strTmp.Find(_T("no carrier")) >= 0))
{ /* 来电后, 对方挂机 */
pGPRS->OnGPRSRecv(pGPRS->m_UserParam, GPRS_STATUS_OTHER_SIDE_HANDUP, "");
}
pGPRS->bSendATCmd = FALSE; /* 复位相关全局变量 */
pGPRS->m_RespCnt = 0;
pGPRS->m_strRespBuf = _T("");
ResetEvent(pGPRS->m_ATCmdRespEvent);
}
/*******************************************************************************************
函数名称: GPRS_GetTheCallNum
描 述: 取得来电的电话号码
输入参数: CString str: 来电时, GPRS 响应字符
输出参数: 无
返 回: 来电电话号码
********************************************************************************************/
CString CGPRS::GPRS_GetTheCallNum(CString str)
{
int pos1 = str.Find(_T("+CLIP: \""), 0);
if (pos1 < 0)
return "";
else
pos1 = pos1 + wcslen(_T("+CLIP: \""));
int pos2 = str.Find(_T("\""), pos1);
if (pos2 < 0)
return "";
CString strNum;
strNum = str.Mid(pos1, pos2 - pos1); /* 取得电话号码 */
return strNum;
}
/*******************************************************************************************
函数名称: GPRS_SendATCmd
描 述: 发送 AT 命令
输入参数: CString strCmd: 命令字
输出参数: 无
返 回: TRUE: 成功 FALSE: 失败
********************************************************************************************/
BOOL CGPRS::GPRS_SendATCmd(CString strCmd)
{
int len = strCmd.GetLength();
BYTE *psendbuf = new BYTE[len + 2];
m_RespCnt = 0;
bSendATCmd = TRUE; /* 进入发送命令状态 */
for(int i = 0; i < len;i++)
psendbuf[i] = (char)strCmd.GetAt(i); /* 转换为单字节字符 */
psendbuf[len] = '\r'; /* 加入结束符 */
psendbuf[len + 1] = '\n';
pCeSerial->Senddata(psendbuf, len + 2); /* 从串口发送数据 */
delete[] psendbuf;
return TRUE;
}
/*******************************************************************************************
函数名称: GPRS_WaitResponseOK
描 述: 等待 AT 命令响应 OK
输入参数: 无
输出参数: 无
返 回: 无
********************************************************************************************/
BOOL CGPRS::GPRS_WaitResponseOK(void)
{
DWORD ret;
BOOL bOK = TRUE;
while(1)
{ // 等待 0.5 秒, 如果得不到回复, 即为错误
ret = WaitForSingleObject(m_ATCmdRespEvent, 500);
if (ret == WAIT_OBJECT_0)
{
if ((m_strRespBuf.Find(_T("ERROR\r\n"), 0) >= 0) ||
(m_strRespBuf.Find(_T("error\r\n"), 0) >= 0))
{ /* 响应中有"ERROR" */
bOK = FALSE;
break;
}
if ((m_strRespBuf.Find(_T("OK\r\n"), 0) >= 0) ||
(m_strRespBuf.Find(_T("ok\r\n"), 0) >= 0))
{ /* 响应中有"OK" */
bOK = TRUE;
break;
}
ResetEvent(m_ATCmdRespEvent);
}
else
{
bOK = FALSE; /* 响应超时 */
break;
}
}
ResetGlobalVarial(); /* 复位用到的全局变量 */
if (FALSE == bOK)
return FALSE;
return TRUE;
}
/*******************************************************************************************
函数名称: GPRS_WriteMsg
描 述: 将短信内容写入 GPRS 模块
输入参数: CString Msg: 短信内容
输出参数: 无
返 回: 无
********************************************************************************************/
BOOL CGPRS::GPRS_WriteMsg(CString Msg)
{
int len = Msg.GetLength();
BYTE *psendbuf = new BYTE[