[Windows] Send sms using gsm modem Delphi/Lazarus

In previous post i wrote small description how asynchronously work with com port, in this post i gave small list where we can use it.

Today i wanna explain how to send sms if you have GSM modem connected to Com Port using created class and AT commands.

The simpliest way if your GSM modem support text mode (i think you have spend some time to find modem that aint support text mode).

So to send sms we need:

  • Open Com Port where modem plugged in
  • Enable Text mode (write to port command “AT+CMGF=1″, if you you will receive error response that means that you modem does not support text mode)
  • Send SMS:
  1. Send command: write to port AT+CMGS=”cell_number” (cell_number = destination number)
  2. Send sms text: after you send command AT+CMGS=”cell_number” you will receive response “>” then you need to write sms text to port

if you will receive response “OK”, congrats message was sent :)

here small class on delphi that sends sms (inherited from TThread):

unit SmsSender;

interface
uses
//  Windows,
Classes, SysUtils, ComPort, messages, Windows;

const
Steps : array[0..3] of string = (
'ATZ',
'AT+CMGF=',
'>',
'+CMGS');

type

PMessageSet = ^TMessageSet;
TMessageSet = record
Number : string; //without any + symbols (example: 80993294258)
Text : string;
Unicode : boolean; //not implemented in this version
end;

TSmsSender = class(TThread)
private
FTerminate : boolean;
FToSend : TList;
FNextStep : TStringList;
FCurrent : string;
FIndex : Integer;
FComPort : TComPort;
public
Constructor Create(PortBoudRate : Integer; PortIndex : Integer);
Destructor Destroy; override;
Procedure SendSms(messageSet : TMessageSet);
Procedure Stop();
Procedure Execute; override;
end;

implementation

Constructor TSmsSender.Create(PortBoudRate : Integer; PortIndex : Integer);
begin
inherited Create(True);
FComPort := TComPort.Create(PortBoudRate, PortIndex);
Priority := tpNormal;
FreeOnTerminate := false;
FTerminate := false;
FToSend := TList.Create;
FNextStep := TStringList.Create;
FIndex := -1;
FCurrent := '';
if (not FComPort.Open()) then
raise Exception.Create('Cannot open Com Port');

Resume();
end;

Destructor TSmsSender.Destroy;
var
SmsItem : PMessageSet;
begin
while (FToSend.Count > 0) do
begin
SmsItem := FToSend[0];
Dispose(SmsItem);
FToSend.Delete(0);
end;
FToSend.Free;
FComPort.Close();
FComPort.Free;
FNextStep.Clear();
FNextStep.Free;
inherited Destroy;
end;

Procedure TSmsSender.SendSms(messageSet : TMessageSet);
var
SmsItem : PMessageSet;
begin
New(SmsItem);
SmsItem^.Number :=  messageSet.Number;
SmsItem^.Text := messageSet.Text;
SmsItem^.Unicode := false; //unicode not implemented
FToSend.Add(SmsItem);
end;

Procedure TSmsSender.Execute;
var
res, tmp : string;
x : Integer;
SmsItem : PMessageSet;
begin
res := '';
tmp := '';

while (not FTerminate) do
begin
if ((FToSend.Count = 0) and (FNextStep.Count = 0) and (FCurrent = '')) then
begin
Sleep(200);
end else
begin
tmp := FComPort.Read();
res := res + tmp;
if (res <> '') then
begin
x := Pos(#13#10 + 'OK', res);
if (x > 0) then
begin
if (Pos(FCurrent, res) > 0) then
begin
if (FNextStep.Count > 0) then
begin
Inc(FIndex);
FCurrent := Steps[FIndex];
tmp := FNextStep[0];
FNextStep.Delete(0);
FComPort.Write(tmp);
end else
begin
MessageBox(0, PChar('Message was sent'), PChar('Congratulations'), 0);
FCurrent := '';
FIndex := -1;
end;
end;
res := '';
end else
begin
x := Pos('ERROR', res);
if (x > 0) then
begin
MessageBox(0, PChar('Message was not sent'), PChar('Error'), 0);
FIndex := -1;
FCurrent := '';
res := '';
FNextStep.Clear();
end else
begin
if (Pos('>', res) > 0) then
begin
Inc(FIndex);
FCurrent := Steps[FIndex];
tmp := FNextStep[0];
FNextStep.Delete(0);
FComPort.Write(tmp);
res := '';
end;
end;
end;
end;
end;

if ((FNextStep.Count = 0) and (FCurrent = '') and (FToSend.Count > 0) and (not FTerminate)) then
begin
SmsItem := FToSend[0];
FIndex := 0;
FCurrent := Steps[FIndex];
FNextStep.Add('AT+CMGF=1' + #13#10);
FNextStep.Add('AT+CMGS="' + SmsItem^.Number + '"' + #13#10);
FNextStep.Add(SmsItem^.Text + #26);
Dispose(SmsItem);
FToSend.Delete(0);
FComPort.Write('ATZ' + #13#10);
Sleep(500);
end;

end;

end;

procedure TSmsSender.Stop();
begin
FTerminate := true;
end;

end.

Sources and Test application you can download here

6 Responses to “[Windows] Send sms using gsm modem Delphi/Lazarus”

  1. 1
    Alberto Gentili Says:

    Hello. I tested the unit and is doing very well. Know any unit to receive messages?. Sorry for the English. I’m from Argentina and use the Google translator.

    Thanks.

  2. 2
    admin Says:

    receiving even easier… there just couple AT commands and you receive sms, the problem that i dont use pascal any more… but i can share c# code or c++

  3. 3
    Modrih Says:

    Hi! You can translate code to receiving SMS to pascal? :) best regards.

  4. 4
    admin Says:

    i can, but i wont :)

  5. 5
    ricky Says:

    can u send me code for received sms?in c# or delphi…send to my email plzzz…thx

  6. 6
    Zemo Says:

    Hi,

    please, could you help me to encode message with “accentuation” ?
    if the message is ENGLISH no problem, but I’m using portuguese and
    it’s require some letter with accentuation….

    could you help ?

    tks
    Zemo

Leave a Reply