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

📄 smsserialport.cpp

📁 使用短信猫可以实现短信的群发
💻 CPP
📖 第 1 页 / 共 2 页
字号:



/*******************************************************************************/
// 发送短消息,仅发送命令,不读取应答
// 输入: pSrc - 源PDU参数指针
int CSmsSerialPort::gsmSendMessage(SM_PARAM& Src)
{
	int nPduLength;		// PDU串长度
	unsigned char nSmscLength;	// SMSC串长度
	int nLength;		// 串口收到的数据长度
	char cmd[16];		// 命令串
	char pdu[512];		// PDU串
	char ans[128];		// 应答串

	nPduLength = gsmEncodePdu(&Src, pdu);	// 根据PDU参数,编码PDU串
	strcat(pdu, "\x01a");		// 以Ctrl-Z结束

	gsmString2Bytes(pdu, &nSmscLength, 2);	// 取PDU串中的SMSC信息长度
	nSmscLength++;		// 加上长度字节本身

	// 命令中的长度,不包括SMSC信息长度,以数据字节计
	sprintf(cmd, "AT+CMGS=%d\r", nPduLength / 2 - nSmscLength);	// 生成命令

	WriteCom(cmd, strlen(cmd));	// 先输出命令串

	nLength = ReadCom(ans, 128);	// 读应答数据

	// 根据能否找到"\r\n> "决定成功与否
	if(nLength == 4 && strncmp(ans, "\r\n> ", 4) == 0)
	{
		return WriteCom(pdu,strlen(pdu));		// 得到肯定回答,继续输出PDU串
	}
	return 0;
}
/*****************************************************************************/
// 读取GSM MODEM的应答,可能是一部分
// 输出: pBuff - 接收应答缓冲区
// 返回: GSM MODEM的应答状态, GSM_WAIT/GSM_OK/GSM_ERR
// 备注: 可能需要多次调用才能完成读取一次应答,首次调用时应将pBuff初始化
int CSmsSerialPort::gsmGetResponse(SM_BUFF& Buff)
{
	int nLength;		// 串口收到的数据长度
	int nState;
	// 从串口读数据,追加到缓冲区尾部
	nLength = ReadCom(&(Buff.data[Buff.len]), 128);	
	Buff.len += nLength;
	
	// 确定GSM MODEM的应答状态
	nState = GSM_WAIT;
	if ((nLength > 0) && (Buff.len >= 4))
	{
		if (strncmp(&(Buff.data[Buff.len - 4]), "OK\r\n", 4) == 0)  nState = GSM_OK;
		else if (strstr(Buff.data, "ERROR") != NULL) nState = GSM_ERR;
	}
	return nState;
}
/****************************************************************************/
// 读取短消息,仅发送命令,不读取应答
// 用+CMGL代替+CMGR,可一次性读出全部短消息
int CSmsSerialPort::gsmReadMessageList()
{
	//return WriteComm("AT+CMGL\r", 8);//读出所有消息
	return WriteCom("AT+CMGL=4\r",10);
}

/****************************************************************************/
// 删除短消息,仅发送命令,不读取应答
// 输入: index - 短消息序号,1-255
int CSmsSerialPort::gsmDeleteMessage(int index)
{
	char cmd[16];		// 命令串
	sprintf(cmd, "AT+CMGD=%d\r", index);	// 生成命令
	// 输出命令串
	return WriteCom(cmd, strlen(cmd));
}
/****************************************************************************/




BOOL CSmsSerialPort::IsExistModen()//测试短信猫是否连接
{
	if(hCom == NULL)
		return FALSE;

	char ans[128]={0};
	WriteCom("AT\r",(DWORD)3);
	Sleep(10);
	ReadCom(ans, (DWORD)128);
	if (strstr(ans, "OK") == NULL)
	{
		return FALSE;
	}
	
	memset(ans,0,sizeof(ans));
	WriteCom("ATE0\r", (DWORD)5);
	Sleep(10);
	ReadCom(ans, (DWORD)128);
	if (strstr(ans,"OK") == NULL)
	{
		return FALSE;
	}
	
	memset(ans,0,sizeof(ans));
	WriteCom("AT+CMGF=0\r", (DWORD)10);
	Sleep(10);
	ReadCom(ans, (DWORD)128);
	if (strstr(ans,"OK") == NULL)
	{
		return FALSE;
	}
	m_isConnectDevice=TRUE;
	return TRUE;
}


//把要发送的数据放入缓冲区
BOOL CSmsSerialPort::PutToSendMessageList(SM_PARAM & sm_Parama)
{
	//消息队列由两个线程共享,必须同步
	EnterCriticalSection(&m_SendNoteMessageListCritical);
	m_SendNoteMessageList.push_back(sm_Parama);
	LeaveCriticalSection(&m_SendNoteMessageListCritical);
	return TRUE;
}

//从发送消息队列中获取要发送的消息
BOOL CSmsSerialPort::GetNoteMessageFromSendMessagelist(SM_PARAM& smParam)
{
	EnterCriticalSection(&m_SendNoteMessageListCritical);
	smParam=m_SendNoteMessageList.front();//取出短消息
	//从队列中删除短消息
	m_SendNoteMessageList.pop_front();
	LeaveCriticalSection(&m_SendNoteMessageListCritical);
	return TRUE;
}

BOOL CSmsSerialPort::SendNoteMessage(SM_PARAM & sm_Param)
{
	//SM_PARAM sms;
	SM_BUFF Buff;
	int waitCount=0;//错误次数
	GetNoteMessageFromSendMessagelist(sm_Param);
	TRACE("串口的hwnd值为 %d",theApp.m_SmsSerialPort.hCom);
	while(!gsmSendMessage(sm_Param));
	int State;
	State=gsmGetResponse(Buff);
	if(State == GSM_OK)
		return TRUE;
	if(State == GSM_ERR)
		return FALSE;
	return TRUE;
}



BOOL CSmsSerialPort::GetNoteMessageInfoFromShowMessageList(NoteMsgInfo & noteMsgInfo)
{
	EnterCriticalSection(&m_ShowNoteMessageListCritical);
	noteMsgInfo=m_ShowNoteMessageList.front();//取出短消息
	//从队列中删除短消息
	m_ShowNoteMessageList.pop_front();
	LeaveCriticalSection(&m_ShowNoteMessageListCritical);
	return TRUE;
}

void CSmsSerialPort::ReceiveNoteMessage(SM_PARAM & sm_Param)
{
	char request[128] = {0}; //存放请求指令
	char response[500] = {0}; //存放响应指令
	SM_PARAM recvBuff;
	sprintf(request,"AT+CMGR=%d\r\n",m_MessagIndex);
	
	WriteCom(request,strlen(request));
	Sleep(500);
	while(1)
	{
		ReadCom(response,500);		
		if(strstr(response,"OK\r\n"))
		{
			break;
		}
		Sleep(300);
		memset(response,0,128);
		
	}
	char* pChar;  //"+CMGR"在响应字符串中的首地址
	char* pTN; //"\r\n"在响应字符串中的首地址
	pChar = strstr(response,"+CMGR");
	
	pTN = strstr(pChar,"\r\n");
	pTN += 2;
	memset(&recvBuff,0,sizeof(SM_PARAM));
	gsmDecodePdu(pTN, &recvBuff);
	memcpy(&sm_Param, &recvBuff,sizeof(SM_PARAM));
	
	m_IsRecvNoteMessageDate = FALSE;
}


ULONG CSmsSerialPort::NoteMessageThread(LPVOID lpParam)
{
	CSmsSerialPort* sp=(CSmsSerialPort *)lpParam;
	SM_PARAM tempParam;
	//TRACE("%d",sp->hCom);
	CString time;
	CString phoneNumber;
	CString action;
	CString state;
	CString content;

	while(sp->m_isRunning)
	{
		TRACE("串口号%d\n",sp->hCom);
		Sleep(100);

		time.Empty();
		phoneNumber.Empty();
		action.Empty();
		state.Empty();
		content.Empty();

		if(sp->m_SendNoteMessageList.size() != 0)
		{

			
			CTime currentTime;
			currentTime = CTime::GetCurrentTime();
			time = currentTime.Format("%Y-%m-%d %H:%M:%S");
			action="发送";

			if(sp->SendNoteMessage(tempParam)==TRUE)
			{
				//发送成功
				phoneNumber=tempParam.TPA;//手机号码
				state="成功";
				content=tempParam.TP_UD; //发送内容

				//////////////////////////////////////////////////////////////////////////
				//把发送的结果保存到显示列表队列中支
				sp->PutToShowNoteMessageList(time,phoneNumber,action,state,content);
				
				//////////////////////////////////////////////////////////////////////////
				//保存发送的结果保存到数据库中支
				sp->SaveToSendLog(tempParam,time,1); //状态1代表发送成功
				//AfxMessageBox("发送成功");
					
			}
			else
			{
				//发送失败				
				phoneNumber=tempParam.TPA;//手机号码
				state="失败";
				content=tempParam.TP_UD;  //发送内容

				//////////////////////////////////////////////////////////////////////////
				//保存发送的结果保存到数据库中支
				sp->PutToShowNoteMessageList(time,phoneNumber,action,state,content);

				//////////////////////////////////////////////////////////////////////////
				//保存发送的结果保存到数据库中支
				sp->SaveToSendLog(tempParam,time,0); //状态1代表发送成功
				//AfxMessageBox("发送失败");
			}

			AfxGetMainWnd()->PostMessage(WM_SHOWNOTEMESSAGE,0,0);
		}
		Sleep(100);
		if(sp->IsRecvNoteMessageDate())
		{

			//////////////////////////////////////////////////////////////////////////
			//接收短信
			sp->ReceiveNoteMessage(tempParam);//接收短信
			//////////////////////////////////////////////////////////////////////////
			//将接收到的保存到数据库中去
			sp->SaveToReceivedLog(tempParam);//将接收到的数据保存到数据库的日志中去

			//////////////////////////////////////////////////////////////////////////
			//把接收到的短信放到显示消息队列中去

			//格式化时间
			int year,month,day,hour,minute,second;
			sscanf(tempParam.TP_SCTS,"%02d%02d%02d%02d%02d%02d",&year,&month,&day,&hour,&minute,&second);
			time.Format("20%02d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
			
			phoneNumber=tempParam.TPA;//手机号码
			content=tempParam.TP_UD;//发送内容
			action="接收";
			state="成功";
			
			//发送到显示消息队列中去
			sp->PutToShowNoteMessageList(time,phoneNumber,action,state,content);

			//////////////////////////////////////////////////////////////////////////
			//发送显示消息
			//将接收到的内容发送到接收队列中去
			//sp->PutToRecvMessageList(tempParam);
			//TRACE("接收队列的大小为%d,内容为",sp->m_RecvNoteMessageList.size());
			//你有新短消息
			AfxGetMainWnd()->PostMessage(WM_SHOWNOTEMESSAGE,0,0);

			//////////////////////////////////////////////////////////////////////////
			//删除手机芯上的收到的记录
			char cmd[100] = {0};
			SM_BUFF temp;
			memset(&temp,0,sizeof(SM_BUFF));
			sprintf(cmd,"AT+CMGD=%d\r",sp->m_MessagIndex);
			sp->WriteCom(cmd,strlen(cmd));
			while( GSM_OK!=sp->gsmGetResponse(temp))
			{
				sp->WriteCom(cmd,strlen(cmd));
			}

		}
		DWORD result=WaitForSingleObject(sp->m_event,100);
		if(result==WAIT_OBJECT_0)
		{
			sp->m_isRunning=FALSE;
		}

	}
	//AfxMessageBox("线程退出");
	return 0;
}

BOOL CSmsSerialPort::StartThread()
{
	m_isRunning = TRUE;
	m_event=CreateEvent(NULL,TRUE,NULL,NULL);


	if( (m_hThread=CreateThread(NULL,0,NoteMessageThread,this,0,&m_dwThreadID)) == NULL)
	{
		TRACE("线程开始时句柄%d",this->hCom);
		TRACE("Create Thread Error\n");
		return FALSE;
	}
	else
		return TRUE;
}

BOOL CSmsSerialPort::StopThread()
{
	SetEvent(m_event);
	CloseHandle(m_hThread);
	//结束进程
	return FALSE;
}


BOOL CSmsSerialPort::IsRunning()//判断是否
{
	return hCom!=NULL;
}

SM_PARAM CSmsSerialPort::NoteMessage(CString ServiceCenter,CString phoneNumber,CString Message,int orderID)
{
/*
SM_PARAM P;
strcpy(P.SCA,"8613800591500");//服务中心号码
strcpy(P.TPA,"8613459112022");
P.TP_PID= 0;
P.TP_DCS = GSM_UCS2;
//P.TP_SCTS = "";
strcpy(P.TP_UD , "你好,SELECT * FORM TABLE,TT");
m_SmsSerialPort.m_SendMessageList.push_back(P);

  if(TRUE==m_SmsSerialPort.SendNoteMessage())
		MessageBox("send success");
		else
		MessageBox("send faild");
		
		  m_SmsSerialPort.CloseSerialPort();
	*/
	SM_PARAM sm_Param;
	memset(&sm_Param,0,sizeof(SM_PARAM));
	strcpy(sm_Param.SCA,ServiceCenter);//服务中心号码
	strcpy(sm_Param.TPA,phoneNumber); //设置手机号
	sm_Param.TP_PID= 0;
	sm_Param.TP_DCS = GSM_UCS2;
	strcpy(sm_Param.TP_UD ,Message);
	sm_Param.index=-1;
	return sm_Param;
}

BOOL CSmsSerialPort::IsRecvNoteMessageDate()
{
	int nLength;
	
	char ans[128] = {0};
	m_IsRecvNoteMessageDate = false;
	nLength = ReadCom(ans, 128);
	if ((nLength > 0))
	{
		if (strstr(ans, "\"SM\"") != 0)
		{
			GetMessageIndex(ans);
			m_IsRecvNoteMessageDate = true;
		}
	}
	
	return m_IsRecvNoteMessageDate;                                 
	
}


void CSmsSerialPort::GetMessageIndex(char *str)
{
	char buff[10] = {0};

	while(!isdigit(*str))
	{
		str++;
	}
	
	char *pBuff = buff;
	while(isdigit(*str))
	{
		*(pBuff++)= *(str++); 
	}
	
	*pBuff = 0;
	m_MessagIndex =  atoi(buff);
	
}





void CSmsSerialPort::SaveToReceivedLog(SM_PARAM sm_Param)
{
	//格式化时间
	int year,month,day,hour,minute,second;
	sscanf(sm_Param.TP_SCTS,"%02d%02d%02d%02d%02d%02d",&year,&month,&day,&hour,&minute,&second);
	CString strTime;
	
	strTime.Format("20%02d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);

	//////////////////////////////////////////////////////////////////////////
	///数据库操作
	CSMSApp * pCSMSApp=(CSMSApp *)AfxGetApp();//取得App类对象的指针
	CSMSADO &Ado=pCSMSApp->m_SMSAdo;
	CString sql;
	sql.Format("insert into receivedlog values \
		(receivedseq.nextval,%s,'%s',to_Date('%s','YYYY-MM-DD HH24:MI:SS') )",
		sm_Param.TPA,//手机号码
		sm_Param.TP_UD,//手机发送的内容
		strTime);
	int isSuccess=Ado.ExecuteWithoutRecordset(sql);
	TRACE(sql);
	if(!isSuccess)
	{
		AfxMessageBox("接收短信插入数据库出错");
 	}
}

void CSmsSerialPort::SaveToSendLog(SM_PARAM sm_Param,CString sendTime,int state)
{
	//////////////////////////////////////////////////////////////////////////
	///数据库操作
	CSMSApp * pCSMSApp=(CSMSApp *)AfxGetApp();//取得App类对象的指针
	CSMSADO &Ado=pCSMSApp->m_SMSAdo;
	CString sql;
	sql.Format("insert into receivedlog values \
		(sendseq.nextval,%d,to_Date('%s','YYYY-MM-DD HH24:MI:SS'),%d,%s)",
		sm_Param.index,//订单号
		sendTime, //发送时间
		state, //状态
		sm_Param.TPA //手机号码
		);
	int isSuccess=Ado.ExecuteWithoutRecordset(sql);
	TRACE(sql);
	if(!isSuccess)
	{
		AfxMessageBox("接收短信插入数据库出错");
 	}
}

BOOL CSmsSerialPort::PutToShowNoteMessageList(CString time,CString phoneNumber,CString action,CString state,CString content)
{
	NoteMsgInfo noteMsgInfo;
	noteMsgInfo.time=time;
	noteMsgInfo.phoneNumber=phoneNumber;
	noteMsgInfo.action=action;
	noteMsgInfo.state=state;
	noteMsgInfo.content=content;

	EnterCriticalSection(&m_ShowNoteMessageListCritical);
	m_ShowNoteMessageList.push_back(noteMsgInfo);
	LeaveCriticalSection(&m_ShowNoteMessageListCritical);
	return 0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -