Současný speedtest na několika LTE modemech

Během karantény mi bylo nabídnuto zúčastnit se vývoje zařízení na měření rychlosti LTE modemů pro několik mobilních operátorů.

Současný speedtest na několika LTE modemech

Zákazník chtěl zhodnotit rychlost všech mobilních operátorů na různých geografických místech, aby bylo možné zjistit, který mobilní operátor je pro něj nejoptimálnější při instalaci zařízení využívajícího LTE spojení, například pro videopřenosy. Přitom bylo třeba úkol vyřešit co nejjednodušeji a nejlevněji, bez drahého vybavení.

Hned říkám, že úkol není nejjednodušší a je náročný na vědu; povím, s jakými problémy jsem se setkal a jak jsem je řešil. Tak tedy, jdeme na to.

Poznámka

Měření rychlosti LTE spojení je velmi složité: je nezbytné správně vybrat vybavení a metodiku měření, také dobře chápat topologii a fungování mobilní sítě. Navíc může na rychlost mít vliv několik faktorů: počet účastníků v buňce, povětrnostní podmínky, ba dokonce si rychlost může výrazně lišit i mezi buňkami kvůli topologii sítě. Obecně je tento úkol s obrovským množstvím neznámých a správně ho může vyřešit jen mobilní operátor.

Původně chtěl zákazník jen posílat kurýra s telefony operátorů, provádět měření přímo na telefonu a poté do sešitu zaznamenávat výsledky měření rychlosti. Moje řešení pro měření rychlosti LTE sítí, i když není dokonalé, ale splňuje stanovený úkol.

Kvůli nedostatku času jsem se rozhodoval ne v prospěch pohodlí nebo praktičnosti, ale ve prospěch rychlosti vývoje. Například pro vzdálený přístup jsem nastavoval reverzní ssh místo praktičtějšího vpn, kvůli úspoře času na nastavení serveru a každého jednotlivého klienta.

Technická specifikace

Jak je uvedeno v článku Bez TZ: proč klient nechce mít specifikaci: Nekonávejte práci bez TZ! Nikdy, nikde!

Technická specifikace byla dost jednoduchá, trochu ji rozšířím pro pochopení koncového uživatele. Výběr technických řešení a vybavení byl určen zákazníkem. Tak tedy, samotná TZ, po všech schváleních:

Na základě jednodeskového počítače vim2 udělat tester rychlosti LTE spojení přes modemy Huawei e3372h — 153 několika operátorů (od jednoho do n). Také je nutné získávat souřadnice z GPS přijímače připojeného přes UART. Měření rychlosti provádět pomocí služby www.speedtest.net a shromažďovat je do tabulky ve formátu:

Současný speedtest na několika LTE modemech

Tabulka ve formátu csv. Poté odesílat tuto tabulku na e-mail každých 6 hodin. V případě chyb rozsvítit LED diodu připojenou k GPIO.

Tz jsem popsal v volné formě po mnoha dohodách. Ale smysl úkolu je již vidět. Termín na vše byl stanoven na týden. Ale ve skutečnosti trval tři týdny. To s ohledem na to, že jsem to dělal pouze po hlavní práci a o víkendech.

Zde chci ještě jednou upozornit, že objednavatel měl předem dohodnuto použití služby měření rychlosti a hardwarového vybavení, což výrazně omezilo mé možnosti. Také byl omezen rozpočet, takže se nic moc nedokupovalo. Takže jsem musel hrát podle těchto pravidel.

Architektura a vývoj

Schéma je jednoduché a zřejmé. Proto ji nechám bez zvláštních komentářů.

Současný speedtest na několika LTE modemech

Celý projekt jsem se rozhodl realizovat v pythonu, i když jsem na tomto jazyce neměl žádné zkušenosti. Vybral jsem ho, protože existovalo spousta připravených příkladů a řešení, která mohla urychlit vývoj. Proto prosím všechny profesionální programátory, aby nekritizovali moje první zkušenosti s vývojem v pythonu, a vždy s potěšením očekávám konstruktivní kritiku pro zlepšení svých dovedností.

Také jsem během procesu zjistil, že python má dvě verze 2 a 3, nakonec jsem se zastavil na třetí.

Hardwarové komponenty

Jednočipový počítač vim2

Jako hlavní stroj mi byl dán jednočipový počítač vim2

Současný speedtest na několika LTE modemech

Skvělý, výkonný multimediální kombinátor pro chytrou domácnost a SMART-TV, avšak mimořádně nevhodný pro tento úkol, nebo řekněme tak, nedostatečně vhodný. Například, jeho hlavní operační systém je Android, zatímco Linux je vedlejší OS, a tudíž nikdo nezaručuje kvalitní fungování všech komponent a ovladačů pod Linuxem. Domnívám se, že část problémů byla spojena s USB ovladači této platformy, proto modemy pracovaly na této desce ne tak, jak jsem očekával. Také má velmi špatnou a roztříštěnou dokumentaci, proto každá operace zabírala hodně času zkoumání v dokumentech. I běžná práce s GPIO mi dala hodně zabrat. Například, abych nastavil práci s LED, potřeboval jsem několik hodin. Ale, pokud mám být objektivní, nebylo principiálně důležité, jaký single-board počítač to je, hlavně, aby fungoval a byly USB porty.

Nejprve potřebuji nainstalovat Linux na tuto desku. Abych nemusel procházet všemi zákoutími dokumentace, a také pro ty, kteří se s tímto single-board počítačem potýkají, píšu tuto kapitolu.

Existují dvě možnosti, jak nainstalovat Linux: na externí SD kartu nebo na interní MMC. S kartou jsem strávil večer, a stále jsem nepochopil, jak ji rozchodit, proto jsem se rozhodl nainstalovat na MMC, ačkoliv bezpochyby by práce s externí kartou byla mnohem jednodušší.

O flashování je tu zmíněno podivně. Překládám ze zvláštního do češtiny. Abych flashoval desku, potřebuji připojit hardwarový UART. Připojoval jsem ho následujícím způsobem.

  • Tool Pin GND: Pin17 VIM GPIO
  • Tool Pin TXD: Pin18 VIM GPIO (Linux_Rx)
  • Tool Pin RXD: Pin19 VIM GPIO (Linux_Tx)
  • Tool Pin VCC: Pin20 VIM GPIO

Současný speedtest na několika LTE modemech

Poté jsem stáhl firmware odsud. Konkrétní verze firmwaru VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Abych nahrál tento firmware, potřebuji potřebné utility. O tom podrobněji tady. Pod Windows jsem nezkoušel flashovat, ale o flashování pod Linuxem bych měl pár slov říct. Nejprve nainstaluji utility podle pokynů.

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

A… Nic nefunguje. Strávil jsem pár hodin úpravou instalačních skriptů, aby se vše správně nainstalovalo. Co jsem tam dělal, už si nepamatuji, ale také to bylo pěkné představení. Tak buďte opatrní. Ale bez těchto utilit nemá smysl mučit vim2. Raději se s ním vůbec nespojovat!

Po sedmi kolech pekla, konfiguraci skriptů a instalaci jsem získal balíček funkčních utilit. Připojil jsem desku přes USB k počítači s linuxem, a také jsem připojil UART podle schématu výše.
Nastavuji svůj oblíbený terminál minicom na rychlost 115200, bez hardwarové a softwarové kontroly chyb. A začínáme.

Současný speedtest na několika LTE modemech

Při bootování VIM2 v terminálu UART stisknu jakýkoli klávesu, například mezerník, abych zastavil bootování. Jakmile se objeví řádek

kvim2# 

Zadávám příkaz:

kvim2# run update

Na hostiteli, odkud bootujeme, vykonávám:

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

Všechno, uf. Flashoval jsem, na desce je Linux. Přihlašovací údaje/heslo khadas:khadas.

Poté provedu několik základních nastavení. Pro další práci vypínám heslo u sudo (ano, není to bezpečné, ale pohodlné).

sudo visudo

Upravuji řádek do podoby a ukládám

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

Po čemž měním aktuální lokalitu, aby byla čas podle Moskvy, jinak bude podle Greenwichi.

sudo timedatectl set-timezone Europe/Moscow

nebo

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

Pokud se vám to zdá složité, tak tuto desku raději nepoužívejte, lepší je Raspberry Pi. Poctivě.

Modem Huawei e3372h — 153

Tento modem mi dal pořádně zabrat a ve skutečnosti se stal nejužším místem celého projektu. Opravdu, název "modem" pro tato zařízení vůbec neodráží podstatu jejich fungování: je to mocný kombinátor, tato krabička má složené zařízení, které se tváří jako CD-ROM pro instalaci ovladačů, a poté přechází do režimu síťové karty.

Architektonicky, z pohledu uživatele Linuxu po všech nastaveních, vypadá takto: po připojení modemu se mi objeví síťové rozhraní eth*, které dostává ip adresu 192.168.8.100 přes dhcp, a výchozí bránu 192.168.8.1.

A nejdůležitější bod! Tento model modemu neumí pracovat v režimu přesně modemu, který je řízen AT příkazy.. Bylo by to mnohem jednodušší, vytvořit ppp spojení na každý modem a pak s nimi operovat. Ale v mém případě se "sám" (přesněji ovladače Linuxu podle pravidel udev) vytváří eth rozhraní a pomocí dhcp mu přiřazuje ip adresu.

Abychom se dále nezamotáli, doporučuji zapomenout na slovo "modem" a mluvit o síťové kartě a bráně, neboť v podstatě to je jako připojení nové síťové karty s bránou.
Když je jeden modem, to nevyvolává zvláštní problémy, ale když jich je víc než jeden, konkrétně n-kusů, vzniká následující obraz sítě.

Současný speedtest na několika LTE modemech

To znamená, že n síťových karet s jednou IP adresou, všechny mají stejnou výchozí bránu. Ve skutečnosti je však každá z nich připojena ke svému operátorovi.

Původně jsem měl jednoduché řešení: pomocí příkazů ifconfig nebo ip vypnout všechna rozhraní a jednoduše je postupně zapínat a testovat. Řešení bylo dobré, kromě toho, že jsem v okamžicích přepínání neměl možnost se k zařízení připojit. A protože bylo přepínání časté a rychlé, vlastně jsem se nemohl připojit vůbec.

Proto jsem zvolil cestu ruční změny IP adres modemů a dále směrování provozu pomocí nastavení směrování.

Současný speedtest na několika LTE modemech

Tímto moje problémy s modemy neskončily: v případě problémů s napájením se odpojovaly, potřeboval jsem dobré stabilní napájení USB hubu. Tento problém jsem vyřešil pevným napájením přímo na hub. Další problém, se kterým jsem se setkal a který zničil celý projekt: po restartu nebo studeném startu zařízení se ne vždy správně detekovaly všechny modemy a nevěděl jsem, proč se to děje a podle jakého algoritmu. Ale všechno popořádku.

Pro správnou funkci modemu jsem nainstaloval balíček usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Po kterém se modem po připojení správně detekuje a konfiguruje subsystémem udev. Ověřuji to jednoduše připojením modemu a ujistěním se, že síť se objevila.
Další problém, který jsem nemohl vyřešit: jak získat název operátora, se kterým pracujeme z tohoto modemu? Název operátora je uveden ve webovém rozhraní modemu na adrese 192.168.8.1. To je dynamická webová stránka, která získává data prostřednictvím ajaxových dotazů, takže jednoduše wgetnout stránku a vyparsovat jméno nebude fungovat. Takže jsem začal zkoumat, jak zpracovat webovou stránku a podobně a uvědomil jsem si, že se zabývám nějakou hloupostí. Nakonec jsem to vzdal a začal získávat operátora pomocí API samotného Speedtestu.

Mnoho by bylo snazší, kdyby měl modem přístup přes AT příkazy. Mohli bychom ho znovu konfigurovat, vytvářet ppp spojení, přidělovat IP adresy, získávat informace o operátorovi a tak dále. Ale bohužel pracuji s tím, co je dáno.

GPS

GPS přijímač, který mi byl vydán, měl rozhraní UART a napájení. Nebylo to nejlepší řešení, ale přesto funkční a jednoduché. Přijímač vypadal přibližně takto.

Současný speedtest na několika LTE modemech

Upřímně řečeno, poprvé jsem pracoval s GPS přijímačem, ale jak jsem předpokládal, všechno už bylo dávno vymyšleno. Takže jen používáme hotová řešení.

Nejprve zapínám uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) pro připojení GPS.

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

Poté kontroluji úspěšnost operace.

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

Tento příkaz zřejmě na místě upravuje devtree, což je velmi užitečné.

Po úspěchu této operace se restartujeme a nainstalujeme gps démon.

khadas@Khadas:~$ sudo reboot

Instalace gps démona. Nainstaluji vše a hned ho vypnu pro další konfiguraci.

sudo apt install gpsd gpsd-clients -y
sudo killall gpsd

/* GPS démon zastavit/vypnout */
sudo systemctl stop gpsd.socket
sudo systemctl disable gpsd.socket

Upravuji konfigurační soubor.

sudo vim /etc/default/gpsd

Nastavuji UART, na kterém bude GPS.

DEVICES="/dev/ttyS4"

A poté vše zapínáme a spouštíme.

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

Pak připojuji GPS.

Současný speedtest na několika LTE modemech

V rukou držím kabel GPS, mezi prsty jsou vidět dráty UART debuggera.

Restartuji se a kontroluji funkčnost GPS pomocí programu gpsmon.

Současný speedtest na několika LTE modemech

Na tomto snímku není vidět satelity, ale je vidět komunikaci s GPS přijímačem, což znamená, že vše je v pořádku.

Na pythonu jsem vyzkoušel mnoho variant práce s tímto démonem, ale zastavil jsem se na tom, který správně fungoval s python 3.

Instaluji potřebnou knihovnu.

sudo -H pip3 install gps3 

A vytvářím kód pro práci.

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("Chyba GPS přijímače!!!")
			return "NA", "NA"
		time.sleep(1.0)
...
f __name__ == '__main__':
...	#gps
	agps_thread = AGPS3mechanism()  # Zřídit AGPS3 mechanizmy
	agps_thread.stream_data()  # Z localhost (), nebo jiných hostitelů, například (host='gps.ddns.net')
	agps_thread.run_thread()  # Časový interval pro spánek po prázdném vyhledávání, výchozí '()' 0.2 dvě desetiny sekundy

Pokud potřebuji získat souřadnice, udělám to následujícím voláním:

longitude, latitude = getPositionData(agps_thread)

A během 1-10 sekund buď získám souřadnici, nebo ne. Ano, pokusů o získání souřadnic jsem měl deset. Není to optimální, krkolomné, ale funguje to. Rozhodl jsem se to tak udělat, protože GPS může špatně chytat a ne vždy získává data. Pokud bych čekal na získání dat, program by se na tomto místě zasekl v případě, že by pracoval v uzavřeném prostoru. Proto jsem zrealizoval tento neefektivní variant.

V podstatě, kdybych měl více času, mohl bych přímo přes UART získávat data z GPS, parsovat je v samostatném vlákně a pracovat s nimi. Ale času nebylo, a proto je kód velmi nehezký. A ano, není mi to trapné.

LED dioda

S připojením LED diody to bylo jednoduché a zároveň složité. Hlavní komplikací bylo, že číslo pinu v systému neodpovídá číslu pinu na desce a že dokumentace je napsaná levou zadní. Abych zjistil odpovídající číslo hardwarového pinu a číslo pinu v OS, musím provést příkaz:

gpio readall

Zobrazí se tabulka odpovídajícího pinu v systému a na desce. Poté mohu pracovat s pinem v samotném OS. V mém případě je LED dioda připojena k GPIOH_5.

Současný speedtest na několika LTE modemech

Přepínám pin GPIO do režimu výstupu.

gpio -g mode 421 out

Zapisuji nulu.

gpio -g write 421 0

Zapisuji jedničku.

gpio -g write 421 1

Současný speedtest na několika LTE modemech
Všechno se rozsvítí, po zapsání "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)

Nyní, v případě chyb volám error_blink() a LED dioda nám hezky bliká.

Programové moduly

Speedtest API

Velkou radostí je, že služba speedtest.net má svůj vlastní python-API, podívat se můžete na Github.

Dobré je, že existují také zdrojové kódy, které lze také zkontrolovat. Jak pracovat s tímto API (nejjednodušší příklady) můžete najít v příslušné sekci.

Instaluji python knihovnu následujícím příkazem.

sudo -H pip3 install speedtest-cli

Pro příklad můžete jednoduše nainstalovat speedtest do Ubuntu přímo z repozitářů. Je to stejné pythonové aplikace, kterou lze poté spustit přímo z konzole.

sudo apt install speedtest-cli -y

A provést měření rychlosti vašeho internetu.

speedtest-cli
Načítání konfigurace speedtest.net...
Testování z B***** (*.*.*.*)...
Načítání seznamu serverů speedtest.net...
Výběr nejlepšího serveru na základě latence...
Hostováno MTS (Moskva) [0,12 km]: 11,8 ms
Testování rychlosti stahování................................................................................
Stahování: 7,10 Mbit/s
Testování rychlosti nahrávání......................................................................................................
Nahrávání: 3,86 Mbit/s

V výsledku, jak jsem to udělal já. Musel jsem se ponořit do zdrojových kódů tohoto speedtestu, abych je mohl plně integrovat do svého projektu. Jedním z nejdůležitějších úkolů je také získat název poskytovatele služby pro vložení do tabulky.

import speedtest
from datetime import datetime
...
# Určujeme konkrétní server pro test
#6053) MaximaTelecom (Moskva, Ruská federace)
servers = ["6053"]
# Pokud chcete použít test s jediným vláknem
threads = None
s = speedtest.Speedtest()
# získáváme jméno mobilního operátora
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
# získáváme textový řetězec s parametry serveru
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
# test stahování
s.download(threads=threads)
# test nahrávání
s.upload(threads=threads)
# získáváme výsledky
s.results.share()

# Pak se vytváří řetězec pro zápis do csv souboru.
# získáváme GPS pozici
longitude, latitude = getPositionData(agps_thread)
# čas a 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"
# zde probíhá zápis do souboru protokolů

I tady to nebylo tak jednoduché, ačkoli se zdálo, že to je snadné. Původně byl parametr servers nastaven na [], což znamená vybrat nejlepší server. V důsledku toho jsem měl náhodné servery a jak asi uhádnete, kolísající rychlost. Je to dost složité téma, používat fixní server, pokud ano, tak statický nebo dynamický, vyžaduje to výzkum. Ale tady je příklad grafů měření rychlosti operátora Beeline při dynamickém výběru testovacího serveru a staticky fixovaného.

Současný speedtest na několika LTE modemech
Výsledek měření rychlosti při výběru dynamického serveru.

Současný speedtest na několika LTE modemech
Výsledek testování rychlosti při přísně vybraném jednom serveru.

Při testování je ‚šum‘ jak zde, tak tam, a ten je potřeba odstraňovat matematickými metodami. Ale při fixním serveru je ho o něco méně a amplituda je stabilnější.
Toto je vlastně místo pro rozsáhlý výzkum. A prováděl bych měření rychlosti na svůj server pomocí utilitky iperf. Ale držíme se zadání.

Odesílání e-mailů a chyb

Pro odesílání e-mailů jsem zkoušel několik desítek různých variant, ale nakonec jsem se zastavil na následujícím. Zaregistroval jsem e-mailovou schránku na yandex a následně vzal tento příklad odesílání e-mailu. Otestoval jsem ho a implementoval do programu. V tomto příkladu se rozebírají různé varianty, včetně odesílání z gmail atd. Nechtěl jsem se zdržovat se zřizováním vlastního poštovního serveru a neměl jsem na to čas, ale jak se později ukázalo, bylo to také zbytečné.

Odesílání logů se provádělo pomocí plánovače, pokud byla dostupná konektivita, každých 6 hodin: ve 00 hodin, 6 ráno, 12 odpoledne a 18 večer. Odesílal jsem následujícím způsobem.

from send_email import *
...
message_log = "Logy testování desky č. 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, "Logy za " + curdata + " " + curtime, files)
	except:
		print("Problém s odesláním emailu")
		return False
	return True

Chyby se také zpočátku odesílaly. Zpočátku se shromažďovaly v seznamu a pak se odesílaly také pomocí plánovače, pokud byla k dispozici konektivita. Později však nastaly problémy, protože Yandex má omezení na počet odesílaných zpráv za den (to je frustrace, smutek a ponížení). Protože mohlo být chyb i za minutu obrovské množství, museli jsme od odesílání chyb přes email upustit. Mějte na paměti, že při automatickém odesílání přes služby Yandex existuje tento problém.

Server zpětné vazby

Abych měl přístup k vzdálenému hardwaru a mohl jej nakonfigurovat a přenastavit, potřeboval jsem externí server. Obecně by bylo správné všechny údaje odesílat na server a ve webovém rozhraní vytvářet pěkné grafy. Ale ne všechno najednou.

Jako VPS jsem vybral ruvds.com. Mohl bych vzít nejjednodušší server. A celkově by pro mé cíle to stačilo. Ale protože jsem za server neplatil ze své kapsy, rozhodl jsem se vzít s malou rezervou, aby to stačilo, pokud budeme rozvíjet webové rozhraní, vlastní SMTP server, vpn atd. Plus možnost nastavit Telegram bota a vyhnout se problémům s jeho blokacemi. Proto jsem vybral Amsterdam a následující parametry.

Současný speedtest na několika LTE modemech

Jako způsob spojení s hardwarem vim2 jsem vybral zpětné ssh spojení a jak ukázala praxe — není to nejlepší volba. Při přerušení spojení server udržuje port a není možné se k němu nějakou dobu připojit. Proto je stále lepší používat jiné způsoby spojení, například vpn. V budoucnu jsem chtěl přejít na vpn, ale nestihl jsem to.

Nebudu se zabývat podrobnostmi nastavení firewallu, omezením práv, zákazem ssh spojení pro uživatele root a dalšími základními pravidly nastavení VPS. Doufám, že to víte. Pro vzdálené spojení vytvářím nového uživatele na serveru.

adduser vimssh

Na našem zařízení generuji klíče pro ssh spojení.

ssh-keygen

A kopíruji je na náš server.

ssh-copy-id vimssh@host.com

Na našem zařízení vytvářím automatické spojení reverzního ssh při každém spuštění.

[Unit]
Popis=Auto Reverse SSH
Vyžaduje=systemd-networkd-wait-online.service
Po=systemd-networkd-wait-online.service
[Service]
Uživatel=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

Všimněte si portu 8083: ten určuje, přes který port se budu připojovat pomocí reverzního ssh. Přidáváme do spouštěcí sekce a spouštíme.

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

Můžete se dokonce podívat na stav:

sudo systemctl status autossh.service

Nyní, na našem VPS serveru, pokud vykonáte:

ssh -p 8083 khadas@localhost

Dostanu se na své testovací zařízení. A z zařízení mohu také odesílat logy a jakékoli údaje přes ssh na svůj server, což je velmi pohodlné.

Dáváme vše dohromady

Současný speedtest na několika LTE modemech
Začínáme, přejdeme k vývoji a ladění

Uf, zdá se, že jsem popsal všechny uzly. Nyní je čas dát to všechno dohromady. Kód si můžete prohlédnout tady.

Důležitý bod s kódem: Tento projekt nemusí takto "z fleku" běžet, protože byl zaměřen na určitou úlohu a konkrétní architekturu. I když dávám zdrojové kódy, to nejcennější, co je, podrobím rozboru tady v textu, jinak by to bylo zcela nepochopitelné.

Na začátku mám inicializaci gps, gpio a spuštění samostatného vlákna plánovače.

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

Plánovač je poměrně jednoduchý: kontroluje, zda přišel čas pro odeslání zpráv a jaký je nyní stav chyb. Pokud je zde chyba, blikáme LED diodou.

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

Nejkomplikovanější částí tohoto projektu je udržet reverzní ssh spojení při každém testu. Při každém testu se znovu nastavuje výchozí brána a dns server. Protože to stejně nikdo nečte, vězte, že vlak nejezdí po dřevěných kolejích. Kdo najde velikonoční vajíčko, dostane cukrovinku.

Pro to vytvářím samostatnou tabulku směrování —set-mark 0x2 a pravidlo pro přesměrování provozu.

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

Podrobněji o tom, jak to funguje, můžete přečíst v tomto článku.

Poté přecházím do nekonečné smyčky, kde pokaždé získávám seznam připojených modemů (abych zjistil, zda se konfigurace sítě nezměnila).

network_list = getNetworklist()

Získání seznamu síťových rozhraní je relativně jednoduché.

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

Po získání seznamu nastavím IP adresy všem rozhraním, jak jsem uvedl na obrázku v kapitole o modemu.

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ále jednoduše procházím každé rozhraní v cyklu. A konfiguruji každé rozhraní.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#resetujeme všechny nastavení
		cmd_run("sudo ip route flush all")
#Nastavíme výchozí bránu
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#nastavujeme dns server (to je potřeba pro fungování speedtest)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

Kontroluji rozhraní na funkčnost, pokud není síť, vytvářím chyby. Pokud síť existuje, čas jednat!

Zde nastavím ssh routování na toto rozhraní (pokud nebylo uděláno), posílám chyby na server, pokud je čas, posílám logy a nakonec provádím speedtest a ukládám logy do csv souboru.

if not NetworkAvalible():
....
#Zde vytváříme chyby
....
else: #Síť je, hurá, pracujeme!
#Pokud máme problémové rozhraní, na kterém je ssh, měníme ho
  if (sshint == lastbanint or sshint =="free"):
    print("********** Nastavení SSH ********************")
    if sshint !="free":
      cmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint +" table 102")
    SetupReverseSSH(iface)
    sshint = iface
#protože síť funguje, pošleme všechno!!!
    if ready_to_send:
      print ("**** Připraveno k odeslání!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#a dále testujeme rychlost a ukládáme logy. 

Možná stojí za zmínku funkce pro nastavení reverzního 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")

A samozřejmě je potřeba celou tuto krásu přidat do automatického spouštění. Za tímto účelem vytvářím soubor:

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

A zapíšu do něho:

[Unit]
Popis=Test rychlosti modemu
Vyžaduje=systemd-networkd-wait-online.service
Po=systemd-networkd-wait-online.service
[Service]
Uživatel=khadas
ExecStart=\/usr\/bin\/python3.6 \/home\/khadas\/modems_speedtest\/networks.py
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target

Zapínám automatické spouštění a spouštím!

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

Teď mohu sledovat logy toho, co se děje pomocí příkazu:

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

Výsledky

A teď to nejdůležitější: jaký byl výsledek? Představím několik grafů, které se mi podařilo pořídit během vývoje a ladění. Grafy byly vytvořeny pomocí gnuplot s následujícím skriptem.

#! /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"

První zkušenost byla s operátorem Tele2, kterou jsem prováděl po dobu několika dní.

Současný speedtest na několika LTE modemech

Zde jsem použil dynamický měřicí server. Měření rychlosti funguje, ale velmi značně kolísá, nicméně přesto je viditelná určitá průměrná hodnota, kterou lze získat filtrací dat, například pomocí klouzavého průměru.

Později jsem vytvořil další řadu grafů pro jiné mobilní operátory. Testovací server byl v tomto případě již jeden a výsledky byly také velmi zajímavé.

Současný speedtest na několika LTE modemech

Současný speedtest na několika LTE modemech

Současný speedtest na několika LTE modemech

Současný speedtest na několika LTE modemech

Jak je vidět, téma je velmi široké pro výzkum a zpracování těchto dat a zjevně to nestačí na pár týdnů práce. Ale…

Výsledek práce

Práce byla náhle ukončena z okolností nezávislých na mně. Jednou z slabých stránek tohoto projektu, podle mého subjektivního názoru, byl modem, který nechtěl pracovat současně s jinými modemy a při každém spuštění dělal takové kousky. Pro tyto účely existuje obrovské množství jiných modelů modemů, obvykle už mají formát Mini PCI-e a vkládají se dovnitř zařízení a jejich konfigurace je mnohem jednodušší. Ale to už je úplně jiný příběh. Projekt byl zajímavý a byl jsem velmi rád, že jsem mohl být jeho součástí.

Současný speedtest na několika LTE modemech

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster