Sms.cpp
上传用户:ynthgy
上传日期:2022-06-13
资源大小:1580k
文件大小:18k
源码类别:

手机短信编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include <stdio.h>
  3. #include "Sms.h"
  4. #include "Comm.h"
  5. BYTE byIndex = 0;
  6. // 可打印字符串转换为字节数据
  7. // 如:"12345678" --> {0x12, 0x34, 0x56, 0x78}
  8. // pSrc: 源字符串指针
  9. // pDst: 目标数据指针
  10. // nSrcLength: 源字符串长度
  11. // 返回: 目标数据长度
  12. int gsmString2Bytes(const char* pSrc, unsigned char* pDst, int nSrcLength)
  13. {
  14. for(int i=0; i<nSrcLength; i+=2)
  15. {
  16. // 输出高4位
  17. if(*pSrc>='0' && *pSrc<='9')
  18. {
  19. *pDst = (*pSrc - '0') << 4;
  20. }
  21. else
  22. {
  23. *pDst = (*pSrc - 'A' + 10) << 4;
  24. }
  25. pSrc++;
  26. // 输出低4位
  27. if(*pSrc>='0' && *pSrc<='9')
  28. {
  29. *pDst |= *pSrc - '0';
  30. }
  31. else
  32. {
  33. *pDst |= *pSrc - 'A' + 10;
  34. }
  35. pSrc++;
  36. pDst++;
  37. }
  38. // 返回目标数据长度
  39. return nSrcLength / 2;
  40. }
  41. // 字节数据转换为可打印字符串
  42. // 如:{0x12, 0x34, 0x56, 0x78} --> "12345678"
  43. // pSrc: 源数据指针
  44. // pDst: 目标字符串指针
  45. // nSrcLength: 源数据长度
  46. // 返回: 目标字符串长度
  47. int gsmBytes2String(const unsigned char* pSrc, char* pDst, int nSrcLength)
  48. {
  49. const char tab[]="0123456789ABCDEF"; // 0x0-0xf的字符查找表
  50. for(int i=0; i<nSrcLength; i++)
  51. {
  52. *pDst++ = tab[*pSrc >> 4]; // 输出高4位
  53. *pDst++ = tab[*pSrc & 0x0f]; // 输出低4位
  54. pSrc++;
  55. }
  56. // 输出字符串加个结束符
  57. *pDst = '';
  58. // 返回目标字符串长度
  59. return nSrcLength * 2;
  60. }
  61. // 7bit编码
  62. // pSrc: 源字符串指针
  63. // pDst: 目标编码串指针
  64. // nSrcLength: 源字符串长度
  65. // 返回: 目标编码串长度
  66. int gsmEncode7bit(const char* pSrc, unsigned char* pDst, int nSrcLength)
  67. {
  68. int nSrc; // 源字符串的计数值
  69. int nDst; // 目标编码串的计数值
  70. int nChar; // 当前正在处理的组内字符字节的序号,范围是0-7
  71. unsigned char nLeft; // 上一字节残余的数据
  72. // 计数值初始化
  73. nSrc = 0;
  74. nDst = 0;
  75. // 将源串每8个字节分为一组,压缩成7个字节
  76. // 循环该处理过程,直至源串被处理完
  77. // 如果分组不到8字节,也能正确处理
  78. while(nSrc<nSrcLength)
  79. {
  80. // 取源字符串的计数值的最低3位
  81. nChar = nSrc & 7;
  82. // 处理源串的每个字节
  83. if(nChar == 0)
  84. {
  85. // 组内第一个字节,只是保存起来,待处理下一个字节时使用
  86. nLeft = *pSrc;
  87. }
  88. else
  89. {
  90. // 组内其它字节,将其右边部分与残余数据相加,得到一个目标编码字节
  91. *pDst = (*pSrc << (8-nChar)) | nLeft;
  92. // 将该字节剩下的左边部分,作为残余数据保存起来
  93. nLeft = *pSrc >> nChar;
  94. // 修改目标串的指针和计数值
  95. pDst++;
  96. nDst++;
  97. }
  98. // 修改源串的指针和计数值
  99. pSrc++;
  100. nSrc++;
  101. }
  102. // 返回目标串长度
  103. return nDst;
  104. }
  105. // 7bit解码
  106. // pSrc: 源编码串指针
  107. // pDst: 目标字符串指针
  108. // nSrcLength: 源编码串长度
  109. // 返回: 目标字符串长度
  110. int gsmDecode7bit(const unsigned char* pSrc, char* pDst, int nSrcLength)
  111. {
  112. int nSrc; // 源字符串的计数值
  113. int nDst; // 目标解码串的计数值
  114. int nByte; // 当前正在处理的组内字节的序号,范围是0-6
  115. unsigned char nLeft; // 上一字节残余的数据
  116. // 计数值初始化
  117. nSrc = 0;
  118. nDst = 0;
  119. // 组内字节序号和残余数据初始化
  120. nByte = 0;
  121. nLeft = 0;
  122. // 将源数据每7个字节分为一组,解压缩成8个字节
  123. // 循环该处理过程,直至源数据被处理完
  124. // 如果分组不到7字节,也能正确处理
  125. while(nSrc<nSrcLength)
  126. {
  127. // 将源字节右边部分与残余数据相加,去掉最高位,得到一个目标解码字节
  128. *pDst = ((*pSrc << nByte) | nLeft) & 0x7f;
  129. // 将该字节剩下的左边部分,作为残余数据保存起来
  130. nLeft = *pSrc >> (7-nByte);
  131. // 修改目标串的指针和计数值
  132. pDst++;
  133. nDst++;
  134. // 修改字节计数值
  135. nByte++;
  136. // 到了一组的最后一个字节
  137. if(nByte == 7)
  138. {
  139. // 额外得到一个目标解码字节
  140. *pDst = nLeft;
  141. // 修改目标串的指针和计数值
  142. pDst++;
  143. nDst++;
  144. // 组内字节序号和残余数据初始化
  145. nByte = 0;
  146. nLeft = 0;
  147. }
  148. // 修改源串的指针和计数值
  149. pSrc++;
  150. nSrc++;
  151. }
  152. // 输出字符串加个结束符
  153. *pDst = '';
  154. // 返回目标串长度
  155. return nDst;
  156. }
  157. // 8bit编码
  158. // pSrc: 源字符串指针
  159. // pDst: 目标编码串指针
  160. // nSrcLength: 源字符串长度
  161. // 返回: 目标编码串长度
  162. int gsmEncode8bit(const char* pSrc, unsigned char* pDst, int nSrcLength)
  163. {
  164. // 简单复制
  165. memcpy(pDst, pSrc, nSrcLength);
  166. return nSrcLength;
  167. }
  168. // 8bit解码
  169. // pSrc: 源编码串指针
  170. // pDst: 目标字符串指针
  171. // nSrcLength: 源编码串长度
  172. // 返回: 目标字符串长度
  173. int gsmDecode8bit(const unsigned char* pSrc, char* pDst, int nSrcLength)
  174. {
  175. // 简单复制
  176. memcpy(pDst, pSrc, nSrcLength);
  177. // 输出字符串加个结束符
  178. *pDst = '';
  179. return nSrcLength;
  180. }
  181. // UCS2编码
  182. // pSrc: 源字符串指针
  183. // pDst: 目标编码串指针
  184. // nSrcLength: 源字符串长度
  185. // 返回: 目标编码串长度
  186. int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)
  187. {
  188. // UNICODE n.统一的字符编码标准, 采用双字节对字符进行编码
  189. int nDstLength; // UNICODE宽字符数目
  190. WCHAR wchar[128]; // UNICODE串缓冲区
  191. // 字符串-->UNICODE串
  192. nDstLength = ::MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);
  193. // 高低字节对调,输出
  194. for(int i=0; i<nDstLength; i++)
  195. {
  196. *pDst++ = wchar[i] >> 8; // 先输出高位字节
  197. *pDst++ = wchar[i] & 0xff; // 后输出低位字节
  198. }
  199. // 返回目标编码串长度
  200. return nDstLength * 2;
  201. }
  202. // UCS2解码
  203. // pSrc: 源编码串指针
  204. // pDst: 目标字符串指针
  205. // nSrcLength: 源编码串长度
  206. // 返回: 目标字符串长度
  207. int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)
  208. {
  209. int nDstLength; // UNICODE宽字符数目
  210. WCHAR wchar[128]; // UNICODE串缓冲区
  211. // 高低字节对调,拼成UNICODE
  212. for(int i=0; i<nSrcLength/2; i++)
  213. {
  214. wchar[i] = *pSrc++ << 8; // 先高位字节
  215. wchar[i] |= *pSrc++; // 后低位字节
  216. }
  217. // UNICODE串-->字符串
  218. nDstLength = ::WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL);
  219. // 输出字符串加个结束符
  220. pDst[nDstLength] = '';
  221. // 返回目标字符串长度
  222. return nDstLength;
  223. }
  224. // 正常顺序的字符串转换为两两颠倒的字符串,若长度为奇数,补'F'凑成偶数
  225. // pSrc: 源字符串指针
  226. // pDst: 目标字符串指针
  227. // nSrcLength: 源字符串长度
  228. // 返回: 目标字符串长度
  229. int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength)
  230. {
  231. int nDstLength; // 目标字符串长度
  232. char ch; // 用于保存一个字符
  233. // 复制串长度
  234. nDstLength = nSrcLength;
  235. // 两两颠倒
  236. for(int i=0; i<nSrcLength;i+=2)
  237. {
  238. ch = *pSrc++; // 保存先出现的字符
  239. *pDst++ = *pSrc++; // 复制后出现的字符
  240. *pDst++ = ch; // 复制先出现的字符
  241. }
  242. // 源串长度是奇数吗?
  243. if(nSrcLength & 1)
  244. {
  245. *(pDst-2) = 'F'; // 补'F'
  246. nDstLength++; // 目标串长度加1
  247. }
  248. // 输出字符串加个结束符
  249. *pDst = '';
  250. // 返回目标字符串长度
  251. return nDstLength;
  252. }
  253. // 两两颠倒的字符串转换为正常顺序的字符串
  254. // pSrc: 源字符串指针
  255. // pDst: 目标字符串指针
  256. // nSrcLength: 源字符串长度
  257. // 返回: 目标字符串长度
  258. int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength)
  259. {
  260. int nDstLength; // 目标字符串长度
  261. char ch; // 用于保存一个字符
  262. // 复制串长度
  263. nDstLength = nSrcLength;
  264. // 两两颠倒
  265. for(int i=0; i<nSrcLength;i+=2)
  266. {
  267. ch = *pSrc++; // 保存先出现的字符
  268. *pDst++ = *pSrc++; // 复制后出现的字符
  269. *pDst++ = ch; // 复制先出现的字符
  270. }
  271. // 最后的字符是'F'吗?
  272. if(*(pDst-1) == 'F')
  273. {
  274. pDst--;
  275. nDstLength--; // 目标字符串长度减1
  276. }
  277. // 输出字符串加个结束符
  278. *pDst = '';
  279. // 返回目标字符串长度
  280. return nDstLength;
  281. }
  282. // PDU编码,用于编制、发送短消息
  283. // pSrc: 源PDU参数指针
  284. // pDst: 目标PDU串指针
  285. // 返回: 目标PDU串长度
  286. int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst)
  287. {
  288. int nLength; // 内部用的串长度
  289. int nDstLength; // 目标PDU串长度
  290. unsigned char buf[256]; // 内部用的缓冲区
  291. // SMSC地址信息段
  292. nLength = strlen(pSrc->SCA); // SMSC地址字符串的长度
  293. buf[0] = (char)((nLength & 1) == 0 ? nLength : nLength + 1) / 2 + 1; // SMSC地址信息长度
  294. buf[1] = 0x91; // 固定: 用国际格式号码
  295. nDstLength = gsmBytes2String(buf, pDst, 2); // 转换2个字节到目标PDU串
  296. nDstLength += gsmInvertNumbers(pSrc->SCA, &pDst[nDstLength], nLength); // 转换SMSC号码到目标PDU串
  297. // TPDU段基本参数、目标地址等
  298. nLength = strlen(pSrc->TPA); // TP-DA地址字符串的长度
  299. buf[0] = 0x11; // 是发送短信(TP-MTI=01),TP-VP用相对格式(TP-VPF=10)
  300. buf[1] = 0; // TP-MR=0
  301. buf[2] = (char)nLength; // 目标地址数字个数(TP-DA地址字符串真实长度)
  302. buf[3] = 0x91; // 固定: 用国际格式号码
  303. nDstLength += gsmBytes2String(buf, &pDst[nDstLength], 4); // 转换4个字节到目标PDU串
  304. nDstLength += gsmInvertNumbers(pSrc->TPA, &pDst[nDstLength], nLength); // 转换TP-DA到目标PDU串
  305. // TPDU段协议标识、编码方式、用户信息等
  306. nLength = strlen(pSrc->TP_UD); // 用户信息字符串的长度
  307. buf[0] = pSrc->TP_PID; // 协议标识(TP-PID)
  308. buf[1] = pSrc->TP_DCS; // 用户信息编码方式(TP-DCS)
  309. //? buf[2] = 0; // 有效期(TP-VP)为5分钟
  310. //? buf[2] = 197; // 有效期(TP-VP)为5周
  311. buf[2] = 167; // 有效期(TP-VP)为5周
  312. if(pSrc->TP_DCS == GSM_7BIT)
  313. {
  314. // 7-bit编码方式
  315. buf[3] = nLength; // 编码前长度
  316. nLength = gsmEncode7bit(pSrc->TP_UD, &buf[4], nLength+1) + 4; // 转换TP-DA到目标PDU串
  317. }
  318. else if(pSrc->TP_DCS == GSM_UCS2)
  319. {
  320. // UCS2编码方式
  321. buf[3] = gsmEncodeUcs2(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串
  322. nLength = buf[3] + 4; // nLength等于该段数据长度
  323. }
  324. else
  325. {
  326. // 8-bit编码方式
  327. buf[3] = gsmEncode8bit(pSrc->TP_UD, &buf[4], nLength); // 转换TP-DA到目标PDU串
  328. nLength = buf[3] + 4; // nLength等于该段数据长度
  329. }
  330. nDstLength += gsmBytes2String(buf, &pDst[nDstLength], nLength); // 转换该段数据到目标PDU串
  331. // 返回目标字符串长度
  332. return nDstLength;
  333. }
  334. // PDU解码,用于接收、阅读短消息
  335. // pSrc: 源PDU串指针
  336. // pDst: 目标PDU参数指针
  337. // 返回: 用户信息串长度
  338. int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst)
  339. {
  340. int nDstLength; // 目标PDU串长度
  341. unsigned char tmp; // 内部用的临时字节变量
  342. unsigned char buf[256]; // 内部用的缓冲区
  343. // SMSC地址信息段
  344. gsmString2Bytes(pSrc, &tmp, 2); // 取长度
  345. tmp = (tmp - 1) * 2; // SMSC号码串长度
  346. pSrc += 4; // 指针后移,忽略了SMSC地址格式
  347. gsmSerializeNumbers(pSrc, pDst->SCA, tmp); // 转换SMSC号码到目标PDU串
  348. pSrc += tmp; // 指针后移
  349. // TPDU段基本参数、回复地址等
  350. gsmString2Bytes(pSrc, &tmp, 2); // 取基本参数
  351. pSrc += 2; // 指针后移
  352. //?if(tmp & 0x80)
  353. //?{
  354. // 包含回复地址,取回复地址信息
  355. gsmString2Bytes(pSrc, &tmp, 2); // 取长度
  356. if(tmp & 1) tmp += 1; // 调整奇偶性
  357. pSrc += 4; // 指针后移,忽略了回复地址(TP-RA)格式
  358. gsmSerializeNumbers(pSrc, pDst->TPA, tmp); // 取TP-RA号码
  359. pSrc += tmp; // 指针后移
  360. //?}
  361. // TPDU段协议标识、编码方式、用户信息等
  362. gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_PID, 2); // 取协议标识(TP-PID)
  363. pSrc += 2; // 指针后移
  364. gsmString2Bytes(pSrc, (unsigned char*)&pDst->TP_DCS, 2); // 取编码方式(TP-DCS)
  365. pSrc += 2; // 指针后移
  366. gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14); // 服务时间戳字符串(TP_SCTS)
  367. pSrc += 14; // 指针后移
  368. gsmString2Bytes(pSrc, &tmp, 2); // 用户信息长度(TP-UDL)
  369. pSrc += 2; // 指针后移
  370. if(pDst->TP_DCS == GSM_7BIT)
  371. {
  372. // 7-bit解码
  373. nDstLength = gsmString2Bytes(pSrc, buf, tmp & 7 ? (int)tmp * 7 / 4 + 2 : (int)tmp * 7 / 4); // 格式转换
  374. gsmDecode7bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
  375. nDstLength = tmp;
  376. }
  377. else if(pDst->TP_DCS == GSM_UCS2)
  378. {
  379. // UCS2解码
  380. nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换
  381. nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
  382. }
  383. else
  384. {
  385. // 8-bit解码
  386. nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2); // 格式转换
  387. nDstLength = gsmDecode8bit(buf, pDst->TP_UD, nDstLength); // 转换到TP-DU
  388. }
  389. // 返回目标字符串长度
  390. return nDstLength;
  391. }
  392. // 发送短消息
  393. // pSrc: 源PDU参数指针
  394. BOOL gsmSendMessage(const SM_PARAM* pSrc)
  395. {
  396.     int nPduLength; // PDU串长度
  397.     unsigned char nSmscLength; // SMSC串长度
  398.     int nLength; // 串口收到的数据长度
  399.     //?char cmd[16]; // 命令串
  400. //?char ans[128]; // 应答串
  401.     char pdu[512]; // PDU串    
  402. char cmd[128]; // 命令串
  403.     char ans[1024]; // 应答串
  404.     if(pSrc->mode == 1)//文本模式
  405.     {
  406. //显示文本格式参数
  407.         sprintf(cmd, "AT+CSDH=1rn");    // 生成命令
  408. WriteComm(cmd, strlen(cmd)); // 输出命令串
  409. memset(ans, 0, 1024);
  410. Sleep(1000);
  411. nLength = ReadComm(ans, 1024); // 读应答数据
  412.         sprintf(cmd, "AT+CSMP=17,167,0,0rn");   //设置在TEXT模式下条件参数
  413.         WriteComm(cmd, strlen(cmd)); // 输出命令串
  414. memset(ans, 0, 1024);
  415. Sleep(1000);
  416. nLength = ReadComm(ans, 1024); // 读应答数据
  417. //使用文本模式
  418. sprintf(cmd, "AT+CMGF=1rn");    // 生成命令
  419. WriteComm(cmd, strlen(cmd)); // 输出命令串
  420. memset(ans, 0, 1024);
  421. Sleep(1000);
  422. nLength = ReadComm(ans, 1024); // 读应答数据
  423. //发送消息
  424. sprintf(cmd, "AT+CMGS=%srn", &pSrc->TPA[2]);        // 生成命令
  425. WriteComm(cmd, strlen(cmd));                     // 输出命令串
  426. memset(ans, 0, 1024);
  427. Sleep(1000);
  428. nLength = ReadComm(ans, 1024);                     // 读应答数据
  429.        sprintf(cmd, "%s%s", pSrc->TP_UD, "x01a");     // 生成命令
  430. //? char cmd1[128];
  431. //? sprintf(cmd1, "%s%s", pSrc->TP_UD, "x01a");     // 生成命令
  432. //? strcat(cmd,cmd1);
  433. WriteComm(cmd, strlen(cmd));                 // 输出命令串
  434. memset(ans, 0, 1024);
  435. Sleep(1000);
  436. nLength = ReadComm(ans, 1024);                 // 读应答数据
  437.         if((nLength > 0) && (strstr(ans, "ERROR") == NULL))
  438. {
  439. return TRUE;
  440. }
  441.     }
  442.     else if(pSrc->mode == 0)//PDU模式
  443.     {
  444.         sprintf(cmd, "AT+CMGF=0rn");    // 生成命令
  445. WriteComm(cmd, strlen(cmd)); // 输出命令串
  446. memset(ans, 0, 1024);
  447. Sleep(1000);
  448. nLength = ReadComm(ans, 1024); // 读应答数据
  449.         nPduLength = gsmEncodePdu(pSrc, pdu); // 根据PDU参数,编码PDU串
  450. strcat(pdu, "x01a"); // 以Ctrl-Z结束
  451. gsmString2Bytes(pdu, &nSmscLength, 2); // 取PDU串中的SMSC信息长度
  452. nSmscLength++; // 加上长度字节本身
  453. // 命令中的长度,不包括SMSC信息长度,以数据字节计
  454. sprintf(cmd, "AT+CMGS=%drn", nPduLength / 2 - nSmscLength); // 生成命令
  455. WriteComm(cmd, strlen(cmd)); // 先输出命令串
  456. memset(ans, 0, 1024);
  457. //? Sleep(1000);
  458. nLength = ReadComm(ans, 1024); // 读应答数据
  459.         // 根据能否找到"rn> "决定成功与否
  460. if((nLength == 15) && (strncmp(&ans[11], "rn> ", 4) == 0))
  461. {
  462. WriteComm(pdu, strlen(pdu)); // 得到肯定回答,继续输出PDU串
  463.             memset(ans, 0, 1024);
  464. //? Sleep(1000);
  465. nLength = ReadComm(ans, 1024); // 读应答数据
  466. // 根据能否找到"+CMS ERROR"决定成功与否
  467. //? if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
  468. if((nLength > 0) && (strstr(ans, "ERROR") == NULL))
  469. {
  470. return TRUE;
  471. }
  472. }
  473.     }
  474.     return FALSE;
  475. }
  476. // 读取短消息
  477. // 用+CMGL代替+CMGR,可一次性读出全部短消息
  478. // pMsg: 短消息缓冲区,必须足够大
  479. // 返回: 短消息条数
  480. int gsmReadMessage(SM_PARAM* pMsg)
  481. {
  482. int nLength; // 串口收到的数据长度
  483. int nMsg; // 短消息计数值
  484. char* ptr; // 内部用的数据指针
  485. char cmd[128];         // 命令串
  486. char ans[4096]; // 应答串
  487. nMsg = 0;
  488. ptr = ans;
  489. /*
  490. for(int i=1; i<=255; i++)
  491. {
  492. gsmDeleteMessage(i);
  493. }
  494. */
  495. //使用PDU模式
  496.     sprintf(cmd, "AT+CMGF=0rn");    // 生成命令
  497. WriteComm(cmd, strlen(cmd)); // 输出命令串
  498. memset(ans, 0, 4096);
  499. Sleep(1000);
  500. nLength = ReadComm(ans, 4096); // 读应答数据
  501. //查询消息
  502. /*
  503. sprintf(cmd, "AT+CMGR=%drn", byIndex); // 生成命令
  504. byIndex++;
  505. if(byIndex > 30)
  506. {
  507. byIndex = 0;
  508. }
  509. */
  510. //?sprintf(cmd, "AT+CMGR=20rn"); // 生成命令
  511. //?sprintf(cmd, "AT+CMGR=21rn"); // 生成命令
  512. //?sprintf(cmd, "AT+CMGR=22rn"); // 生成命令
  513. //?sprintf(cmd, "AT+CMGR=23rn"); // 生成命令
  514. //?sprintf(cmd, "AT+CMGR=24rn"); // 生成命令
  515. //? sprintf(cmd, "AT+CMGR=25rn"); // 生成命令
  516. //? sprintf(cmd, "AT+CMGR=26rn"); // 生成命令
  517. //? sprintf(cmd, "AT+CMGR=27rn"); // 生成命令
  518. //? sprintf(cmd, "AT+CMGR=28rn"); // 生成命令
  519. sprintf(cmd, "AT+CMGL=1rn"); // 已接受但已读消息
  520. WriteComm(cmd, strlen(cmd)); // 输出命令串
  521. memset(ans, 0, 4096);
  522. Sleep(1000);
  523. nLength = ReadComm(ans, 4096); // 读应答数据
  524. ptr = ans;
  525. // 根据能否找到"+CMS ERROR"决定成功与否
  526. //? if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
  527. if((nLength > 0) && (strstr(ans, "ERROR") == NULL))
  528. {
  529. // 循环读取每一条短消息, 以"+CMGL:"开头
  530. while((ptr = strstr(ptr, "+CMGL:")) != NULL)
  531. //? if((ptr = strstr(ptr, "+CMGL:")) != NULL)
  532. //? while((ptr = strstr(ptr, "+CMGR:")) != NULL)
  533. {
  534. ptr += 6; // 跳过"+CMGL:"
  535. sscanf(ptr, "%d", &pMsg->index); // 读取序号
  536. ptr = strstr(ptr, "rn"); // 找下一行
  537. ptr += 2; // 跳过"rn"
  538. gsmDecodePdu(ptr, pMsg); // PDU串解码
  539. pMsg++; // 准备读下一条短消息
  540. nMsg++; // 短消息计数加1
  541. }
  542. }
  543. sprintf(cmd, "AT+CMGL=0rn"); // 已接受但未读消息
  544. WriteComm(cmd, strlen(cmd)); // 输出命令串
  545. memset(ans, 0, 4096);
  546. Sleep(1000);
  547. nLength = ReadComm(ans, 4096); // 读应答数据
  548. ptr = ans;
  549. // 根据能否找到"+CMS ERROR"决定成功与否
  550. //? if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
  551. if((nLength > 0) && (strstr(ans, "ERROR") == NULL))
  552. {
  553. // 循环读取每一条短消息, 以"+CMGL:"开头
  554. while((ptr = strstr(ptr, "+CMGL:")) != NULL)
  555. //? if((ptr = strstr(ptr, "+CMGL:")) != NULL)
  556. //? while((ptr = strstr(ptr, "+CMGR:")) != NULL)
  557. {
  558. ptr += 6; // 跳过"+CMGL:"
  559. sscanf(ptr, "%d", &pMsg->index); // 读取序号
  560. ptr = strstr(ptr, "rn"); // 找下一行
  561. ptr += 2; // 跳过"rn"
  562. gsmDecodePdu(ptr, pMsg); // PDU串解码
  563. pMsg++; // 准备读下一条短消息
  564. nMsg++; // 短消息计数加1
  565. }
  566. }
  567. return nMsg;
  568. }
  569. // 删除短消息
  570. // index: 短消息序号,从1开始
  571. BOOL gsmDeleteMessage(const int index)
  572. {
  573. int nLength; // 串口收到的数据长度
  574. char cmd[128]; // 命令串
  575. char ans[1024]; // 应答串
  576. //使用PDU模式
  577.     sprintf(cmd, "AT+CMGF=0rn");    // 生成命令
  578. WriteComm(cmd, strlen(cmd)); // 输出命令串
  579. memset(ans, 0, 1024);
  580. Sleep(1000);
  581. nLength = ReadComm(ans, 1024); // 读应答数据
  582. //删除消息
  583. sprintf(cmd, "AT+CMGD=%drn", index); // 生成命令
  584. // 输出命令串
  585. WriteComm(cmd, strlen(cmd));
  586. // 读应答数据
  587. memset(ans, 0, 1024);
  588. Sleep(1000);
  589. nLength = ReadComm(ans, 1024);
  590. // 根据能否找到"+CMS ERROR"决定成功与否
  591. //? if(nLength > 0 && strncmp(ans, "+CMS ERROR", 10) != 0)
  592. if((nLength > 0) && (strstr(ans, "ERROR") == NULL))
  593. {
  594. return TRUE; //删除短消息成功
  595. }
  596. return FALSE; //删除短消息失败
  597. }