📄 gsmmodem.cpp
字号:
// GsmModem.cpp: implementation of the CGsmModem class.
//
//////////////////////////////////////////////////////////////////////
#include "..\stdafx.h"
#include "GsmModem.h"
//#include "configFile.h"
#include "Sms.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
#define M_GSMTYPE 2 //1为TC35 2为MC45
#ifdef _DEBUG
#undef M_GSMTYPE
#define M_GSMTYPE 1
#endif
#if(M_GSMTYPE==2)
extern "C" void gprs_on();
extern "C" void mic_on(BOOL nIsOn);
#endif
extern char g_strPhoneNum[32];
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
//构造函数
//////////////////////////////////////////////////////////////////////
CGsmModem::CGsmModem()
{
//设串口为无效值
m_hComm=INVALID_HANDLE_VALUE;
//为解析到的短消息分配空间及初始化
m_pShortMsgInfo=new SHORTMSGINFO;
m_pShortMsgInfo->nMsgType=0;
m_pShortMsgInfo->nMsgLen=0;
m_pShortMsgInfo->pSrcPhoneNum[0]=0;
m_pShortMsgInfo->pTime[0]=0;
m_pShortMsgInfo->MsgData[0]=0;
m_pShortMsgInfo->nRecInfo=0;
//GSM关闭
m_bIsGsmOn=0;
m_bIsSendOver=1;
m_nTransNum=1;
m_nMsgCount = 0;
//初始化变量
for (int i = 0; i < M_MAXMSGNUMBER;i++)
{
m_SaveMsg[i].nCount = -1;
m_SaveMsg[i].nFlag = -1;
for(int j = 0;j < 10; j++)
{
m_SaveMsg[i].bAccess[j] = FALSE;
m_SaveMsg[i].nLength[j] = 0;
m_SaveMsg[i].msg[j]=NULL;
}
}
}
///////////////////////////////////////////////////////////////
//析构函数
///////////////////////////////////////////////////////////////
CGsmModem::~CGsmModem()
{
delete m_pShortMsgInfo;
ClosePort();
}
//////////////////////////////////////////////////////////////////////////////////
//功能:初始化串口
//history name data remark
// wanfangjie 2003.03.05 create
// wanfangjie 2003.04.04 添加错误处理
//参数说明:int iPort 串口的端口号(1~2)
//返回值:1 创建成功 0 创建失败
//////////////////////////////////////////////////////////////////////////////////
int CGsmModem::InitPort(int iPort)
{
COMMTIMEOUTS sCommTimeouts;
DCB sDcb;
char aTempPool[64];
//如果串口开打,关闭该串口
if(m_hComm!=INVALID_HANDLE_VALUE)
{
CloseHandle(m_hComm);
m_hComm=INVALID_HANDLE_VALUE;
}
//创建串口,获取串口句柄
m_hComm = CreateFile(_T("COM1:"),
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
0, // sync I/O
NULL); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
strcpy(aTempPool,"为GSM创建串口错");
return 0;
}
//设串口读写缓冲区
SetupComm(m_hComm,1024,1024);
// 设置时间超时值
// readfile function using "MAXDWORD" can return fleetly.
sCommTimeouts.ReadIntervalTimeout = MAXDWORD;
sCommTimeouts.ReadTotalTimeoutMultiplier = 10;
sCommTimeouts.ReadTotalTimeoutConstant = 1000;
sCommTimeouts.WriteTotalTimeoutMultiplier = 10;
sCommTimeouts.WriteTotalTimeoutConstant = 1000;
//设置时间超时
if(SetCommTimeouts(m_hComm, &sCommTimeouts)==NULL)
{
strcpy(aTempPool,"为GSM设置时间超时错");
return 0;
}
//串口配置
GetCommState(m_hComm, &sDcb);
//set dcb structure
sDcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
sDcb.DCBlength = sizeof( DCB ) ;
sDcb.BaudRate = 9600;
sDcb.ByteSize = 8;
sDcb.fParity = 0;
//在同步方式下,停止位必须为0
sDcb.StopBits = 0;
if(!SetCommState(m_hComm, &sDcb))
{
strcpy(aTempPool,"为GSM设置串口配置错");
return 0;
}
// 清除串口
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
return 1;
}
///////////////////////////////////////////////////////////////////////
//功能:清串口缓冲区
//history name data remark
// wanfangjie 2002.09.23 create
//参数说明 int itype 0 清读缓冲区
// 1 清写缓冲区
// 2 清读写缓冲区
///////////////////////////////////////////////////////////////////////
void CGsmModem::ClearCommBuf(int iType)
{
switch(iType)
{
case 0:
PurgeComm(m_hComm,PURGE_RXCLEAR);
break;
case 1:
PurgeComm(m_hComm,PURGE_TXCLEAR);
break;
case 2:
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
break;
default:
PurgeComm(m_hComm,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
}
}
///////////////////////////////////////////////////////////////////////
//功能:写串口
//history name data remark
// wanfangjie 2002.09.18 create
//返回值:1 成功 0 失败
///////////////////////////////////////////////////////////////////////
int CGsmModem::WriteDataToPort(const char *pWritePool, long nWriteLen)
{
BOOL nReturn=0;
DWORD nRealLen=0;
if (m_hComm == INVALID_HANDLE_VALUE)
{
return 0;
}
////清除写缓冲区
ClearCommBuf(1);
nReturn=WriteFile(m_hComm,pWritePool,nWriteLen,&nRealLen,NULL);
return nReturn;
}
///////////////////////////////////////////////////////////////////////
//功能:读串口
//history name data remark
// wanfangjie 2002.09.18 create
//参数说明:char *pReadPool 返回串口中的内容
// long nReadLen 要读的长度
// BOOL bIsClearBuf 是否清除读的缓存
//返回值:非0实际读的长度 0 失败
///////////////////////////////////////////////////////////////////////
int CGsmModem::ReadDataFromPort(char *pReadPool, long nReadLen,BOOL bIsClearBuf)
{
BOOL nReturn=0;
DWORD nRealLen=0;
if (m_hComm == INVALID_HANDLE_VALUE)
{
return 0;
}
nReturn=ReadFile(m_hComm,pReadPool,nReadLen,&nRealLen,NULL);
//读成功
if(nRealLen)
{
pReadPool[nRealLen]=0;
}
if(bIsClearBuf)
{
ClearCommBuf(0);//清除读缓冲区
}
return nRealLen;
}
///////////////////////////////////////////////////////////////////////
//功能:等待串口的事件
//history name data remark
// wanfangjie 2002.09.20 create
// wanfangjie 2002.10.10 把返回值由布尔类型改为整型
//参数说明 iEventType 0表示不需要等待事件,立即判断事件是否出现
// 1表示等待事件,直到事件的出现
//返回值:非0 表示事件出现 0 事件没出现
///////////////////////////////////////////////////////////////////////
int CGsmModem::GetCommEvent(int iEventType)
{
int bResult=0;
COMSTAT comStat;
DWORD dEvtMask;
DWORD dwError=0;
if (m_hComm == INVALID_HANDLE_VALUE)
{
return 0;
}
switch(iEventType)
{
case 0:
ClearCommError(m_hComm, &dwError, &comStat);
if(comStat.cbInQue!=0)
{
bResult=comStat.cbInQue;
}
break;
case 1:
//设置的事件为接受缓冲区出现字符
SetCommMask(m_hComm,EV_RXCHAR);
bResult =WaitCommEvent (m_hComm, &dEvtMask, 0);
break;
default:
break;
}
return bResult;
}
//////////////////////////////////////////////////////////////////////////////////////
//功能:初始化GSM
//history name data remark
// wanfangjie 2002.09.20 create
// wanfangjie 2003.04.04 添加错误处理及信号的强弱
//返回值:0,初始化失败,1初始化成功
///////////////////////////////////////////////////////////////////////
int CGsmModem::InitGsm()
{
int nBufLen;
m_bIsGsmOn=0;
//打开GSM
#if(M_GSMTYPE==2)
// gprs_on();
#endif
//判断串口是否打开
if(m_hComm==INVALID_HANDLE_VALUE)
{
//调用打开串口函数
int n = InitPort(1);
if(n==0)
{
int iii = 0;//AfxMessageBox(_T("初始化串口错"));
}
}
//测试模块是否正确与连接
ClearCommBuf(0);
SendATCmd("AT\r");
nBufLen=GetCommEvent(0);
if(nBufLen>0)
{
ReadDataFromPort(m_pReadPool,nBufLen,1);
if((m_pReadPool[0]==M_ERROR)&&strstr(m_pReadPool,"OK")==NULL)
{
// AfxMessageBox(_T("通讯模块坏"));
return 0;
}
}
else
{
// AfxMessageBox(_T("通讯模块未开机"));
return 0;
}
//挂机
SendATCmd("ATH\r");
//取消命令回显
SendATCmd("ATE0\r");
//设置结果码的显示方式为字符形式
SendATCmd("ATV1\r");
SendATCmd("AT^SNFS=1\r");
ClearCommBuf(0);
//设置短信格式(pdu),文本方式
SendATCmd("AT+CMGF=0\r");
nBufLen=GetCommEvent(0);
if(nBufLen>0)
{
ReadDataFromPort(m_pReadPool,nBufLen,1);
}
//新短信提示
SendATCmd("AT+CNMI=1,1,0,0,1\r");
ClearCommBuf(0);
int x = M_GSMTYPE;
#if(M_GSMTYPE==2)
SendATCmd("AT^SNFS=2\r");
SendATCmd("AT^SAIC=2,2,3\r");
DelayTimer(300);
#endif
#ifndef _SIEMENS
SendATCmd("AT*E2EAMS=9,2\r");
SendATCmd("AT*E2EAMS=10,2\r");
SendATCmd("AT*E2EAMS=255\r");
SendATCmd("AT*ECAM=1\r");
SendATCmd("AT+cpms=\"me\",\"me\",\"me\"\r");
SendATCmd("AT+cnmi=3,1\r");
SendATCmd("AT&W\r");
#endif
//删除所有短消息
DeleteAllMsg();
//GSM已打开
m_bIsGsmOn=1;
return 1;
}
////////////////////////////////////////////////////////////////////////////
//功能:把数据组织成短消息的格式
//history name data remark
// wanfangjie 2003.03.20 创建
// wanfangjie 2003.04.03 从VC下移植到VCE
// wanfangjie 2003.04.14 添加边界条件处理
// wanfangjie 2003.05.08 添加处理发送中英短消息的情况
// wanfangjie 2003.09.04 更改函数名,把SendMsg改为OrganizeMsg
// wanfangjie 2003.09.17 添加参数 int nIsUnicode
//参数说明 char *pData 发送的数据
// char *pPhoneNum 电话号码
// int nDataLen 数据的长度 小于140
// int nMsgType 消息类型 0x00 文本短消息
// 0x08 UCS2格式
// 0x15 数据格式
// int nIsUnicode 是否为UNICODE代码
//返回值: 1发送成功
// 0发送失败
/////////////////////////////////////////////////////////////////////////////
int CGsmModem::OrganizeMsg(char *pData, const char *pPhoneNum,int nDataLen, int nMsgType,int nIsUnicode)
{
char pAtCmd[64];
int nShortMsgLen=0;
int nPduLen=0;
int iPoolLen=0;
char aTempPool[64];
char aPhoneNum[32];
unsigned char ucDataLen=0;
char *pTempPool;
unsigned short *pUnicode;
char cPhoneLen=0;
strcpy(aPhoneNum,pPhoneNum);
if(nDataLen>140)
{
nDataLen=140;
}
ucDataLen=(unsigned char)nDataLen;
//判断GSM是否打开
//IsGsmOn();
if(m_bIsGsmOn==0)
{
if(InitGsm()==0)
{
return 0;
}
}
//判断信号的质量
if(GsmSignalQuality()<3)
{
strcpy(aTempPool,"信号质量差");
// AfxMessageBox(_T("信号不好,发送失败"));
return 0;
}
//开空间
pTempPool=new char[1024];
if(pTempPool==NULL)
{ strcpy(aTempPool,"内存错在SendMsg内");
return 0;
}
pUnicode=new unsigned short[1024];
if(pUnicode==NULL)
{
delete []pTempPool;
strcpy(aTempPool,"内存错在SendMsg内");
return 0;
}
//服务中心号码从SIM卡中读出
strcpy(m_pWritePool,"00");
//FO PDU第一字节,典型值为04H为接受,11H为发送
strcat(m_pWritePool,"11");
//MR(消息参考号码),一般设为00
strcat(m_pWritePool,"00");
//目标地址
//国内号码,取电话号码的长度
cPhoneLen=(char)strlen(aPhoneNum);
//变为双字节
m_cGSMProtocol.ByteToTwoCharacter(&cPhoneLen, pTempPool,1);
strcat(m_pWritePool,pTempPool);
//81国内码,91为国际码,若设为国际码,号码位数为0D多86
strcat(m_pWritePool,"81");
//把电话号码转化为PDU格式
m_cGSMProtocol.PhoneNumToPduNum(aPhoneNum,pTempPool,strlen(aPhoneNum));
strcat(m_pWritePool,pTempPool);
//PID协议标志
strcat(m_pWritePool,"00");
switch(nMsgType)
{
case 0x08://中文短消息
strcat(m_pWritePool,"08");
//在VC下把ANSI转化为UNICODE
if(nIsUnicode)
{
memcpy((char*)pUnicode,pData,nDataLen);
}
else
{
// MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,pData,-1, pUnicode,140);
// nDataLen=wcslen(pUnicode)*2;
int nLen = MultiByteToWideChar(936,MB_PRECOMPOSED,pData,nDataLen, pUnicode,140);
nDataLen = nLen*2;
if(nDataLen>140)
{
nDataLen=140;
}
ucDataLen=(unsigned char)nDataLen;
}
m_cGSMProtocol.InterchangeByteInWord((char*)pUnicode, pData,nDataLen);
break;
case 0x15://数据
strcat(m_pWritePool,"15");
break;
default://数据处理
strcat(m_pWritePool,"15");
break;
}
//有效时间
strcat(m_pWritePool,"a7");
//消息长度为转化为字符
m_cGSMProtocol.ByteToTwoCharacter((char*)&ucDataLen,pTempPool,sizeof(unsigned char));
strcat(m_pWritePool,pTempPool);
//数据转化为字符
m_cGSMProtocol.ByteToTwoCharacter(pData, pTempPool,ucDataLen);
strcat(m_pWritePool,pTempPool);
//计算数据包的长度
nShortMsgLen=strlen(m_pWritePool);
nPduLen=nShortMsgLen/2-1;
//短消息结束标志Ctrl+Z
m_pWritePool[nShortMsgLen++]=0x1a;
//把nPduLen转化为字符串
m_cGSMProtocol.ThirdDigitNumToCharacter(nPduLen,pTempPool);
//发送短消息的命令
strcpy(pAtCmd,"AT+CMGS=");
strcat(pAtCmd,pTempPool);
strcat(pAtCmd,"\r");
SendATCmd(pAtCmd);
iPoolLen=GetCommEvent(0);
if(iPoolLen>0)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -