10 Things to Consider When Buying 16-ports USB GSM SMS modem
May. 13, 2024
Setting up SMS Sending and Receiving using a USB GSM ...
Disable Unnecessary Modem Properties
The USB GSM modem, MF190, comes with properties like appearing as a CD-ROM drive on Linux or as a mass storage device or both. In our case, on Kali Linux, this device appeared as 3 different devices: a CD-ROM device /dev/sr1
, a mass storage device /dev/sdc
and a USB modem /dev/ttyUSB2
. These device names can be extracted from the dmesg
output as below as soon as you plugin the USB device to your computer.
If you are looking for more details, kindly visit 16-ports USB GSM SMS modem.
$ sudo dmesg | tail -n 1000
[1800781.986806] usb 1-2.4.2: new high-speed USB device number 7 using ehci-pci
[1800782.197336] usb 1-2.4.2: New USB device found, idVendor=19d2, idProduct=2000, bcdDevice= 0.00
[1800782.197343] usb 1-2.4.2: New USB device strings: Mfr=3, Product=2, SerialNumber=4
[1800782.197347] usb 1-2.4.2: Product: ZTE WCDMA Technologies MSM
[1800782.197350] usb 1-2.4.2: Manufacturer: ZTE,Incorporated
[1800782.197352] usb 1-2.4.2: SerialNumber: MF1900ZTED010000
[1800782.199979] usb-storage 1-2.4.2:1.0: USB Mass Storage device detected
[1800782.201943] scsi host3: usb-storage 1-2.4.2:1.0
[1800783.221344] scsi 3:0:0:0: CD-ROM ZTE USB SCSI CD-ROM 2.31 PQ: 0 ANSI: 2
[1800783.225970] sr 3:0:0:0: [sr1] scsi-1 drive
[1800783.243508] sr 3:0:0:0: Attached scsi CD-ROM sr1
[1800783.243741] sr 3:0:0:0: Attached scsi generic sg4 type 5
[1800784.752096] usb 1-2.4.2: USB disconnect, device number 7
[1800785.078898] usb 1-2.4.2: new high-speed USB device number 8 using ehci-pci
[1800785.290082] usb 1-2.4.2: New USB device found, idVendor=19d2, idProduct=0117, bcdDevice= 0.00
[1800785.290090] usb 1-2.4.2: New USB device strings: Mfr=3, Product=2, SerialNumber=4
[1800785.290093] usb 1-2.4.2: Product: ZTE WCDMA Technologies MSM
[1800785.290096] usb 1-2.4.2: Manufacturer: ZTE,Incorporated
[1800785.290099] usb 1-2.4.2: SerialNumber: MF1900ZTED010000
[1800785.293883] usb-storage 1-2.4.2:1.3: USB Mass Storage device detected
[1800785.294205] scsi host3: usb-storage 1-2.4.2:1.3
[1800785.974549] usbcore: registered new interface driver option
[1800785.976340] usbserial: USB Serial support registered for GSM modem (1-port)
[1800785.977650] option 1-2.4.2:1.0: GSM modem (1-port) converter detected
[1800785.977975] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB0
[1800785.978392] option 1-2.4.2:1.1: GSM modem (1-port) converter detected
[1800785.978596] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB1
[1800785.979220] option 1-2.4.2:1.2: GSM modem (1-port) converter detected
[1800785.979462] usb 1-2.4.2: GSM modem (1-port) converter now attached to ttyUSB2
[1800786.324071] scsi 3:0:0:0: CD-ROM ZTE USB SCSI CD-ROM 2.31 PQ: 0 ANSI: 2
[1800786.325395] scsi 3:0:0:1: Direct-Access ZTE MMC Storage 2.31 PQ: 0 ANSI: 2
[1800786.331560] sr 3:0:0:0: [sr1] scsi-1 drive
[1800786.359076] sr 3:0:0:0: Attached scsi CD-ROM sr1
[1800786.359210] sr 3:0:0:0: Attached scsi generic sg4 type 5
[1800786.359645] sd 3:0:0:1: Attached scsi generic sg5 type 0
[1800786.373392] sd 3:0:0:1: [sdc] 7716864 512-byte logical blocks: (3.95 GB/3.68 GiB)
[1800786.375021] sd 3:0:0:1: [sdc] Write Protect is off
[1800786.375026] sd 3:0:0:1: [sdc] Mode Sense: 0f 0e 00 00
[1800786.375768] sd 3:0:0:1: [sdc] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[1800786.416178] sdc: sdc1
[1800786.435203] sd 3:0:0:1: [sdc] Attached SCSI removable disk
You can also use lsusb
to check that the device has been loaded.
$ lsusb | grep -i zte
Bus 001 Device 008: ID 19d2:0117 ZTE WCDMA Technologies MSM MF667
The device seems to show MF667
but the labeling says MF190
. Either way, they support the same commands for sending and receiving SMS.
For this post, we will disable both the CD-ROM and mass storage feature. It may so happen that you may want to take advantage of the mass storage feature to save messages or to use the USB GSM modem to receive files over GSM and that is out of the scope of this post.
First eject the CD-ROM from the host machine
$ sudo eject /dev/sr1
Then connect to the USB modem using a serial program like
minicom
and run the following commands to disable the CD-ROM features. The first command makes the device online and the second command disables the CD-ROM auto-run feature.
$ minicom -b 115200 /dev/ttyUSB2
AT+ZOPRT=5
AT+ZCDRUN=8
Now the device is ready for sending and receiving messages and phone calls. For this post, we will not be making any phone calls.
Install Perl Modules
Once the device has been setup and configured, let us try to use it using a Perl script. The GSM device acts like a modem with a serial port so the dependency that you need to install using the cpanm
tool is primarily Device::Gsm
which will install other dependencies like Device::Modem
and Device::SerialPort
. Of course, you could also use a Python script to connect to the modem, but we love writing Perl.
$ cpanm Device::Gsm Device::Modem Device::SerialPort
Sending Messages
Sending messages can be done very easily using the Device::Gsm
module as shown below in the perl script. The $modem
, $text
and $recipient
variables must be edited as per your needs. The phone number must have no spaces, must include the country code and the +
sign in front of it.
Once you create a Device::Gsm
object, then you connect to the modem over the serial port /dev/ttyUSB2
with a baud rate of 115200. Once that connection works, you can then send a message using the send_sms
function which is obvious in the below code.
use strict;
use warnings;
use Device::Gsm;
## setup the USB GSM modem
my $modem = '/dev/ttyUSB2'; # or other like /dev/modem
my $gsm = Device::Gsm->new(port => $modem, log => 'file,/tmp/gsm.log',
loglevel => 'info');
$gsm->connect(115200) or die "Failed to connect to $modem";
## my message
my $text = "This is a test message";
## my phone number
my $recipient = '+12012012010'; # the full phone number you want to use
## send the message
my $sent = $gsm->send_sms(
content => substr($text, 0, 140),
recipient => $recipient,
);
die "Unable to send message to $recipient ", scalar localtime unless $sent;
print "Sent message to $recipient at ", scalar localtime, "\n";
Receiving Messages
Receiving messages is similarly done. You must connect to the modem at a baud rate of 115200 and then invoke the messages()
function with the storage option defined as ME
which stands for the phone memory, which is where the messages are stored by default on this ZTE device.
If you have messages stored in memory, the for
loop will get invoked and each message which is an instance of Device::Gsm::Sms
can then be handled or printed or processed or stored in a database etc. In the code below, we delete the message if the status is UNREAD
, but that is where the processing by the user can be done.
use strict;
use warnings;
use Device::Gsm;
use Device::Gsm::Sms;
## setup the USB GSM modem
my $modem = '/dev/ttyUSB2'; # or other like /dev/modem
my $gsm = Device::Gsm->new(port => $modem, log => 'file,/tmp/gsm.log',
loglevel => 'info');
$gsm->connect(115200) or die "Failed to connect to $modem";
## get the messages from the local storage 'ME'
my @messages = $gsm->messages('ME');
printf "You have %d messages\n", scalar(@messages);
my $idx = 0;
foreach my $msg (@messages) {
next unless defined $msg;
print '-' x 60, "\n", "MESSAGE N. $idx\n";
print 'Type ',($msg->type() eq Device::Gsm::Sms::SMS_SUBMIT ? 'SUBMIT' : 'DELIVER'), "\n";
print 'Status ', $msg->status(), "\n";
print 'From ', $msg->sender(), "\n";
print 'To ', $msg->recipient(), "\n";
print 'Time ', $msg->time(), "\n";
print 'Text [', $msg->text(), "]\n";
## if the message is unread, delete it now since you may have read it or
if ($msg->status() =~ /UNREAD/) {
### DO SOME PROCESSING HERE
print "DELETING SMS FROM STORAGE!!\n";
$msg->delete();
}
$idx++;
}
The received messages will look like the below:
------------------------------------------------------------
MESSAGE N. 0
Type DELIVER
Status REC UNREAD
From LYCAMOBILE
To
Text [Dear customer ,Your $19 INTERNATIONAL PLAN has been renewed succesfully.it is good through 09/16/2021. Visit https://www.lycamobile.us/login for details.]
------------------------------------------------------------
MESSAGE N. 1
Type DELIVER
Status REC UNREAD
From LYCAMOBILE
To
Text [ Thank you for using Lycamobile.]
------------------------------------------------------------
------------------------------------------------------------
MESSAGE N. 2
Type DELIVER
Status REC UNREAD
From +12012012010
To
Text [Test]
------------------------------------------------------------
MESSAGE N. 3
Type DELIVER
Status REC UNREAD
From +12012012010
To
Text [Got it]
------------------------------------------------------------
Sending & Receiving Together
The below script lets you send a message to a recipient and receive replies by checking every 5 seconds. The most important thing to note is that you have to reconnect to the GSM modem if you have sent a message and then want to receive new messages. This forces the modem to exit the sending state and enter a receiving state.
The rest of the code is similar to the above code blocks in the earlier sections. This script was tested on Kali Linux and it works as of this writing.
#!/usr/bin/env perl
use strict;
use warnings;
use sigtrap qw/handler signal_handler normal-signals/;
use Device::Gsm;
use Device::Gsm::Sms;
use Data::Dumper;
sub usage {
die << "..."
Usage: $0 <phone number like +12125432109> <message>
Press Ctrl-C to exit program.
...
}
sub send_sms {
my ($gsm, $text, $recipient) = @_;
return unless length($text // '');
return unless $recipient;
my $sent = $gsm->send_sms(
content => substr($text, 0, 140),
recipient => $recipient,
);
die "Unable to send message to $recipient ", scalar localtime unless $sent;
print "Sent message to $recipient at ", scalar localtime, "\n";
}
sub receive_messages {
my $gsm = shift;
my @messages = $gsm->messages('ME');
printf "You have %d messages\n", scalar(@messages);
my $idx = 0;
foreach my $msg (@messages) {
next unless defined $msg;
print '-' x 60, "\n", "MESSAGE N. $idx\n";
print 'Type ',($msg->type() eq Device::Gsm::Sms::SMS_SUBMIT ? 'SUBMIT' : 'DELIVER'), "\n";
print 'Status ', $msg->status(), "\n";
print 'From ', $msg->sender(), "\n";
print 'To ', $msg->recipient(), "\n";
print 'Time ', $msg->time(), "\n";
print 'Text [', $msg->text(), "]\n";
if ($msg->status() =~ /UNREAD/) {
print "DELETING SMS FROM STORAGE!!\n";
$msg->delete();
}
$idx++;
}
}
sub signal_handler {
die "Signal caught: $!";
}
usage() unless scalar(@ARGV);
usage() unless defined $ARGV[0];#TODO: verify phone number format
usage() unless length($ARGV[1] // '');
warn "Message to be sent is longer than 140 chars and will be truncated" if length($ARGV[1]) > 140;
my $recipient = shift(@ARGV);
my $message = shift(@ARGV);
print "Using phone number $recipient for recipient\n";
my $modem = '/dev/modem';
$modem = '/dev/ttyACM0' if -e '/dev/ttyACM0';
$modem = '/dev/ttyUSB2' if -e '/dev/ttyUSB2';
my %log = (log => 'file,/tmp/gsm.log', loglevel => 'debug');
my $gsm = Device::Gsm->new(port => $modem, %log);
$gsm->connect(115200) or die "Failed to connect to $modem";
send_sms($gsm, $message, $recipient);
while (1) {
$gsm->connect(115200);
if ($gsm->is_active()) {
receive_messages($gsm);
sleep 5;
} else {
warn "GSM modem is not active";
last;
}
}
__END__
###
###
### COPYRIGHT: 2013-2021 Selective Intellect LLC. All Rights Reserved.
Building a 128/256 SIM card bank with consumer tech on ...
Building a 128/256 SIM card bank with consumer tech on the cheap
Церебрална Романтика
·
Follow
7 min read
·
Sep 8, 2023
--
A SIM pool + SIM bank assembled for less than 600$ . Credit: aliexpress.comAt a point several years prior I was compelled to build an internal company solution for managing multiple SIM cards for receiving SMS codes to our marketing department. Commercial solutions run into thousands easily and a decision was made to go down the economical path. Even though such a solution may be used for sending SMS messages, our case was receiving and routing the messages to our account management platform.
The reason to publish such a document is that a lot of guesswork and reverse engineering has gone into building a working solution. As such it would be magnificent if time on behalf of others might be saved with the findings described.
Commercial vs consumer grade
The principle behind every SIM pool is the same — the vendor crams as many embedded(industrial) GSM modems as possible onto a chassis along with antennae and SIM slots. A commercial vendor will add an additional transport layer for routing the incoming SMS messages to an endpoint(HTTP/Database/SMTP) for easier integration. Often times the industrial modems are Wavecom or Siemens modules that expose serial ports for running AT commands and/or voice channels. Commercial solutions pack 16/32 or more such modems in a chassis compounding to a high cost of acquisition.
Consumer grade boards include 1/2/4/8/16 modems in a chassis with only a USB connection exposing the serial ports and very little documentation.
This is a consumer grade SIM pool. Credit : aliexpress.comThe budget-friendly compromise
I did not want to settle for anything less than 128 SIM cards with a budget under 1000$. After searching on aliexpress for a while I stumbled upon what vendors call a SIM bank. This is basically a switch with a dummy SIM card connector that you insert into your real modem slot and it extends the connection to an array of 16 physical slots. The drawback is that it is a switch, not a multiplexer. As such only 1 of the 16 slots in the SIM bank is online for a modem port at a given moment. The SIM bank exposes a serial interface via USB that lets you change the port assignments on demand. As one may guess, the documentation for this is scarce if not obscure. So the compromise is availability. One would have to iterate the slots on the SIM bank and look for activity on every slot. This is easy with a few quirks.
Software
There is a Windows application called SMSCaster that is marked compatible with the SIM pools and possibly the SIM banks. It is on a commercial license and offers a limited feature set. It provided a basic glimpse into how the pool is working but quickly got discarded as a realistic candidate for SMS management.
The wonderful world of FOSS has provided SMSTools3 SMS Server (http://smstools3.kekekasvi.com/). It is configurable and very flexible in terms of managing the modems and the message data. Linux is the platform of choice for me for hosting internal applications. In this instance Raspbian on Raspberry Pi 1 model B+. It was hosted on a RPi 3 initially which I dedicated to another project so switched to the 1 model B+.
I have included a slightly modified smstools3 version in the github.com repo for this project. As noted in the README.md, it only activates a particular alarm handler that sends a request to a backend that a SIM card is successfully checked for messages( even if no new messages have been received )
You would wanna do :
mkdir /home/socks
mkdir /run/smstools/
chown socks /run/smstoolscd /home/socks/
git clone https://github.com/sertys3/sms-receiver.git .
cd smstools3
sudo make && sudo make install
Related links:
Key Questions to Ask When Ordering 4G LTE 32Ports with M35 Module SMS Modem" - The Ultimate GuideFor more usb gsm modeminformation, please contact us. We will provide professional answers.
cp /home/socks/smsd.conf /etc/
Hardware
- A Raspberry Pi ( 1 model B+ in my case) with Raspbian installed
- 16-port SIM pool — https://www.aliexpress.com/item/32701584178.html
- SIM bank — https://www.aliexpress.com/item/32947688074.html
Drivers
5 Reasons Smart Building Controls Make Good Business ...
The SIM pool requires a kernel driver that exposes the different modem devices properly. They otherwise show as cdc_acm / usb2serial devices, but communication is not possible.
Get your driver here:
In my case it was :
Software: Drivers Linux 3.6.x and Newer 1D September 2021 29.9 KB
but version C as it was the latest back then. In order to build you have to :
sudo apt-get install build-essential linux-headers screen
decompress the archive, go to the decompressed path and
make && sudo make install
Hopefully that would compile your driver and install it into the modules directory.
The driver is of the CDC class and one would have to blacklist the original cdc_acm driver to make sure this one loads instead :
sudo echo “blacklist cdc-acm” > /etc/modprobe.d/blacklist-cdc.conf
After a reboot you will find the corresponding ttyXRUSB devices in your /dev/
root@raspberrypi:/# ls /dev/ttyXRUSB*
/dev/ttyXRUSB0 /dev/ttyXRUSB10 /dev/ttyXRUSB12 /dev/ttyXRUSB14 /dev/ttyXRUSB2 /dev/ttyXRUSB4 /dev/ttyXRUSB6 /dev/ttyXRUSB8
/dev/ttyXRUSB1 /dev/ttyXRUSB11 /dev/ttyXRUSB13 /dev/ttyXRUSB15 /dev/ttyXRUSB3 /dev/ttyXRUSB5 /dev/ttyXRUSB7 /dev/ttyXRUSB9
SIM bank switching explained
The SIM bank itself has one USB port to be connected to your host device. It shows up as :
Bus 001 Device 005: ID 0403:6001 Future Technology Devices International, Ltd FT232 Serial (UART) IC
Which is just a serial port exposed on /dev/ttyUSB0. It responds to custom AT commands — basically AT+CWSIM to check the device status and AT+SWIT[01–16]-[SLOT] to switch a port to the desired slot. I do not even remember where the documentation to that was found but certainly was not easily available.
The published pool_switch_2.pl script iterates over the ports and changes slots every 200 seconds. Keep in mind that switching is dumb and the modems do not receive a notification that the SIM card has effectively changed.
SMSTools3 configuration
[Port1]
#init = AT+CMEE=1
pre_init = no
device = /dev/ttyXRUSB0
init = AT+CPMS=”SM”
incoming = yes
mode = new
baudrate = 115200
rtscts = yes
cs_convert = yes
report = yes
memory_start = 1
check_memory_method = 1
primary_memory = SM
pin = ignore
check_sim = yes
check_sim_cmd = AT+CUSD=1,”*123#”,15
check_sim_reset = AT+CFUN=1,1
check_sim_retries = forever
check_sim_wait = 2
device_open_retries = -1
#give_up_on_io_error = no
eventhandler = /home/socks/pool_forward_sms.pl
ignore_unexpected_input = +CME ERROR: 10
detect_unexpected_input = no
#pin = 0000
#pinsleeptime = 2
queues = Port1
This is what port configuration looks like in the bundled smsd.conf. The smsd is spawning threads that run AT commands on the modem devices for each port at regular intervals(configured in the delaytime directive in the global section of smsd.conf [10 seconds in this case] ). Since switching is dumb on the SIM bank we need to make sure every check has a network-registered SIM card. The AT+CPMS=”SM” command is trying to set the Message Store to SM. But in case the SIM card is not working or freshly switched, the modem returns an error. smsd will try to reset the modem with AT+CFUN=1,1.
The smsd.conf file has a USSD command of *123# that it executes on a SIM card after re-initializing the modem with AT+CFUN=1,1 . This has proven valuable in waking up the SIM cards to receive messages upon reset. Otherwise messages are delivered often times after the 200 seconds checking interval. Put a USSD command that your carrier understands for maximum efficiency.
Putting it all together
Once everything is connected one would need to start the scripts to iterate over the ports and receive the messages. Luckily SMSTools3 is simple to configure. The provided smsd.conf file in the repository lists all 16 ports on the SIM pool yet only 8 are active in our case. If the need arises we may add another 8x16-slot SIM bank and have 256 SIM cards hosted in total.
There’s the peculiarity of installing your perl modules from CPAN for the scripts provided :
perl -MCPAN -e install Device::SerialPort
perl -MCPAN -e install LWP::UserAgent
Then it’s a matter of doing
/etc/init.d/sms3 start
This may or may not be created by the make install of smstools3. Otherwise start manualy with
smsd -c /etc/smsd.conf
screen /home/socks/pool_switch_2.pl
Now smstools3 should be checking enabled ports for SMS messages every 10 seconds and pool_switch_2.pl will rotate the switch slots every 200 seconds.
In case an SMS is received, it will be handled by pool_forward_sms.pl , which will send a POST request to a web server of your choice. Do not forget to change the $POST_ENDPOINT variable.
Slot fast forward
Since SMS codes are time sensitive, pool_switch_2.pl will look for /run/smstools/[PORT]_next files and switch to the contained slot number upon iteration. The mechanism to write those files in the backend was implemented in our account management platform. So a user expecting an SMS on Port 3, Slot 10 will trigger a check and a /run/smstools/3_next file will be created with string content “10”. And within a maximum of 200 seconds his SMS will be pushed back to him and rendered in the interface.
A note on SIM Bank location
The current SIM card location is derived from the values in /run/smstools/ which pool_switch_2.pl updates upon switching.
root@raspberrypi:/home/pi# ls /run/smstools/
1_current 2_current 3_current 4_current 5_current 6_current 7_current 8_current
As such there’s a ‘location’ parameter in the POST request with a string value of [PORT]x[SLOT]. And the ingesting endpoint maps the message to the correct SIM card number based on that parameter.
The alarmhandler script
In the global section of the smsd.conf you will find
#alarmhandler = /home/socks/pool_alarm.pl
which receives all alarms from smsd and looks for a particular one indicating that a check on a SIM card has been successful. It then sends a POST request to an endpoint set in $POST_ENDPOINT in pool_alarm.pl This alarm is only available in the modified smstools3 version bundled.
Once this got deployed to a RPi 1 the script was killing the system with numerous Perl interpretator spawns. So my best man re-wrote it in Go and had it compiled. I would happily share the source to that upon request.
The directive is now commented by default as to ease up initial deployment.
Goal achieved
This is a solution that we’ve had in production for several years and with a total purchase price of <600$. It clearly may be deemed a success and it would be great to see it replicated. Happy SMSing!
For more information, please visit gsm to voip gateway.
109
0
0
Comments
All Comments (0)