Simultaneous speedtest on multiple LTE modems

In quarantine, I was offered to participate in the development of a device for measuring the speed of LTE modems for several mobile operators.

Simultaneous speedtest on multiple LTE modems

The customer wanted to evaluate the speed of various telecom operators in different geographic locations in order to be able to understand which mobile operator is the most optimal for him when installing equipment using an LTE connection, for example, for video broadcasts. At the same time, the task had to be solved as simply and cheaply as possible, without expensive equipment.

I must say right away that the task is not the easiest and most science-intensive, I will tell you what problems I encountered and how I solved them. So let's go.

Note

Measuring the speed of an LTE connection is a very complicated matter: it is necessary to choose the right equipment and measurement methodology, as well as to have a good understanding of the topology and operation of the cellular network. Plus, several factors can affect the speed: the number of subscribers per cell, weather conditions, even from cell to cell, the speed can differ dramatically due to the network topology. In general, this is a problem with a huge number of unknowns, and only a telecom operator can solve it correctly.

Initially, the customer wanted to simply drive a courier with operators' phones, take measurements directly on the phone, and then write down the results of speed measurements in a notebook. My solution for measuring the speed of lte networks, although not ideal, but solves the problem.

Due to lack of time, I made decisions not in favor of convenience or practicality, but in favor of speed of development. For example, reverse ssh was raised for remote access, instead of the more practical vpn, in order to save time on setting up the server and each individual client.

Technical task

As stated in the article Without TK: why the client does not want it: Do not work without TK! Never, nowhere!

The terms of reference were quite simple, I will expand it a little for the understanding of the end user. The choice of technical solutions and equipment was dictated by the customer. So, the TK itself, after all the approvals:

Based on a single board computer vim2 make lte connection speed tester via H modemsuawei e3372h-153 several telecom operators (from one to n). It is also necessary to receive coordinates from a GPS receiver connected via UART. Speed ​​measurements to be made using the service www.speedtest.net and put them in a table like this:

Simultaneous speedtest on multiple LTE modems

Table in csv format. Then send this sign to e-mail every 6 hours. In case of errors, blink the LED that is connected to the GPIO.

I described the TK in free form, after a lot of approvals. But the meaning of the task is already visible. The deadline for everything about everything was given a week. But in reality, it stretched out for three weeks. This is in view of the fact that I did it only after the main work and on weekends.

Here I want to once again draw your attention to the fact that the customer agreed in advance to use the speed measurement service and hardware, which severely limited my capabilities. The budget was also limited, so nothing special was purchased. So I had to play by those rules.

Architecture and development

The scheme is simple and obvious. So I'll leave it without much comment.

Simultaneous speedtest on multiple LTE modems

I decided to implement the entire project in python, despite the fact that I had no development experience in this language at all. I chose it because there were a lot of ready-made examples and solutions that could speed up development. Therefore, I ask all professional programmers not to scold my first development experience in python, and I am always happy to hear constructive criticism to improve my skill.

Also in the process, I discovered that python has two running versions 2 and 3, as a result, I settled on the third one.

Hardware nodes

vim2 single board

As the main machine, I was given a single-payer vim2

Simultaneous speedtest on multiple LTE modems

An excellent, powerful media combine for a smart home and SMART-TV, but extremely unsuitable for this task, or, let's say, poorly suitable. For example, its main OS is Android, and Linux is a companion OS, and accordingly, no one guarantees the quality work of all nodes and drivers under Linux. And I assume that some of the problems were related to the USB drivers of this platform, so the modems did not work on this board as expected. It also has very poor and scattered documentation, so each operation took a lot of time digging through the docks. Even ordinary work with GPIO drank a lot of blood. For example, it took me several hours to set up the work with the LED. But, to be objective, it didn’t matter in principle what kind of single-board, the main thing was that it worked and there were USB ports.

First I need to install Linux on this board. In order not to scour everyone through the jungle of documentation, as well as for those who will deal with this single-payer, I am writing this chapter.

There are two options to install Linux: on an external SD card, or on an internal MMC. I struggled with the card in the evening, and did not get a taste of how to make it work, so I decided to install it on MMC, although without a doubt it would be much easier to work with an external card.

About firmware badly told here. I translate from strange into Russian. In order to flash the board, I need to connect a hardware UART. Plugged it in in the following way.

  • Tool Pin GND: <—> Pin17 of VIMs's GPIO
  • Tool Pin TXD: <—> Pin18 of VIMs's GPIO (Linux_Rx)
  • Tool Pin RXD: <—> Pin19 of VIMs's GPIO (Linux_Tx)
  • Tool Pin VCC: <—> Pin20 of VIMs's GPIO

Simultaneous speedtest on multiple LTE modems

After that, I downloaded the firmware hence. Specific firmware version VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

In order to fill in this firmware, I need utilities. More details about this here. I didn’t try to flash it under Windows, but I need to say a few words about firmware under Linux. To begin with, I will install the utilities, according to the instructions.

git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALL

Eee... Nothing works. I spent a couple of hours editing the installation scripts so that everything was installed correctly for me. I don’t remember what I did there, but it’s also that circus with horses. So be careful. But without these utilities, there is no point in further tormenting vim2. It's better not to mess with him at all!

After seven circles of hell, script configuration and installation, I got a package of working utilities. I connected the board via USB to my Linux computer, and the UART is also connected according to the diagram above.
I'm setting my favorite minicom terminal to baud rate 115200, without hardware or software error control. And let's get started.

Simultaneous speedtest on multiple LTE modems

When loading VIM2 in the UART terminal, I press any key, such as space, to stop the download. After the line appears

kvim2# 

I enter the command:

kvim2# run update

On the host from which we are loading, I execute:

burn-tool -v aml -b VIM2 -i  VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.img

Everything, phew. I asked, there is Linux on the board. Login/password khadas:khadas.

After that, small initial settings. For further work, I disable the password for sudo (yes, not safe, but convenient).

sudo visudo

I edit the line to the view and save

# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALL

Then I change the current locale so that the time is in Moscow, otherwise it will be in Greenwich Mean Time.

sudo timedatectl set-timezone Europe/Moscow

or

ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime

If it seemed difficult for you, then do not use this board, Raspberry Pi is better. Honestly.

Modem Huawei e3372h - 153

This modem drank my blood notably, and, in fact, it became the bottleneck of the entire project. In general, the name “modem” for these devices does not reflect the essence of the work at all: this is a powerful combine, this piece of iron has a composite device that pretends to be a CD-ROM in order to install drivers, and then goes into network card mode.

Architecturally, from the point of view of a Linux user after all the settings, it looks like this: after connecting the modem, I have an eth* network interface, which receives the ip address 192.168.8.100 via dhcp, and the default gateway is 192.168.8.1.

And the most important moment! This modem model does not know how to work in the mode of the modem, which is controlled by AT commands. Everything would be much simpler, create ppp connections for each modem and then operate with them. But in my case, “himself” (more precisely, a Linux diver according to udev rules), creates an eth interface and assigns an ip address to it via dhcp.

In order not to get confused further, I propose to forget the word "modem" and say network card and gateway, because in fact, it's like connecting a new network card with a gateway.
When there is one modem, this does not cause any particular problems, but when there are more than one, namely n-pieces, then the following network picture appears.

Simultaneous speedtest on multiple LTE modems

That is n NICs, with the same IP address, each with the same default gateway. But in fact, each of them is connected to its own operator.

Initially, I had a simple solution: use the ifconfig or ip command to turn off all interfaces and just turn on one in turn and test it. The decision was all good, except that at the moments of switching I was not able to connect to the device. And since the switching is frequent and fast, in fact, I did not have the opportunity to connect at all.

Therefore, I chose the path to change "manually" the ip-addresses of the modems and continue to drive traffic using the routing settings.

Simultaneous speedtest on multiple LTE modems

My problems with modems did not end there: in case of power problems, they fell off, I needed a good stable power supply from the USB hub. This problem was solved by hard soldering the power directly to the hub. Another problem that I encountered and which ruined the entire project: after a reboot or a cold start of the device, not all modems were detected and not always, and why this happened and by what algorithm I could not install. But first things first.

For the modem to work correctly, I installed the usb-modeswitch package.

sudo apt update
sudo apt install -y usb-modeswitch

After that, the modem after connection will be correctly detected and configured by the udev subsystem. I check by simply connecting the modem and making sure that the network has appeared.
Another problem that I could not solve: how to get the name of the operator we are working with from this modem? The operator name is contained in the modem's web interface at 192.168.8.1. This is a dynamic web page that receives data through ajax requests, so just wget-pushing the page and parsing the name will not work. So I started looking at how to work out a web page, etc., and realized that I was doing some kind of nonsense. As a result, he spat, and the operator began to receive using the API of Speedtest itself.

Much would be easier if the modem had access via AT commands. It would be possible to reconfigure it, create a ppp connection, assign an IP, get a carrier, etc. But alas, I work with what they gave me.

GPS

The GPS receiver they gave me had a UART interface and power. It was not the best decision, but nevertheless working and simple. The receiver looked like this.

Simultaneous speedtest on multiple LTE modems

To be honest, it was the first time I worked with a GPS receiver, but as I expected, everything was invented for us a long time ago. So we just use ready-made solutions.

First, I turn on uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) to connect GPS.

khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okay

After I check the success of the operation.

khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okay

This command, apparently, edits the devtree on the fly, which is very convenient.

After the success of this operation, reboot and install the gps daemon.

khadas@Khadas:~$ sudo reboot

Installing the gps daemon. I install everything and cut it off immediately for further configuration.

sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
 
/* GPS daemon stop/disable */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket

Editing the settings file.

sudo vim /etc/default/gpsd

I install UART, on which GPS will hang.

DEVICES="/dev/ttyS4"

And then we turn everything on and start.

/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket

After that, I connect the GPS.

Simultaneous speedtest on multiple LTE modems

In the hands of the GPS wire, the UART debugger wires are visible under the fingers.

I reboot and check the GPS using the gpsmon program.

Simultaneous speedtest on multiple LTE modems

There are no satellites in this screenshot, but communication with the GPS receiver is visible, and this says that everything is fine.

In python, I tried many options for working with this daemon, but I settled on the one that worked correctly with python 3.

I install the required library.

sudo -H pip3 install gps3 

And I sculpt the work code.

from gps3.agps3threaded import AGPS3mechanism
...

def getPositionData(agps_thread):
	counter = 0;
	while True:
		longitude = agps_thread.data_stream.lon
		latitude = agps_thread.data_stream.lat
		if latitude != 'n/a' and longitude != 'n/a':
			return '{}' .format(longitude), '{}' .format(latitude)
		counter = counter + 1
		print ("Wait gps counter = %d" % counter)
		if counter == 10:
			ErrorMessage("Ошибка GPS приемника!!!")
			return "NA", "NA"
		time.sleep(1.0)
...
f __name__ == '__main__':
...
	#gps
	agps_thread = AGPS3mechanism()  # Instantiate AGPS3 Mechanisms
	agps_thread.stream_data()  # From localhost (), or other hosts, by example, (host='gps.ddns.net')
	agps_thread.run_thread()  # Throttle time to sleep after an empty lookup, default '()' 0.2 two tenths of a second

If I need to get the coordinates, then this is done by the following call:

longitude, latitude = getPositionData(agps_thread)

And within 1-10 seconds I will either get the coordinate or not. Yes, I had ten attempts to get the coordinates. Not optimal, crooked and askew, but it works. I decided to do this because GPS can catch badly and not always receive data. If you wait for data to be received, then in the case of working in a remote room, the program will hang in this place. Therefore implemented such not elegant variant.

In principle, there would be more time, it would be possible to receive data from GPS directly via UART, parse them in a separate thread and work with them. But there was no time at all, hence the fierce ugly code. And yes, I'm not ashamed.

Light-emitting diode

With the connection of the LED, everything was simple and difficult at the same time. The main difficulty is that the pin number in the system does not match the pin number on the board and because the documentation is written with a left heel. To match the hardware pin number and the pin number in the OS, you need to run the command:

gpio readall

A pin correspondence table will be displayed in the system and on the board. After that, I can already operate with a pin in the OS itself. In my case the LED is connected to GPIOH_5.

Simultaneous speedtest on multiple LTE modems

I put the GPIO pin in output mode.

gpio -g mode 421 out

I write zero.

gpio -g write 421 0

I write down the unit.

gpio -g write 421 1

Simultaneous speedtest on multiple LTE modems
Everything is lit, after writing "1"

#gpio subsistem
def gpio_init():
	os.system("gpio -g mode 421 out")
	os.system("gpio -g write 421 1")

def gpio_set(val):
	os.system("gpio -g write 421 %d" % val)
	
def error_blink():
	gpio_set(0)
	time.sleep(0.1)
	gpio_set(1)
	time.sleep(0.1)
	gpio_set(0)
	time.sleep(0.1)
	gpio_set(1)
	time.sleep(0.1)
	gpio_set(0)
	time.sleep(1.0)
	gpio_set(1)

def good_blink():
	gpio_set(1)

Now, in case of errors, I call error_blink () and the LED blinks beautifully for us.

Software nodes

Speedtest API

It's a great joy that the speedtest.net service has its own python-API, you can look at Github.

The good thing is that there are source codes that can also be viewed. How to work with this API (the simplest examples) can be found in the relevant section.

I install the python library with the following command.

sudo -H pip3 install speedtest-cli

For example, you can generally install a speedtester in Ubuntu directly from the rap. This is the same python application, which can then be run directly from the console.

sudo apt install speedtest-cli -y

And measure your internet speed.

speedtest-cli
Retrieving speedtest.net configuration...
Testing from B***** (*.*.*.*)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by MTS (Moscow) [0.12 km]: 11.8 ms
Testing download speed................................................................................
Download: 7.10 Mbit/s
Testing upload speed......................................................................................................
Upload: 3.86 Mbit/s

As a result, how I did it. I had to dig into the source codes of this speedtest in order to more fully implement them in my project. One of the most important tasks is to get the name of the telecom operator to substitute it in the plate.

import speedtest
from datetime import datetime
...
#Указываем конкретный сервер для теста
#6053) MaximaTelecom (Moscow, Russian Federation)
servers = ["6053"]
# If you want to use a single threaded test
threads = None
s = speedtest.Speedtest()
#получаем имя оператора сотовой связи
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
#получаем текстовую строку с параметрами сервера
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
#тест загрузки
s.download(threads=threads)
#тест выгрузки
s.upload(threads=threads)
#получаем результаты
s.results.share()

#После чего формируется строка для записи в csv-файл.
#получаем позицию GPS
longitude, latitude = getPositionData(agps_thread)
#время и дата
curdata = datetime.now().strftime('%d.%m.%Y')
curtime = datetime.now().strftime('%H:%M:%S')
delimiter = ';'
result_string = opos + delimiter + str(curpos) + delimiter + 
	curdata + delimiter + curtime + delimiter + longitude + ', ' + latitude + delimiter + 
	str(s.results.download/1000.0/1000.0) + delimiter + str(s.results.upload / 1000.0 / 1000.0) + 
	delimiter + str(s.results.ping) + delimiter + testserver + "n"
#тут идет запись в файл логов

Here, too, everything turned out to be not so simple, although it would seem much easier. Initially, the servers parameter was equal to []Please choose the best server. As a result, I had random servers, and, as you might guess, floating speed. This is a rather complex topic, using a fixed server, if so, static or dynamic, requires research. But here is an example of graphs for measuring the speed of the Beeline operator with a dynamic selection of a test server and a statically fixed one.

Simultaneous speedtest on multiple LTE modems
Speed ​​measurement result when dynamic server is selected.

Simultaneous speedtest on multiple LTE modems
The result of speed testing, with one strictly selected one server.

"Wool" during testing is here and there, and it must be removed by mathematical methods. But with a fixed server, it is slightly less and the amplitude is more stable.
In general, this is a place of great research. And I would take speed measurements to my server using the iperf utility. But we stick to TK.

Sending mail and errors

To send mail, I tried several dozen different options, but as a result I settled on the following. I registered a mailbox on yandex and then took this example of sending mail. I checked it and implemented it into the program. This example explores various options, including sending from gmail, etc. I didn’t want to mess with raising my mail server and didn’t have time for it, but as it turned out later, it was also in vain.

Logs were sent according to the scheduler, if there is a connection, every 6 hours: at 00 hours, 06 am, 12 noon and 18 pm. Sent as follows.

from send_email import *
...
message_log = "Логи тестирования платы №1"
EmailForSend = ["[email protected]", "[email protected]"]
files = ["/home/khadas/modems_speedtest/csv"]
...
def sendLogs():
	global EmailForSend
	curdata = datetime.now().strftime('%d.%m.%Y')
	сurtime = datetime.now().strftime('%H:%M:%S')
	try:
		for addr_to in EmailForSend:
			send_email(addr_to, message_log, "Логи за " + curdata + " " + сurtime, files)
	except:
		print("Network problem for send mail")
		return False
	return True

Errors were also initially sent. To begin with, they were accumulated in the list, and then sent also using the scheduler, if there was a connection. However, then there were problems with the fact that yandex has a limit on the number of messages sent per day (this is pain, sadness and humiliation). Since there could be a huge number of errors even per minute, it was necessary to refuse to send errors by mail. So keep in mind when automatically sending through Yandex services about such a problem.

Feedback server

In order to have access to a remote piece of hardware and be able to configure and reconfigure it, I needed an external server. In general, to be fair, it would be right to send all the data to the server and build all the beautiful graphs in the web interface. But not all at once.

I chose as a VPS ruvds.com. It would be possible to take the simplest server. And in general, for my purposes, this would be enough for the eyes. But since I didn’t pay for the server out of my own pocket, I decided to take it with a small margin so that it would be enough if we deploy a web interface, our own SMTP server, vpn, etc. Plus, to be able to set up a Telegram bot and not have problems with its blocking. Therefore, I chose Amsterdam and the following options.

Simultaneous speedtest on multiple LTE modems

Vim2 chose the reverse ssh connection as a way to communicate with the hardware, and as practice has shown, it is not the best. When the connection is broken, the server holds the port and it is impossible to connect to it for a while. Therefore, it is still better to use other communication methods, such as vpn. In the future, I wanted to switch to vpn, but did not have time.

I will not go into the details of setting up a firewall, restricting rights, disabling the ssh connection to root, and other common truths of setting up a VPS. I want to believe that you already know everything. For a remote connection, I create a new user on the server.

adduser vimssh

On our piece of iron I generate ssh connection keys.

ssh-keygen

And I copy them to our server.

ssh-copy-id [email protected]

On our hardware, I create an automatic reverse ssh connection at each boot.

[Unit] Description=Auto Reverse SSH
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 [email protected]
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

Pay attention to port 8083: it determines on which port I will connect via reverse ssh. Add to autoload and start.

sudo systemctl enable autossh.service
sudo systemctl start autossh.service

You can even see the status:

sudo systemctl status autossh.service

Now, on our VPS server, if you run:

ssh -p 8083 khadas@localhost

Then I get on my test piece of iron. And from a piece of iron I can also send logs and any data via ssh to my server, which is very convenient.

Putting it all together

Simultaneous speedtest on multiple LTE modems
Power on, start developing and debugging

Phew, well, everything seems to have described all the nodes. Now it's time to put it all together. You can see the code here.

An important point with the code: This project may not start up like this, because it was sharpened for a specific task, a specific architecture. Although I give the source code, I will still analyze the most valuable here, right in the text, otherwise it is completely incomprehensible.

At the beginning, I am initializing gps, gpio and launching a separate scheduler thread.

#запуск потока планировщика
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()

The scheduler is quite simple: it looks to see if the time to send messages has come and what the error status is now. If there is an error flag, then blink the LED.

#sheduler
def ShedulerThread(name):
	global ready_to_send
	while True:
		d = datetime.today()
		time_x = d.strftime('%H:%M')
		if time_x in time_send_csv:
			ready_to_send = True
		if error_status:
			error_blink()
		else:
			good_blink()
		time.sleep(1)

The hardest part of this project is keeping the reverse ssh connection alive on every test. In each test, the default gateway and dns server are reconfigured. Since no one reads anyway, know that the train does not ride on wooden rails. Whoever finds an Easter egg gets candy.

To do this, I create a separate routing table --set-mark 0x2 and a rule to redirect traffic.

def InitRouteForSSH():
	cmd_run("sudo iptables -t mangle -A OUTPUT -p tcp -m tcp --dport 22 -j MARK --set-mark 0x2")
	cmd_run("sudo ip rule add fwmark 0x2/0x2 lookup 102")

You can learn more about how it works read in this article.

After that, I go into an infinite loop, where each time we get a list of connected modems (to find out if the network configuration has suddenly changed).

network_list = getNetworklist()

Getting a list of network interfaces is quite simple.

def getNetworklist():
	full_networklist = os.listdir('/sys/class/net/')
	network_list = [x for x in full_networklist if "eth" in x and x != "eth0"]
	return network_list

After receiving the list, I set the IP addresses to all interfaces, as I showed in the picture in the modem chapter.

SetIpAllNetwork(network_list)

def SetIpAllNetwork(network_list):
	for iface in network_list:
		lastip = "%d" % (3 + network_list.index(iface))
		cmd_run ("sudo ifconfig " + iface + " 192.168.8." + lastip +" up")

Further simply in a cycle I go on each interface. And I configure each interface.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#сбрасываем все настройки
		cmd_run("sudo ip route flush all")
#Назначаем шлюз по умолчанию
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#задаем dns-сервер (это нужно для работы speedtest)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

I check the interface for operability, if there is no network, then I generate errors. If there is a network, then it's time to act!

Here I set up ssh routing to this interface (if not already done), send errors to the server if it's time, send logs and finally run a speedtest and save the logs to a csv file.

if not NetworkAvalible():
....
#Здесь мы формируем ошибки
....
else: #Есть сеть, ура, работаем!
#Если у нас проблемный интерфейс, на котором ssh, то меняем его
  if (sshint == lastbanint or sshint =="free"):
    print("********** Setup SSH ********************")
    if sshint !="free":
      сmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint +" table 102")
    SetupReverseSSH(iface)
    sshint = iface
#раз сетка работает, то давай срочно все отправим!!!
    if ready_to_send:
      print ("**** Ready to send!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#и далее тестируем скорость и сохраняем логи. 

Unless it's worth mentioning the reverse ssh configuration function.

def SetupReverseSSH(iface):
	cmd_run("sudo systemctl stop autossh.service")
	cmd_run("sudo ip route add default via 192.168.8.1 dev " + iface +" table 102")
	cmd_run("sudo systemctl start autossh.service")

And of course, you need to add all this beauty to autoload. To do this, I create a file:

sudo vim /etc/systemd/system/modems_speedtest.service

And I write to it:

[Unit] Description=Modem Speed Test
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/python3.6 /home/khadas/modems_speedtest/networks.py
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

I turn on autoload and start!

sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.service

Now I can see the logs of what is happening with the command:

journalctl -u modems_speedtest.service --no-pager -f

The results

Well, now the most important thing, what happened as a result? Here are a few graphs that I managed to capture during development and debugging. Graphs were built using gnuplot with the following script.

#! /usr/bin/gnuplot -persist
set terminal postscript eps enhanced color solid
set output "Rostelecom.ps"
 
#set terminal png size 1024, 768
#set output "Rostelecom.png"
 
set datafile separator ';'
set grid xtics ytics
set xdata time
set ylabel "Speed Mb/s"
set xlabel 'Time'
set timefmt '%d.%m.%Y;%H:%M:%S'
set title "Rostelecom Speed"

plot "Rostelecom.csv" using 3:6 with lines title "Download", '' using 3:7 with lines title "Upload"
 
set title "Rostelecom 2 Ping"
set ylabel "Ping ms"
plot "Rostelecom.csv" using 3:8 with lines title "Ping"

The first experience was the Tele2 operator, which I spent several days.

Simultaneous speedtest on multiple LTE modems

Here I used a dynamic measuring server. Speed ​​measurements work, but they float very much, but some average value is still visible, and it can be obtained by filtering the data, for example, by moving average.

Later, I built a number of graphs for other telecom operators. In this case, there was already one testing server, and the results are also very interesting.

Simultaneous speedtest on multiple LTE modems

Simultaneous speedtest on multiple LTE modems

Simultaneous speedtest on multiple LTE modems

Simultaneous speedtest on multiple LTE modems

As you can see, the topic is very extensive for research and processing of this data, and obviously does not pull for a couple of weeks of work. But…

Outcome of work

The work was abruptly completed due to circumstances beyond my control. One of the weaknesses of this project, in my subjective opinion, was the modem, which did not really want to work simultaneously with other modems, and made such tricks with each boot. For these purposes, there are a huge number of other models of modems, usually they already have the Mini PCI-e format and are placed inside the device and are much easier to configure. But that's a completely different story. The project was interesting and I was very glad that I was able to participate in it.

Simultaneous speedtest on multiple LTE modems

Source: habr.com

Add a comment