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

📄 gsmmodem.cpp

📁 使用gsm收发短信的方式传递文件
💻 CPP
📖 第 1 页 / 共 5 页
字号:
  // 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 + -