📄 smstoolsfun.cpp
字号:
// 包含回复地址,取回复地址信息
gsmString2Bytes(pSrc, &tmp, 2); // 取长度
if(tmp & 1) tmp += 1; // 调整奇偶性
pSrc += 4; // 指针后移
gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA号码
pSrc += tmp; // 指针后移
}
// TPDU段协议标识、编码方式、用户信息等
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取协议标识(TP-PID)
pSrc += 2; // 指针后移
gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取编码方式(TP-DCS)
pSrc += 2; // 指针后移
gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14); // 服务时间戳字符串(TP_SCTS)
pSrc += 14; // 指针后移
gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)
pSrc += 2; // 指针后移
if(pDst->TP_DCS == GSM_7BIT)
{
// 7-bit解码
nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式转换
gsmDecode7bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
nDstLength = tmp;
}
else
if(pDst->TP_DCS == GSM_UCS2)
{
// UCS2解码
memset(buf, 0, sizeof(buf));///////////
nDstLength = gsmString2Bytes(pSrc, buf, tmp*2); // 格式转换
nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
}
else
{
// 8-bit解码
nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换
nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
}
// 返回目标字符串长度
return nDstLength;
}
//-----------------------------------------------------------------------------
// 发送短消息
// pSrc: 源PDU参数指针
BOOL gsmSendMessage(const SM_PARAM* pSrc)
{
int nPduLength; // PDU串长度
unsigned char nSmscLength; // SMSC串长度
int nLength; // 串口收到的数据长度
char cmd[16]; // 命令串
char pdu[512]; // PDU串
char ans[512]; // 应答串
int len;
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); // 生成命令
WriteComm(cmd, strlen(cmd)); // 先输出命令串
memset(ans, 0, sizeof(ans));
Sleep(500);
nLength = ReadComm(ans, sizeof(ans)); // 读应答数据
// 根据能否找到"\r\n> "决定成功与否
if( strstr(ans+strlen(cmd), "\r\n>") != NULL)
{
//清除串口缓冲区
PurgeComm(hComm,PURGE_TXCLEAR);
PurgeComm(hComm,PURGE_RXCLEAR);
WriteComm(pdu, strlen(pdu)); // 得到肯定回答,继续输出PDU串
memset(ans, 0, sizeof(ans));
Sleep(7000); //暂停几秒钟,以等待手机应答
nLength = ReadComm(ans, sizeof(ans));// 读应答数据
// 根据能否找到"+CMS ERROR"决定成功与否
if(nLength > 0 && strstr(ans+nPduLength, "OK") != NULL)
{
return TRUE;
}
/*
else{//继续读应答
memset(ans, 0, sizeof(ans));
Sleep(3000);
nLength=ReadComm(ans, sizeof(ans));
if( nLength>0 && strstr(ans+nPduLength, "OK") != NULL )
return TRUE;
}
*/
}
return FALSE;
}
//-----------------------------------------------------------------------------
// 读取短消息
// 用+CMGL代替+CMGR,可一次性读出全部短消息
// pMsg: 短消息缓冲区,必须足够大
// 返回: 短消息条数
int gsmReadMessage(SM_PARAM* pMsg)
{
int nLength; // 串口收到的数据长度
int nMsg; // 短消息计数值
char* ptr; // 内部用的数据指针
char cmd[16]; // 命令串
char ans[1024]; // 应答串
nMsg = 0;
ptr = ans;
sprintf(cmd, "AT+CMGL=0\r"); // 生成命令
WriteComm(cmd, strlen(cmd)); // 输出命令串
nLength = ReadComm(ans, 1024); // 读应答数据
// 根据能否找到"+CMS ERROR"决定成功与否
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
// 循环读取每一条短消息, 以"+CMGL:"开头
while((ptr = strstr(ptr, "+CMGL:")) != NULL)
{
ptr += 6; // 跳过"+CMGL:"
sscanf(ptr, "%d", &pMsg->index); // 读取序号
//TRACE(" index=%d\n",pMsg->index);
ptr = strstr(ptr, "\r\n"); // 找下一行
ptr += 2; // 跳过"\r\n"
gsmDecodePdu(ptr, pMsg); // PDU串解码
pMsg++; // 准备读下一条短消息
nMsg++; // 短消息计数加1
}
}
return nMsg;
}
//-----------------------------------------------------------------------------
int my_gsmReadMessage(SM_PARAM* pMsg)
{
int nLength; // 串口收到的数据长度
int nMsg; // 短消息计数值
char* ptr; // 内部用的数据指针
char cmd[16]; // 命令串
char ans[10240]; // 应答串
int i=0;
int j=0;
FILE *fp;
int get_systime1(char *bgntime);
char full_file_name[100],tmp[1024],time[100];
void WriteComm1(void* pData, int nLength);
int ReadComm1(void* pData, int nLength);
memset(full_file_name, 0, sizeof(full_file_name));
getcwd(full_file_name, 100);
strcat(full_file_name,"\\sms_recv.txt");
if( (fp=fopen(full_file_name, "a+"))==NULL ){
sprintf(tmp, "打开短信数据文件[%s]失败,接收线程结束\n", full_file_name);
Form1->StatusBar1->Panels->Items[0]->Text=tmp;
return(-1);
}
nMsg = 0;
ptr = ans;
sprintf(cmd, "AT+CMGL=0\r"); // 生成命令-"0读出未读的短信" 1-已读
WriteComm1(cmd, strlen(cmd)); // 输出命令串
Sleep(1000);
nLength = ReadComm1(ans, 10240); // 读应答数据
//fprintf(fp, "ans=\n[%s]\n", ans);///////////////////////
//fflush(fp); //////////////////////
// 根据能否找到"+CMS ERROR"决定成功与否
if(nLength > 0 && strstr(ans, "ERROR")==NULL)
{
// 循环读取每一条短消息, 以"+CMGL:"开头
while((ptr = strstr(ptr, "+CMGL:")) != NULL)
{
ptr += 6; // 跳过"+CMGL:"
sscanf(ptr, "%d", &pMsg->index); // 读取序号
//TRACE(" index=%d\n",pMsg->index);
ptr = strstr(ptr, "\r\n"); // 找下一行
ptr += 2; // 跳过"\r\n"
//p=ptr; ////////////////
//ptr = strstr(ptr, "\r\n"); // 找下一行 ////////////////
memset(tmp, 0, sizeof(tmp));
i=0;
while( ptr[0]!='\r' ){
tmp[i]=ptr[0];
ptr++; i++;
}
ptr++; ptr++;
//gsmDecodePdu(ptr, pMsg); // PDU串解码
//fprintf(fp, "tmp=[%s]\n", tmp);///////////////////////
//fflush(fp); //////////////////////
gsmDecodePdu(tmp, pMsg); // PDU串解码
//把读出的信息写入文件
memset(time, 0, sizeof(time));
get_systime1(time);
sprintf(tmp, "%-20s|%-15s|%-s", time, pMsg->TPA, pMsg->TP_UD);
fprintf(fp, "%s\n", tmp);
fflush(fp);
//-----------------
//显示接收情况
{
TListItem * item;
item=Form1->ListView2->Items->Add();
item->Caption=time;
item->SubItems->Add(pMsg->TPA);
item->SubItems->Add(pMsg->TP_UD);
//上滚屏幕
Form1->ListView2->Scroll(0, 10000);;
}
//----------------
//删除该短信
j=0;
while(j<5){
char ans1[1024];
PurgeComm(hComm1,PURGE_TXCLEAR);
PurgeComm(hComm1,PURGE_RXCLEAR);
sprintf(cmd, "AT+CMGd=%d\r", pMsg->index); // 生成命令
WriteComm1(cmd, strlen(cmd)); // 输出命令串
Sleep(2000);
memset(ans1, 0, sizeof(ans1));
nLength = ReadComm1(ans1, 1024); // 读应答数据
if( strstr(ans1,"OK")!=NULL )
break;
//Sleep(1000);
}
pMsg++; // 准备读下一条短消息
nMsg++; // 短消息计数加1
}
}
fclose(fp);
return nMsg;
}
//-----------------------------------------------------------------------------
// 删除短消息
// index: 短消息序号,从1开始
BOOL gsmDeleteMessage(const int index)
{
int nLength; // 串口收到的数据长度
char cmd[16]; // 命令串
char ans[128]; // 应答串
sprintf(cmd, "AT+CMGD=%d\r", index); // 生成命令
// 输出命令串
WriteComm(cmd, strlen(cmd));
Sleep(1500);
// 读应答数据
nLength = ReadComm(ans, 128);
// 根据能否找到"+CMS ERROR"决定成功与否
if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
{
return TRUE;
}
return FALSE;
}
//-----------------------------------------------------------------------------
// 打开串口
// pPort: 串口名称或设备路径,可用"COM1"或"\\.\COM1"两种方式,建议用后者
// nBaudRate: 波特率
// nParity: 奇偶校验
// nByteSize: 数据字节宽度
// nStopBits: 停止位
BOOL OpenComm(const char* pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits)
{
DCB dcb; // 串口控制块
COMMTIMEOUTS timeouts = { // 串口超时控制参数
100, // 读字符间隔超时时间: 100 ms
1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
500, // 基本的(额外的)读超时时间: 500 ms
1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
100}; // 基本的(额外的)写超时时间: 100 ms
hComm = CreateFile(pPort, // 串口名称或设备路径
GENERIC_READ | GENERIC_WRITE, // 读写方式
0, // 共享方式:独占
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if(hComm == INVALID_HANDLE_VALUE) return FALSE; // 打开串口失败
GetCommState(hComm, &dcb); // 取DCB
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nByteSize;
//dcb.Parity = nParity;
dcb.Parity = NOPARITY;
dcb.StopBits = nStopBits;
SetCommState(hComm, &dcb); // 设置DCB
SetupComm(hComm, 4096, 1024); // 设置输入输出缓冲区大小
SetCommTimeouts(hComm, &timeouts); // 设置超时
return TRUE;
}
//-----------------------------------------------------------------------------
BOOL OpenComm1(const char* pPort, int nBaudRate, int nParity, int nByteSize, int nStopBits)
{
DCB dcb; // 串口控制块
COMMTIMEOUTS timeouts = { // 串口超时控制参数
//100, // 读字符间隔超时时间: 100 ms
100, // 读字符间隔超时时间: 100 ms
//1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
1, // 读操作时每字符的时间: 1 ms (n个字符总共为n ms)
//500, // 基本的(额外的)读超时时间: 500 ms
500, // 基本的(额外的)读超时时间: 500 ms
//1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
1, // 写操作时每字符的时间: 1 ms (n个字符总共为n ms)
//100}; // 基本的(额外的)写超时时间: 100 ms
100}; // 基本的(额外的)写超时时间: 100 ms
hComm1 = CreateFile(pPort, // 串口名称或设备路径
GENERIC_READ | GENERIC_WRITE, // 读写方式
0, // 共享方式:独占
NULL, // 默认的安全描述符
OPEN_EXISTING, // 创建方式
0, // 不需设置文件属性
NULL); // 不需参照模板文件
if(hComm1 == INVALID_HANDLE_VALUE) return FALSE; // 打开串口失败
GetCommState(hComm1, &dcb); // 取DCB
dcb.BaudRate = nBaudRate;
dcb.ByteSize = nByteSize;
//dcb.Parity = nParity;
dcb.Parity = NOPARITY;
dcb.StopBits = nStopBits;
SetCommState(hComm1, &dcb); // 设置DCB
SetupComm(hComm1, 4096, 1024); // 设置输入输出缓冲区大小
SetCommTimeouts(hComm1, &timeouts); // 设置超时
return TRUE;
}
//-----------------------------------------------------------------------------
// 关闭串口
BOOL CloseComm()
{
return CloseHandle(hComm);
}
//------------------------------------------------------------------------------
BOOL CloseComm1()
{
return CloseHandle(hComm1);
}
//-----------------------------------------------------------------------------
// 写串口
// pData: 待写的数据缓冲区指针
// nLength: 待写的数据长度
void WriteComm(void* pData, int nLength)
{
DWORD dwNumWrite; // 串口发出的数据长度
WriteFile(hComm, pData, (DWORD)nLength, &dwNumWrite, NULL);
}
//-----------------------------------------------------------------------------
void WriteComm1(void* pData, int nLength)
{
DWORD dwNumWrite; // 串口发出的数据长度
WriteFile(hComm1, pData, (DWORD)nLength, &dwNumWrite, NULL);
}
//-----------------------------------------------------------------------------
// 读串口
// pData: 待读的数据缓冲区指针
// nLength: 待读的最大数据长度
// 返回: 实际读入的数据长度
int ReadComm(void* pData, int nLength)
{
DWORD dwNumRead; // 串口收到的数据长度
ReadFile(hComm, pData, (DWORD)nLength, &dwNumRead, NULL);
return (int)dwNumRead;
}
//--------------------------------------------------------------------
int ReadComm1(void* pData, int nLength)
{
DWORD dwNumRead; // 串口收到的数据长度
ReadFile(hComm1, pData, (DWORD)nLength, &dwNumRead, NULL);
return (int)dwNumRead;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -