Proba de velocidade simultánea en varios módems LTE

Durante a corentena, ofrecéronme participar no desenvolvemento dun dispositivo para medir a velocidade dos módems LTE para varios operadores móbiles.

Proba de velocidade simultánea en varios módems LTE

O cliente quería avaliar a velocidade de varios operadores de telecomunicacións en diferentes localizacións xeográficas para poder entender cal era o operador de telefonía móbil máis óptimo para el á hora de instalar equipos mediante conexión LTE, por exemplo, para as emisións de vídeo. Ao mesmo tempo, o problema tiña que ser resolto o máis sinxelo e barato posible, sen equipos caros.

Enseguida direi que a tarefa non é a máis sinxela e a máis intensiva en coñecementos; contarei que problemas atopei e como os resolvín. Entón, imos.

Nota

Medir a velocidade dunha conexión LTE é un asunto moi complexo: cómpre escoller o equipo e a técnica de medición adecuados, e tamén ter unha boa comprensión da topoloxía e o funcionamento da rede móbil. Ademais, a velocidade pode verse influenciada por varios factores: o número de subscritores nunha célula, as condicións meteorolóxicas, incluso dunha célula a outra, a velocidade pode variar drasticamente debido á topoloxía da rede. En xeral, este é un problema cunha gran cantidade de incógnitas e só un operador de telecomunicacións pode solucionalo correctamente.

Inicialmente, o cliente só quería conducir o correo cos teléfonos dos operadores, tomar medidas directamente no teléfono e despois anotar os resultados da medición da velocidade nun caderno. A miña solución para medir a velocidade das redes lte, aínda que non é a ideal, resolve o problema.

Por falta de tempo, tomei decisións non a favor da comodidade ou da practicidade, senón a favor da velocidade de desenvolvemento. Por exemplo, utilizouse ssh inverso para o acceso remoto, en lugar da VPN máis práctica, para aforrar tempo na configuración do servidor e de cada cliente individual.

Tarefa técnica

Como se indica no artigo Sen especificacións técnicas: por que o cliente non o quere: Non traballes sen especificacións técnicas! Nunca, en ningures!

A tarefa técnica foi bastante sinxela, ampliarei un pouco para a comprensión do usuario final. A elección das solucións técnicas e do equipamento foi ditada polo cliente. Así, a propia especificación técnica, despois de todas as aprobacións:

Baseado nun único ordenador de placa vim2 facer un probador de velocidade para conexións lte mediante módems Huawei e3372h - 153 varios operadores de telecomunicacións (de un a n). Tamén é necesario recibir as coordenadas dun receptor GPS conectado mediante UART. Facer medicións de velocidade utilizando o servizo www.speedtest.net e poñelos nunha mesa como:

Proba de velocidade simultánea en varios módems LTE

Táboa en formato csv. A continuación, envíe este sinal por correo electrónico cada 6 horas. En caso de erros, faga parpadear o LED que está conectado ao GPIO.

Describín as especificacións técnicas en forma libre, despois de moitas aprobacións. Pero o significado da tarefa xa é visible. Deuse unha semana para todo. Pero en realidade durou tres semanas. Isto é tendo en conta o feito de que o fixen só despois do meu traballo principal e os fins de semana.

Aquí quero chamar unha vez máis a atención sobre o feito de que o cliente acordou previamente o uso do servizo e hardware de medición de velocidade, o que limitou moito as miñas capacidades. O orzamento tamén era limitado, polo que non se comprou nada especial. Entón tivemos que xogar con estas regras.

Arquitectura e desenvolvemento

O esquema é sinxelo e obvio. Polo tanto, deixareio sen ningún comentario especial.

Proba de velocidade simultánea en varios módems LTE

Decidín implementar todo o proxecto en python, a pesar de que non tiña ningunha experiencia no desenvolvemento desta linguaxe. Escollíno porque había unha morea de exemplos e solucións preparadas que poderían acelerar o desenvolvemento. Por iso, pídolles a todos os programadores profesionais que non reprendan a miña primeira experiencia de desenvolvemento en python, e sempre estou feliz de escoitar críticas construtivas para mellorar as miñas habilidades.

Tamén no proceso descubrín que Python ten dúas versións en execución 2 e 3, polo que me decidín pola terceira.

Nodos de hardware

Placa única vim2

Entregáronme un ordenador de placa única como máquina principal vim2

Proba de velocidade simultánea en varios módems LTE

Un procesador multimedia excelente e potente para unha casa intelixente e SMART-TV, pero extremadamente inadecuado para esta tarefa ou, digamos, pouco axeitado. Por exemplo, o seu sistema operativo principal é Android e Linux é un sistema operativo secundario e, en consecuencia, ninguén garante o funcionamento de alta calidade de todos os nodos e controladores baixo Linux. E supoño que algúns dos problemas estaban relacionados cos controladores USB desta plataforma, polo que os módems non funcionaron como se esperaba nesta placa. Tamén conta cunha documentación moi pobre e dispersa, polo que cada operación levaba moito tempo escavando polos peiraos. Incluso o traballo normal con GPIO levou moito sangue. Por exemplo, levoume varias horas configurar o LED. Pero, para ser obxectivos, fundamentalmente non era importante que tipo de placa única era, o principal era que funcionase e había portos USB.

En primeiro lugar, necesito instalar Linux nesta placa. Para non percorrer a documentación salvaxe para todos, e tamén para aqueles que se ocuparán deste sistema de placa única, escribo este capítulo.

Hai dúas opcións para instalar Linux: nunha tarxeta SD externa ou nunha MMC interna. Pasei unha noite intentando descubrir como facelo funcionar coa tarxeta, así que decidín instalalo na MMC, aínda que sen dúbida sería moito máis fácil traballar cunha tarxeta externa.

Sobre o firmware torto contado aquí. Traduzo de estraño ao ruso. Para flashear a placa, teño que conectar o hardware UART. Conectado do seguinte xeito.

  • Pin da ferramenta GND: <—> Pin17 do GPIO de VIM
  • Pin da ferramenta TXD: <—> Pin18 do GPIO de VIM (Linux_Rx)
  • Pin da ferramenta RXD: <—> Pin19 do GPIO de VIM (Linux_Tx)
  • Pin da ferramenta VCC: <—> Pin20 do GPIO de VIM

Proba de velocidade simultánea en varios módems LTE

Despois diso, descarguei o firmware por iso. Versión específica de firmware VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Para cargar este firmware, necesito utilidades. Máis detalles sobre isto aquí. Non probei a flashear en Windows, pero teño que dicirlle algunhas palabras sobre o firmware en Linux. En primeiro lugar, instalarei as utilidades segundo as instrucións.

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

Aaand... Non funciona nada. Pasei un par de horas editando os scripts de instalación para que todo se instalase correctamente. Non lembro o que fixen alí, pero tamén había ese circo con cabalos. Así que teña coidado. Pero sen estas utilidades non ten sentido torturar máis vim2. É mellor non meterse con el en absoluto!

Despois de sete círculos do inferno, configuración e instalación de scripts, recibín un paquete de utilidades de traballo. Conectei a placa mediante USB ao meu ordenador Linux e tamén conectei o UART segundo o diagrama anterior.
Estou configurando o meu terminal minicom favorito para unha velocidade de 115200, sen control de erros de hardware e software. E imos comezar.

Proba de velocidade simultánea en varios módems LTE

Ao cargar VIM2 no terminal UART, premo unha tecla, como a barra de espazo, para deter a carga. Despois de aparecer a liña

kvim2# 

Intro o comando:

kvim2# run update

No host desde o que estamos a cargar, executo:

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

Iso é todo, uf. Comprobei, hai Linux no taboleiro. Inicio de sesión/contrasinal khadas:khadas.

Despois diso, algunhas configuracións iniciais menores. Para seguir traballando, desactivo o contrasinal para sudo (si, non é seguro, pero cómodo).

sudo visudo

Edito a liña no formulario e gardo

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

Despois cambio a localización actual para que a hora sexa en Moscova, senón será en Greenwich.

sudo timedatectl set-timezone Europe/Moscow

ou

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

Se che resulta difícil, non uses esta placa; Raspberry Pi é mellor. Sinceramente.

Módem Huawei e3372h – 153

Este módem foi unha importante fonte de sangue para min e, de feito, converteuse no pescozo de botella de todo o proxecto. En xeral, o nome "módem" para estes dispositivos non reflicte en absoluto a esencia do traballo: esta é unha combinación poderosa, esta peza de hardware ten un dispositivo composto que pretende ser un CD-ROM para instalar controladores, e despois cambia ao modo de tarxeta de rede.

Arquitectónicamente, desde o punto de vista dun usuario de Linux, despois de todos os axustes, ten o seguinte aspecto: despois de conectar o módem, teño unha interface de rede eth*, que a través de dhcp recibe o enderezo IP 192.168.8.100, e a pasarela predeterminada. é 192.168.8.1.

E o momento máis importante! Este modelo de módem non pode funcionar no modo módem, que se controla mediante comandos AT. Todo sería moito máis sinxelo, crear conexións PPP para cada módem e despois operar con eles. Pero no meu caso, "el mesmo" (máis precisamente, un mergullo de Linux segundo as regras de udev), crea unha interface eth e asígnalle un enderezo IP a través de dhcp.

Para evitar máis confusións, suxiro esquecer a palabra "módem" e dicir tarxeta de rede e pasarela, porque en esencia, é como conectar unha nova tarxeta de rede cunha pasarela.
Cando hai un módem, isto non causa ningún problema especial, pero cando hai máis de un, é dicir, n pezas, xorde a seguinte imaxe de rede.

Proba de velocidade simultánea en varios módems LTE

É dicir, n tarxetas de rede, co mesmo enderezo IP, cada unha coa mesma pasarela predeterminada. Pero de feito, cada un deles está conectado ao seu propio operador.

Inicialmente, tiña unha solución sinxela: usar o comando ifconfig ou ip, apagar todas as interfaces e simplemente activar unha e probala. A solución foi boa para todos, excepto que durante os momentos de cambio non puiden conectarme ao dispositivo. E como o cambio é frecuente e rápido, en realidade non tiven a oportunidade de conectarme.

Polo tanto, escollín o camiño de cambiar manualmente os enderezos IP dos módems e despois dirixir o tráfico mediante a configuración de enrutamento.

Proba de velocidade simultánea en varios módems LTE

Este non foi o final dos meus problemas cos módems: en caso de problemas de alimentación, caíanse e requería unha boa fonte de alimentación estable para o concentrador USB. Resolvín este problema soldando a enerxía directamente ao concentrador. Outro problema que atopei e que arruinou todo o proxecto: despois dun reinicio ou arranque en frío do dispositivo, non se detectaron todos os módems e non sempre, e non puiden determinar por que ocorreu isto e con que algoritmo. Pero primeiro o primeiro.

Para que o módem funcione correctamente, instalei o paquete usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Despois diso, despois da conexión, o módem será detectado e configurado correctamente polo subsistema udev. Comprobo simplemente conectando o módem e asegurándome de que aparece a rede.
Outro problema que non puiden solucionar: como podo obter o nome do operador co que estamos traballando deste módem? O nome do operador está contido na interface web do módem en 192.168.8.1. Esta é unha páxina web dinámica que recibe datos a través de solicitudes Ajax, polo que non funcionará simplemente obter a páxina e analizar o nome. Entón comecei a mirar como desenvolver unha páxina web, etc., e decateime de que estaba facendo algún tipo de tontería. Como resultado, cuspir e o operador comezou a recibir usando a propia API Speedtest.

Sería moito máis doado se o módem tivese acceso mediante comandos AT. Sería posible reconfiguralo, crear unha conexión ppp, asignar unha IP, conseguir un operador de telecomunicacións, etc. Pero por desgraza, estou traballando co que me deron.

GPS

O receptor GPS que me regalaron tiña unha interface UART e potencia. Non era a mellor solución, pero aínda así era viable e sinxela. O receptor parecía algo así.

Proba de velocidade simultánea en varios módems LTE

Para ser honesto, esta era a primeira vez que traballaba cun receptor GPS, pero como esperaba, todo estaba pensado para nós hai moito tempo. Entón só usamos solucións preparadas.

Primeiro, habilito uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) para conectar o GPS.

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

Despois comprobo o éxito da operación.

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

Este comando aparentemente edita o devtree sobre a marcha, o que é moi cómodo.

Despois do éxito desta operación, reinicie e instale o daemon GPS.

khadas@Khadas:~$ sudo reboot

Instalación do daemon GPS. Instalo todo e córtoo inmediatamente para máis configuración.

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

Editando o ficheiro de configuración.

sudo vim /etc/default/gpsd

Estou instalando un UART no que se colgará o GPS.

DEVICES="/dev/ttyS4"

E entón acendemos todo e comezamos.

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

Despois diso, conecto o GPS.

Proba de velocidade simultánea en varios módems LTE

O cable do GPS está nas miñas mans, os cables do depurador UART son visibles baixo os meus dedos.

Reinicio e comprobo o funcionamento do GPS usando o programa gpsmon.

Proba de velocidade simultánea en varios módems LTE

Non podes ver os satélites nesta captura de pantalla, pero podes ver a comunicación co receptor GPS, e isto significa que todo está ben.

En Python, probei moitas opcións para traballar con este daemon, pero decidín a que funcionaba correctamente con Python 3.

Instalo a biblioteca necesaria.

sudo -H pip3 install gps3 

E esculpo o código de traballo.

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 necesito obter coordenadas, faise coa seguinte chamada:

longitude, latitude = getPositionData(agps_thread)

E dentro de 1-10 segundos obterei a coordenada ou non. Si, tiven dez intentos para obter coordenadas. Non é óptimo, torto e torcido, pero funciona. Decidín facelo porque o GPS pode ter unha mala recepción e non sempre recibir datos. Se esperas a recibir datos, se traballas nunha sala remota, o programa conxelarase neste lugar. Polo tanto, implementei esta opción pouco elegante.

En principio, se houbese máis tempo, sería posible recibir datos do GPS directamente a través de UART, analizalos nun fío separado e traballar con el. Pero non había tempo, de aí o código brutalmente feo. E si, non me avergoño.

Diodo emisor de luz

Conectar o LED foi sinxelo e difícil ao mesmo tempo. A principal dificultade é que o número de pin no sistema non se corresponde co número de pin do encerado e porque a documentación está escrita coa man esquerda. Para comparar o número de pin do hardware e o número de pin no SO, cómpre executar o comando:

gpio readall

Mostrarase unha táboa de correspondencia de pins no sistema e no taboleiro. Despois do cal xa podo operar o pin no propio sistema operativo. No meu caso, o LED está conectado GPIOH_5.

Proba de velocidade simultánea en varios módems LTE

Cambio o pin GPIO ao modo de saída.

gpio -g mode 421 out

Escribo cero.

gpio -g write 421 0

Anoto un.

gpio -g write 421 1

Proba de velocidade simultánea en varios módems LTE
Todo está iluminado, despois de escribir "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)

Agora, en caso de erros, chamo error_blink() e o LED parpadeará moi ben.

Nodos de software

API Speedtest

É unha gran alegría que o servizo speedtest.net teña a súa propia API de python, podes ver Github.

O bo é que hai códigos fonte que tamén se poden ver. Como traballar con esta API (exemplos sinxelos) pódese atopar en sección pertinente.

Instalo a biblioteca de Python co seguinte comando.

sudo -H pip3 install speedtest-cli

Por exemplo, pode incluso instalar un probador de velocidade en Ubuntu directamente desde o software. Esta é a mesma aplicación Python, que se pode iniciar directamente desde a consola.

sudo apt install speedtest-cli -y

E mide a túa velocidade de 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

Como resultado, igual que eu fixen. Tiven que entrar nos códigos fonte desta proba de velocidade para implementalos máis plenamente no meu proxecto. Unha das tarefas máis importantes é obter o nome do operador de telecomunicacións para substituílo na placa.

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"
#тут идет запись в файл логов

Tamén aquí non todo resultou tan sinxelo, aínda que parecería moito máis sinxelo. Inicialmente, o parámetro servidores era igual a [], din, escolle o mellor servidor. Como resultado, tiña servidores aleatorios e, como podes supoñer, velocidade variable. Este é un tema bastante complexo, usar un servidor fixo, se é así, estático ou dinámico, require investigación. Pero aquí tes un exemplo de gráficos de medición de velocidade para un operador de Beeline cando selecciona de forma dinámica un servidor de proba e un fixo estáticamente.

Proba de velocidade simultánea en varios módems LTE
O resultado de medir a velocidade ao elixir un servidor dinámico.

Proba de velocidade simultánea en varios módems LTE
O resultado da proba de velocidade, cun servidor rigorosamente seleccionado.

Durante a proba, hai "pelo" en ambos os lugares e hai que eliminalo mediante métodos matemáticos. Pero cun servidor fixo é un pouco menos e a amplitude é máis estable.
En xeral, este é un lugar de gran investigación. E mediría a velocidade do meu servidor usando a utilidade iperf. Pero seguimos as especificacións técnicas.

Envío de correo e erros

Para enviar correo, probei varias ducias de opcións diferentes, pero ao final decidín as seguintes. Rexistrei unha caixa de correo en Yandex e despois tomei Este é un exemplo de envío de correo. Comprobeino e implementeino no programa. Este exemplo examina varias opcións, incluído o envío desde gmail, etc. Non quería molestarme en configurar o meu servidor de correo e non tiña tempo para iso, pero como resultou máis tarde, tamén foi en balde.

Os rexistros foron enviados segundo o planificador, se hai conexión, cada 6 horas: ás 00h, 06h, 12h e 18h. Enviouno do seguinte xeito.

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

Tamén se enviaron erros inicialmente. Para comezar, acumulábanse na lista, e despois enviábanse tamén mediante o planificador, se había conexión. Non obstante, xurdiron problemas co feito de que Yandex ten un límite no número de mensaxes enviadas ao día (isto é dor, tristeza e humillación). Dado que podía haber un gran número de erros mesmo por minuto, tivemos que abandonar o envío de erros por correo. Polo tanto, teña en conta ao enviar automaticamente información sobre tal problema a través dos servizos de Yandex.

Servidor de comentarios

Para ter acceso a unha peza de hardware remota e poder personalizala e reconfigurala, necesitaba un servidor externo. En xeral, para ser xustos, sería correcto enviar todos os datos ao servidor e construír todos os fermosos gráficos na interface web. Pero non todos á vez.

Para VPS escollín ruvds.com. Podes tomar o servidor máis sinxelo. E, en xeral, para os meus fins sería suficiente. Pero como non paguei o servidor do meu peto, decidín levalo cunha pequena reserva para que abondase con implantar unha interface web, o noso propio servidor SMTP, VPN, etc. Ademais, poderás configurar un bot de Telegram e non ter problemas para bloquealo. Polo tanto, escollín Amsterdam e os seguintes parámetros.

Proba de velocidade simultánea en varios módems LTE

Como método de comunicación co hardware, vim2 escolleu unha conexión ssh inversa e, como demostrou a práctica, non é a mellor. Se se perde a conexión, o servidor mantén o porto e é imposible conectarse a través del durante algún tempo. Polo tanto, aínda é mellor usar outros métodos de comunicación, por exemplo VPN. No futuro quería cambiar a VPN, pero non tiña tempo.

Non entrarei en detalles sobre a configuración dun cortalumes, a restrición de dereitos, a desactivación de conexións ssh root e outros truismos sobre a configuración dun VPS. Gustaríame crer que xa o sabes todo. Para unha conexión remota, creo un novo usuario no servidor.

adduser vimssh

Xero claves de conexión ssh no noso hardware.

ssh-keygen

E cópioos no noso servidor.

ssh-copy-id [email protected]

No noso hardware, creo unha conexión ssh inversa automática en cada inicio.

[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

Preste atención ao porto 8083: determina que porto usarei para conectarme mediante ssh inverso. Engádeo ao inicio e comeza.

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

Incluso podes ver o estado:

sudo systemctl status autossh.service

Agora, no noso servidor VPS, se executamos:

ssh -p 8083 khadas@localhost

Despois chego á miña peza de proba de hardware. E desde o hardware tamén podo enviar rexistros e calquera dato a través de ssh ao meu servidor, o que é moi cómodo.

Poñer todo isto en conxunto

Proba de velocidade simultánea en varios módems LTE
Acendendo, imos comezar o desenvolvemento e a depuración

Uf, ben, iso é todo, describín todos os nodos. Agora toca xuntalo todo. Podes ver o código aquí.

Un punto importante co código: este proxecto pode non comezar así, porque foi feito a medida para unha tarefa específica, dunha arquitectura específica. Aínda que estou dando o código fonte, aínda vou explicar aquí as cousas máis valiosas, xusto no texto, se non, é completamente incomprensible.

Ao principio, inicializo gps, gpio e lanzo un fío de programación separado.

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

O programador é bastante sinxelo: mira para ver se chegou o momento de enviar mensaxes e cal é o estado de erro actual. Se hai unha bandeira de erro, acendemos o 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)

A parte máis difícil deste proxecto é manter a conexión ssh inversa para cada proba. Cada proba implica volver configurar a pasarela predeterminada e o servidor DNS. Xa que ninguén le de todos os xeitos, saiba que o tren non circula sobre carrís de madeira. Quen atope o ovo de Pascua recibe uns doces.

Para iso, creo unha táboa de enrutamento separada -set-mark 0x2 e unha regra para redirixir o tráfico.

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

Podes aprender máis sobre como funciona lido neste artigo.

Despois do cal entro nun bucle interminable, onde cada vez obtemos unha lista de módems conectados (para saber se cambiou de súpeto a configuración da rede).

network_list = getNetworklist()

Obter unha lista de interfaces de rede é bastante sinxelo.

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

Despois de recibir a lista, configurei enderezos IP para todas as interfaces, como mostrei na imaxe do capítulo sobre o módem.

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

Entón simplemente paso por cada interface nun bucle. E configuro cada interface.

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

Comprobo a funcionalidade da interface, se non hai rede, entón xero erros. Se hai unha rede, é hora de actuar!

Aquí configuro o enrutamento ssh a esta interface (se non se fixo), envío erros ao servidor se chegou o momento, envío rexistros e, finalmente, executo un speedtest e gardo os rexistros nun ficheiro 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()
#и далее тестируем скорость и сохраняем логи. 

Paga a pena mencionar a función de configurar ssh inverso.

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, por suposto, cómpre engadir toda esta beleza ao inicio. Para iso creo un ficheiro:

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

E escribo nel:

[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

Active a carga automática e comezo!

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

Agora podo ver rexistros do que está a suceder usando o comando:

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

Descubrimentos

Ben, agora o máis importante é, que pasou como resultado? Aquí tes algúns gráficos que conseguín capturar durante o proceso de desenvolvemento e depuración. Os gráficos foron construídos usando gnuplot co seguinte 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"

A primeira experiencia foi coa operadora de Tele2, que realicei durante varios días.

Proba de velocidade simultánea en varios módems LTE

Aquí usei un servidor de medición dinámica. As medicións de velocidade funcionan, pero oscilan moito, pero aínda é visible algún valor medio, e isto pódese obter filtrando os datos, por exemplo, cunha media móbil.

Despois construín unha serie de gráficos para outros operadores de telecomunicacións. Neste caso, xa había un servidor de probas, e os resultados tamén foron moi interesantes.

Proba de velocidade simultánea en varios módems LTE

Proba de velocidade simultánea en varios módems LTE

Proba de velocidade simultánea en varios módems LTE

Proba de velocidade simultánea en varios módems LTE

Como podedes ver, o tema é moi extenso para a investigación e procesamento destes datos, e claramente non dura un par de semanas de traballo. Pero…

Resultado do traballo

O traballo rematou bruscamente por circunstancias alleas ao meu control. Unha das debilidades deste proxecto, na miña opinión subxectiva, era o módem, que realmente non quería funcionar simultaneamente con outros módems, e facía tales trucos cada vez que se cargaba. Para estes efectos, hai unha gran cantidade de outros modelos de módem; normalmente xa están en formato Mini PCI-e e están instalados dentro do dispositivo e son moito máis fáciles de configurar. Pero esa é unha historia completamente diferente. O proxecto foi interesante e alegreime moito de poder participar nel.

Proba de velocidade simultánea en varios módems LTE

Fonte: www.habr.com

Engadir un comentario