As discussed in an earlier post, you can connect to a GSM modem and use AT commands to send SMS messages. There are 2 possible methods: text mode and PDU mode.
It turns out that most devices support PDU mode, but only a few support text mode.
Here is an example AT command to submit a PDU:
AT+CMGS=24<crlf> > 0001000B915121551532F400000CC8F79D9C07E54F61363B04<Ctrl-Z>
|1 octet||00||This indicates that we don’t supply an SMSC number. The one that is configured in the device will be used.|
|1 octet||01||PDU type and options. This is a one octet bit-field that controls:
The most significant of these is the UDH indicator. More on these fields in a future post.
|1 octet||00||Our message reference. In case there is an error delivering the message, this number will be part of the error response so we can see which message failed.|
|1 octet||0B||Size of the destination telephone number (in digits)|
|1 octet||91||International numbering plan. This indicates that what follows is an international telephone number.|
|6 octets||5121551532f4||Telephone number. This is the destination phone number is a reverse nibble encoding:
So ‘915121551532f4’ translates to +1 512 555 1234.
|1 octet||00||Protocol identifier. This can be used to indicate a higher-level protocol. ‘0’ indicates no higher-level protocol.|
|1 octet||00||This represents the Data Coding Scheme. A ‘0’ indicates that the messages are encoded in the GSM 7 (default) alphabet.
‘There are other (fun) uses for this byte that I’ll show in a future post.
|1 octet||0c||Payload size in septets (characters). This field is also called User Data Length.|
|The payload, also known as User Data. In this case, it is just GSM encoded text. This is the tricky encoding:
This particular string represents “Howdy y’all!”
The GSM-7 payload encoding is hard to explain, I’ll show how it works with the example above. Each character is represented by the bits with the same color:
|C8||1||1||0||0||1||0||0||0||1001000 = ‘H’|
|F7||1||1||1||1||0||1||1||1||1101111 = ‘o’|
|9D||1||0||0||1||1||1||0||1||1110111 = ‘w’|
|9C||1||0||0||1||1||1||0||0||1100100 = ‘d’|
|07||0||0||0||0||0||1||1||1||1111001 = ‘y’|
|E5||1||1||1||0||0||1||0||1||0100000 = ‘ ‘ (space)|
|4F||0||1||0||0||1||1||1||1||1111001 = ‘y’,0100111 = ‘‘’ (quote)|
|61||0||1||1||0||0||0||0||1||1100001 = ‘a’|
|36||0||0||1||1||0||1||1||0||1101100 = ‘l’|
|04||0||0||0||0||0||1||0||0||0100001 = ‘!’|
So every septet is added by first inserting the least significant bits in the unused most significant bits of the octet, then the rest of the bits (the most significant bits) are inserted in the next octet’s least significant bits. Confused? It becomes a lot clearer if you realize the octets are transmitted right to left. I have written articles (with code) on how to convert to the GSM-7 character set and another on how to pack GSM-7 septets.
The precise specification of the PDUs is given in 3GPP TS 23.040. The spec for the AT commands is in 3GPP TS 27.005. The GSM-7 character set is described in 3GPP TS 23.038.
There is little literature on these topics, but I found the following book has a pretty good introduction to the general topic and explores some SIM-based scenarios: