昨天簡單完成瞭解碼部分,今天加入編碼部分(同一個類中)。方式和編碼部分類似,利用屬性對欄位訪問的特點,把解碼程式寫在屬性訪問部分。解碼的函數只需讀取這些屬性值即可完成PDU解碼工作。
手機或簡訊貓接收到的PDU字串包含SCA、PDU-Type、OA、PID、DCS、SCTS、UDL、UD八個部分,每個部分包含對應欄位和屬性,欄位中儲存PDU格式編碼對應段的字串(函數先把對應字串存入對應欄位),屬性讀取過程寫入代碼,讀取的值即為解碼後的資料(簡訊內容、手機號碼等)。
從PDU擷取資訊需讀出(解碼)四部分:SCA、OA、SCTS、UD,以下分別對其講解。
有關收到資訊PDU格式解析參考:
簡訊貓軟體的實現(C#)<三>PDU格式簡訊解析
樣本PDU串:從15050850677收到一條簡訊,內容“你好”。
0891683110402505F0240BA15150800576F7000801112081600423044F60597D
- SCA(短Message Service中心)部分解碼:
欄位:serviceCenterAddress;屬性:ServiceCenterAddress。
解碼時,先把SCA部分PDU串(0891683110402505F0)寫入欄位serviceCenterAddress。屬性訪問器get部分完成解碼工作。get部分代碼:
1: get
2: {
3: int len = Convert.ToInt32(serviceCenterAddress.Substring(0, 2)); //擷取SCA長度
4: string result = serviceCenterAddress.Substring(4, len - 4); //去掉起頭部分
5: //ParityChange函數見上一篇的編碼
6: result = ParityChange(result); //奇偶互換
7: result = result.TrimEnd('F', 'f'); //去掉結尾F
8: return result;
9: }
這樣,讀取ServiceCenterAddress屬性即可得到短訊息中心地址。程式可讀取樣本訊息中心:8613010452500
欄位:originatorAddress;屬性:OriginatorAddress。
解碼時,先把OA部分PDU串(0BA15150800576F7)寫入欄位originatorAddress。同樣,從屬性讀取到的即為發送方的手機號碼。
對應get訪問器代碼:
1: get
2: {
3: int len = Convert.ToInt32(originatorAddress.Substring(0, 2),16); //十六進位字串轉為整形資料
4: string result = string.Empty;
5: if (len % 2 == 1) //號碼長度是奇數,長度加1 編碼時加了F
6: {
7: len++;
8: }
9: result = originatorAddress.Substring(4, len); //去迴轉部
10: result = ParityChange(result).TrimEnd('F', 'f'); //奇偶互換,並去掉結尾F
11:
12: return result;
13: }
這樣,讀取OriginatorAddress屬性即可得到短訊息中心地址。程式可讀取樣本訊息中心:15050850677
欄位:serviceCenterTimeStamp;屬性:ServiceCenterTimeStamp。
解碼時,先把SCTS部分PDU串(01112081600423)寫入欄位serviceCenterTimeStamp。同樣,從屬性讀取到的即為訊息中心收到資訊的時間。
對應get訪問器代碼:
1: get
2: {
3: string result = ParityChange(serviceCenterTimeStamp); //奇偶互換
4: result = "20" + result.Substring(0, 12); //年加開始的“20”
5:
6: return result;
7: }
讀取ServiceCenterTimeStamp屬性即可得到時間字串:20101102180640 代表:2010-11-02 18:06:44
1: get
2: {
3: int len = Convert.ToInt32(userDataLenghth, 16) * 2;
4: string result = string.Empty;
5: //四個一組,每組譯為一個USC2字元
6: for (int i = 0; i < len; i += 4)
7: {
8: string temp = userData.Substring(i , 4);
9:
10: int byte1 = Convert.ToInt16(temp, 16);
11:
12: result += ((char)byte1).ToString();
13: }
14:
15: return result;
16: }
訪問UserData即得段內容。樣本可得到簡訊內容:“你好”。
解碼程式須將對應PDu編碼的值賦給對應欄位,然後讀取各個屬性即可完成解碼:
1: /// <summary>
2: /// 完成手機或簡訊貓收到PDU格式簡訊的解碼 暫時僅支援中文編碼
3: /// 未用DCS部分
4: /// </summary>
5: /// <param name="strPDU">簡訊PDU字串</param>
6: /// <param name="msgCenter">短Message Service中心 輸出</param>
7: /// <param name="phone">發送方手機號碼 輸出</param>
8: /// <param name="msg">簡訊內容 輸出</param>
9: /// <param name="time">時間字串 輸出</param>
10: public void PDUDecoder(string strPDU, out string msgCenter, out string phone, out string msg, out string time)
11: {
12: int lenSCA = Convert.ToInt32(strPDU.Substring(0, 2), 16) * 2 + 2; //短訊息中心占長度
13: serviceCenterAddress = strPDU.Substring(0, lenSCA);
14:
15: int lenOA = Convert.ToInt32(strPDU.Substring(lenSCA + 2, 2),16); //OA佔用長度
16: if (lenOA % 2 == 1) //奇數則加1 F位
17: {
18: lenOA++;
19: }
20: lenOA += 4; //加號碼編碼的頭部長度
21: originatorAddress = strPDU.Substring(lenSCA + 2, lenOA);
22:
23: serviceCenterTimeStamp = strPDU.Substring(lenSCA + lenOA + 6, 14);
24:
25: userDataLenghth = strPDU.Substring(lenSCA + lenOA + 20, 2);
26: int lenUD = Convert.ToInt32(userDataLenghth, 16) * 2;
27: userData = strPDU.Substring(lenSCA + lenOA + 22, lenUD);
28:
29: msgCenter = ServiceCenterAddress;
30: phone = OriginatorAddress;
31: msg = UserData;
32: time = ServiceCenterTimeStamp;
33: }
調用程式pe.PDUDecoder("0891683110402505F0240BA15150800576F7000801112081600423044F60597D", out s1, out s2, out s3, out s4);(pe:PDUEncoding pe=new PDUEncoding();)
輸出:
s1:8613010452500
s2:15050850677
s2:你好
s3:20101102180640
成功!
至此編碼部分簡單完成。
實現的比較簡單,沒有實現7bit及8bit部分編解碼。有興趣可以下載附件,自己添加。
附件:工程專案檔