📄 sms.cpp
字号:
nPduLength = gsmEncodePdu(pSrc, 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); // 生成命令
// TRACE("%s", cmd);
// TRACE("%s\n", pdu);
for(int i=0;i<3;i++) // 测试AT+I指令,允许重发两次,否则初始化失败,检查硬件连接
{
WriteComm(cmd, strlen(cmd)); // 先输出命令串
ReadComm(ans, 128); // 读应答数据
if (strstr(ans, ">") == NULL)// 返回ok,说明初始化成功
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
WriteComm(pdu, strlen(pdu)); // 得到肯定回答,继续输出PDU串
return 0;
}
// 读取短消息,仅发送命令,不读取应答
// 用+CMGL代替+CMGR,可一次性读出全部短消息
int gsmReadMessageList()
{
return WriteComm("AT+CMGL=0\r", 10);
}
// 删除短消息,仅发送命令,不读取应答
// 输入: index - 短消息序号,1-255
int gsmDeleteMessage(int index)
{
char cmd[16]; // 命令串
sprintf(cmd, "AT+CMGD=%d\r", index); // 生成命令
// 输出命令串
return WriteComm(cmd, strlen(cmd));
}
// 读取GSM MODEM的应答,可能是一部分
// 输出: pBuff - 接收应答缓冲区
// 返回: GSM MODEM的应答状态, GSM_WAIT/GSM_OK/GSM_ERR
// 备注: 可能需要多次调用才能完成读取一次应答,首次调用时应将pBuff初始化
int gsmGetResponse(SM_BUFF* pBuff)
{
int nLength; // 串口收到的数据长度
int nState;
// 从串口读数据,追加到缓冲区尾部
nLength = ReadComm(&pBuff->data[pBuff->len], 128);
pBuff->len += nLength;
// 确定GSM MODEM的应答状态
nState = GSM_WAIT;
if ((nLength > 0) && (pBuff->len >= 4))
{
if (strncmp(&pBuff->data[pBuff->len - 4], "OK\r\n", 4) == 0) nState = GSM_OK;
else if (strstr(pBuff->data, "ERROR") != NULL) nState = GSM_ERR;
}
return nState;
}
// 从列表中解析出全部短消息
// 输入: pBuff - 短消息列表缓冲区
// 输出: pMsg - 短消息缓冲区
// 返回: 短消息条数
int gsmParseMessageList(SM_PARAM* pMsg, SM_BUFF* pBuff)
{
int nMsg; // 短消息计数值
char* ptr; // 内部用的数据指针
nMsg = 0;
ptr = pBuff->data;
// 循环读取每一条短消息, 以"+CMGL:"开头
while((ptr = strstr(ptr, "+CMGL:")) != NULL)
{
ptr += 6; // 跳过"+CMGL:", 定位到序号
sscanf(ptr, "%d", &pMsg->index); // 读取序号,此序号在ptr内容的第一个字节保存
// TRACE(" index=%d\n",pMsg->index);
ptr = strstr(ptr, "\r\n"); // 找下一行
if (ptr != NULL)
{
ptr += 2; // 跳过"\r\n", 定位到PDU
gsmDecodePdu(ptr, pMsg); // PDU串解码
pMsg++; // 准备读下一条短消息
nMsg++; // 短消息计数加1
}
}
return nMsg;
}
// 初始化Gprs
// 返回: TRUE 初始化成功 FALSE 初始化失败
BOOL InitGprs()
{
char ans[30];
char buffer[30];
for(int i=0;i<3;i++) // 测试AT+I指令,允许重发两次,否则初始化失败,检查硬件连接
{
WriteComm("ATE0\r",5);
ReadComm(ans,20);
if (strstr(ans, "OK") == NULL)// 返回ok,说明初始化成功
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
memset(ans,0,30);
for(i=0;i<3;i++) // 测试AT+I指令,允许重发两次,否则初始化失败,检查硬件连接
{
WriteComm("AT\r",3);
ReadComm(ans,20);
if (strstr(ans, "OK") == NULL)// 返回ok,说明初始化成功
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
memset(ans,0,30);
for(i=0;i<3;i++) // 测试AT+CPIN指令,判断SIM的状态,返回READY则SIM卡工作正常
{
WriteComm("AT+CPIN?\r",9);
ReadComm(ans,40);
if (strstr(ans, "READY") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
memset(ans,0,30);
for(i=0;i<3;i++) // 设置短消息中心号码,其格式为AT+CMGF="+8613800451500"
{
int length = sprintf(buffer,"AT+CSCA=%c+8613800451500%c\r\n",34,34);
WriteComm(buffer,length);
ReadComm(ans,30);
if (strstr(ans, "OK") == NULL) // 返回OK,说明设置成功
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
memset(ans,0,30);
for(i=0;i<3;i++) // 设置是否有新短消息时给终端主动发送通知
{
WriteComm("AT+CNMI=3,1\r",12); // 0,0为不主动发送,3,1为主动发送
ReadComm(ans,30);
if (strstr(ans, "OK") == NULL) // 返回OK,说明设置成功
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
return TRUE;
}
// 设置短消息发送格式
// 格式:state,为0表示Text方式,不能发送汉字,为1表示PDU格式,可以发送汉字
// 返回: TRUE设置成功 FALSE 设置失败
BOOL SetMessageType(int state)
{
char ans[30];
for(int i=0;i<3;i++) // 测试AT+CMGF=1指令,设置短消息发送方式
{
if(state==0) WriteComm("AT+CMGF=1\r",25); // Text发送
else if(state==1) WriteComm("AT+CMGF=0\r",25); // PDU发送
ReadComm(ans,30);
if (strstr(ans, "OK") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
return TRUE;
}
// 切换AT指令和ATI指令
// type:指令类型,为真为ATI指令集,为假则为AT指令集
BOOL ChangeCommandType(BOOL type)
{
char ans[60];
if (type)
{
for(int i=0;i<3;i++) // 测试AT+IMCM指令,进入手机模块AT命令直传状态
{
WriteComm("AT+I\r",8);
ReadComm(ans,20);
if (strstr(ans, "I/OK") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
}
else
{
for(int i=0;i<3;i++) // 测试AT+IMCM指令,进入手机模块AT命令直传状态
{
WriteComm("AT+IMCM\r",8);
ReadComm(ans,20);
if (strstr(ans, "I/OK") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
}
return TRUE;
}
// 以Text方式发送短消息
// number:对方手机号码
// content:短信内容
// 返回:TRUE 发送成功,FALSE 发送失败
BOOL SendTextMessage(CString number,CString content)
{
char ans[60];
char buffer[30];
int length;
for(int i=0;i<3;i++) // 发送目标手机号
{
length = sprintf(buffer,"AT+CMGS=%c+86%s%c\r",34,number,34);
WriteComm(buffer,length);
ReadComm(ans,30);
if (strstr(ans, ">") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
for(i=0;i<3;i++) // 发送短消息内容
{
length = sprintf(buffer,"%s%c",content,26);
WriteComm(buffer,length);
Sleep(2000);
ReadComm(ans,140);
if (strstr(ans, "OK") == NULL)
{
if(i==2)
{
return FALSE;
}
Sleep(500);
}
else
{
break;
}
}
return TRUE;
}
// 打开并建立一个SOCKET连接
// 输入: pSocket 需要建立的pSocket连接的参数
// 仅发送命令,不接收应答
// 指令:AT+ISTCP:xxx.xxx.xxx.xxx,<Port Number> <CR>句柄,此指令返回socket句柄
BOOL ConnectSocket(SOCKET_PARAM* pSocket)
{
char buffer[70];
int length = sprintf(buffer,"AT+MIPOPEN=%s,%s,%c%s%c,%s,%d\r\n",pSocket->SOCKET_ID,pSocket->SPORT_NUMBER,34,pSocket->IP_ADDRESS,34,pSocket->DPORT_NUMBER,0);
WriteComm(buffer,length);
return TRUE;
}
// 关闭一个SOCKET连接
// 输入: pSocket 需要建立的pSocket连接的参数
// 仅发送命令,不接收应答
// 指令:AT+ISCLS:000<CR>,句柄000为socket等待返回I/DONE
void CloseSocket(SOCKET_PARAM* pSocket)
{
char buffer[20];
int length = sprintf(buffer,"AT+MIPCLOSE=%s\r",pSocket->SOCKET_ID);
WriteComm(buffer,length);
}
// 通过指定socket发送数据
// 输入: pSocket 需要发送的数据以及相应的socket信息
// 仅发送命令,不接收应答
// 指令:AT+ISSND%:xxx,<string Length>:<CR>
void SocketSendData(SOCKETDATA_PARAM* pSocket)
{
char buffer[5000]; // 长度以后需要指定
int length = sprintf(buffer,"AT+MIPSEND=%s,%c%s%c\r",pSocket->SOCKET_ID,34,pSocket->SEND_DATA,34);
WriteComm(buffer,length);
}
// 从缓冲区数据列表中解析出数据包
// 输入: pBuff - 数据列表缓冲区
// 输入: pSocket - 当前的socket信息
// 输出: pData - 数据包缓冲区
// 返回: 数据包个数
int SocketParseMessageList(SOCKET_PARAM* pSocket,SOCKETDATA_PARAM* pData, SOCKET_BUFF* pBuff)
{
char *ptr;
ptr = sRecData.data;
ptr = strstr(ptr,",");
ptr +=1;
ptr = strstr(ptr,",");
ptr +=1;
strcpy(pData->SEND_DATA,ptr);
strcpy(pData->IP_ADDRESS,pSocket->IP_ADDRESS);
strcpy(pData->SOCKET_ID,pSocket->SOCKET_ID);
return strlen(pData->SEND_DATA);
}
// 读取缓冲区中的数据,仅发送命令,不读取应答
// 一次性的读出缓冲区中的所有数据
// 指令AT+ISRCV:xxx<CR>
/*void SocketReadDataList(SOCKET_PARAM* pSocket)
{
CString str;
// str.Format("AT+ISRCV:%s\r",pSocket->SOCKET_HANDLE);
WriteComm(str.GetBuffer(15),str.GetLength());
}*/
// 读取Socket通讯时应答
// 输出: pBuff - 接收应答缓冲区
// 备注: 可能需要多次调用才能完成读取一次应答,首次调用时应将pBuff初始化
void SocketGetResponse(SOCKET_BUFF* pBuff)
{
int nLength; // 串口收到的数据长度
// 从串口读数据,追加到缓冲区尾部
nLength = ReadComm(&pBuff->data[pBuff->len], 128);
pBuff->len += nLength;
}
void IsRecMsgOrData(void* pData)
{
char* p = (char*) pData;
if (strstr(p,"CMTI"))
{
bRecMsgFlag = TRUE;
}
if (strstr(p,"MIPRTCP"))
{
bRecDatFlag = TRUE;
Sleep(1000);
strcpy(sRecData.data,p);
while(*p)
{
p++;
}
p=p+2;
pData = p;
}
}
int Char2Ascii(char* pSrc,char* pDst)
{
// TODO: Add extra initialization herx
BYTE a;
char buffer[3];
int length=0;
while(*pSrc)
{
a = *pSrc;
sprintf(buffer,"%x",a);
strcat(pDst,buffer);
pSrc++;
length++;
}
return 2*length;
}
BOOL GetRecMsgFlag()
{
return bRecMsgFlag;
}
BOOL GetRecDataFlag()
{
return bRecDatFlag;
}
void SetRecMsgFlag(BOOL flag)
{
bRecMsgFlag = flag;
}
void SetRecDatFlag(BOOL flag)
{
bRecDatFlag = flag;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -