📄 gprser.cpp
字号:
/*! \file GGPRSer.cpp
\brief GPRS类实现文件
\author 陈华毅
\version 1.0
通过实现CGPRSer类,应用程序可以通过CGPRSer类的实体来实现对GPRS模块操作。
\defgroup GPRSER_IMPLEMENT CGPRSDer类实现说明
*/
#include "stdafx.h"
#include "GPRS.h"
#include "GPRSer.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//@{Group: GPRSER_IMPLEMENT
/*! CGPRS构造函数,构造时打开串口
\param 无
\return 无
*/
CGPRSer::CGPRSer()
{
m_serial.OpenComm();
}
/*! CGPRS析构函数,析构时关闭串口
\param 无
\return 无
*/
CGPRSer::~CGPRSer()
{
m_serial.CloseComm();
}
/*! 初始化GSM状态
\param 无
\return 成功返回TRUE,失败返回FALSE。
*/
BOOL CGPRSer::GPRSInit()
{
/* 测试连接:“AT”测试终端是否连接正确。成功后返回“OK”。*/
char ans[128];
m_serial.WriteComm((UCHAR*)"AT\r", 3);
Sleep(30);
m_serial.ReadComm((UCHAR*)ans, 128);
if (strstr(ans, "ERROR") != NULL)
return FALSE;
/*设置回显:(此步骤为了测试方便)ATE1 */
m_serial.WriteComm((UCHAR*)"ATE0\r", 5);
Sleep(30);
m_serial.ReadComm((UCHAR*)ans, 128);
/* PDU模式 */
m_serial.WriteComm((UCHAR*)"AT+CMGF=0\r", 10);
Sleep(30);
m_serial.ReadComm((UCHAR*)ans, 128);
/* 选择话筒 */
m_serial.WriteComm((UCHAR*)"AT+SPEAKER=1\r", 15);
Sleep(30);
/*设置GPRS新消息提示方式 */
// m_serial.WriteComm((UCHAR*)"AT+CMGS=2,1,0,0,1\r", 20);
// m_serial.ReadComm((UCHAR*)ans, 128);
return TRUE;
}
/*! 发送短消息,仅发送命令,不读取应答
\param [in] strNum - 发送消息手机号
\param [in] strCon - 短消息内容
\return 成功返回TRUE,失败返回FALSE。
*/
BOOL CGPRSer::gprsSendMessage(CString strNum, CString strCon)
{
CHAR ans[128] = {0}; /* 应答串 */
CString strSmsc = "";
CString strNumber = "";
CString strContent = "";
m_serial.WriteComm((UCHAR*)"AT+CSCA?\r", 10);
Sleep(60);
m_serial.ReadComm((UCHAR*)ans, 128);
if (strstr(ans, "+CSCA:"))
{
CString strTempCsca = CString(ans);
strSmsc = strTempCsca.Mid(10, 14);
if ((strSmsc.GetLength() != 14) || (strSmsc.GetAt(0) != '+'))
{
AfxMessageBox(_T("提取短消息中心号码失败!请重新设置短消息中心号码!"));
}
}else{
AfxMessageBox(_T("提取短消息中心号码失败!请重新设置短消息中心号码!"));
}
strNumber = strNum;
strContent = strCon;
SM_PARAM SmParam;
memset(&SmParam, 0, sizeof(SM_PARAM));
/* 去掉号码前的"+" */
if(strSmsc[0] == '+') strSmsc = strSmsc.Mid(1);
if(strNumber[0] == '+') strNumber = strNumber.Mid(1);
/* 在号码前加"86" */
if(strSmsc.Left(2) != "86") strSmsc = "86" + strSmsc;
if(strNumber.Left(2) != "86") strNumber = "86" + strNumber;
/* 填充短消息结构 */
strcpy(SmParam.SCA, CStringToCharArray(strSmsc));
strcpy(SmParam.TPA, CStringToCharArray(strNumber));
wcscpy(SmParam.TP_UD, strContent);
SmParam.TP_PID = 0;
SmParam.TP_DCS = GSM_UCS2;
int nPduLength; /* PDU串长度 */
UCHAR nSmscLength; /* SMSC串长度 */
int nLength; /* 串口收到的数据长度 */
char cmd[16]; /* 命令串 */
char pdu[512]; /* PDU串 */
nPduLength = gprsEncodePdu(&SmParam, pdu); /* 根据PDU参数,编码PDU串 */
strcat(pdu, "\x01a"); /* 以Ctrl-Z结束 strcat---字符串拼接函数 */
gprsString2Bytes(pdu, &nSmscLength, 2); /* 取PDU串中的SMSC信息长度 */
nSmscLength++; /* 加上长度字节本身 */
/* 命令中的长度,不包括SMSC信息长度,以数据字节计 */
sprintf(cmd, "AT+CMGS=0%d\r", nPduLength / 2 - nSmscLength); /* 生成命令 */
/*送格式化输出到字符串cmd中 */
// TRACE("%s", cmd);
// TRACE("%s\n", pdu);
m_serial.WriteComm((UCHAR*)cmd, strlen(cmd)); /* 先输出命令串 */
Sleep(60);
nLength = m_serial.ReadComm((UCHAR*)ans, 128); /* 读应答数据 */
/* 根据能否找到"+CMS ERROR"决定成功与否 */
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
m_serial.WriteComm((UCHAR*)pdu, strlen(pdu));
Sleep(30);
nLength = m_serial.ReadComm((UCHAR*)ans, 128);
if((nLength > 0) && strstr(ans, "> "))
{
AfxMessageBox(TEXT("Send succeessfully!"));
}
return TRUE;
}
else
{
AfxMessageBox(TEXT("Send fail!"));
return FALSE;
}
}
/*! PDU编码,用于编制、发送短消息
\param [in] pSrc - 源PDU参数指针
\param [in] pDst - 目标PDU串指针
\return 目标PDU串长度
*/
DWORD CGPRSer::gprsEncodePdu(const SM_PARAM *pSrc, CHAR *pDst)
{
DWORD nLength; /* 内部用的串长度 */
DWORD nDstLength; /* 目标PDU串长度 */
UCHAR buf[256]; /* 内部用的缓冲区 */
/* SMSC地址信息段 */
nLength = strlen(pSrc->SCA); /* SMSC地址字符串的长度 */
buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1; /* SMSC地址信息长度 */
buf[1] = 0x91; /* 固定: 用国际格式号码 */
nDstLength = gprsBytes2String(buf, pDst, 2); /* 转换2个字节到目标PDU串 */
nDstLength += gprsInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); /* 转换SMSC号码到目标PDU串 */
/* TPDU段基本参数、目标地址等 */
nLength = strlen(pSrc->TPA); /* TP-DA地址字符串的长度 */
buf[0] = 0x11; /* 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10) */
buf[1] = 0; /* TP-MR=0 */
buf[2] = (char)nLength; /* 目标地址数字个数(TP-DA地址字符串真实长度) */
buf[3] = 0x91; /* 固定: 用国际格式号码 */
nDstLength += gprsBytes2String(buf, &pDst[nDstLength], 4); /* 转换4个字节到目标PDU串 */
nDstLength += gprsInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); /* 转换TP-DA到目标PDU串 */
/* TPDU段协议标识、编码方式、用户信息等 */
nLength = wcslen(pSrc->TP_UD); /* 用户信息字符串的长度 */
buf[0] = pSrc->TP_PID; /* 协议标识(TP-PID) */
buf[1] = pSrc->TP_DCS; /* 用户信息编码方式(TP-DCS) */
buf[2] = 0; /* 有效期(TP-VP)为5分钟 */
if(pSrc->TP_DCS == GSM_7BIT)
{
/* 7-bit编码方式 */
buf[3] = nLength; /* 编码前长度 */
// nLength = gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4; /* 转换TP-DA到目标PDU串 */
}
else if(pSrc->TP_DCS == GSM_UCS2)
{
/* UCS2编码方式 */
buf[3] = gprsEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); /* 转换TP-DA到目标PDU串 */
nLength = buf[3] + 4; /* nLength等于该段数据长度 */
}
else
{
/* 8-bit编码方式 */
// buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength); /* 转换TP-DA到目标PDU串 */
nLength = buf[3] + 4; /* nLength等于该段数据长度 */
}
nDstLength += gprsBytes2String(buf, &pDst[nDstLength], nLength); /* 转换该段数据到目标PDU串 */
/* 返回目标字符串长度 */
return nDstLength;
}
/*! UCS2编码
\param [in] pSrc - 源字符串指针
\param [in] nSrcLength - 源字符串长度
\param [out] pDst - 目标编码串指针
\return 目标编码串长度
*/
DWORD CGPRSer::gprsEncodeUcs2(const TCHAR *pSrc, UCHAR *pDst, DWORD nSrcLength)
{
/* 高低字节对调,输出 */
for(int i=0; i < (INT)nSrcLength; i++)
{
*pDst++ = *pSrc >> 8; /* 先输出高位字节 */
*pDst++ = *pSrc++ & 0xff; /* 后输出低位字节 */
}
/* 返回目标编码串长度 */
return nSrcLength * 2;
}
/*! 打电话函数
\param [in] str - 呼号的电话号码
\return 拨号成功返回TRUE,失败返回FALSE
*/
BOOL CGPRSer::gprsCall(CString str)
{
UCHAR sendbuf[256];
CString strSend;
strSend = "atd";
strSend = strSend + str;
strSend = strSend + ";\r\n";
for (INT i=0; i < strSend.GetLength();i++)
{
sendbuf[i] = strSend.GetAt(i);
}
m_serial.WriteComm(sendbuf, strSend.GetLength());
return TRUE;
}
/*! 字符串数据转换成字符组数据函数
\param [in] str - 待转换的字符串数据
\return 由字符串转换成字符组数据
*/
CHAR* CGPRSer::CStringToCharArray(CString str)
{
for (INT i = 0; i < str.GetLength(); i++)
{
ch[i] = str.GetAt(i);
}
ch[i] = '\0';
return ch;
}
/*! 挂机函数
\param 无
\return 拦挂机成功返回TRUE,失败返回FALSE
*/
BOOL CGPRSer::gprsHang()
{
m_serial.WriteComm((UCHAR*)"ath\r", 4);
return TRUE;
}
/*! UCS2解码
\param [in] pSrc - 源编码串指针
\param [in] nSrcLength - 源编码串长度
\param [out] pDst - 目标字符串指针
\return 目标字符串长度
*/
DWORD CGPRSer::gprsDecodeUcs2(const UCHAR *pSrc, TCHAR *pDst, DWORD nSrcLength)
{
/* 高低字节对调,拼成UNICODE */
for(INT i=0; i < (INT)nSrcLength/2; i++)
{
*pDst = *pSrc++ << 8; /* 先高位字节 */
*pDst++ |= *pSrc++; /* 后低位字节 */
}
/* 输出字符串加个结束符 */
*pDst = '\0';
/* 返回目标字符串长度 */
return (nSrcLength/2);
}
/*! 7bit解码
\param [in] pSrc - 源编码串指针
\param [in] nSrcLength - 源编码串长度
\param [out] pDst - 目标字符串指针
\return 目标字符串长度
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -