标题:
手机短信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