Board logo

标题: 手机短信PDU编码与解码 [打印本页]

作者: 梦景    时间: 2011-10-17 23:19     标题: 手机短信PDU编码与解码

//将短信转化为待发送编码
//AT+CMGS=021
//0011000D91683176116125F0000801064F60597DFF01

//021 TPDU长度
//PDU:SMSC地址+TPDU

//00 服务中心号码(SMSC地址)
//11
//00 TP-MR(TP-Message-Reference)
//0D91683176116125F0 TP-DA 收信人手机号码
//00 TP-PID(TP-Protocol-Identifier)
//08 TP-DCS(TP-Data-Coding-Scheme)
//01 TP-VP(TP-Validy-Period)
//06 TP-UDL 短信长度
//4F60597DFF01 TP-UD 你好!

//服务中心号码、收信人手机号码格式
//0D Address-Length 地址长度
//91 Type-of-Address 地址类型
// Bits 7
//    1
// Bits 6 5 4
//    0 0 0 Unknown1
//    0 0 1 International number2
//    0 1 0 National number3
//    1 1 1 Reserved for extension
// Bits 3 2 1 0
//    0 0 0 0 Unknown
//    0 0 0 1 ISDN/telephone numbering plan (E.164/E.163)
//    1 1 1 1 Reserved for extension

//683176116125F0 号码

bool CMobile::EncodeSMS(CSMS sms, CPDUSMS & pdu)
{
try
{
   //收信人手机号码============
   CString sTo = sms.m_sNumber;
   CString sTA; //类型:国际/国内

   sTo.TrimLeft("+");
   //国际号码
   if(sTo.Left(2) == "86")
   {
    sTA = "91";
   }
   else if((sTo.GetLength() == 11) && sTo.Left(2) == "13")
   {
    sTo = "86" + sTo;
    sTA = "91";
   }
   //国内号码
   else
   {
    sTA = "A1";
   }

   //号码长度
   int nAL = sTo.GetLength();
   //补偶
   if(nAL % 2)
    sTo += "F";
   //号码两两对换

   sTo = Swap2(sTo);

   CString sTPDA;
   sTPDA.Format("%02X%s%s", nAL, sTA, sTo);

   //短信===================
   //将消息转换成UNICODE编码

   CString sSMS = String2HEX(sms.m_sBody);

   //普通
   if(!sms.m_nClass)
   {
    pdu.m_sPDUBody.Format(_T("001100%s000801%02X%s"),  
     sTPDA, sSMS.GetLength() / 2, sSMS);

   }
   //免提
   else
   {
    pdu.m_sPDUBody.Format(_T("001100%s001801%02X%s"),  
     sTPDA, sSMS.GetLength() / 2, sSMS);
   }

   pdu.m_sHeader.Format(_T("AT+CMGS=%03d"), pdu.m_sPDUBody.GetLength() / 2 - 1);
}
catch(CException * e)
{
   e->Delete();
   return false;
}
return true;
}

//将存储的短信转化为可读的SMS
bool CMobile:ecodeSMS(CPDUSMS pdu, CSMS & sms)
{
/*
已读 +8613683196704 03-01-01 11:07:21 元旦快乐
+CMGL: 6,1,,28
089168[6/6]
3108100005F0[12/18]服务中心号码
04[2/20]
0D[2/22]电话号码长度
91[2/24]
683186136907F4电话号码[14]
24[2]
08[2]编码方式,08为16bit,04为8bit,00为7bit
301010117012时间[12]
23[2]短信长度
08514365E65FEB4E50短信内容
*/
/*
未发送
+CMGL: 4,2,,35
089168[6/6]
3108100005F0[12/18]服务中心号码
===============================
11480180F000[12/30]
08[2/32]编码方式
AD[2/34]
1A[2/36]短信长度
短信内容
*/
try
{
   char cBuffer[512];

   strcpy(cBuffer, pdu.m_sHeader);

   int nLength;
   sscanf(cBuffer + 7, "%d,%d,,%d", &sms.m_nIndex, &sms.m_nType, &nLength);

   //读取PDU内容

   strcpy(cBuffer, pdu.m_sPDUBody);

   //读取服务中心
   CString sc;
   sc = pdu.m_sPDUBody.Mid(6, 12);
   sc = Swap2(sc);
   sc.TrimRight("F");

   sms.m_sSC = sc;

   //发送方手机号码长度
   int nUserLength;
   int nBegin;
   //手机编码方式
   CString sFormat;

   if(sms.m_nType != CMobile::smsUnsent)
   {
    //读取发送方手机号码
    sscanf(cBuffer + 20, "%02X", &nUserLength);

    //有可能补偶
    if(nUserLength % 2)
     nUserLength ++;

    CString sNumber = pdu.m_sPDUBody.Mid(24, nUserLength);
    sNumber = Swap2(sNumber);
    sNumber.TrimRight("F");
    sNumber.TrimLeft("86");

    sms.m_sNumber = sNumber;

    //读取编码格式
    nBegin = 24 + nUserLength + 2;
    sFormat = pdu.m_sPDUBody.Mid(nBegin, 2);

    //读取时间
    nBegin += 2;
    CString sTime = pdu.m_sPDUBody.Mid(nBegin, 12);
    sTime = Swap2(sTime);

    int nYear, nMonth, nDay, nHour, nMinute, nSecond;
    sscanf(sTime, "%02d%02d%02d%02d%02d%2d", &nYear,
     &nMonth, &nDay, &nHour, &nMinute, &nSecond);

    CTime oTime(nYear + 2000, nMonth, nDay, nHour, nMinute, nSecond);
    sms.m_nTime = oTime.GetTime();

    //准备读取短信长度
    nBegin += 14;
   }

   //未发送短信
   else
   {
    sms.m_sNumber = "(本地)";
    sms.m_nTime = 0;

    //读取编码格式
    nBegin = 30;
    sFormat = pdu.m_sPDUBody.Mid(nBegin, 2);
    //准备读取短信长度
    nBegin += 4;
   }


   //读取短信长度
   sscanf(cBuffer + nBegin, "%02X", &nLength);

   //读取短信
   nBegin += 2;

   int nBits = 16;
   if(sFormat == "00")
    nBits = 7;
   if(sFormat == "04")
    nBits = 8;

   sms.m_sBody = HEX2String(cBuffer + nBegin, nLength, nBits);
}
catch(CException * e)
{
   e->Delete();
   return false;
}
return true;
}

CString CMobile::Swap2(CString sSource)
{
CString sSwap = sSource;
for(int i = 0; i < sSource.GetLength(); i += 2)
{
   sSwap.SetAt(i, sSource.GetAt(i + 1));
   sSwap.SetAt(i + 1, sSource.GetAt(i));
}
return sSwap;
}

CString CMobile::HEX2String(char *pSource, int nLength, int nBits)
{
CString sDecode;
switch(nBits)
{
   //B7 to ANSI
case 7:
   {
    unsigned char nch = 0;
    for(int i = 0; i < nLength; i++)
    {
     unsigned char ch;
     sscanf(pSource + i * 2, "%02X", &ch);
     sDecode += ((char)((unsigned char)(ch << (i % 7 + 1)) >> 1) + nch);
     nch = ((unsigned char)(ch >> (7 - i % 7)));

     if(i % 7 == 6)
     {
      sDecode += nch;
     }
    }
    break;
   }
case 8:
   {
    for(int i = 0; i < nLength; i++)
    {
     unsigned char ch;
     sscanf(pSource + i * 2, "%02X", &ch);
     sDecode += ch;
    }
    break;
   }
   //UNICODE
default:
   {
    wchar_t pwc[200];

    for(int i = 0; i < nLength   / 2; i++)
    {
     sscanf(pSource + i * 4, "%04X", pwc + i);
    }

    pwc[i] = wchar_t('\0');

    _bstr_t bstrSMS(pwc);
    sDecode = (char *)bstrSMS;
    break;
   }
}

return sDecode;
}

CString CMobile::String2HEX(CString sSource)
{
_bstr_t bstrSMS(sSource);
int nSMSLength = bstrSMS.length();

wchar_t * pwc = (wchar_t *)bstrSMS;

CString sEncode;
for(int i = 0; i < nSMSLength; i++)
{
   CString sHex;
   sHex.Format(_T("%04X"), pwc[i]);
   sEncode += sHex;
}

return sEncode;
}




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0