Under quarantine, I was invited to participate in the development of a device for measuring the speed of LTE modems for several mobile operators.
The client wanted to assess the speed of various telecommunications operators in different geographical locations to understand which mobile operator would be most optimal for installing equipment that uses LTE connections, such as for video streaming. The task needed to be solved as simply and cheaply as possible, without expensive equipment.
I will say right away that this task is not the simplest and requires scientific knowledge; I will share the problems I encountered and how I solved them. So, let's go.
AnmÀrkning
Measuring LTE connection speed is quite complex: it is necessary to choose the right equipment and measurement methodology, and also to have a good understanding of the topology and operation of the mobile network. Additionally, several factors can affect speed: the number of subscribers on the cell, weather conditions, and even from cell to cell, the speed can vary drastically due to network topology. In general, this task comes with a huge number of unknowns, and only a mobile operator can solve it correctly.
Initially, the client just wanted to have a courier run with phones from different operators, conducting measurements directly on the phones and then writing the speed measurement results in a notebook. My solution for measuring LTE network speeds, while not perfect, meets the task at hand.
Due to a lack of time, I made decisions not in favor of convenience or practicality, but in favor of the speed of development. For example, for remote access, I set up reverse SSH instead of a more practical VPN, to save time on server and client setup.
Teknisk specifikation
As stated in the article : Do not work without a technical specification! Never, anywhere!
The technical specification was quite simple; I will expand on it a bit for the end user to understand. The choice of technical solutions and equipment was dictated by the client. So, the specification itself, after all agreements:
Based on a single-board computer vim2 to create an LTE connection speed tester through Huawei e3372h â 153 flera operatörer (frĂ„n en till n). Det Ă€r ocksĂ„ nödvĂ€ndigt att fĂ„ koordinater frĂ„n GPS-mottagaren, ansluten via UART. HastighetsmĂ€tningar ska utföras med hjĂ€lp av tjĂ€nsten och sammanstĂ€lla dem i en tabell av typ:
Tabell i csv-format. DÀrefter ska denna tabell skickas via e-post var sjÀtte timme. Vid fel ska en LED-lampa, som Àr kopplad till GPIO, blinka.
Tekniska specifikationer har jag beskrivit i friform, efter mÄnga godkÀnnanden. Men syftet med uppgiften Àr redan tydligt. Tiden för allt detta var en vecka. Men i verkligheten strÀckte den sig över tre veckor. Detta med beaktande av att jag gjorde det endast efter mitt ordinarie jobb och pÄ helger.
HÀr vill jag Äterigen pÄpeka att uppdragsgivaren i förvÀg hade avtalat om anvÀndning av hastighetsmÀtningstjÀnsten och hÄrdvaran, vilket kraftigt begrÀnsade mina möjligheter. Budgeten var ocksÄ begrÀnsad, sÄ det köptes knappt nÄgot ytterligare. SÄ jag var tvungen att spela med de angivna reglerna.
Arkitektur och utveckling
Schemat Àr enkelt och uppenbart. DÀrför lÀmnar jag det utan kommentarer.

Jag beslutade att genomföra hela projektet i Python, trots att jag inte hade nÄgon erfarenhet av att utveckla i detta sprÄk. Jag valde det eftersom det fanns mÄnga fÀrdiga exempel och lösningar som kunde snabba upp utvecklingen. DÀrför ber jag alla professionella programmerare att inte kritisera min första erfarenhet av att utveckla i Python, och jag Àr alltid villig att höra konstruktiv kritik för att förbÀttra mina fÀrdigheter.
Jag upptÀckte ocksÄ att Python har tvÄ populÀra versioner, 2 och 3, sÄ jag fastnade för den tredje.
HÄrdvarunoder
Enkortsdator vim2
Som huvudmaskin fick jag en enkortsdator

Ett utmÀrkt, kraftfullt mediacombo för smarta hem och SMART-TV, men sÀllsynt olÀmpligt för denna uppgift, eller lÄt oss sÀga, svagt lÀmpligt. Till exempel, dess huvud-OS Àr Android, medan Linux Àr ett biprodukt-OS, och dÀrför kan ingen garantera att alla komponenter och drivrutiner fungerar bra under Linux. Jag misstÀnker att en del av problemen var relaterade till USB-drivrutinerna för denna plattform, sÄ modem fungerade inte som jag förvÀntat mig. Det finns ocksÄ vÀldigt dÄlig och spridd dokumentation, sÄ varje operation tog mycket tid pÄ att grÀva i dokumentationen. Till och med en vanlig uppgift med GPIO tog mycket tid. Till exempel, för att konfigurera en LED-lampa tog det mig flera timmar. Men för att vara objektiv, sÄ var det principiellt sett inte viktigt vilken enskild kortdator det var, sÄ lÀnge den fungerade och hade USB-portar.
Först mÄste jag installera Linux pÄ denna platta. För att inte behöva leta runt i dokumentationen, och ocksÄ för de som ska arbeta med denna enskilda kortdator, skriver jag detta kapitel.
Det finns tvÄ alternativ för att installera Linux: pÄ ett externt SD-kort eller pÄ intern MMC. Jag kÀmpade med kortet en kvÀll och fick det inte att fungera, sÄ jag bestÀmde mig för att installera pÄ MMC, Àven om det utan tvekan skulle vara mycket enklare att arbeta med ett externt kort.
Om flashning . Jag översÀtter frÄn ett konstigt sprÄk till ryska. För att kunna blinka plattan mÄste jag ansluta en hÄrdvaru-UART. Jag anslöt den
- Tool Pin GND: Pin17 av VIM:s GPIO
- Tool Pin TXD: Pin18 av VIM:s GPIO (Linux_Rx)
- Tool Pin RXD: Pin19 av VIM:s GPIO (Linux_Tx)
- Tool Pin VCC: Pin20 av VIM:s GPIO

Efter det laddade jag ner firmware . Den specifika versionen av firmware .
För att ladda denna firmware behöver jag vissa verktyg. Mer information om detta beskrivs . Jag har inte försökt att blinka under Windows, men det behöver sÀgas ett par ord om flashning under Linux. Först installerar jag verktygen enligt instruktionerna.
git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALLOch⊠inget fungerar. Jag lade ner ett par timmar pÄ att redigera installationsskripten för att allt skulle installeras korrekt för mig. Vad jag gjorde minns jag inte, men det var ocksÄ ett rikt circus. SÄ var försiktig. Men utan dessa verktyg finns det ingen mening att fortsÀtta med vim2. BÀttre att överhuvudtaget inte knyta an till den!
Efter sju helveten, konfigurationer av skript och installation fick jag paketet med fungerande verktyg. Jag kopplade brÀdan via USB till min Linux-dator, och UART kopplades ocksÄ enligt skissen ovan.
Jag konfigurerar min favoritterminal minicom till 115200 hastighet, utan hÄrdvaru- och programvaruövervakning av fel. Och vi sÀtter igÄng.

Vid uppstart av VIM2 i UART-terminalen trycker jag pÄ nÄgon tangent, till exempel mellanslag, för att stoppa uppstarten. NÀr raden visas
kvim2# Skriver in kommandot:
kvim2# run updatePÄ vÀrden dÀr vi laddar ner, utför jag:
burn-tool -v aml -b VIM2 -i VIM2_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.imgDet Àr klart, puh. Jag har flasht, brÀdan har Linux. Inloggning/lösenord khadas:khadas.
DÀrefter gör jag nÄgra smÄ grundinstÀllningar. För vidare arbete inaktiverar jag lösenordet för sudo (ja, inte sÀkert, men praktiskt).
sudo visudoRedigerar raden sÄ att den ser ut sÄ hÀr och sparar.
# Allow members of group sudo to execute any command
%sudo ALL=(ALL:ALL) NOPASSWD: ALLEfter det Àndrar jag nuvarande lokal sÄ att tiden Àr enligt Moskva, annars blir det enligt Greenwich.
sudo timedatectl set-timezone Europe/Moscoweller
ln -s /usr/share/zoneinfo/Europe/Moscow /etc/localtimeOm du tyckte att det verkade komplicerat, anvĂ€nd dĂ„ inte denna brĂ€da, bĂ€ttre Raspberry Pi. Ărligt.
Modem Huawei e3372h â 153
Detta modem har verkligen gett mig en del problem, och det blev till slut den svagaste lÀnken i hela projektet. Egentligen, namnet "modem" för dessa enheter speglar inte alls deras funktion: det Àr en kraftfull kombination, den har en komponent som lÄtsas vara en CD-ROM för att installera drivrutiner, och sedan gÄr den över i lÀge som nÀtverkskort.
Arkitektoniskt, sett ur en Linux-anvÀndares perspektiv efter alla instÀllningar, ser det ut sÄ hÀr: efter att ha anslutit modemet, fÄr jag ett nÀtverksgrÀnssnitt eth*, som via DHCP fÄr IP-adressen 192.168.8.100, och standardgateway 192.168.8.1.
Och den viktigaste punkten! Denna modemmodell kan inte fungera i lÀge som modem, som styrs av AT-kommandon.. Allt skulle varit mycket enklare, om man skapade PPP-anslutningar för varje modem och sedan opererade med dem. Men i mitt fall skapar "den" (nÀrmare bestÀmt Linux-drivrutiner enligt reglerna för udev) ett eth-grÀnssnitt och tilldelar det en IP-adress via DHCP.
För att inte förvirra lÀngre, föreslÄr jag att vi glömmer ordet "modem" och istÀllet pratar om nÀtverkskort och gateway, eftersom det i grunden Àr som att ansluta ett nytt nÀtverkskort med en gateway.
NÀr det Àr ett modem, orsakar det inga sÀrskilda problem, men nÀr det finns mer Àn ett, nÀmligen n stycken, dÄ uppstÄr följande nÀtverksbild.

Det vill sÀga n nÀtverkskort, alla med samma IP-adress och samma standardgateway. Men i verkligheten Àr varje kort kopplat till sin egen operatör.
Initialt hade jag en enkel lösning: genom att anvÀnda kommandot ifconfig eller ip stÀnga av alla grÀnssnitt och sedan slÄ pÄ dem ett i taget för att testa dem. Lösningen fungerade bra, förutom att jag under bytena inte hade möjlighet att koppla upp mig mot enheten. Eftersom bytena var frekventa och snabba, hade jag faktiskt ingen möjlighet att koppla upp mig överhuvudtaget.
DÀrför valde jag att manuellt Àndra IP-adresserna pÄ modemen och sedan styra trafiken genom routingen.

Mina problem med modemen slutade inte hÀr: vid strömbortfall kopplade de ifrÄn, sÄ jag behövde en stabil USB-hubb. Jag löste detta genom att löda strömmen direkt till hubben. Ett annat problem jag stötte pÄ, som satte stopp för hela projektet, var att efter omstart eller kallstart kÀnde enheten inte alltid igen alla modem, och jag kunde inte faststÀlla varför eller enligt vilket algoritm det intrÀffade. Men lÄt oss ta det steg för steg.
För att modemet skulle fungera korrekt installerade jag paketet usb-modeswitch.
sudo apt update
sudo apt install -y usb-modeswitch Efter detta kommer modemet att kÀnnas igen korrekt och konfigureras av udev-systemet vid anslutning. Jag kontrollerar genom att helt enkelt koppla in modemet och försÀkra mig om att nÀtverket har dykt upp.
Ett annat problem jag inte kunde lösa var hur man fÄr namnet pÄ operatören som vi arbetar med frÄn detta modem? Operatörens namn finns i modemens webgrÀnssnitt pÄ adressen 192.168.8.1. Detta Àr en dynamisk webbsida som fÄr data via ajax-förfrÄgningar, sÄ det Àr inte möjligt att bara wget:a sidan och parsa namnet. DÀrför började jag leta efter sÀtt att hantera webbsidan och liknande, och insÄg att jag pysslar med en massa strunt. Resultatet blev att jag gav upp och började hÀmta operatörens namn via Speedtests API.
Mycket skulle vara enklare om modemet hade tillgÄng via AT-kommandon. Man skulle kunna omkonfigurera det, skapa ppp-anslutningar, tilldela IP, fÄ operatörens namn osv. Men tyvÀrr fÄr jag arbeta med det jag har.
GPS
GPS-mottagaren som jag fick hade en UART-grÀnssnitt och strömförsörjning. Det var inte den bÀsta lösningen, men det var funktionellt och enkelt. Mottagaren sÄg ungefÀr ut sÄ hÀr.

Ărligt talat, det var första gĂ„ngen jag arbetade med en GPS-mottagare, men som jag misstĂ€nkte har andra redan tĂ€nkt pĂ„ allting. SĂ„ vi anvĂ€nder bara fĂ€rdiga lösningar.
Först aktiverar jag uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) för att ansluta GPS.
khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okayDĂ€refter kontrollerar jag om operationen lyckades.
khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okayDenna kommando verkar redigera devtree i realtid, vilket Àr mycket praktiskt.
Efter att denna operation lyckats, startar vi om och installerar gps-daemonen.
khadas@Khadas:~$ sudo rebootInstallation av gps-daemonen. Jag installerar allt och stÀnger av den direkt för ytterligare konfiguration.
sudo apt install gpsd gpsd-clients -y
sudo killall gpsd
/* GPS-daemon stoppa/inaktivera */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socketJag redigerar konfigurationsfilen.
sudo vim /etc/default/gpsdJag stÀller in UART som GPS-enheten kommer att ansluta till.
DEVICES="/dev/ttyS4"Och sedan aktiverar vi allt och startar det.
/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socketSedan ansluter jag GPS.

I hÀnderna har jag GPS-kabeln och jag kÀnner UART-debuggerns kablar under fingrarna.
Jag startar om och testar GPS:en med programmet gpsmon.

I den hÀr skÀrmbilden syns inga satelliter, men man kan se kommunikationen med GPS-mottagaren, vilket betyder att allt Àr i sin ordning.
Jag har testat mÄnga alternativ pÄ python för att arbeta med denna daemon, men jag fastnade för den som fungerade korrekt med python 3.
Jag installerar den nödvÀndiga biblioteken.
sudo -H pip3 install gps3 Och jag skriver koden för att arbeta.
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 ("VÀntar gps rÀknare = %d" % counter)
if counter == 10:
ErrorMessage("Fel GPS-mottagare!!!")
return "NA", "NA"
time.sleep(1.0)
...
f __name__ == '__main__':
... #gps
agps_thread = AGPS3mechanism() # Instansiera AGPS3-mekanismer
agps_thread.stream_data() # FrÄn localhost (), eller andra vÀrdar, till exempel, (host='gps.ddns.net')
agps_thread.run_thread() # TidsbegrÀnsning för att somna efter en tom sökning, standard '()' 0.2 tvÄ tiondelar av en sekund
Om jag behöver hÀmta koordinater, görs det med följande anrop:
longitude, latitude = getPositionData(agps_thread)
Och inom 1-10 sekunder kommer jag antingen att fÄ koordinaten eller inte. Ja, jag har gjort tio försök att fÄ koordinater. Inte optimalt, klumpigt och krÄngligt, men det fungerar. Jag beslutade att göra sÄ hÀr eftersom GPS kan ha dÄlig mottagning och ibland inte fÄ data. Om man vÀntar pÄ att fÄ data kan programmet hÀnga sig i tysta miljöer. DÀrför implementerade jag denna mindre eleganta lösning.
I princip, om jag hade haft mer tid, skulle jag kunna ta emot data frÄn GPS via UART direkt, parsa dem i en separat trÄd och arbeta med dem. Men jag hade ingen tid alls, dÀrav den helt fula koden. Och ja, jag skÀms inte.
LED
Anslutningen av LED-lampan var bÄde enkel och svÄr pÄ samma gÄng. Den största svÄrigheten Àr att pin-nummer i systemet inte motsvarar pin-nummer pÄ kortet och att dokumentationen Àr skriven med venstre fot. För att matcha hÄrdvarupinnens nummer och systemets pinnummer mÄste jag köra kommandot:
gpio readallDet kommer att visas en tabell som motsvarar pinnen i systemet och pÄ kortet. Efter det kan jag arbeta med pinnen i sjÀlva OS:et. I mitt fall Àr LED-lampan ansluten till GPIOH_5.

Jag sÀtter GPIO-pin i utgÄngslÀge.
gpio -g mode 421 outJag skriver 0.
gpio -g write 421 0Jag skriver 1.
gpio -g write 421 1 
Allt lyser efter att ha skrivit '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, vid fel, anropar jag error_blink() och LED-lampan blinkar vackert.
Programvarunoder
Speedtest API
En stor glÀdje Àr att tjÀnsten speedtest.net har sitt eget python-API, som kan ses pÄ .
Det Àr bra att det finns kÀllkoder som ocksÄ kan ses. Hur man arbetar med detta API (de enklaste exemplen) kan ses i .
Jag installerar python-biblioteket med följande kommando.
sudo -H pip3 install speedtest-cliSom exempel kan du helt enkelt installera hastighetstestaren i Ubuntu direkt frÄn repos. Det Àr samma python-applikation som sedan kan startas direkt frÄn konsolen.
sudo apt install speedtest-cli -yOch mÀta hastigheten pÄ din internetuppkoppling.
speedtest-cli
HĂ€mtar speedtest.net-konfiguration...
Testar frÄn B***** (*.*.*.*)...
HÀmtar serverlista frÄn speedtest.net...
VÀljer bÀsta server baserat pÄ ping...
VĂ€rd av MTS (Moskva) [0.12 km]: 11.8 ms
Tester nedladdningshastighet................................................................................
Nedladdning: 7.10 Mbit/s
Tester uppladdningshastighet......................................................................................................
Uppladdning: 3.86 Mbit/s
Som resultat av hur jag gjorde detta. Jag var tvungen att dyka ner i kÀllkoderna för detta hastighetstest för att mer fullstÀndigt integrera dem i mitt projekt. En av de viktigaste uppgifterna Àr att fÄ Àven namnet pÄ teleoperatören för att sÀtta in det i tabellen.
import speedtest
from datetime import datetime
...
# Ange specifik server för testet
#6053) MaximaTelecom (Moskva, Ryska federationen)
servers = ["6053"]
# Om du vill anvÀnda ett entrÄdat test
threads = None
s = speedtest.Speedtest()
# HÀmtar namnet pÄ mobiloperatören
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
# HÀmtar en textstrÀng med serverparametrar
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
# Nedladdningstest
s.download(threads=threads)
# Uppladdningstest
s.upload(threads=threads)
# HĂ€mtar resultaten
s.results.share()
# DÀrefter skapas en strÀng för att skriva till csv-fil.
# HĂ€mtar GPS-positionen
longitude, latitude = getPositionData(agps_thread)
# Tid och datum
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"
# HĂ€r skrivs loggfilen
Det visade sig att det inte heller var sÄ enkelt, Àven om det borde vara enklare. Ursprungligen var parametern servers lika med [], som sa att jag skulle vÀlja den bÀsta servern. Resultatet blev att jag hade slumpmÀssiga servrar, och som man kan gissa, fluktuerande hastigheter. Det Àr en ganska komplex frÄga att anvÀnda en fast server, och om ja, sÄ krÀver det forskning om den Àr statisk eller dynamisk. Men hÀr Àr ett exempel pÄ hastighetsmÀtningar frÄn operatören Beeline med dynamisk val av testserver och en statiskt faststÀlld.

Resultatet av hastighetsmÀtningen med val av dynamisk server.

Resultatet av hastighetstestet med en strikt valt server.
Det finns "brus" i testerna bÄde hÀr och dÀr, och det behöver tas bort med matematiska metoder. Men med en fast server Àr det lite mindre brus och amplituden Àr mer stabil.
Detta Àr faktiskt ett omrÄde för omfattande forskning. Jag skulle göra hastighetsmÀtningar till min server med hjÀlp av verktyget iperf. Men vi följer kraven i specifikationen.
E-postskickning och fel
För att skicka e-post testade jag flera olika alternativ, men slutligen fastnade jag vid följande. Jag registrerade en e-postadress pÄ yandex och dÀrefter tog jag . Jag testade det och implementerade det i programmet. I detta exempel gÄr vi igenom olika alternativ, inklusive att skicka frÄn gmail med mera. Jag ville inte brÄka med att sÀtta upp min egen e-postserver och hade inte tid för det, men som det visade sig var det ocksÄ förgÀves.
Jag skickade loggar via schemalÀggaren, om det fanns en anslutning, var sjÀtte timme: klockan 00, 06, 12 och 18. Jag skickade pÄ följande sÀtt.
from send_email import *
...
message_log = "Testloggar för kort #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, "Loggar för " + curdata + " " + curtime, files)
except:
print("NÀtverksproblem för att skicka mail")
return False
return True
Fel skickades ocksÄ initialt. Först samlades de i en lista, och jag skickade dem ocksÄ via schemalÀggaren, om det fanns en anslutning. Men det uppstod sedan problem eftersom Yandex har en grÀns för antalet meddelanden som kan skickas per dag (detta Àr smÀrta, sorg och förnedring). Eftersom det kunde finnas ett stort antal fel pÄ en minut, tvingades jag avstÄ frÄn att skicka fel via e-post. SÄ ha det i Ätanke nÀr du skickar automatiskt via Yandex-tjÀnster angÄende detta problem.
Feedbackserver
För att fÄ tillgÄng till den fjÀrranslutna hÄrdvaran och kunna finjustera och omkonfigurera den behövde jag en extern server. Egentligen skulle det vara rÀttvist att skicka all data till servern och bygga alla fina diagram i webbgrÀnssnittet. Men inte allt pÄ en gÄng.
Som VPS valde jag . Jag kunde ha tagit den enklaste servern. Och för mina syften skulle det i stort sett ha varit mer Àn tillrÀckligt. Men eftersom jag inte betalade för servern ur min egen plÄnbok, beslutade jag mig för att ta en med lite extra kapacitet, sÄ att det skulle rÀcka om vi skulle rulla ut ett webbgrÀnssnitt, egen SMTP-server, VPN, osv. Dessutom ville jag kunna stÀlla in en Telegram-bot och undvika problem med dess blockeringar. DÀrför valde jag Amsterdam och följande parametrar.

Som anslutningsmetod till enheten vim2 valde jag omvÀnd ssh-anslutning och, som praktiken visade, Àr det inte det bÀsta. Vid avbrott i anslutningen hÄller servern porten, och det Àr inte möjligt att ansluta under en tid. DÀrför Àr det ÀndÄ bÀttre att anvÀnda andra anslutningsmetoder, som VPN. I framtiden ville jag byta till VPN, men jag hann inte.
Jag kommer inte att gÄ in pÄ detaljer om konfigurationen av brandvÀggen, begrÀnsningar av rÀttigheter, avstÀngning av ssh-anslutning för root och andra grundlÀggande konfigurationer av VPS. Jag hoppas att ni redan vet allt detta. För fjÀrranslutning skapar jag en ny anvÀndare pÄ servern.
adduser vimsshPÄ vÄr maskin genererar jag ssh-nycklar.
ssh-keygenOch jag kopierar dem till vÄr server.
ssh-copy-id vimssh@host.comPÄ vÄr maskin skapar jag en automatisk Äteranslutning via ssh vid varje uppstart.
[Enhet]
Beskrivning=Auto Reverse SSH
KrÀver=systemd-networkd-wait-online.service
Efter=systemd-networkd-wait-online.service
[Service]
AnvÀndare=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 vimssh@host.com
RestartSec=5
Restart=alltid
[Install]
WantedBy=multi-user.target
Observera port 8083: den avgör vilken port jag kommer att anvÀnda för att ansluta via Äteranslutning. Vi lÀgger till detta i autostart och startar det.
sudo systemctl enable autossh.service
sudo systemctl start autossh.serviceMan kan Àven kolla status:
sudo systemctl status autossh.serviceNu, pÄ vÄr VPS-server, om jag kör:
ssh -p 8083 khadas@localhostDÄ kommer jag Ät min testmaskin. Och frÄn maskinen kan jag Àven skicka loggar och data via ssh till min server, vilket Àr mycket praktiskt.
Sammanfattar allt

Nu börjar vi utveckla och debugga
Puh, jag har nog beskrivit alla noder. Nu Àr det dags att sammanfoga allt till en enhet. Koden kan ses hÀr .
En viktig punkt med koden: Detta projekt kan inte starta som det Ă€r, eftersom det Ă€r inriktat pĂ„ en viss uppgift och specifik arkitektur. Ăven om jag ger kĂ€llkoden, Ă€r det viktigaste förklarat hĂ€r i texten, annars Ă€r det helt oklart.
I början har jag initialization av gps, gpio och start av en separat trÄd för planering.
#запŃŃĐș ĐżĐŸŃĐŸĐșа ĐżĐ»Đ°ĐœĐžŃĐŸĐČŃĐžĐșа
pShedulerThread = threading.Thread(target=ShedulerThread, args=(1,))
pShedulerThread.start()Planeraren Àr ganska enkel: den kollar om det Àr dags att skicka meddelanden och vad den nuvarande felstatusen Àr. Om det finns en felflagga, blinkar vi med en lysdiod.
#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 svÄraste momentet i detta projekt Àr att behÄlla den omvÀnda ssh-anslutningen vid varje test. I varje test stÀlls standardgateway och dns-server pÄ nytt. Eftersom ingen ÀndÄ lÀser, vet att tÄget inte rullar pÄ trÀspÄr. Den som hittar pÄskÀgget fÄr godis.
För detta skapar jag en separat routingtabelle âset-mark 0x2 och en regel för att omdirigera 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")Mer om hur detta fungerar kan .
Efter det gÄr jag in i en oÀndlig loop dÀr jag varje gÄng fÄr en lista över anslutna modem (för att se om nÀtverkskonfigurationen har Àndrats).
network_list = getNetworklist()Att hÀmta listan över nÀtverksgrÀnssnitt Àr ganska 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_listEfter att ha fÄtt listan tilldelar jag IP-adresser till alla grÀnssnitt, som jag visade pÄ bilden i kapitlet om modem.
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')DÀrefter gÄr jag helt enkelt igenom varje grÀnssnitt i en loop. Och konfigurerar varje grÀnssnitt.
for iface in network_list:
ConfigNetwork(iface)def ConfigNetwork(iface):
#ÄterstÀller alla instÀllningar
cmd_run('sudo ip route flush all')
#TillsÀtter standardgateway
cmd_run('sudo route add default gw 192.168.8.1 ' + iface)
#tilldelar dns-server (detta behövs för att köra speedtest)
cmd_run('sudo bash -c "echo nameserver 8.8.8.8 > /etc/resolv.conf"')Jag kontrollerar grÀnssnittet för funktionalitet, om det inte finns nÄgot nÀtverk, sÄ genererar jag fel. Om det finns ett nÀtverk, sÄ Àr det dags att agera!
HÀr konfigurerar jag ssh-routing för detta grÀnssnitt (om det inte redan har gjorts), skickar fel till servern, och om det Àr dags, skickar jag loggar och till sist genomför jag en speedtest och sparar loggarna i en csv-fil.
if not NetworkAvalible():
....
#HĂ€r generar vi fel
....
else: #Det finns nÀtverk, hurra, vi jobbar!
#Om vi har ett problematiskt grÀnssnitt, pÄ vilket ssh, sÄ Àndrar 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
#eftersom nÀtverket fungerar, lÄt oss skicka allt!!!
if ready_to_send:
print('**** Ready to send!!!')
if sendLogs():
ready_to_send = False
if error_status:
SendErrors()
#och sedan testar vi hastigheten och sparar loggar. Det Àr vÀrt att nÀmna funktionen för att konfigurera omvÀnd 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')Och sjÀlvklart Àr det nödvÀndigt att lÀgga till allt detta i autostart. För detta skapar jag en fil:
sudo vim /etc/systemd/system/modems_speedtest.serviceOch jag skriver in den:
[Enhet]
Beskrivning=Modem Hastighetstest
KrÀver=systemd-networkd-wait-online.service
Efter=systemd-networkd-wait-online.service
[Service]
AnvÀndare=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
RestartSec=5
Restart=alltid
[Install]
WantedBy=multi-user.target
Jag aktiverar autostarten och startar!
sudo systemctl enable modems_speedtest.service
sudo systemctl start modems_speedtest.serviceNu kan jag se loggarna för vad som hÀnder med kommandot:
journalctl -u modems_speedtest.service --no-pager -fResultat
Men nu Àr den viktigaste frÄgan, vad blev resultatet? Jag kommer att ge nÄgra grafer som jag lyckades fÄnga under utvecklings- och debuggningsprocessen. Graferna skapades med hjÀlp av gnuplot enligt följande 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örsta erfarenheten var frÄn operatören Tele2, som jag genomförde under flera dagar.

HÀr anvÀnde jag en dynamisk mÀtserver. MÀtningarna av hastighet fungerar, men varierar kraftigt, ÀndÄ syns en viss genomsnittlig siffra, och den kan erhÄllas genom att filtrera data, till exempel med ett glidande medelvÀrde.
Senare byggde jag ytterligare ett antal grafer för andra operatörer. Testservern i det hÀr fallet var en och samma, och resultaten var ocksÄ mycket intressanta.




Som syns Ă€r Ă€mnet mycket omfattande för forskning och bearbetning av dessa data, och drar uppenbarligen inte bara ett par veckors arbete. MenâŠ
Slutsats av arbetet
Arbetet avslutades plötsligt pÄ grund av omstÀndigheter som jag inte kunde pÄverka. En av de svaga punkterna i detta projekt, enligt min personliga Äsikt, var modemet, som inte riktigt ville fungera samtidigt med andra modem, och gjorde knep vid varje omstart. För dessa ÀndamÄl finns det ett stort antal andra modemmodeller, vanligtvis har de redan formatet Mini PCI-e och sÀtts in i enheten, vilket gör dem mycket enklare att konfigurera. Men det Àr en helt annan historia. Projektet var intressant och jag var mycket glad över att jag fick delta.
KĂ€lla: habr.com

