Egyidejű sebességteszt több LTE-modemen

A karantén alatt felajánlották nekem, hogy részt vegyek egy LTE-modemek sebességének mérésére szolgáló eszköz fejlesztésében több mobilszolgáltató számára.

Egyidejű sebességteszt több LTE-modemen

A megrendelő fel akarta mérni a különböző szolgáltatók sebességét különböző földrajzi helyeken, hogy megérthesse, melyik mobilszolgáltató a legoptimálisabb számára az LTE-kapcsolaton alapuló berendezések telepítésekor, például videóközvetítésekhez. A feladatot a lehető legegyszerűbben és legolcsóbban kellett megoldani, drága berendezések nélkül.

Azonnal mondom, hogy a feladat nem a legegyszerűbb és kutatásigényes, elmondom, hogy milyen problémák merültek fel és hogyan oldottam meg őket. Nos, kezdjük.

Megjegyzés

Az LTE-kapcsolat sebességének mérése igen bonyolult dolog: helyesen kell kiválasztani a berendezést és a mérési módszert, és jól kell ismerni a mobilhálózat topológiáját és működését. Emellett a sebességet több tényező is befolyásolhatja: az előfizetők száma az egyes cellákban, az időjárási körülmények, sőt, akár cellánként a sebesség drasztikusan eltérhet a hálózat topológiájának függvényében. Összességében ez egy olyan feladat, amely rengeteg ismeretlennel rendelkezik, és helyesen csak a szolgáltató tudja megoldani.

Kezdetben a megrendelő azt akarta, hogy egyszerűen egy futárt küldjenek a szolgáltatók telefonjával, és közvetlenül a telefonon végezzenek méréseket, majd jegyzetfüzetbe írják a sebességmérések eredményeit. Az LTE-hálózatok sebességének mérésére javasolt megoldásom, bár nem tökéletes, de éppen megfelel a kitűzött célnak.

Az időhiány miatt nem a kényelem vagy a praktikum, hanem a fejlesztés sebessége mellett döntöttem. Például távoli hozzáféréshez fordított SSH-t indítottam, ahelyett, hogy a praktikusabb VPN-t választottam volna, hogy időt takarítsak meg a szerver és az egyes kliensek beállításához.

Műszaki követelmény

Ahogy a cikkben van írva TÉR nélkül: miért nem akarja a kliens: Ne dolgozzon TÉR nélkül! Soha, sehol!

A műszaki leírás eléggé egyszerű volt, egy kicsit ki fogom bővíteni a végfelhasználó megértéséhez. A műszaki megoldások és berendezések kiválasztása a megrendelő által volt diktálva. Tehát az önálló TÉR, minden egyeztetést követően:

Egylapos számítógép alapjain vim2 LTE-kapcsolat sebességtesztelő készítése H modemeken keresztüluawei e3372h — 153 több szolgáltató (1-től n-ig). Szintén szükséges a GPS-vevő koordinátáit megkapni, UART-on keresztül csatlakoztatva. A sebességméréseket a szolgáltatás segítségével kell elvégezni www.speedtest.net és ezeket egy ilyen táblázatba összesíteni:

Egyidejű sebességteszt több LTE-modemen

CSV formátumú táblázat. Ezt követően a táblázatot minden 6 órában e-mailben kell elküldeni. Hibák esetén a GPIO-hoz csatlakoztatott LED-nek világítania kell.

A műszaki leírást szabad formában írtam le, számos egyeztetés után. De a feladat értelme már látható. Mindenre egy hetet adtak, de a valóságban három hétre nyúlt el. Ez figyelembe véve, hogy csak a fő munka után és hétvégén foglalkoztam vele.

Itt még egyszer szeretném felhívni a figyelmet, hogy a megrendelő előre rögzítette a sebességmérő szolgáltatás és a hardver használatát, ami jelentősen korlátozta a lehetőségeimet. A költségvetés is korlátozott volt, ezért különösebben nem vásároltam semmit. Így kénytelen voltam ezen szabályok szerint játszani.

Architektúra és fejlesztés

A séma egyszerű és nyilvánvaló. Ezért külön megjegyzések nélkül hagyom.

Egyidejű sebességteszt több LTE-modemen

Az egész projektet Python-on szerettem volna megvalósítani, annak ellenére, hogy egyáltalán nem volt tapasztalatom ezzel a nyelvvel. Ezt választottam, mivel rengeteg kész példa és megoldás volt, amelyek felgyorsíthatták a fejlesztést. Ezért kérem az összes profi programozót, hogy ne bírálják az első Python-os fejlesztési tapasztalatomat, és mindig örömmel várom a konstruktív kritikát a tudásom fejlesztéséhez.

Továbbá a folyamat során felfedeztem, hogy a Python-nak két futó verziója van, a 2-es és a 3-as, végül a harmadikon állapodtam meg.

Hardveregységek

VIM2 egylapos számítógép

Fő gépként egy egylapos számítógépet kaptam. vim2

Egyidejű sebességteszt több LTE-modemen

Kiváló, erős média kombájn az okos otthonok és SMART-TV-k számára, de ritkán alkalmas erre a feladatra, vagy mondjuk úgy, gyengén alkalmas. Például, a fő operációs rendszere Android, míg a Linux egy mellékes operációs rendszer, így senki sem garantálja a rendszer összes komponensének és meghajtójának megfelelő működését Linux alatt. Feltételezem, hogy egyes problémák a platform USB-meghajtóival voltak összefüggésben, ezért a modemek nem úgy működtek ezzel az alaplappal, ahogy vártam. Emellett nagyon gyenge és szétszórt dokumentációja van, ezért minden művelet sok időt vett igénybe a doksikban való keresgélésre. Még egy egyszerű feladat, mint a GPIO-val való munka is sok bosszúságot okozott. Például, a LED működésének beállítása több órámba telt. De ha objektívak akarunk lenni, lényegében nem számított, milyen egylapos, a lényeg, hogy működjön és legyenek USB-portok.

Először is szükségem van a Linux telepítésére erre az alaplapra. Anélkül, hogy mindenkinek kutatnia kellene a dokumentáció mély vizeiben, és azok számára, akik foglalkozni fognak ezzel az egylapossal, írom ezt a fejezetet.

Két lehetőség van a Linux telepítésére: külső SD-kártyára vagy belső MMC-re. Egy kis estét töltöttem a kártyával, de nem tudtam rávenni, hogy működjön, ezért úgy döntöttem, hogy az MMC-re telepítek, bár kétségtelenül a külső kártyával sokkal könnyebb lett volna dolgozni.

A firmware-ről rosszul van itt elmondva. A furcsa nyelvről oroszra fordítok. A lap firmware-ének frissítéséhez csatlakoztatnom kell a hardveres UART-ot. Így csatlakoztattam: a következőképpen.

  • Tool Pin GND: Pin17 a VIM GPIO-ján
  • Tool Pin TXD: Pin18 a VIM GPIO-ján (Linux_Rx)
  • Tool Pin RXD: Pin19 a VIM GPIO-ján (Linux_Tx)
  • Tool Pin VCC: Pin20 a VIM GPIO-ján

Egyidejű sebességteszt több LTE-modemen

Ezután letöltöttem a firmware-t innen. A firmware specifikus verziója VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Ahhoz, hogy ezt a firmware-t fel tudjam tölteni, szükségem van bizonyos segédprogramokra. Részletesebben erről itt van szó itt. Windows alatt nem próbáltam frissíteni, de a Linux alatti firmware-t érdemes pár szóban említeni. Először telepítem a segédprogramokat az útmutató szerint.

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

És… semmi sem működik. Pár órát töltöttem a telepítő szkriptek módosítgatásával, hogy minden hibátlanul települjön nálam. Már nem emlékszem, mit csináltam, de az is egy cirkusz volt. Szóval légy óvatos. De ezek a segédprogramok nélkül értelmetlen tovább szenvedni a vim2-vel. Jobb, ha egyáltalán nem keveredsz vele!

Hét környi pokol, a szkriptek konfigurálása, és a telepítés után megkaptam egy működő eszközcsomagot. Az USB-n keresztül csatlakoztattam a lapkát a Linux számítógépemhez, és a UART is csatlakozott a fentiek szerint.
Beállítom a kedvenc terminálomat, a minicom-ot, 115200 sebességre, hardveres és szoftveres hibaellenőrzés nélkül. Most pedig kezdjük.

Egyidejű sebességteszt több LTE-modemen

A VIM2 indításakor a UART terminálon megnyomok egy billentyűt, például a szóköz billentyűt, hogy megállítsam az indítást. Amikor megjelenik a sor

kvim2# 

Beírom a parancsot:

kvim2# run update

A gazdagépen, ahonnan indítunk, ezt végzem:

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

Kész, fúj. Flash-elve lett, a lapon van Linux. Bejelentkezés/jelszó khadas:khadas.

Ezután néhány alapvető beállítás. A további munkához letiltom a jelszót a sudo-nál (igen, nem biztonságos, de kényelmes).

sudo visudo

Szerkesztem a sort, hogy így nézzen ki, és mentem.

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

Ezután megváltoztatom az aktuális lokalizációt, hogy az idő Moszkvában legyen, különben Greenwich idő szerint lesz.

sudo timedatectl set-timezone Europe/Moscow

vagy

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

Ha nehéznek tűnik, akkor ne használja ezt a lapkát, jobb a Raspberry Pi. Őszintén.

Huawei e3372h modem — 153

Ez a modem sok gondot okozott nekem, és tulajdonképpen ő lett a projekt legnagyobb szűk keresztmetszete. Valójában a "modem" név ezekre az eszközökre egyáltalán nem tükrözi a működés lényegét: ez egy rendkívül erős kombinált eszköz, ez a masina egy összetett eszköz, amely CD-ROM-nak álcázza magát a meghajtók telepítéséhez, majd átmegy hálózati kártya üzemmódba.

Architekturálisan, a Linux felhasználó szemszögéből, miután minden beállítást elvégeztem, így néz ki: a modem csatlakoztatása után egy eth* hálózati interfészem van, amely DHCP-n keresztül kapja az ip címet 192.168.8.100, és az alapértelmezett átjáró 192.168.8.1.

És a legfontosabb pont! Ez a modem modell nem képes modemben működni, amely AT-parancsokkal vezérelhető.Sokkal egyszerűbb lenne, ha ppp kapcsolatokat hoznánk létre minden modemhez, és utána már azzal operálnánk. De az én esetemben a "maga" (pontosabban a Linux meghajtók a udev szabályai szerint) létrehoz egy eth interfészt, és DHCP-n keresztül IP-címet rendel hozzá.

Hogy elkerüljük a zűrzavart, javaslom elfelejteni a "modem" szót, és úgy beszélni, mint egy hálózati kártya és átjáró, mert valójában ez olyan, mintha egy új hálózati kártyát csatlakoztatnánk átjáróval.
Amikor egy modem van, nem okoz különösebb problémát, de amikor több, pontosabban n darab van, akkor a hálózat következő képe keletkezik.

Egyidejű sebességteszt több LTE-modemen

Tehát n hálózati kártya, egy IP-címmel, mindegyik ugyanazzal az alapértelmezett átjáróval. De valójában mindegyik saját szolgáltatójához van csatlakoztatva.

Kezdetben egyszerű megoldásom volt: az ifconfig vagy az ip parancs segítségével leállítani az összes interfészt, majd egyenként bekapcsolni őket és tesztelni. A megoldás mindenki számára megfelelő volt, kivéve azt, hogy a váltások pillanataiban nem voltam képes csatlakozni az eszközhöz. Mivel a váltások gyakoriak és gyorsak voltak, gyakorlatilag nem volt lehetőségem csatlakozni egyáltalán.

Ezért döntöttem úgy, hogy "kézzel" változtatom meg a modemek IP-címeit, és folytatom a forgalom irányítását a routing beállításaival.

Egyidejű sebességteszt több LTE-modemen

Ezekkel a modemekkel való problémáim még nem zárultak le: áramellátási problémák esetén leválasztódtak, stabil USB-hub tápellátásra volt szükség. Ezt a problémát úgy oldottam meg, hogy közvetlenül a hubra forrasztottam a tápellátást. Egy másik probléma, amellyel szembesültem, és amely tönkretette az egész projektet: újraindítás vagy hidegindítás után nem minden modem volt felismerve, és nem mindig, és nem tudtam meghatározni, miért és milyen algoritmus szerint történt ez. De mindenre majd sorjában.

A modem megfelelő működéséhez telepítettem az usb-modeswitch csomagot.

sudo apt update
sudo apt install -y usb-modeswitch

Ezután a modem csatlakoztatása után helyesen fogja a udev alrendszer felismerni és konfigurálni. Ellenőrzöm, hogy egyszerűen csatlakoztatom a modemet, és megbizonyosodom arról, hogy a hálózat megjelent.
Még egy probléma, amelyet nem tudtam megoldani: hogyan lehetne megtudni a modem által használt szolgáltató nevét? A szolgáltató neve a modem webes felületén található a 192.168.8.1 címen. Ez egy dinamikus weboldal, amely ajax-kéréseken keresztül szerzi be az adatokat, ezért egyszerűen le kellene töltenem az oldalt wget segítségével, és ki kellene olvasnom a nevet, de ez nem működik. Ezért elkezdtem nézni, hogyan kell kezelni a weboldalt, és rájöttem, hogy valami értelmetlen dolgot csinálok. Végül feladtam, és a szolgáltatót a Speedtest API-ján keresztül kezdtem el lekérni.

Sokkal egyszerűbb lenne, ha a modem rendelkezne AT-parancsos hozzáféréssel. Akkor át tudnám konfigurálni, ppp-kapcsolatokat létrehozni, IP-t kiosztani, szolgáltatót kapni stb. De sajnos azzal kell dolgoznom, amit kaptam.

GPS

A GPS receiver that was issued to me had a UART interface and power supply. It wasn't the best solution, but it was functional and simple. The receiver looked approximately like this.

Egyidejű sebességteszt több LTE-modemen

To be honest, this was my first time working with a GPS receiver, but as I expected, everything had already been figured out for us. So we just use ready-made solutions.

First, I enable uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) to connect the GPS.

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

After that, I check for the success of the operation.

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

This command seems to edit the devtree on the fly, which is quite convenient.

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

khadas@Khadas:~$ sudo reboot

Installing the GPS daemon. I install everything and immediately disable it 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

I edit the configuration file.

sudo vim /etc/default/gpsd

I set up the UART where the GPS will be connected.

DEVICES="/dev/ttyS4"

And then we turn everything on and start it.

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

After which, I connect the GPS.

Egyidejű sebességteszt több LTE-modemen

In my hands is the GPS wire, and under my fingers, I can see the wires of the UART debugger.

I reboot and check the GPS operation using the gpsmon program.

Egyidejű sebességteszt több LTE-modemen

In this screenshot, no satellites are visible, but I can see the communication with the GPS receiver, which indicates that everything is fine.

I tried many variations of working with this daemon in Python, but I settled on the one that worked correctly with Python 3.

I install the necessary library.

sudo -H pip3 install gps3 

And I craft the working 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 receiver error!!!")
			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, I do it with the following call:

longitude, latitude = getPositionData(agps_thread)

1-10 másodperc alatt vagy megkapom a koordinátát, vagy nem. Igen, összesen tíz próbálkozásom volt a koordináták megszerzésére. Nem optimális, ügyetlen és hibás, de működik. Ezt így döntöttem, mert a GPS néha rosszul működik, és nem mindig tud adatokat kapni. Ha az adatok megszerzésére várok, akkor a program elakad, ha zárt térben dolgozom. Ezért valósítottam meg ezt a nem elegáns megoldást.

Elvileg, ha lett volna több idő, közvetlenül UART-on keresztül is megkaphattam volna az adatokat a GPS-től, ezeket egy külön szálban elemezhettem volna, és dolgozhattam volna velük. De egyáltalán nem volt idő, ezért lett ilyen csúnya kód. És igen, nem szégyellem.

LED

A LED csatlakoztatása egyszerre volt egyszerű és bonyolult. A legnagyobb nehézség az, hogy a rendszerbeli pin száma nem felel meg a táblán lévő pin számának, és a dokumentációt mintha a bal lábammal írták volna. Az hardveres pin számának és az OS pin számának összesorolásához a következő parancsot kell végrehajtanom:

gpio readall

Ki fogja írni a táblázatot a pin megfelelősségéről a rendszerben és a táblán. Ezek után már tudom működtetni a pint az OS-ben. Az én esetemben a LED a következőhöz van csatlakoztatva: GPIOH_5.

Egyidejű sebességteszt több LTE-modemen

A GPIO pint kimeneti üzemmódra állítom.

gpio -g mode 421 out

Beírom a nullát.

gpio -g write 421 0

Beírom az egyet.

gpio -g write 421 1

Egyidejű sebességteszt több LTE-modemen
Minden világít, miután beírtam az '1'-et.

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

Most, hiba esetén meghívom az error_blink() függvényt, és a LED szépen elkezd villogni.

Szoftveres modulok

Speedtest API

Nagy öröm, hogy a speedtest.net-nek van saját python-API-ja, amit meg lehet nézni a Githubot.

Amit az tesz jónak, hogy vannak forráskódok, amelyeket szintén meg lehet nézni. Hogyan kell dolgozni ezzel az API-val (egyszerű példák) a megfelelő részben.

Az alábbi paranccsal telepítem a python könyvtárat.

sudo -H pip3 install speedtest-cli

Például az Ubuntu-ban közvetlenül a repóból is telepíthet egy spidtester-t. Ez ugyanaz a python-alkalmazás, amelyet később közvetlenül a konzolból is elindíthat.

sudo apt install speedtest-cli -y

És megmérheti az internet sebességét.

sebességteszt-cli
A speedtest.net konfigurációjának lekérése...
Tesztelés B***** (*.*.*.*) címről...
A speedtest.net szerverlista lekérése...
A legjobb szerver kiválasztása a ping alapján...
MTS által hosztolt (Moszkva) [0,12 km]: 11,8 ms
Letöltési sebesség tesztelése................................................................................
Letöltés: 7,10 Mbit/s
Feltöltési sebesség tesztelése......................................................................................................
Feltöltés: 3,86 Mbit/s

Ennek eredményeként, ahogyan ezt én megcsináltam. Be kellett nyúlnom az eredeti kódokhoz, hogy teljesebben beépítsem őket a projektbe. Az egyik legfontosabb feladat — a szolgáltató nevét is megszerezni, hogy be lehessen illeszteni a táblázatba.

import speedtest
from datetime import datetime
...
# Meghatározzuk a tesztelt szervert
#6053) MaximaTelecom (Moscow, Oroszország)
servers = ["6053"]
# Ha egy szálú tesztet szeretne használni
threads = None
s = speedtest.Speedtest()
# lekérjük a mobilszolgáltató nevét
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
# lekérjük a szerver paraméterek szöveges stringjét
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
# letöltési teszt
s.download(threads=threads)
# feltöltési teszt
s.upload(threads=threads)
# lekérjük az eredményeket
s.results.share()

# Ezt követően a CSV fájlba írandó stringet alakítunk ki.
# megszerezzük a GPS pozíciót
longitude, latitude = getPositionData(agps_thread)
# idő és dátum
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"
# itt a naplófájlba írás következik

Itt sem volt minden olyan egyszerű, bár úgy tűnik, hogy ez bárhol is működhetne. Kezdetben a servers paraméterem a következő volt [], mondva, hogy válasszam ki a legjobb szervert. Ennek eredményeként véletlenszerű szerverekkel találkoztam, és mint könnyen kitalálható, az sebesség ingadozott. Ez egy elég bonyolult téma, ha fix szervert szeretnél használni, az vagy statikus, vagy dinamikus lehet, amely kutatást igényel. De itt van egy példa a Beeline szolgáltató sebességmérésének grafikonjaira dinamikus teszt szerver választás esetén és statikusan rögzített szerver esetén.

Egyidejű sebességteszt több LTE-modemen
Sebességmérés eredménye dinamikus szerver választása esetén.

Egyidejű sebességteszt több LTE-modemen
Sebességteszt eredménye, egy szigorúan kiválasztott egyetlen szerver esetén.

A tesztelés során a "zaj" jelen van itt is, ott is, és ezt matematikai módszerekkel kell eltávolítani. De fix szerver esetén valamivel kevesebb, és az amplitúdó stabilabb.
Ez a terület nagyszabású kutatások színhelye. Én sebességméréseket végeznék a szerveremhez az iperf eszközzel. De mi ragaszkodunk a műszaki specifikációhoz.

E-mailek küldése és hibák

E-mailek küldésére több tucat különböző megoldást próbáltam, de végül a következőre álltam meg. Regisztráltam egy e-mail fiókot a yandexen, és ezt követően vettem ezt az e-mail küldési példát. Ellenőriztem és beépítettem a programba. Ebben a példában különféle megoldásokat tárgyalunk, beleértve a gmailről történő küldést is. Nem akartam saját levelezőszervert üzemeltetni, és nem volt rá időm, de mint kiderült, ez is hiábavalóan bizonyult.

A naplók küldését a ütemező segítségével végeztem, ha van kapcsolat,, 6 óránként: éjfélkor, reggel 6-kor, délben 12-kor és este 6-kor. A következő módon küldtem el.

from send_email import *
...
message_log = "Tesztelő lap logs №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, "Logok a " + curdata + " " + сurtime, files)
	except:
		print("Hálózati probléma az e-mail küldés során")
		return False
	return True

A hibákat is kezdetben küldtem. Először a lista gyűlt össze, majd szintén az ütemező segítségével, ha volt kapcsolat, küldtem el. Azonban később problémák merültek fel, mivel a Yandex-nek korlátozása van a napi elküldhető e-mailek számában (ez fájdalom, szomorúság és megaláztatás). Mivel a hibákból akár percenként hatalmas mennyiség is lehetett, a hibák e-mailben való küldéséről le kellett mondanom. Ezért vegye figyelembe, hogy a Yandex szolgáltatásaival történő automatikus küldés során ilyen problémával találkozhat.

Visszajelző szerver

Ahhoz, hogy hozzáférjek a távoli hardverhez és újra konfiguráljam, szükségem volt egy külső szerverre. Valójában, az igazság kedvéért, helyes lenne az összes adatot a szerverre küldeni, és a webes interfészen szép grafikonokat készíteni. De nem minden egyszerre.

VPS-ként a következőt választottam: ruvds.com. A legegyszerűbb szerver is elegendő lett volna a céljaimhoz. De mivel nem a saját zsebemből fizettem a szerverért, úgy döntöttem, hogy egy kicsit tartalékot veszek, hogy elegendő legyen, ha webes interfészt, saját SMTP szervert, VPN-t stb. indítunk. Plusz lehetőség a Telegram-bot beállítására és a blokkolásával kapcsolatos problémák elkerülésére. Ezért választottam Amsterdam és a következő paramétereket.

Egyidejű sebességteszt több LTE-modemen

A vim2 eszközzel való kapcsolat módjaként a visszafelé SSH kapcsolatot választottam, és a gyakorlat azt mutatta, hogy nem a legjobb megoldás. A kapcsolat megszakításakor a szerver megtartja a portot, és egy ideig nem lehet csatlakozni rajta. Ezért jobb, ha más kapcsolatot alkalmazunk, például VPN-t. A jövőben szerettem volna VPN-re váltani, de nem jutottam el addig.

Nem fogok belemenni a tűzfal beállításaiba, a jogosultságok korlátozásába, a root ssh kapcsolat letiltásába és egyéb alapvető VPS beállításokba. Remélem, hogy ezt már tudod. A távoli kapcsolat létrehozásához új felhasználót hozok létre a szerveren.

adduser vimssh

A gépünkön létrehozom az ssh kapcsolathoz szükséges kulcsokat.

ssh-keygen

És átmásolom őket a szerverünkre.

ssh-copy-id vimssh@host.com

A gépünkön létrehozok egy automatikus visszacsatolt ssh kapcsolatot minden indításkor.

[Unit]
Leírás=Auto Reverse SSH
Szükséges=systemd-networkd-wait-online.service
Után=systemd-networkd-wait-online.service
[Service]
Felhasználó=khadas
ExecStart=\/usr\/bin\/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 vimssh@host.com
ÚjraindításSec=5
Újraindítás=mindig
[Install]
WantedBy=multi-user.target

Figyelj a 8083-as portra: ez határozza meg, hogy melyik porton fogok csatlakozni a visszacsatolt ssh-n keresztül. Hozzáadjuk az automatikus indításhoz és elindítjuk.

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

Még meg is nézhetjük az állapotot:

sudo systemctl status autossh.service

Most, a VPS szerverünknél, ha végrehajtjuk:

ssh -p 8083 khadas@localhost

Akkor elérhetem a teszt jelzőmet. A jelzőről pedig logokat és bármilyen adatot küldhetek ssh-n keresztül a szerveremre, ami nagyon kényelmes.

Mindent egybehozni

Egyidejű sebességteszt több LTE-modemen
Bekapcsolás, kezdjünk hozzá a fejlesztéshez és a hibakereséshez.

Hűha, úgy tűnik, minden csomópontot leírtam. Most itt az idő, hogy mindezt egy egységes egészbe gyűjtsem. A kódot megnézheted. itt található.

Fontos dolog a kódnál: ezt a projektet nem lehet csak úgy "hopp" elindítani, mivel egy bizonyos feladatra és architektúrára lett optimalizálva. Bár a forrást adom, a legértékesebb részeket azonban itt, a szövegben fogom részletezni, különben teljesen érthetetlen lesz.

Kezdésként az gps, gpio inicializálása és egy külön szál indítása a tervezőhöz.

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

A tervező meglehetősen egyszerű: figyel, hogy elérkezett-e az üzenetek küldési ideje, és milyen hibafolyamat áll fenn. Ha van hiba jelző, villogtatom a LED-et.

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

A projekt legbonyolultabb része a visszacsatolt ssh kapcsolat fenntartása minden teszt során. Minden teszt során újra beállítom az alapértelmezett átjárót és a dns szervert. Mivel senki sem olvassa el ezt, tudd, hogy a vonat nem fátlan síneken közlekedik. Aki felfedezi a rejtvényt, az édességet kap.

Ehhez létrehozok egy külön útvonal-táblát —set-mark 0x2, és egy szabályt a forgalom átirányítására.

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

További információt arról, hogy ez hogyan működik, találhatsz itt ebből a cikkből.

Ezután egy végtelen ciklusba lépek, ahol minden alkalommal lekérdezem a csatlakoztatott modemek listáját (hogy megtudjam, vajon változott-e a hálózati konfiguráció).

network_list = getNetworklist()

A hálózati interfészek listájának lekérése meglehetősen egyszerű.

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

A lista megkapása után IP-címeket adok minden interfésznek, ahogy az a modemről szóló fejezet képén szerepel.

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

Ezután egyszerűen végigmegyek minden interfészen a ciklusban. És konfigurálom minden interfészt.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#töröljük az összes beállítást
		cmd_run("sudo ip route flush all")
#alapértelmezett átjáró megadása
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#dns-szerver beállítása (ez a speedtest működéséhez szükséges)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

Ellenőrzöm az interfészt a működőképesség érdekében, ha nincs hálózat, akkor hibákat generálok. Ha van hálózat, itt az idő cselekedni!

Itt ssh útvonalat állítok be erre az interfészre (ha még nem történt meg), hibákat küldök a szerverre, ha eljött az ideje, elküldöm a naplókat, végül pedig speedtestet végzek, és a naplókat csv fájlba mentem.

if not NetworkAvalible():
....
#Itt hibákat generálunk
....
else: #Van hálózat, hurrá, dolgozunk!
#Ha probléma van az ssh interfésszel, amelyen ssh van, azt megváltoztatjuk
  if (sshint == lastbanint or sshint == "free"):
    print("********** SSH Beállítása ********************")
    if sshint != "free":
      cmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint + " table 102")
    SetupReverseSSH(iface)
    sshint = iface
#mivel a hálózat működik, végre mindent küldjünk el!!!
    if ready_to_send:
      print ("**** Kész a küldésre!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#és aztán tesztelünk a sebességet és mentjük a naplókat. 

Talán meg kellene említeni az ssh visszafelé állító funkciót.

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

És természetesen, mindezt a szépséget fel kell venni az autóstartóba. Ehhez létrehozok egy fájlt:

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

És beírom:

[Unit]
Leírás=Modem Sebesség Teszt
Szükséges=systemd-networkd-wait-online.service
Után=systemd-networkd-wait-online.service
[Service]
Felhasználó=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
ÚjraindításSec=5
Újraindítás=mindig
[Install]
WantedBy=multi-user.target

Bekapcsolom az autóstartást, és elindítom!

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

Most már figyelhetem a naplókat az alábbi parancs használatával:

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

Eredmények

Most importantly, what was the result? I will present several graphs that I managed to capture during the development and debugging process. The graphs were created 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 with the Tele2 operator, which I conducted over several days.

Egyidejű sebességteszt több LTE-modemen

Here I used a dynamic measuring server. The speed measurements work, but fluctuate significantly; however, some average value is still evident, and it can be obtained by filtering the data, for example, using a moving average.

Later, I built several more graphs for other telecommunications operators. In this case, there was a single testing server, and the results were also very interesting.

Egyidejű sebességteszt több LTE-modemen

Egyidejű sebességteszt több LTE-modemen

Egyidejű sebességteszt több LTE-modemen

Egyidejű sebességteszt több LTE-modemen

As you can see, this topic is vast for research and processing this data, and clearly doesn't fit into just a couple of weeks of work. But…

The outcome of the work

The work was abruptly finished due to circumstances beyond my control. One of the weak points of this project, in my subjective opinion, was the modem, which did not perform well when working alongside other modems, causing various issues with each boot. For these purposes, there are numerous other modem models available, usually in the Mini PCI-e format, which fit 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 to have been a part of it.

Egyidejű sebességteszt több LTE-modemen

Forrás: habr.com

Megbízható hosting vásárlása weboldalak számára, DDoS védelemmel, VPS VDS szerverek. 🔥 Megbízható webtárhely vásárlása DDoS védelemmel, VPS VDS szerverek | ProHoster