📄 smsserialport.cpp
字号:
/*******************************************************************************/
// 发送短消息,仅发送命令,不读取应答
// 输入: 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 + -