Karantiinis soovitati mul osaleda LTE-modemite kiirusmõõtmisseadmestiku arenduses mitme mobiilside operaatori jaoks.
Kliendil oli soov hinnata erinevate mobiilside operaatorite kiirus erinevates geograafilistes punktides, et mõista, milline mobiilside operaator oleks tema jaoks ökonoomseim LTE-ühendusega seadmete paigaldamisel, näiteks videostreaminguks. Samas pidi ülesanne olema lahendatud maksimaalselt lihtsalt ja odavalt, ilma kallite seadmeteta.
Tõden kohe, et ülesanne ei olnud lihtne ja teaduslikult keeruline, ning räägin, millised probleemid mul tekkisid ja kuidas ma neid lahendasin. Nii et, alustame.
Märkus
LTE-ühenduse kiirusmõõtmine on üsna keeruline asi: tuleb õigesti valida varustus ja mõõtmismeetod ning samas olla hästi kursis mobiilsidevõrgu topoloogia ja töötamisega. Lisaks võivad kiirusse mõjutada mitmed tegurid: abonentide arv sektoris, ilmastikuolud, isegi sektorite vahel võib kiirus märgatavalt erineda võrgu topoloogia tõttu. Kokkuvõttes on see ülesanne, kus on palju teadmata, ja õigesti suudab seda lahendada vaid mobiilsideoperaator.
Kliendi algne soov oli lihtsalt saata kullerit mobiilioperaatorite telefonidega, mõõta kiirust otse telefonis ja seejärel kirja panna mõõtmis tulemused vihikusse. Minu lahendus LTE-võrkude kiirusmõõtmiseks, ehkki mitte ideaalne, lahendab antud ülesande.
Aja vähesuse tõttu tegin otsuseid mitte mugavuse või praktilisuse kasuks, vaid arenduse kiirusest lähtudes. Näiteks, kauaksesiooni jaoks tõstsin üles pöördssh, asemel et kasutada praktilisemat vpn-i, et säästa aega serveri ja iga eraldi kliendi seadistamise pealt.
Tehniline ülesanne
Nagu artiklis öeldud : Ärge töötage ilma TÅž! Kunagi, kusagil!
Tehniline ülesanne oli piisavalt lihtne, laiendan seda veidi lõppkasutaja mõistmiseks. Tehniliste lahenduste ja seadmete valik sõltus kliendist. Niisiis, siin on TÅž, pärast kõiki kooskõlastamisi:
Ühe plaadi arvuti baasil vim2 teha LTE-ühenduse kiirusetester H-modemite kauduuawei e3372h — 153 mitmest telekommunikatsiooni operaatorist (ühest kuni n). Samuti on vajalik GPS-vastuvõtjalt, mis on ühendatud UART-i kaudu, saada koordinaate. Kiirusmõõtmisi teostatakse teenuse abil, ja need kokku viia järgmise vorminguga tabelisse:
Tabel csv-formaadis. Pärast seda saata see e-posti teel iga 6 tunni järel. Viga tekkimisel vilkuma LED, mis on ühendatud GPIO-ga.
Tehnilised nõuded olen kirja pannud vabalt, pärast mitmeid kooskõlastusi. Kuid ülesande sisu on juba selge. Tähtaeg oli algselt nädal, kuid reaalsuses venis see kolmeks nädalaks. See arvesse võttes, et tegin seda ainult pärast põhitööd ja nädalavahetustel.
Siinkohal tahan veelkord rõhutada, et tellija oli eelnevalt kokku leppinud kiirusmõõtmis teenuse ja riistvara kasutamise, mis piiras oluliselt minu võimalusi. Eelarve oli samuti piiratud, seega ei soetatud eriti midagi lisaks. Nii et tuli mängida nende reeglite järgi.
Arhitektuur ja arendus
Schema on lihtne ja arusaadav. Seetõttu jätan selle ilma eriliste kommentaarideta.

Otsustasin kogu projekti teostada pythonis, vaatamata sellele, et mul ei olnud sellel keelel arendamise osas üldse kogemusi. Valisin selle, kuna oli palju valmislahendusi ja näiteid, mis võiksid arendust kiirendada. Seetõttu palun kõigil professionaalsetel programmeerijatel mitte kritiseerida minu esimest arendusprojekti pythonis ja olen alati valmis kuulama konstruktiivset kriitikat, et oma oskusi parandada.
Samuti avastasin protsessi käigus, et pythonil on kaks peamist versiooni: 2 ja 3, seetõttu jäin pidama kolmanda peale.
Riistvara sõlmed
Üheplaadiline vim2
Põhimasinaks anti mulle üheplaadiline arvuti

Hea, võimas meedia kombain nutikodu ja SMART-TV jaoks, kuid imelikult sobimatu selle ülesande jaoks, või ütleme nii, nõrgalt sobiv. Näiteks, selle peamine opsüsteem on Android ja Linux on juhuslik opsüsteem, seega ei garanteeri keegi, et kõik komponendid ja draiverid Linuxis hästi töötavad. Arvan, et osa probleemidest oli seotud selle platvormi USB-draiveritega, mistõttu modemid ei töötanud sel plaadil ootuspäraselt. Samuti on dokumentatsioon väga kehv ja killustatud, seega iga operatsiooni jaoks kulus palju aega dokumentides kaevamisele. Isegi tavaline töö GPIO-ga nõudis palju vaeva. Näiteks, et LED-i tööks seadistada, kulus mul mitu tundi. Kuid olema objektiivne, ei olnud põhimõtteliselt oluline, milline üheplaadi arvuti see on, peamine, et see töötaks ja et oleks USB-pordid.
Esiteks pean ma sellel plaadil Linuxi installima. Et mitte ekselda dokumentatsiooni labürindis, kirjutan selle peatüki ka neile, kes selle üheplaadi arvutiga tegelema hakkavad.
On kaks võimalust Linuxi installimiseks: kas välisele SD-kaardile või sise MMC-le. Kaardiga ma nokitsesin õhtujagu, kuid ei suutnud välja selgitada, kuidas see tööle saada, seega otsustasin installida MMC-le, kuigi ka väline kaart oleks olnud kindlasti lihtsam.
Firmware'ist . Tõlgin kummalisest venekeelsest eesti keelde. Et plaati flashingida, pean ma ühendama riistvara UART-i. Ühendasin selle
- Tööriista Pin GND: Pin17 VIMi GPIO-st
- Tööriista Pin TXD: Pin18 VIMi GPIO-st (Linux_Rx)
- Tööriista Pin RXD: Pin19 VIMi GPIO-st (Linux_Tx)
- Tööriista Pin VCC: Pin20 VIMi GPIO-st

Pärast seda laadisin alla firmware'i . Konkreetne firmware'i versioon .
Et seda firmware'i üles laadida, on mul vajalikud utiliidid. Selle kohta on rohkem üksikasju . Windowsi all ei ole ma proovinud flashingida, aga Linuxi alla flashingist tasub paar sõna rääkida. Esiteks installin ma utiliidid vastavalt juhistele.
git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALLJa… Ei midagi ei tööta. Kulutasin paar tundi installatsiooniskeemide parandamisele, et kõik õigesti installida. Mis seal tegin, ei mäleta, aga see oli ka omaette tsirkus. Seega olge ettevaatlikud. Ilma nende utiliidita pole VIM2-ga edasine vaev mõistlik. Parema meelega ära sue sellega üldse!
Pärast seitsme ringi läbi põrgu, skriptide seadistamist ja installimist sain töötava utiliitide paketi. Ühendasin plaadi USB kaudu oma Linuxi arvutiga ja UART on samuti ühendatud eelnevalt kirjeldatud skeemiga.
Seadistan oma lemmikterminaali minicom kiirusel 115200, ilma riist- ja tarkvarakontrollita. Alustame.

VIM2 laadimise ajal UART terminalis vajutan mis tahes nupule, näiteks tühikule, et laadimise peatada. Pärast seda, kui rida ilmub
kvim2# Sisestan käsu:
kvim2# run updateKodus, kust laadime, täidan:
burn-tool -v aml -b VIM2 -i VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.imgKõik, puh, flashitud, plaadil on Linux. Logi sisse/käepide khadas:khadas.
Pärast seda on mõned algsed seadistused. Edasi töötamiseks lülitan sudo parooli välja (jah, see ei ole turvaline, aga mugav).
sudo visudoKäin redigeerimas rida selliseks ja salvestan
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALLPärast seda muudan praegust lokaali, et kell oleks Moskva ajavööndis, vastasel juhul on see Greenwichi ajavööndis.
sudo timedatectl set-timezone Europe/Moscowvõi
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtimeKui see tundub keeruline, siis ärge kasutage seda plaati, parem on Raspberry Pi. Ausalt.
Mudel Huawei e3372h - 153
See modem on mulle tõeliselt peavalu valmistanud ja tegelikult on ta saanud terve projekti kõige kitsamaks kohaks. Tegelikult ei peegelda sellise seadme nimetus „modem” tõepoolest töö olemust: see on jõhker kombain, see seade sisaldab komponente, mis käituvad CD-ROMina draiverite paigaldamiseks ja seejärel lülitub võrkaartide režiimi.
Arhitektuuriliselt, Linuxi kasutaja seisukohalt, näeb see pärast kõiki seadistusi välja nii: modemiga ühendamisel ilmub mulle võrgu liides eth*, mis saab DHCP kaudu IP-aadressi 192.168.8.100 ja vaikimisi värava 192.168.8.1.
Ja kõige olulisem punkt! See mudel modem ei oska töötada modemirežiimis, mida juhitakse AT-käskudega.Kõik oleks palju lihtsam, luua iga modemiga ppp-ühendus ja siis nendega töötada. Kuid minu puhul loob „ise” (täpsemalt Linuxi draiverid vastavalt udev reeglitele) eth-liidese ja määrab sellele DHCP kaudu IP-aadressi.
Kuna edaspidi segadust vältida, pakun unustada sõna „modem” ja rääkida võrkaartidest ja väravatest, sest tegelikult on see nagu uue võrkaartide ja värava ühendamine.
Kui on üks modem, siis ei põhjusta see erilisi probleeme, kuid kui neid on rohkem kui üks, nimelt n-tükki, siis tekib järgmine võrgu pilt.

See, n network cards, all with one IP address, and each has the same default gateway. But in reality, each of them is connected to its own operator.
Initially, I had a simple solution: using the ifconfig or ip command to disable all interfaces and just enable one at a time to test it. The solution worked well for everyone, except that during the switching moments, I had no way to connect to the device. And since the switches were frequent and fast, I essentially had no way to connect at all.
Therefore, I chose to manually change the IP addresses of the modems and then route the traffic using routing settings.

My modem problems did not end there: in case of power issues, they would disconnect, requiring a stable USB hub power supply. I resolved this issue by hard soldering the power directly to the hub. Another problem I encountered, which ruined the entire project: after a reboot or cold start, not all modems were recognized, and not always. I couldn't determine why this happened or establish any algorithm for it. But let’s take this step by step.
To ensure proper modem operation, I installed the usb-modeswitch package.
sudo apt update
sudo apt install -y usb-modeswitch After that, the modem will be correctly recognized and configured by the udev subsystem upon connection. I check this by simply connecting the modem and ensuring the network appears.
Another problem I couldn't solve: how to get the name of the operator we're working with from this modem? The operator's name is contained in the modem's web interface at the address 192.168.8.1. This is a dynamic web page that retrieves data using ajax requests, so simply using wget to download the page and parse the name won't work. So I started looking into how to work with the web page, and I realized I was doing something pointless. In the end, I gave up and started obtaining the operator's name using the Speedtest API.
Much would be easier if the modem had access via AT commands. I could reconfigure it, create a ppp connection, assign IPs, obtain the operator’s information, etc. But unfortunately, I have to work with what I was given.
GPS
GPS-vastuvõtja, mille sain, oli UART-liidestusega ja toiteallikaga. See polnud parim lahendus, kuid siiski toimiv ja lihtne. Vastuvõtja nägi välja umbes selline.

Tõeliselt, ma töötasin esmakordselt GPS-vastuvõtjaga, kuid just nagu oletasin, on kõik juba ammu meie jaoks välja mõeldud. Seega kasutame lihtsalt olemasolevaid lahendusi.
Esialgu lülitan sisse uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) GPS-i ühendamiseks.
khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okaySeejärel kontrollin operatsiooni edukust.
khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okaySee käsk näib olevat midagi, mis redigeerib devtree-d reaalajas, mis on üsna mugav.
Pärast selle operatsiooni edukust taaskäivitame ja installime gps-deemoni.
khadas@Khadas:~$ sudo rebootgps-deemoni installimine. Installin kõik ja katkestan selle kohe edasise konfigureerimise jaoks.
sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
/* GPS daemon stop/disable */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socketRedigeerin seadistuste faili.
sudo vim /etc/default/gpsdSeadistan UART-i, millele GPS on ühendatud.
DEVICES="/dev/ttyS4"Ja siis lülitame kõik sisse ja käivitame.
/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socketSeejärel ühendangi GPS-i.

Käes on GPS-kaabel, sõrmede all on nähtavad UART-debuggeri juhtmed.
Taaskäivitun ja kontrollin GPS-i tööd gpsmon-programmi abil.

Sellel ekraanipildil pole satelliite, kuid on nähtav side GPS-vastuvõtjaga, mis tähendab, et kõik on korras.
Olen proovinud pythonis palju variatsioone selle deemoni töö jaoks, kuid peatusin sellel, mis töötas õigesti python 3-ga.
Installin vajaliku teegi.
sudo -H pip3 install gps3 Ja kirjutan töö koodi.
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 vastuvõtja rike!!!")
return "NA", "NA"
time.sleep(1.0)
...
f __name__ == '__main__':
...
#gps
agps_thread = AGPS3mechanism() # Instantiiri AGPS3 mehhanismid
agps_thread.stream_data() # Kohalikust hostist (), või muudelt hostidelt, näiteks (host='gps.ddns.net')
agps_thread.run_thread() # Aeglustus pärast tühja otsingut, vaikimisi '()' 0.2 kaks kümnendikku sekundit
Kui mul on vaja koordinaate saada, siis teen seda järgmise kutsumisega:
longitude, latitude = getPositionData(agps_thread)
Ja kestab 1-10 sekundit, et kas ma saan koordinaadi või mitte. Jah, mul oli kümme katset koordinaatide saamiseks. See pole optimaalne, natuke kohmakas, aga töötab. Otsustasin nii teha, sest GPS võib halvasti töötada ja mitte alati andmeid saada. Kui oodata andmete saamist, siis suletud ruumis programm seiskub. Seetõttu rakendasin sellise mitteüllatava variandi.
Põhimõtteliselt, kui oleks olnud rohkem aega, oleks saanud otse UARTi kaudu GPS-andmeid saada, neid eraldi protsessis parsida ja nendega töötada. Kuid aega ei olnud absoluutselt, seetõttu see kohmakas kood. Ja jah, mul pole selle pärast piinlik.
LED
LED-iga ühendamine oli samas lihtne ja keeruline. Peamine keerukus on see, et süsteemi pinenumber ei vasta plaadi pinenumbrile ja dokumentatsioon on kirjutatud vasaku jalaga. Et seostada riistvara pinenumber ja pinenumber OS-is, tuleb täita käsk:
gpio readallTuleb välja tabel, mis seob pinenumbri süsteemis ja plaadil. Pärast seda saan juba operatiivset pinenumbrit OS-is kasutada. Minu juhul on LED ühendatud GPIOH_5.

Panen GPIO pinni väljundrežiimi.
gpio -g mode 421 outKirjutan nulli.
gpio -g write 421 0Kirjutan üht.
gpio -g write 421 1 
Kõik süttib, pärast «1» kirjutamist
#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üüd, juhul kui esinevad vead, kutsun esile error_blink() ja LED vilgub kenasti.
Programmi moodulid
Speedtest API
Suur rõõm, et speedtest.net teenusel on oma python-API, seda saab vaadata siin .
Mis on hea, on see, et olemas on ka lähtekoodid, mida saab vaadata. Kuidas selle API-ga töötada (lihtsad näited) saab vaadata .
Installin python-kogumi järgmise käsklusega.
sudo -H pip3 install speedtest-cliNäiteks võite Ubuntu-sse installida spidtesteri otse repost. See on sama python-rakendus, mida saab juhtida otse konsolist.
sudo apt install speedtest-cli -yJa mõõta oma interneti kiirus.
speedtest-cli
Laadin speedtest.net konfiguratsiooni...
Testimine aadressilt B***** (*.*.*.*)...
Laadin speedtest.net serverite loendit...
Valin parima serveri vastavalt pingile...
Pakub MTS (Moskvas) [0.12 km]: 11.8 ms
Laadia kiirus................................................................................
Allalaadimise kiirus: 7.10 Mbit/s
Üleslaadimise kiirus......................................................................................................
Üleslaadimise kiirus: 3.86 Mbit/s
Tulemusena, nagu mina seda tegin. Mul tuli tuua sisse spidtesti lähtekoodid, et neid oma projekti paremini integreerida. Üks tähtsamaid ülesandeid on saada ka sideoperaatori nimi, et see tabelisse sisestada.
import speedtest
from datetime import datetime
...
#Määrame kindla serveri testi jaoks
#6053) MaximaTelecom (Moskva, Venemaa)
servers = ["6053"]
# Kui soovite kasutada ühte lõime testimist
threads = None
s = speedtest.Speedtest()
#saame mobiilioperaatori nime
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
#saame serveri parameetrite tekstirea
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
#laadimistesti
s.download(threads=threads)
#üleslaadimistesti
s.upload(threads=threads)
#saame tulemused
s.results.share()
#Pärast seda moodustatakse rida CSV-faili kirjutamiseks.
#saame GPS positsiooni
longitude, latitude = getPositionData(agps_thread)
#aeg ja kuupäev
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"
#siin toimub logifaili kirjutamine
Siin osutus ka asi mitte nii lihtsaks, kuigi tundus, et see võiks olla lihtne. Alguses oli parameeter servers mul määratud [], et vali parim server. Tulemuseks olid juhuslikud serverid ja nagu võib arvata, kõikuv kiirus. See on piisavalt keeruline teema, kasutada fikseeritud serverit, kui jah, siis staatiline või dünaamiline, vajab uurimist. Kuid siin on näide Beeline'i operaatori kiirusmõõtmise graafikutest dünaamilise testserveri valiku ja staatiliselt fikseeritud serveri korral.

Dünaamilise serveri valikul kiirusmõõtmise tulemus.

Kiiruskatse tulemus, kui on valitud üks kindel server.
Testimise käigus on nii seal kui ka seal "vill" olemas, ja see tuleb matemaatiliste meetoditega eemaldada. Kuid fikseeritud serveri korral on seda veidi vähem ja amplituud stabiilsem.
Tegelikult on see suurte uuringute koht. Ja ma teeksin kiirusmõõtmisi oma serverisse, kasutades iperf utiliiti. Kuid me jääme projektikonspekti juurde.
Kiri ja vead
Kiri saatmiseks proovisin mitmeid kümneid erinevaid variante, kuid tulemuseks jõudsin järgmise variandini. Registreerisin postkasti yandexis ja seejärel võtsin . Kontrollisin seda ja rakendasin programmi. Selles näites käsitletakse erinevaid variante, sealhulgas saatmist gmailist jne. Omandada oma postiserveri üles ehitamine ei olnud mul huvi ja aega, kuid nagu hiljem selgus, oli see ka mõttetu.
Logide saatide alusel saatis, kui ühendus on olemas,, iga 6 tunni järel: kell 00, 06, 12 ja 18. Saatsin järgmiselt.
from send_email import *
...
message_log = "Testimise logid 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, "Logid " + curdata + " " + curtime, files)
except:
print("Võrguprobleem e-kirjade saatmisel")
return False
return True
Vead saadeti alguseski. Algul koguti need nimekirja ja seejärel saatsin samuti ajakava alusel, kui ühendus oli olemas. Kuid hiljem tekkis probleeme, kuna Yandexil on piirang päevasele saatmise arvule (see on valu, kurbus ja häbistamine). Kuna vigu võis olla isegi minutis tohutult, tuli loobuda vigade saatmisest e-posti teel. Seega pidage meeles, et automaatse saatmise kohta Yandexi teenuste kaudu on selline probleem.
Tagasiside server
Kaugarvuti ligipääsu ja tõhustamise võimaluse saavutamiseks vajan ma välist serverit. Ausalt öeldes, oleks õigesti olnud, et kõik andmed saadetakse serverisse ja veebiliideses genereeritakse kõik kaunid graafikud. Kuid mitte kõike korraga.
VPS-na valisin . Oleks olnud võimalik võtta kõige lihtsam server. Ja kokkuvõttes oleks see minu eesmärkide jaoks piisav. Kuid kuna ei maksnud serveri eest oma rahakotist, otsustasin võtta mõne varuga, et see piisaks, kui hakkame välja töötama web-liidest, oma SMTP-serverit, VPN-i jne. Pluss on võimalus seadistada Telegram-bot ja mitte kogeda selle blokeerimise probleeme. Seetõttu valisin Amsterdam ja järgmised parameetrid.

Seadmega vim2 suhtlemise viisiks valisin tagas ssh-ühenduse ja nagu praktika näitas — ei olnud see parim. Ühenduse katkemisel hoiab server porti ja selle kaudu ei saa mõnda aega ühendust võtta. Seega on siiski parem kasutada teisi sideviise, näiteks VPN-i. Tulevikus tahtsin minna VPN-i peale, kuid ei jõudnud.
Ma ei hakka tutvustama tulemüüri seadistamise, õiguste piiramisest, root ssh-ühenduse keelamisest ja muust VPS seadistamistest. Loodan, et teate seda kõike juba. Kaugühenduse loomiseks loon ma serveris uue kasutaja.
adduser vimsshMeie seadmel genereerin ssh-ühenduse võtmed.
ssh-keygenJa kopeerin need meie serverisse.
ssh-copy-id vimssh@host.comMeie seadmel loon automaatse tagasipesa ssh-ühenduse igal käivitamisel.
[Unit]
Kirjeldus=Auto Reverse SSH
Nõuab=systemd-networkd-wait-online.service
Pärast=systemd-networkd-wait-online.service
[Service]
Kasutaja=khadas
ExecStart=\/usr\/bin\/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 vimssh@host.com
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target
Pöörake tähelepanu pordile 8083: see määrab, millisel pordil toimub tagasipesa ssh-ühendus. Lisame auto käivitamise loetellu ja käivitame.
sudo systemctl enable autossh.service
sudo systemctl start autossh.serviceVõite isegi vaadata olekut:
sudo systemctl status autossh.serviceNüüd, meie VPS-serveris, kui täita:
ssh -p 8083 khadas@localhostSiis jõuan oma testseadmest. Ja seadmest saan samuti saata logisid ja muid andmeid ssh kaudu oma serverisse, mis on väga mugav.
Kogume kõik ühte

Käivitamine, asume arendama ja siluma
Phew, tundub, et olen kõik sõlmed kirjeldanud. Nüüd on aeg kõik see ühte kuhja koguda. Koodi saab vaadata .
Oluline punkt koodi osas: see projekt ei pruugi niimoodi 'nagu on' töötada, kuna see on kohandatud teatud ülesande, kindla arhitektuuri jaoks. Kuigi annan allikaid, on kõike väärtuslikku selgitan siin, tekstis, vastasel juhul jääb see täiesti arusaamatuks.
Alustan GPS-i, GPIO ja eraldi ajakava sündmuse käivitamise algatamisega.
#запуск потока планировщика
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()Ajakava on piisavalt lihtne: ta vaatab, kas on kätte jõudnud sõnumite saatmise aeg ja milline on praegune vigade staatus. Kui on vea lipp, siis vilgub LED.
#sheduler
def ShedulerThread(name):
global ready_to_send
while True:
d = datetime.today()
time_x = d.strftime('%H:%M')
if time_x in time_send_csv:
ready_to_send = True
if error_status:
error_blink()
else:
good_blink()
time.sleep(1)Selle projekti kõige keerulisem moment on tagasipesa ssh-ühenduse säilitamine iga testi käigus. Igas testis toimub vaikimisi värava ja dns-serveri seadistamine uuesti. Kuna keegi ei loe nagunii, siis teadke, et rong ei sõida puidust rööbasteel. Kes leiab munakese, sellele maius.
Selleks loon eraldi marsruuditabeli —set-mark 0x2 ja reegli liikluse suunamiseks.
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")Rohkem teavet selle toimimise kohta leiate .
See jääb lõputu tsüklisse, kus iga kord saame ühendatud modemite nimekirja (et teada saada, kas võrgu konfiguratsioon on muutunud).
network_list = getNetworklist()Võrguliideste nimekirja saamine on piisavalt lihtne.
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_listPärast nimekirja saamist määran kõikidele liidestele IP-aadresse, nagu ma näitasin pildil modemite peatükis.
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")Seejärel liigun lihtsalt tsüklis läbi iga liidese. Ja konfigureerin iga liidese.
for iface in network_list:
ConfigNetwork(iface)def ConfigNetwork(iface):
#likvideerime kõik seadistused
cmd_run("sudo ip route flush all")
#Määrame vaikegateway
cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#määra dns-server (see on vajalik speed testi toimimiseks)
cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")Kontrollin liidest töökorras, kui võrku pole, siis genereerin vead. Kui võrk on olemas, siis on aeg tegutseda!
Siin seadistan ssh marsruutimise antud liidesele (kui see pole juba tehtud), saadan vead serverisse, kui aeg on käes, saadan logid ja lõpuks teen speed testi ning salvestan logid csv-faili.
if not NetworkAvalible():
....
#Siin genereerime vead
....
else: #Võrk on olemas, hurraa, töötame!
#Kui meil on probleemne liides, millel on ssh, siis muudame selle
if (sshint == lastbanint or sshint == "free"):
print("********** Set up SSH ********************")
if sshint != "free":
cmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint + " table 102")
SetupReverseSSH(iface)
sshint = iface
#kuna võrk töötab, siis kiirelt saadame kõik!!!
if ready_to_send:
print("**** Valmis saatmiseks!!!")
if sendLogs():
ready_to_send = False
if error_status:
SendErrors()
#ja seejärel testime kiirus ja salvestame logid. Ainult tasub mainida tagurpidi ssh seadistamise funktsiooni.
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")Ja loomulikult tuleb kogu see ilu lisada autolaadimisele. Selleks loon faili:
sudo vim /etc/systemd/system/modems_speedtest.serviceJa kirjutan sellesse:
[Unit]
Kirjeldus=Modemi kiiruskatse
Nõuab=systemd-networkd-wait-online.service
Pärast=systemd-networkd-wait-online.service
[Service]
Kasutaja=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target
Ajan autolaadimise käima ja alustamiseks!
sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.serviceNüüd saan vaadata logisid, mis juhtub, kasutades käsku:
journalctl -u modems_speedtest.service --no-pager -ftulemused näitasid ainult nelja ebaolulise koodibloki kattuvust, mis olid tingitud POSIX ja ANSI C nõuetest.
Nüüd on kõige tähtsam, mida tulemusena saavutati? Toome välja mõned graafikud, mida mul õnnestus arendus- ja testeetimisprotsessis jäädvustada. Graafikud koostati gnuplot'i abil järgmise skripti järgi.
#! /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"
Esimene katse oli Tele2 operaatori puhul, mida tegin mitme päeva jooksul.

Siin kasutasin dünaamilist mõõteserverit. Kiirusetappide mõõtmised toimivad, kuigi nad kõiguvad üsna palju, kuid siiski on näha mingit keskmist väärtust, mille saab välja filtreerida, näiteks liigenduskeskmisega.
Hiljem koostasin veel mitmeid graafikuid teiste sideoperaatorite jaoks. Testimisserver oli sel puhul juba üks ja tulemused olid samuti väga huvitavad.




Kuidas näha, on teema teadusuuringuteks ja nende andmete töötlemiseks väga ulatuslik ning ilmselgelt ei piisa paarist nädalast tööst. Kuid...
Töö tulemus
Töö lõpetati järsult minu tahtest olenematutel asjaoludel. Üks selle projekti subjektiivne nõrk koht oli modem, mis ei soovinud eriti hästi koos teiste modemitega töötada ja iga käivitamise ajal tegi selliseid trikke. Nende eesmärkide jaoks on olemas tohutul hulgal teisi modemimudeleid, mis tavaliselt juba omavad Mini PCI-e formaati ja paigaldatakse seadme sisse, ning need on palju lihtsamini konfigureeritavad. Kuid see on juba hoopis teine lugu. Projekt oli huvitav ja mul oli väga hea meel, et sain selles osaleda.
Allikas: habr.com

