[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

Leave a Reply