Click here to Skip to main content
12,826,151 members (27,833 online)
Click here to Skip to main content
Add your own
alternative version


122 bookmarked
Posted 31 May 2005

Using VB.NET to Encode SMS and EMS

, 31 May 2005 CPOL
Rate this:
Please Sign up or sign in to vote.
An article on SMS and EMS Encoders.


Hi, we're back again to generate the PDU code while we have known how to decode PDU code. 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.


It 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 encoder

The most important parts, public class SMS and ConcatenatedShortMessage, are under the namespace SMS and Encoder. Figure 1 shows this.

The SMS class is foundation of SMS and EMS. It has the basic elements required for SMS. Figure 2 shows you the SMS class. I'll explain how this class works in detail later.

Please note that I have set a group of protected variables prefixed with TP. These variables' names can be easily found in 3GPP or GSM documents. And there're also a set of properties, e.g. ServiceCenterNumber, TP_Status_Report_Request. When you set these properties, they prepare the correct PDU string and store them in protected variables for future use.

This class implements one function GetSMSPDUCode() to generate PDU code. This function simply joins the protected variables in a certain order to get a PDU code. Another function FirstOctet() contains the first octet data in PDU code. We can use it in some particular occasions.

We know that EMS is composed of several SMSs. Each SMS has TP_UserDataHeader set which is different from simple SMS. We can easily inherent from SMS to create the base of EMS. And please note the Concatenated Short Message is only part of EMS, which allows you to send messages containing more than 160 ASCII characters or 70 Unicode characters. You can inherent the SMS class and build another portion of EMS.

From figure 2 you can see an Integer variable named TotalMessages. It tells you how many SMS PDU Codes are generated. And note the GetEMSPDUCode(), it returns a number of SMS PDU codes. I'll explain this later.

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 GetPDU() in the Form and make a checkpoint. We will trace it down.

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 SMSObject is an object type. It will be blind to a specific type of SMS or EMS. Going down the code, we see it sets ServiceCenterNumber and other properties.

Please trace into ServiceCenterNumber property and you can see it prepares PDU code from your setting. The final result is stored in a protected variable SC_Number. Similar process happen to all the properties.

Then, according to the type of SMSObject, we use GetSMSPDUCode() or GetEMSPDUCode() to get PDU codes.

Function details

Let's look into the detail of the GetSMSPDUCode function:

Public Overridable 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_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 PDUCode
End 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 PDUCode. Note the PDU codes are added by a certain order. So it is an easy task to modify the order or add some more PDU codes simply by changing the order or adding the other PDU codes to PDUCode. This gives my class flexibility and extensibility.

Here are also two core functions: Encode7Bit() and EncodeUCS2(). You can treat UCS2 as Unicode and use AscW function to get Unicode character.

But Encode7Bit is much more complex. In order to ease this encoding, I use several help functions such as BitsToHex, CharTo7Bits and so on. First I convert hex number to binary and join them together, then I split them into 8 bits. Please refer to GSM documents for detailed information about 7 bit encoding.

Let us take a look at GetEMSPDUCode():

Public 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]
            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
Return Result

As you can see, the above code is similar to GetSMSPDUCode(). But you can also see TP_UDHI is set indicating that TP_UDH appears in TP_UD. Note TP_UDL is calculated during the loop process. As I mentioned in my source code, it also has problems treating TP_UDL while the TP_DCS is DefaultAlphabet. To get details on how EMS is created, please refer to 3GPP TS 23.040 V6.5.0.

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
+CMGL: 2,1,,83

Step 7: Use my PDU Decoder to decode above PDU codes. Note there're some Chinese characters.

Send time:2005-5-31 16:42:55 Receive time:2005-5-31 16:42:55 Status:Success
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!



You 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


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Web Developer
China China
I'm a undergraduate student in UESTC in China.
I have being learing computer for more than ten years. And now studying programming and have some software made by myself.
I learned SMS technology and did some work on OBEX, PDU, AT commands, IrDA and so on.
If you have interested in this field, please contact me.
And see more on my web site:

You may also be interested in...


Comments and Discussions

QuestionNeed Help Pin
Humayun Rashed19-Feb-15 5:51
memberHumayun Rashed19-Feb-15 5:51 
QuestionThanks! Pin
JhingLopez14-Jan-12 1:05
memberJhingLopez14-Jan-12 1:05 
GeneralMy vote of 5 Pin
Amir Mehrabi-Jorshary17-Jan-11 23:16
memberAmir Mehrabi-Jorshary17-Jan-11 23:16 
Questionflash sms Pin
ajithamalar4-Jan-11 23:34
memberajithamalar4-Jan-11 23:34 
GeneralFlash SMS Pin
nyt197223-Oct-10 1:39
membernyt197223-Oct-10 1:39 
Generaldatagrid keypress Pin
Rudiana8311-Jun-09 23:53
memberRudiana8311-Jun-09 23:53 
GeneralSend Outgoing SMS on perticular port Pin
Member 35080567-Feb-09 1:32
memberMember 35080567-Feb-09 1:32 
Questionconcatenated SMS used to send long WAP push message Pin
joe_03_8518-Dec-08 19:40
memberjoe_03_8518-Dec-08 19:40 
QuestionHow can i sent long SMS? Pin
Muthuganesh10-Jul-08 21:09
memberMuthuganesh10-Jul-08 21:09 
GeneralSMS Sending Pin
nitin_ion22-May-08 2:08
membernitin_ion22-May-08 2:08 
QuestionHow to send Long SMS or Concated Message using AT Commands Pin
Saeed.39413-Mar-08 0:20
memberSaeed.39413-Mar-08 0:20 
GeneralDTMF Pin
Saeed.39412-Mar-08 20:18
memberSaeed.39412-Mar-08 20:18 
GeneralRe: DTMF Pin
hesicong12-Mar-08 20:36
memberhesicong12-Mar-08 20:36 
GeneralRe: DTMF Pin
Member 339753130-May-08 19:12
memberMember 339753130-May-08 19:12 
GeneralUDH problem Pin
Saeed.39410-Mar-08 23:23
memberSaeed.39410-Mar-08 23:23 
GeneralRe: UDH problem Pin
hesicong11-Mar-08 1:07
memberhesicong11-Mar-08 1:07 
QuestionHow to implement Unicode SMS, multipart SMS and high capacity sending Pin
William Ike8-Mar-08 22:51
memberWilliam Ike8-Mar-08 22:51 
If you don't have a lot of time it could be a good idea to use an SMS gateway,
such as the Ozeki SMS Sending and SMS
receiving Gateway
, because it does a lot things that is very hard to
implement: character conversion to unicode SMS messages, GSM 7 bit, segmentation
and reassembly for multipart SMS messages with 8 bit reference numbering and 16
bit reference numbering, message delivered to network report,
message delivered to handset report, message delivery failed
report, etc. Not to talk about long term upgrade. If you do a system now with
a GSM modem, it might be possible that you will have to upgrade in the long term
to higher capcity IP SMS connection, such as SMPP
sms sending
, UCP sms sending or CIMD2 sms sending. Remember,
a GSM modem can only send 10 SMS meessages per minute, while an IP SMS connection
will allow you to send 3000 or more SMS messages per minute.
AnswerRe: How to implement Unicode SMS, multipart SMS and high capacity sending Pin
hesicong8-Mar-08 22:58
memberhesicong8-Mar-08 22:58 
AnswerRe: How to implement Unicode SMS, multipart SMS and high capacity sending Pin
littlegang10-Jun-08 18:27
memberlittlegang10-Jun-08 18:27 
GeneralSMS Pin
jennina23-Feb-08 22:36
memberjennina23-Feb-08 22:36 
Questionhow to send image with SMS? Pin
Shakeel Mumtaz10-Jun-07 19:38
memberShakeel Mumtaz10-Jun-07 19:38 
QuestionMMS Message Pin
lorenzo76_surfer13-Mar-07 2:21
memberlorenzo76_surfer13-Mar-07 2:21 
AnswerRe: MMS Message Pin
hesicong13-Mar-07 3:53
memberhesicong13-Mar-07 3:53 
GeneralRe: MMS Message Pin
lorenzo76_surfer13-Mar-07 3:58
memberlorenzo76_surfer13-Mar-07 3:58 
GeneralRe: MMS Message Pin
YAKAND2-Dec-08 23:25
memberYAKAND2-Dec-08 23:25 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170326.1 | Last Updated 1 Jun 2005
Article Copyright 2005 by hesicong
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid