Thursday, October 20, 2011

Sending SMS via GPRS modem using Perl Device::SerialPort

Sometimes ago, I posted a script to send SMS using Gammu. Now, I would like to deep dive on the underlying communication to GPRS modem using AT command to send SMS.

The sequence of AT commands to use are:
  • ATZ : Reset modem 
  • ATE0 : Disable echo (not necessary)
  • AT+CMGF : Setting the SMS mode (Text or PDU) 
  • AT+CSCA : Query or set the SMS center number 
  • AT+CMGS: Send SMS 
To cut the story short, here is the example of Perl script I use to send SMS using a GPRS modem.Note that checks have been omitted for brevity.

use POSIX;
use Device::SerialPort;

# change it to your mobile network SMSC number.


# to read modem response
sub readModem
    if (!defined $_[0])
    } else {
        my $tmout = 2;
        my $ret = "";
        while ($tmout>0)
            my ($cnt,$saw) = $_[0]->read(255);
            if ($cnt>0)
            } else {

        return $ret;

$modem = Device::SerialPort->new($modem_dev);
if (defined $modem)
    $modem->read_char_time(0); # don't wait each char
    $modem->read_const_time(500); # spend 500ms to read data from serial line
} else {
    print "Modem ".$modem_dev." is not available.\n";

$phone = $ARGV[0];
$msg = $ARGV[1];


$str = &readModem($modem);

$str = &readModem($modem);

$str = &readModem($modem);

$str = &readModem($modem);

# Some modems requires \r\n  for this command
$str = &readModem($modem);
# wait for 2 second for the prompt to appear
select(undef,undef,undef,2);\" : ".$str."\n";


$str = &readModem($modem);


To use this script, you need to pass 2 arguments which are phone number as the first argument and the message as the second argument.
# ./sendSMS "+62812344556" "Test SMS via Perl"

I hope this could help.

No comments: