我发表在Codeproject上的文章,直接粘贴过来了。此文被评为Prize Winner |
IntroductionHi, we're back again to generate the PDU code while we have known . But at first, sorry for the late publishing of my PDU encoder as I was busy for a long time. These classes are written for my own program, but they can be easily implemented in your project. And this tiny demo program can be used to get the correct PDU code from your setting so as to convince your AT command test work. I'll show how to do this later in this article. BackgroundIt was last year that I did some work on SMS and EMS PDU code encoding and decoding. And I wrote my PDU Decoder to help me get the PDU strings returned from the mobile. That article has been read by more than twenty thousands people all over the world. Some one pointed out the bugs hidden in my decoder and they helped me to improve my decoder. But my encoder, although I have done it in February this year, I have it shown to the world in the hot summer. I'm sorry again for this. Like the decoder, this encoder also was created according to GSM 03.40. But I use 3GPP TS 23.040 V6.5.0 for reference. The link to these documents can be found at the end of this article. OK. Here we start, I'll introduce my encoder step by step and hope it will give you a hand when designing an encoder. The architecture of this encoderThe most important parts, The Please note that I have set a group of This class implements one function We know that EMS is composed of several SMSs. Each SMS has From figure 2 you can see an How it really works?In order to demonstrate and explain the details about how this encoder works, let us open my demo program in Visual Studio. First, please find function Then build and start this program. Fill the blanks according to the picture shown at the beginning of this article and then click Get PDU Code button. The program stops at the checkpoint. Let's trace down the code. It first check the coding scheme and user data length to ensure if EMS will be used. Please note that the Please trace into Then, according to the type of Function detailsLet's look into the detail of the Public Overridable Function GetSMSPDUCode() Function GetSMSPDUCode() As String Dim PDUCode As String 'Check User Data Length If TP_DCS = ENUM_TP_DCS.DefaultAlphabet Then If TP_UD.Length > 280 Then Throw New Exception("User Data is TOO LONG for SMS") End If If TP_DCS = ENUM_TP_DCS.UCS2 Then If TP_UD.Length > 280 Then Throw New Exception("User Data is TOO LONG for SMS") End If 'Make PDUCode PDUCode = SC_Number PDUCode += FirstOctet() PDUCode += Format(TP_MR, "X2") PDUCode += TP_DA PDUCode += Format(TP_PID, "X2") PDUCode += Format(TP_DCS, "X2") PDUCode += Format(TP_VP, "X2") PDUCode += Format(TP_UDL, "X2") PDUCode += TP_UD Return PDUCodeEnd Function This function first checks the coding and determines if the length of user data is longer than the maximum size. Then every prepared PDU code is added to the variable Here are also two core functions: But Let us take a look at Public Function GetEMSPDUCode() Function GetEMSPDUCode() As String() Select Case tp_dcs Case ENUM_TP_DCS.UCS2 TotalMessages = (TP_UD.Length / 4) \ 66 + ((TP_UD.Length / 4 Mod 66) = 0) Case ENUM_TP_DCS.DefaultAlphabet TotalMessages = (tp_ud.Length \ 266) - ((tp_ud.Length Mod 266) = 0) End Select Dim Result(TotalMessages) As String Dim tmpTP_UD As String Dim i As Integer TP_UDHI = 2 ^ 6 Dim Reference As Integer = Rnd(1) * 65536 '16bit Reference Number 'See 3GPP Document For i = 0 To TotalMessages Select Case tp_dcs Case ENUM_TP_DCS.UCS2 tmpTP_UD = Mid(TP_UD, i * 66 * 4 + 1, 66 * 4) 'When TP_UDL is odd, the max length of an Unicode string 'in PDU code is 66 Charactor. 'See [3GPP TS 23.040 V6.5.0 (2004-09] 9.2.3.24.1 Case ENUM_TP_DCS.DefaultAlphabet tmpTP_UD = Mid(tp_ud, i * 133 * 2 + 1, 133 * 2) End Select Result(i) = SC_Number Result(i) += FirstOctet() Result(i) += Format(TP_MR, "X2") Result(i) += TP_DA Result(i) += Format(TP_PID, "X2") Result(i) += Format(TP_DCS, "X2") Result(i) += Format(TP_VP, "X2") If tp_dcs = ENUM_TP_DCS.UCS2 Then TP_UDL = tmpTP_UD.Length / 2 + 6 + 1 '6:IE End If If tp_dcs = ENUM_TP_DCS.DefaultAlphabet Then TP_UDL = Fix((tmpTP_UD.Length + 7 * 2) * 4 / 7) '6:length of IE End If Result(i) += Format(TP_UDL, "X2") Result(i) += "060804" 'TP_UDHL and some of Concatenated message Result(i) += Format(Reference, "X4") Result(i) += Format(TotalMessages + 1, "X2") Result(i) += Format(i + 1, "X2") Result(i) += tmpTP_UD NextReturn Result As you can see, the above code is similar to Let us send an SMS!I'm happy to show you that it's so easy to send an SMS to a certain number. In this demonstration, I'll show you how to get my account information using my PDU Encoder, Microsoft HyperTerminal and my PDU Decoder. My phone is Siemens M55, and note some AT commands may not work on your phone or GSM Modem. First let's produce an SMS PDU Code. Start my program, and fill the Number, Options and User Data as shown in Figure 3. Then press "Get PDU Code" button to get PDU code and length for AT which will be used later. Press "Copy to Clipboard" to copy PDU Code to clipboard. Start HyperTerminal program. I give this session a name "Send SMS Demo" and I choose COM3 which is the port my phone is connected to. Then follow these instructions: <CR> equals to Enter key of your keyboard. Step 1: Type AT<CR> and ensure the device is ready. Step 2: Type AT+CPMS="MT","MT","MT"<CR> to set preferred memory storage. Here I set it to Mobile Terminal. Step 3: Type AT+CMGS=12<CR>. The number 12. Step 4: Paste PDU code to HyperTerminal and press CTRL+Z to end the input. At this time your phone will send SMS to the number you specified. Here my destination number is 1861 from which I can get my account info. Step 5: After a while I can see my phone receive a status report and my account info. Step 6: Type AT+CMGL=1 to list the incoming message. Here it returns: +CMGL: 1,1,,166 0891683108200805F0066104818116505013612455005050136124550000FFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +CMGL: 2,1,,83 0891683108200805F00404A1811600085050136164350044672C67085DF24F7F75288BDD8D39003A 00350031002E00340037002052694F5998845B586B3E003A00350039002E0033003600204F1860E0 003A00370039002E00350031 Step 7: Use my PDU Decoder to decode above PDU codes. Note there're some Chinese characters. SMS_STATUS_REPORT Send time:2005-5-31 16:42:55 Receive time:2005-5-31 16:42:55 Status:Success SMS_RECEIVED From:1861 Time:2005-5-31 16:46:53 ±¾ÔÂÒÑʹÓû°·Ñ:51.47 Ê£ÓàÔ¤´æ¿î:59.36 ÓÅ»Ý:79.51 You can see that it's an easy task to manually send and receive SMSs though my tools and HyperTerminal. Be glad to use them to ease your test work! ReferenceNoteYou can use and modify my code freely. If you find some bugs or improve my code, please contact me. This will help me to fix bugs and also it will help a lot of people all over the world! Thanks for reading my article and thanks again for using my code! Contact me
|