Created
January 23, 2021 17:24
-
-
Save barijaona/da26156d04ca27fc633e80a367eab695 to your computer and use it in GitHub Desktop.
Perform USSD requests through USB modem
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env perl | |
# | |
# Send USSD requests | |
# | |
# Authored by Barijaona Ramaholimihaso | |
# https://gist.github.com/barijaona | |
# Loosely derived from https://gist.github.com/vshymanskyy/5085138 | |
# | |
use strict; | |
use warnings; | |
use Getopt::Std; | |
use Device::SerialPort; | |
use 5.8.0; # Encode::GSM0338 only vailable since 5.8 | |
use Encode qw/encode decode/; | |
# defaults | |
our ($opt_p, $opt_v, $opt_h); | |
my $USAGE = <<__EOU; | |
Usage: $0 -p io_port [-hv] [ussd_msg] | |
Description: | |
Send and receive USSD messages using GSM/UMTS USB modem. | |
Options: | |
-p port Port to send and receive. | |
-h Print this help. | |
-v Be verbose. | |
Examples: | |
Linux or macSOS: $0 -p /dev/ttyUSB2 *100# | |
Win32: $0 -p COM6 *100# | |
__EOU | |
$Getopt::Std::STANDARD_HELP_VERSION = 1; | |
sub HELP_MESSAGE { print "$USAGE\n"; exit; } | |
sub VERSION_MESSAGE { print "USSD v0.1\n";}; | |
getopts ('p:hv'); | |
HELP_MESSAGE() if (defined($opt_h) or not defined($opt_p)); | |
print "Opening $opt_p\n" if $opt_v; | |
my $port = new Device::SerialPort($opt_p) || die "Can't open $opt_p: $^E\n"; | |
$port->baudrate(115200); | |
$port->databits(8); | |
$port->stopbits(1); | |
$port->parity("none"); | |
$port->handshake("none"); | |
$port->write_settings or die; | |
$port->are_match("OK\r\n", "ERROR\r\n"); | |
$port->write("ATZE0+CSCS=\"GSM\"\n"); # reset modem, no echo, GSM encoding | |
sleep(1); | |
$port->lookfor(); | |
$port->write("AT+CUSD=2\n"); # cancel previous session | |
sleep(1); | |
$port->lookfor(); | |
my $user_input; | |
if ($ARGV[0]) { | |
$user_input = $ARGV[0]; | |
} else { | |
print "Command> "; | |
$user_input = <STDIN>; | |
$user_input =~ s/[\n\f\t]//g; | |
}; | |
while ($user_input ne "") { | |
$port->lookclear; # empty buffers | |
sleep 1; | |
my $ussd_req = encode("gsm0338", $user_input); | |
print "Sending PDU USSD request: $ussd_req ($user_input)\n" if $opt_v; | |
$port->write("AT+CUSD=1,\"$ussd_req\",15\n"); | |
print "Waiting for USSD reply...\n" if $opt_v; | |
my $answer = ""; | |
until ("" ne $answer) { | |
$answer = $port->lookfor(); | |
if ($answer) { | |
$port->lookclear; | |
my ($presentation, $ussd_reply, $ussd_coding); | |
if ($answer =~ m/\+CUSD:\s*(\d)\s*,\s*\"(.*)\",\s*([0-9]*)/s) { | |
($presentation, $ussd_reply, $ussd_coding) = ($1, $2, $3); | |
print "USSD encoding: $ussd_coding\n" if $opt_v; | |
print "USSD reply: $ussd_reply\n" if $opt_v; | |
if ($presentation eq "2") { | |
print "USSD session ended: "; | |
} | |
} else { | |
undef $ussd_reply; | |
print "Got unknown message: $answer\n"; | |
} | |
if ($ussd_reply) { | |
print "Decoded: " if $opt_v; | |
if ($ussd_coding eq '15') { | |
printf "%s\n", decode("gsm0338", $ussd_reply); | |
} elsif ($ussd_coding eq '72') { | |
printf "%s\n", decode("UCS-2BE", $ussd_reply); | |
} else { | |
print "Could not decode: $ussd_reply,$ussd_coding\n"; | |
} | |
} | |
} else { | |
sleep(1); | |
} | |
} | |
# next user input | |
print "Command> "; | |
$user_input = <STDIN>; | |
$user_input =~ s/[\n\f\t]//g; | |
} | |
$port->write("ATZ\n"); | |
$port->close or die; | |
undef $port; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment