Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Während der Quarantäne wurde mir angeboten, an der Entwicklung eines Geräts zur Geschwindigkeitsmessung von LTE-Modems für mehrere Mobilfunkbetreiber mitzuwirken.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Der Kunde wollte die Geschwindigkeit verschiedener Telekommunikationsbetreiber an verschiedenen geografischen Standorten bewerten, um herauszufinden, welcher Mobilfunkanbieter für ihn bei der Installation von Geräten mit LTE-Verbindung, beispielsweise für Videoübertragungen, am besten geeignet ist. Gleichzeitig sollte das Problem möglichst einfach und kostengünstig gelöst werden, ohne teure Geräte.

Ich sage gleich, dass die Aufgabe nicht die einfachste und wissensintensivste ist; ich erzähle Ihnen, auf welche Probleme ich gestoßen bin und wie ich sie gelöst habe. So lass uns gehen.

Beachten

Die Messung der Geschwindigkeit einer LTE-Verbindung ist eine sehr komplexe Angelegenheit: Sie müssen die richtige Ausrüstung und Messtechnik auswählen und außerdem über ein gutes Verständnis der Topologie und Funktionsweise des Mobilfunknetzes verfügen. Darüber hinaus kann die Geschwindigkeit von mehreren Faktoren beeinflusst werden: der Anzahl der Teilnehmer in einer Zelle, den Wetterbedingungen und sogar von Zelle zu Zelle kann die Geschwindigkeit aufgrund der Netzwerktopologie dramatisch variieren. Im Allgemeinen handelt es sich hierbei um ein Problem mit einer großen Anzahl von Unbekannten, das nur ein Telekommunikationsbetreiber richtig lösen kann.

Zunächst wollte der Kunde lediglich mit den Telefonen der Betreiber den Kurier fahren, Messungen direkt am Telefon vornehmen und anschließend die Ergebnisse der Geschwindigkeitsmessung in ein Notizbuch schreiben. Meine Lösung zur Messung der Geschwindigkeit von LTE-Netzwerken ist zwar nicht ideal, löst aber das Problem.

Aus Zeitmangel habe ich mich nicht für Bequemlichkeit oder Praktikabilität entschieden, sondern für die Geschwindigkeit der Entwicklung. Beispielsweise wurde für den Fernzugriff Reverse SSH anstelle des praktischeren VPN verwendet, um Zeit bei der Einrichtung des Servers und jedes einzelnen Clients zu sparen.

Technische Aufgabe

Wie im Artikel angegeben Ohne technische Spezifikationen: Warum der Kunde es nicht will: Arbeiten Sie nicht ohne technische Spezifikationen! Niemals und nirgendwo!

Die technische Aufgabe war recht einfach, ich werde sie zum Verständnis des Endbenutzers etwas erweitern. Die Wahl der technischen Lösungen und Ausstattung wurde vom Kunden vorgegeben. Also die technische Spezifikation selbst, nach allen Genehmigungen:

Basierend auf einem Einplatinencomputer vim2 Erstellen Sie einen Geschwindigkeitstester für LTE-Verbindungen über H-ModemsHuawei E3372h – 153 mehrere Telekommunikationsbetreiber (von eins bis n). Es ist außerdem notwendig, Koordinaten von einem über UART angeschlossenen GPS-Empfänger zu empfangen. Führen Sie Geschwindigkeitsmessungen mit dem Dienst durch www.speedtest.net und lege sie in eine Tabelle wie:

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Tabelle im CSV-Format. Dann verschicken Sie dieses Zeichen alle 6 Stunden per E-Mail. Bei Fehlern blinkt die LED, die mit dem GPIO verbunden ist.

Ich habe die technischen Spezifikationen nach vielen Genehmigungen in freier Form beschrieben. Aber der Sinn der Aufgabe ist bereits erkennbar. Für alles wurde eine Woche gegeben. Aber in Wirklichkeit dauerte es drei Wochen. Dies trägt der Tatsache Rechnung, dass ich dies nur nach meinem Hauptberuf und am Wochenende getan habe.

An dieser Stelle möchte ich noch einmal darauf aufmerksam machen, dass der Kunde vorab der Nutzung des Geschwindigkeitsmessdienstes und der Hardware zugestimmt hat, was meine Möglichkeiten stark einschränkte. Auch das Budget war begrenzt, sodass nichts Besonderes angeschafft wurde. Also mussten wir uns an diese Regeln halten.

Architektur und Entwicklung

Das Schema ist einfach und offensichtlich. Daher werde ich es ohne besondere Kommentare belassen.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Ich habe mich entschieden, das gesamte Projekt in Python umzusetzen, obwohl ich überhaupt keine Erfahrung mit der Entwicklung in dieser Sprache hatte. Ich habe mich dafür entschieden, weil es eine Menge vorgefertigter Beispiele und Lösungen gab, die die Entwicklung beschleunigen könnten. Deshalb bitte ich alle professionellen Programmierer, nicht über meine ersten Erfahrungen mit der Entwicklung in Python zu schimpfen, und ich freue mich immer über konstruktive Kritik, um meine Fähigkeiten zu verbessern.

Dabei entdeckte ich auch, dass Python zwei laufende Versionen 2 und 3 hat, weshalb ich mich für die dritte entschied.

Hardwareknoten

Einzelplatte vim2

Als Hauptmaschine wurde mir ein Einplatinencomputer zur Verfügung gestellt vim2

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Ein ausgezeichneter, leistungsstarker Medienprozessor für Smart Home und SMART-TV, aber für diese Aufgabe äußerst ungeeignet, oder sagen wir, schlecht geeignet. Das Hauptbetriebssystem ist beispielsweise Android, und Linux ist ein sekundäres Betriebssystem, und dementsprechend garantiert niemand den qualitativ hochwertigen Betrieb aller Knoten und Treiber unter Linux. Und ich gehe davon aus, dass einige der Probleme mit den USB-Treibern dieser Plattform zusammenhingen, sodass die Modems auf diesem Board nicht wie erwartet funktionierten. Außerdem gibt es eine sehr dürftige und verstreute Dokumentation, so dass die Durchsuchung der Docks bei jedem Vorgang viel Zeit in Anspruch nahm. Selbst die normale Arbeit mit GPIO hat viel Blut gekostet. Ich habe zum Beispiel mehrere Stunden gebraucht, um die LED einzurichten. Aber objektiv gesehen war es im Grunde egal, was für ein Single-Board es war, Hauptsache es funktionierte und es gab USB-Anschlüsse.

Zuerst muss ich Linux auf diesem Board installieren. Um nicht für jeden und auch für diejenigen, die sich mit diesem Einplatinensystem befassen, die Wildnis der Dokumentation zu durchforsten, schreibe ich dieses Kapitel.

Es gibt zwei Möglichkeiten, Linux zu installieren: auf einer externen SD-Karte oder auf einer internen MMC. Ich verbrachte einen Abend damit, herauszufinden, wie ich es mit der Karte zum Laufen bringen könnte, und beschloss, es auf der MMC zu installieren, obwohl es ohne Zweifel viel einfacher wäre, mit einer externen Karte zu arbeiten.

Über die Firmware hier schief erzählt. Ich übersetze aus dem Fremden ins Russische. Um das Board zu flashen, muss ich den Hardware-UART anschließen. Habe es angeschlossen wie folgt.

  • Werkzeug-Pin GND: <-> Pin17 des GPIO des VIMs
  • Werkzeug-Pin TXD: <-> Pin18 des GPIO des VIMs (Linux_Rx)
  • Tool Pin RXD: <-> Pin19 des GPIO des VIMs (Linux_Tx)
  • Werkzeug-Pin VCC: <-> Pin20 des GPIO des VIMs

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Anschließend habe ich die Firmware heruntergeladen daher. Spezifische Firmware-Version VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Um diese Firmware hochzuladen, benötige ich Dienstprogramme. Weitere Details dazu hier. Ich habe noch nicht versucht, es unter Windows zu flashen, aber ich muss Ihnen ein paar Worte zur Firmware unter Linux sagen. Zuerst installiere ich die Dienstprogramme gemäß den Anweisungen.

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

Uuund... Nichts funktioniert. Ich habe ein paar Stunden damit verbracht, die Installationsskripte zu bearbeiten, damit bei mir alles korrekt installiert wird. Ich weiß nicht mehr, was ich dort gemacht habe, aber es gab auch einen Zirkus mit Pferden. Also sei vorsichtig. Aber ohne diese Dienstprogramme macht es keinen Sinn, vim2 weiter zu quälen. Es ist besser, sich überhaupt nicht mit ihm anzulegen!

Nach sieben Höllenrunden, Skriptkonfiguration und Installation erhielt ich ein Paket mit funktionierenden Dienstprogrammen. Ich habe das Board über USB an meinen Linux-Computer angeschlossen und auch den UART gemäß der obigen Abbildung angeschlossen.
Ich richte mein Lieblings-Minicom-Terminal auf eine Geschwindigkeit von 115200 ein, ohne Hardware- und Software-Fehlerkontrolle. Und fangen wir an.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Beim Laden von VIM2 im UART-Terminal drücke ich eine Taste, beispielsweise die Leertaste, um den Ladevorgang zu stoppen. Nachdem die Zeile erscheint

kvim2# 

Ich gebe den Befehl ein:

kvim2# run update

Auf dem Host, von dem wir laden, führe ich Folgendes aus:

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

Das ist es, puh. Ich habe nachgesehen, dass Linux auf dem Board ist. Login/Passwort khadas:khadas.

Danach einige kleinere Grundeinstellungen. Für weitere Arbeiten deaktiviere ich das Passwort für sudo (ja, nicht sicher, aber praktisch).

sudo visudo

Ich bearbeite die Zeile im Formular und speichere sie

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

Dann ändere ich das aktuelle Gebietsschema so, dass die Zeit in Moskau ist, andernfalls in Greenwich.

sudo timedatectl set-timezone Europe/Moscow

oder

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

Wenn es Ihnen schwer fällt, dann verwenden Sie dieses Board nicht; Raspberry Pi ist besser. Ehrlich.

Modem Huawei e3372h – 153

Dieses Modem war für mich eine wichtige Blutquelle und wurde tatsächlich zum Flaschenhals des gesamten Projekts. Im Allgemeinen spiegelt der Name „Modem“ für diese Geräte überhaupt nicht das Wesentliche der Arbeit wider: Dies ist ein leistungsstarker Mähdrescher, diese Hardware verfügt über ein zusammengesetztes Gerät, das vorgibt, eine CD-ROM zu sein, um Treiber zu installieren. und wechselt dann in den Netzwerkkartenmodus.

Architektonisch sieht es aus Sicht eines Linux-Benutzers nach allen Einstellungen so aus: Nach dem Anschließen des Modems habe ich eine eth*-Netzwerkschnittstelle, die über DHCP die IP-Adresse 192.168.8.100 erhält, und das Standard-Gateway ist 192.168.8.1.

Und der wichtigste Moment! Dieses Modemmodell kann nicht im Modemmodus arbeiten, der durch AT-Befehle gesteuert wird. Alles wäre viel einfacher, für jedes Modem PPP-Verbindungen erstellen und dann damit arbeiten. Aber in meinem Fall erstellt „er selbst“ (genauer gesagt ein Linux-Taucher nach den udev-Regeln) eine Eth-Schnittstelle und weist ihr per DHCP eine IP-Adresse zu.

Um weitere Verwirrung zu vermeiden, schlage ich vor, das Wort „Modem“ zu vergessen und stattdessen „Netzwerkkarte“ und „Gateway“ zu sagen, denn im Grunde ist es so, als würde man eine neue Netzwerkkarte mit einem Gateway verbinden.
Bei einem Modem bereitet das keine besonderen Probleme, bei mehreren, nämlich n-Stücken, ergibt sich folgendes Netzwerkbild.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Das heißt, n Netzwerkkarten mit derselben IP-Adresse und jeweils demselben Standard-Gateway. Tatsächlich ist jedoch jeder von ihnen mit seinem eigenen Betreiber verbunden.

Anfangs hatte ich eine einfache Lösung: Schalten Sie mit dem Befehl ifconfig oder ip alle Schnittstellen aus und schalten Sie nacheinander einfach eine ein und testen Sie sie. Die Lösung war für alle gut, außer dass ich während der Umschaltmomente keine Verbindung zum Gerät herstellen konnte. Und da das Umschalten häufig und schnell erfolgt, hatte ich eigentlich überhaupt keine Möglichkeit, eine Verbindung herzustellen.

Deshalb habe ich den Weg gewählt, die IP-Adressen der Modems manuell zu ändern und dann den Verkehr über Routing-Einstellungen zu steuern.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Damit waren meine Probleme mit Modems noch nicht beendet: Bei Stromproblemen fielen sie ab und es war eine gute, stabile Stromversorgung des USB-Hubs erforderlich. Ich habe dieses Problem gelöst, indem ich die Stromversorgung direkt an die Nabe festgelötet habe. Ein weiteres Problem, auf das ich gestoßen bin und das das gesamte Projekt ruiniert hat: Nach einem Neustart oder Kaltstart des Geräts wurden nicht alle Modems und nicht immer erkannt, und ich konnte nicht feststellen, warum dies geschah und durch welchen Algorithmus. Aber das Wichtigste zuerst.

Damit das Modem ordnungsgemäß funktioniert, habe ich das Paket usb-modeswitch installiert.

sudo apt update
sudo apt install -y usb-modeswitch

Nach der Verbindung wird das Modem vom udev-Subsystem korrekt erkannt und konfiguriert. Ich überprüfe es, indem ich einfach das Modem anschließe und sicherstelle, dass das Netzwerk angezeigt wird.
Ein weiteres Problem, das ich nicht lösen konnte: Wie kann ich von diesem Modem den Namen des Betreibers erfahren, mit dem wir zusammenarbeiten? Der Betreibername ist in der Modem-Weboberfläche unter 192.168.8.1 enthalten. Dies ist eine dynamische Webseite, die Daten über Ajax-Anfragen empfängt. Daher wird es nicht funktionieren, die Seite einfach abzurufen und den Namen zu analysieren. Also fing ich an zu überlegen, wie man eine Webseite usw. entwickelt, und stellte fest, dass ich irgendeinen Unsinn machte. Infolgedessen spuckte er aus und der Betreiber begann, über die Speedtest-API selbst zu empfangen.

Viel einfacher wäre es, wenn das Modem über AT-Befehle Zugriff hätte. Es wäre möglich, es neu zu konfigurieren, eine PPP-Verbindung herzustellen, eine IP zuzuweisen, einen Telekommunikationsbetreiber zu beauftragen usw. Aber leider arbeite ich mit dem, was mir gegeben wurde.

GPS- Ortung

Der GPS-Empfänger, den ich bekam, verfügte über eine UART-Schnittstelle und Strom. Es war nicht die beste Lösung, aber dennoch praktikabel und einfach. Der Empfänger sah ungefähr so ​​aus.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Ehrlich gesagt habe ich zum ersten Mal mit einem GPS-Empfänger gearbeitet, aber wie erwartet war alles schon vor langer Zeit für uns geplant. Deshalb nutzen wir einfach fertige Lösungen.

Zuerst aktiviere ich uart_AO_B (UART_RX_AO_B, UART_TX_AO_B), um eine GPS-Verbindung herzustellen.

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

Anschließend prüfe ich den Erfolg der Operation.

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

Dieser Befehl bearbeitet den Devtree offenbar im Handumdrehen, was sehr praktisch ist.

Nachdem dieser Vorgang erfolgreich war, starten Sie den GPS-Daemon neu und installieren Sie ihn.

khadas@Khadas:~$ sudo reboot

Installieren des GPS-Daemons. Ich installiere alles und schneide es sofort zur weiteren Konfiguration ab.

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

Bearbeiten der Einstellungsdatei.

sudo vim /etc/default/gpsd

Ich installiere einen UART, an dem das GPS hängt.

DEVICES="/dev/ttyS4"

Und dann schalten wir alles ein und starten.

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

Danach schließe ich das GPS an.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Das GPS-Kabel liegt in meinen Händen, die UART-Debugger-Kabel sind unter meinen Fingern sichtbar.

Ich starte neu und überprüfe den GPS-Betrieb mit dem Programm gpsmon.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

In diesem Screenshot sind die Satelliten nicht zu sehen, aber die Kommunikation mit dem GPS-Empfänger ist zu sehen, was bedeutet, dass alles in Ordnung ist.

In Python habe ich viele Optionen für die Arbeit mit diesem Daemon ausprobiert, mich aber für die entschieden, die mit Python 3 korrekt funktionierte.

Ich installiere die notwendige Bibliothek.

sudo -H pip3 install gps3 

Und ich gestalte den Arbeitscode.

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

Wenn ich Koordinaten benötige, geschieht dies mit folgendem Aufruf:

longitude, latitude = getPositionData(agps_thread)

Und innerhalb von 1-10 Sekunden erhalte ich entweder die Koordinate oder nicht. Ja, ich hatte zehn Versuche, Koordinaten zu bekommen. Nicht optimal, schief und schief, aber es funktioniert. Ich habe mich dafür entschieden, weil GPS einen schlechten Empfang haben kann und nicht immer Daten empfängt. Wenn Sie auf den Empfang von Daten warten und in einem entfernten Raum arbeiten, friert das Programm an diesem Ort ein. Deshalb habe ich diese unelegante Option implementiert.

Prinzipiell wäre es bei mehr Zeit möglich, GPS-Daten direkt über UART zu empfangen, in einem separaten Thread zu analysieren und damit zu arbeiten. Aber es gab überhaupt keine Zeit, daher der brutal hässliche Code. Und ja, ich schäme mich nicht.

LED

Der Anschluss der LED war einfach und schwierig zugleich. Die Hauptschwierigkeit besteht darin, dass die Pin-Nummer im System nicht mit der Pin-Nummer auf der Platine übereinstimmt und dass die Dokumentation mit der linken Hand geschrieben wird. Um die Hardware-Pin-Nummer und die Pin-Nummer im Betriebssystem zu vergleichen, müssen Sie den folgenden Befehl ausführen:

gpio readall

Es wird eine Tabelle der Pin-Entsprechungen im System und auf der Tafel angezeigt. Danach kann ich den Pin bereits im OS selbst bedienen. In meinem Fall ist die LED angeschlossen GPIOH_5.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Ich schalte den GPIO-Pin in den Ausgabemodus.

gpio -g mode 421 out

Ich schreibe Null auf.

gpio -g write 421 0

Ich schreibe eins auf.

gpio -g write 421 1

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems
Alles leuchtet, nachdem „1“ geschrieben wurde

#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)

Jetzt rufe ich im Fehlerfall error_blink() auf und die LED blinkt wunderschön.

Softwareknoten

Speedtest-API

Es ist eine große Freude, dass der speedtest.net-Dienst über eine eigene Python-API verfügt, die Sie sich ansehen können Github.

Das Gute ist, dass es Quellcodes gibt, die auch eingesehen werden können. Wie Sie mit dieser API arbeiten (einfache Beispiele), finden Sie in entsprechenden Abschnitt.

Ich installiere die Python-Bibliothek mit dem folgenden Befehl.

sudo -H pip3 install speedtest-cli

Beispielsweise können Sie in Ubuntu sogar einen Geschwindigkeitstester direkt aus der Software heraus installieren. Dabei handelt es sich um dieselbe Python-Anwendung, die dann direkt von der Konsole aus gestartet werden kann.

sudo apt install speedtest-cli -y

Und messen Sie Ihre Internetgeschwindigkeit.

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

Im Ergebnis, genau wie ich. Ich musste mich mit den Quellcodes dieses Geschwindigkeitstests befassen, um sie vollständiger in mein Projekt implementieren zu können. Eine der wichtigsten Aufgaben besteht darin, den Namen des Telekommunikationsbetreibers zu ermitteln, um ihn in das Schild einzufügen.

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"
#тут идет запись в файл логов

Auch hier stellte sich heraus, dass nicht alles so einfach war, obwohl es viel einfacher erscheinen würde. Ursprünglich war der Serverparameter gleich []Sie sagen, wählen Sie den besten Server. Infolgedessen hatte ich zufällige Server und, wie Sie sich vorstellen können, eine variable Geschwindigkeit. Dies ist ein ziemlich komplexes Thema. Die Verwendung eines festen Servers, ob statisch oder dynamisch, erfordert Recherche. Aber hier ist ein Beispiel für Geschwindigkeitsmessdiagramme für einen Beeline-Betreiber bei der dynamischen Auswahl eines Testservers und eines statisch festen Servers.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems
Das Ergebnis der Geschwindigkeitsmessung bei der Auswahl eines dynamischen Servers.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems
Das Ergebnis eines Geschwindigkeitstests mit einem streng ausgewählten Server.

Bei der Prüfung kommt es an beiden Stellen zu „Fell“, das mit mathematischen Methoden entfernt werden muss. Bei einem festen Server ist sie jedoch etwas geringer und die Amplitude ist stabiler.
Im Allgemeinen ist dies ein Ort großartiger Forschung. Und ich würde die Geschwindigkeit meines Servers mit dem Dienstprogramm iperf messen. Wir halten uns aber an die technischen Vorgaben.

E-Mail-Versand und Fehler

Um E-Mails zu versenden, habe ich mehrere Dutzend verschiedene Optionen ausprobiert, aber am Ende habe ich mich für Folgendes entschieden. Ich habe ein Postfach bei Yandex registriert und dann genommen Dies ist ein Beispiel für das Versenden von E-Mails. Ich habe es überprüft und in das Programm implementiert. In diesem Beispiel werden verschiedene Optionen untersucht, darunter das Senden über Gmail usw. Ich wollte mich nicht um die Einrichtung meines Mailservers kümmern und hatte auch keine Zeit dafür, aber wie sich später herausstellte, war es auch vergebens.

Die Protokolle wurden gemäß dem Planer gesendet. wenn es einen Zusammenhang gibt, alle 6 Stunden: um 00 Uhr, 06 Uhr, 12 Uhr und 18 Uhr. Habe es wie folgt verschickt.

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

Es wurden zunächst auch Fehler gesendet. Sie wurden zunächst in der Liste gesammelt und dann bei bestehender Verbindung auch über den Scheduler versendet. Dann traten jedoch Probleme mit der Tatsache auf, dass Yandex die Anzahl der pro Tag gesendeten Nachrichten begrenzt (das ist Schmerz, Traurigkeit und Demütigung). Da es schon pro Minute zu sehr vielen Fehlern kommen konnte, mussten wir auf den Fehlerversand per Post verzichten. Denken Sie also daran, wenn Sie automatisch Informationen zu einem solchen Problem über Yandex-Dienste senden.

Feedback-Server

Um Zugriff auf eine Remote-Hardware zu haben und diese anpassen und neu konfigurieren zu können, benötigte ich einen externen Server. Um fair zu sein, wäre es im Allgemeinen richtig, alle Daten an den Server zu senden und alle schönen Grafiken in der Weboberfläche zu erstellen. Aber nicht alles auf einmal.

Für VPS habe ich mich entschieden ruvds.com. Sie könnten den einfachsten Server nehmen. Und im Allgemeinen würde dies für meine Zwecke ausreichen. Da ich den Server aber nicht aus eigener Tasche bezahlt habe, habe ich mich entschieden, ihn mit einer kleinen Reserve zu nehmen, sodass es ausreichen würde, wenn wir ein Webinterface, einen eigenen SMTP-Server, VPN usw. bereitstellen würden. Außerdem können Sie einen Telegram-Bot einrichten und haben keine Probleme mit dessen Blockierung. Daher habe ich mich für Amsterdam und die folgenden Parameter entschieden.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Als Kommunikationsmethode mit der Hardware wählte vim2 eine umgekehrte SSH-Verbindung und wie die Praxis gezeigt hat, ist diese nicht die beste. Wenn die Verbindung unterbrochen wird, behält der Server den Port und es ist für einige Zeit nicht möglich, über ihn eine Verbindung herzustellen. Daher ist es immer noch besser, andere Kommunikationsmethoden zu verwenden, beispielsweise VPN. In Zukunft wollte ich auf VPN umsteigen, hatte aber keine Zeit.

Ich werde nicht näher auf die Einrichtung einer Firewall, das Einschränken von Rechten, das Deaktivieren von Root-SSH-Verbindungen und andere Binsenweisheiten beim Einrichten eines VPS eingehen. Ich würde gerne glauben, dass Sie bereits alles wissen. Für eine Remote-Verbindung erstelle ich einen neuen Benutzer auf dem Server.

adduser vimssh

Ich generiere SSH-Verbindungsschlüssel auf unserer Hardware.

ssh-keygen

Und ich kopiere sie auf unseren Server.

ssh-copy-id [email protected]

Auf unserer Hardware erstelle ich bei jedem Booten eine automatische Reverse-SSH-Verbindung.

[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

Achten Sie auf Port 8083: Er bestimmt, welchen Port ich für die Verbindung über Reverse SSH verwende. Fügen Sie es zum Startup hinzu und starten Sie.

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

Sie können sogar den Status sehen:

sudo systemctl status autossh.service

Wenn wir nun auf unserem VPS-Server Folgendes ausführen:

ssh -p 8083 khadas@localhost

Dann komme ich zu meiner Testhardware. Und von der Hardware aus kann ich auch Protokolle und beliebige Daten per SSH an meinen Server senden, was sehr praktisch ist.

Alles zusammensetzen

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems
Nach dem Einschalten beginnen wir mit der Entwicklung und dem Debuggen

Puh, das war's, ich habe alle Knoten beschrieben. Jetzt ist es an der Zeit, alles zusammenzustellen. Sie können den Code sehen hierher.

Ein wichtiger Punkt beim Code: Dieses Projekt startet möglicherweise nicht so, weil es auf eine bestimmte Aufgabe, eine bestimmte Architektur zugeschnitten wurde. Auch wenn ich den Quellcode gebe, erkläre ich die wertvollsten Dinge hier direkt im Text, sonst ist es völlig unverständlich.

Zu Beginn initialisiere ich GPS, GPIO und starte einen separaten Scheduler-Thread.

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

Der Scheduler ist ganz einfach: Er prüft, ob der Zeitpunkt zum Versenden von Nachrichten gekommen ist und wie der aktuelle Fehlerstatus ist. Wenn ein Fehlerflag vorliegt, blinken wir die 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)

Der schwierigste Teil dieses Projekts besteht darin, die umgekehrte SSH-Verbindung für jeden Test aufrechtzuerhalten. Bei jedem Test müssen das Standard-Gateway und der DNS-Server neu konfiguriert werden. Da sowieso niemand liest, sei darauf hingewiesen, dass der Zug nicht auf Holzschienen fährt. Wer das Osterei findet, bekommt Süßigkeiten.

Dazu erstelle ich eine separate Routing-Tabelle -set-mark 0x2 und eine Regel zur Umleitung des Datenverkehrs.

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")

Sie können mehr darüber erfahren, wie es funktioniert in diesem Artikel lesen.

Danach gehe ich in eine Endlosschleife, in der wir jedes Mal eine Liste der angeschlossenen Modems erhalten (um herauszufinden, ob sich die Netzwerkkonfiguration plötzlich geändert hat).

network_list = getNetworklist()

Eine Liste der Netzwerkschnittstellen zu erhalten ist ganz einfach.

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

Nach Erhalt der Liste habe ich für alle Schnittstellen IP-Adressen eingestellt, wie ich es im Bild im Kapitel über das Modem gezeigt habe.

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")

Dann gehe ich einfach jede Schnittstelle in einer Schleife durch. Und ich konfiguriere jede Schnittstelle.

	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'")

Ich überprüfe die Schnittstelle auf Funktionsfähigkeit, wenn kein Netzwerk vorhanden ist, dann erzeuge ich Fehler. Wenn es ein Netzwerk gibt, ist es Zeit zu handeln!

Hier konfiguriere ich das SSH-Routing zu dieser Schnittstelle (falls noch nicht geschehen), sende Fehler an den Server, wenn es soweit ist, sende Protokolle und führe schließlich einen Geschwindigkeitstest durch und speichere die Protokolle in einer CSV-Datei.

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()
#и далее тестируем скорость и сохраняем логи. 

Erwähnenswert ist die Funktion zum Einrichten von Reverse SSH.

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")

Und natürlich müssen Sie all diese Schönheit zum Startup hinzufügen. Dazu erstelle ich eine Datei:

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

Und ich schreibe darin:

[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

Ich schalte das automatische Laden ein und starte!

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

Jetzt kann ich Protokolle darüber sehen, was passiert, indem ich den folgenden Befehl verwende:

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

Ergebnisse

Nun, das Wichtigste ist, was ist als Ergebnis passiert? Hier sind ein paar Diagramme, die ich während des Entwicklungs- und Debugging-Prozesses erfassen konnte. Die Diagramme wurden mit gnuplot mit dem folgenden Skript erstellt.

#! /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"

Die erste Erfahrung machte ich mit dem Tele2-Betreiber, den ich mehrere Tage lang machte.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Hier habe ich einen dynamischen Messserver verwendet. Geschwindigkeitsmessungen funktionieren zwar, schwanken aber stark, es ist aber immer noch ein gewisser Durchschnittswert sichtbar, der durch Filterung der Daten, beispielsweise mit einem gleitenden Durchschnitt, ermittelt werden kann.

Später habe ich eine Reihe von Diagrammen für andere Telekommunikationsbetreiber erstellt. In diesem Fall gab es bereits einen Testserver und die Ergebnisse waren ebenfalls sehr interessant.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Wie Sie sehen, ist das Thema für die Recherche und Verarbeitung dieser Daten sehr umfangreich und reicht offensichtlich nicht für ein paar Wochen Arbeit aus. Aber…

Das Ergebnis der Arbeit

Die Arbeiten wurden aufgrund von Umständen, die außerhalb meiner Kontrolle lagen, abrupt abgeschlossen. Eine der Schwächen dieses Projekts war meiner subjektiven Meinung nach das Modem, das nicht wirklich gleichzeitig mit anderen Modems arbeiten wollte und bei jedem Laden solche Tricks machte. Für diese Zwecke gibt es eine Vielzahl weiterer Modemmodelle; in der Regel liegen sie bereits im Mini-PCI-e-Format vor, werden im Gerät verbaut und sind deutlich einfacher zu konfigurieren. Aber das ist eine ganz andere Geschichte. Das Projekt war interessant und ich war sehr froh, dass ich daran teilnehmen konnte.

Gleichzeitiger Geschwindigkeitstest auf mehreren LTE-Modems

Source: habr.com

Kommentar hinzufügen