Током карантина, понуђено ми је да учествујем у развоју уређаја за мерење брзине ЛТЕ модема за неколико мобилних оператера.
Купац је желео да процени брзину разних телеком оператера на различитим географским локацијама како би могао да разуме који му је мобилни оператер најоптималнији приликом инсталирања опреме која користи ЛТЕ везу, на пример, за видео емитовање. У исто време, проблем је морао да се реши што једноставније и јефтиније, без скупе опреме.
Одмах ћу рећи да задатак није најједноставнији и најзахтјевнији, рећи ћу вам на које сам проблеме наишао и како сам их ријешио. Па идемо.
Приметити
Мерење брзине ЛТЕ везе је веома сложена ствар: потребно је да изаберете праву опрему и технику мерења, као и да добро разумете топологију и рад ћелијске мреже. Осим тога, на брзину може утицати неколико фактора: број претплатника на ћелију, временски услови, чак и од ћелије до ћелије брзина може драматично да варира због топологије мреже. Генерално, ово је проблем са огромним бројем непознаница и само га телеком оператер може исправно решити.
У почетку, купац је само желео да одвезе курира са телефонима оператера, изврши мерења директно на телефону и затим запише резултате мерења брзине у бележницу. Моје решење за мерење брзине лте мрежа, иако није идеално, решава проблем.
Због недостатка времена доносио сам одлуке не у корист погодности или практичности, већ у корист брзине развоја. На пример, за даљински приступ коришћен је обрнути ссх, уместо практичнијег ВПН-а, како би се уштедело време на подешавању сервера и сваког појединачног клијента.
Технички задатак
Како је наведено у чланку : Не радите без техничких спецификација! Никад, нигде!
Технички задатак је био прилично једноставан, мало ћу га проширити за разумевање крајњег корисника. Избор техничких решења и опреме диктирао је наручилац. Дакле, сама техничка спецификација, након свих одобрења:
Заснован на рачунару на једној плочи вим2 направите тестер брзине за лте везе преко Х модемауавеи е3372х - 153 неколико телеком оператера (од један до н). Такође је неопходно примати координате са ГПС пријемника повезаног преко УАРТ-а. Извршите мерења брзине помоћу услуге и ставите их у табелу као што је:
Табела у цсв формату. Затим пошаљите овај знак е-поштом сваких 6 сати. У случају грешке, трепери ЛЕД диода која је повезана на ГПИО.
Описао сам техничке спецификације у слободној форми, након многих одобрења. Али смисао задатка је већ видљив. За све је дата недеља. Али у стварности је то трајало три недеље. Ово узимајући у обзир чињеницу да сам ово радио само након главног посла и викендом.
Овде желим још једном да скренем пажњу на чињеницу да је купац унапред договорио коришћење услуге мерења брзине и хардвера, што је у великој мери ограничило моје могућности. И буџет је био ограничен, па ништа посебно није купљено. Тако да смо морали да играмо по овим правилима.
Архитектура и развој
Шема је једноставна и очигледна. Стога ћу то оставити без посебних коментара.

Одлучио сам да имплементирам цео пројекат на Питхон-у, упркос чињеници да нисам имао никаквог искуства у развоју овог језика. Изабрао сам га јер је постојала гомила готових примера и решења која би могла да убрзају развој. Зато молим све професионалне програмере да не грде моје прво искуство развијања у Питхон-у, и увек сам срећан да чујем конструктивне критике да унапредим своје вештине.
Такође у процесу сам открио да Питхон има две активне верзије 2 и 3, као резултат тога, одлучио сам се на трећу.
Хардверски чворови
Једноструки вим2
Добио сам једноплочни рачунар као главну машину

Одличан, моћан медијални комбинатор за паметни дом и СМАРТ ТВ, али изузетно непогодан за овај задатак, или, рецимо, слабо прилагођен. На пример, његов главни ОС је AndroidИ Linux - ово је пратећи ОС и сходно томе нико не гарантује квалитетан рад свих компоненти и драјвера под њим LinuxСумњам да су неки од проблема били повезани са УСБ драјверима платформе, због чега модеми нису радили како се очекивало на овој плочи. Такође је имала веома лошу и неповезану документацију, тако да је свака операција одузимала доста времена и захтевала претраживање документације. Чак је и рутинска манипулација GPIO-ом била права мука. На пример, подешавање ЛЕД диоде трајало је неколико сати. Али, искрено, није било битно каква је врста једноплочног рачунара у питању, све док је радио и имао УСБ портове.
Прво треба да инсталирам Linux За ову плочу. Да бих избегао претраживање документације и за оне који ће схватати како да користе овај једноплочни рачунар, пишем ово поглавље.
Постоје две опције за инсталирање Линук-а: на спољну СД картицу или на интерни ММЦ. Провео сам вече покушавајући да смислим како да то натерам да ради са картицом, па сам одлучио да је инсталирам на ММЦ, иако би без сумње било много лакше радити са екстерном картицом.
О фирмверу . Преводим са страног на руски. Да бих флешовао плочу, морам да повежем хардверски УАРТ. Повезано
- Алат Пин ГНД: <—> Пин17 ГПИО ВИМ-а
- Алат TXD пин: <—> Пин18 VIM-овог GPIO-а (Linux_Ркс)
- Пин алата RXD: <—> Пин19 VIM-овог GPIO-а (Linux_Tx)
- Тоол Пин ВЦЦ: <—> Пин20 ГПИО ВИМ-а

Након тога сам преузео фирмвер . Конкретна верзија фирмвера .
Да бих поставио овај фирмвер, потребни су ми услужни програми. Више детаља о овоме ... Под Windows Нисам покушао да га флешујем, али што се тиче флешовања испод... Linux Морам рећи неколико речи. Прво ћу инсталирати услужне програме према упутствима.
git clone https://github.com/khadas/utils
cd /path/to/utils
sudo ./INSTALLАаа... Ништа не ради. Провео сам неколико сати уређујући инсталационе скрипте како би се све исправно инсталирало за мене. Не сећам се шта сам тамо радио, али био је и онај циркус са коњима. Па зато будите пажљиви. Али без ових услужних програма нема смисла даље мучити вим2. Боље је да се уопште не зезате са њим!
После седам кругова пакла, конфигурисања скрипте и инсталације, добио сам пакет радних услужних програма. Повезао сам плочу преко УСБ-а на мој Линук рачунар, а такође сам спојио УАРТ према дијаграму изнад.
Подешавам свој омиљени миником терминал за брзину од 115200, без контроле хардверских и софтверских грешака. И хајде да почнемо.

Када учитавам ВИМ2 у УАРТ терминалу, притиснем тастер, као што је размакница, да зауставим учитавање. Након што се појави линија
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 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Ако вам је тешко, онда немојте користити ову плочу; Искрено.
Модем Хуавеи е3372х – 153
Овај модем је за мене био значајан извор крви и, у ствари, постао је уско грло целог пројекта. Генерално, назив „модем“ за ове уређаје уопште не одражава суштину посла: ово је моћан комбинат, овај комад хардвера има композитни уређај који се претвара да је ЦД-РОМ да би инсталирао драјвере, а затим прелази у режим мрежне картице.
Архитектонски, са становишта корисника Linux Након свих подешавања, изгледа овако: након повезивања модема, имам мрежни интерфејс eth*, који преко DHCP-а добија IP адресу 192.168.8.100, а подразумевани gateway је 192.168.8.1.
И најважнији тренутак! Овај модел модема не може да ради у модемском режиму, који се контролише АТ командамаБило би много једноставније креирати PPP везе за сваки модем, а затим радити са њима. Али у мом случају, „ја“ (или боље речено, ронилац) Linux према udev правилима), креира eth интерфејс и додељује му IP адресу путем dhcp-а.
Да бисте избегли даљу забуну, предлажем да заборавите реч „модем“ и кажете мрежна картица и мрежни пролаз, јер је то у суштини као повезивање нове мрежне картице са мрежним пролазом.
Када постоји један модем, то не прави посебне проблеме, али када постоји више од једног, односно н-комада, појављује се следећа мрежна слика.

То јест, н мрежних картица, са истом ИП адресом, свака са истим подразумеваним мрежним пролазом. Али у ствари, сваки од њих је повезан са сопственим оператером.
У почетку сам имао једноставно решење: користећи команду ифцонфиг или ип, искључите све интерфејсе и једноставно укључите један редом и тестирајте га. Решење је било добро за све, осим што у моментима пребацивања нисам могао да се повежем на уређај. А пошто је пребацивање често и брзо, заправо нисам имао прилику да се повежем уопште.
Због тога сам одабрао пут ручне промене ИП адреса модема и затим усмеравања саобраћаја користећи подешавања рутирања.

Ово није био крај мојим проблемима са модемима: у случају проблема са напајањем, они су испадали и било је потребно добро стабилно напајање УСБ чворишта. Решио сам овај проблем чврстим лемљењем напајања директно на чвориште. Још један проблем на који сам наишао и који је упропастио цео пројекат: након поновног покретања или хладног покретања уређаја, нису сви модеми откривени и не увек, и нисам могао да утврдим зашто се то догодило и којим алгоритмом. Али прво ствари.
Да би модем исправно радио, инсталирао сам пакет усб-модесвитцх.
sudo apt update
sudo apt install -y usb-modeswitch Након тога, након повезивања, модем ће бити исправно откривен и конфигурисан од стране удев подсистема. Проверавам тако што једноставно повежем модем и проверим да ли се мрежа појављује.
Још један проблем који нисам могао да решим: како да добијем име оператера са којим радимо са овог модема? Име оператера се налази у веб интерфејсу модема на 192.168.8.1. Ово је динамичка веб страница која прима податке преко Ајак захтева, тако да једноставно добијање странице и рашчлањивање имена неће радити. Па сам почео да гледам како да развијем веб страницу итд. и схватио да радим неку глупост. Као резултат тога, пљунуо је, а оператер је почео да прима користећи сам Спеедтест АПИ.
Много би било лакше да модем има приступ преко АТ команди. Било би могуће поново га конфигурисати, направити ппп везу, доделити ИП, добити телеком оператера итд. Али, авај, радим са оним што ми је дато.
ГПС-
ГПС пријемник који сам добио имао је УАРТ интерфејс и напајање. То није било најбоље решење, али је и даље било изводљиво и једноставно. Пријемник је изгледао отприлике овако.

Да будем искрен, ово ми је био први пут да радим са ГПС пријемником, али као што сам и очекивао, све нам је одавно смишљено. Зато користимо само готова решења.
Прво, омогућавам уарт_АО_Б (УАРТ_РКС_АО_Б, УАРТ_ТКС_АО_Б) да повежем ГПС.
khadas@Khadas:~$ sudo fdtput -t s /dtb.img /serial@c81004e0 status okayПосле проверавам успех операције.
khadas@Khadas:~$ fdtget /dtb.img /serial@c81004e0 status
okayОва команда очигледно уређује девтрее у ходу, што је веома згодно.
Након успеха ове операције, поново покрените и инсталирајте ГПС демон.
khadas@Khadas:~$ sudo rebootИнсталирање ГПС демона. Све инсталирам и одмах одсечем ради даље конфигурације.
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Инсталирам УАРТ на коме ће виси ГПС.
DEVICES="/dev/ttyS4"А онда све укључујемо и почињемо.
/* GPS daemon enable/start */
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socketНакон тога повезујем ГПС.

ГПС жица је у мојим рукама, жице УАРТ дебуггера су видљиве испод мојих прстију.
Поново покрећем и проверавам ГПС рад користећи гпсмон програм.

Не можете видети сателите на овом снимку екрана, али можете видети комуникацију са ГПС пријемником, а то значи да је све у реду.
У Питхон-у сам испробао многе опције за рад са овим демоном, али сам се одлучио на ону која је исправно радила са Питхон-ом 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 секунди или ћу добити координате или не. Да, имао сам десет покушаја да добијем координате. Није оптимално, криво и искривљено, али ради. Одлучио сам да то урадим јер ГПС може имати лош пријем и не прима увек податке. Ако чекате да примите податке, онда ако радите у удаљеној просторији, програм ће се замрзнути на овом месту. Стога сам имплементирао ову неелеганцију.
У принципу, да је било више времена, било би могуће примати податке са ГПС-а директно преко УАРТ-а, рашчланити их у посебну нит и радити са њима. Али уопште није било времена, отуда брутално ружан код. И да, не стидим се.
Светлећа диода
Повезивање ЛЕД-а било је једноставно и тешко у исто време. Главна потешкоћа је што пин број у систему не одговара броју пина на плочи и што се документација пише левом руком. Да бисте упоредили хардверски пин број и пин број у ОС-у, потребно је да покренете наредбу:
gpio readallПриказаће се табела кореспонденције пинова у систему и на табли. Након тога већ могу да управљам пином у самом ОС. У мом случају је ЛЕД спојен на ГПИОХ_5.

Пребацујем ГПИО пин у излазни режим.
gpio -g mode 421 outЗаписујем нулу.
gpio -g write 421 0Записујем једну.
gpio -g write 421 1 
Све је упаљено, након што напишете "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)
Сада, у случају грешака, позивам еррор_блинк() и ЛЕД ће лепо трептати.
Софтверски чворови
Спеедтест АПИ
Велика је радост што сервис спеедтест.нет има свој питхон-АПИ, можете погледати .
Добра ствар је што постоје изворни кодови који се такође могу погледати. Како радити са овим АПИ-јем (једноставни примери) можете пронаћи у .
Инсталирам питхон библиотеку са следећом командом.
sudo -H pip3 install speedtest-cliНа пример, генерално можете инсталирати тестер брзине у Ubuntu Директно из репозиторијума. Ово је иста Пајтон апликација која се затим може покренути директно из конзоле.
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"
#тут идет запись в файл логов
И овде се све показало да није тако једноставно, иако би изгледало много једноставније. У почетку је параметар сервера био једнак [], кажу, изаберите најбољи сервер. Као резултат тога, имао сам насумичне сервере и, као што можете претпоставити, променљиву брзину. Ово је прилично сложена тема, коришћење фиксног сервера, ако јесте, статички или динамички, захтева истраживање. Али ево примера графикона мерења брзине за Беелине оператера када динамички бира тест сервер и статички фиксни.

Резултат мерења брзине при избору динамичког сервера.

Резултат тестирања брзине, са једним строго одабраним сервером.
Током тестирања, на оба места постоји „крзно“, које је потребно уклонити математичким методама. Али код фиксног сервера је нешто мање и амплитуда је стабилнија.
Генерално, ово је место великог истраживања. А ја бих измерио брзину свог сервера користећи иперф услужни програм. Али држимо се техничких спецификација.
Слање поште и грешке
За слање поште, покушао сам неколико десетина различитих опција, али сам се на крају одлучио на следеће. Регистровао сам поштанско сандуче на Иандек-у и онда узео . Проверио сам и имплементирао у програм. Овај пример испитује различите опције, укључујући слање са Гмаил-а, итд. Нисам желео да се мучим са подешавањем свог сервера за пошту и нисам имао времена за то, али како се касније испоставило, и то је било узалуд.
Дневници су послати према распореду, ако постоји веза, сваких 6 часова: у 00 часова, 06, 12 и 18 часова. Послао је на следећи начин.
from send_email import *
...
message_log = "Логи тестирования платы №1"
EmailForSend = ["dlinyj@trololo.ru", "pupkin@trololo.ru"]
files = ["/home/khadas/modems_speedtest/csv"]
...
def sendLogs():
global EmailForSend
curdata = datetime.now().strftime('%d.%m.%Y')
с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
Грешке су такође послате у почетку. За почетак су се акумулирали на листи, а затим су послати и помоћу планера, ако је постојала веза. Међутим, тада су настали проблеми са чињеницом да Иандек има ограничење броја порука које се шаљу дневно (ово је бол, туга и понижење). Пошто је могао бити огроман број грешака чак и по минуту, морали смо да одустанемо од слања грешака поштом. Зато имајте на уму када аутоматски шаљете информације о таквом проблему путем услуга Иандек-а.
Сервер за повратне информације
Да бих имао приступ удаљеном комаду хардвера и могао да га прилагодим и поново конфигуришем, био ми је потребан спољни сервер. Генерално, да будемо поштени, било би исправно послати све податке на сервер и изградити све прелепе графиконе у веб интерфејсу. Али не све одједном.
За ВПС сам изабрао . Можете узети најједноставнији сервер. И генерално, за моје потребе ово би било довољно. Али пошто сервер нисам платио из свог џепа, одлучио сам да га узмем са малом резервом да би било довољно да поставимо веб интерфејс, сопствени СМТП сервер, ВПН итд. Поред тога, можете да подесите Телеграм бот и да немате проблема са блокирањем. Стога сам изабрао Амстердам и следеће параметре.

Као метод комуникације са хардвером, вим2 је изабрао обрнуту ссх везу и, како је пракса показала, није најбоља. Ако се веза изгуби, сервер држи порт и неко време је немогуће повезати се преко њега. Због тога је ипак боље користити друге методе комуникације, на пример ВПН. У будућности сам желео да пређем на ВПН, али нисам имао времена.
Нећу улазити у детаље о постављању заштитног зида, ограничавању права, онемогућавању роот ссх веза и другим истинама о постављању ВПС-а. Волео бих да верујем да већ све знате. За даљинску везу, креирам новог корисника на серверу.
adduser vimsshГенеришем кључеве за ссх везу на нашем хардверу.
ssh-keygenИ копирам их на наш сервер.
ssh-copy-id vimssh@host.comНа нашем хардверу правим аутоматску обрнуту ссх везу при сваком покретању.
[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 vimssh@host.com
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target
Обратите пажњу на порт 8083: он одређује који порт ћу користити за повезивање преко обрнутог ссх-а. Додајте га у стартуп и почните.
sudo systemctl enable autossh.service
sudo systemctl start autossh.serviceМожете чак и да видите статус:
sudo systemctl status autossh.serviceСада, на нашем ВПС серверу, ако покренемо:
ssh -p 8083 khadas@localhostОнда долазим до свог тестног комада хардвера. А са хардвера такође могу да шаљем логове и све податке преко ссх-а на свој сервер, што је веома згодно.
Све заједно

Укључујући, почнимо развој и отклањање грешака
Фуј, па то је то, описао сам све чворове. Сада је време да се све то споји. Можете видети код .
Важна тачка кода: Овај пројекат можда неће почети овако, јер је скројен за одређени задатак, специфичне архитектуре. Иако дајем изворни код, највредније ћу ипак објаснити овде, одмах у тексту, иначе је потпуно неразумљиво.
На почетку иницијализујем гпс, гпио и покрећем засебну нит планера.
#запуск потока планировщика
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)Најтежи део овог пројекта је одржавање обрнуте ссх везе за сваки тест. Сваки тест укључује поновно конфигурисање подразумеваног мрежног пролаза и ДНС сервера. Пошто ионако нико не чита, знајте да воз не вози по дрвеним шинама. Ко нађе ускршње јаје добија слаткише.
Да бих то урадио, креирам засебну табелу рутирања -сет-марк 0к2 и правило за преусмеравање саобраћаја.
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Након што сам добио листу, поставио сам ИП адресе на све интерфејсе, као што сам показао на слици у поглављу о модему.
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'")Проверавам функционалност интерфејса, ако нема мреже, онда генеришем грешке. Ако постоји мрежа, онда је време да се делује!
Овде конфигуришем ссх рутирање до овог интерфејса (ако није урађено), шаљем грешке серверу ако је дошло време, шаљем логове и на крају покрећем спеедтест и чувам логове у цсв датотеку.
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()
#и далее тестируем скорость и сохраняем логи. Вреди поменути функцију подешавања обрнутог ссх-а.
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Налази
Па, сада је најважније шта се десило као резултат? Ево неколико графикона које сам успео да ухватим током процеса развоја и отклањања грешака. Графикони су направљени коришћењем гнуплота са следећом скриптом.
#! /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"
Прво искуство је било са Теле2 оператером, који сам водио неколико дана.

Овде сам користио сервер за динамичко мерење. Мерења брзине раде, али веома варирају, али нека просечна вредност је и даље видљива, а то се може добити филтрирањем података, на пример, помоћу покретног просека.
Касније сам направио низ графикона за друге телеком оператере. У овом случају је већ постојао један сервер за тестирање, а резултати су такође били веома интересантни.




Као што видите, тема је веома обимна за истраживање и обраду ових података и очигледно не траје пар недеља рада. Али…
Резултат рада
Посао је нагло завршен због околности које су биле ван моје контроле. Једна од слабости овог пројекта, по мом субјективном мишљењу, био је модем, који заправо није желео да ради истовремено са другим модемима и правио је такве трикове сваки пут када се учитава. За ове сврхе постоји велики број других модела модема обично су већ у Мини ПЦИ-е формату и инсталирани су унутар уређаја и много их је лакше конфигурисати. Али то је сасвим друга прича. Пројекат је био занимљив и било ми је веома драго што сам могао да учествујем у њему.
Извор: ввв.хабр.цом

