摘要:在介紹SMS無線數據傳輸與MC35i模塊的基礎上,解析SMS無線數據傳輸格式,采用標準C語言實現。結果表明采用C語言實現的基于MC35i模塊實現電表的集中監測系統具有系統結構明晰、成本低、性能可靠等優點,適合于在近似領域推廣使用。
關鍵詞:SMS;無線監測;MC35i
中圖分類號:TP393 文獻標示碼:A文章編號:1009-3044(2009)36-10594-03
The Design and Implement of the Wireless MM System Based on the MC35i Module
CHEN Jun1, CHEN Lin2, WU Wen-ping2
(1.Xinjiang Branch of Armed Police, Urumqi 830063, China; 2.Unit 69046, Urumqi 830001, China)
Abstract: The format of the SMS wireless data transport is explained with the C language based on the introduction of the wireless Data transport and MC35i module. The result is reached that the centralized MM system with the C language based on the the MC35i module has the advantages of clear system structure, low expensive, high stability and so on. The system can be used on similar areas.
Key words: SMS; Wireless MM; MC35i
1 概述
本模塊采用MC35i通過RS-232接口實現,數據傳輸上采用SMS方式進行。
SMS是由ESTI制定的一個規范,在收發短信上,按照時間先后有三種模式:Block模式、Text模式、PDU模式。在我國由于需要支持中文,基本都采用PDU模式。PDU模式使用三種編碼,分別是7bit、8bit、16bit。16bit編碼也叫UCS2編碼或Unicode編碼,要支持中文必須用UCS2編碼方式,最多一次可發送70字符。
2 SMS數據格式解析
以一組收發數據為例,介紹SMS數據格式。
假設要發送“你好”到手機“13812345678”,發送的PDU數據串為:08 91 683108701305F0 11 00 0D 91 683118325476F8 00 08 00 04 4F60597D。其數據格式解析如下:
08:短消息服務中心地址長度,8個字節。
91:短消息服務中心號碼類型。
683108701305F0:短消息服務中心號碼,8613800731500。
11:文件頭部。
00:信息參考。
0D:被叫號碼長度13位。
91:被叫號碼類型。
683118325476F8:被叫號碼8613812345678。
00:協議標示。
08:數據編碼方案。
00:有效期。
04:用戶數據長度。
4F60597D:用戶數據“你好”的Unicode編碼。
假設接收到一組PDU串,08 91 683108701305F0 24 0B A1 3118325476F8 00 08 50303211509220 04 4F60597D。分析如下:
08:短消息服務中心地址長度,8個字節。
91:短消息服務中心號碼類型。
683108701305F0:短消息服務中心號碼8613800731500。
24:文件頭字節。
0B:被叫號碼長度,11位。
A1:被叫號碼類型。
3118325476F8:被叫號碼13812345678。
00:協議標示。
08:數據編碼方案。
50303211509220:時間戳。
04:用戶數據長度。
4F60597D:用戶數據“你好”的Unicode編碼。
3 SMS編程實現
SMS信息必須經過字符到字節以及其相反的轉換。其轉換函數為:int gsmString2Bytes(const char* pSrc,unsigned char* pDst,int nSrcLength),pSrc為源字符串指針,nSrcLength源字符串長度,pDst為目標數據指針;int gsmBytes2String(const unsigned char* pSrc,char* pDst,int nSrcLength),pSrc為源數據指針,nSrcLength源數據長度,pDst為目標字符串指針。代碼略。
UCS2編碼函數gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)和UCS2解碼函數int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength)部分代碼如下所示:
UCS2編碼,輸入:pSrc - 源字符串指針,nSrcLength - 源字符串長度,輸出:pDst - 目標編碼串指針,返回:目標編碼串長度
int gsmEncodeUcs2(const char* pSrc, unsigned char* pDst, int nSrcLength)
{int nDstLength;// UNICODE寬字符數目
WCHAR wchar[128];// UNICODE串緩沖區
// 字符串-->UNICODE串
nDstLength = MultiByteToWideChar(CP_ACP, 0, pSrc, nSrcLength, wchar, 128);
// 高低字節對調,輸出
for(int i=0; i {*pDst++ = wchar[i] >> 8;// 先輸出高位字節 *pDst++ = wchar[i] 0xff;// 后輸出低位字節 } // 返回目標編碼串長度 return nDstLength * 2; } UCS2解碼,輸入:pSrc - 源編碼串指針,nSrcLength -源編碼串長度,輸出:pDst -目標字符串指針,返回:目標字符串長度 int gsmDecodeUcs2(const unsigned char* pSrc, char* pDst, int nSrcLength) {int nDstLength;// UNICODE寬字符數目 WCHAR wchar[128];// UNICODE串緩沖區 // 高低字節對調,拼成UNICODE for(int i=0; i {wchar[i] = *pSrc++ << 8;// 先高位字節 wchar[i] |= *pSrc++;// 后低位字節 } // UNICODE串-->字符串 nDstLength = WideCharToMultiByte(CP_ACP, 0, wchar, nSrcLength/2, pDst, 160, NULL, NULL); // 輸出字符串加個結束符 pDst[nDstLength] = '\\0'; // 返回目標字符串長度 return nDstLength; } 在PDU編碼解碼函數中,還要用到如下數據順序轉換函數:1、正常順序的字符串轉換為兩兩顛倒的字符串,若長度為奇數,補'F'湊成偶數。輸入:pSrc - 源字符串指針,nSrcLength - 源字符串長度,輸出:pDst - 目標字符串指針,返回:目標字符串長度,int gsmInvertNumbers(const char* pSrc, char* pDst, int nSrcLength)。2、兩兩顛倒的字符串轉換為正常順序的字符串,輸入: pSrc - 源字符串指針, nSrcLength - 源字符串長度,輸出:pDst - 目標字符串指針,返回:目標字符串長度,int gsmSerializeNumbers(const char* pSrc, char* pDst, int nSrcLength)。 PDU編碼,用于編制、發送短消息,輸入:pSrc - 源PDU參數指針,輸出:pDst - 目標PDU串指針,返回:目標PDU串長度 int gsmEncodePdu(const SM_PARAM* pSrc, char* pDst) {int nLength;// 內部用的串長度 int nDstLength;// 目標PDU串長度 unsigned char buf[256];// 內部用的緩沖區 // SMSC地址信息段 nLength = strlen(pSrc->SCA);// SMSC地址字符串的長度 buf[0] = (char)((nLength 1) == 0 ? nLength : nLength + 1) / 2 + 1;//SMSC地址信息長度 buf[1] = 0x91;// 固定: 用國際格式號碼 nDstLength = gsmBytes2String(buf, pDst, 2);// 轉換2個字節到目標PDU串 nDstLength += gsmInvertNumbers(pSrc->SCA, pDst[nDstLength], nLength);// 轉換SMSC號碼到目標PDU串 // TPDU段基本參數、目標地址等 nLength = strlen(pSrc->TPA);// TP-DA地址字符串的長度 buf[0] = 0x11;// 是發送短信(TP-MTI=01),TP-VP用相對格式(TP-VPF=10) buf[1] = 0;// TP-MR=0 buf[2] = (char)nLength; // 目標地址數字個數(TP-DA地址字符串真實長度) buf[3] = 0x91;// 固定: 用國際格式號碼 nDstLength += gsmBytes2String(buf, pDst[nDstLength], 4);//轉換4字節到目標PDU串 nDstLength += gsmInvertNumbers(pSrc->TPA, pDst[nDstLength], nLength); //轉換TP-DA到目標PDU串 // TPDU段協議標識、編碼方式、用戶信息等 nLength = strlen(pSrc->TP_UD);// 用戶信息字符串的長度 buf[0] = pSrc->TP_PID;// 協議標識(TP-PID) buf[1] = pSrc->TP_DCS;// 用戶信息編碼方式(TP-DCS) buf[2] = 0;// 有效期(TP-VP)為5分鐘 // UCS2編碼方式 buf[3] = gsmEncodeUcs2(pSrc->TP_UD, buf[4], nLength); // 轉換TP-DA到目標PDU串 nLength = buf[3] + 4;// nLength等于該段數據長度 nDstLength += gsmBytes2String(buf, pDst[nDstLength], nLength); // 轉換該段數據到目標PDU串 // 返回目標字符串長度 return nDstLength; } PDU解碼,用于接收、閱讀短消息,輸入:pSrc - 源PDU串指針,輸出: pDst - 目標PDU參數指針,返回:用戶信息串長度。 int gsmDecodePdu(const char* pSrc, SM_PARAM* pDst) {int nDstLength;// 目標PDU串長度 unsigned char tmp;// 內部用的臨時字節變量 unsigned char buf[256];// 內部用的緩沖區 // SMSC地址信息段 gsmString2Bytes(pSrc, tmp, 2);// 取長度 tmp = (tmp - 1) * 2;// SMSC號碼串長度 pSrc += 4;// 指針后移,忽略了SMSC地址格式 gsmSerializeNumbers(pSrc, pDst->SCA, tmp);// 轉換SMSC號碼到目標PDU串 pSrc += tmp;// 指針后移 // TPDU段基本參數 gsmString2Bytes(pSrc, tmp, 2);// 取基本參數 pSrc += 2;// 指針后移 // 取回復號碼 gsmString2Bytes(pSrc, tmp, 2);// 取長度 if(tmp 1) tmp += 1;// 調整奇偶性 pSrc += 4;// 指針后移,忽略了回復地址(TP-RA)格式 gsmSerializeNumbers(pSrc, pDst->TPA, tmp);// 取TP-RA號碼 pSrc += tmp;// 指針后移 // TPDU段協議標識、編碼方式、用戶信息等 gsmString2Bytes(pSrc, (unsigned char*)pDst->TP_PID, 2);// 取協議標識(TP-PID) pSrc += 2;// 指針后移 gsmString2Bytes(pSrc, (unsigned char*)pDst->TP_DCS, 2);// 取編碼方式(TP-DCS) pSrc += 2;// 指針后移 gsmSerializeNumbers(pSrc, pDst->TP_SCTS, 14);// 服務時間戳字符串(TP_SCTS) pSrc += 14;// 指針后移 gsmString2Bytes(pSrc, tmp, 2);// 用戶信息長度(TP-UDL) pSrc += 2;// 指針后移 // UCS2解碼 nDstLength = gsmString2Bytes(pSrc, buf, tmp * 2);// 格式轉換 nDstLength = gsmDecodeUcs2(buf, pDst->TP_UD, nDstLength);// 轉換到TP-DU // 返回目標字符串長度 return nDstLength; } 整體程序的編制就是調用以上函數,從而實現讀取顯示SMS信息和發送SMS信息的功能。 4 結論 該程序在電表遠程監測應用,功能基本完善,性能可靠,由于程序采用標準C語言實現,可以不用改變移植到嵌入式系統使用,具有很好的通用性。 參考文獻: [1] 高守傳,聶云銘,鄭靜.Visual C++開發指南[M].北京:人民郵電出版社,2007. [2] 胡志坤,秦業,鄢鋒.Visual C++通信編程工程實例精解[M].北京:機械工業出版社,2007. [3] 龔建偉,熊光明.Visual C++/Turbo C 串口通信編程實踐[M].2版.北京:電子工業出版社,2007. [4] 賽奎春,高春艷,李俊民.Visual Basic 工程應用與項目實踐[M].北京:機械工業出版社,2007.