手机短信PDU编码与解码

来源:互联网 发布:eric 6 python 编辑:程序博客网 时间:2024/05/04 04:44
  1. //将短信转化为待发送编码   
  2. //AT+CMGS=021   
  3. //0011000D91683176116125F0000801064F60597DFF01   
  4.   
  5. //021 TPDU长度   
  6. //PDU:SMSC地址+TPDU   
  7.   
  8. //00 服务中心号码(SMSC地址)   
  9. //11    
  10. //00 TP-MR(TP-Message-Reference)   
  11. //0D91683176116125F0 TP-DA 收信人手机号码   
  12. //00 TP-PID(TP-Protocol-Identifier)   
  13. //08 TP-DCS(TP-Data-Coding-Scheme)   
  14. //01 TP-VP(TP-Validy-Period)   
  15. //06 TP-UDL 短信长度   
  16. //4F60597DFF01 TP-UD 你好!   
  17.   
  18. //服务中心号码、收信人手机号码格式   
  19. //0D Address-Length 地址长度   
  20. //91 Type-of-Address 地址类型   
  21. //  Bits 7   
  22. //       1   
  23. //  Bits 6 5 4   
  24. //       0 0 0 Unknown1   
  25. //       0 0 1 International number2   
  26. //       0 1 0 National number3   
  27. //       1 1 1 Reserved for extension   
  28. //  Bits 3 2 1 0   
  29. //       0 0 0 0 Unknown   
  30. //       0 0 0 1 ISDN/telephone numbering plan (E.164/E.163)   
  31. //       1 1 1 1 Reserved for extension   
  32.   
  33. //683176116125F0 号码   
  34.   
  35. bool CMobile::EncodeSMS(CSMS sms, CPDUSMS & pdu)   
  36. {   
  37.     try  
  38.     {   
  39.         //收信人手机号码============   
  40.         CString sTo = sms.m_sNumber;   
  41.         CString sTA; //类型:国际/国内   
  42.            
  43.         sTo.TrimLeft("+");   
  44.         //国际号码   
  45.         if(sTo.Left(2) == "86")   
  46.         {   
  47.             sTA = "91";   
  48.         }   
  49.         else if((sTo.GetLength() == 11) && sTo.Left(2) == "13")   
  50.         {   
  51.             sTo = "86" + sTo;   
  52.             sTA = "91";   
  53.         }   
  54.         //国内号码   
  55.         else  
  56.         {   
  57.             sTA = "A1";   
  58.         }   
  59.            
  60.         //号码长度   
  61.         int nAL = sTo.GetLength();   
  62.         //补偶   
  63.         if(nAL % 2)   
  64.             sTo += "F";   
  65.         //号码两两对换   
  66.            
  67.         sTo = Swap2(sTo);   
  68.            
  69.         CString sTPDA;   
  70.         sTPDA.Format("%02X%s%s", nAL, sTA, sTo);   
  71.            
  72.         //短信===================   
  73.         //将消息转换成UNICODE编码   
  74.            
  75.         CString sSMS = String2HEX(sms.m_sBody);   
  76.            
  77.         //普通   
  78.         if(!sms.m_nClass)   
  79.         {   
  80.             pdu.m_sPDUBody.Format(_T("001100%s000801%02X%s"),     
  81.                 sTPDA, sSMS.GetLength() / 2, sSMS);   
  82.                
  83.         }   
  84.         //免提   
  85.         else  
  86.         {   
  87.             pdu.m_sPDUBody.Format(_T("001100%s001801%02X%s"),     
  88.                 sTPDA, sSMS.GetLength() / 2, sSMS);   
  89.         }   
  90.            
  91.         pdu.m_sHeader.Format(_T("AT+CMGS=%03d"), pdu.m_sPDUBody.GetLength() / 2 - 1);   
  92.     }   
  93.     catch(CException * e)   
  94.     {   
  95.         e->Delete();   
  96.         return false;   
  97.     }   
  98.     return true;   
  99. }   
  100.   
  101. //将存储的短信转化为可读的SMS   
  102. bool CMobile::DecodeSMS(CPDUSMS pdu, CSMS & sms)   
  103. {   
  104.     /*  
  105.     已读 +8613683196704 03-01-01 11:07:21 元旦快乐   
  106.     +CMGL: 6,1,,28  
  107.     089168[6/6]  
  108.     3108100005F0[12/18]服务中心号码  
  109.     04[2/20]  
  110.     0D[2/22]电话号码长度  
  111.     91[2/24]  
  112.     683186136907F4电话号码[14]  
  113.     24[2]  
  114.     08[2]编码方式,08为16bit,04为8bit,00为7bit  
  115.     301010117012时间[12]  
  116.     23[2]短信长度  
  117.     08514365E65FEB4E50短信内容  
  118.     */  
  119.     /*  
  120.     未发送  
  121.     +CMGL: 4,2,,35  
  122.     089168[6/6]  
  123.     3108100005F0[12/18]服务中心号码  
  124.     ===============================  
  125.     11480180F000[12/30]  
  126.     08[2/32]编码方式  
  127.     AD[2/34]  
  128.     1A[2/36]短信长度  
  129.     短信内容  
  130.     */  
  131.     try  
  132.     {   
  133.         char cBuffer[512];   
  134.            
  135.         strcpy(cBuffer, pdu.m_sHeader);   
  136.            
  137.         int nLength;   
  138.         sscanf(cBuffer + 7, "%d,%d,,%d", &sms.m_nIndex, &sms.m_nType, &nLength);   
  139.            
  140.         //读取PDU内容   
  141.            
  142.         strcpy(cBuffer, pdu.m_sPDUBody);   
  143.            
  144.         //读取服务中心   
  145.         CString sc;   
  146.         sc = pdu.m_sPDUBody.Mid(6, 12);   
  147.         sc = Swap2(sc);   
  148.         sc.TrimRight("F");   
  149.            
  150.         sms.m_sSC = sc;   
  151.            
  152.         //发送方手机号码长度   
  153.         int nUserLength;   
  154.         int nBegin;   
  155.         //手机编码方式   
  156.         CString sFormat;   
  157.            
  158.         if(sms.m_nType != CMobile::smsUnsent)   
  159.         {   
  160.             //读取发送方手机号码   
  161.             sscanf(cBuffer + 20, "%02X", &nUserLength);   
  162.                
  163.             //有可能补偶   
  164.             if(nUserLength % 2)   
  165.                 nUserLength ++;   
  166.                
  167.             CString sNumber = pdu.m_sPDUBody.Mid(24, nUserLength);   
  168.             sNumber = Swap2(sNumber);   
  169.             sNumber.TrimRight("F");   
  170.             sNumber.TrimLeft("86");   
  171.                
  172.             sms.m_sNumber = sNumber;   
  173.                
  174.             //读取编码格式   
  175.             nBegin = 24 + nUserLength + 2;   
  176.             sFormat = pdu.m_sPDUBody.Mid(nBegin, 2);   
  177.                
  178.             //读取时间   
  179.             nBegin += 2;   
  180.             CString sTime = pdu.m_sPDUBody.Mid(nBegin, 12);   
  181.             sTime = Swap2(sTime);   
  182.                
  183.             int nYear, nMonth, nDay, nHour, nMinute, nSecond;   
  184.             sscanf(sTime, "%02d%02d%02d%02d%02d%2d", &nYear,    
  185.                 &nMonth, &nDay, &nHour, &nMinute, &nSecond);   
  186.                
  187.             CTime oTime(nYear + 2000, nMonth, nDay, nHour, nMinute, nSecond);   
  188.             sms.m_nTime = oTime.GetTime();   
  189.                
  190.             //准备读取短信长度   
  191.             nBegin += 14;   
  192.         }   
  193.            
  194.         //未发送短信   
  195.         else  
  196.         {   
  197.             sms.m_sNumber = "(本地)";   
  198.             sms.m_nTime = 0;   
  199.                
  200.             //读取编码格式   
  201.             nBegin = 30;   
  202.             sFormat = pdu.m_sPDUBody.Mid(nBegin, 2);   
  203.             //准备读取短信长度   
  204.             nBegin += 4;   
  205.         }   
  206.            
  207.            
  208.         //读取短信长度   
  209.         sscanf(cBuffer + nBegin, "%02X", &nLength);   
  210.            
  211.         //读取短信   
  212.         nBegin += 2;   
  213.            
  214.         int nBits = 16;   
  215.         if(sFormat == "00")   
  216.             nBits = 7;   
  217.         if(sFormat == "04")   
  218.             nBits = 8;   
  219.            
  220.         sms.m_sBody = HEX2String(cBuffer + nBegin, nLength, nBits);   
  221.     }   
  222.     catch(CException * e)   
  223.     {   
  224.         e->Delete();   
  225.         return false;   
  226.     }   
  227.     return true;   
  228. }   
  229.   
  230. CString CMobile::Swap2(CString sSource)   
  231. {   
  232.     CString sSwap = sSource;   
  233.     for(int i = 0; i < sSource.GetLength(); i += 2)   
  234.     {   
  235.         sSwap.SetAt(i, sSource.GetAt(i + 1));   
  236.         sSwap.SetAt(i + 1, sSource.GetAt(i));   
  237.     }   
  238.     return sSwap;   
  239. }   
  240.   
  241. CString CMobile::HEX2String(char *pSource, int nLength, int nBits)   
  242. {   
  243.     CString sDecode;   
  244.     switch(nBits)   
  245.     {   
  246.         //B7 to ANSI   
  247.     case 7:   
  248.         {   
  249.             unsigned char nch = 0;   
  250.             for(int i = 0; i < nLength; i++)   
  251.             {   
  252.                 unsigned char ch;   
  253.                 sscanf(pSource + i * 2, "%02X", &ch);   
  254.                 sDecode += ((char)((unsigned char)(ch << (i % 7 + 1)) >> 1) + nch);   
  255.                 nch = ((unsigned char)(ch >> (7 - i % 7)));   
  256.                    
  257.                 if(i % 7 == 6)   
  258.                 {   
  259.                     sDecode += nch;   
  260.                 }   
  261.             }   
  262.             break;   
  263.         }   
  264.     case 8:   
  265.         {   
  266.             for(int i = 0; i < nLength; i++)   
  267.             {   
  268.                 unsigned char ch;   
  269.                 sscanf(pSource + i * 2, "%02X", &ch);   
  270.                 sDecode += ch;   
  271.             }   
  272.             break;   
  273.         }   
  274.         //UNICODE   
  275.     default:   
  276.         {   
  277.             wchar_t pwc[200];   
  278.                
  279.             for(int i = 0; i < nLength  / 2; i++)   
  280.             {   
  281.                 sscanf(pSource + i * 4, "%04X", pwc + i);   
  282.             }   
  283.                
  284.             pwc[i] = wchar_t('/0');   
  285.                
  286.             _bstr_t bstrSMS(pwc);   
  287.             sDecode = (char *)bstrSMS;   
  288.             break;   
  289.         }   
  290.     }   
  291.        
  292.     return sDecode;   
  293. }   
  294.   
  295. CString CMobile::String2HEX(CString sSource)   
  296. {   
  297.     _bstr_t bstrSMS(sSource);   
  298.     int nSMSLength = bstrSMS.length();   
  299.        
  300.     wchar_t * pwc = (wchar_t *)bstrSMS;   
  301.        
  302.     CString sEncode;   
  303.     for(int i = 0; i < nSMSLength; i++)   
  304.     {   
  305.         CString sHex;   
  306.         sHex.Format(_T("%04X"), pwc[i]);   
  307.         sEncode += sHex;   
  308.     }   
  309.        
  310.     return sEncode;   
  311. }  
原创粉丝点击