Speedtest simultaneo su più modem LTE

Durante la quarantena mi è stato offerto di partecipare allo sviluppo di un dispositivo per misurare la velocità dei modem LTE per diversi operatori cellulari.

Speedtest simultaneo su più modem LTE

Il cliente voleva valutare la velocità di vari operatori di telecomunicazioni in diverse località geografiche per poter capire quale operatore cellulare fosse più ottimale per lui durante l'installazione di apparecchiature che utilizzano una connessione LTE, ad esempio, per le trasmissioni video. Allo stesso tempo, il problema doveva essere risolto nel modo più semplice ed economico possibile, senza attrezzature costose.

Dirò subito che il compito non è dei più semplici e ad alta intensità di conoscenza, ti dirò quali problemi ho riscontrato e come li ho risolti. Quindi andiamo.

Nota

Misurare la velocità di una connessione LTE è una questione molto complessa: è necessario scegliere la giusta attrezzatura e tecnica di misurazione, oltre ad avere una buona conoscenza della topologia e del funzionamento della rete cellulare. Inoltre, la velocità può essere influenzata da diversi fattori: il numero di abbonati su una cella, le condizioni meteorologiche, anche da cella a cella la velocità può variare notevolmente a causa della topologia della rete. In generale, questo è un problema con un numero enorme di incognite e solo un operatore di telecomunicazioni può risolverlo correttamente.

Inizialmente il cliente voleva semplicemente guidare il corriere con i telefoni degli operatori, effettuare le misurazioni direttamente sul telefono e poi annotare i risultati della misurazione della velocità su un taccuino. La mia soluzione per misurare la velocità delle reti LTE, sebbene non ideale, risolve il problema.

Per mancanza di tempo, ho preso decisioni non a favore della comodità o della praticità, ma a favore della velocità di sviluppo. Ad esempio, per l'accesso remoto è stato utilizzato reverse ssh, al posto della più pratica VPN, in modo da risparmiare tempo nella configurazione del server e di ogni singolo client.

Termini di riferimento

Come affermato nell'articolo Senza specifiche tecniche: perché il cliente non lo vuole: Non lavorare senza specifiche tecniche! Mai, da nessuna parte!

Il compito tecnico era abbastanza semplice, lo espanderò un po' per la comprensione dell'utente finale. La scelta delle soluzioni tecniche e delle attrezzature è stata dettata dal cliente. Quindi, le specifiche tecniche stesse, dopo tutte le approvazioni:

Basato su un computer a scheda singola vim2 realizzare un tester di velocità per le connessioni LTE tramite modem Huawei e3372h-153 più operatori di telecomunicazioni (da uno a n). È inoltre necessario ricevere le coordinate da un ricevitore GPS collegato tramite UART. Effettua misurazioni della velocità utilizzando il servizio www.speedtest.net e inserirli in una tabella come:

Speedtest simultaneo su più modem LTE

Tabella in formato CSV. Quindi invia questo segno via e-mail ogni 6 ore. In caso di errori, far lampeggiare il LED collegato al GPIO.

Ho descritto le specifiche tecniche in forma libera, dopo numerose approvazioni. Ma il significato del compito è già visibile. È stata concessa una settimana per tutto. Ma in realtà durò tre settimane. Questo tenendo conto del fatto che l'ho fatto solo dopo il mio lavoro principale e nei fine settimana.

Qui voglio attirare ancora una volta l'attenzione sul fatto che il cliente ha concordato in anticipo l'utilizzo del servizio e dell'hardware di misurazione della velocità, il che ha limitato notevolmente le mie capacità. Anche il budget era limitato, quindi non è stato acquistato nulla di speciale. Quindi abbiamo dovuto giocare secondo queste regole.

Architettura e sviluppo

Lo schema è semplice e ovvio. Pertanto lo lascerò senza commenti particolari.

Speedtest simultaneo su più modem LTE

Ho deciso di implementare l'intero progetto in Python, nonostante non avessi alcuna esperienza di sviluppo in questo linguaggio. L'ho scelto perché c'erano un sacco di esempi e soluzioni già pronti che potevano accelerare lo sviluppo. Chiedo quindi a tutti i programmatori professionisti di non rimproverare la mia prima esperienza di sviluppo in Python, e sono sempre felice di ricevere critiche costruttive per migliorare le mie capacità.

Inoltre nel processo ho scoperto che Python ha due versioni in esecuzione 2 e 3, di conseguenza ho optato per la terza.

Nodi hardware

Vim2 a piastra singola

Mi è stato assegnato un computer a scheda singola come macchina principale vim2

Speedtest simultaneo su più modem LTE

Un eccellente e potente processore multimediale per una casa intelligente e una SMART-TV, ma estremamente inadatto a questo compito o, diciamo, poco adatto. Ad esempio, il suo sistema operativo principale è Android e Linux è un sistema operativo secondario e, di conseguenza, nessuno garantisce il funzionamento di alta qualità di tutti i nodi e driver sotto Linux. E presumo che alcuni dei problemi fossero legati ai driver USB di questa piattaforma, quindi i modem non hanno funzionato come previsto su questa scheda. Ha anche una documentazione molto scarsa e dispersa, quindi ogni operazione ha richiesto molto tempo per scavare tra le banchine. Anche il lavoro ordinario con GPIO richiedeva molto sangue. Ad esempio, mi ci sono volute diverse ore per impostare il LED. Ma, per essere obiettivi, fondamentalmente non era importante che tipo di scheda singola fosse, l'importante era che funzionasse e che ci fossero porte USB.

Per prima cosa devo installare Linux su questa scheda. Per non frugare nella documentazione per tutti, e anche per chi si occuperà di questo sistema a scheda singola, scrivo questo capitolo.

Esistono due opzioni per installare Linux: su una scheda SD esterna o su una MMC interna. Ho passato una serata a cercare di capire come farlo funzionare con la scheda, quindi ho deciso di installarlo sulla MMC, anche se senza dubbio sarebbe molto più semplice lavorare con una scheda esterna.

Informazioni sul firmware qui raccontato in modo storto. Traduco dallo strano al russo. Per eseguire il flashing della scheda, devo collegare l'hardware UART. Collegato come segue.

  • Pin strumento GND: <—> Pin17 del GPIO dei VIM
  • Strumento Pin TXD: <—> Pin18 del GPIO di VIM (Linux_Rx)
  • Strumento Pin RXD: <—> Pin19 del GPIO di VIM (Linux_Tx)
  • Strumento Pin VCC: <—> Pin20 del GPIO di VIM

Speedtest simultaneo su più modem LTE

Successivamente ho scaricato il firmware quindi. Versione firmware specifica VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Per caricare questo firmware, ho bisogno di utilità. Maggiori dettagli a riguardo qui. Non ho provato a installarlo su Windows, ma devo dirti alcune parole sul firmware su Linux. Per prima cosa installerò le utilità secondo le istruzioni.

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

Eeeek... Non funziona niente. Ho passato un paio d'ore a modificare gli script di installazione in modo che tutto venisse installato correttamente per me. Non ricordo cosa ho fatto lì, ma c’era anche quel circo con i cavalli. Perciò stai attento. Ma senza queste utilità non ha senso torturare ulteriormente vim2. È meglio non scherzare affatto con lui!

Dopo sette gironi dell'inferno, configurazione e installazione dello script, ho ricevuto un pacchetto di utilità funzionanti. Ho collegato la scheda tramite USB al mio computer Linux e ho anche collegato l'UART secondo lo schema sopra.
Sto configurando il mio terminale Minicom preferito per una velocità di 115200, senza controllo degli errori hardware e software. E cominciamo.

Speedtest simultaneo su più modem LTE

Quando carico VIM2 nel terminale UART, premo un tasto, come la barra spaziatrice, per interrompere il caricamento. Dopo che appare la linea

kvim2# 

Inserisco il comando:

kvim2# run update

Sull'host da cui stiamo caricando, eseguo:

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

Questo è tutto, va bene. Ho controllato, c'è Linux sulla scheda. Accesso/password khadas:khadas.

Successivamente, alcune piccole impostazioni iniziali. Per ulteriore lavoro, disabilito la password per sudo (sì, non sicura, ma comoda).

sudo visudo

Modifico la riga nel modulo e salvo

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

Quindi cambio la località attuale in modo che l'ora sia a Mosca, altrimenti sarà a Greenwich.

sudo timedatectl set-timezone Europe/Moscow

o

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

Se lo trovi difficile, non utilizzare questa scheda; Raspberry Pi è migliore. Onestamente.

ModemHuawei e3372h-153

Questo modem è stato per me una significativa fonte di sangue e, di fatto, è diventato il collo di bottiglia dell'intero progetto. In generale, il nome "modem" per questi dispositivi non riflette affatto l'essenza del lavoro: si tratta di una potente mietitrebbia, questo pezzo di hardware ha un dispositivo composito che finge di essere un CD-ROM per installare i driver, e poi passa alla modalità scheda di rete.

Architettonicamente, dal punto di vista di un utente Linux, dopo tutte le impostazioni, appare così: dopo aver collegato il modem, ho un'interfaccia di rete eth*, che tramite DHCP riceve l'indirizzo IP 192.168.8.100, e il gateway predefinito è 192.168.8.1.

E il momento più importante! Questo modello di modem non può funzionare in modalità modem, che è controllata dai comandi AT. Tutto sarebbe molto più semplice, creare connessioni PPP per ogni modem e poi operare con essi. Ma nel mio caso, "lui stesso" (più precisamente, un subacqueo Linux secondo le regole udev), crea un'interfaccia eth e le assegna un indirizzo IP tramite DHCP.

Per evitare ulteriore confusione, suggerisco di dimenticare la parola “modem” e di dire scheda di rete e gateway, perché in sostanza è come connettere una nuova scheda di rete con un gateway.
Quando è presente un modem ciò non causa particolari problemi, ma quando ce n'è più di uno, cioè n pezzi, si presenta la seguente immagine di rete.

Speedtest simultaneo su più modem LTE

Cioè n schede di rete, con lo stesso indirizzo IP, ciascuna con lo stesso gateway predefinito. Ma in realtà ognuno di essi è collegato al proprio operatore.

Inizialmente, avevo una soluzione semplice: utilizzando il comando ifconfig o ip, disattivare tutte le interfacce e accenderne semplicemente una a turno e testarla. La soluzione è andata bene a tutti, tranne che nei momenti di commutazione non sono riuscito a connettermi al dispositivo. E poiché il passaggio è frequente e veloce, in realtà non ho avuto alcuna possibilità di connettermi.

Pertanto, ho scelto il percorso di modifica manuale degli indirizzi IP dei modem e quindi di indirizzamento del traffico utilizzando le impostazioni di routing.

Speedtest simultaneo su più modem LTE

I miei problemi con i modem non sono finiti qui: in caso di problemi di alimentazione cadevano ed era necessaria una buona alimentazione stabile per l'hub USB. Ho risolto questo problema saldando l'alimentazione direttamente all'hub. Un altro problema che ho riscontrato e che ha rovinato l'intero progetto: dopo un riavvio o un avvio a freddo del dispositivo, non tutti i modem sono stati rilevati e non sempre, e non sono riuscito a determinare il motivo per cui ciò è accaduto e con quale algoritmo. Ma prima le cose principali.

Affinché il modem funzioni correttamente, ho installato il pacchetto usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Dopodiché, dopo la connessione, il modem verrà rilevato e configurato correttamente dal sottosistema udev. Controllo semplicemente collegando il modem e assicurandomi che appaia la rete.
Altro problema che non sono riuscito a risolvere: come posso ottenere da questo modem il nome dell'operatore con cui stiamo lavorando? Il nome dell'operatore è contenuto nell'interfaccia web del modem all'indirizzo 192.168.8.1. Questa è una pagina Web dinamica che riceve dati tramite richieste Ajax, quindi il semplice recupero della pagina e l'analisi del nome non funzioneranno. Così ho iniziato a pensare a come sviluppare una pagina web, ecc., e ho capito che stavo facendo una specie di sciocchezza. Di conseguenza, ha sputato e l'operatore ha iniziato a ricevere utilizzando l'API Speedtest stessa.

Sarebbe molto più semplice se il modem avesse accesso tramite comandi AT. Sarebbe possibile riconfigurarlo, creare una connessione ppp, assegnare un IP, ottenere un operatore di telecomunicazioni, ecc. Ma ahimè, sto lavorando con ciò che mi è stato dato.

GPS

Il ricevitore GPS che mi è stato dato aveva un'interfaccia e un'alimentazione UART. Non era la soluzione migliore, ma era comunque praticabile e semplice. Il ricevitore assomigliava a questo.

Speedtest simultaneo su più modem LTE

A dire il vero, era la prima volta che lavoravo con un ricevitore GPS, ma come mi aspettavo, tutto è stato pensato per noi molto tempo fa. Quindi utilizziamo solo soluzioni già pronte.

Innanzitutto, abilito uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) per connettere il GPS.

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

Successivamente verifico la riuscita dell'operazione.

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

Apparentemente questo comando modifica il devtree al volo, il che è molto conveniente.

Dopo il successo di questa operazione, riavviare e installare il demone GPS.

khadas@Khadas:~$ sudo reboot

Installazione del demone GPS. Installo tutto e lo spengo immediatamente per un'ulteriore configurazione.

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

Modifica del file delle impostazioni.

sudo vim /etc/default/gpsd

Sto installando un UART su cui si bloccherà il GPS.

DEVICES="/dev/ttyS4"

E poi accendiamo tutto e iniziamo.

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

Successivamente collego il GPS.

Speedtest simultaneo su più modem LTE

Il cavo del GPS è nelle mie mani, i cavi del debugger UART sono visibili sotto le mie dita.

Riavvio e controllo il funzionamento del GPS utilizzando il programma gpsmon.

Speedtest simultaneo su più modem LTE

Non puoi vedere i satelliti in questo screenshot, ma puoi vedere la comunicazione con il ricevitore GPS e questo significa che va tutto bene.

In Python ho provato molte opzioni per lavorare con questo demone, ma ho optato per quella che funzionava correttamente con Python 3.

Installo la libreria necessaria.

sudo -H pip3 install gps3 

E scolpisco il codice del lavoro.

from gps3.agps3threaded import AGPS3mechanism
...

def getPositionData(agps_thread):
	counter = 0;
	while True:
		longitude = agps_thread.data_stream.lon
		latitude = agps_thread.data_stream.lat
		if latitude != 'n/a' and longitude != 'n/a':
			return '{}' .format(longitude), '{}' .format(latitude)
		counter = counter + 1
		print ("Wait gps counter = %d" % counter)
		if counter == 10:
			ErrorMessage("Ошибка GPS приемника!!!")
			return "NA", "NA"
		time.sleep(1.0)
...
f __name__ == '__main__':
...
	#gps
	agps_thread = AGPS3mechanism()  # Instantiate AGPS3 Mechanisms
	agps_thread.stream_data()  # From localhost (), or other hosts, by example, (host='gps.ddns.net')
	agps_thread.run_thread()  # Throttle time to sleep after an empty lookup, default '()' 0.2 two tenths of a second

Se ho bisogno di ottenere le coordinate, lo faccio con la seguente chiamata:

longitude, latitude = getPositionData(agps_thread)

Ed entro 1-10 secondi otterrò le coordinate oppure no. Sì, ho fatto dieci tentativi per ottenere le coordinate. Non ottimale, storto e di traverso, ma funziona. Ho deciso di farlo perché il GPS può avere una ricezione scarsa e non sempre ricevere dati. Se aspetti di ricevere i dati, se lavori in una stanza remota, il programma si bloccherà in questo luogo. Pertanto, ho implementato questa opzione inelegante.

In linea di principio, se ci fosse più tempo, sarebbe possibile ricevere i dati dal GPS direttamente tramite UART, analizzarli in un thread separato e lavorarci. Ma non c'era tempo, da qui il codice brutalmente brutto. E sì, non mi vergogno.

Diodo ad emissione luminosa

Collegare il LED è stato semplice e difficile allo stesso tempo. La difficoltà principale è che il numero pin nel sistema non corrisponde al numero pin sulla scheda e perché la documentazione è scritta con la mano sinistra. Per confrontare il numero pin dell'hardware e il numero pin nel sistema operativo, è necessario eseguire il comando:

gpio readall

Verrà visualizzata una tabella di corrispondenza dei pin nel sistema e sulla scheda. Dopodiché posso già utilizzare il pin nel sistema operativo stesso. Nel mio caso il LED è collegato a GPIOH_5.

Speedtest simultaneo su più modem LTE

Cambio il pin GPIO in modalità output.

gpio -g mode 421 out

Scrivo zero.

gpio -g write 421 0

Ne scrivo uno.

gpio -g write 421 1

Speedtest simultaneo su più modem LTE
Tutto si accende, dopo aver scritto “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)

Ora, in caso di errori, chiamo error_blink() e il LED lampeggerà magnificamente.

Nodi software

API di test di velocità

È una grande gioia che il servizio speedtest.net abbia la propria API Python, puoi guardarla Github.

La cosa buona è che ci sono anche codici sorgente che possono essere visualizzati. Puoi trovare come lavorare con questa API (semplici esempi) in sezione pertinente.

Installo la libreria Python con il seguente comando.

sudo -H pip3 install speedtest-cli

Ad esempio, puoi persino installare uno speed tester in Ubuntu direttamente dal software. Si tratta della stessa applicazione Python, che può quindi essere lanciata direttamente dalla console.

sudo apt install speedtest-cli -y

E misura la tua velocità Internet.

speedtest-cli
Retrieving speedtest.net configuration...
Testing from B***** (*.*.*.*)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by MTS (Moscow) [0.12 km]: 11.8 ms
Testing download speed................................................................................
Download: 7.10 Mbit/s
Testing upload speed......................................................................................................
Upload: 3.86 Mbit/s

Di conseguenza, proprio come ho fatto io. Ho dovuto accedere ai codici sorgente di questo test di velocità per implementarli in modo più completo nel mio progetto. Uno dei compiti più importanti è ottenere il nome dell'operatore di telecomunicazioni per poterlo sostituire nella targa.

import speedtest
from datetime import datetime
...
#Указываем конкретный сервер для теста
#6053) MaximaTelecom (Moscow, Russian Federation)
servers = ["6053"]
# If you want to use a single threaded test
threads = None
s = speedtest.Speedtest()
#получаем имя оператора сотовой связи
opos = '%(isp)s' % s.config['client']
s.get_servers(servers)
#получаем текстовую строку с параметрами сервера
testserver = '%(sponsor)s (%(name)s) [%(d)0.2f km]: %(latency)s ms' % s.results.server
#тест загрузки
s.download(threads=threads)
#тест выгрузки
s.upload(threads=threads)
#получаем результаты
s.results.share()

#После чего формируется строка для записи в csv-файл.
#получаем позицию GPS
longitude, latitude = getPositionData(agps_thread)
#время и дата
curdata = datetime.now().strftime('%d.%m.%Y')
curtime = datetime.now().strftime('%H:%M:%S')
delimiter = ';'
result_string = opos + delimiter + str(curpos) + delimiter + 
	curdata + delimiter + curtime + delimiter + longitude + ', ' + latitude + delimiter + 
	str(s.results.download/1000.0/1000.0) + delimiter + str(s.results.upload / 1000.0 / 1000.0) + 
	delimiter + str(s.results.ping) + delimiter + testserver + "n"
#тут идет запись в файл логов

Anche qui tutto si è rivelato non così semplice, anche se sembrerebbe molto più semplice. Inizialmente, il parametro server era uguale a [], dicono, scegli il server migliore. Di conseguenza, avevo server casuali e, come puoi immaginare, a velocità variabile. Questo è un argomento piuttosto complesso, l'utilizzo di un server fisso, se è così, statico o dinamico, richiede ricerca. Ma ecco un esempio di grafici di misurazione della velocità per un operatore Beeline quando seleziona dinamicamente un server di prova e uno fisso staticamente.

Speedtest simultaneo su più modem LTE
Il risultato della misurazione della velocità quando si sceglie un server dinamico.

Speedtest simultaneo su più modem LTE
Il risultato del test di velocità, con un server rigorosamente selezionato.

Durante i test, in entrambi i punti è presente del “pelliccia” che deve essere rimossa utilizzando metodi matematici. Ma con un server fisso è leggermente inferiore e l'ampiezza è più stabile.
In generale, questo è un luogo di grande ricerca. E misurerei la velocità del mio server utilizzando l'utilità iperf. Ma ci atteniamo alle specifiche tecniche.

Invio di posta ed errori

Per inviare la posta, ho provato diverse dozzine di opzioni diverse, ma alla fine ho optato per quanto segue. Ho registrato una casella di posta su Yandex e poi l'ho presa Questo è un esempio di invio di posta. L'ho controllato e implementato nel programma. Questo esempio esamina varie opzioni, incluso l'invio da Gmail, ecc. Non volevo preoccuparmi di configurare il mio server di posta e non avevo tempo per farlo, ma come si è scoperto in seguito, anche questo è stato vano.

I log sono stati inviati secondo lo scheduler, se c'è una connessione, ogni 6 ore: alle 00, alle 06, alle 12 e alle 18. Inviato come segue.

from send_email import *
...
message_log = "Логи тестирования платы №1"
EmailForSend = ["[email protected]", "[email protected]"]
files = ["/home/khadas/modems_speedtest/csv"]
...
def sendLogs():
	global EmailForSend
	curdata = datetime.now().strftime('%d.%m.%Y')
	сurtime = datetime.now().strftime('%H:%M:%S')
	try:
		for addr_to in EmailForSend:
			send_email(addr_to, message_log, "Логи за " + curdata + " " + сurtime, files)
	except:
		print("Network problem for send mail")
		return False
	return True

Inizialmente sono stati inviati anche degli errori. Per cominciare, si sono accumulati nell'elenco e poi sono stati inviati anche tramite lo scheduler, se c'era una connessione. Tuttavia, sono sorti problemi con il fatto che Yandex ha un limite al numero di messaggi inviati al giorno (questo è dolore, tristezza e umiliazione). Dato che poteva verificarsi un numero elevato di errori anche al minuto, abbiamo dovuto abbandonare l'invio di errori tramite posta. Quindi tienilo a mente quando invii automaticamente informazioni su un problema del genere tramite i servizi Yandex.

Server di feedback

Per poter accedere a un componente hardware remoto ed poterlo personalizzare e riconfigurare, avevo bisogno di un server esterno. In generale, per essere onesti, sarebbe corretto inviare tutti i dati al server e costruire tutti i bellissimi grafici nell'interfaccia web. Ma non tutto in una volta.

Per VPS ho scelto ruvds.com. Potresti prendere il server più semplice. E in generale, per i miei scopi questo sarebbe sufficiente. Ma poiché non ho pagato di tasca mia il server, ho deciso di prenderlo con una piccola riserva, in modo che fosse sufficiente implementare un'interfaccia web, un proprio server SMTP, VPN, ecc. Inoltre, potrai configurare un bot di Telegram e non avere problemi con il suo blocco. Pertanto, ho scelto Amsterdam e i seguenti parametri.

Speedtest simultaneo su più modem LTE

Come metodo di comunicazione con l'hardware, vim2 ha scelto una connessione ssh inversa e, come ha dimostrato la pratica, non è la migliore. Se la connessione viene persa, il server mantiene la porta ed è impossibile connettersi attraverso di essa per un po' di tempo. Pertanto è ancora meglio utilizzare altri metodi di comunicazione, ad esempio VPN. In futuro avrei voluto passare alla VPN, ma non avevo tempo.

Non entrerò nei dettagli sulla configurazione di un firewall, sulla limitazione dei diritti, sulla disabilitazione delle connessioni root ssh e su altre verità ovvie sulla configurazione di un VPS. Mi piacerebbe credere che tu sappia già tutto. Per una connessione remota, creo un nuovo utente sul server.

adduser vimssh

Genero chiavi di connessione ssh sul nostro hardware.

ssh-keygen

E li copio sul nostro server.

ssh-copy-id [email protected]

Sul nostro hardware, creo una connessione ssh inversa automatica ad ogni avvio.

[Unit] Description=Auto Reverse SSH
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/ssh -NT -o ExitOnForwardFailure=yes -o ServerAliveInterval=60 -CD 8080 -R 8083:localhost:22 [email protected]
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

Presta attenzione alla porta 8083: determina quale porta utilizzerò per connettermi tramite reverse ssh. Aggiungilo all'avvio e avvia.

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

Puoi anche vedere lo stato:

sudo systemctl status autossh.service

Ora, sul nostro server VPS, se eseguiamo:

ssh -p 8083 khadas@localhost

Poi arrivo al mio componente hardware di prova. E dall'hardware posso anche inviare log ed eventuali dati via ssh al mio server, il che è molto comodo.

Mettendo tutto insieme

Speedtest simultaneo su più modem LTE
All'accensione, iniziamo lo sviluppo e il debug

Uff, beh, tutto qui, ho descritto tutti i nodi. Ora è il momento di mettere tutto insieme. Puoi vedere il codice qui.

Un punto importante con il codice: questo progetto potrebbe non iniziare così, perché è stato adattato per un compito specifico, di un'architettura specifica. Anche se fornisco il codice sorgente, spiegherò comunque le cose più preziose qui, direttamente nel testo, altrimenti sarebbe completamente incomprensibile.

All'inizio inizializzo gps, gpio e lancio un thread di pianificazione separato.

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

Lo scheduler è abbastanza semplice: controlla se è giunto il momento di inviare messaggi e qual è lo stato di errore corrente. Se è presente un flag di errore, facciamo lampeggiare il 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)

La parte più difficile di questo progetto è mantenere la connessione ssh inversa per ogni test. Ogni test prevede la riconfigurazione del gateway predefinito e del server DNS. Dato che comunque nessuno legge, sappi che il treno non viaggia su rotaie di legno. Chi trova l'uovo di Pasqua riceve delle caramelle.

Per fare ciò, creo una tabella di routing separata -set-mark 0x2 e una regola per reindirizzare il traffico.

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

Puoi saperne di più su come funziona leggi in questo articolo.

Dopodiché entro in un loop infinito, dove ogni volta otteniamo l'elenco dei modem collegati (per scoprire se la configurazione della rete è cambiata improvvisamente).

network_list = getNetworklist()

Ottenere un elenco di interfacce di rete è abbastanza semplice.

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

Dopo aver ricevuto la lista, ho impostato gli indirizzi IP su tutte le interfacce, come mostrato nell'immagine nel capitolo relativo al 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")

Quindi eseguo semplicemente ciascuna interfaccia in un ciclo. E configuro ogni interfaccia.

	for iface in network_list:
		ConfigNetwork(iface)

def ConfigNetwork(iface):
#сбрасываем все настройки
		cmd_run("sudo ip route flush all")
#Назначаем шлюз по умолчанию
		cmd_run("sudo route add default gw 192.168.8.1 " + iface)
#задаем dns-сервер (это нужно для работы speedtest)
		cmd_run ("sudo bash -c 'echo nameserver 8.8.8.8 > /etc/resolv.conf'")

Controllo la funzionalità dell'interfaccia, se non è presente la rete, genera errori. Se c’è una rete, allora è il momento di agire!

Qui configuro il routing ssh su questa interfaccia (se non è stato fatto), invio errori al server se è giunto il momento, invio i log e infine eseguo uno speedtest e salvo i log in un file CSV.

if not NetworkAvalible():
....
#Здесь мы формируем ошибки
....
else: #Есть сеть, ура, работаем!
#Если у нас проблемный интерфейс, на котором ssh, то меняем его
  if (sshint == lastbanint or sshint =="free"):
    print("********** Setup SSH ********************")
    if sshint !="free":
      сmd_run("sudo ip route del default via 192.168.8.1 dev " + sshint +" table 102")
    SetupReverseSSH(iface)
    sshint = iface
#раз сетка работает, то давай срочно все отправим!!!
    if ready_to_send:
      print ("**** Ready to send!!!")
        if sendLogs():
          ready_to_send = False
        if error_status:
          SendErrors()
#и далее тестируем скорость и сохраняем логи. 

Vale la pena menzionare la funzione di impostazione del reverse 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")

E, naturalmente, devi aggiungere tutta questa bellezza all'avvio. Per fare questo creo un file:

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

E ci scrivo:

[Unit] Description=Modem Speed Test
Requires=systemd-networkd-wait-online.service
After=systemd-networkd-wait-online.service
[Service] User=khadas
ExecStart=/usr/bin/python3.6 /home/khadas/modems_speedtest/networks.py
RestartSec=5
Restart=always
[Install] WantedBy=multi-user.target

Accendo il caricamento automatico e inizio!

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

Ora posso vedere i log di ciò che sta accadendo usando il comando:

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

Giudizio

Bene, ora la cosa più importante è: cosa è successo di conseguenza? Ecco alcuni grafici che sono riuscito a acquisire durante il processo di sviluppo e debug. I grafici sono stati costruiti utilizzando gnuplot con il seguente 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"

La prima esperienza è stata con l'operatore Tele2, che ho condotto per diversi giorni.

Speedtest simultaneo su più modem LTE

Qui ho utilizzato un server di misurazione dinamico. Le misurazioni della velocità funzionano, ma fluttuano molto, ma un valore medio è ancora visibile e questo può essere ottenuto filtrando i dati, ad esempio, con una media mobile.

Successivamente ho creato una serie di grafici per altri operatori di telecomunicazioni. In questo caso esisteva già un server di test e anche i risultati sono stati molto interessanti.

Speedtest simultaneo su più modem LTE

Speedtest simultaneo su più modem LTE

Speedtest simultaneo su più modem LTE

Speedtest simultaneo su più modem LTE

Come puoi vedere, l'argomento è molto vasto per la ricerca e l'elaborazione di questi dati, e chiaramente non dura un paio di settimane di lavoro. Ma…

Risultato del lavoro

Il lavoro è stato improvvisamente completato a causa di circostanze indipendenti dalla mia volontà. Uno dei punti deboli di questo progetto, secondo la mia opinione soggettiva, era il modem, che non voleva davvero lavorare contemporaneamente ad altri modem e faceva questi trucchi ogni volta che veniva caricato. Per questi scopi esistono numerosi altri modelli di modem, solitamente sono già in formato Mini PCI-e e vengono installati all'interno del dispositivo e sono molto più facili da configurare. Ma questa è una storia completamente diversa. Il progetto è stato interessante e sono stato molto contento di aver potuto parteciparvi.

Speedtest simultaneo su più modem LTE

Fonte: habr.com

Aggiungi un commento