Едновременен тест за скорост на няколко LTE модема

По време на карантина ми предложиха да участвам в разработването на устройство за измерване на скоростта на LTE модеми за няколко клетъчни оператора.

Едновременен тест за скорост на няколко LTE модема

Клиентът искаше да оцени скоростта на различни телекомуникационни оператори в различни географски местоположения, за да може да разбере кой клетъчен оператор е най-оптимален за него, когато инсталира оборудване, използващо LTE връзка, например за видео излъчвания. В същото време проблемът трябваше да бъде решен възможно най-просто и евтино, без скъпо оборудване.

Веднага ще кажа, че задачата не е най-простата и изискваща много знания; ще ви кажа какви проблеми срещнах и как ги реших. И така, да вървим.

Внимание

Измерването на скоростта на LTE връзка е много сложен въпрос: трябва да изберете правилното оборудване и техника за измерване, както и да имате добро разбиране на топологията и работата на клетъчната мрежа. Освен това скоростта може да бъде повлияна от няколко фактора: броя на абонатите в клетката, метеорологичните условия, дори от клетка до клетка скоростта може да варира драстично поради топологията на мрежата. Като цяло това е проблем с огромен брой неизвестни и само телеком оператор може да го реши правилно.

Първоначално клиентът просто искаше да кара куриера с телефоните на операторите, да направи измервания директно на телефона и след това да запише резултатите от измерването на скоростта в тетрадка. Моето решение за измерване на скоростта на lte мрежите, въпреки че не е идеално, решава проблема.

Поради липса на време взех решения не в полза на удобството или практичността, а в полза на скоростта на разработка. Например обратният ssh беше използван за отдалечен достъп, вместо по-практичната VPN, за да се спести време за настройка на сървъра и всеки отделен клиент.

Техническо задание

Както е посочено в статията Без технически спецификации: защо клиентът не го иска: Не работете без технически спецификации! Никога и никъде!

Техническата задача беше доста проста, ще я разширя малко за разбиране на крайния потребител. Изборът на технически решения и оборудване беше продиктуван от клиента. И така, самата техническа спецификация, след всички одобрения:

Базиран на едноплатков компютър vim2 направете тестер за скорост за lte връзки през H модемиuawei e3372h - 153 няколко телеком оператора (от един до n). Също така е необходимо да получите координати от GPS приемник, свързан чрез UART. Извършвайте измервания на скоростта с помощта на услугата www.speedtest.net и ги поставете в таблица като:

Едновременен тест за скорост на няколко LTE модема

Таблица в csv формат. След това изпращайте този знак по имейл на всеки 6 часа. В случай на грешки, мига светодиодът, който е свързан към GPIO.

Описах техническите характеристики в свободна форма, след много одобрения. Но смисълът на задачата вече е видим. За всичко беше дадена седмица. Но в действителност това продължи три седмици. Това като се вземе предвид факта, че правех това само след основната си работа и през почивните дни.

Тук още веднъж искам да обърна внимание на факта, че клиентът предварително се съгласи с използването на услугата и хардуера за измерване на скоростта, което значително ограничи възможностите ми. Бюджетът също беше ограничен, така че не беше закупено нищо специално. Така че трябваше да играем по тези правила.

Архитектура и развитие

Схемата е проста и очевидна. Затова ще го оставя без специални коментари.

Едновременен тест за скорост на няколко LTE модема

Реших да реализирам целия проект на python, въпреки факта, че нямах никакъв опит в разработването на този език. Избрах го, защото имаше куп готови примери и решения, които можеха да ускорят развитието. Затова моля всички професионални програмисти да не се карат на моя първи опит в разработването на python и винаги се радвам да чуя градивна критика, за да подобря уменията си.

Също така в процеса открих, че Python има две работещи версии 2 и 3, в резултат на което се спрях на третата.

Хардуерни възли

Vim2 с една плоча

Дадоха ми едноплатков компютър като основна машина vim2

Едновременен тест за скорост на няколко LTE модема

Отличен, мощен медиен процесор за интелигентен дом и SMART-TV, но изключително неподходящ за тази задача или, да кажем, неподходящ. Например основната му операционна система е Android, а Linux е вторична операционна система и съответно никой не гарантира висококачествената работа на всички възли и драйвери под Linux. И предполагам, че някои от проблемите са били свързани с USB драйверите на тази платформа, така че модемите не са работили според очакванията на тази платка. Освен това има много лоша и разпръсната документация, така че всяка операция отнемаше много време за копаене в доковете. Дори обикновената работа с GPIO отне много кръв. Например, отне ми няколко часа, за да настроя светодиода. Но, за да бъдем обективни, по същество не беше важно какъв вид единична платка беше, основното беше, че работи и има USB портове.

Първо, трябва да инсталирам Linux на тази платка. За да не ровя в дебрите на документацията за всички, а също и за тези, които ще се занимават с тази едноплаткова система, пиша тази глава.

Има две опции за инсталиране на Linux: на външна SD карта или на вътрешна MMC. Прекарах една вечер в измисляне как да го накарам да работи с картата и реших да го инсталирам на MMC, въпреки че без съмнение щеше да е много по-лесно да работи с външна карта.

Относно фърмуера криво казано тук. Превеждам от чужд на руски. За да флашна платката, трябва да свържа хардуерния UART. Свърза го както следва.

  • Пин на инструмента GND: <—> Пин17 на GPIO на VIM
  • Пин на инструмента TXD: <—> Пин18 на GPIO на VIM (Linux_Rx)
  • Пин на инструмента RXD: <—> Пин19 на GPIO на VIM (Linux_Tx)
  • Пин на инструмента VCC: <—> Пин20 на GPIO на VIM

Едновременен тест за скорост на няколко LTE модема

След което изтеглих фърмуера следователно. Конкретна версия на фърмуера VIM1_Ubuntu-сървър-bionic_Linux-4.9_arm64_EMMC_V20191231.

За да кача този фърмуер, имам нужда от помощни програми. Повече подробности за това тук. Не съм опитвал да го флашвам под Windows, но трябва да ви кажа няколко думи за фърмуера под Linux. Първо ще инсталирам помощните програми според инструкциите.

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

Ааа... Нищо не работи. Прекарах няколко часа в редактиране на инсталационните скриптове, така че всичко да се инсталира правилно за мен. Не помня какво съм правил там, но имаше и онзи цирк с коне. Така че внимавай. Но без тези помощни програми няма смисъл да измъчваме vim2 допълнително. По-добре изобщо да не се заяждате с него!

След седем кръга на ада, конфигуриране на скрипт и инсталиране, получих пакет от работещи помощни програми. Свързах платката чрез USB към моя Linux компютър и също така свързах UART според диаграмата по-горе.
Настройвам любимия си minicom терминал за скорост 115200, без хардуерен и софтуерен контрол на грешките. И да започваме.

Едновременен тест за скорост на няколко LTE модема

Когато зареждам VIM2 в UART терминала, натискам клавиш, като интервал, за да спра зареждането. След като се появи линията

kvim2# 

Въвеждам командата:

kvim2# run update

На хоста, от който зареждаме, изпълнявам:

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

Това е, уф. Проверих, има Linux на платката. Вход/парола khadas:khadas.

След това някои малки първоначални настройки. За по-нататъшна работа деактивирам паролата за sudo (да, не е сигурно, но удобно).

sudo visudo

Редактирам реда към формуляра и запазвам

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

След това променям текущия локал, така че часът да е в Москва, в противен случай ще бъде в Гринуич.

sudo timedatectl set-timezone Europe/Moscow

или

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

Ако ви е трудно, тогава не използвайте тази дъска; Raspberry Pi е по-добре. Честно казано.

Модем Huawei e3372h – 153

Този модем беше важен източник на кръв за мен и всъщност се превърна в тясното място на целия проект. Като цяло името „модем“ за тези устройства изобщо не отразява същността на работата: това е мощен комбайн, тази част от хардуера има съставно устройство, което се представя за CD-ROM, за да инсталира драйвери, и след това превключва в режим на мрежова карта.

Архитектурно, от гледна точка на Linux потребител, след всички настройки изглежда така: след свързване на модема имам мрежов интерфейс eth*, който чрез dhcp получава IP адрес 192.168.8.100 и шлюз по подразбиране е 192.168.8.1.

И най-важният момент! Този модел модем не може да работи в модемен режим, който се управлява от AT команди. Всичко би било много по-просто, създайте PPP връзки за всеки модем и след това работете с тях. Но в моя случай, „самият“ (по-точно, гмуркач на Linux според правилата на udev), създава eth интерфейс и му присвоява IP адрес чрез dhcp.

За да избегнете допълнително объркване, предлагам да забравите думата „модем“ и да кажете мрежова карта и шлюз, защото по същество това е като да свържете нова мрежова карта с шлюз.
Когато има един модем, това не създава особени проблеми, но когато има повече от един, а именно n-броя, се получава следната мрежова картина.

Едновременен тест за скорост на няколко LTE модема

Тоест n мрежови карти с един и същ IP адрес, всяка с един и същ шлюз по подразбиране. Но всъщност всеки от тях е свързан със собствен оператор.

Първоначално имах просто решение: използвайки командата ifconfig или ip, изключете всички интерфейси и просто включете един на свой ред и го тествайте. Решението беше добро за всички, с изключение на това, че в моментите на превключване не успях да се свържа с устройството. И тъй като превключването е често и бързо, всъщност изобщо нямах възможност да се свържа.

Затова избрах пътя на ръчна промяна на IP адресите на модемите и след това насочване на трафик с помощта на настройките за маршрутизиране.

Едновременен тест за скорост на няколко LTE модема

Това не беше краят на моите проблеми с модемите: в случай на проблеми със захранването те паднаха и беше необходимо добро стабилно захранване на USB хъба. Реших този проблем чрез твърдо запояване на захранването директно към хъба. Друг проблем, с който се сблъсках и който съсипа целия проект: след рестартиране или студен старт на устройството не всички модеми бяха открити и не винаги и не можах да определя защо това се случи и по какъв алгоритъм. Но на първо място.

За да работи модемът правилно, инсталирах пакета usb-modeswitch.

sudo apt update
sudo apt install -y usb-modeswitch

След което, след свързване, модемът ще бъде правилно открит и конфигуриран от подсистемата udev. Проверявам, като просто свързвам модема и се уверявам, че мрежата се появява.
Друг проблем, който не можах да реша: как мога да получа името на оператора, с който работим от този модем? Името на оператора се съдържа в уеб интерфейса на модема на 192.168.8.1. Това е динамична уеб страница, която получава данни чрез Ajax заявки, така че простото получаване на страницата и анализирането на името няма да работи. Така че започнах да търся как да разработя уеб страница и т.н. и разбрах, че правя някакви глупости. В резултат на това той се изплю и операторът започна да получава с помощта на самия Speedtest API.

Много по-лесно би било, ако модемът имаше достъп чрез AT команди. Би било възможно да го преконфигурирате, да създадете ppp връзка, да зададете IP, да получите телеком оператор и т.н. Но уви, работя с това, което ми е дадено.

GPS

GPS приемникът, който ми беше даден, имаше UART интерфейс и мощност. Това не беше най-доброто решение, но все пак беше работещо и просто. Приемникът изглеждаше нещо подобно.

Едновременен тест за скорост на няколко LTE модема

Честно казано, за първи път работих с GPS приемник, но както очаквах, всичко беше измислено за нас отдавна. Така че ние просто използваме готови решения.

Първо, разрешавам uart_AO_B (UART_RX_AO_B, UART_TX_AO_B) за свързване на GPS.

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

След това проверявам успеха на операцията.

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

Тази команда очевидно редактира devtree в движение, което е много удобно.

След успеха на тази операция рестартирайте и инсталирайте GPS демона.

khadas@Khadas:~$ sudo reboot

Инсталиране на GPS демон. Инсталирам всичко и веднага го прекъсвам за допълнителна конфигурация.

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

Редактиране на файла с настройки.

sudo vim /etc/default/gpsd

Инсталирам UART, на който GPS ще виси.

DEVICES="/dev/ttyS4"

И тогава включваме всичко и започваме.

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

След това свързвам GPS-а.

Едновременен тест за скорост на няколко LTE модема

GPS кабелът е в ръцете ми, проводниците на UART дебъгера се виждат под пръстите ми.

Рестартирам и проверявам работата на GPS с помощта на програмата gpsmon.

Едновременен тест за скорост на няколко LTE модема

Не можете да видите сателитите на тази екранна снимка, но можете да видите комуникация с GPS приемника и това означава, че всичко е наред.

В Python опитах много опции за работа с този демон, но се спрях на този, който работи правилно с Python 3.

Инсталирам необходимата библиотека.

sudo -H pip3 install gps3 

И аз извайвам работния код.

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

Ако трябва да получа координати, това става със следното извикване:

longitude, latitude = getPositionData(agps_thread)

И в рамките на 1-10 секунди или ще получа координатите, или не. Да, имах десет опита да получа координати. Не е оптимално, криво и накриво, но работи. Реших да направя това, защото GPS може да има лошо приемане и не винаги да получава данни. Ако чакате да получите данни, тогава ако работите в отдалечена стая, програмата ще замръзне на това място. Затова приложих тази неелегантна опция.

По принцип, ако имаше повече време, би било възможно да се получават данни от GPS директно през UART, да се анализират в отделна нишка и да се работи с тях. Но изобщо нямаше време, оттам и брутално грозният код. И да, не ме е срам.

Светодиод

Свързването на светодиода беше лесно и трудно в същото време. Основната трудност е, че пин номерът в системата не съответства на пин номера на платката и защото документацията се пише с лявата ръка. За да сравните хардуерния пин номер и пин номера в операционната система, трябва да изпълните командата:

gpio readall

Ще се покаже таблица на съответствието на пиновете в системата и на таблото. След което вече мога да работя с пина в самата ОС. В моя случай светодиодът е свързан към GPIOH_5.

Едновременен тест за скорост на няколко LTE модема

Превключвам GPIO щифта в изходен режим.

gpio -g mode 421 out

Записвам нула.

gpio -g write 421 0

Записвам едно.

gpio -g write 421 1

Едновременен тест за скорост на няколко LTE модема
Всичко свети след изписване на „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)

Сега, в случай на грешки, извиквам error_blink() и светодиодът ще мига красиво.

Софтуерни възли

API за Speedtest

Голяма радост е, че услугата speedtest.net има собствен python-API, можете да погледнете Github.

Хубавото е, че има изходни кодове, които също могат да се видят. Как да работите с този API (прости примери) можете да намерите в съответния раздел.

Инсталирам библиотеката на python със следната команда.

sudo -H pip3 install speedtest-cli

Например, можете дори да инсталирате тестер за скорост в Ubuntu директно от софтуера. Това е същото приложение на Python, което след това може да се стартира директно от конзолата.

sudo apt install speedtest-cli -y

И измерете скоростта на интернет.

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

В резултат точно както направих аз. Трябваше да вляза в изходните кодове на този тест за скорост, за да ги внедря по-пълно в моя проект. Една от най-важните задачи е да получите името на телекомуникационния оператор, за да го замените в табелата.

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

И тук всичко се оказа не толкова просто, въпреки че изглежда много по-просто. Първоначално параметърът сървъри беше равен на [], казват те, изберете най-добрия сървър. В резултат на това имах произволни сървъри и, както може би се досещате, променлива скорост. Това е доста сложна тема, използването на фиксиран сървър, ако е така, статичен или динамичен, изисква проучване. Но ето пример за графики за измерване на скоростта за оператор на Beeline при динамичен избор на тестов сървър и статично фиксиран.

Едновременен тест за скорост на няколко LTE модема
Резултатът от измерването на скоростта при избор на динамичен сървър.

Едновременен тест за скорост на няколко LTE модема
Резултат от тестване на скоростта, с един строго избран един сървър.

По време на тестването и на двете места има „козина“ и тя трябва да бъде премахната с помощта на математически методи. Но при фиксиран сървър е малко по-малко и амплитудата е по-стабилна.
Като цяло това е място за големи изследвания. И бих измерил скоростта на моя сървър с помощта на помощната програма iperf. Но ние се придържаме към техническите спецификации.

Изпращане на поща и грешки

За изпращане на поща опитах няколко десетки различни опции, но в крайна сметка се спрях на следното. Регистрирах пощенска кутия на Yandex и след това взех Това е пример за изпращане на поща. Проверих го и го внедрих в програмата. Този пример разглежда различни опции, включително изпращане от gmail и т.н. Не исках да се занимавам с настройката на пощенския си сървър и нямах време за това, но както се оказа по-късно, също беше напразно.

Регистрационните файлове бяха изпратени според графика, ако има връзка, на всеки 6 часа: в 00ч., 06ч., 12ч. и 18ч. Изпрати го по следния начин.

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

Първоначално бяха изпратени и грешки. Като начало те бяха натрупани в списъка и след това изпратени също с помощта на планировчика, ако имаше връзка. Тогава обаче възникнаха проблеми с факта, че Yandex има ограничение за броя на съобщенията, изпратени на ден (това е болка, тъга и унижение). Тъй като може да има огромен брой грешки дори на минута, трябваше да изоставим изпращането на грешки по пощата. Така че имайте предвид, когато автоматично изпращате информация за такъв проблем чрез услугите на Yandex.

Сървър за обратна връзка

За да имам достъп до отдалечен хардуер и да мога да го персонализирам и преконфигурирам, имах нужда от външен сървър. Като цяло, за да бъдем честни, би било правилно да изпратите всички данни на сървъра и да изградите всички красиви графики в уеб интерфейса. Но не наведнъж.

За VPS избрах ruvds.com. Можете да вземете най-простия сървър. И като цяло, за моите цели това би било достатъчно. Но тъй като не плащах за сървъра от собствения си джоб, реших да го взема с малък резерв, така че да е достатъчно, ако трябва да разположим уеб интерфейс, собствен SMTP сървър, VPN и т.н. Освен това можете да настроите бот на Telegram и да нямате проблеми с блокирането му. Затова избрах Амстердам и следните параметри.

Едновременен тест за скорост на няколко LTE модема

Като метод за комуникация с хардуера vim2 избра обратна ssh връзка и, както показа практиката, тя не е най-добрата. Ако връзката се загуби, сървърът задържа порта и е невъзможно да се свържете през него известно време. Следователно все още е по-добре да използвате други методи за комуникация, например VPN. В бъдеще исках да премина към VPN, но нямах време.

Няма да навлизам в подробности за настройката на защитна стена, ограничаването на правата, деактивирането на root ssh връзките и други истини за настройка на VPS. Бих искал да вярвам, че вече знаете всичко. За отдалечена връзка създавам нов потребител на сървъра.

adduser vimssh

Генерирам ssh ключове за връзка на нашия хардуер.

ssh-keygen

И ги копирам на нашия сървър.

ssh-copy-id [email protected]

На нашия хардуер създавам автоматична обратна ssh връзка при всяко зареждане.

[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

Обърнете внимание на порт 8083: той определя кой порт ще използвам за свързване чрез обратен ssh. Добавете го към стартиране и започнете.

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

Можете дори да видите състоянието:

sudo systemctl status autossh.service

Сега, на нашия VPS сървър, ако стартираме:

ssh -p 8083 khadas@localhost

След това стигам до моето тестово парче хардуер. И от хардуера мога също да изпращам логове и всякакви данни чрез ssh до моя сървър, което е много удобно.

Поставете всичко заедно

Едновременен тест за скорост на няколко LTE модема
Включваме, нека започнем разработката и отстраняването на грешки

Фу, добре, това е, описах всички възли. Сега е време да съберем всичко заедно. Можете да видите кода тук.

Важен момент с кода: Този проект може да не започне така, защото е пригоден за конкретна задача, с конкретна архитектура. Въпреки че давам изходния код, все пак ще обясня най-ценните неща тук, направо в текста, иначе е напълно неразбираемо.

В началото инициализирам gps, gpio и стартирам отделна нишка за планиране.

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

Планировчикът е доста прост: той проверява дали е дошъл моментът за изпращане на съобщения и какво е текущото състояние на грешката. Ако има флаг за грешка, тогава светодиодът мига.

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

Най-трудната част от този проект е поддържането на обратната ssh връзка за всеки тест. Всеки тест включва повторно конфигуриране на шлюза по подразбиране и DNS сървъра. Тъй като и без това никой не чете, знайте, че влакът не се движи по дървени релси. Който намери великденското яйце, получава бонбони.

За да направя това, създавам отделна таблица за маршрутизиране -set-mark 0x2 и правило за пренасочване на трафика.

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

Можете да научите повече за това как работи прочетете в тази статия.

След което влизам в безкраен цикъл, където всеки път получаваме списък със свързани модеми (за да разберем дали мрежовата конфигурация внезапно се е променила).

network_list = getNetworklist()

Получаването на списък с мрежови интерфейси е доста просто.

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

След като получих списъка, зададох IP адреси на всички интерфейси, както показах на снимката в главата за модема.

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

След това просто преминавам през всеки интерфейс в цикъл. И аз конфигурирам всеки интерфейс.

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

Проверявам интерфейса за функционалност, ако няма мрежа, тогава генерирам грешки. Ако има мрежа, тогава е време да действате!

Тук конфигурирам ssh маршрутизиране към този интерфейс (ако не е направено), изпращам грешки на сървъра, ако времето е дошло, изпращам регистрационни файлове и накрая стартирам тест за скорост и записвам регистрационните файлове в 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()
#и далее тестируем скорость и сохраняем логи. 

Заслужава да се спомене функцията за настройка на обратен 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")

И разбира се, трябва да добавите цялата тази красота към стартирането. За да направя това, създавам файл:

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

И аз пиша в него:

[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

Включвам автоматично зареждане и започвам!

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

Сега мога да видя регистрационни файлове на случващото се с помощта на командата:

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

резултати

Е, сега най-важното е какво се случи в резултат? Ето няколко графики, които успях да заснема по време на процеса на разработка и отстраняване на грешки. Графиките са построени с помощта на gnuplot със следния скрипт.

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

Първият опит беше с оператора Tele2, който проведох няколко дни.

Едновременен тест за скорост на няколко LTE модема

Тук използвах динамичен измервателен сървър. Измерванията на скоростта работят, но се колебаят много, но все още се вижда някаква средна стойност и това може да се получи чрез филтриране на данните, например с подвижна средна.

По-късно изградих редица графики за други телеком оператори. В този случай вече имаше един тестов сървър и резултатите също бяха много интересни.

Едновременен тест за скорост на няколко LTE модема

Едновременен тест за скорост на няколко LTE модема

Едновременен тест за скорост на няколко LTE модема

Едновременен тест за скорост на няколко LTE модема

Както можете да видите, темата е много обширна за изследване и обработка на тези данни и очевидно не стига за няколко седмици работа. Но…

Резултатът от работата

Работата беше внезапно завършена поради обстоятелства извън моя контрол. Една от слабостите на този проект, по мое субективно мнение, беше модемът, който всъщност не искаше да работи едновременно с други модеми и правеше такива трикове при всяко зареждане. За тези цели има огромен брой други модели модеми; обикновено те вече са във формат Mini PCI-e и са инсталирани вътре в устройството и са много по-лесни за конфигуриране. Но това е съвсем различна история. Проектът беше интересен и много се радвам, че успях да участвам в него.

Едновременен тест за скорост на няколко LTE модема

Източник: www.habr.com

Добавяне на нов коментар