Der Kunde wollte die Geschwindigkeit aller Arten von Telekommunikationsbetreibern an verschiedenen geografischen Standorten bewerten, um zu verstehen, welcher Mobilfunkbetreiber für ihn am besten geeignet ist, wenn Geräte installiert werden, die eine LTE-Verbindung verwenden, beispielsweise für Videosendungen. Gleichzeitig musste die Aufgabe so einfach und kostengünstig wie möglich ohne teure Ausrüstung gelöst werden.
Ich muss sofort sagen, dass die Aufgabe nicht die einfachste und wissensintensivste ist. Ich werde Ihnen sagen, auf welche Probleme ich gestoßen bin und wie ich sie gelöst habe. So lass uns gehen.
Hinweis
Das Messen der Geschwindigkeit einer LTE-Verbindung ist eine sehr schwierige Angelegenheit: Sie müssen die richtige Ausrüstung und Messmethode auswählen und eine gute Vorstellung von der Topologie und dem Betrieb des Mobilfunknetzes haben. Darüber hinaus kann die Geschwindigkeit durch verschiedene Faktoren beeinflusst werden: Die Anzahl der Teilnehmer pro Zelle, die Wetterbedingungen, selbst von Zelle zu Zelle. Die Geschwindigkeit kann aufgrund der Netzwerktopologie auffällig unterschiedlich sein. Im Allgemeinen ist dies ein Problem mit einer großen Anzahl von Unbekannten, und nur ein Telekommunikationsbetreiber kann es richtig lösen.
Zunächst wollte der Kunde den Kurier nur mit den Telefonen der Bediener fahren, Messungen direkt am Telefon durchführen und dann 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 Zeitgründen traf ich Entscheidungen nicht zugunsten der Zweckmäßigkeit oder Praktikabilität, sondern zugunsten der Entwicklungsgeschwindigkeit. Für den Remotezugriff wurde beispielsweise der umgekehrte SSH anstelle des praktischeren VPN ausgelöst, um Zeit beim Einrichten des Servers und jedes einzelnen Clients zu sparen.
Technische Aufgabe
Wie im Artikel Ohne TK angegeben: Warum der Kunde es nicht will : Arbeiten Sie nicht ohne TK! Niemals, nirgendwo!
Die technische Aufgabe war recht einfach, ich werde sie ein wenig erweitern, um den Endbenutzer zu verstehen. Die Auswahl der technischen Lösungen und Geräte wurde vom Kunden vorgegeben. Also, die TK selbst, nach all den Zulassungen:
vim2 lte- Huawei e3372h — 153 ( n). GPS-, UART. www.speedtest.net :
csv. - 6 . , GPIO.
Nach vielen Genehmigungen habe ich die TK in freier Form beschrieben. Die Bedeutung der Aufgabe ist jedoch bereits sichtbar. Die Frist für alles wurde eine Woche gegeben. Aber in Wirklichkeit dauerte es drei Wochen. Dies liegt daran, dass ich es erst nach der Hauptarbeit und am Wochenende gemacht habe.
An dieser Stelle möchte ich Sie darauf aufmerksam machen, dass der Kunde zuvor zugestimmt hatte, den Geschwindigkeitsmessdienst und die Hardware zu nutzen, was meine Fähigkeiten stark einschränkte. Das Budget war ebenfalls begrenzt, so dass zusätzlich nichts gekauft wurde. Also musste ich mich an diese Regeln halten.
Architektur und Entwicklung
Das Schema ist einfach und unkompliziert. Daher werde ich es ohne besondere Kommentare verlassen.
Ich habe mich entschlossen, das gesamte Projekt in Python zu implementieren, obwohl ich überhaupt keine Erfahrung mit der Entwicklung in dieser Sprache hatte. Ich habe mich dafür entschieden, weil es eine Reihe von vorgefertigten Beispielen und Lösungen gab, die die Entwicklung beschleunigen könnten. Deshalb bitte ich alle professionellen Programmierer, meine ersten Erfahrungen in der Python-Entwicklung nicht zu schelten, und ich freue mich immer über konstruktive Kritik, um meine Fähigkeiten zu verbessern.
Dabei habe ich auch festgestellt, dass Python zwei laufende Versionen 2 und 3 hat. Daher habe ich beim dritten angehalten.
Hardwareknoten
Single Board vim2
Als Hauptmaschine erhielt ich ein Single-Board- vim2
Eine exzellente, leistungsstarke Medienkombination für ein 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 vorübergehendes Betriebssystem. Daher garantiert niemand den qualitativ hochwertigen Betrieb aller Knoten und Treiber unter Linux. Und ich nehme an, dass einige der Probleme mit den USB-Treibern dieser Plattform zusammenhängen, sodass die Modems auf diesem Board nicht wie erwartet funktionierten. Er hat auch sehr schlechte und verstreute Unterlagen, so dass jede Operation viel Zeit in Anspruch nahm, um in den Docks zu graben. Selbst die normale Arbeit mit GPIO trank viel Blut. Zum Beispiel habe ich mehrere Stunden gebraucht, um die Arbeit mit der LED einzurichten. Um objektiv zu sein, war es grundsätzlich nicht wichtig, welche Art von Single-Board-Gerät es ist. Hauptsache, es sollte funktionieren und über USB-Anschlüsse verfügen.
Zuerst muss ich Linux auf diesem Board installieren. Um den Dschungel der Dokumentation nicht für alle und auch für diejenigen zu durchsuchen, die sich mit diesem Single-Board-Gerät befassen, schreibe ich dieses Kapitel.
Es gibt zwei Möglichkeiten, Linux zu installieren: auf einer externen SD-Karte oder auf einer internen MMC. Ich hatte abends Probleme mit der Karte und wusste nicht, wie ich sie zum Laufen bringen sollte. Deshalb habe ich beschlossen, sie auf MMC zu installieren, obwohl es ohne Zweifel viel einfacher wäre, mit einer externen Karte zu arbeiten.
Die Firmware wird hier schief beschrieben . Ich übersetze vom Fremden ins Russische. Um die Karte zu flashen, muss ich den Hardware-UART anschließen. Ich habe es wie folgt angeschlossen.
- Tool Pin GND: <—> Pin17 des GPIO von VIMs
- Tool Pin TXD: <—> Pin18 des GPIO von VIMs (Linux_Rx)
- Tool Pin RXD: <—> Pin19 des GPIO von VIMs (Linux_Tx)
- Tool Pin VCC: <—> Pin20 des GPIO von VIMs
Danach habe ich die Firmware von hier heruntergeladen . Die spezifische Firmware-Version lautet VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231 .
Um diese Firmware hochzuladen, benötige ich bestimmte Dienstprogramme. Lesen Sie mehr dazu hier . Ich habe nicht versucht, es unter Windows zu flashen, aber ich muss Ihnen ein paar Worte zur Linux-Firmware sagen. Zuerst installiere ich die Dienstprogramme gemäß den Anweisungen.
git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALL
Iii ... Nichts funktioniert. Ich habe ein paar Stunden damit verbracht, die Installationsskripte so zu bearbeiten, dass alles für mich korrekt installiert wurde. Ich erinnere mich nicht, was ich dort gemacht habe, aber auch an diesen Zirkus mit Pferden. Also sei vorsichtig. Aber ohne diese Dienstprogramme macht es keinen Sinn, vim2 weiter zu quälen. Besser gar nicht mit ihm rumspielen!
Nach sieben Höllenkreisen, Skriptkonfiguration und Installation erhielt ich ein Paket mit funktionierenden Dienstprogrammen. Ich habe die Karte über USB an meinen Linux-Computer angeschlossen, und der UART ist auch gemäß der obigen Abbildung angeschlossen.
Ich stelle mein Lieblings-Minicom-Terminal auf 115200 ein, keine Hardware- oder Software-Fehlerkontrolle. Und fangen wir an.
Beim Booten von VIM2 im UART-Terminal drücke ich eine beliebige Taste, z. B. die Leertaste, um das Booten zu beenden. Nachdem die Zeile angezeigt wird
kvim2#
Ich gebe den Befehl ein:
kvim2# run update
Auf dem Host, von dem wir herunterladen, führe ich Folgendes aus:
burn-tool -v aml -b VIM2 -i VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.img
Jeder, Puh. Ich fragte, es gibt Linux auf dem Board. Login / Passwort khadas: khadas.
Danach kleine Grundeinstellungen. Für weitere Arbeiten deaktiviere ich das Passwort für sudo (ja, nicht sicher, aber praktisch).
sudo visudo
Ich bearbeite die Zeile zur Ansicht und speichere
# 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, sonst ist es GMT.
sudo timedatectl set-timezone Europe/Moscow
oder
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtime
Wenn Sie es schwierig finden, dann verwenden Sie dieses Board nicht, Raspberry Pi ist besser. Messe.
Modem Huawei e3372h - 153
Dieses Modem hat mein Blut gut getrunken, und tatsächlich wurde es zum Engpass 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 Verbundgerät, das sich als CD-ROM ausgibt, um Treiber zu installieren, und wechselt dann in den Netzwerkkartenmodus.
Aus architektonischer Sicht sieht es aus Sicht eines Linux-Benutzers nach allen Einstellungen folgendermaßen aus: Nach dem Anschließen des Modems habe ich eine eth * -Netzwerkschnittstelle, die die IP-Adresse 192.168.8.100 über dhcp empfängt, und das Standard-Gateway 192.168.8.1.
Und der wichtigste Punkt! Dieses Modemmodell kann nicht im Modemmodus arbeiten, der von AT-Befehlen gesteuert wird. Alles wäre viel einfacher, erstellen Sie PPP-Verbindungen für jedes Modem und arbeiten Sie dann mit ihnen. In meinem Fall erstellt "ich" (genauer gesagt ein Linux-Taucher gemäß den udev-Regeln) eine eth-Schnittstelle und weist ihr über dhcp eine IP-Adresse zu.
Um nicht weiter verwirrt zu werden, schlage ich vor, das Wort "Modem" zu vergessen und eine Netzwerkkarte und ein Gateway zu sagen, da es tatsächlich so ist, als würde man eine neue Netzwerkkarte mit einem Gateway verbinden.
Wenn es ein Modem gibt, verursacht dies keine besonderen Probleme. Wenn jedoch mehr als ein Modem vorhanden ist, nämlich n-Teile, wird das folgende Bild des Netzwerks angezeigt.
Das heißt, n Netzwerkkarten mit derselben IP-Adresse und jeweils demselben Standard-Gateway. Tatsächlich ist jeder von ihnen mit seinem eigenen Betreiber verbunden.
Anfangs hatte ich eine einfache Lösung: Verwenden Sie den Befehl ifconfig oder ip, um alle Schnittstellen zu löschen, und schalten Sie nacheinander eine ein und testen Sie sie. Die Lösung war für alle gut, außer dass ich in den Momenten des Wechsels keine Verbindung zum Gerät herstellen konnte. Und da das Umschalten häufig und schnell erfolgt, hatte ich überhaupt keine Gelegenheit, eine Verbindung herzustellen.
Aus diesem Grund habe ich mich dafür entschieden, die IP-Adressen der Modems "manuell" zu ändern und den Datenverkehr mithilfe der Routing-Einstellungen weiter zu steuern.
Dies war nicht das Ende meiner Probleme mit den Modems: Bei Stromproblemen fielen sie aus, und es war eine gute stabile Stromversorgung für den USB-Hub erforderlich. Dieses Problem wurde gelöst, indem das Netzteil direkt an die Nabe gelötet wurde. Ein weiteres Problem, mit dem ich konfrontiert war und das das gesamte Projekt ruinierte: Nach einem Neustart oder einem Kaltstart des Geräts wurden nicht alle Modems erkannt und nicht immer, und warum dies geschah und mit welchem Algorithmus ich nicht installieren konnte. Aber das Wichtigste zuerst.
Damit das Modem richtig funktioniert, habe ich das USB-Modeswitch-Paket installiert.
sudo apt update
sudo apt install -y usb-modeswitch
Danach wird das Modem nach der Verbindung vom udev-Subsystem korrekt erkannt und konfiguriert. Ich überprüfe dies, indem ich einfach das Modem anschließe und sicherstelle, dass das Netzwerk aktiv ist.
Ein weiteres Problem, das ich nicht lösen konnte: Wie erhalte ich den Namen des Operators, mit dem wir arbeiten, von diesem Modem? Der Name des Bedieners ist in der Weboberfläche des Modems unter 192.168.8.1 enthalten. Dies ist eine dynamische Webseite, die Daten über Ajax-Anforderungen empfängt. Sie können also nicht einfach die Seite abrufen und den Namen analysieren. Also fing ich an zu überlegen, wie man eine Webseite usw. erstellt, und stellte fest, dass ich eine Art Unsinn machte. Infolgedessen spuckte er aus und begann, den Bediener über die API des Speedtests selbst zu empfangen.
Viele Dinge wären einfacher, wenn auf das Modem über AT-Befehle zugegriffen werden könnte. Es wäre möglich, es neu zu konfigurieren, eine PPP-Verbindung herzustellen, eine IP zuzuweisen, einen Netzbetreiber zu erhalten usw. Aber leider arbeite ich mit dem, was ich gegeben habe.
GPS
Der GPS-Empfänger, den ich erhielt, hatte eine UART-Schnittstelle und Stromversorgung. Es war nicht die beste Lösung, aber es funktionierte und war einfach. Der Empfänger war so etwas.
Um ehrlich zu sein, war dies das erste Mal, dass ich mit einem GPS-Empfänger gearbeitet habe, aber wie erwartet wurde alles vor langer Zeit für uns erfunden. Wir verwenden also nur vorgefertigte Lösungen.
Zuerst schalte ich uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) ein, um das GPS anzuschließen.
khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okay
Dann überprüfe ich den Erfolg der Operation.
khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okay
Dieser Befehl bearbeitet anscheinend devtree im laufenden Betrieb, was sehr praktisch ist.
Starten Sie nach Abschluss dieses Vorgangs den GPS-Dämon neu und installieren Sie ihn.
khadas@Khadas:~$ sudo reboot
Installieren des GPS-Daemons. Ich installiere alles und schneide es sofort für die weitere 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 den UART, an dem das GPS hängt.
DEVICES="/dev/ttyS4"
Und dann schalten wir alles ein und fangen an.
/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket
Danach schließe ich das GPS an.
Das GPS-Kabel befindet sich in den Händen, die UART-Kabel des Debuggers sind unter den Fingern sichtbar.
Ich starte neu und überprüfe das GPS mit dem Programm gpsmon.
In diesem Screenshot können Sie die Satelliten nicht sehen, aber Sie können die Kommunikation mit dem GPS-Empfänger sehen, und dies besagt, dass alles in Ordnung ist.
In Python habe ich viele Optionen für die Arbeit mit diesem Daemon ausprobiert, aber ich habe mich für die entschieden, die mit Python 3 korrekt funktioniert.
Installieren Sie die erforderliche 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 die Koordinaten erhalten muss, erfolgt dies durch den folgenden Aufruf:
longitude, latitude = getPositionData(agps_thread)
Und innerhalb von 1-10 Sekunden bekomme ich entweder die Koordinate oder nicht. Ja, ich hatte zehn Versuche, die Koordinaten zu ermitteln. Nicht optimal, krumm und schief, aber es funktioniert. Ich habe mich dazu entschlossen, weil GPS schlecht erfassen kann und nicht immer Daten empfängt. Wenn Sie auf den Empfang der Daten warten und in einem entfernten Raum arbeiten, friert das Programm an dieser Stelle ein. Deshalb habe ich eine solche nicht elegante Option implementiert.
Im Prinzip würde es mehr Zeit geben, es wäre möglich, Daten von GPS direkt über UART zu empfangen, sie in einem separaten Stream zu analysieren und mit ihnen zu arbeiten. Aber es war überhaupt keine Zeit, daher der heftige hässliche Code. Und ja, ich schäme mich nicht.
Leuchtdiode
Das Anschließen der LED war gleichzeitig einfach und kompliziert. Die Hauptschwierigkeit besteht darin, dass die PIN-Nummer im System nicht der PIN-Nummer auf der Platine entspricht und dass die Dokumentation mit der linken Ferse geschrieben ist. Um die Hardware-PIN-Nummer und die PIN-Nummer im Betriebssystem abzugleichen, müssen Sie den folgenden Befehl ausführen:
gpio readall
Eine Tabelle mit der PIN-Entsprechung im System und auf der Karte wird angezeigt. Danach kann ich den Pin bereits im Betriebssystem selbst bedienen. In meinem Fall ist die LED mit GPIOH_5 verbunden .
Ich übertrage den GPIO-Pin in den Ausgangsmodus.
gpio -g mode 421 out
Ich schreibe Null auf.
gpio -g write 421 0
Ich schreibe einen auf.
gpio -g write 421 1
Nach der Aufnahme von "1" ist alles eingeschaltet.
#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)
Im Falle von Fehlern rufe ich jetzt error_blink () auf und die LED blinkt gut für uns.
Softwareknoten
Speedtest API
Es ist eine große Freude, dass der Dienst speedtest.net über eine eigene Python-API verfügt, die Sie auf Github sehen können .
Die gute Nachricht ist, dass es Quellcodes gibt, die auch angezeigt werden können. Wie Sie mit dieser API arbeiten (die einfachsten Beispiele), finden Sie im entsprechenden Abschnitt .
Installieren Sie die Python-Bibliothek mit dem folgenden Befehl.
sudo -H pip3 install speedtest-cli
Zum Beispiel können Sie den Geschwindigkeitstester sogar direkt vom Repräsentanten in Ubuntu installieren. Dies ist dieselbe Python-Anwendung, die Sie dann direkt von der Konsole aus ausführen können.
sudo apt install speedtest-cli -y
Und messen Sie die Geschwindigkeit Ihres Internets. Infolgedessen wie ich. Ich musste mich mit den Quellcodes dieses Speedtests befassen, um sie vollständiger in mein Projekt zu implementieren. Eine der wichtigsten Aufgaben besteht darin, den Namen des Telekommunikationsbetreibers zu ermitteln, um ihn in der Platte zu ersetzen.
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
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 alles nicht so einfach war, obwohl es viel einfacher zu sein scheint. Anfangs war der Server-Parameter gleich [] , wählen Sie den besten Server. Infolgedessen hatte ich zufällige Server und, wie Sie sich vorstellen können, schwebende Geschwindigkeit. Dies ist ein ziemlich komplexes Thema, bei dem die Verwendung eines festen Servers, wenn ja, statisch oder dynamisch, Nachforschungen erfordert. Hier ist ein Beispiel für Diagramme zum Messen der Geschwindigkeit des Beeline-Operators mit einer dynamischen Auswahl eines Testservers und eines statisch festgelegten.
Das Ergebnis der Geschwindigkeitsmessung bei der Auswahl eines dynamischen Servers.
Geschwindigkeitstestergebnis mit einem streng ausgewählten Server.
"Wolle" während des Testens ist da und da und muss mit mathematischen Methoden entfernt werden. Bei einem festen Server ist dies jedoch etwas weniger und die Amplitude ist stabiler.
Im Allgemeinen ist dies ein Ort großer Forschung. Und ich würde die Geschwindigkeit zu meinem Server mit dem Dienstprogramm iperf messen. Aber wir bleiben bei der TK.
Senden von E-Mails und Fehlern
Ich habe mehrere Dutzend verschiedene Optionen zum Senden von E-Mails ausprobiert, aber als Ergebnis habe ich mich für Folgendes entschieden. Ich habe ein Postfach bei yandex registriert und dann dieses Beispiel für das Senden von E-Mails verwendet . Ich habe es überprüft und in das Programm implementiert. In diesem Beispiel werden verschiedene Optionen erläutert, darunter das Senden über Google Mail usw. Ich wollte mich nicht darum kümmern, meinen Mailserver zu erhöhen, und hatte keine Zeit dafür, aber wie sich später herausstellte, war es auch vergebens.
Die Protokolle wurden nach Zeitplan alle 6 Stunden gesendet, sofern eine Verbindung bestand: um 00 Uhr, 06:00 Uhr, 12:00 Uhr und 18:00 Uhr. Ich habe es wie folgt gesendet.
from send_email import *
...
message_log = " №1"
EmailForSend = ["dlinyj@trololo.ru", "pupkin@trololo.ru"]
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
Zunächst wurden auch Fehler eingereicht. Zunächst sammelten sie sich in der Liste und sendeten sie dann auch über den Scheduler, wenn eine Verbindung bestand. Dann gab es jedoch Probleme mit der Tatsache, dass Yandex die Anzahl der pro Tag gesendeten Nachrichten begrenzt hat (dies ist Schmerz, Traurigkeit und Demütigung). Da es auch in einer Minute zu einer Vielzahl von Fehlern kommen konnte, musste das Versenden von Fehlern per Post abgelehnt werden. Denken Sie also daran, wenn Sie über ein solches Problem automatisch über Yandex-Dienste senden.
Feedback-Server
Um Zugriff auf eine Remote-Hardware zu haben und diese optimieren und neu konfigurieren zu können, benötigte ich einen externen Server. Im Allgemeinen wäre es fairerweise richtig, alle Daten an den Server zu senden und alle schönen Grafiken in der Weboberfläche zu erstellen. Aber nicht alle auf einmal.
Ich habe ruvds.com als VPS gewählt . Der einfachste Server könnte genommen werden. Und im Allgemeinen würde dies für meine Zwecke für die Augen ausreichen. Da ich den Server jedoch nicht aus eigener Tasche bezahlt habe, habe ich mich für einen kleinen Spielraum entschieden, damit es ausreicht, wenn wir ein Webinterface, unseren eigenen SMTP-Server, VPN usw. bereitstellen. Außerdem können Sie einen Telegramm-Bot einrichten und haben keine Probleme, ihn zu blockieren. Deshalb habe ich Amsterdam und die folgenden Parameter gewählt.
Um mit einer Hardware zu kommunizieren, hat sich vim2 für eine umgekehrte SSH-Verbindung entschieden. Wie die Praxis gezeigt hat, ist dies nicht die beste. Wenn die Verbindung unterbrochen ist, hält der Server den Port und es ist für einige Zeit nicht möglich, eine Verbindung über ihn herzustellen. Daher ist es immer noch besser, andere Kommunikationsmethoden zu verwenden, beispielsweise VPN. In Zukunft wollte ich zu VPN wechseln, hatte aber keine Zeit.
Ich werde nicht näher auf das Einrichten einer Firewall, das Einschränken von Rechten, das Deaktivieren von SSH-Root-Verbindungen und andere allgemeine Wahrheiten der VPS-Einstellungen eingehen. Ich würde gerne glauben, dass Sie bereits alles wissen. Für eine Remoteverbindung erstelle ich einen neuen Benutzer auf dem Server.
adduser vimssh
Auf unserer Hardware generiere ich SSH-Verbindungsschlüssel.
ssh-keygen
Und ich kopiere sie auf unseren Server.
ssh-copy-id vimssh@host.com
Auf unserer Hardware erstelle ich bei jedem Start eine automatische Verbindung des Reverse-SSH. Achten Sie auf Port 8083: Er bestimmt, an welchem Port ich über Reverse SSH eine Verbindung herstellen werde. Zum Start hinzufügen und starten.
[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 vimssh@host.com
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target
sudo systemctl enable autossh.service
sudo systemctl start autossh.service
Sie können sogar den Status sehen:
sudo systemctl status autossh.service
Wenn Sie jetzt auf unserem VPS-Server Folgendes ausführen:
ssh -p 8083 khadas@localhost
Dann komme ich zu meinem Teststück. Und aus dem Stück Eisen kann ich auch Protokolle und alle Daten über ssh an meinen Server senden, was sehr praktisch ist.
Alles zusammenfügen
Beim
Einschalten beginnen wir mit der Entwicklung und dem Debuggen von Fuh. Nun, alles scheint alle Knoten beschrieben zu haben. Jetzt ist es Zeit, alles zusammenzusetzen. Der Code kann hier eingesehen werden .
Ein wichtiger Punkt mit dem Code: Dieses Projekt wie dieses "vlob" wird möglicherweise nicht gestartet, da es für eine bestimmte Aufgabe einer bestimmten Architektur geschärft wurde. Obwohl ich den Quellcode gebe, werde ich hier direkt im Text den wertvollsten analysieren, sonst ist er völlig unverständlich.
Zu Beginn habe ich die Initialisierung von GPS, GPIO und den Start eines separaten Scheduler-Threads.
#
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()
Der Scheduler ist ganz einfach: Er prüft, ob die Zeit zum Senden von Nachrichten gekommen ist und wie der Fehlerstatus jetzt ist. Wenn ein Fehlerflag vorliegt, blinken Sie 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 Punkt in diesem Projekt ist es, bei jedem Test die umgekehrte SSH-Verbindung beizubehalten. In jedem Test werden das Standard-Gateway und der DNS-Server neu konfiguriert. Da sowieso niemand liest, beachten Sie, dass der Zug nicht auf Holzschienen rollt. Wer ein Osterei findet, hat einen süßen Zahn.
Dazu erstelle ich eine separate Routing-Tabelle --set-mark 0x2 und eine Regel zum Umleiten 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")
Weitere Informationen dazu finden Sie in diesem Artikel .
Dann gehe ich in eine Endlosschleife, in der jedes Mal eine Liste der verbundenen Modems angezeigt wird (um herauszufinden, ob sich die Netzwerkkonfiguration geändert hat).
network_list = getNetworklist()
Das Abrufen einer Liste von Netzwerkschnittstellen ist ziemlich 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 weise ich allen Schnittstellen IP-Adressen zu, wie im Bild im Kapitel über das Modem gezeigt.
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, generiere ich Fehler. Wenn es ein Netzwerk gibt, ist es Zeit zu handeln!
Hier habe ich das SSH-Routing für diese Schnittstelle eingerichtet (falls dies nicht geschehen ist), Fehler an den Server gesendet, wenn die Zeit gekommen ist, Protokolle gesendet und schließlich einen Geschwindigkeitstest ausgeführt und die Protokolle in einer CSV-Datei gespeichert.
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()
# .
Mit Ausnahme der umgekehrten SSH-Konfigurationsfunktion.
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 dem Startup all diese Schönheit hinzufügen. Dazu erstelle ich eine Datei:
sudo vim /etc/systemd/system/modems_speedtest.service
Und ich schreibe hinein: Ich schalte das Autoload ein und starte!
[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
sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.service
Jetzt kann ich mit dem folgenden Befehl die Protokolle der Vorgänge anzeigen:
journalctl -u modems_speedtest.service --no-pager -f
Ergebnisse
Nun, das Wichtigste ist, was als Ergebnis passiert ist. Hier sind einige Diagramme, die ich während des Entwicklungs- und Debugging-Prozesses erfasst habe. 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 war der Betreiber Tele2, den ich mehrere Tage lang verbracht habe.
Ich habe hier einen dynamischen Messserver verwendet. Die Geschwindigkeitsmessungen funktionieren, aber sie schweben sehr stark, es ist jedoch immer noch ein Durchschnittswert sichtbar, der durch Filtern der Daten beispielsweise mit einem gleitenden Durchschnitt erhalten werden kann.
Später habe ich eine Reihe von Grafiken für andere Telekommunikationsbetreiber erstellt. In diesem Fall gab es bereits einen Testserver, und die Ergebnisse sind auch sehr interessant.
Wie Sie sehen, ist das Thema für die Recherche und Verarbeitung dieser Daten sehr umfangreich und dauert eindeutig nicht einige Wochen. Aber…
Ergebnis der Arbeit
Die Arbeit wurde 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 solche Tricks mit jedem Boot machte. Für diese Zwecke gibt es eine Vielzahl anderer Modemmodelle. In der Regel haben sie bereits das Mini-PCI-e-Format, sind im Gerät installiert und viel einfacher zu konfigurieren. Aber das ist eine ganz andere Geschichte. Das Projekt war interessant und war sehr froh, dass wir es geschafft haben, daran teilzunehmen.