Samtidig hastighetstest på flere LTE-modemer

Under karantene ble jeg tilbudt å delta i utviklingen av en enhet for å måle hastigheten til LTE-modem for flere mobiloperatører.

Samtidig hastighetstest på flere LTE-modemer

Kunden ønsket å vurdere hastigheten til ulike teleoperatører på ulike geografiske steder for å kunne forstå hvilken mobiloperatør som var mest optimal for ham ved installasjon av utstyr ved bruk av en LTE-forbindelse, for eksempel for videosendinger. Samtidig måtte problemet løses så enkelt og billig som mulig, uten dyrt utstyr.

Jeg vil si med en gang at oppgaven ikke er den enkleste og mest kunnskapsintensive; jeg skal fortelle deg hvilke problemer jeg møtte og hvordan jeg løste dem. Så la oss gå.

Note

Å måle hastigheten til en LTE-tilkobling er en veldig kompleks sak: du må velge riktig utstyr og måleteknikk, og også ha en god forståelse av topologien og driften av mobilnettverket. I tillegg kan hastigheten påvirkes av flere faktorer: antall abonnenter på en celle, værforhold, selv fra celle til celle kan hastigheten variere dramatisk på grunn av nettverkstopologien. Generelt er dette et problem med et stort antall ukjente, og bare en teleoperatør kan løse det riktig.

I utgangspunktet ville kunden bare kjøre kureren med operatørenes telefoner, ta målinger direkte på telefonen og deretter skrive ned hastighetsmålingsresultatene i en notatbok. Min løsning for å måle hastigheten til lte-nettverk, selv om den ikke er ideell, løser problemet.

På grunn av mangel på tid tok jeg beslutninger ikke til fordel for bekvemmelighet eller praktisk, men til fordel for utviklingshastighet. For eksempel ble omvendt ssh brukt for ekstern tilgang, i stedet for den mer praktiske VPN, for å spare tid på å sette opp serveren og hver enkelt klient.

Teknisk oppgave

Som det står i artikkelen Uten tekniske spesifikasjoner: hvorfor klienten ikke vil ha det: Ikke arbeid uten tekniske spesifikasjoner! Aldri, hvor som helst!

Den tekniske oppgaven var ganske enkel, jeg skal utvide den litt for forståelsen av sluttbrukeren. Valg av tekniske løsninger og utstyr ble diktert av kunden. Så, selve den tekniske spesifikasjonen, etter alle godkjenninger:

Basert på en enkeltbordsdatamaskin vim2 lag en hastighetstester for lte-tilkoblinger via H-modemuawei e3372h - 153 flere teleoperatører (fra en til n). Det er også nødvendig å motta koordinater fra en GPS-mottaker tilkoblet via UART. Foreta hastighetsmålinger ved hjelp av tjenesten www.speedtest.net og legg dem inn i en tabell som:

Samtidig hastighetstest på flere LTE-modemer

Tabell i csv-format. Send deretter dette skiltet på e-post hver 6. time. Ved feil blinker LED-en som er koblet til GPIO-en.

Jeg beskrev de tekniske spesifikasjonene i fri form, etter mange godkjenninger. Men meningen med oppgaven er allerede synlig. En uke ble gitt til alt. Men i virkeligheten varte det i tre uker. Dette er tatt i betraktning at jeg gjorde dette kun etter hovedjobben og i helgene.

Her vil jeg nok en gang gjøre oppmerksom på at kunden på forhånd avtalte bruk av hastighetsmålingstjenesten og maskinvare, noe som i stor grad begrenset mine muligheter. Budsjettet var også begrenset, så det ble ikke kjøpt noe spesielt. Så vi måtte spille etter disse reglene.

Arkitektur og utvikling

Ordningen er enkel og åpenbar. Derfor lar jeg det stå uten noen spesielle kommentarer.

Samtidig hastighetstest på flere LTE-modemer

Jeg bestemte meg for å implementere hele prosjektet i python, til tross for at jeg ikke hadde noen erfaring med å utvikle dette språket i det hele tatt. Jeg valgte det fordi det var en haug med ferdige eksempler og løsninger som kunne få fart på utviklingen. Derfor ber jeg alle profesjonelle programmerere om å ikke skjelle ut min første erfaring med å utvikle meg i python, og jeg er alltid glad for å høre konstruktiv kritikk for å forbedre ferdighetene mine.

Også i prosessen oppdaget jeg at python har to kjørende versjoner 2 og 3, som et resultat slo jeg meg på den tredje.

Maskinvare noder

Enkeltplate vim2

Jeg fikk en enkeltbords datamaskin som hovedmaskin vim2

Samtidig hastighetstest på flere LTE-modemer

En utmerket, kraftig medieprosessor for et smart hjem og SMART-TV, men ekstremt uegnet for denne oppgaven, eller, la oss si, dårlig egnet. For eksempel er hovedoperativsystemet Android, og Linux er et sekundært operativsystem, og følgelig garanterer ingen høykvalitetsdrift av alle noder og drivere under Linux. Og jeg antar at noen av problemene var relatert til USB-driverne til denne plattformen, så modemene fungerte ikke som forventet på dette brettet. Den har også svært dårlig og spredt dokumentasjon, så hver operasjon tok mye tid å grave gjennom kaiene. Selv ordinært arbeid med GPIO tok mye blod. For eksempel tok det meg flere timer å sette opp lysdioden. Men for å være objektiv var det grunnleggende ikke viktig hva slags enkeltkort det var, hovedsaken var at det fungerte og det var USB-porter.

Først må jeg installere Linux på dette brettet. For ikke å gjennomsøke dokumentasjonens villmark for alle, og også for de som skal håndtere dette enkeltbordssystemet, skriver jeg dette kapittelet.

Det er to alternativer for å installere Linux: på et eksternt SD-kort eller på en intern MMC. Jeg brukte en kveld på å finne ut hvordan jeg skulle få det til å fungere med kortet, så jeg bestemte meg for å installere det på MMC, selv om det uten tvil ville vært mye lettere å jobbe med et eksternt kort.

Om fastvaren skjevt fortalt her. Jeg oversetter fra merkelig til russisk. For å flashe brettet må jeg koble til maskinvaren UART. Koblet den til som følger.

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

Samtidig hastighetstest på flere LTE-modemer

Deretter lastet jeg ned fastvaren derav. Spesifikk fastvareversjon VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

For å laste opp denne fastvaren trenger jeg verktøy. Flere detaljer om dette her. Jeg har ikke prøvd å flashe den under Windows, men jeg trenger å fortelle deg noen ord om fastvare under Linux. Først skal jeg installere verktøyene i henhold til instruksjonene.

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

Aaand... Ingenting fungerer. Jeg brukte et par timer på å redigere installasjonsskriptene slik at alt skulle installeres riktig for meg. Jeg husker ikke hva jeg gjorde der, men det var også det sirkuset med hester. Så vær forsiktig. Men uten disse verktøyene er det ingen vits i å torturere vim2 ytterligere. Det er bedre å ikke rote med ham i det hele tatt!

Etter syv sirkler av helvete, skriptkonfigurasjon og installasjon, mottok jeg en pakke med fungerende verktøy. Jeg koblet styret via USB til min Linux-datamaskin, og koblet også til UART i henhold til diagrammet ovenfor.
Jeg setter opp min favoritt minicom-terminal for en hastighet på 115200, uten maskinvare- og programvarefeilkontroll. Og la oss komme i gang.

Samtidig hastighetstest på flere LTE-modemer

Når jeg laster VIM2 i UART-terminalen, trykker jeg på en tast, for eksempel mellomromstasten, for å stoppe innlastingen. Etter at linjen vises

kvim2# 

Jeg skriver inn kommandoen:

kvim2# run update

På verten som vi laster fra, utfører jeg:

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

Det er det, phew. Jeg sjekket, det er Linux på brettet. Logg inn/passord khadas:khadas.

Etter det, noen mindre innledende innstillinger. For videre arbeid deaktiverer jeg passordet for sudo (ja, ikke sikkert, men praktisk).

sudo visudo

Jeg redigerer linjen til skjemaet og lagrer

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

Så endrer jeg gjeldende lokalitet slik at klokken er i Moskva, ellers blir den i Greenwich.

sudo timedatectl set-timezone Europe/Moscow

eller

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

Hvis du synes det er vanskelig, så ikke bruk dette brettet; Raspberry Pi er bedre. Ærlig talt.

Modem Huawei e3372h – 153

Dette modemet var en betydelig blodkilde for meg, og faktisk ble det flaskehalsen i hele prosjektet. Generelt gjenspeiler ikke navnet "modem" for disse enhetene essensen av arbeidet i det hele tatt: dette er en kraftig kombi, denne maskinvaren har en sammensatt enhet som utgir seg for å være en CD-ROM for å installere drivere, og bytter deretter til nettverkskortmodus.

Arkitektonisk, fra synspunktet til en Linux-bruker, etter alle innstillingene, ser det slik ut: etter å ha koblet til modemet, har jeg et eth* nettverksgrensesnitt, som via dhcp mottar IP-adressen 192.168.8.100, og standard gateway er 192.168.8.1.

Og det viktigste øyeblikket! Denne modemmodellen kan ikke fungere i modemmodus, som styres av AT-kommandoer. Alt ville vært mye enklere, opprette PPP-tilkoblinger for hvert modem og deretter operere med dem. Men i mitt tilfelle, "seg selv" (mer presist, en Linux-dykker i henhold til udev-reglene), oppretter et eth-grensesnitt og tildeler en IP-adresse til det via dhcp.

For å unngå ytterligere forvirring foreslår jeg at du glemmer ordet "modem" og sier nettverkskort og gateway, for i hovedsak er det som å koble et nytt nettverkskort med en gateway.
Når det er ett modem gir dette ingen spesielle problemer, men når det er mer enn ett, nemlig n-stykker, oppstår følgende nettverksbilde.

Samtidig hastighetstest på flere LTE-modemer

Det vil si n nettverkskort, med samme IP-adresse, hver med samme standard gateway. Men faktisk er hver av dem koblet til sin egen operatør.

I utgangspunktet hadde jeg en enkel løsning: ved å bruke ifconfig- eller ip-kommandoen, slå av alle grensesnitt og bare slå på ett etter tur og teste det. Løsningen var bra for alle, bortsett fra at jeg under bytteøyeblikkene ikke klarte å koble til enheten. Og siden vekslingen er hyppig og rask, hadde jeg faktisk ingen mulighet til å koble til i det hele tatt.

Derfor valgte jeg veien for å manuelt endre IP-adressene til modemene og deretter drive trafikk ved å bruke ruteinnstillinger.

Samtidig hastighetstest på flere LTE-modemer

Dette var ikke slutten på problemene mine med modemer: i tilfelle strømproblemer falt de av, og en god stabil strømforsyning til USB-huben var nødvendig. Jeg løste dette problemet ved å hardlodde strømmen direkte til navet. Et annet problem som jeg møtte og som ødela hele prosjektet: etter en omstart eller kaldstart av enheten ble ikke alle modemer oppdaget og ikke alltid, og jeg kunne ikke finne ut hvorfor dette skjedde og med hvilken algoritme. Men først ting først.

For at modemet skulle fungere riktig, installerte jeg usb-modeswitch-pakken.

sudo apt update
sudo apt install -y usb-modeswitch

Deretter, etter tilkobling, vil modemet bli riktig oppdaget og konfigurert av udev-delsystemet. Jeg sjekker ved å koble til modemet og sørge for at nettverket vises.
Et annet problem som jeg ikke kunne løse: hvordan kan jeg få navnet på operatøren vi jobber med fra dette modemet? Operatørnavnet finnes i modemets nettgrensesnitt på 192.168.8.1. Dette er en dynamisk nettside som mottar data gjennom Ajax-forespørsler, så bare å wgete siden og analysere navnet vil ikke fungere. Så jeg begynte å se på hvordan man utvikler en nettside osv., og skjønte at jeg holdt på med en slags tull. Som et resultat spyttet han, og operatøren begynte å motta ved å bruke selve Speedtest API.

Mye ville vært enklere hvis modemet hadde tilgang via AT-kommandoer. Det ville være mulig å rekonfigurere det, opprette en ppp-tilkobling, tilordne en IP, få en teleoperatør, etc. Men dessverre, jeg jobber med det jeg har fått.

GPS

GPS-mottakeren jeg fikk hadde UART-grensesnitt og strøm. Det var ikke den beste løsningen, men den var fortsatt gjennomførbar og enkel. Mottakeren så omtrent slik ut.

Samtidig hastighetstest på flere LTE-modemer

For å være ærlig var dette første gang jeg jobbet med en GPS-mottaker, men som jeg forventet, var alt tenkt opp for oss for lenge siden. Så vi bruker bare ferdige løsninger.

Først aktiverer jeg uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) for å koble til GPS.

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

Etterpå sjekker jeg suksessen til operasjonen.

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

Denne kommandoen redigerer tilsynelatende devtreet umiddelbart, noe som er veldig praktisk.

Etter at denne operasjonen er vellykket, start på nytt og installer GPS-demonen.

khadas@Khadas:~$ sudo reboot

Installerer GPS-demonen. Jeg installerer alt og klipper det av umiddelbart for videre konfigurasjon.

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

Redigerer innstillingsfilen.

sudo vim /etc/default/gpsd

Jeg installerer en UART som GPS-en skal henge på.

DEVICES="/dev/ttyS4"

Og så slår vi på alt og starter.

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

Etter det kobler jeg til GPS-en.

Samtidig hastighetstest på flere LTE-modemer

GPS-ledningen er i hendene mine, UART debugger-ledningene er synlige under fingrene mine.

Jeg starter på nytt og sjekker GPS-operasjonen ved å bruke gpsmon-programmet.

Samtidig hastighetstest på flere LTE-modemer

Du kan ikke se satellittene i dette skjermbildet, men du kan se kommunikasjon med GPS-mottakeren, og dette betyr at alt er i orden.

I python prøvde jeg mange alternativer for å jobbe med denne demonen, men jeg slo meg på den som fungerte riktig med python 3.

Jeg installerer det nødvendige biblioteket.

sudo -H pip3 install gps3 

Og jeg skulpturerer arbeidskoden.

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 trenger å få koordinater, gjøres dette med følgende anrop:

longitude, latitude = getPositionData(agps_thread)

Og innen 1-10 sekunder vil jeg enten få koordinaten eller ikke. Ja, jeg hadde ti forsøk på å få koordinater. Ikke optimalt, skjevt og skjevt, men det fungerer. Jeg bestemte meg for å gjøre dette fordi GPS kan ha dårlig mottak og ikke alltid motta data. Hvis du venter på å motta data, vil programmet fryse på dette stedet hvis du jobber i et eksternt rom. Derfor implementerte jeg dette uelegante alternativet.

I prinsippet, hvis det var mer tid, ville det vært mulig å motta data fra GPS direkte via UART, analysere det i en egen tråd og jobbe med det. Men det var ikke tid i det hele tatt, derav den brutalt stygge koden. Og ja, jeg skammer meg ikke.

Lysdiode

Koble til LED-en var enkel og vanskelig på samme tid. Hovedvanskeligheten er at pin-nummeret i systemet ikke samsvarer med pin-nummeret på tavlen og fordi dokumentasjonen er skrevet med venstre hånd. For å sammenligne maskinvare-pin-nummeret og pin-nummeret i operativsystemet, må du kjøre kommandoen:

gpio readall

En tabell med pin-korrespondanse i systemet og på tavlen vil vises. Deretter kan jeg allerede betjene pinnen i selve OS. I mitt tilfelle er LED koblet til GPIOH_5.

Samtidig hastighetstest på flere LTE-modemer

Jeg bytter GPIO-pinnen til utgangsmodus.

gpio -g mode 421 out

Jeg skriver ned null.

gpio -g write 421 0

Jeg skriver ned en.

gpio -g write 421 1

Samtidig hastighetstest på flere LTE-modemer
Alt lyser etter å ha 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)

Nå, i tilfelle feil, ringer jeg error_blink() og LED-en vil blinke vakkert.

Programvare noder

Speedtest API

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

Det som er bra er at det er kildekoder som også kan sees. Hvordan du jobber med denne APIen (enkle eksempler) finner du i relevant seksjon.

Jeg installerer python-biblioteket med følgende kommando.

sudo -H pip3 install speedtest-cli

For eksempel kan du til og med installere en hastighetstester i Ubuntu direkte fra programvaren. Dette er den samme python-applikasjonen, som deretter kan startes direkte fra konsollen.

sudo apt install speedtest-cli -y

Og mål Internett-hastigheten din.

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, akkurat som jeg gjorde. Jeg måtte gå inn i kildekodene til denne hastighetstesten for å implementere dem mer fullstendig i prosjektet mitt. En av de viktigste oppgavene er å få navnet på teleoperatøren for å erstatte det i platen.

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 seg å ikke være så enkelt, selv om det virket mye enklere. Opprinnelig var serverparameteren lik [], sier de, velg den beste serveren. Som et resultat hadde jeg tilfeldige servere, og, som du kanskje gjetter, variabel hastighet. Dette er et ganske komplekst emne, og bruk av en fast server, i så fall statisk eller dynamisk, krever forskning. Men her er et eksempel på grafer for hastighetsmåling for en Beeline-operatør ved dynamisk valg av en testserver og en statisk fast.

Samtidig hastighetstest på flere LTE-modemer
Resultatet av måling av hastighet ved valg av dynamisk server.

Samtidig hastighetstest på flere LTE-modemer
Resultatet av hastighetstesting, med en strengt valgt server.

Under testingen er det "pels" begge steder, og den må fjernes ved hjelp av matematiske metoder. Men med en fast server er det litt mindre og amplituden er mer stabil.
Generelt er dette et sted for stor forskning. Og jeg ville måle hastigheten til serveren min ved å bruke iperf-verktøyet. Men vi holder oss til de tekniske spesifikasjonene.

Sending av mail og feil

For å sende e-post prøvde jeg flere dusin forskjellige alternativer, men til slutt bestemte jeg meg for følgende. Jeg registrerte en postkasse på Yandex og tok deretter Dette er et eksempel på å sende post. Jeg sjekket det og implementerte det i programmet. Dette eksemplet undersøker ulike alternativer, inkludert sending fra gmail, etc. Jeg ville ikke bry meg med å sette opp e-postserveren min og hadde ikke tid til det, men som det viste seg senere, var det også forgjeves.

Loggene ble sendt i henhold til planleggeren, hvis det er en sammenheng, hver 6. time: klokken 00, 06, 12 og 18. Sendte den 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

Det ble også sendt feil i første omgang. Til å begynne med ble de samlet i listen, og deretter sendt også ved hjelp av planleggeren, hvis det var en forbindelse. Imidlertid oppsto det problemer med det faktum at Yandex har en grense på antall meldinger sendt per dag (dette er smerte, tristhet og ydmykelse). Siden det kunne være et stort antall feil selv per minutt, måtte vi slutte å sende feil per post. Så husk når du automatisk sender informasjon om et slikt problem gjennom Yandex-tjenester.

Tilbakemeldingsserver

For å ha tilgang til en ekstern maskinvare og kunne tilpasse og rekonfigurere den, trengte jeg en ekstern server. Generelt, for å være rettferdig, ville det være riktig å sende alle dataene til serveren og bygge alle de vakre grafene i webgrensesnittet. Men ikke alt på en gang.

For VPS valgte jeg ruvds.com. Du kan ta den enkleste serveren. Og generelt sett, for mine formål ville dette være nok. Men siden jeg ikke betalte for serveren av egen lomme, bestemte jeg meg for å ta den med en liten reserve, slik at det ville være nok hvis vi skulle distribuere et webgrensesnitt, vår egen SMTP-server, VPN, etc. Plus, kunne sette opp en Telegram-bot og ikke ha problemer med at den blir blokkert. Derfor valgte jeg Amsterdam og følgende parametere.

Samtidig hastighetstest på flere LTE-modemer

Som en metode for kommunikasjon med maskinvaren, valgte vim2 en omvendt ssh-tilkobling, og som praksis har vist, er den ikke den beste. Hvis tilkoblingen blir brutt, holder serveren porten og det er umulig å koble til gjennom den på en stund. Derfor er det fortsatt bedre å bruke andre kommunikasjonsmetoder, for eksempel VPN. I fremtiden ønsket jeg å bytte til VPN, men hadde ikke tid.

Jeg vil ikke gå inn på detaljer om å sette opp en brannmur, begrense rettigheter, deaktivere root ssh-tilkoblinger og andre truismer ved å sette opp en VPS. Jeg vil gjerne tro at du allerede vet alt. For en ekstern tilkobling oppretter jeg en ny bruker på serveren.

adduser vimssh

Jeg genererer ssh-tilkoblingsnøkler på maskinvaren vår.

ssh-keygen

Og jeg kopierer dem til serveren vår.

ssh-copy-id [email protected]

På maskinvaren vår oppretter jeg en automatisk omvendt ssh-tilkobling ved hver oppstart.

[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 oppmerksom på port 8083: den bestemmer hvilken port jeg skal bruke for å koble til via omvendt ssh. Legg den til oppstart og start.

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

Du kan til og med se statusen:

sudo systemctl status autossh.service

Nå, på vår VPS-server, hvis vi kjører:

ssh -p 8083 khadas@localhost

Så kommer jeg til testbiten med maskinvare. Og fra maskinvaren kan jeg også sende logger og eventuelle data via ssh til serveren min, noe som er veldig praktisk.

Setter alt sammen

Samtidig hastighetstest på flere LTE-modemer
Slår på, la oss starte utvikling og feilsøking

Puh, vel, det er det, jeg beskrev alle nodene. Nå er det på tide å sette alt sammen. Du kan se koden her.

Et viktig poeng med koden: Dette prosjektet starter kanskje ikke slik, fordi det var skreddersydd for en spesifikk oppgave, av en spesifikk arkitektur. Selv om jeg gir kildekoden, vil jeg fortsatt forklare de mest verdifulle tingene her, rett i teksten, ellers er det helt uforståelig.

I begynnelsen initialiserer jeg gps, gpio og starter en egen planleggingstråd.

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

Planleggeren er ganske enkel: den ser ut om tiden er inne for å sende meldinger og hva gjeldende feilstatus er. Hvis det er et feilflagg, 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 vanskeligste delen av dette prosjektet er å opprettholde den omvendte ssh-tilkoblingen for hver test. Hver test involverer rekonfigurering av standard gateway og DNS-server. Siden ingen leser uansett, vit at toget ikke kjører på treskinner. Den som finner påskeegget får litt godteri.

For å gjøre dette lager jeg en egen rutingtabell -set-mark 0x2 og en regel for å omdirigere trafikk.

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 mer om hvordan det fungerer les i denne artikkelen.

Deretter går jeg inn i en endeløs loop, hvor vi hver gang får en liste over tilkoblede modemer (for å finne ut om nettverkskonfigurasjonen plutselig har endret seg).

network_list = getNetworklist()

Å få en liste over nettverksgrensesnitt er ganske enkelt.

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

Etter å ha mottatt listen satte jeg IP-adresser til alle grensesnitt, som jeg viste på bildet i kapittelet om modemet.

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

Deretter går jeg ganske enkelt gjennom hvert grensesnitt i en loop. Og jeg konfigurerer hvert grensesnitt.

	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 sjekker grensesnittet for funksjonalitet, hvis det ikke er noe nettverk, genererer jeg feil. Hvis det er et nettverk, er det på tide å handle!

Her konfigurerer jeg ssh-ruting til dette grensesnittet (hvis det ikke er gjort), sender feil til serveren hvis tiden er inne, sender logger og kjører til slutt en speedtest og lagrer loggene 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 verdt å nevne funksjonen til å sette opp 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 må du legge til all denne skjønnheten til oppstart. For å gjøre dette lager 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 slår på autoloading og starter!

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

Nå kan jeg se logger over hva som skjer ved å bruke kommandoen:

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

Funn

Vel, nå er det viktigste, hva skjedde som et resultat? Her er noen grafer som jeg klarte å fange under utviklings- og feilsøkingsprosessen. Grafene ble bygget ved hjelp av gnuplot med følgende skript.

#! /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 opplevelsen var med Tele2-operatøren, som jeg gjennomførte i flere dager.

Samtidig hastighetstest på flere LTE-modemer

Her brukte jeg en dynamisk måleserver. Hastighetsmålinger fungerer, men svinger veldig, men en viss gjennomsnittsverdi er fortsatt synlig, og dette kan oppnås ved å filtrere dataene, for eksempel med et glidende gjennomsnitt.

Senere bygde jeg en rekke grafer for andre teleoperatører. I dette tilfellet var det allerede én testserver, og resultatene var også veldig interessante.

Samtidig hastighetstest på flere LTE-modemer

Samtidig hastighetstest på flere LTE-modemer

Samtidig hastighetstest på flere LTE-modemer

Samtidig hastighetstest på flere LTE-modemer

Som du ser er temaet svært omfattende for forskning og bearbeiding av disse dataene, og varer tydeligvis ikke i et par ukers arbeid. Men…

Resultat av arbeid

Arbeidet ble brått fullført på grunn av omstendigheter utenfor min kontroll. En av svakhetene ved dette prosjektet, etter min subjektive mening, var modemet, som egentlig ikke ønsket å jobbe samtidig med andre modemer, og gjorde slike triks hver gang det ble lastet. For disse formålene er det et stort antall andre modemmodeller; vanligvis er de allerede i Mini PCI-e-formatet og er installert inne i enheten og er mye enklere å konfigurere. Men det er en helt annen historie. Prosjektet var interessant og jeg var veldig glad for at jeg fikk være med på det.

Samtidig hastighetstest på flere LTE-modemer

Kilde: www.habr.com

Legg til en kommentar