Under quarantine, I was invited to participate in the development of a device for measuring the speed of LTE modems for several mobile network operators.
The client wanted to assess the speed of various network operators in different geographical locations to understand which mobile network would be most optimal for installing equipment that uses LTE connections, for example, for video streaming. The solution needed to be as simple and inexpensive as possible, without costly equipment.
I will say right away that the task is not the simplest and is quite research-intensive; I will tell you about the problems I encountered and how I solved them. So, let's get started.
Bemærk
Measuring the speed of LTE connections is quite complex: it is necessary to properly select the equipment and measurement methodology, as well as to have a good understanding of the topology and operation of the mobile network. Additionally, several factors can affect the speed: the number of subscribers on the cell, weather conditions, and even the speed can drastically differ from one cell to another due to network topology. Overall, this is a task with a huge number of unknowns, and only a network operator can solve it correctly.
Initially, the client just wanted to have a courier run around with phones of the operators, performing measurements directly on the phones and then recording the results in a notebook. My solution for measuring LTE network speeds, while not perfect, does address the task at hand.
Due to time constraints, I made decisions not in favor of convenience or practicality, but for faster development. For example, for remote access, I initiated a reverse SSH instead of a more practical VPN, to save time on server configuration and each individual client.
Teknisk specifikation
As stated in the article : Don't work without a technical specification! Never, anywhere!
The technical specification was quite simple; I will expand it a bit for the understanding of the end user. The choice of technical solutions and equipment was dictated by the client. Thus, the technical specification, after all approvals:
Based on a single-board computer vim2 to make an LTE connection speed tester through H modemsuawei e3372h — 153 flere teleoperatører (fra én til n). Det er også nødvendigt at få koordinater fra en GPS-modtager, der er tilsluttet via UART. Hastighedsmålinger udføres ved hjælp af tjenesten og samlet dem i en tabel af typen:
Tabel i csv-format. Herefter skal denne tabel sendes pr. e-mail hver 6. time. I tilfælde af fejl, skal en LED, der er tilsluttet GPIO, blinke.
Jeg har beskrevet kravene i frie former, efter mange godkendelser. Men formålet med opgaven er allerede klart. Tiden til det hele blev givet en uge. Men i virkeligheden strakte det sig over tre uger. Dette medtaget at jeg kun gjorde dette efter hovedarbejdet og i weekenderne.
Her vil jeg endnu engang påpege, at kunden på forhånd havde aftalt brugen af hastighedsmålingstjenesten og det hardware, hvilket stærkt begrænsede mine muligheder. Budgettet var også begrænset, så der blev ikke købt meget ekstra. Så jeg måtte spille efter disse regler.
Arkitektur og udvikling
Skemaet er simpelt og åbenlyst. Derfor vil jeg lade det være uden særlige kommentarer.

Jeg besluttede at realisere hele projektet i python, selvom jeg slet ikke havde erfaring med udvikling på dette sprog. Jeg valgte det, da der var en masse klare eksempler og løsninger, der kunne fremskynde udviklingen. Så jeg beder alle professionelle programmører om ikke at kritisere min første udviklingserfaring med python, og jeg er altid glad for at høre konstruktiv kritik for at forbedre mine færdigheder.
Jeg opdagede også undervejs, at python har to populære versioner 2 og 3, som endte med at vælge den tredje.
Hardware enheder
Enkeltbrædt vim2
Som hovedmaskine fik jeg et enkeltbrædt

En fremragende, kraftfuld medieenhed til smart home og SMART-TV, men bemærkelsesværdigt lidt egnet til denne opgave, eller lad os sige, svagt egnet. For eksempel er dens hoved-OS Android, mens Linux er et supplement, og derfor garanterer ingen, at alle komponenter og drivere fungerer godt under Linux. Jeg formoder, at dele af problemerne var relateret til USB-drivere på denne platform, hvilket betød, at modemmerne ikke fungerede på bundkortet, som jeg havde forventet. Derudover er dokumentationen meget dårlig og fragmenteret, så hver operation tog lang tid at finde ud af i dokumenterne. Selv en simpel opgave med GPIO kostede mig meget tid. For eksempel tog det mig flere timer at konfigurere lysdioden. Men for at være objektiv var det ikke grundlæggende vigtigt, hvilken enkeltstående enhed det var, det vigtigste var, at den fungerede, og at der var USB-porte.
For at komme i gang skal jeg installere Linux på dette bundkort. For ikke at lede alle gennem dokumentationsjunglen, og også for dem, der skal arbejde med denne enkeltstående enhed, skriver jeg dette kapitel.
Der er to måder at installere Linux på: enten på et eksternt SD-kort eller på den interne MMC. Jeg kæmpede en aften med kortet, og fik aldrig styr på, hvordan jeg fik det til at fungere, så jeg besluttede at installere det på MMC, selvom det uden tvivl ville have været meget lettere at arbejde med et eksternt kort.
Om firmware . Jeg oversætter fra det mærkelige til russisk. For at kunne flashe bundkortet er jeg nødt til at tilslutte en hardware UART. Jeg tilsluttede den
- Tool Pin GND: Pin17 på VIM's GPIO
- Tool Pin TXD: Pin18 på VIM's GPIO (Linux_Rx)
- Tool Pin RXD: Pin19 på VIM's GPIO (Linux_Tx)
- Tool Pin VCC: Pin20 på VIM's GPIO

Derefter downloadede jeg firmwaren . Den specifikke firmwareversion .
For at kunne overføre denne firmware har jeg brug for nogle værktøjer. Mere detaljeret om dette er beskrevet . Jeg har ikke prøvet at flashe under Windows, men jeg skal nævne et par ord om at flashe under Linux. Først installerer jeg værktøjerne i henhold til instruktionerne.
git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALLOg… Intet virker. Jeg brugte et par timer på at rette installationsscripts, så alt kunne installeres korrekt hos mig. Hvad jeg gjorde kan jeg ikke huske, men det var også en bestemt cirkus med heste. Så vær forsigtig. Men uden disse værktøjer giver det ikke mening at plage vim2 videre. Det er bedre ikke at involvere mig overhovedet!
Efter syv runder i helvede, konfiguration af scripts og installation fik jeg pakken med fungerende værktøjer. Jeg tilsluttede kredsboardet via USB til min Linux-computer, og UART er også tilsluttet efter skemaet ovenfor.
Jeg indstiller min yndlingsterminal minicom til en hastighed på 115200, uden hardware- og softwarefejlkontrol. Så går vi i gang.

Når jeg starter VIM2 i UART-terminalen, trykker jeg på en vilkårlig tast, for eksempel mellemrum, for at stoppe opstarten. Når linjen vises,
kvim2# Indtaster kommandoen:
kvim2# run updatePå værten, hvorfra vi downloader, udfører jeg:
burn-tool -v aml -b VIM2 -i VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.imgDet hele, puha. Jeg har opdateret firmware, og der er Linux på kredsboardet. Login/password khadas:khadas.
Efter det små indledende indstillinger. For videre arbejde slukker jeg for adgangskoden til sudo (ja, det er usikkert, men praktisk).
sudo visudoJeg redigerer linjen til at se sådan ud og gemmer
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALLDerefter ændrer jeg den nuværende lokalitet, så tiden er i Moskva, ellers vil den være i Greenwich.
sudo timedatectl set-timezone Europe/Moscoweller
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtimeHvis det virker svært, så brug ikke dette kredsboard, det er bedre at vælge Raspberry Pi. Ærligt.
Huawei e3372h modem — 153
Dette modem har givet mig en del problemer, og det blev faktisk det svageste led i hele projektet. Egentlig afspejler betegnelsen "modem" ikke arbejdet i disse enheder: det er en kraftfuld kombination, denne enhed har et sammensat apparat, som foregiver at være CD-ROM for at installere drivere, og derefter skifter det til netværkskortmodus.
Arkitektonisk set, set fra en Linux-bruger efter alle indstillinger, ser det sådan ud: efter tilslutning af modemet, får jeg et netværksinterface eth*, som via DHCP får ip-adressen 192.168.8.100 og standardgatewayen 192.168.8.1.
Og det vigtigste punkt! Denne model af modem kan ikke arbejde i modemtilstand, som styres af AT-kommandoer.. Alt ville have været meget lettere at oprette PPP-forbindelser til hvert modem og derefter operere med dem. Men i mit tilfælde skaber "sig selv" (mere præcist Linux-drivere i henhold til reglerne for udev) eth-interface og tildeler det en ip-adresse via DHCP.
For at undgå forvirring foreslår jeg at glemme ordet "modem" og tale om netværkskort og gateway, da det i princippet er som at tilslutte et nyt netværkskort med en gateway.
Når der er et modem, giver det ikke særlige problemer, men når der er mere end ét, specielt n-stykker, så opstår følgende netværkssituation.

Det vil sige, at n netværkskort har én IP-adresse, og hver af dem har den samme standardgateway. Men i praksis er hver enkelt tilsluttet sin egen operatør.
Oprindeligt havde jeg en simpel løsning: ved hjælp af kommandoerne ifconfig eller ip deaktiverede jeg alle interfaces og aktiverede dem enkeltvis for at teste dem. Løsningen var god, undtagen at jeg i overgangsperioderne ikke havde mulighed for at tilslutte til enheden. Da overgange ofte og hurtigt skete, havde jeg reelt ikke mulighed for at tilslutte overhovedet.
Derfor valgte jeg at ændre IP-adresserne på modemmerne 'manuelt' og derefter køre trafik ved hjælp af routingindstillinger.

Mine problemer med modemmerne sluttede ikke der: i tilfælde af strømproblemer frakoblede de sig, og der krævedes en god stabil strømforsyning til USB-hubben. Jeg løste dette problem ved at lodde strømmen direkte til hubben. Et andet problem, jeg stødte på, og som ødelagde hele projektet: efter genstart eller koldt start af enheden blev ikke alle modemmer anerkendt, og det skete ikke altid, og jeg kunne ikke finde ud af, hvorfor det skete, og hvilken algoritme der lå bag. Men lad os tage det skridt for skridt.
For korrekt drift af modemmet installerede jeg pakken usb-modeswitch.
sudo apt update
sudo apt install -y usb-modeswitch Derefter vil modemmet blive korrekt anerkendt og konfigureret af udev-systemet efter tilslutning. Jeg checker bare ved at tilslutte modemmet og sikre, at netværket er aktivt.
En anden problemstilling, jeg ikke kunne løse: hvordan får jeg navnet på den operatør, vi arbejder med, fra dette modem? Operatørens navn findes i modemmes web-interface på adressen 192.168.8.1. Dette er en dynamisk webside, der får data via ajax-forespørgsler, så det er ikke muligt bare at wget'e siden og parse navnet. Derfor begyndte jeg at se på, hvordan man kunne arbejde med websiden osv., og indså, at jeg lavede noget tåbeligt. Resultatet var, at jeg gav op og begyndte at hente operatøren ved hjælp af API'et fra Speedtest.
Meget ville være lettere, hvis modemmet havde adgang via AT-kommandoer. Det ville være muligt at re-konfigurere det, oprette ppp-forbindelser, tildele IP'er, få operatørens navn osv. Men desværre arbejder jeg med det, der er givet.
GPS
GPS-modtageren, jeg fik udleveret, havde en UART-grænseflade og strømforsyning. Det var ikke den bedste løsning, men det var stadig funktionelt og enkelt. Modtageren så nogenlunde sådan ud.

Ærligt talt arbejdede jeg første gang med en GPS-modtager, men som forventet, var der allerede fundet løsninger på forhånd. Så vi bruger blot de eksisterende løsninger.
Jeg starter med at aktivere uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) til at tilslutte GPS.
khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okayDerefter kontrollerer jeg, om operationen var succesfuld.
khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okayDenne kommando redigerer tilsyneladende devtree i realtid, hvilket er meget nyttigt.
Efter en vellykket operation genstarter vi og installerer gps-dæmonen.
khadas@Khadas:~$ sudo rebootInstallation af gps-dæmonen. Jeg installerer alt og stopper den straks til videre konfiguration.
sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
/* GPS dæmon stop/disable */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socketJeg redigerer konfigurationsfilen.
sudo vim /etc/default/gpsdJeg konfigurerer UART, som GPS'en vil være tilsluttet.
DEVICES="/dev/ttyS4"Og så tænder vi for det hele og starter det op.
/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socketEfterfølgende tilslutter jeg GPS.

I hænderne har jeg en GPS-kabel, og under fingrene kan jeg mærke UART-debuggerens ledninger.
Jeg genstarter og kontrollerer GPS'ens funktion ved hjælp af programmet gpsmon.

På dette skærmbillede ses der ingen satellitter, men der er kommunikation med GPS-modtageren, hvilket indikerer, at alt er i orden.
Jeg har afprøvet mange varianter af at arbejde med denne dæmon i Python, men jeg stoppede ved den, der fungerede korrekt med Python 3.
Jeg installerer den nødvendige bibliotek.
sudo -H pip3 install gps3 Og jeg skriver kode til arbejdet.
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 ("Vent gps tæller = %d" % counter)
if counter == 10:
ErrorMessage("Fejl med GPS-modtageren!!!")
return "NA", "NA"
time.sleep(1.0)
...
f __name__ == '__main__':
...
#gps
agps_thread = AGPS3mechanism() # Instansier AGPS3-mekanismer
agps_thread.stream_data() # Fra localhost (), eller andre værter, fx (host='gps.ddns.net')
agps_thread.run_thread() # Tidsbegrænsning for at sove efter et tomt opslag, standard '()' 0,2 to tidedele af et sekund
Hvis jeg skal have koordinater, gøres det med følgende kald:
longitude, latitude = getPositionData(agps_thread)
Inden for 1-10 sekunder vil jeg enten få koordinatoren, eller jeg vil ikke. Ja, jeg har haft ti forsøg på at få koordinatorer. Det er ikke ideelt, men det virker. Jeg valgte at gøre det sådan, fordi GPS kan have en dårlig forbindelse og ikke altid modtage data. Hvis man venter på at få data, vil programmet hænge i det øjeblik, man arbejder i et lukket rum. Derfor implementerede jeg denne lidt klodsede løsning.
I princippet, hvis der var mere tid, kunne man modtage data direkte fra GPS via UART, parse dem i en separat tråd og arbejde med dem. Men jeg havde slet ikke tid, så derfor den forfærdelige kode. Og ja, jeg skammer mig ikke.
LED
Også tilslutningen af LED var både simpel og kompliceret på samme tid. Hovedproblemet er, at pin-nummeret i systemet ikke svarer til pin-nummeret på kredspladen, og fordi dokumentationen er skrevet halvhjertet. For at matche det fysiske pin-nummer med pin-nummeret i operativsystemet skal man udføre kommandoen:
gpio readallDer vil blive vist en tabel med overensstemmelse mellem pin i systemet og på kredspladen. Efter dette kan jeg arbejde med pinnen i selve operativsystemet. I mit tilfælde er LED tilsluttet GPIOH_5.

Jeg skifter GPIO pin i udgangsmodus.
gpio -g mode 421 outJeg skriver nul.
gpio -g write 421 0Jeg skriver en.
gpio -g write 421 1 
Alt lyser, efter at jeg har 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 blinker pænt for os.
Programmoduler
Speedtest API
Jeg er glad for, at speedtest.net har sit eget python-API, som man kan se på .
Det gode ved dette er, at der også er kildekoder, som man kan se. Hvordan man arbejder med dette API (simpelste eksempler) kan ses i .
Jeg installerer python-biblioteket med følgende kommando.
sudo -H pip3 install speedtest-cliSom et eksempel kan du endda installere speedtesteren i Ubuntu direkte fra repo. Det er det samme python-program, som efterfølgende kan køres direkte fra konsollen.
sudo apt install speedtest-cli -yOg foretage målinger af din internetforbindelse.
speedtest-cli
Henter speedtest.net-konfiguration...
Tester fra B***** (*.*.*.*)...
Henter serverliste fra speedtest.net...
Vælger den bedste server baseret på ping...
Vært af MTS (Moskva) [0.12 km]: 11.8 ms
Tester downloadhastighed................................................................................
Download: 7.10 Mbit/s
Tester uploadhastighed......................................................................................................
Upload: 3.86 Mbit/s
I resultatet, som jeg har gjort. Jeg måtte dykke ned i kildekoderne til denne speedtest for at integrere dem mere fuldstændigt i mit projekt. En af de vigtigste opgaver er at også få navnet på teleselskabet for at indsætte det i tabellen.
import speedtest
from datetime import datetime
...
# Angiv en specifik server til testen
#6053) MaximaTelecom (Moskva, Den Russiske Føderation)
servers = ["6053"]
# Hvis du vil bruge en single-threaded test
threads = None
s = speedtest.Speedtest()
# Hent mobiloperatørens navn
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
# Hent en tekststreng med serverparametrene
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
# Download test
s.download(threads=threads)
# Upload test
s.upload(threads=threads)
# Hent resultaterne
s.results.share()
# Derefter dannes en streng til at skrive til en csv-fil.
# Hent GPS-position
longitude, latitude = getPositionData(agps_thread)
# Tid og dato
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"
# Her kommer der skrivning til logfilen
Det viste sig heller ikke at være så enkelt, selvom det kunne synes sådan. Oprindeligt var parameteren servers lig med [], som sagde vælg den bedste server. Resultatet var, at jeg havde tilfældige servere, og som man let kan gætte, svingende hastigheder. Det er et ret komplekst emne at bruge en fast server, og hvis ja, så en statisk eller dynamisk, kræver det undersøgelse. Men her er et eksempel på hastighedsmålinger fra operatøren Beeline med dynamisk valg af testserver og én fast valgt.

Resultatet af hastighedsmålingen ved valg af en dynamisk server.

Resultatet af hastighedstesten, ved kun at vælge én fast server.
Der er "brus" i testen begge steder, og det skal fjernes med matematiske metoder. Men med en fast server er det en smule mindre, og amplituden er mere stabil.
Generelt er dette et sted for omfattende undersøgelser. Og jeg ville have foretaget hastighedsmålinger til min egen server ved hjælp af værktøjet iperf. Men vi holder os til kravspecifikationen.
Afsendelse af e-mails og fejl
Jeg har prøvet en række forskellige metoder til at sende e-mails, men endte med følgende. Jeg registrerede en e-mailadresse på yandex og tog derefter . Jeg testede det og implementerede det i programmet. I dette eksempel gennemgås forskellige metoder, herunder afsendelse via gmail osv. Jeg havde ikke lyst til at rode med at opsætte min egen e-mailserver, og der var ikke tid til det, men som det senere viste sig, var det heller ikke nødvendigt.
Logene blev sendt via planlæggeren, hvis der var forbindelse, hver 6. time: kl. 00.00, 06.00, 12.00 og 18.00. Jeg sendte dem på følgende måde.
from send_email import *
...
message_log = "Log for test af board nr. 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')
curtime = datetime.now().strftime('%H:%M:%S')
try:
for addr_to in EmailForSend:
send_email(addr_to, message_log, "Log for " + curdata + " " + curtime, files)
except:
print("Netværksproblem ved sending af mail")
return False
return True
Fejlene blev også sendt fra begyndelsen. Først blev de akkumuleret i en liste, og så blev de sendt også ved hjælp af planlæggeren, hvis der var forbindelse. Men senere opstod der problemer, da Yandex har en begrænsning på antallet af sendte beskeder pr. dag (det er en smerte, sorg og ydmygelse). Da der kunne være et enormt antal fejl på et minut, måtte man give op med at sende fejl via mail. Så husk dette, når der sendes automatisk via Yandex-tjenester.
Feedback-server
For at have adgang til det fjerne udstyr og have mulighed for at konfigurere og omkonfigurere det, havde jeg brug for en ekstern server. Generelt set ville det være korrekt at sende alle data til serveren og opbygge alle de flotte grafer i webgrænsefladen. Men ikke alt på én gang.
Som VPS valgte jeg . Man kunne have taget den simpleste server. Og i princippet ville det være mere end tilstrækkeligt til mine formål. Men da jeg ikke betalte for serveren af egen lomme, besluttede jeg at vælge med lidt ekstra kapacitet, så det ville være tilstrækkeligt, hvis vi skulle implementere webgrænsefladen, vores SMTP-server, VPN osv. Plus at have mulighed for at konfigurere en Telegram-bot uden problemer med blokeringer. Derfor valgte jeg Amsterdam og følgende parametre.

Som metode til at kommunikere med udstyret vim2 valgte jeg omvendt SSH-forbindelse, og som erfaringen viser — det er ikke det bedste. Når forbindelsen brydes, holder serveren porten, og det er umuligt at forbinde i nogen tid. Derfor er det stadig bedre at bruge andre kommunikationsmetoder, for eksempel VPN. Jeg ville gerne skifte til VPN i fremtiden, men jeg nåede ikke at få det gjort.
Jeg vil ikke gå i detaljer med firewall-konfigurationen, begrænsning af rettigheder, deaktivering af SSH-forbindelsen for root og andre grundlæggende VPS-indstillinger. Jeg håber, at du allerede kender det hele. For at oprette en fjernforbindelse opretter jeg en ny bruger på serveren.
adduser vimsshPå vores maskine genererer jeg SSH-nøgleforbindelser.
ssh-keygenOg jeg kopierer dem til vores server.
ssh-copy-id vimssh@host.comPå vores maskine opretter jeg automatisk en tilbagegående SSH-forbindelse ved hver opstart.
[Unit]
Beskrivelse=Auto Reverse SSH
Kræver=systemd-networkd-wait-online.service
Efter=systemd-networkd-wait-online.service
[Service]
Bruger=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 vimssh@host.com
RestartSec=5
Restart=altid
[Install]
WantedBy=multi-user.target
Bemærk, at port 8083 bestemmer, hvilken port jeg vil bruge til at oprette forbindelse via tilbagegående SSH. Vi tilføjer det til opstart og starter det.
sudo systemctl enable autossh.service
sudo systemctl start autossh.serviceMan kan endda se status:
sudo systemctl status autossh.serviceNu, på vores VPS-server, hvis jeg udfører:
ssh -p 8083 khadas@localhostKommer jeg til min testmaskine. Og fra maskinen kan jeg også sende logfiler og data via SSH til min server, hvilket er meget praktisk.
Vi samler det hele

Lad os begynde, vi går i gang med udvikling og fejlfinding.
Puh, jeg har vist dækket alle punkter. Nu er det tid til at samle det hele til en samlet helhed. Du kan se koden. .
Et vigtigt punkt med koden: Dette projekt vil muligvis ikke starte «out of the box», da det er tilpasset en specifik opgave og arkitektur. Selvom jeg giver kildekoden, vil jeg dog gerne give de mest værdifulde informationer her i teksten; ellers er det helt uforståeligt.
I starten har jeg initialisering af GPS, GPIO og starter en separat tråd til planlæggeren.
#запуск потока планировщика
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()Planlæggeren er ret simpel: den tjekker, om det er tid til at sende beskeder, samt hvad status for fejl er. Hvis der er en fejlflag, blinker 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)Det mest komplekse ved dette projekt er at bevare den tilbagegående SSH-forbindelse under hver test. Hver test kræver en ny konfiguration af standard gateway og DNS-server. Da ingen alligevel læser det, så ved, at toget ikke kører på træskinner. Den der finder påskeægget vil få en godbid.
Til dette opretter jeg en separat routingtabel —set-mark 0x2 og en regel for trafikdirigering.
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æse mere om, hvordan dette fungerer .
Derefter går jeg ind i en uendelig loop, hvor jeg hver gang henter listen over tilsluttede modemmer (for at se, om netværkskonfigurationen er ændret).
network_list = getNetworklist()At hente listen over netværksinterface er relativt 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_listEfter at have hentet listen, tildeler jeg IP-adresser til alle interface, som vist på billedet i kapitlet om modemmer.
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")Derefter går jeg simpelthen gennem hvert interface i en loop. Og jeg konfigurerer hvert interface.
for iface in network_list:
ConfigNetwork(iface)def ConfigNetwork(iface):
#nulstiller alle indstillinger
cmd_run("sudo ip route flush all")
#Tildeler standardgateway
cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#angiver dns-server (dette er nødvendigt for at køre speedtest)
cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")Jeg kontrollerer interface for funktionalitet; hvis der ikke er noget netværk, danner jeg fejl. Hvis netværket findes, er det tid til at handle!
Her konfigurerer jeg ssh-routing til det pågældende interface (hvis det ikke allerede er gjort), sender fejl til serveren, og når tiden er inde, sender jeg logfiler og til sidst udfører jeg speedtest og gemmer loggene i en csv-fil.
if not NetworkAvalible():
....
#Her danner vi fejl
....
else: #Der er netværk, hurra, vi arbejder!
#Hvis vi har et problematisk interface, hvor ssh kører, så ændrer vi det
if (sshint == lastbanint or sshint == "free"):
print("********** Setup SSH ********************")
if sshint != "free":
cmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint + " table 102")
SetupReverseSSH(iface)
sshint = iface
#da netværket fungerer, lad os hurtigt sende alt!!!
if ready_to_send:
print ("**** Klar til at sende!!!")
if sendLogs():
ready_to_send = False
if error_status:
SendErrors()
#og så tester vi hastigheden og gemmer loggene. Det er værd at nævne funktionen til at indstille 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 er det nødvendigt at tilføje al denne skønhed til autostart. For dette opretter jeg en fil:
sudo vim /etc/systemd/system/modems_speedtest.serviceOg skriver dette i den:
[Unit]
Beskrivelse=Modem hastighedstest
Kræver=systemd-networkd-wait-online.service
Efter=systemd-networkd-wait-online.service
[Service]
Bruger=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
RestartSec=5
Restart=altid
[Install]
WantedBy=multi-user.target
Aktiverer autostart og starter!
sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.serviceNu kan jeg se loggene over, hvad der sker ved hjælp af kommandoen:
journalctl -u modems_speedtest.service --no-pager -fResultater
Men nu er det vigtigste: hvad blev resultatet? Jeg vil præsentere nogle grafer, som jeg har formået at optage under udviklingen og fejlretningen. Grafene 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 erfaring var med Tele2, som jeg gennemførte over flere dage.

Her brugte jeg en dynamisk måleserver. Målingerne af hastigheden fungerer, men varierer meget, dog er der stadig en vis gennemsnitlig værdi, som kan opnås ved at filtrere data, for eksempel ved hjælp af glidende gennemsnit.
Senere byggede jeg flere grafer for forskellige teleselskaber. Testserveren i dette tilfælde var den samme, og resultaterne var også meget interessante.




Som det ses, er emnet meget omfattende til forskning og behandling af disse data, og det kræver tydeligvis ikke bare et par uger af arbejdet. Men…
Resultatet af arbejdet
Arbejdet blev brat afsluttet af omstændigheder, der ikke var under min kontrol. En af projektets svagheder, efter min subjektive mening, var modemet, som ikke rigtig ville fungere samtidigt med andre modemer, og ved hver opstart lavede det sådanne numre. Til disse formål findes der et stort antal andre modemmodeller, der typisk har Mini PCI-e format og placeres inde i enheden, og de er meget nemmere at konfigurere. Men det er en helt anden historie. Projektet var interessant, og jeg var meget glad for at have fået mulighed for at deltage i det.
Kilde: habr.com

