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.

#!/usr/bin/perl
use POSIX;
use Device::SerialPort;

$modem_dev="/dev/ttyS1";
# change it to your mobile network SMSC number.

$smsc="+62811000000";

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

            select(undef,undef,undef,0.2);
        }
        return $ret;
    }
}


$modem = Device::SerialPort->new($modem_dev);
if (defined $modem)
{
    $modem->databits(8);
    $modem->baudrate(115200);
    $modem->parity("none");
    $modem->stopbits(1);
    $modem->stty_echo(0);
    $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";
    exit();
}
 

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

$modem->write("ATZ\r\n");

$str = &readModem($modem);

$modem->write("ATE0\r\n");
$str = &readModem($modem);
 

$modem->write("AT+CMGF=1\r\n");
$str = &readModem($modem);
 

$modem->write("AT+CSCA=\"$smsc\",145\r\n");
$str = &readModem($modem);
 

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

$modem->write($msg.pack('c',26));

sleep(2);
$str = &readModem($modem);

$modem->close();


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.
e.g:
# ./sendSMS "+62812344556" "Test SMS via Perl"

I hope this could help.

1 comment:

bellacollins said...

You should be providing really good interfaces to your customers that they can utilize to contact you as quickly as possible. Nowadays most of the business owners are preferring the apps that allow their customers to send sms to slack. These are very affordable too.