Teste de velocidade simultâneo em vários modems LTE

Durante a quarentena, fui convidado a participar do desenvolvimento de um dispositivo de medição de velocidade de modems LTE para diversas operadoras de celular.

Teste de velocidade simultâneo em vários modems LTE

O cliente pretendia avaliar a velocidade de vários operadores de telecomunicações em diferentes localizações geográficas para poder perceber qual o operador móvel mais adequado para ele ao instalar equipamentos através de uma ligação LTE, por exemplo, para transmissões de vídeo. Ao mesmo tempo, o problema tinha que ser resolvido da forma mais simples e barata possível, sem equipamentos caros.

Direi desde já que a tarefa não é das mais simples e exige muito conhecimento, direi quais problemas encontrei e como os resolvi. Então vamos.

Nota

Medir a velocidade de uma conexão LTE é uma questão muito complexa: você precisa escolher o equipamento e a técnica de medição corretos, além de ter um bom conhecimento da topologia e operação da rede celular. Além disso, a velocidade pode ser influenciada por vários fatores: o número de assinantes em uma célula, as condições climáticas, até mesmo de célula para célula a velocidade pode variar drasticamente devido à topologia da rede. Em geral, este é um problema com um grande número de incógnitas e somente uma operadora de telecomunicações pode resolvê-lo corretamente.

Inicialmente, o cliente queria apenas conduzir o entregador com os telefones das operadoras, fazer as medições diretamente no telefone e depois anotar os resultados da medição de velocidade em um caderno. Minha solução para medir a velocidade de redes LTE, embora não seja a ideal, resolve o problema.

Por falta de tempo, tomei decisões não pela comodidade ou praticidade, mas pela rapidez de desenvolvimento. Por exemplo, o ssh reverso foi usado para acesso remoto, em vez da VPN mais prática, para economizar tempo na configuração do servidor e de cada cliente individual.

Termos de Referência

Como afirmado no artigo Sem especificações técnicas: por que o cliente não quer: Não trabalhe sem especificações técnicas! Nunca, em lugar nenhum!

A tarefa técnica foi bastante simples, vou expandi-la um pouco para o entendimento do usuário final. A escolha das soluções técnicas e equipamentos foi ditada pelo cliente. Então, a própria especificação técnica, após todas as aprovações:

Baseado em um computador de placa única vim2 faça um testador de velocidade para conexões LTE via modems HHuawei e3372h - 153 vários operadores de telecomunicações (de um a n). Também é necessário receber coordenadas de um receptor GPS conectado via UART. Faça medições de velocidade usando o serviço www.speedtest.net e coloque-os em uma tabela como:

Teste de velocidade simultâneo em vários modems LTE

Tabela em formato csv. Em seguida, envie este sinal por e-mail a cada 6 horas. Em caso de erros, pisque o LED que está conectado ao GPIO.

Descrevi as especificações técnicas de forma livre, após muitas aprovações. Mas o significado da tarefa já é visível. Foi dada uma semana para tudo. Mas, na realidade, durou três semanas. Isso levando em consideração o fato de que eu fazia isso somente depois do meu trabalho principal e nos finais de semana.

Quero aqui mais uma vez chamar a atenção para o fato de o cliente ter concordado previamente com a utilização do serviço e hardware de medição de velocidade, o que limitou bastante minhas capacidades. O orçamento também era limitado, então nada de especial foi comprado. Então tivemos que seguir essas regras.

Arquitetura e desenvolvimento

O esquema é simples e óbvio. Portanto, deixarei sem comentários especiais.

Teste de velocidade simultâneo em vários modems LTE

Decidi implementar todo o projeto em python, apesar de não ter nenhuma experiência em desenvolvimento nesta linguagem. Eu escolhi porque havia vários exemplos e soluções prontas que poderiam acelerar o desenvolvimento. Portanto, peço a todos os programadores profissionais que não repreendam minha primeira experiência de desenvolvimento em python, e fico sempre feliz em ouvir críticas construtivas para melhorar minhas habilidades.

Também no processo descobri que o python tem duas versões em execução 2 e 3, como resultado optei pela terceira.

Nós de hardware

Vim2 de placa única

Recebi um computador de placa única como minha máquina principal vim2

Teste de velocidade simultâneo em vários modems LTE

Um processador de mídia excelente e poderoso para uma casa inteligente e SMART-TV, mas extremamente inadequado para esta tarefa, ou, digamos, pouco adequado. Por exemplo, seu sistema operacional principal é o Android e o Linux é um sistema operacional secundário e, portanto, ninguém garante a operação de alta qualidade de todos os nós e drivers no Linux. E presumo que alguns dos problemas estavam relacionados aos drivers USB desta plataforma, portanto os modems não funcionaram como esperado nesta placa. Também possui documentação muito pobre e dispersa, de modo que cada operação demorava muito tempo vasculhando as docas. Até mesmo o trabalho comum com GPIO exigia muito sangue. Por exemplo, levei várias horas para configurar o LED. Mas, para ser objetivo, não importava fundamentalmente que tipo de placa única era, o principal é que funcionasse e houvesse portas USB.

Primeiro, preciso instalar o Linux nesta placa. Para não vasculhar a documentação para todos, e também para aqueles que vão lidar com esse sistema de placa única, estou escrevendo este capítulo.

Existem duas opções para instalar o Linux: em um cartão SD externo ou em um MMC interno. Passei uma noite tentando descobrir como fazer funcionar com a placa, então resolvi instalar no MMC, embora sem dúvida seria muito mais fácil trabalhar com uma placa externa.

Sobre o firmware contado torto aqui. Eu traduzo do estranho para o russo. Para atualizar a placa, preciso conectar o hardware UART. Conectei como segue.

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

Teste de velocidade simultâneo em vários modems LTE

Depois disso, baixei o firmware por isso. Versão específica do firmware VIM1_Ubuntu-server-bionic_Linux-4.9_arm64_EMMC_V20191231.

Para fazer upload deste firmware, preciso de utilitários. Mais detalhes sobre isso aqui. Não tentei atualizá-lo no Windows, mas preciso contar algumas palavras sobre firmware no Linux. Primeiro, instalarei os utilitários de acordo com as instruções.

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

Eaand... Nada funciona. Passei algumas horas editando os scripts de instalação para que tudo fosse instalado corretamente para mim. Não me lembro o que fiz lá, mas também tinha aquele circo com cavalos. Por isso tem cuidado. Mas sem esses utilitários não faz sentido torturar ainda mais o vim2. É melhor não mexer com ele de jeito nenhum!

Depois de sete círculos infernais, configuração e instalação de scripts, recebi um pacote de utilitários funcionais. Conectei a placa via USB ao meu computador Linux e também conectei o UART conforme o diagrama acima.
Estou configurando meu terminal minicom favorito para uma velocidade de 115200, sem controle de erros de hardware e software. E vamos começar.

Teste de velocidade simultâneo em vários modems LTE

Ao carregar o VIM2 no terminal UART, pressiono uma tecla, como a barra de espaço, para interromper o carregamento. Depois que a linha aparecer

kvim2# 

Eu insiro o comando:

kvim2# run update

No host do qual estamos carregando, eu executo:

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

É isso, ufa. Eu verifiquei, há Linux na placa. Login/senha khadas:khadas.

Depois disso, algumas pequenas configurações iniciais. Para trabalhos futuros, desativo a senha do sudo (sim, não é seguro, mas é conveniente).

sudo visudo

Eu edito a linha no formulário e salvo

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

Então mudo o local atual para que a hora seja em Moscou, caso contrário, será em Greenwich.

sudo timedatectl set-timezone Europe/Moscow

ou

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

Se você achar difícil, não use esta placa; Raspberry Pi é melhor. Honestamente.

Modem Huawei e3372h – 153

Esse modem foi uma fonte significativa de sangue para mim e, na verdade, tornou-se o gargalo de todo o projeto. Em geral, o nome “modem” para esses dispositivos não reflete em nada a essência do trabalho: esta é uma combinação poderosa, esta peça de hardware possui um dispositivo composto que finge ser um CD-ROM para instalar drivers, e depois muda para o modo de placa de rede.

Arquitetonicamente, do ponto de vista de um usuário Linux, depois de todas as configurações, fica assim: após conectar o modem, tenho uma interface de rede eth*, que via dhcp recebe o endereço IP 192.168.8.100, e o gateway padrão é 192.168.8.1.

E o momento mais importante! Este modelo de modem não pode funcionar no modo modem, que é controlado por comandos AT. Tudo seria muito mais simples, criar conexões PPP para cada modem e depois operar com elas. Mas no meu caso, “ele mesmo” (mais precisamente, um mergulhador Linux de acordo com as regras do udev), cria uma interface eth e atribui um endereço IP a ela via dhcp.

Para evitar mais confusão, sugiro esquecer a palavra “modem” e dizer placa de rede e gateway, porque, em essência, é como conectar uma nova placa de rede a um gateway.
Quando existe um modem, isto não causa quaisquer problemas especiais, mas quando existe mais do que um, nomeadamente n peças, surge a seguinte imagem de rede.

Teste de velocidade simultâneo em vários modems LTE

Ou seja, n placas de rede, com o mesmo endereço IP, cada uma com o mesmo gateway padrão. Mas, na verdade, cada um deles está conectado à sua operadora.

Inicialmente, tive uma solução simples: usando o comando ifconfig ou ip, desligue todas as interfaces e simplesmente ligue uma de cada vez e teste-a. A solução foi boa para todos, exceto que durante os momentos de troca não consegui me conectar ao aparelho. E como a troca é frequente e rápida, na verdade não tive oportunidade de me conectar.

Portanto, escolhi o caminho de alterar manualmente os endereços IP dos modems e, em seguida, direcionar o tráfego usando as configurações de roteamento.

Teste de velocidade simultâneo em vários modems LTE

Este não foi o fim dos meus problemas com modems: em caso de problemas de energia, eles caíram e foi necessária uma fonte de alimentação boa e estável para o hub USB. Resolvi esse problema soldando a energia diretamente no hub. Outro problema que encontrei e que estragou todo o projeto: após uma reinicialização ou inicialização a frio do dispositivo, nem todos os modems foram detectados e nem sempre, e não consegui determinar por que isso aconteceu e por qual algoritmo. Mas primeiro as primeiras coisas.

Para que o modem funcione corretamente, instalei o pacote usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

Depois disso, após a conexão, o modem será detectado e configurado corretamente pelo subsistema udev. Eu verifico simplesmente conectando o modem e certificando-me de que a rede aparece.
Outro problema que não consegui resolver: como posso obter deste modem o nome da operadora com a qual trabalhamos? O nome da operadora está contido na interface web do modem em 192.168.8.1. Esta é uma página da web dinâmica que recebe dados por meio de solicitações Ajax, portanto, simplesmente wget a página e analisar o nome não funcionará. Então comecei a procurar como desenvolver uma página web, etc., e percebi que estava fazendo algum tipo de bobagem. Como resultado, ele cuspiu e a operadora passou a receber usando a própria API Speedtest.

Muito seria mais fácil se o modem tivesse acesso através de comandos AT. Seria possível reconfigurá-lo, criar uma conexão ppp, atribuir um IP, conseguir uma operadora de telecomunicações, etc. Mas, infelizmente, estou trabalhando com o que me foi dado.

GPS

O receptor GPS que recebi tinha uma interface UART e alimentação. Não era a melhor solução, mas ainda assim era viável e simples. O receptor era mais ou menos assim.

Teste de velocidade simultâneo em vários modems LTE

Para ser sincero, foi a primeira vez que trabalhei com um receptor GPS, mas como eu esperava, tudo foi pensado para nós há muito tempo. Então, usamos apenas soluções prontas.

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

Depois verifico o sucesso da operação.

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

Este comando aparentemente edita o devtree instantaneamente, o que é muito conveniente.

Após o sucesso desta operação, reinicie e instale o daemon GPS.

khadas@Khadas:~$ sudo reboot

Instalando o daemon GPS. Eu instalo tudo e desligo imediatamente para posterior configuração.

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 arquivo de configurações.

sudo vim /etc/default/gpsd

Estou instalando um UART no qual o GPS ficará pendurado.

DEVICES="/dev/ttyS4"

E então ligamos tudo e começamos.

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

Depois disso, conecto o GPS.

Teste de velocidade simultâneo em vários modems LTE

O fio GPS está em minhas mãos, os fios do depurador UART estão visíveis sob meus dedos.

Eu reinicio e verifico o funcionamento do GPS usando o programa gpsmon.

Teste de velocidade simultâneo em vários modems LTE

Você não pode ver os satélites nesta captura de tela, mas pode ver a comunicação com o receptor GPS, e isso significa que está tudo bem.

Em python, tentei várias opções para trabalhar com esse daemon, mas optei por aquela que funcionava corretamente com python 3.

Eu instalo a biblioteca necessária.

sudo -H pip3 install gps3 

E eu esculpo o código de trabalho.

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 eu precisar obter coordenadas, isso é feito com a seguinte chamada:

longitude, latitude = getPositionData(agps_thread)

E dentro de 1 a 10 segundos obterei a coordenada ou não. Sim, tive dez tentativas para obter coordenadas. Não é o ideal, é torto e torto, mas funciona. Decidi fazer isso porque o GPS pode ter má recepção e nem sempre receber dados. Se você esperar para receber os dados, se trabalhar em uma sala remota, o programa irá congelar neste local. Portanto, implementei esta opção deselegante.

A princípio, se houvesse mais tempo, seria possível receber dados do GPS diretamente via UART, analisá-los em um thread separado e trabalhar com eles. Mas não houve tempo algum, daí o código brutalmente feio. E sim, não tenho vergonha.

Diodo emissor de luz

Conectar o LED foi simples e difícil ao mesmo tempo. A principal dificuldade é que o número do pino no sistema não corresponde ao número do pino na placa e porque a documentação é escrita com a mão esquerda. Para comparar o número do pino do hardware e o número do pino no sistema operacional, você precisa executar o comando:

gpio readall

Uma tabela de correspondência de pins no sistema e no quadro será exibida. Depois disso já posso operar o pino no próprio sistema operacional. No meu caso, o LED está conectado a GPIOH_5.

Teste de velocidade simultâneo em vários modems LTE

Eu mudo o pino GPIO para o modo de saída.

gpio -g mode 421 out

Eu escrevo zero.

gpio -g write 421 0

Eu escrevo um.

gpio -g write 421 1

Teste de velocidade simultâneo em vários modems LTE
Tudo está aceso, depois de escrever “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, em caso de erros, chamo error_blink() e o LED piscará lindamente.

Nós de software

API de teste rápido

É uma grande alegria que o serviço speedtest.net tenha sua própria API python, você pode dar uma olhada Github.

O bom é que existem códigos-fonte que também podem ser visualizados. Como trabalhar com esta API (exemplos simples) pode ser encontrado em seção relevante.

Eu instalo a biblioteca python com o seguinte comando.

sudo -H pip3 install speedtest-cli

Por exemplo, você pode até instalar um testador de velocidade no Ubuntu diretamente do software. Este é o mesmo aplicativo python, que pode ser iniciado diretamente do console.

sudo apt install speedtest-cli -y

E meça a velocidade da sua 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, assim como eu fiz. Tive que entrar nos códigos-fonte deste teste de velocidade para implementá-los de forma mais completa em meu projeto. Uma das tarefas mais importantes é obter o nome da operadora de telecomunicações 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"
#тут идет запись в файл логов

Também aqui tudo acabou por não ser tão simples, embora parecesse muito mais simples. Inicialmente, o parâmetro servidores era igual a [], dizem eles, escolha o melhor servidor. Como resultado, tive servidores aleatórios e, como você pode imaginar, velocidade variável. Este é um tema bastante complexo, utilizar um servidor fixo, se for o caso, estático ou dinâmico, requer pesquisa. Mas aqui está um exemplo de gráficos de medição de velocidade para um operador Beeline ao selecionar dinamicamente um servidor de teste e um servidor estaticamente fixo.

Teste de velocidade simultâneo em vários modems LTE
O resultado da medição da velocidade ao escolher um servidor dinâmico.

Teste de velocidade simultâneo em vários modems LTE
O resultado de testes de velocidade, com um servidor estritamente selecionado.

Durante o teste, há “pelo” em ambos os locais e precisa ser removido por métodos matemáticos. Mas com um servidor fixo é um pouco menor e a amplitude é mais estável.
Em geral, este é um local de grandes pesquisas. E eu mediria a velocidade do meu servidor usando o utilitário iperf. Mas nos atemos às especificações técnicas.

Envio de e-mail e erros

Para enviar e-mail, tentei várias dezenas de opções diferentes, mas no final decidi pela seguinte. Registrei uma caixa de correio no Yandex e depois peguei Este é um exemplo de envio de e-mail. Eu verifiquei e implementei no programa. Este exemplo examina várias opções, incluindo envio do Gmail, etc. Eu não queria me preocupar em configurar meu servidor de e-mail e não tinha tempo para isso, mas como descobri mais tarde, também foi em vão.

Os logs foram enviados de acordo com o agendador, se houver uma conexão, a cada 6 horas: às 00h, 06h, 12h e 18h. Enviou da seguinte forma.

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

Erros também foram enviados inicialmente. Para começar, eles eram acumulados na lista e depois enviados também pelo agendador, caso houvesse conexão. Porém, surgiram problemas com o fato de o Yandex ter um limite no número de mensagens enviadas por dia (isso é dor, tristeza e humilhação). Como pode haver um grande número de erros por minuto, tivemos que abandonar o envio de erros por correio. Portanto, lembre-se de enviar automaticamente informações sobre esse problema por meio dos serviços Yandex.

Servidor de comentários

Para ter acesso a um hardware remoto e poder personalizá-lo e reconfigurá-lo, eu precisava de um servidor externo. Em geral, para ser justo, seria correto enviar todos os dados para o servidor e construir todos os lindos gráficos na interface web. Mas não tudo ao mesmo tempo.

Para VPS eu escolhi ruvds. com. Você poderia pegar o servidor mais simples. E, em geral, para meus propósitos, isso seria suficiente. Mas como não paguei o servidor do meu próprio bolso, resolvi levá-lo com uma pequena reserva para que fosse suficiente se implantássemos uma interface web, nosso próprio servidor SMTP, VPN, etc. Além disso, ser capaz de configurar um bot do Telegram e não ter problemas com seu bloqueio. Portanto, escolhi Amsterdã e os seguintes parâmetros.

Teste de velocidade simultâneo em vários modems LTE

Como método de comunicação com o hardware, o vim2 escolheu uma conexão ssh reversa e, como a prática tem mostrado, não é a melhor. Se a conexão for perdida, o servidor retém a porta e é impossível conectar-se por meio dela por algum tempo. Portanto, é ainda melhor usar outros métodos de comunicação, por exemplo VPN. No futuro queria mudar para VPN, mas não tive tempo.

Não entrarei em detalhes sobre como configurar um firewall, restringir direitos, desabilitar conexões root ssh e outros truísmos da configuração de um VPS. Gostaria de acreditar que você já sabe tudo. Para uma conexão remota, crio um novo usuário no servidor.

adduser vimssh

Eu gero chaves de conexão ssh em nosso hardware.

ssh-keygen

E eu os copio para o nosso servidor.

ssh-copy-id [email protected]

Em nosso hardware, eu crio uma conexão SSH reversa automática a cada inicialização.

[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 atenção na porta 8083: ela determina qual porta usarei para conectar via ssh reverso. Adicione-o à inicialização e comece.

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

Você pode até ver o status:

sudo systemctl status autossh.service

Agora, em nosso servidor VPS, se executarmos:

ssh -p 8083 khadas@localhost

Então chego ao meu hardware de teste. E do hardware também posso enviar logs e quaisquer dados via ssh para o meu servidor, o que é muito conveniente.

Colocando tudo junto

Teste de velocidade simultâneo em vários modems LTE
Ligando, vamos começar o desenvolvimento e a depuração

Ufa, bem, é isso, descrevi todos os nós. Agora é hora de juntar tudo. Você pode ver o código aqui.

Um ponto importante com o código: Este projeto pode não começar assim, pois foi feito sob medida para uma tarefa específica, de uma arquitetura específica. Mesmo dando o código-fonte, ainda vou explicar o que há de mais valioso aqui, direto no texto, caso contrário fica completamente incompreensível.

No início, inicializo GPS, GPIO e inicio um thread de agendador separado.

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

O agendador é bastante simples: verifica se chegou a hora de enviar mensagens e qual é o status atual do erro. Se houver um sinalizador de erro, piscamos 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 mais difícil deste projeto é manter a conexão SSH reversa para cada teste. Cada teste envolve a reconfiguração do gateway padrão e do servidor DNS. Como ninguém lê mesmo, saiba que o trem não anda sobre trilhos de madeira. Quem encontrar o ovo de Páscoa ganha alguns doces.

Para fazer isso, crio uma tabela de roteamento separada -set-mark 0x2 e uma regra para redirecionar o tráfego.

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

Você pode aprender mais sobre como funciona leia neste artigo.

Depois disso, entro em um loop infinito, onde cada vez obtemos uma lista de modems conectados (para descobrir se a configuração da rede mudou repentinamente).

network_list = getNetworklist()

Obter uma lista de interfaces de rede é bastante simples.

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

Após receber a lista, configurei os endereços IP para todas as interfaces, conforme mostrei na figura do capítulo sobre 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")

Então eu simplesmente percorro cada interface em um loop. E eu 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'")

Verifico a funcionalidade da interface, se não houver rede, gero erros. Se existe uma rede, então é hora de agir!

Aqui eu configuro o roteamento ssh para esta interface (caso não tenha sido feito), envio erros para o servidor se chegar a hora, envio logs e por fim executo um speedtest e salvo os logs em um arquivo 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 ressaltar a função de configurar o ssh reverso.

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 claro, você precisa agregar toda essa beleza à startup. Para fazer isso eu crio um arquivo:

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

E eu escrevo nele:

[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

Eu ligo o carregamento automático e começo!

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

Agora posso ver os registros do que está acontecendo usando o comando:

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

Descobertas

Bem, agora o mais importante é: o que aconteceu como resultado? Aqui estão alguns gráficos que consegui capturar durante o processo de desenvolvimento e depuração. Os gráficos foram construídos usando gnuplot com o 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 experiência foi com a operadora Tele2, que conduzi durante vários dias.

Teste de velocidade simultâneo em vários modems LTE

Aqui usei um servidor de medição dinâmico. As medições de velocidade funcionam, mas flutuam muito, mas algum valor médio ainda é visível, e isso pode ser obtido filtrando os dados, por exemplo, com uma média móvel.

Mais tarde, construí vários gráficos para outras operadoras de telecomunicações. Neste caso, já existia um servidor de testes e os resultados também foram muito interessantes.

Teste de velocidade simultâneo em vários modems LTE

Teste de velocidade simultâneo em vários modems LTE

Teste de velocidade simultâneo em vários modems LTE

Teste de velocidade simultâneo em vários modems LTE

Como você pode ver, o tema é muito extenso para pesquisa e processamento desses dados e claramente não dura algumas semanas de trabalho. Mas…

Resultado do trabalho

O trabalho foi concluído abruptamente devido a circunstâncias fora do meu controle. Um dos pontos fracos deste projeto, na minha opinião subjetiva, era o modem, que realmente não queria funcionar simultaneamente com outros modems, e fazia esses truques toda vez que era carregado. Para isso, existe uma grande quantidade de outros modelos de modem, geralmente já estão no formato Mini PCI-e e são instalados dentro do dispositivo e são muito mais fáceis de configurar. Mas essa é uma história completamente diferente. O projeto foi interessante e fiquei muito feliz por poder participar dele.

Teste de velocidade simultâneo em vários modems LTE

Fonte: habr.com

Adicionar um comentário