You might have been thinking – damn! why does he not post that SMS article as well .. well here it is. Hope you enjoy it.

“How to send a SMS message to a mobile phone using a dial up connection to a gateway.”

Some of you might already know it, but I use to have a Windows 3.1 program and a Win32 library for sending SMS messages from a Windows machine to a GSM cell phone, using gateways provided by the different telecoms.

Due to many factors, I’m not able to keep the work on these programs up to date, and due to the use of (customized) AsyncPro components, I can not make (the full) source public. Instead of providing source, I will try to describe the very simple process of building and sending the messages.

UCP / ERMES / ETS 300 133-3

The protocol used for sending messages via a dial-up link is actually a subset of the ETSI specification ETC 300 133-3[1][2]. This specification covers a protocol that is (was?) a part of the ERMES pager network. In the specifications there is a sub section covering a so-called Universal Computer Protocol (UCP), which is what actually is used for this simple communication.

The protocol is basically a very simple ACK/NAK protocol, where the initiator (you) sends a message and receive a response informing you the request was accepted or not. The initiator does not have to be the one actually dialing up to the service center (or gateway), but in this type of applications this is usually the case.

At this point, you will need to establish a modem (or ISDN) connection to a service center using 8 data bits, No parity and 1 stop bit (8N1). How to do that is outside the scope of this document.

The messages in UCP have the great advantage almost only to consist of readable characters, which make debugging significant easier. There are two control (non readable) characters – the STX (Start of TeXt or 2 hex) and ETX (End of TeXt or 3 hex) characters – which are used to frame each message. When creating a message, each field inside the message is separated with the separator character, the forward slash '/'.

When building messages, all messages will have the following blocks:



The header consist of the following fields:

 TRN   LEN   O/R   OT 
o  TRN - Transaction Number

The transaction number is a unique id generated by the sender. The value must be in the range of 0 to 99. It should be transmitted as two ascii character (e.g. '20').

o  LEN - Length

The length is the total length, in octets (characters), between STX and ETX. This is including the header, the separators and the checksum field (but not including the STX and ETX characters). It should be transmitted as five ascii characters, prepended with zeros as needed (e.g. '00036').

o  O/R - Operation / Result

This is an indication to mark the message as an operation (e.g. a new message being send) or as a Result (e.g. the answer – ACK or NAK – from the other side, telling if the message was accepted or not). It should be transmitted as the single ascii character 'O' or 'R' (upper case).

o  OT - Operation Type

As in any other protocol, UCP can have multiple message formats (or message types). It should be transmitted as two ascii characters (e.g. '30').


The checksum is the 8 LSB (least significant bits) of a simple addition of all octets (note that a message type '30' is two octets with the values 33 hex and 30 hex) following the STX character and until the checksum field. Note that all separators will be included in the checksum, but the STX, checksum and the ETX will not be included.


Before we continue to the message format, let’s look at a simple request for sending the message ‘Hello World’ from ‘87654321’ to ‘12345678’.


We can see from this message, that the transaction number is 01 (I have avoided to use zero, but it’s not said that zero is illegal). Further we can see that the message is 64 octets long – this is excluding STX ([02]) and ETX ([03]) – it’s an operation and the message type is '30'. Finally we see that the checksum have been calculated to be C2 hex or 194.

Before we continue

As always every implementation should be prepared to send certain standard error messages. For me this proved it’s value when the German mobile phone provider Mannesmann (now Arcor) changed their implementation from “rev. 1” to “rev. 2”. Since I responded in the expected fashion with an error message saying that I didn’t recognize the message, they would fall back to “rev. 1” type messages.


An acknowledgement, positive or negative, does always contain the same operation type (OT) and transaction number (TRN) as the message which it’s responding to. The operation type (O/R) is always set to 'R' (for response).

For negative acknowledgements the format is almost always the same. In some cases of “rev. 2” messages, the format is, like the positive acknowledgements, dependant on the incoming message, but the “standard” error message is always the same.

 NAC   EC   SM 
o  NAC - Not acknowledged (Mandatory)

Always the 'N' character

o  EC - Error Code (Mandatory)

This is an error code, transmitted as two ascii characters. The one saving me was '03' – Operation not supported. Two other very interesting ones: '01' – Checksum error and '02' – Syntax error. The rest can be found in the ETSI standard.[1][2]

o  SM - System Message (Optional)

A system message containing alphanumeric letters, encoded as IA5 (see later) characters.[3]

If we look at the following example below we see that it’s a response to the transaction '01', it’s negative and the error code is '03', which is ‘Operation not supported’, and the message have been truncated for display purpose.

 [02]01/00098/R/30/N/03/534D53657276 ... 74797065/0B[03]

Message Transfer Operation (30)

When you want to send a message, you should use the message type '30' called “SMS Message Transfer Operation”.

 AdC   OAdC   AC   NRq   NAd   NPID   DD   DDT   VP   AMsg 
o  AdC - Address Code, Recipient (Mandatory)

This is the phone number of the receiver. Normally this would be the number as you dial it on the phone (note that the number is as the gateway expect to see the number). As an example I can mention the number of a German mobile phone, reached via a Danish gateway. Here you must display the number as ‘00491724504232’. Note that ’00’ is the international access code from Denmark. ’49’ is the Germany international code. ‘172’ is the “area code” (excluding the leading zero) for the German network, and ‘4504232’ is the phone number. If you want to use a French gateway you should most likely use ‘019’ as the international access code from France! Usually you can leave the international stuff away if you want to reach a phone local to the gateway (use ‘01724504232’ if you want to reach the above phone via a German gateway). Note that this number scheme is use all places where we referee to a phone number or address.

Only numeric “characters” are allowed – to ‘+’ is also not allowed!

o  OAdC - Originator Address Code, Sender. (Optional)

This is the phone number of the sender. My experience shows that the providers treat this field transparently, and the number is used on the mobile phone to display the sender (a random code could be used!).

Only numeric “characters”.

o  AC - Authentication Code (Optional)

Leave empty.


o  NRq - Notification Request (Optional).

Empty or ascii '1'. If set to one, the gateway will respond with a notification message, containing a response, from the system, to the request. This message is usually a text string in the language used in the country where they gateway is present. There will be no numeric codes to translate into “local” languages.

o  NAd - Notification Address (Optional)

Leave empty – honestly this is most likely some kind of address where it can reach you with the notification (which you just requested in the previous field), but I have always kept it empty.

Only numeric “characters”.

o  NPID - Notification PID value (Optional)

This should be a value (only numeric characters) that identifies the notification, but unfortunately we don’t get it back with the notification so just leave it empty.

o  DD - Deferred Delivery (Optional)

Empty or ascii '1'. If set to '1' the message will not be delivered right away, but deferred until later (see next field).

o  DDT - Deferred Delivery Time (Optional)

This is the time at which the message should be delivered. The format is 10 ascii numbers in the format YYMMDDhhmm. It can also be left empty.

o  VP - Validity Period (Optional)

This is the time at which the message will expire. Formatted as the Deferred Delivery Time.

o  AMsg - A Message (optional)

Finally the message encoded as IA5 (see later) characters[3].

So this was the message transfer format – let’s look at the previous example:


We already know that '01/00064/O/30/' is the header and '/C2' is the checksum. ‘12345678’ is then the address of the recipient, ‘87654321’ the address of the originator and ‘48656C6C6F20576F726C64’ the message in IA5 format.

So when we now transmit the above message to the gateway, we must way for the gateway to answer with an acknowledgement – positive or negative. The negative format we already know and in this case the positive acknowledgement have the following format.

 ACK   MVP   SM 
o  ACK - Acknowledged (Mandatory)

The ACK field is the letter 'A'.

o  MVP - Modified Validity Period (Optional)

This is time at which the gateway will expire the message, if it’s not delivered before that. The format is the same as the DDT in the Message transfer.

o  SM - System Message

A system message containing alphanumeric letters, encoded as IA5 (see later) characters[3].

This is (almost) enough to send a SMS message, and to know if the message was accepted for delivery of if it was rejected by the gateway. The state machine used for sending, retransmitting etc. is left as an exercise.

Did that person actually receive the message? Often we would like to know a little more about the delivery, so we often use the Notification Request (NRq) in the message transfer. If we set the NRq flag, and the modem/ISDN/serial connection is still available, the gateway will respond with a call input operation.

Call Input Operation (01)

When you receive the call input operation, the message will have the message type ’01’ and the following format.

 AdC   OAdC   AC   MT
o  AdC - Address Code, recipient (Mandatory)

You know, just like on the message transfer.

o  OAdC - Address Code, originator (Optional)

You know, just like on the message transfer (actually the sender of the SMS message and not the sender of the system message).

o  AC - Authentication Code, originator (optional)

Leave empty, just like in the message transfer.

o  MT - Message Type (Mandatory)

The message type following this message header:

'2' mean a numeric message. (NMsg)

'3' a string (AMsg)

'4' a “transparent data message” (NB/TMsg) (never used this)

NMsg is a sequence of numbers.

AMsg is a sequence of alphanumeric letters, encoded as IA5[3].

Let’s look at an alphanumeric example.


The header is '[02]00/00256/O/01/' and the checksum is '/72[03]'. The recipient is ‘12345678’, the originator is ‘00491724504232’, there is no authentication and the message type is '3'. The message itself is an IA5 encoded string.

If the operation isn’t acknowledged, positive or negative, most systems will try for quite a while to retransmit the message, therefore always remember to acknowledge all messages – and the ones you don’t know should be acknowledged negatively with ‘Operation not supported’.

Positive acknowledgement is done with a very simple message

o  ACK - Acknowledge (Mandatory)

The letter ‘A’ to acknowledge the message.

o  SM - System Message (Optional)

A system message encoded as an IA5 string[3].


You have seen this multiple times now, the IA5 encoding of strings. IA5 is defined by ETS 300 133-2[3] appendix B2. It’s a seven bit encoding of letters roughly matching the one of ascii characters. The lower 32 characters in the in the IA5 table is used for country specific characters (and don’t expect all countries to use the same tables!!!). Let’s just make it simple and say that ‘0’ to ‘9’, ‘A’ to ‘Z’ and ‘a’ to ‘z’ are placed identically to where the ascii characters are placed. This result in ‘0’ being equal to ’30 hex’, ‘A’ being equal to ’41 hex’ and finally ‘a’ being equal to ’61 hex’.

When encoding these characters in IA5, the 3 MSB is taken and displayed as an ascii value. For ‘0’ the 3 MSB of the 7 bit value is ‘3’. This rest, the 4 LSB, is ‘0’. This gives the output ’30’ in ascii characters.

If we look at the message type '30' we were sending above, the message string was '48656C6C6F20576F726C64'. Let’s decode that one.

The first two characters is ‘4’ and ‘8’. This gives the hex value ’48’. If ‘A’ is ’41’, ’48’ will be the eights letter … ‘H’. The next to characters is ’65’, which turn out to be fifth lower case letter ‘e’. The complete string can be decoded in this fashion, and much to our surprise the string becomes ‘Hello World’.

Anything else?

This is enough for being able to create, transmit and receive SMS messages via a service center gateway. There are more message types, with more functions declared in both revision one and two. You should especially notice that revision two depend on detecting revision implementations by expecting the implementation to answer with the standard “Operation not supported” NAK message.

Another protocol, called the “Telocator Alphanumeric Protocol”[4], covers basically the same functionality. A large difference between the UCP approach and the TAP approach is the more “protocol like” functionality of UCP and the ability of TAP to run as terminal as well as automatic transfer protocol.


I hope that this will aid in creating applications using SMS as a media. I created the first program as an exercise for myself as well as to fill a hole. Today the hole seems mostly in aiding developers in using the functionality in automated systems, and not so much in human communication. Good luck.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.