Samtidig hastighedstest på flere LTE-modems

Under karantæne blev jeg tilbudt at deltage i udviklingen af ​​en enhed til måling af hastigheden af ​​LTE-modem for flere mobiloperatører.

Samtidig hastighedstest på flere LTE-modems

Kunden ønskede at evaluere hastigheden af ​​forskellige teleoperatører på forskellige geografiske steder for at kunne forstå, hvilken mobiloperatør der var mest optimal for ham, når han installerede udstyr ved hjælp af en LTE-forbindelse, for eksempel til videoudsendelser. Samtidig skulle problemet løses så enkelt og billigt som muligt, uden dyrt udstyr.

Jeg vil med det samme sige, at opgaven ikke er den enkleste og mest videntunge; jeg vil fortælle dig, hvilke problemer jeg stødte på, og hvordan jeg løste dem. Så lad os gå.

Bemærk

At måle hastigheden af ​​en LTE-forbindelse er en meget kompleks sag: du skal vælge det rigtige udstyr og måleteknik og også have en god forståelse af topologien og driften af ​​det cellulære netværk. Plus, hastigheden kan påvirkes af flere faktorer: antallet af abonnenter på en celle, vejrforhold, selv fra celle til celle kan hastigheden variere dramatisk på grund af netværkstopologien. Generelt er dette et problem med et stort antal ubekendte, og kun en teleoperatør kan løse det korrekt.

I første omgang ville kunden bare køre kureren med operatørernes telefoner, tage mål direkte på telefonen og derefter skrive hastighedsmålingsresultaterne ned i en notesbog. Min løsning til at måle hastigheden på lte-netværk, selvom den ikke er ideel, løser problemet.

På grund af mangel på tid traf jeg beslutninger ikke til fordel for bekvemmelighed eller praktisk, men til fordel for udviklingshastighed. For eksempel blev reverse ssh brugt til fjernadgang, i stedet for den mere praktiske VPN, for at spare tid på opsætning af serveren og hver enkelt klient.

Teknisk opgave

Som der står i artiklen Uden tekniske specifikationer: hvorfor kunden ikke ønsker det: Arbejd ikke uden tekniske specifikationer! Aldrig, hvor som helst!

Den tekniske opgave var ret enkel, jeg vil udvide den lidt for forståelsen af ​​slutbrugeren. Valget af tekniske løsninger og udstyr blev dikteret af kunden. Så selve den tekniske specifikation, efter alle godkendelser:

Baseret på en enkeltbordscomputer vim2 lav en hastighedstester til lte-forbindelser via H-modemuawei e3372h - 153 flere teleoperatører (fra en til n). Det er også nødvendigt at modtage koordinater fra en GPS-modtager tilsluttet via UART. Foretag hastighedsmålinger ved hjælp af tjenesten www.speedtest.net og læg dem i en tabel som:

Samtidig hastighedstest på flere LTE-modems

Tabel i csv-format. Send derefter dette skilt på e-mail hver 6. time. I tilfælde af fejl blinker LED'en, der er tilsluttet GPIO'en.

Jeg beskrev de tekniske specifikationer i fri form, efter mange godkendelser. Men meningen med opgaven er allerede synlig. En uge blev givet til alt. Men i virkeligheden varede det i tre uger. Dette er under hensyntagen til, at jeg kun gjorde dette efter mit hovedjob og i weekenden.

Her vil jeg endnu en gang gøre opmærksom på, at kunden på forhånd aftalte brugen af ​​hastighedsmålingstjenesten og hardware, hvilket i høj grad begrænsede mine muligheder. Budgettet var også begrænset, så der blev ikke købt noget særligt. Så vi var nødt til at spille efter disse regler.

Arkitektur og udvikling

Ordningen er enkel og indlysende. Derfor vil jeg efterlade det uden særlige kommentarer.

Samtidig hastighedstest på flere LTE-modems

Jeg besluttede at implementere hele projektet i python, på trods af at jeg slet ikke havde erfaring med at udvikle på dette sprog. Jeg valgte det, fordi der var en masse færdige eksempler og løsninger, der kunne sætte gang i udviklingen. Derfor beder jeg alle professionelle programmører om ikke at skælde ud på min første erfaring med at udvikle sig i python, og jeg er altid glad for at høre konstruktiv kritik for at forbedre mine kompetencer.

Også i processen opdagede jeg, at python har to kørende versioner 2 og 3, som et resultat, jeg slog mig ned på den tredje.

Hardware noder

Enkeltplade vim2

Jeg fik en enkeltbordscomputer som min hovedmaskine vim2

Samtidig hastighedstest på flere LTE-modems

En fremragende, kraftfuld medieprocessor til et smart hjem og SMART-TV, men ekstremt uegnet til denne opgave, eller, lad os sige, dårligt egnet. For eksempel er dets primære OS Android, og Linux er et sekundært OS, og derfor garanterer ingen højkvalitetsdrift af alle noder og drivere under Linux. Og jeg antager, at nogle af problemerne var relateret til USB-driverne på denne platform, så modemerne fungerede ikke som forventet på dette board. Det har også meget dårlig og spredt dokumentation, så hver operation tog meget tid at grave gennem havnen. Selv almindeligt arbejde med GPIO tog meget blod. For eksempel tog det mig flere timer at sætte LED'en op. Men for at være objektiv var det grundlæggende ikke vigtigt, hvilken slags enkeltkort det var, det vigtigste var, at det virkede, og der var USB-porte.

Først skal jeg installere Linux på dette board. For ikke at gennemsøge dokumentationens vildmark for alle, og også for dem, der vil beskæftige sig med dette singleboard-system, skriver jeg dette kapitel.

Der er to muligheder for at installere Linux: på et eksternt SD-kort eller på en intern MMC. Jeg brugte en aften på at finde ud af, hvordan jeg skulle få det til at fungere med kortet, så jeg besluttede at installere det på MMC'en, selvom det uden tvivl ville være meget nemmere at arbejde med et eksternt kort.

Om firmwaren skævt fortalt her. Jeg oversætter fra fremmed til russisk. For at flashe boardet skal jeg tilslutte hardwaren UART. Forbundet det som følger.

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

Samtidig hastighedstest på flere LTE-modems

Hvorefter jeg downloadede firmwaren dermed. Specifik firmwareversion VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

For at kunne uploade denne firmware skal jeg bruge hjælpeprogrammer. Flere detaljer om dette her. Jeg har ikke prøvet at flashe det under Windows, men jeg er nødt til at fortælle dig et par ord om firmware under Linux. Først installerer jeg hjælpeprogrammerne i henhold til instruktionerne.

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

Aaand... Intet virker. Jeg brugte et par timer på at redigere installationsscripts, så alt ville installeres korrekt for mig. Jeg kan ikke huske, hvad jeg lavede der, men der var også det cirkus med heste. Så vær forsigtig. Men uden disse hjælpeprogrammer er der ingen mening i at torturere vim2 yderligere. Det er bedre ikke at rode med ham overhovedet!

Efter syv helvedes cirkler, scriptkonfiguration og installation modtog jeg en pakke med fungerende hjælpeprogrammer. Jeg tilsluttede kortet via USB til min Linux-computer, og tilsluttede også UART'en i henhold til diagrammet ovenfor.
Jeg er ved at konfigurere min foretrukne minicom-terminal til en hastighed på 115200 uden hardware- og softwarefejlkontrol. Og lad os komme i gang.

Samtidig hastighedstest på flere LTE-modems

Når jeg indlæser VIM2 i UART-terminalen, trykker jeg på en tast, såsom mellemrumstasten, for at stoppe indlæsningen. Efter linjen vises

kvim2# 

Jeg indtaster kommandoen:

kvim2# run update

På værten, som vi indlæser fra, udfører jeg:

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

Det var det, pyt. Jeg tjekkede, at der er Linux på tavlen. Login/adgangskode khadas:khadas.

Derefter nogle mindre indledende indstillinger. For yderligere arbejde deaktiverer jeg adgangskoden til sudo (ja, ikke sikker, men praktisk).

sudo visudo

Jeg redigerer linjen til formularen og gemmer

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

Så ændrer jeg den nuværende lokalitet, så klokken er i Moskva, ellers bliver den i Greenwich.

sudo timedatectl set-timezone Europe/Moscow

eller

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

Hvis du synes det er svært, så brug ikke dette board; Raspberry Pi er bedre. Ærligt talt.

Modem Huawei e3372h – 153

Dette modem var en betydelig blodkilde for mig, og faktisk blev det flaskehalsen i hele projektet. Generelt afspejler navnet "modem" for disse enheder slet ikke essensen af ​​arbejdet: dette er en kraftfuld mejetærsker, dette stykke hardware har en sammensat enhed, der foregiver at være en cd-rom for at installere drivere, og skifter derefter til netværkskorttilstand.

Arkitektonisk set fra en Linux-brugers synspunkt, efter alle indstillinger, ser det sådan ud: efter at jeg har tilsluttet modemmet, har jeg et eth* netværksinterface, som via dhcp modtager IP-adressen 192.168.8.100, og standard-gatewayen er 192.168.8.1.

Og det vigtigste øjeblik! Denne modemmodel kan ikke fungere i modemtilstand, som styres af AT-kommandoer. Alt ville være meget enklere, oprette PPP-forbindelser for hvert modem og derefter arbejde med dem. Men i mit tilfælde opretter "sig selv" (mere præcist, en Linux-dykker i henhold til udev-reglerne), en eth-grænseflade og tildeler en IP-adresse til den via dhcp.

For at undgå yderligere forvirring foreslår jeg at glemme ordet "modem" og sige netværkskort og gateway, for i bund og grund er det som at forbinde et nyt netværkskort med en gateway.
Når der er ét modem giver det ikke særlige problemer, men når der er mere end et, nemlig n-stykker, opstår følgende netværksbillede.

Samtidig hastighedstest på flere LTE-modems

Det vil sige n netværkskort, med samme IP-adresse, hver med samme standardgateway. Men faktisk er hver af dem forbundet med sin egen operatør.

Til at begynde med havde jeg en simpel løsning: ved at bruge ifconfig- eller ip-kommandoen, sluk for alle grænseflader og tænd blot en efter tur og test den. Løsningen var god for alle, bortset fra at jeg i skifteøjeblikket ikke var i stand til at oprette forbindelse til enheden. Og da skiftet er hyppigt og hurtigt, havde jeg faktisk slet ikke mulighed for at oprette forbindelse.

Derfor valgte jeg stien til manuelt at ændre IP-adresserne på modemmerne og derefter drive trafik ved hjælp af routingindstillinger.

Samtidig hastighedstest på flere LTE-modems

Dette var ikke slutningen på mine problemer med modemer: i tilfælde af strømproblemer faldt de af, og en god stabil strømforsyning til USB-hubben var påkrævet. Jeg løste dette problem ved at hårdlodde strømmen direkte til navet. Et andet problem, som jeg stødte på, og som ødelagde hele projektet: efter en genstart eller koldstart af enheden blev ikke alle modemer opdaget og ikke altid, og jeg kunne ikke bestemme, hvorfor dette skete og med hvilken algoritme. Men først ting først.

For at modemmet skulle fungere korrekt, installerede jeg usb-modeswitch-pakken.

sudo apt update
sudo apt install -y usb-modeswitch

Hvorefter modemmet efter tilslutning bliver registreret og konfigureret korrekt af udev-undersystemet. Jeg tjekker ved blot at tilslutte modemmet og sørge for at netværket vises.
Et andet problem, som jeg ikke kunne løse: hvordan kan jeg få navnet på den operatør, vi arbejder med, fra dette modem? Operatørnavnet er indeholdt i modemets webgrænseflade på 192.168.8.1. Dette er en dynamisk webside, der modtager data gennem Ajax-anmodninger, så blot at wgete siden og parse navnet vil ikke fungere. Så jeg begyndte at se på, hvordan man udvikler en webside osv., og indså, at jeg lavede noget sludder. Som et resultat spyttede han, og operatøren begyndte at modtage ved hjælp af selve Speedtest API.

Meget ville være nemmere, hvis modemmet havde adgang via AT-kommandoer. Det ville være muligt at omkonfigurere det, oprette en ppp-forbindelse, tildele en IP, få en teleoperatør osv. Men ak, jeg arbejder med det, jeg har fået.

GPS

GPS-modtageren, jeg fik, havde et UART-interface og strøm. Det var ikke den bedste løsning, men det var stadig brugbart og enkelt. Modtageren så nogenlunde sådan her ud.

Samtidig hastighedstest på flere LTE-modems

For at være ærlig var det første gang, jeg arbejdede med en GPS-modtager, men som jeg forventede, var alt tænkt for os for længe siden. Så vi bruger bare færdige løsninger.

Først aktiverer jeg uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) for at forbinde GPS.

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

Bagefter tjekker jeg operationens succes.

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

Denne kommando redigerer tilsyneladende devtree'et i farten, hvilket er meget praktisk.

Efter succes med denne operation, genstart og installer GPS-dæmonen.

khadas@Khadas:~$ sudo reboot

Installation af GPS-dæmonen. Jeg installerer alt og skærer det af med det samme for yderligere konfiguration.

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

Redigering af indstillingsfilen.

sudo vim /etc/default/gpsd

Jeg installerer en UART, som GPS'en hænger på.

DEVICES="/dev/ttyS4"

Og så tænder vi alt og starter.

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

Derefter tilslutter jeg GPS'en.

Samtidig hastighedstest på flere LTE-modems

GPS-ledningen er i mine hænder, UART-debugger-ledningerne er synlige under mine fingre.

Jeg genstarter og kontrollerer GPS-driften ved hjælp af gpsmon-programmet.

Samtidig hastighedstest på flere LTE-modems

Du kan ikke se satellitterne på dette skærmbillede, men du kan se kommunikation med GPS-modtageren, og det betyder, at alt er i orden.

I python prøvede jeg mange muligheder for at arbejde med denne dæmon, men jeg besluttede mig for den, der fungerede korrekt med python 3.

Jeg installerer det nødvendige bibliotek.

sudo -H pip3 install gps3 

Og jeg skulpturerer arbejdskoden.

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

Hvis jeg skal have koordinater, gøres dette med følgende opkald:

longitude, latitude = getPositionData(agps_thread)

Og inden for 1-10 sekunder får jeg enten koordinaten eller ej. Ja, jeg havde ti forsøg på at få koordinater. Ikke optimalt, skævt og skævt, men det virker. Jeg besluttede at gøre dette, fordi GPS kan have dårlig modtagelse og ikke altid modtage data. Hvis du venter på at modtage data, så hvis du arbejder i et fjerntliggende rum, fryser programmet på dette sted. Derfor implementerede jeg denne uelege mulighed.

Hvis der var mere tid, ville det i princippet være muligt at modtage data fra GPS direkte via UART, parse det i en separat tråd og arbejde med det. Men der var slet ikke tid, derfor den brutalt grimme kode. Og ja, jeg skammer mig ikke.

Lysdiode

Tilslutning af LED var enkel og vanskelig på samme tid. Den største vanskelighed er, at pin-nummeret i systemet ikke svarer til pin-nummeret på tavlen, og fordi dokumentationen er skrevet med venstre hånd. For at sammenligne hardware-pin-nummeret og pin-nummeret i operativsystemet skal du køre kommandoen:

gpio readall

En tabel med pin-korrespondance i systemet og på tavlen vil blive vist. Hvorefter jeg allerede kan betjene stiften i selve OS. I mit tilfælde er lysdioden tilsluttet GPIOH_5.

Samtidig hastighedstest på flere LTE-modems

Jeg skifter GPIO-pinden til udgangstilstand.

gpio -g mode 421 out

Jeg skriver nul.

gpio -g write 421 0

Jeg skriver en ned.

gpio -g write 421 1

Samtidig hastighedstest på flere LTE-modems
Alt er tændt efter at have skrevet "1"

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

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

def good_blink():
	gpio_set(1)

Nu, i tilfælde af fejl, kalder jeg error_blink(), og LED'en vil blinke smukt.

Software noder

Speedtest API

Det er en stor glæde, at speedtest.net-tjenesten har sin egen python-API, du kan se på Github.

Det gode er, at der er kildekoder, som også kan ses. Hvordan man arbejder med denne API (enkle eksempler) kan findes i relevant afsnit.

Jeg installerer python-biblioteket med følgende kommando.

sudo -H pip3 install speedtest-cli

For eksempel kan du endda installere en hastighedstester i Ubuntu direkte fra softwaren. Dette er den samme python-applikation, som derefter kan startes direkte fra konsollen.

sudo apt install speedtest-cli -y

Og mål din internethastighed.

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

Som et resultat, ligesom jeg gjorde. Jeg var nødt til at komme ind i kildekoderne til denne hastighedstest for mere fuldt ud at implementere dem i mit projekt. En af de vigtigste opgaver er at få navnet på teleoperatøren for at erstatte det med pladen.

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

Også her viste alt sig ikke at være så enkelt, selvom det virkede meget enklere. Oprindeligt var serverens parameter lig med [], siger de, vælg den bedste server. Som et resultat havde jeg tilfældige servere og, som du måske kan gætte, variabel hastighed. Dette er et ret komplekst emne, og brug af en fast server, hvis ja, statisk eller dynamisk, kræver forskning. Men her er et eksempel på grafer for hastighedsmåling for en Beeline-operatør, når han dynamisk vælger en testserver og en statisk fast.

Samtidig hastighedstest på flere LTE-modems
Resultatet af måling af hastighed, når du vælger en dynamisk server.

Samtidig hastighedstest på flere LTE-modems
Resultatet af hastighedstest, med en strengt udvalgt en server.

Under test er der "pels" begge steder, og det skal fjernes ved hjælp af matematiske metoder. Men med en fast server er det lidt mindre, og amplituden er mere stabil.
Generelt er dette et sted med stor forskning. Og jeg ville måle hastigheden på min server ved hjælp af iperf-værktøjet. Men vi holder os til de tekniske specifikationer.

Afsendelse af mail og fejl

For at sende mail prøvede jeg flere dusin forskellige muligheder, men i sidste ende besluttede jeg mig for følgende. Jeg registrerede en postkasse på Yandex og tog derefter Dette er et eksempel på at sende mail. Jeg tjekkede det og implementerede det i programmet. Dette eksempel undersøger forskellige muligheder, herunder afsendelse fra gmail osv. Jeg ville ikke bøvle med at sætte min mailserver op og havde ikke tid til det, men som det senere viste sig, var det også forgæves.

Logfilerne blev sendt i henhold til skemalæggeren, hvis der er en forbindelse, hver 6. time: klokken 00, 06, 12 og 18. Sendte det som følger.

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

Der blev også sendt fejl i første omgang. Til at begynde med blev de akkumuleret i listen, og derefter sendt også ved hjælp af skemalæggeren, hvis der var en forbindelse. Men så opstod der problemer med det faktum, at Yandex har en grænse for antallet af meddelelser sendt om dagen (dette er smerte, tristhed og ydmygelse). Da der kunne være et stort antal fejl selv i minuttet, måtte vi opgive at sende fejl med posten. Så husk, når du automatisk sender oplysninger om et sådant problem gennem Yandex-tjenester.

Feedback server

For at få adgang til et eksternt stykke hardware og kunne tilpasse og omkonfigurere det, havde jeg brug for en ekstern server. Generelt, for at være retfærdig, ville det være korrekt at sende alle data til serveren og bygge alle de smukke grafer i webgrænsefladen. Men ikke alt på én gang.

Til VPS valgte jeg ruvds.com. Du kunne tage den enkleste server. Og generelt ville dette være nok til mine formål. Men da jeg ikke betalte for serveren af ​​egen lomme, besluttede jeg at tage den med en lille reserve, så det ville være nok, hvis vi skulle installere en webgrænseflade, vores egen SMTP-server, VPN osv. Plus, være i stand til at konfigurere en Telegram-bot og ikke have problemer med, at den bliver blokeret. Derfor valgte jeg Amsterdam og følgende parametre.

Samtidig hastighedstest på flere LTE-modems

Som en metode til kommunikation med hardwaren valgte vim2 en omvendt ssh-forbindelse, og som praksis har vist, er den ikke den bedste. Hvis forbindelsen afbrydes, holder serveren porten, og det er umuligt at oprette forbindelse gennem den i nogen tid. Derfor er det stadig bedre at bruge andre kommunikationsmetoder, for eksempel VPN. I fremtiden ville jeg skifte til VPN, men havde ikke tid.

Jeg vil ikke gå i detaljer om opsætning af en firewall, begrænsning af rettigheder, deaktivering af root ssh-forbindelser og andre truismer ved opsætning af en VPS. Jeg vil gerne tro, at du allerede ved alt. For en fjernforbindelse opretter jeg en ny bruger på serveren.

adduser vimssh

Jeg genererer ssh-forbindelsesnøgler på vores hardware.

ssh-keygen

Og jeg kopierer dem til vores server.

ssh-copy-id [email protected]

På vores hardware opretter jeg en automatisk omvendt ssh-forbindelse ved hver opstart.

[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

Vær opmærksom på port 8083: den bestemmer hvilken port jeg vil bruge til at forbinde via omvendt ssh. Tilføj det til opstart og start.

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

Du kan endda se status:

sudo systemctl status autossh.service

Nu, på vores VPS-server, hvis vi kører:

ssh -p 8083 khadas@localhost

Så kommer jeg til mit test stykke hardware. Og fra hardwaren kan jeg også sende logs og eventuelle data via ssh til min server, hvilket er meget praktisk.

Sætte det hele sammen

Samtidig hastighedstest på flere LTE-modems
Tænd, lad os begynde udvikling og fejlfinding

Pyha, det er det, jeg beskrev alle noderne. Nu er det tid til at samle det hele. Du kan se koden her.

En vigtig pointe med koden: Dette projekt starter måske ikke sådan, fordi det var skræddersyet til en specifik opgave, af en specifik arkitektur. Selvom jeg giver kildekoden, vil jeg stadig forklare de mest værdifulde ting her, lige i teksten, ellers er det fuldstændig uforståeligt.

I begyndelsen initialiserer jeg gps, gpio og starter en separat planlægningstråd.

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

Planlæggeren er ret enkel: den ser ud for at se, om tiden er inde til at sende beskeder, og hvad den aktuelle fejlstatus er. Hvis der er et fejlflag, blinker vi LED'en.

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

Den sværeste del af dette projekt er at opretholde den omvendte ssh-forbindelse for hver test. Hver test involverer genkonfiguration af standardgatewayen og DNS-serveren. Da ingen alligevel læser, skal du vide, at toget ikke kører på træskinner. Den, der finder påskeægget, får noget slik.

For at gøre dette opretter jeg en separat routingtabel -set-mark 0x2 og en regel for at omdirigere trafik.

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

Du kan lære mere om, hvordan det fungerer læses i denne artikel.

Hvorefter jeg går ind i en endeløs loop, hvor vi hver gang får en liste over tilsluttede modemer (for at finde ud af om netværkskonfigurationen pludselig har ændret sig).

network_list = getNetworklist()

At få en liste over netværksgrænseflader er ret simpelt.

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

Efter at have modtaget listen satte jeg IP-adresser til alle interfaces, som jeg viste på billedet i kapitlet om modemmet.

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

Så gennemgår jeg simpelthen hver grænseflade i en løkke. Og jeg konfigurerer hver grænseflade.

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

Jeg tjekker grænsefladen for funktionalitet, hvis der ikke er noget netværk, genererer jeg fejl. Hvis der er et netværk, så er det tid til at handle!

Her konfigurerer jeg ssh routing til denne grænseflade (hvis det ikke er blevet gjort), sender fejl til serveren hvis tiden er inde, sender logs og kører til sidst en speedtest og gemmer logs til en csv fil.

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

Det er værd at nævne funktionen til at opsætte omvendt 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")

Og selvfølgelig skal du tilføje al denne skønhed til opstart. For at gøre dette opretter jeg en fil:

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

Og jeg skriver i den:

[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

Jeg tænder for autoloading og starter!

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

Nu kan jeg se logfiler over, hvad der sker ved hjælp af kommandoen:

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

Fund

Nå, nu er det vigtigste, hvad der skete som et resultat? Her er et par grafer, som jeg formåede at fange under udviklings- og fejlretningsprocessen. Graferne blev bygget ved hjælp af gnuplot med følgende 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"

Den første oplevelse var med Tele2-operatøren, som jeg gennemførte i flere dage.

Samtidig hastighedstest på flere LTE-modems

Her brugte jeg en dynamisk måleserver. Hastighedsmålinger virker, men svinger meget, men en vis gennemsnitsværdi er stadig synlig, og dette kan opnås ved at filtrere dataene, for eksempel med et glidende gennemsnit.

Senere byggede jeg en række grafer for andre teleoperatører. I dette tilfælde var der allerede én testserver, og resultaterne var også meget interessante.

Samtidig hastighedstest på flere LTE-modems

Samtidig hastighedstest på flere LTE-modems

Samtidig hastighedstest på flere LTE-modems

Samtidig hastighedstest på flere LTE-modems

Som du kan se, er emnet meget omfattende for forskning og bearbejdning af disse data, og holder tydeligvis ikke til et par ugers arbejde. Men…

Resultatet af arbejdet

Arbejdet blev brat afsluttet på grund af omstændigheder uden for min kontrol. En af svaghederne ved dette projekt, efter min subjektive mening, var modemmet, som ikke rigtig ønskede at arbejde samtidigt med andre modemer, og lavede sådanne tricks hver gang det blev indlæst. Til disse formål er der et stort antal andre modemmodeller; normalt er de allerede i Mini PCI-e-formatet og er installeret inde i enheden og er meget nemmere at konfigurere. Men det er en helt anden historie. Projektet var interessant, og jeg var meget glad for, at jeg kunne deltage i det.

Samtidig hastighedstest på flere LTE-modems

Kilde: www.habr.com

Tilføj en kommentar