Hi Habr. In this article I would like to share my experience with the GSM modem, or rather the experience of sending SMS messages. The implementation of the Delphi program for sending SMS messages, as well as reading and deleting incoming / outgoing messages from the modem will be described below. In my case it was a HUAWEI modem from MTS. All who are interested, I ask under the cat.
The birth of an idea
It all started with the fact that in one small chain of stores there was a need to daily inform the authorities about the revenue for each store per day. The central office accumulates sales information, and then you need to bring it to the head. Gen.dir. (customer) is a very busy person, and as a director he needs to receive timely data on the revenue of stores, the Internet is sometimes unavailable, and his mobile phone is always at hand, so it was decided to send him a text message to his phone for each store readable form.
Sample SMS:
08.11.2011
1. A, 123045 .
2. B, 134520 .
3. C, 215403 .
...
08.11.2011
1. A, 123045 .
2. B, 134520 .
3. C, 215403 .
...
;
As it turned out later, this is not all that is needed, but more on that later.
At first, it was proposed to send SMS via the gate, of which there are now a great many. But the customer immediately rejected this offer for security reasons, because the data on daily revenue is a rather confidential thing. Then it was decided to send SMS just from the phone connected to the computer via USB cable, and as a result, instead of the phone, a USB modem was used which had been lying around for quite a while.
')
Where to begin
Of course, I had to work with the COM port, but I hadn’t been able to communicate with the modem by means of AT commands. AT teams are of course quite a lot, but everything turned out to be much simpler than I expected, since for our purpose it took only 5 teams:
AT + CMGF - sets the operation mode: 0-digital or 1-text. This command will be called first, depends on the format of subsequent commands and modem responses.
AT + CMGS - sending a message, the format of the parameter strongly depends on the mode (ie, from the previous command).
AT + CMGL - reading messages from a modem, one of five values ​​can be passed as a parameter, it should be noted that depending on the mode (AT + CMGF) digital or string values ​​should be sent:

AT + CMGD - delete one message from the modem, send the message number as a parameter.
AT + CMGR - reading a single message from a modem, also transmitting the message number.
First results
After several hours (trial / error) I found out that sending an SMS message from a modem is not much more difficult than doing it from a regular mobile phone. As mentioned above, to send an SMS, use the “AT + CMGS” command. And so, I opened hyperterm, connected to a modem (via COM port), and sent the following commands to the port:
AT+CMGF=1 [Enter] AT+CMGS=+79261234567 [Enter] hello habr, this is test message [Ctrl+Z]
An example of the same in Delphi:
procedure SendSMS(AComPort: integer; AMsg: String; ANumTel: String); var hFile: THandle; procedure WriteStr(AStr: String);
Voila, and pocket device reported the expected event.
But alas, the positive emotions that I had at the time of this success did not last long, or rather, until the moment when it was discovered that the Russian text is much more complicated. Firstly, to send messages in Russian, you need to switch the mode from text to digital (AT + CMGF = 0), and secondly, the message itself must be sent in UCS2 encoding. And if with the first problems at least, then with the second it was necessary to tinker.
Text encoding in UCS and back (again in Delphi):
function UCSToAnsi(AStr: AnsiString): AnsiString; function Convert(ACnvStr: AnsiString): AnsiChar; var j: integer; begin j := StrToIntDef('$'+ACnvStr, 0); case j of 1040..1103: j := j - 848; 1105: j := 184; end; Result := Chr(j); end; var c, i: integer; begin Result := ''; c := Length(AStr) div 4; for i := 0 to c - 1 do Result := Result + Convert(Copy(AStr, i*4+1, 4)); end; function AnsiToUCS(AStr: AnsiString): AnsiString; function Convert(AChar: AnsiChar): AnsiString; var j: integer; begin Result := ''; j := ord(AChar); case j of 192..255: j := j + 848; 184: j := 1105; end; Result := IntToHex(j, 4) end; var c, i: integer; begin Result := ''; c := Length(AStr); for i := 1 to c do Result := Result + Convert(AStr[i]); end;
I will not say that everything turned out immediately and easily, but still it turned out. If earlier I sent to the modem:
AT+CMGF=1 [Enter] AT+CMGS=+79261234567 [Enter] hello habr, this is test message [Ctrl+Z]
then in order to send a message in Russian you will need to send:
AT+CMGF=0 [Enter] AT+CMGS=84 [Enter] 0011000B919762214365F70008C146043F04400438043204350442002004450430043 10440002C0020044D0442043E00200442043504410442043E0432043E043500200441 043E043E043104490435043D04380435 [Ctrl+Z]
First, switching the mode (to digital), then the length of the message is sent (84), and the last line contains: phone number, message text and various settings (such as SMS center number, whether to save the message with the recipient, etc.).
Delphi example:
procedure SendSMSMessage(AComPort: integer; AMsg: String; ANumTel: String); var Lng, i: Integer; LRead, LText, LMes, LTel, ANum: String; hFile: THandle; procedure WriteStr(AStr: String); var LWrited: Cardinal; begin
Idea development
To say that I was happy when the long-awaited Russian text came to the mobile, instead of “krakozyabr”, means to say nothing. The next day I added the main part of the program, and everything seems to be. Messages with data about the revenue are sent to the customer’s phone, it seems that life was a success, but it was not there. Somewhere in a week, the customer asked to finalize the application, namely, to make it so that after he received an SMS with the text:
08.11.2011
1. A, 123045 .
2. B, 134520 .
3. C, 215403 .
...
he could, in response to this message, send the store number and receive a new message, but with more detailed information on the indicated store.
Well, in general, the logic is simple: the program should store the last sent "report" on all stores and read incoming messages as soon as a message appears with conditional text (for example, "shop = 12"), pull out the store number from there, look in the last message sent what was under this number and send detailed information on this store (unfortunately at the moment the customer has not decided on the format and content of the “detailed report”, so there is nothing to give as an example). To implement the above logic, the modem requires: read the SMS from the memory, delete the SMS from the memory (so as not to accumulate). To read messages, I used the AT + CMGR and AT + CMGL commands (a brief description was given earlier). Reading all messages will look like:
AT+CMGF=1 [Enter] AT+CMGL="ALL" [Enter] +CMGL: 6,"REC READ","778467",,"11/09/03,18:49:40+16" 007700770077002E006D00740073002E00720075 +CMGL: 7,"REC READ","+79261234567",,"11/10/18,18:38:00+16" 04220435044104420020043F044004380435043C043000200073006D0073002004410 43E043E043104490435043D04380439002100200421043C04410020043D043D043D04 3004340430003F0021003F00210028002D005F002D00290020 [Enter]
Everything is easier than before. Each message consists of 2 lines, the first contains data about the message (such as: from whom, when, message number), and the second message text itself (again in UCS encoding, the UCSToAnsi function was cited above). Reading a single message is carried out as:
AT+CMGF=1 [Enter] AT+CMGR=7 [Enter] +CMGR: "REC READ","+79261234567",,"11/10/18,18:38:00+16" 04220435044104420020043F044004380435043C043000200073006D0073002004410 43E043E043104490435043D04380439002100200421043C04410020043D043D043D04 3004340430003F0021003F00210028002D005F002D00290020 [Enter]
Similarly, the removal of messages occurs. If, for example, in my case, send the command AT + CMGD = 7, then with the next AT + CMGL = "ALL" I will not see message number 7, since it will be removed.
Conclusion
And so, the basic commands for working with SMS messages through a GSM modem were disassembled, sending, reading, deleting messages was considered. Lastly, I would like to note that the scope of such use of SMS messages is quite wide (especially because it is possible to organize two-way communication). For example: user sends SMS, modem accepts, our program reads, performs some actions based on the text of the message and sends the result to the user. Or vice versa: some event occurs on the PC, and the program sends the user a message about this event. Good luck with your experiments, thank you!
Sources test program
here .