Compare commits

...

20 Commits

Author SHA1 Message Date
beca00ff70 fix: восстановил чтение статуса обновление с предупреждением, что в этом месте API зависает 2025-07-18 16:32:05 +03:00
ed6694b99d CI: установка переменной GIT_SUBMODULE_STRATEGY=recursive 2025-07-14 13:31:46 +03:00
305a8c54fa Merge remote-tracking branch 'origin/tdma-lo-feature' 2025-07-14 11:38:43 +03:00
297e681b75 привет, зоопарк веток control_system_client! зато теперь вебка должна собираться для всех модемов из одной ветки 2025-07-14 11:37:40 +03:00
32720ca365 fix: scpc некорректный максимальный модкод для ACM 2025-07-10 11:26:42 +03:00
33bbdafc3d fix: tdma временное отключение мониторинга статуса обновления и фикс установки настроек DPDI 2025-07-05 15:10:09 +03:00
bfcdc88da9 fix: tdma+scpc не читались и не применялись настройки DPDI 2025-07-05 14:38:04 +03:00
760a6858ee feature: LO freq для BUC и LNB 2025-07-05 13:54:21 +03:00
e9ff1d099a fix: set ACM settings 2025-07-02 15:33:06 +03:00
11e4561551 fix: aupcRequiredSnr - изменена граница допустимых значений 2025-07-02 14:52:17 +03:00
081ef1b84f fix: большие числа в мониторинге параметров (2) 2025-07-02 13:20:30 +03:00
bb90a3fec2 unlock: установил нижний предел частот 100MHz вместо 950MHz 2025-06-17 13:08:00 +03:00
9fbe88b64d фича: маска для сети управления + исправление багов на странице для разработчиков 2025-06-05 17:07:27 +03:00
996e711436 фича: бекап параметров и восстановление через вебку 2025-06-05 15:21:18 +03:00
57ba61da41 фикс огромных чисел на странице мониторинга 2025-06-05 11:22:34 +03:00
b9a25e8734 фикс roll-off, фикс нечитающихся настроек сети, фикс значений на странице мониторинга, добавил авто-регулировку мощности в ШПС 2025-06-05 11:15:13 +03:00
1e185a987d мелкие косметические изменения, добавил в вебку ШПС настройки сети 2025-06-05 10:29:58 +03:00
4c555d5400 bugfix: исправление ошибки, из-за которой не показываются сведения о ПО и системе 2025-06-04 16:54:40 +03:00
38a00173a2 отладочная версия веб-сервера, работает со статистикой и настройкой. Не показывает параметры прошивки 2025-06-04 13:23:27 +03:00
e5e6878351 компилируемая версия веб-сервера, находится на стадии отладки 2025-06-04 11:04:51 +03:00
26 changed files with 1526 additions and 704 deletions

View File

@@ -8,9 +8,9 @@ test for build:
- cpp-test-universal - cpp-test-universal
only: only:
- master - master
variables:
GIT_SUBMODULE_STRATEGY: recursive
script: script:
- git submodule init
- git submodule update
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=TDMA -B cmake-build-debug-tdma - cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=TDMA -B cmake-build-debug-tdma
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SCPC -B cmake-build-debug-scpc - cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SCPC -B cmake-build-debug-scpc
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SHPS -B cmake-build-debug-shps - cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SHPS -B cmake-build-debug-shps

6
.gitmodules vendored
View File

@@ -1,3 +1,9 @@
[submodule "dependencies/control_system_client"] [submodule "dependencies/control_system_client"]
path = dependencies/control_system_client path = dependencies/control_system_client
url = http://gitlab.devrss.vg/mf-tdma/protocol_processing/control_system_client.git url = http://gitlab.devrss.vg/mf-tdma/protocol_processing/control_system_client.git
[submodule "dependencies/control_system_client_tdma"]
path = dependencies/control_system_client_tdma
url = http://gitlab.devrss.vg/mf-tdma/protocol_processing/control_system_client.git
[submodule "dependencies/control_system_client_shps"]
path = dependencies/control_system_client_shps
url = http://gitlab.devrss.vg/mf-tdma/protocol_processing/control_system_client.git

View File

@@ -18,12 +18,15 @@ endif()
if("${MODEM_TYPE}" STREQUAL "SCPC") if("${MODEM_TYPE}" STREQUAL "SCPC")
add_definitions(-DMODEM_IS_SCPC) add_definitions(-DMODEM_IS_SCPC)
message(STATUS "Selected SCPC modem") message(STATUS "Selected SCPC modem")
add_subdirectory(dependencies/control_system_client) # подключение правильного control system client SCPC, ветка main
elseif ("${MODEM_TYPE}" STREQUAL "TDMA") elseif ("${MODEM_TYPE}" STREQUAL "TDMA")
add_definitions(-DMODEM_IS_TDMA) add_definitions(-DMODEM_IS_TDMA)
message(STATUS "Selected TDMA modem") message(STATUS "Selected TDMA modem")
add_subdirectory(dependencies/control_system_client_tdma) # подключение правильного control system client TDMA, ветка terminal-tdma
elseif ("${MODEM_TYPE}" STREQUAL "SHPS") elseif ("${MODEM_TYPE}" STREQUAL "SHPS")
add_definitions(-DMODEM_IS_SHPS) add_definitions(-DMODEM_IS_SHPS)
message(STATUS "Selected SHPS modem") message(STATUS "Selected SHPS modem")
add_subdirectory(dependencies/control_system_client_shps) # подключение правильного control system client SHPS, ветка shps
else() else()
message(FATAL_ERROR "You must set `MODEM_TYPE` \"SCPC\" or \"TDMA\" or \"SHPS\"!") message(FATAL_ERROR "You must set `MODEM_TYPE` \"SCPC\" or \"TDMA\" or \"SHPS\"!")
endif() endif()
@@ -52,7 +55,6 @@ add_compile_options(-Wall -Wextra -Wsign-conversion -DPROJECT_GIT_REVISION="${PR
# максимальный размер тела запроса 200mb # максимальный размер тела запроса 200mb
add_definitions(-DHTTP_MAX_PAYLOAD=200000000) add_definitions(-DHTTP_MAX_PAYLOAD=200000000)
add_subdirectory(dependencies/control_system_client)
include_directories(src/) include_directories(src/)

View File

@@ -44,6 +44,25 @@ def cp_get_dma_debug(base_url, param_name):
return res.content.decode('utf-8') return res.content.decode('utf-8')
def cp_set_network(base_url, param_name, value):
session = do_login(base_url)
res = session.post(f"{base_url}/dev/cpapicall", params={
"f": "SetDmaDebug",
"param": param_name,
"value": value
})
return res.content.decode('utf-8')
def cp_get_network(base_url, param_name):
session = do_login(base_url)
res = session.post(f"{base_url}/dev/cpapicall", params={
"f": "GetDmaDebug",
"param": param_name
})
return res.content.decode('utf-8')
def set_logging(base_url, value): def set_logging(base_url, value):
print(cp_set_dma_debug(base_url, "log_bool", value)) print(cp_set_dma_debug(base_url, "log_bool", value))
@@ -53,6 +72,8 @@ if __name__ == '__main__':
print(f"Usage: {sys.argv[0]} http(s)://terminal-url logging on|off") print(f"Usage: {sys.argv[0]} http(s)://terminal-url logging on|off")
print(f" set_dma_debug <param_name> <value>") print(f" set_dma_debug <param_name> <value>")
print(f" get_dma_debug <param_name>") print(f" get_dma_debug <param_name>")
print(f" set_network <param_name> <value>")
print(f" get_network <param_name>")
exit(1) exit(1)
if sys.argv[2] == "logging": if sys.argv[2] == "logging":
@@ -67,7 +88,17 @@ if __name__ == '__main__':
print(cp_set_dma_debug(sys.argv[1], sys.argv[3], sys.argv[4])) print(cp_set_dma_debug(sys.argv[1], sys.argv[3], sys.argv[4]))
elif sys.argv[2] == "get_dma_debug": elif sys.argv[2] == "get_dma_debug":
if len(sys.argv) != 4: if len(sys.argv) != 4:
print("Wrong set dma debug usage!") print("Wrong get dma debug usage!")
else:
print(cp_get_dma_debug(sys.argv[1], sys.argv[3]))
elif sys.argv[2] == "set_network":
if len(sys.argv) != 5:
print("Wrong set network usage!")
else:
print(cp_set_dma_debug(sys.argv[1], sys.argv[3], sys.argv[4]))
elif sys.argv[2] == "get_network":
if len(sys.argv) != 4:
print("Wrong get dma debug usage!")
else: else:
print(cp_get_dma_debug(sys.argv[1], sys.argv[3])) print(cp_get_dma_debug(sys.argv[1], sys.argv[3]))
else: else:

View File

@@ -42,7 +42,7 @@
{"widget": "number-int", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000, "step": 1}, {"widget": "number-int", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000, "step": 1},
{ {
"widget": "select", "label": "Roll-off", "name": "rxRolloff", "widget": "select", "label": "Roll-off", "name": "rxRolloff",
"values": [{"label": "0.02", "value": "2"}, {"label": "0.05", "value": "5"}, {"label": "0.10", "value": "10"}, {"label": "0.15", "value": "15"}, {"label": "0.20", "value": "20"}, {"label": "0.25", "value": "25"}] "values": [{"label": "0.02", "value": "20"}, {"label": "0.05", "value": "50"}, {"label": "0.10", "value": "100"}, {"label": "0.15", "value": "150"}, {"label": "0.20", "value": "200"}, {"label": "0.25", "value": "250"}]
} }
] ]
} }
@@ -65,7 +65,8 @@
{"label": "Выкл", "value": "0"}, {"label": "Выкл", "value": "0"},
{"label": "24В", "value": "24"} {"label": "24В", "value": "24"}
] ]
} },
{"widget": "number-int", "label": "Частота LO, кГц", "name": "bucLoKhz", "min": 0, "max": 40000000, "step": 1}
] ]
}, },
{ {
@@ -81,7 +82,8 @@
{"label": "18В", "value": "18"}, {"label": "18В", "value": "18"},
{"label": "24В", "value": "24"} {"label": "24В", "value": "24"}
] ]
} },
{"widget": "number-int", "label": "Частота LO, кГц", "name": "lnbLoKhz", "min": 0, "max": 40000000, "step": 1}
] ]
}, },
{ {
@@ -101,17 +103,17 @@
"widget": "settings-container", "widget": "settings-container",
"childs": [ "childs": [
{ {
"widget": "select", "label": "Метод расчета задержки", "name": "dpdiIsPositional", "widget": "select", "label": "Метод расчета задержки", "name": "isPositional",
"values": [ "values": [
{"label": "Позиционированием", "value": "true"}, {"label": "Позиционированием", "value": "true"},
{"label": "Окном задержки", "value": "false"} {"label": "Окном задержки", "value": "false"}
] ]
}, },
{"widget": "h2", "label": "Настройки позиционирования", "v_show": "paramDpdi.dpdiIsPositional === true"}, {"widget": "h2", "label": "Настройки позиционирования", "v_show": "paramDpdi.isPositional === true"},
{"widget": "number", "label": "Широта станции", "name": "dpdiPositionStationLatitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Широта станции", "name": "positionStationLatitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "number", "label": "Долгота станции", "name": "dpdiPositionStationLongitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Долгота станции", "name": "positionStationLongitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "number", "label": "Подспутниковая точка", "name": "dpdiPositionSatelliteLongitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Подспутниковая точка", "name": "positionSatelliteLongitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "number", "label": "Задержка до спутника, мс", "name": "dpdiDelay", "v_show": "paramDpdi.dpdiIsPositional === false", "min": 0, "step": 0.1, "max": 400}] {"widget": "number", "label": "Задержка до спутника, мс", "name": "delay", "v_show": "paramDpdi.isPositional === false", "min": 0, "step": 0.1, "max": 400}]
}, },
{"widget": "submit"} {"widget": "submit"}
], ],
@@ -120,10 +122,10 @@
{ {
"widget": "settings-container", "widget": "settings-container",
"childs": [ "childs": [
{"widget": "text", "label": "Пароль для входа в сеть ЦЗС", "name": "netCesPassword"}, {"widget": "text", "label": "Пароль для входа в сеть ЦЗС", "name": "cesPassword"},
{"widget": "h3", "label": "Настройки интерфейса управления"}, {"widget": "h3", "label": "Настройки интерфейса управления"},
{"widget": "ip-address", "label": "IP Интерфейса управления (/24)", "name": "netManagementIp"}, {"widget": "ip-address-mask", "label": "Интерфейс управления (a.d.d.r/mask)", "name": "managementIp"},
{"widget": "text", "label": "Имя веб-сервера", "name": "netServerName"} {"widget": "text", "label": "Имя веб-сервера", "name": "serverName"}
] ]
} }
] ]
@@ -170,11 +172,11 @@
"values": [{"label": "Ethernet", "value": "false"}, {"label": "Тест", "value": "true"}] "values": [{"label": "Ethernet", "value": "false"}, {"label": "Тест", "value": "true"}]
}, },
{"widget": "h3", "label": "Параметры передачи"}, {"widget": "h3", "label": "Параметры передачи"},
{"widget": "number-int", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 950000, "max": 6000000, "step": 0.01}, {"widget": "number-int", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 100000, "max": 6000000, "step": 0.01},
{"widget": "number-int", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 200000, "max": 54000000}, {"widget": "number-int", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 200000, "max": 54000000},
{ {
"widget": "select", "label": "Roll-off", "name": "txRolloff", "widget": "select", "label": "Roll-off", "name": "txRolloff",
"values": [{"label": "0.02", "value": "2"}, {"label": "0.05", "value": "5"}, {"label": "0.10", "value": "10"}, {"label": "0.15", "value": "15"}, {"label": "0.20", "value": "20"}, {"label": "0.25", "value": "25"}] "values": [{"label": "0.02", "value": "20"}, {"label": "0.05", "value": "50"}, {"label": "0.10", "value": "100"}, {"label": "0.15", "value": "150"}, {"label": "0.20", "value": "200"}, {"label": "0.25", "value": "250"}]
}, },
{ {
"widget": "select", "label": "Номер последовательности Голда", "name": "txGoldan", "widget": "select", "label": "Номер последовательности Голда", "name": "txGoldan",
@@ -217,7 +219,7 @@
{"widget": "checkbox", "label": "Авто-регулировка мощности", "name": "aupcEn"}, {"widget": "checkbox", "label": "Авто-регулировка мощности", "name": "aupcEn"},
{"widget": "number", "label": "Минимальное ослабление, дБ", "name": "aupcMinAttenuation", "min": 0, "step": 0.1, "max": 10}, {"widget": "number", "label": "Минимальное ослабление, дБ", "name": "aupcMinAttenuation", "min": 0, "step": 0.1, "max": 10},
{"widget": "number", "label": "Максимальное ослабление, дБ", "name": "aupcMaxAttenuation", "min": 0, "step": 0.1, "max": 10}, {"widget": "number", "label": "Максимальное ослабление, дБ", "name": "aupcMaxAttenuation", "min": 0, "step": 0.1, "max": 10},
{"widget": "number", "label": "Требуемое ОСШ", "name": "aupcRequiredSnr", "min": 0, "step": 0.01, "max": 10} {"widget": "number", "label": "Требуемое ОСШ", "name": "aupcRequiredSnr", "min": 0, "step": 0.01, "max": 30}
] ]
}, },
{ {
@@ -231,11 +233,11 @@
{"widget": "number", "label": "Усиление, дБ", "name": "rxManualGain", "min": -40, "step": 0.01, "max": 40, "v_show": "paramRxtx.rxAgcEn === false"}, {"widget": "number", "label": "Усиление, дБ", "name": "rxManualGain", "min": -40, "step": 0.01, "max": 40, "v_show": "paramRxtx.rxAgcEn === false"},
{"widget": "watch-expr", "label": "Текущее усиление", "expr": "paramRxtx.rxManualGain", "v_show": "paramRxtx.rxAgcEn === true"}, {"widget": "watch-expr", "label": "Текущее усиление", "expr": "paramRxtx.rxManualGain", "v_show": "paramRxtx.rxAgcEn === true"},
{"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"}, {"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"},
{"widget": "number-int", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 950000, "max": 6000000, "step": 0.01}, {"widget": "number-int", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 100000, "max": 6000000, "step": 0.01},
{"widget": "number-int", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000}, {"widget": "number-int", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000},
{ {
"widget": "select", "label": "Roll-off", "name": "rxRolloff", "widget": "select", "label": "Roll-off", "name": "rxRolloff",
"values": [{"label": "0.02", "value": "2"}, {"label": "0.05", "value": "5"}, {"label": "0.10", "value": "10"}, {"label": "0.15", "value": "15"}, {"label": "0.20", "value": "20"}, {"label": "0.25", "value": "25"}] "values": [{"label": "0.02", "value": "20"}, {"label": "0.05", "value": "50"}, {"label": "0.10", "value": "100"}, {"label": "0.15", "value": "150"}, {"label": "0.20", "value": "200"}, {"label": "0.25", "value": "250"}]
}, },
{ {
"widget": "select", "label": "Номер последовательности Голда", "name": "rxGoldan", "widget": "select", "label": "Номер последовательности Голда", "name": "rxGoldan",
@@ -252,20 +254,20 @@
"widget": "settings-container", "v_show": "paramRxtx.isCinC", "widget": "settings-container", "v_show": "paramRxtx.isCinC",
"childs": [ "childs": [
{ {
"widget": "select", "label": "Метод расчета задержки", "name": "dpdiIsPositional", "widget": "select", "label": "Метод расчета задержки", "name": "isPositional",
"values": [ "values": [
{"label": "Позиционированием", "value": "true"}, {"label": "Позиционированием", "value": "true"},
{"label": "Окном задержки", "value": "false"} {"label": "Окном задержки", "value": "false"}
] ]
}, },
{"widget": "number", "label": "Полоса поиска, КГц ±", "name": "dpdiSearchBandwidth", "min": 0, "step": 1, "max": 100}, {"widget": "number", "label": "Полоса поиска, КГц ±", "name": "searchBandwidth", "min": 0, "step": 1, "max": 100},
{"widget": "h2", "label": "Настройки позиционирования", "v_show": "paramDpdi.dpdiIsPositional === true"}, {"widget": "h2", "label": "Настройки позиционирования", "v_show": "paramDpdi.isPositional === true"},
{"widget": "number", "label": "Широта станции", "name": "dpdiPositionStationLatitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Широта станции", "name": "positionStationLatitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "number", "label": "Долгота станции", "name": "dpdiPositionStationLongitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Долгота станции", "name": "positionStationLongitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "number", "label": "Подспутниковая точка", "name": "dpdiPositionSatelliteLongitude", "v_show": "paramDpdi.dpdiIsPositional === true", "min": -180, "step": 0.000001, "max": 180}, {"widget": "number", "label": "Подспутниковая точка", "name": "positionSatelliteLongitude", "v_show": "paramDpdi.isPositional === true", "min": -180, "step": 0.000001, "max": 180},
{"widget": "h2", "label": "Задержка до спутника", "v_show": "paramDpdi.dpdiIsPositional === false"}, {"widget": "h2", "label": "Задержка до спутника", "v_show": "paramDpdi.isPositional === false"},
{"widget": "number", "label": "от, мс", "name": "dpdiDelayMin", "v_show": "paramDpdi.dpdiIsPositional === false", "min": 0, "step": 0.1, "max": 400}, {"widget": "number", "label": "от, мс", "name": "delayMin", "v_show": "paramDpdi.isPositional === false", "min": 0, "step": 0.1, "max": 400},
{"widget": "number", "label": "до, мс", "name": "dpdiDelayMax", "v_show": "paramDpdi.dpdiIsPositional === false", "min": 0, "step": 0.1, "max": 400}] {"widget": "number", "label": "до, мс", "name": "delayMax", "v_show": "paramDpdi.isPositional === false", "min": 0, "step": 0.1, "max": 400}]
}, },
{"widget": "submit", "v_show": "paramRxtx.isCinC"} {"widget": "submit", "v_show": "paramRxtx.isCinC"}
], ],
@@ -316,30 +318,20 @@
] ]
} }
], ],
"tcpaccel": [
{"widget": "h2", "label": "Настройки TCP-акселерации"},
{
"widget": "settings-container",
"childs": [
{"widget": "checkbox", "label": "Активировать акселерацию", "name": "accelEn"},
{"widget": "number", "label": "Максимальное количество соединений", "name": "accelMaxConnections", "min": 0, "step": 1, "max": 4000}
]
}
],
"network": [ "network": [
{"widget": "h2", "label": "Настройки сети"}, {"widget": "h2", "label": "Настройки сети"},
{ {
"widget": "settings-container", "widget": "settings-container",
"childs": [ "childs": [
{"widget": "h3", "label": "Настройки интерфейса управления"}, {"widget": "h3", "label": "Настройки интерфейса управления"},
{"widget": "ip-address", "label": "Интерфейс управления (/24)", "name": "netManagementIp"}, {"widget": "ip-address-mask", "label": "Интерфейс управления (a.d.d.r/mask)", "name": "managementIp"},
{ {
"widget": "select", "label": "Режим сети", "name": "netIsL2", "widget": "select", "label": "Режим сети", "name": "isL2",
"values": [{"label": "Маршрутизатор", "value": "false"}, {"label": "Коммутатор", "value": "true"}] "values": [{"label": "Маршрутизатор", "value": "false"}, {"label": "Коммутатор", "value": "true"}]
}, },
{"widget": "ip-address", "label": "Интерфейс данных (/24)", "name": "netDataIp", "v_show": "paramNetwork.netIsL2 === false"}, {"widget": "ip-address", "label": "Интерфейс данных (/24)", "name": "dataIp", "v_show": "paramNetwork.isL2 === false"},
{"widget": "number", "label": "MTU интерфейса данных", "name": "netDataMtu", "min": 1500, "step": 1, "max": 2000}, {"widget": "number", "label": "MTU интерфейса данных", "name": "dataMtu", "min": 1500, "step": 1, "max": 2000},
{"widget": "text", "label": "Имя веб-сервера", "name": "netServerName"} {"widget": "text", "label": "Имя веб-сервера", "name": "serverName"}
] ]
} }
] ]
@@ -378,20 +370,26 @@
"values": [{"label": "Ethernet", "value": "false"}, {"label": "Тест", "value": "true"}] "values": [{"label": "Ethernet", "value": "false"}, {"label": "Тест", "value": "true"}]
}, },
{"widget": "h3", "label": "Параметры передачи"}, {"widget": "h3", "label": "Параметры передачи"},
{"widget": "number", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 950000, "max": 6000000, "step": 0.01}, {"widget": "number", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 100000, "max": 6000000, "step": 0.01},
{"widget": "number", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 200000, "max": 54000000}, {"widget": "number", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 200000, "max": 54000000},
{ {
"widget": "select", "label": "Roll-off", "name": "txRolloff", "widget": "select", "label": "Roll-off", "name": "txRolloff",
"values": [{"label": "0.02", "value": "2"}, {"label": "0.05", "value": "5"}, {"label": "0.10", "value": "10"}, {"label": "0.15", "value": "15"}, {"label": "0.20", "value": "20"}, {"label": "0.25", "value": "25"}] "values": [{"label": "0.02", "value": "20"}, {"label": "0.05", "value": "50"}, {"label": "0.10", "value": "100"}, {"label": "0.15", "value": "150"}, {"label": "0.20", "value": "200"}, {"label": "0.25", "value": "250"}]
}, },
{"widget": "number", "label": "Коэф. расширения", "name": "txSpreadCoef", "max": 1000, "min": -1000, "step": 0.01}, {"widget": "number", "label": "Коэф. расширения", "name": "txSpreadCoef", "max": 1000, "min": -1000, "step": 0.01},
{
"widget": "select", "label": "Номер последовательности Голда", "name": "txGoldan",
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
},
{"widget": "number", "label": "Ослабление, дБ", "name": "txAttenuation", "max": 0, "min": -40, "step": 0.25} {"widget": "number", "label": "Ослабление, дБ", "name": "txAttenuation", "max": 0, "min": -40, "step": 0.25}
] ]
}, },
{
"widget": "settings-container",
"childs": [
{"widget": "h3", "label": "Авто-регулировка мощности"},
{"widget": "checkbox", "label": "Авто-регулировка мощности", "name": "aupcEn"},
{"widget": "number", "label": "Минимальное ослабление, дБ", "name": "aupcMinAttenuation", "min": 0, "step": 0.1, "max": 10},
{"widget": "number", "label": "Максимальное ослабление, дБ", "name": "aupcMaxAttenuation", "min": 0, "step": 0.1, "max": 10},
{"widget": "number", "label": "Требуемое ОСШ", "name": "aupcRequiredSnr", "min": 0, "step": 0.01, "max": 30}
]
},
{ {
"widget": "settings-container", "widget": "settings-container",
"childs": [ "childs": [
@@ -403,17 +401,13 @@
{"widget": "number", "label": "Усиление, дБ", "name": "rxManualGain", "min": -40, "step": 0.01, "max": 40, "v_show": "paramRxtx.rxAgcEn === false"}, {"widget": "number", "label": "Усиление, дБ", "name": "rxManualGain", "min": -40, "step": 0.01, "max": 40, "v_show": "paramRxtx.rxAgcEn === false"},
{"widget": "watch-expr", "label": "Текущее усиление", "expr": "paramRxtx.rxManualGain", "v_show": "paramRxtx.rxAgcEn === true"}, {"widget": "watch-expr", "label": "Текущее усиление", "expr": "paramRxtx.rxManualGain", "v_show": "paramRxtx.rxAgcEn === true"},
{"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"}, {"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"},
{"widget": "number", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 950000, "max": 6000000, "step": 0.01}, {"widget": "number", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 100000, "max": 6000000, "step": 0.01},
{"widget": "number", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000}, {"widget": "number", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000},
{ {
"widget": "select", "label": "Roll-off", "name": "rxRolloff", "widget": "select", "label": "Roll-off", "name": "rxRolloff",
"values": [{"label": "0.02", "value": "2"}, {"label": "0.05", "value": "5"}, {"label": "0.10", "value": "10"}, {"label": "0.15", "value": "15"}, {"label": "0.20", "value": "20"}, {"label": "0.25", "value": "25"}] "values": [{"label": "0.02", "value": "20"}, {"label": "0.05", "value": "50"}, {"label": "0.10", "value": "100"}, {"label": "0.15", "value": "150"}, {"label": "0.20", "value": "200"}, {"label": "0.25", "value": "250"}]
}, },
{"widget": "number", "label": "Коэф. расширения", "name": "rxSpreadCoef", "max": 1000, "min": -1000, "step": 0.01}, {"widget": "number", "label": "Коэф. расширения", "name": "rxSpreadCoef", "max": 1000, "min": -1000, "step": 0.01}
{
"widget": "select", "label": "Номер последовательности Голда", "name": "rxGoldan",
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
}
] ]
} }
] ]
@@ -465,6 +459,23 @@
} }
] ]
} }
],
"network": [
{"widget": "h2", "label": "Настройки сети"},
{
"widget": "settings-container",
"childs": [
{"widget": "h3", "label": "Настройки интерфейса управления"},
{"widget": "ip-address-mask", "label": "Интерфейс управления (a.d.d.r/mask)", "name": "managementIp"},
{
"widget": "select", "label": "Режим сети", "name": "isL2",
"values": [{"label": "Маршрутизатор", "value": "false"}, {"label": "Коммутатор", "value": "true"}]
},
{"widget": "ip-address", "label": "Интерфейс данных (/24)", "name": "dataIp", "v_show": "paramNetwork.isL2 === false"},
{"widget": "number", "label": "MTU интерфейса данных", "name": "dataMtu", "min": 1500, "step": 1, "max": 2000},
{"widget": "text", "label": "Имя веб-сервера", "name": "serverName"}
]
}
] ]
}, },
"tabs": [ "tabs": [

View File

@@ -72,3 +72,130 @@
this.submitStatus.modemReboot = 30 this.submitStatus.modemReboot = 30
fetch('/api/reboot', { method: 'POST' }).then((r) => {}) fetch('/api/reboot', { method: 'POST' }).then((r) => {})
}, },
async restoreAllSettings() {
// Порядок применения настроек
const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network'];
// 1. Чтение JSON-файла, выбранного пользователем
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.json';
const filePromise = new Promise((resolve, reject) => {
fileInput.onchange = e => {
const file = e.target.files[0];
if (!file) {
reject(new Error('Файл не выбран'));
return;
}
const reader = new FileReader();
reader.onload = event => {
try {
const jsonData = JSON.parse(event.target.result);
resolve(jsonData);
} catch (error) {
reject(new Error('Ошибка парсинга JSON'));
}
};
reader.onerror = () => reject(new Error('Ошибка чтения файла'));
reader.readAsText(file);
};
fileInput.click();
});
try {
const settingsToApply = await filePromise;
const errors = [];
// 2. Перебор групп параметров в заданном порядке
for (const groupName of settingsApplyOrder) {
if (!settingsToApply.hasOwnProperty(groupName)) {
continue; // Пропускаем группы, которых нет в файле
}
const groupSettings = settingsToApply[groupName];
if (typeof groupSettings !== 'object' || groupSettings === null) {
continue;
}
try {
// 2.1. POST-запрос для применения группы параметров
const postResponse = await fetch(`/api/set/${groupName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(groupSettings)
});
if (!postResponse.ok) {
throw new Error(`HTTP error ${postResponse.status}`);
}
const postResult = await postResponse.json();
if (postResult.status !== 'ok') {
throw new Error(`API error: ${postResult.message || 'unknown error'}`);
}
// 2.2. Проверка примененных параметров
const getResponse = await fetch('/api/get/settings', { method: 'GET' });
if (!getResponse.ok) {
throw new Error(`HTTP error ${getResponse.status}`);
}
const fetchSettingsResult = await getResponse.json();
if (fetchSettingsResult.status !== 'ok') {
throw new Error('Не удалось получить текущие настройки');
}
// Проверка соответствия параметров
const appliedGroup = fetchSettingsResult.settings[groupName] || {};
const failedSettings = [];
for (const [key, value] of Object.entries(groupSettings)) {
if (appliedGroup[key] !== value) {
failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`);
}
}
if (failedSettings.length > 0) {
throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`);
}
} catch (groupError) {
errors.push(`Группа ${groupName}: ${groupError.message}`);
}
}
// 3. Показ ошибок, если они есть
if (errors.length > 0) {
const errorMessage = errors.join('\n\n') +
'\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.';
alert(errorMessage);
}
} catch (error) {
alert(`Ошибка при восстановлении настроек: ${error.message}`);
return;
}
// 4. Перезагрузка страницы
location.reload();
},
async dumpAllSettings() {
function downloadAsFile(data, filename) {
let a = document.createElement("a");
let file = new Blob([data], {type: 'application/json'});
a.href = URL.createObjectURL(file);
a.download = filename;
a.click();
}
const response = await fetch('/api/get/settings', { method: 'GET' })
if (response.ok) {
const jres = await response.json()
if (jres["status"] === "ok") {
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
},

View File

@@ -21,6 +21,8 @@
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button> <button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
</div> </div>
<button class="action-button" @click="dumpAllSettings()">Сохранить бекап конфигурации</button>
<button class="dangerous-button" @click="restoreAllSettings()">Восстановить бекап конфигурации</button>
</div> </div>
<h2>Обновление ПО</h2> <h2>Обновление ПО</h2>

View File

@@ -24,7 +24,7 @@
update{{ g['group'] | title }}Settings(vals) { update{{ g['group'] | title }}Settings(vals) {
this.submitStatus.{{ g['group'] }} = false this.submitStatus.{{ g['group'] }} = false
{% for p in g['params'] %} {% for p in g['params'] %}
{{ build_setter_js(g['group'], p, "vals[\"settings\"][\"" ~ p['name'] ~ "\"]") }} {{ build_setter_js(g['group'], p, "vals[\"settings\"][\"" ~ g['group'] ~ "\"][\"" ~ p['name'] ~ "\"]") }}
{% endfor %} {% endfor %}
}, },
{% endfor %} {% endfor %}

View File

@@ -18,69 +18,68 @@
} }
this.lastUpdateTime = new Date(); this.lastUpdateTime = new Date();
this.initState = vals["mainState"]["initState"] this.initState = vals["state"]["initState"]
this.testState = vals["state"]["testState"]
{% if modem == 'scpc' %} {% if modem == 'scpc' %}
this.isCinC = vals["mainState"]["isCinC"] this.isCinC = vals["state"]["isCinC"]
{% endif %} {% endif %}
this.statRx.state = vals["mainState"]["rx.state"] this.statRx.state = vals["state"]["rx"]["state"]
this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"] this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"]
this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"] this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"]
this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"] this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"]
this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"] this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"]
this.statRx.snr = vals["mainState"]["rx.snr"] this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10
this.statRx.rssi = vals["mainState"]["rx.rssi"] this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10
this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"]) this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"])
this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"] this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"]
this.statRx.isPilots = vals["mainState"]["rx.isPilots"] this.statRx.isPilots = vals["state"]["rx"]["isPilots"]
this.statRx.symError = vals["mainState"]["rx.symError"] this.statRx.symError = vals["state"]["rx"]["symError"]
this.statRx.freqErr = vals["mainState"]["rx.freqErr"] this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100
this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"] this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100
this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"] this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"]
this.statRx.pllError = vals["mainState"]["rx.pllError"] this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100
this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"] this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100
this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"] this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100
this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"] this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"]
this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"] this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"]
this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"] this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"]
{% if modem == 'scpc' %} {% if modem == 'scpc' %}
this.statTx.state = vals["mainState"]["tx.state"] this.statTx.state = vals["state"]["tx"]["state"]
this.statTx.snr = vals["mainState"]["tx.snr"] this.statTx.snr = Math.round(vals["state"]["tx"]["snr"] * 100) / 100
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"])
this.statTx.frameSizeNormal = vals["mainState"]["tx.frameSizeNormal"] this.statTx.frameSizeNormal = vals["state"]["tx"]["frameSizeNormal"]
this.statTx.isPilots = vals["mainState"]["tx.isPilots"] this.statTx.isPilots = vals["state"]["tx"]["isPilots"]
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100
this.statCinc.occ = vals["mainState"]["cinc.occ"] this.statCinc.occ = vals["state"]["cinc"]["occ"]
this.statCinc.correlator = vals["mainState"]["cinc.correlator"] this.statCinc.correlator = vals["state"]["cinc"]["correlator"]
this.statCinc.correlatorFails = vals["mainState"]["cinc.correlatorFails"] this.statCinc.correlatorFails = vals["state"]["cinc"]["correlatorFails"]
this.statCinc.freqErr = vals["mainState"]["cinc.freqErr"] this.statCinc.freqErr = Math.round(vals["state"]["cinc"]["freqErr"] * 100) / 100
this.statCinc.freqErrAcc = vals["mainState"]["cinc.freqErrAcc"] this.statCinc.freqErrAcc = Math.round(vals["state"]["cinc"]["freqErrAcc"] * 100) / 100
this.statCinc.channelDelay = vals["mainState"]["cinc.channelDelay"] this.statCinc.channelDelay = vals["state"]["cinc"]["channelDelay"]
{% else %} {% else %}
this.statTx.state = vals["mainState"]["tx.state"] this.statTx.state = vals["state"]["tx"]["state"]
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"])
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100
this.statTx.centerFreq = vals["mainState"]["tx.centerFreq"] this.statTx.centerFreq = vals["state"]["tx"]["centerFreq"]
this.statTx.symSpeed = vals["mainState"]["tx.symSpeed"] this.statTx.symSpeed = vals["state"]["tx"]["symSpeed"]
{% endif %} {% endif %}
this.statDevice.adrv = vals["mainState"]["device.adrv"] this.statDevice.adrv = vals["state"]["device"]["adrv"]
this.statDevice.zynq = vals["mainState"]["device.zynq"] this.statDevice.zynq = vals["state"]["device"]["zynq"]
this.statDevice.fpga = vals["mainState"]["device.fpga"] this.statDevice.fpga = vals["state"]["device"]["fpga"]
{% if modem == 'tdma' %} {% if modem == 'tdma' %}
this.statDevice.upgradeStatus = vals["mainState"]["device.upgradeStatus"] this.statDevice.upgradeStatus = vals["state"]["device"]["upgradeStatus"]
this.statDevice.upgradePercent = vals["mainState"]["device.upgradePercent"] this.statDevice.upgradePercent = vals["state"]["device"]["upgradePercent"]
this.statDevice.upgradeImage = vals["mainState"]["device.upgradeImage"] this.statDevice.upgradeImage = vals["state"]["device"]["upgradeImage"]
{% endif %} {% endif %}
this.testState = vals["mainState"]["testState"]
// аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид
let uptime = vals["sysinfo"]["uptime"] let uptime = vals["state"]["device"]["uptime"]
if (uptime) { if (uptime) {
let secs = uptime % 60; uptime = Math.floor(uptime / 60) let secs = uptime % 60; uptime = Math.floor(uptime / 60)
let mins = uptime % 60; uptime = Math.floor(uptime / 60) let mins = uptime % 60; uptime = Math.floor(uptime / 60)
@@ -92,11 +91,11 @@
} else { } else {
this.statOs.uptime = '?' this.statOs.uptime = '?'
} }
this.statOs.load1 = vals["sysinfo"]["load1min"] this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100
this.statOs.load5 = vals["sysinfo"]["load5min"] this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100
this.statOs.load15 = vals["sysinfo"]["load15min"] this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100
this.statOs.totalram = vals["sysinfo"]["totalram"] this.statOs.totalram = vals["state"]["device"]["totalram"]
this.statOs.freeram = vals["sysinfo"]["freeram"] this.statOs.freeram = vals["state"]["device"]["freeram"]
}, },
resetPacketsStatistics() { resetPacketsStatistics() {

View File

@@ -44,15 +44,17 @@
} }
let query = { let query = {
"en": this.paramQos.en, "en": this.paramQos.en,
"rt1": [], "profile": {
"rt2": [], "rt1": [],
"rt3": [], "rt2": [],
"cd": [] "rt3": [],
"cd": []
}
} }
for (let i = 0; i < this.paramQos.rt1.length; i++) { query.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) } for (let i = 0; i < this.paramQos.rt1.length; i++) { query.profile.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) }
for (let i = 0; i < this.paramQos.rt2.length; i++) { query.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) } for (let i = 0; i < this.paramQos.rt2.length; i++) { query.profile.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) }
for (let i = 0; i < this.paramQos.rt3.length; i++) { query.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) } for (let i = 0; i < this.paramQos.rt3.length; i++) { query.profile.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) }
for (let i = 0; i < this.paramQos.cd.length; i++) { query.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) } for (let i = 0; i < this.paramQos.cd.length; i++) { query.profile.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) }
//console.log(query) //console.log(query)
fetch('/api/set/qos', { fetch('/api/set/qos', {
@@ -73,9 +75,9 @@
updateQosSettings(vals) { updateQosSettings(vals) {
this.submitStatusQos = false this.submitStatusQos = false
this.paramQos.en = vals["settings"]["qosEnabled"] this.paramQos.en = vals["settings"]["qos"]["en"]
const qosProfile = vals["settings"]["qosProfile"] const qosProfile = vals["settings"]["qos"]["profile"]
if (qosProfile !== null && qosProfile !== undefined) { if (qosProfile !== null && qosProfile !== undefined) {
this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length) this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length)
this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length) this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length)

View File

@@ -58,6 +58,10 @@
<span>{{ widget.label }}</span> <span>{{ widget.label }}</span>
<input v-model="param{{ param_group | title }}.{{ widget.name }}" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"> <input v-model="param{{ param_group | title }}.{{ widget.name }}" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
</label>{% endmacro %} </label>{% endmacro %}
{% macro build_widget_ip_address_mask(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
<span>{{ widget.label }}</span>
<input v-model="param{{ param_group | title }}.{{ widget.name }}" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$">
</label>{% endmacro %}
{% macro build_widget_text(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}> {% macro build_widget_text(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
<span>{{ widget.label }}</span> <span>{{ widget.label }}</span>
@@ -78,22 +82,23 @@
{% elif widget.widget == 'modulation-modcod' %}{{ build_widget_modulation_modcod(param_group, widget) }} {% elif widget.widget == 'modulation-modcod' %}{{ build_widget_modulation_modcod(param_group, widget) }}
{% elif widget.widget == 'modulation-speed' %}{{ build_widget_modulation_speed(param_group, widget) }} {% elif widget.widget == 'modulation-speed' %}{{ build_widget_modulation_speed(param_group, widget) }}
{% elif widget.widget == 'ip-address' %}{{ build_widget_ip_address(param_group, widget) }} {% elif widget.widget == 'ip-address' %}{{ build_widget_ip_address(param_group, widget) }}
{% elif widget.widget == 'ip-address-mask' %}{{ build_widget_ip_address_mask(param_group, widget) }}
{% elif widget.widget == 'text' %}{{ build_widget_text(param_group, widget) }} {% elif widget.widget == 'text' %}{{ build_widget_text(param_group, widget) }}
{% else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p> {% else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}
{% macro build_getter_js(param_group, widget) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{% {% macro build_getter_js(param_group, widget) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{%
elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'modulation-modcod', 'modulation-speed', 'text'] %}this.param{{ param_group | title }}.{{ widget.name }}{% elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'ip-address-mask', 'modulation-modcod', 'modulation-speed', 'text'] %}this.param{{ param_group | title }}.{{ widget.name }}{%
elif widget.widget == 'number-int' %}parseFloat(this.param{{ param_group | title }}.{{ widget.name }}.replace(/[^0-9,.]/g, '').replace(',', '.')){% elif widget.widget == 'number-int' %}parseFloat(this.param{{ param_group | title }}.{{ widget.name }}.replace(/[^0-9,.]/g, '').replace(',', '.')){%
else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %} else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %}
{% macro build_setter_js(param_group, widget, expr) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{% {% macro build_setter_js(param_group, widget, expr) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{%
elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'modulation-modcod', 'modulation-speed', 'text'] %}this.param{{ param_group | title }}.{{ widget.name }} = {{ expr }}{% elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'ip-address-mask', 'modulation-modcod', 'modulation-speed', 'text'] %}this.param{{ param_group | title }}.{{ widget.name }} = {{ expr }}{%
elif widget.widget == 'number-int' %}this.param{{ param_group | title }}.{{ widget.name }} = this.inputFormatNumber({{ expr }}, {{ js_build_number_number_validator(widget) }}){% elif widget.widget == 'number-int' %}this.param{{ param_group | title }}.{{ widget.name }} = this.inputFormatNumber({{ expr }}, {{ js_build_number_number_validator(widget) }}){%
else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %} else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %}
{% macro build_setter(param_group, widget, expr) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{% {% macro build_setter(param_group, widget, expr) %}{% if widget.widget in ['flex-container', 'settings-container', 'h2', 'h3', 'submit', 'watch', 'watch-expr'] %}null{%
elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'modulation-modcod', 'modulation-speed', 'text'] %}param{{ param_group | title }}.{{ widget.name }} = {{ expr }}{% elif widget.widget in ['checkbox', 'number', 'select', 'ip-address', 'ip-address-mask', 'modulation-modcod', 'modulation-speed', 'text'] %}param{{ param_group | title }}.{{ widget.name }} = {{ expr }}{%
elif widget.widget == 'number-int' %}param{{ param_group | title }}.{{ widget.name }} = inputFormatNumber({{ expr }}, {{ js_build_number_number_validator(widget) }}){% elif widget.widget == 'number-int' %}param{{ param_group | title }}.{{ widget.name }} = inputFormatNumber({{ expr }}, {{ js_build_number_number_validator(widget) }}){%
else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %} else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>{% endif %}{% endmacro %}

View File

@@ -235,11 +235,11 @@
try { try {
const fr = await fetch("/api/get/aboutFirmware") const fr = await fetch("/api/get/aboutFirmware")
const d = await fr.json() const d = await fr.json()
this.about.firmwareVersion = d["fw.version"] this.about.firmwareVersion = d["firmware"]["version"]
this.about.modemUid = d["fw.modemId"] this.about.modemUid = d["firmware"]["modemId"]
this.about.modemSn = d["fw.modemSn"] this.about.modemSn = d["firmware"]["modemSn"]
this.about.macManagement = d["fw.macMang"] this.about.macManagement = d["firmware"]["macMang"]
this.about.macData = d["fw.macData"] this.about.macData = d["firmware"]["macData"]
} catch (e) { } catch (e) {
console.log('Ошибка загрузки версии ПО', e) console.log('Ошибка загрузки версии ПО', e)
} }

View File

@@ -105,9 +105,12 @@ void api_driver::TerminalApiDaemon::run() {
#endif #endif
// обновление статистики // обновление статистики
{.uo = CpUpdatebleObject([this]() { {.uo = CpUpdatebleObject([this]() {
std::shared_lock _slock1(this->settingsMutex);
obj::TerminalState tmp(state); obj::TerminalState tmp;
_slock1.release(); {
std::shared_lock _slock1(this->settingsMutex);
tmp = state;
}
tmp.updateCallback(cp); tmp.updateCallback(cp);
std::lock_guard _slock2(this->settingsMutex); std::lock_guard _slock2(this->settingsMutex);
@@ -128,9 +131,11 @@ void api_driver::TerminalApiDaemon::run() {
}, CACHE_SETTINGS_UPDATE_MS), .updaterName = "updateRxTxSettings"}, }, CACHE_SETTINGS_UPDATE_MS), .updaterName = "updateRxTxSettings"},
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE #ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
{.uo = CpUpdatebleObject([this]() { {.uo = CpUpdatebleObject([this]() {
std::shared_lock _slock1(this->settingsMutex); obj::TerminalNetworkSettings net;
obj::TerminalNetworkSettings net(settingsNetwork); {
_slock1.release(); std::shared_lock _slock1(this->settingsMutex);
net = settingsNetwork;
}
net.updateCallback(cp); net.updateCallback(cp);
std::lock_guard _slock2(this->settingsMutex); std::lock_guard _slock2(this->settingsMutex);
@@ -201,6 +206,51 @@ void api_driver::TerminalApiDaemon::getDeviceState(obj::TerminalDeviceState &des
dest = stateDev; dest = stateDev;
} }
api_driver::obj::TerminalRxTxSettings api_driver::TerminalApiDaemon::getSettingsRxTx() {
obj::TerminalRxTxSettings s;
{
std::shared_lock _olock(this->settingsMutex);
s = settingsRxTx;
}
return s;
}
void api_driver::TerminalApiDaemon::setSettingsRxTx(obj::TerminalRxTxSettings &s) {
std::lock_guard _olock(settingsMutex);
settingsRxTx = s;
}
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
api_driver::obj::TerminalNetworkSettings api_driver::TerminalApiDaemon::getNetworkSettings() {
obj::TerminalNetworkSettings s;
{
std::shared_lock _olock(this->settingsMutex);
s = settingsNetwork;
}
return s;
}
void api_driver::TerminalApiDaemon::setNetworkSettings(obj::TerminalNetworkSettings &s) {
std::lock_guard _olock(settingsMutex);
settingsNetwork = s;
}
#endif
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE
api_driver::obj::TerminalQosSettings api_driver::TerminalApiDaemon::getQosSettings() {
obj::TerminalQosSettings s;
{
std::shared_lock _olock(this->settingsMutex);
s = settingsQos;
}
return s;
}
void api_driver::TerminalApiDaemon::setQosSettings(obj::TerminalQosSettings &s) {
std::lock_guard _olock(settingsMutex);
settingsQos = s;
}
#endif
api_driver::obj::TerminalFirmwareVersion api_driver::TerminalApiDaemon::getFirmware() { api_driver::obj::TerminalFirmwareVersion api_driver::TerminalApiDaemon::getFirmware() {
obj::TerminalFirmwareVersion res; obj::TerminalFirmwareVersion res;

View File

@@ -52,17 +52,17 @@ namespace api_driver {
// * Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. // * Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
// * Установка настроек просто копирует настройки и устанавливает их текущими // * Установка настроек просто копирует настройки и устанавливает их текущими
// */ // */
obj::TerminalRxTxSettings getSettingsRxTx() const; obj::TerminalRxTxSettings getSettingsRxTx();
void setSettingsRxTx(obj::TerminalRxTxSettings &s); void setSettingsRxTx(obj::TerminalRxTxSettings &s);
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE #ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
obj::TerminalNetworkSettings getNetworkSettings() const; obj::TerminalNetworkSettings getNetworkSettings();
void setNetworkSettings(obj::TerminalNetworkSettings &s); void setNetworkSettings(obj::TerminalNetworkSettings &s);
#endif #endif
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE #ifdef API_OBJECT_QOS_SETTINGS_ENABLE
obj::TerminalQosSettings getQosSettings() const; obj::TerminalQosSettings getQosSettings();
void setQosSettings(bool enabled, const std::string &str); void setQosSettings(obj::TerminalQosSettings &s);
#endif #endif
obj::TerminalFirmwareVersion getFirmware(); obj::TerminalFirmwareVersion getFirmware();

View File

@@ -67,18 +67,21 @@ void api_driver::proxy::CpProxy::setDemodSettings(demodulator_settings &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::setDemodSettings", CP_SetDemodulatorSettings, (sid, dest), "struct {...}"); CPAPI_PROXY_CALL_HELPER("CpProxy::setDemodSettings", CP_SetDemodulatorSettings, (sid, dest), "struct {...}");
} }
#ifdef API_STRUCT_ACM_ENABLE
void api_driver::proxy::CpProxy::getAcmSettings(ACM_parameters_serv_ &dest) { void api_driver::proxy::CpProxy::getAcmSettings(ACM_parameters_serv_ &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getAcmSettings", CP_GetAcmParams, (sid, &dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getAcmSettings", CP_GetAcmParams, (sid, &dest), "");
} }
void api_driver::proxy::CpProxy::setAcmSettings(ACM_parameters_serv_ &dest) { void api_driver::proxy::CpProxy::setAcmSettings(ACM_parameters_serv_ &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::setAcmSettings", CP_GetAcmParams, (sid, &dest), "struct {...}"); CPAPI_PROXY_CALL_HELPER("CpProxy::setAcmSettings", CP_SetAcmParams, (sid, dest), "struct {...}");
} }
#endif
void api_driver::proxy::CpProxy::getDeviceState(device_state &dest) { void api_driver::proxy::CpProxy::getDeviceState(device_state &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getDeviceState", CP_GetDeviceState, (sid, dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getDeviceState", CP_GetDeviceState, (sid, dest), "");
} }
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE
std::tuple<std::string, bool> api_driver::proxy::CpProxy::getQosSettings() { std::tuple<std::string, bool> api_driver::proxy::CpProxy::getQosSettings() {
std::string rules; std::string rules;
bool en; bool en;
@@ -89,7 +92,9 @@ std::tuple<std::string, bool> api_driver::proxy::CpProxy::getQosSettings() {
void api_driver::proxy::CpProxy::setQosSettings(const std::string &rules, bool enable) { void api_driver::proxy::CpProxy::setQosSettings(const std::string &rules, bool enable) {
CPAPI_PROXY_CALL_HELPER("CpProxy::setQosSettings", CP_SetQoSSettings, (sid, rules, enable), "`" << rules << "`, " << (enable ? "true" : "false")); CPAPI_PROXY_CALL_HELPER("CpProxy::setQosSettings", CP_SetQoSSettings, (sid, rules, enable), "`" << rules << "`, " << (enable ? "true" : "false"));
} }
#endif
#ifdef API_OBJECT_DPDI_SETTINGS_ENABLE
void api_driver::proxy::CpProxy::getDpdiSettings(DPDI_parmeters &dest) { void api_driver::proxy::CpProxy::getDpdiSettings(DPDI_parmeters &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getDpdiSettings", CP_GetDpdiParams, (sid, &dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getDpdiSettings", CP_GetDpdiParams, (sid, &dest), "");
} }
@@ -97,7 +102,9 @@ void api_driver::proxy::CpProxy::getDpdiSettings(DPDI_parmeters &dest) {
void api_driver::proxy::CpProxy::setDpdiSettings(DPDI_parmeters &dest) { void api_driver::proxy::CpProxy::setDpdiSettings(DPDI_parmeters &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::setDpdiSettings", CP_SetDpdiParams, (sid, dest), "struct {...}"); CPAPI_PROXY_CALL_HELPER("CpProxy::setDpdiSettings", CP_SetDpdiParams, (sid, dest), "struct {...}");
} }
#endif
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
void api_driver::proxy::CpProxy::getBuclnbSettings(buc_lnb_settings &dest) { void api_driver::proxy::CpProxy::getBuclnbSettings(buc_lnb_settings &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getBuclnbSettings", CP_GetBUC_LNB_settings, (sid, dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getBuclnbSettings", CP_GetBUC_LNB_settings, (sid, dest), "");
} }
@@ -105,14 +112,25 @@ void api_driver::proxy::CpProxy::getBuclnbSettings(buc_lnb_settings &dest) {
void api_driver::proxy::CpProxy::setBuclnbSettings(buc_lnb_settings &dest) { void api_driver::proxy::CpProxy::setBuclnbSettings(buc_lnb_settings &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::setBuclnbSettings", CP_SetBUC_LNB_settings, (sid, dest), "struct {...}"); CPAPI_PROXY_CALL_HELPER("CpProxy::setBuclnbSettings", CP_SetBUC_LNB_settings, (sid, dest), "struct {...}");
} }
#endif
#ifdef MODEM_IS_SCPC
void api_driver::proxy::CpProxy::getCincState(CinC_state &dest) { void api_driver::proxy::CpProxy::getCincState(CinC_state &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getCincState", CP_GetCinCState, (sid, dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getCincState", CP_GetCinCState, (sid, dest), "");
} }
#endif
#ifdef API_OBJECT_DEBUG_METRICS_ENABLE
void api_driver::proxy::CpProxy::getDebugMetrics(debug_metrics &dest) { void api_driver::proxy::CpProxy::getDebugMetrics(debug_metrics &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getDebugMetrics", CP_GetDebugMetrics, (sid, dest), ""); CPAPI_PROXY_CALL_HELPER("CpProxy::getDebugMetrics", CP_GetDebugMetrics, (sid, dest), "");
} }
#endif
#ifdef MODEM_IS_TDMA
void api_driver::proxy::CpProxy::getUpdateStatus(progress_msg &dest) {
CPAPI_PROXY_CALL_HELPER("CpProxy::getUpdateStatus", CP_GetUpdateStatus, (sid, dest), "");
}
#endif
api_driver::proxy::CpProxy::~CpProxy() { api_driver::proxy::CpProxy::~CpProxy() {
disconnect(); disconnect();

View File

@@ -6,11 +6,11 @@
#define API_OBJECT_DEBUG_METRICS_ENABLE #define API_OBJECT_DEBUG_METRICS_ENABLE
#endif #endif
#if defined(MODEM_IS_SCPC) #if defined(MODEM_IS_SCPC) || defined(MODEM_IS_SHPS)
#define API_STRUCT_ACM_ENABLE #define API_STRUCT_ACM_ENABLE
#endif #endif
#if defined(MODEM_IS_SCPC) || defined(MODEM_IS_TDMA) #if defined(MODEM_IS_SCPC) || defined(MODEM_IS_TDMA) || defined(MODEM_IS_SHPS)
#define API_OBJECT_NETWORK_SETTINGS_ENABLE #define API_OBJECT_NETWORK_SETTINGS_ENABLE
#endif #endif

View File

@@ -9,50 +9,6 @@
#define TIME_NOW() std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count() #define TIME_NOW() std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count()
typedef boost::property_tree::ptree::path_type json_path;
// static int calculateSubnetMask(const std::string& subnet_mask) {
// int mask = 0;
// std::istringstream iss(subnet_mask);
// std::string octet;
// while (std::getline(iss, octet, '.')) {
// int octet_value = std::stoi(octet);
// for (int i = 7; i >= 0; i--) {
// if (octet_value & (1 << i)) {
// mask++;
// }
// }
// }
// return mask;
// }
/**
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
*/
// std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
// auto pos = input.find('/');
// if (pos == std::string::npos) {
// // Обработка ошибки: нет символа '/'
// throw std::runtime_error("address not contains mask");
// }
// std::string ip = input.substr(0, pos);
// const unsigned int mask_int = std::stoul(input.substr(pos + 1));
//
// if (mask_int > 32) {
// throw std::runtime_error("invalid mask");
// }
//
// std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
// std::string mask_str;
//
// for (unsigned int i = 0; i < 4; ++i) {
// std::string octet = mask_binary.substr(i * 8u, 8);
// int octet_value = std::stoi(octet, nullptr, 2);
// mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
// }
//
// return std::make_pair(ip, mask_str);
// }
static inline void rtrim(std::string &s) { static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) { s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch); return !std::isspace(ch);
@@ -94,14 +50,13 @@ std::string makeTimepointFromMillis(int64_t unix_time_ms) {
#ifdef API_OBJECT_DEBUG_METRICS_ENABLE #ifdef API_OBJECT_DEBUG_METRICS_ENABLE
api_driver::obj::StatisticsLogger::StatisticsLogger(): timeStart(TIME_NOW()) {} api_driver::obj::StatisticsLogger::StatisticsLogger(): timeStart(TIME_NOW()) {}
std::string api_driver::obj::StatisticsLogger::getSettings() { nlohmann::json api_driver::obj::StatisticsLogger::getSettings() {
std::lock_guard _lock(mutex); std::lock_guard _lock(mutex);
std::stringstream res; nlohmann::json res;
res << "{\"en\":" << boolAsStr(this->logEn); res["en"] = this->logEn;
res << ",\"logPeriodMs\":" << logPeriodMs; res["logPeriodMs"] = logPeriodMs.load();
res << ",\"maxAgeMs\":" << maxAgeMs; res["maxAgeMs"] = maxAgeMs.load();
res << '}'; return res;
return res.str();
} }
void api_driver::obj::StatisticsLogger::setSettings(const nlohmann::json& data) { void api_driver::obj::StatisticsLogger::setSettings(const nlohmann::json& data) {
@@ -178,6 +133,49 @@ api_driver::obj::StatisticsLogger::~StatisticsLogger() = default;
#endif #endif
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE #ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
static int calculateSubnetMask(const std::string& subnet_mask) {
int mask = 0;
std::istringstream iss(subnet_mask);
std::string octet;
while (std::getline(iss, octet, '.')) {
int octet_value = std::stoi(octet);
for (int i = 7; i >= 0; i--) {
if (octet_value & (1 << i)) {
mask++;
}
}
}
return mask;
}
/**
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
*/
std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
auto pos = input.find('/');
if (pos == std::string::npos) {
// Обработка ошибки: нет символа '/'
throw std::runtime_error("address not contains mask");
}
std::string ip = input.substr(0, pos);
const unsigned int mask_int = std::stoul(input.substr(pos + 1));
if (mask_int > 32) {
throw std::runtime_error("invalid mask");
}
std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
std::string mask_str;
for (unsigned int i = 0; i < 4; ++i) {
std::string octet = mask_binary.substr(i * 8u, 8);
int octet_value = std::stoi(octet, nullptr, 2);
mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
}
return std::make_pair(ip, mask_str);
}
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings() { loadDefaults(); } api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings() { loadDefaults(); }
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const TerminalNetworkSettings &src) = default; api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const TerminalNetworkSettings &src) = default;
@@ -185,7 +183,7 @@ api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const Terminal
api_driver::obj::TerminalNetworkSettings & api_driver::obj::TerminalNetworkSettings::operator=(const TerminalNetworkSettings &src) = default; api_driver::obj::TerminalNetworkSettings & api_driver::obj::TerminalNetworkSettings::operator=(const TerminalNetworkSettings &src) = default;
void api_driver::obj::TerminalNetworkSettings::loadDefaults() { void api_driver::obj::TerminalNetworkSettings::loadDefaults() {
managementIp = "0.0.0.0"; managementIp = "0.0.0.0/24";
managementGateway = ""; managementGateway = "";
isL2 = true; isL2 = true;
dataIp = "0.0.0.0"; dataIp = "0.0.0.0";
@@ -197,8 +195,8 @@ void api_driver::obj::TerminalNetworkSettings::updateCallback(proxy::CpProxy &cp
loadDefaults(); loadDefaults();
try { try {
managementIp = cp.getNetwork("addr"); managementIp = cp.getNetwork("addr");
// s.managementIp += "/"; managementIp += "/";
// s.managementIp += std::to_string(calculateSubnetMask(cp.getNetwork("mask"))); managementIp += std::to_string(calculateSubnetMask(cp.getNetwork("mask")));
managementGateway = cp.getNetwork("gateway"); managementGateway = cp.getNetwork("gateway");
if (cp.getNetwork("mode") == "tun") { if (cp.getNetwork("mode") == "tun") {
@@ -217,7 +215,7 @@ void api_driver::obj::TerminalNetworkSettings::updateCallback(proxy::CpProxy &cp
} }
} }
void api_driver::obj::TerminalNetworkSettings::updateFromJson(nlohmann::json &data) { void api_driver::obj::TerminalNetworkSettings::updateFromJson(const nlohmann::json &data) {
managementIp = data.value("managementIp", managementIp); managementIp = data.value("managementIp", managementIp);
isL2 = data.value("isL2", isL2); isL2 = data.value("isL2", isL2);
dataIp = data.value("dataIp", dataIp); dataIp = data.value("dataIp", dataIp);
@@ -228,12 +226,13 @@ void api_driver::obj::TerminalNetworkSettings::updateFromJson(nlohmann::json &da
void api_driver::obj::TerminalNetworkSettings::store(proxy::CpProxy& cp) { void api_driver::obj::TerminalNetworkSettings::store(proxy::CpProxy& cp) {
try { try {
cp.setNetwork("mode", isL2 ? "tap" : "tun"); cp.setNetwork("mode", isL2 ? "tap" : "tun");
cp.setNetwork("addr", managementIp); auto [mAddr, mMask] = splitIpAndMask(managementIp);
cp.setNetwork("addr", mAddr);
cp.setNetwork("mask", mMask);
if (!isL2) { if (!isL2) {
cp.setNetwork("addr_data", dataIp); cp.setNetwork("addr_data", dataIp);
} }
cp.setNetwork("mask", "255.255.255.0");
cp.setNetwork("gateway", managementGateway); cp.setNetwork("gateway", managementGateway);
// cp.setNetwork("data_mtu", std::to_string(dataMtu)); // cp.setNetwork("data_mtu", std::to_string(dataMtu));
@@ -279,7 +278,7 @@ void api_driver::obj::TerminalQosSettings::updateCallback(proxy::CpProxy &cp) {
} }
} }
void api_driver::obj::TerminalQosSettings::updateFromJson(nlohmann::json &data) { void api_driver::obj::TerminalQosSettings::updateFromJson(const nlohmann::json &data) {
qosEnabled = data.value("en", qosEnabled); qosEnabled = data.value("en", qosEnabled);
qosSettingsJson = data.value("profile", qosSettingsJson); qosSettingsJson = data.value("profile", qosSettingsJson);
} }
@@ -391,10 +390,8 @@ void api_driver::obj::TerminalState::updateCallback(proxy::CpProxy& cp) {
fCincFreqErrAcc = cinc.freq_fine_estimate; fCincFreqErrAcc = cinc.freq_fine_estimate;
fCincChannelDelay = cinc.delay_dpdi; fCincChannelDelay = cinc.delay_dpdi;
#endif #endif
#ifdef MODEM_IS_TDMA
fTxCenterFreq = modSet.central_freq_in_kGz; fTxCenterFreq = modSet.central_freq_in_kGz;
fTxSymSpeed = static_cast<double>(modSet.baudrate) / 1000.0; fTxSymSpeed = static_cast<double>(modSet.baudrate) / 1000.0;
#endif
} }
nlohmann::json api_driver::obj::TerminalState::asJson() { nlohmann::json api_driver::obj::TerminalState::asJson() {
@@ -402,7 +399,6 @@ nlohmann::json api_driver::obj::TerminalState::asJson() {
res["initState"] = fInitState; res["initState"] = fInitState;
res["testState"] = fIsTest; res["testState"] = fIsTest;
res["fTxState"] = fIsTest;
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
res["isCinC"] = fIsCinC; res["isCinC"] = fIsCinC;
#endif #endif
@@ -431,6 +427,7 @@ nlohmann::json api_driver::obj::TerminalState::asJson() {
res["rx"]["packetsDummy"] = fRxPacketsDummy; res["rx"]["packetsDummy"] = fRxPacketsDummy;
res["tx"]["modcod"] = fTxModcod; res["tx"]["modcod"] = fTxModcod;
res["tx"]["state"] = fTxState;
res["tx"]["speedOnTxKbit"] = fTxSpeedOnTxKbit; res["tx"]["speedOnTxKbit"] = fTxSpeedOnTxKbit;
res["tx"]["speedOnIifKbit"] = fTxSpeedOnIifKbit; res["tx"]["speedOnIifKbit"] = fTxSpeedOnIifKbit;
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
@@ -454,10 +451,8 @@ nlohmann::json api_driver::obj::TerminalState::asJson() {
res["cinc"]["correlator"] = nullptr; res["cinc"]["correlator"] = nullptr;
} }
#endif #endif
#ifdef MODEM_IS_TDMA
res["tx"]["centerFreq"] = fTxCenterFreq; res["tx"]["centerFreq"] = fTxCenterFreq;
res["tx"]["symSpeed"] = fTxSymSpeed; res["tx"]["symSpeed"] = fTxSymSpeed;
#endif
return res; return res;
} }
@@ -639,16 +634,16 @@ void api_driver::obj::TerminalRxTxSettings::updateMainSettings(const nlohmann::j
mod.is_cinc = data.value("isCinC", mod.is_cinc); mod.is_cinc = data.value("isCinC", mod.is_cinc);
#endif #endif
mod.tx_is_on = data.value("txEn", mod.tx_is_on); mod.tx_is_on = data.value("txEn", mod.tx_is_on);
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
mod.is_save_current_state = data.value("txAutoStart", mod.is_save_current_state); mod.is_save_current_state = data.value("txAutoStart", mod.is_save_current_state);
mod.is_test_data = data.value("txIsTestInput", mod.is_test_data); mod.is_test_data = data.value("txIsTestInput", mod.is_test_data);
#endif #endif
mod.is_carrier = !data.value("txModulatorIsTest", !mod.is_carrier); mod.is_carrier = !data.value("txModulatorIsTest", !mod.is_carrier);
mod.central_freq_in_kGz = data.value("txCentralFreq", mod.central_freq_in_kGz); mod.central_freq_in_kGz = data.value("txCentralFreq", mod.central_freq_in_kGz);
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
mod.baudrate = data.value("txBaudrate", mod.baudrate); mod.baudrate = data.value("txBaudrate", mod.baudrate);
mod.rollof = data.value("txRolloff", mod.rollof); mod.rollof = data.value("txRolloff", mod.rollof);
mod.gold_seq_is_active = data.value("txGoldan", mod.gold_seq_is_active); mod.gold_seq_is_active = data.value("txGoldan", mod.gold_seq_is_active ? 1 : 0);
#endif #endif
mod.attenuation = data.value("txAttenuation", mod.attenuation); mod.attenuation = data.value("txAttenuation", mod.attenuation);
@@ -660,6 +655,9 @@ void api_driver::obj::TerminalRxTxSettings::updateMainSettings(const nlohmann::j
acmIsPilots = data.value("txIsPilots", acmIsPilots); acmIsPilots = data.value("txIsPilots", acmIsPilots);
mod.modcod_tx = buildModcodFromJson(data, mod.modcod_tx, "dvbCcm", acmIsFrameSizeNormal, acmIsPilots); mod.modcod_tx = buildModcodFromJson(data, mod.modcod_tx, "dvbCcm", acmIsFrameSizeNormal, acmIsPilots);
#endif #endif
#ifdef MODEM_IS_SHPS
mod.koef_spread = data.value("txSpreadCoef", mod.koef_spread);
#endif
// демодулятор // демодулятор
dem.is_aru_on = data.value("rxAgcEn", dem.is_aru_on); dem.is_aru_on = data.value("rxAgcEn", dem.is_aru_on);
@@ -668,18 +666,21 @@ void api_driver::obj::TerminalRxTxSettings::updateMainSettings(const nlohmann::j
dem.central_freq_in_kGz = data.value("rxCentralFreq", dem.central_freq_in_kGz); dem.central_freq_in_kGz = data.value("rxCentralFreq", dem.central_freq_in_kGz);
dem.baudrate = data.value("rxBaudrate", dem.baudrate); dem.baudrate = data.value("rxBaudrate", dem.baudrate);
dem.rollof = data.value("rxRolloff", dem.rollof); dem.rollof = data.value("rxRolloff", dem.rollof);
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
dem.gold_seq_is_active = data.value("rxGoldan", dem.gold_seq_is_active); dem.gold_seq_is_active = data.value("rxGoldan", dem.gold_seq_is_active ? 1 : 0);
#endif
#ifdef MODEM_IS_SHPS
dem.koef_spread = data.value("rxSpreadCoef", dem.koef_spread);
#endif #endif
#ifdef API_STRUCT_ACM_ENABLE #ifdef API_STRUCT_ACM_ENABLE
// ACM // ACM
#ifndef MODEM_IS_SHPS #ifdef MODEM_IS_SCPC
// в ШПС этих настроек нет // эти настройки только в SCPC
acm.period_pack_acm = data.value("dvbServicePacketPeriod", acm.period_pack_acm); acm.period_pack_acm = data.value("dvbServicePacketPeriod", acm.period_pack_acm);
acm.enable_acm = data.value("dvbIsAcm", acm.enable_acm); acm.enable_acm = data.value("dvbIsAcm", acm.enable_acm);
acm.min_modcod_acm = buildModcodFromJson(data, acm.min_modcod_acm, "dvbAcmMin", acmIsFrameSizeNormal, acmIsPilots); acm.min_modcod_acm = buildModcodFromJson(data, acm.min_modcod_acm, "dvbAcmMin", acmIsFrameSizeNormal, acmIsPilots);
acm.min_modcod_acm = buildModcodFromJson(data, acm.max_modcod_acm, "dvbAcmMax", acmIsFrameSizeNormal, acmIsPilots); acm.max_modcod_acm = buildModcodFromJson(data, acm.max_modcod_acm, "dvbAcmMax", acmIsFrameSizeNormal, acmIsPilots);
acm.snr_threashold_acm = data.value("dvbSnrReserve", acm.snr_threashold_acm); // запас ОСШ acm.snr_threashold_acm = data.value("dvbSnrReserve", acm.snr_threashold_acm); // запас ОСШ
#endif #endif
@@ -703,38 +704,38 @@ static std::tuple<uint8_t, uint8_t> translateCoordinates(double abs) {
} }
void api_driver::obj::TerminalRxTxSettings::updateDpdiSettings(const nlohmann::json &data) { void api_driver::obj::TerminalRxTxSettings::updateDpdiSettings(const nlohmann::json &data) {
dpdi.is_delay_window = !data.value("dpdiIsPositional", !dpdi.is_delay_window); dpdi.is_delay_window = !data.value("isPositional", !dpdi.is_delay_window);
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
dpdi.freq_offset = data.value("dpdiSearchBandwidth", dpdi.freq_offset); dpdi.freq_offset = data.value("searchBandwidth", dpdi.freq_offset);
#endif #endif
if (data["dpdiPositionStationLatitude"]) { if (data.contains("positionStationLatitude")) {
const double pos = data["dpdiPositionStationLatitude"]; const double pos = data["positionStationLatitude"];
const auto [g, m] = translateCoordinates(pos); const auto [g, m] = translateCoordinates(pos);
dpdi.latitude_station_grad = g; dpdi.latitude_station_grad = g;
dpdi.latitude_station_minute = m; dpdi.latitude_station_minute = m;
} }
if (data["dpdiPositionStationLongitude"]) { if (data.contains("positionStationLongitude")) {
const double pos = data["dpdiPositionStationLongitude"]; const double pos = data["positionStationLongitude"];
const auto [g, m] = translateCoordinates(pos); const auto [g, m] = translateCoordinates(pos);
dpdi.longitude_station_grad = g; dpdi.longitude_station_grad = g;
dpdi.longitude_station_minute = m; dpdi.longitude_station_minute = m;
} }
if (data["dpdiPositionSatelliteLongitude"]) { if (data.contains("positionSatelliteLongitude")) {
const double pos = data["dpdiPositionSatelliteLongitude"]; const double pos = data["positionSatelliteLongitude"];
const auto [g, m] = translateCoordinates(pos); const auto [g, m] = translateCoordinates(pos);
dpdi.longitude_sattelite_grad = g; dpdi.longitude_sattelite_grad = g;
dpdi.longitude_sattelite_minute = m; dpdi.longitude_sattelite_minute = m;
} }
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
dpdi.min_delay = data.value("dpdiDelayMin", dpdi.min_delay); dpdi.min_delay = data.value("delayMin", dpdi.min_delay);
dpdi.max_delay = data.value("dpdiDelayMax", dpdi.max_delay); dpdi.max_delay = data.value("delayMax", dpdi.max_delay);
#else #else
s.min_delay = 0; dpdi.min_delay = 0;
s.max_delay = data.value("dpdiDelay", dpdi.max_delay); dpdi.max_delay = data.value("delay", dpdi.max_delay);
#endif #endif
} }
void api_driver::obj::TerminalRxTxSettings::storeDpdiSettings(proxy::CpProxy &cp) { void api_driver::obj::TerminalRxTxSettings::storeDpdiSettings(proxy::CpProxy &cp) {
@@ -764,6 +765,9 @@ void api_driver::obj::TerminalRxTxSettings::updateBuclnbSettings(const nlohmann:
} }
} }
buclnb.is_ref_10MHz_buc = data.value("bucRefClk10M", buclnb.is_ref_10MHz_buc); buclnb.is_ref_10MHz_buc = data.value("bucRefClk10M", buclnb.is_ref_10MHz_buc);
#ifdef MODEM_IS_TDMA
buclnb.lo_buc_inkHz = data.value("bucLoKhz", buclnb.lo_buc_inkHz);
#endif
{ {
// напряжение lnb // напряжение lnb
@@ -783,8 +787,10 @@ void api_driver::obj::TerminalRxTxSettings::updateBuclnbSettings(const nlohmann:
default: buclnb.lnb = voltage_lnb::DISABLE; default: buclnb.lnb = voltage_lnb::DISABLE;
} }
} }
buclnb.is_ref_10MHz_lnb = data.value("lnbRefClk10M", buclnb.is_ref_10MHz_lnb); buclnb.is_ref_10MHz_lnb = data.value("lnbRefClk10M", buclnb.is_ref_10MHz_lnb);
#ifdef MODEM_IS_TDMA
buclnb.lo_lnb_inkHz = data.value("lnbLoKhz", buclnb.lo_lnb_inkHz);
#endif
buclnb.is_ref_10MHz_output = data.value("srvRefClk10M", buclnb.is_ref_10MHz_output); buclnb.is_ref_10MHz_output = data.value("srvRefClk10M", buclnb.is_ref_10MHz_output);
buclnb.is_save_current_state = data.value("bucLnbAutoStart", buclnb.is_save_current_state); buclnb.is_save_current_state = data.value("bucLnbAutoStart", buclnb.is_save_current_state);
@@ -817,18 +823,21 @@ nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
rxtx["isCinC"] = mod.is_cinc; rxtx["isCinC"] = mod.is_cinc;
#endif #endif
rxtx["txEn"] = mod.tx_is_on; rxtx["txEn"] = mod.tx_is_on;
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
rxtx["txAutoStart"] = mod.is_save_current_state; rxtx["txAutoStart"] = mod.is_save_current_state;
rxtx["txIsTestInput"] = mod.is_test_data; rxtx["txIsTestInput"] = mod.is_test_data;
#endif #endif
rxtx["txModulatorIsTest"] = !mod.is_carrier; rxtx["txModulatorIsTest"] = !mod.is_carrier;
rxtx["txCentralFreq"] = mod.central_freq_in_kGz; rxtx["txCentralFreq"] = mod.central_freq_in_kGz;
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
rxtx["txBaudrate"] = mod.baudrate; rxtx["txBaudrate"] = mod.baudrate;
rxtx["txRolloff"] = mod.rollof; rxtx["txRolloff"] = mod.rollof;
rxtx["txGoldan"] = mod.gold_seq_is_active; rxtx["txGoldan"] = mod.gold_seq_is_active ? 1 : 0;
#endif #endif
rxtx["txAttenuation"] = mod.attenuation; rxtx["txAttenuation"] = mod.attenuation;
#ifdef MODEM_IS_SHPS
rxtx["txSpreadCoef"] = mod.koef_spread;
#endif
#if defined(MODEM_IS_SCPC) || defined(MODEM_IS_SHPS) #if defined(MODEM_IS_SCPC) || defined(MODEM_IS_SHPS)
const bool acmIsFrameSizeNormal = extractModcodFrameSizeNormal(mod.modcod_tx); const bool acmIsFrameSizeNormal = extractModcodFrameSizeNormal(mod.modcod_tx);
@@ -848,14 +857,18 @@ nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
rxtx["rxCentralFreq"] = dem.central_freq_in_kGz; rxtx["rxCentralFreq"] = dem.central_freq_in_kGz;
rxtx["rxBaudrate"] = dem.baudrate; rxtx["rxBaudrate"] = dem.baudrate;
rxtx["rxRolloff"] = dem.rollof; rxtx["rxRolloff"] = dem.rollof;
#ifdef MODEM_IS_SCPC #if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
rxtx["rxGoldan"] = dem.gold_seq_is_active; rxtx["rxGoldan"] = dem.gold_seq_is_active ? 1 : 0;
#endif
#ifdef MODEM_IS_SHPS
rxtx["txSpreadCoef"] = mod.koef_spread;
rxtx["rxSpreadCoef"] = dem.koef_spread;
#endif #endif
#ifdef API_STRUCT_ACM_ENABLE #ifdef API_STRUCT_ACM_ENABLE
// ACM // ACM
#ifndef MODEM_IS_SHPS #ifdef MODEM_IS_SCPC
// в ШПС этих настроек нет // эти настройки только в SCPC
rxtx["dvbServicePacketPeriod"] = acm.period_pack_acm; rxtx["dvbServicePacketPeriod"] = acm.period_pack_acm;
rxtx["dvbIsAcm"] = acm.enable_acm; rxtx["dvbIsAcm"] = acm.enable_acm;
@@ -879,20 +892,20 @@ nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
{ {
auto& dp = res["dpdi"]; auto& dp = res["dpdi"];
dp["dpdiIsPositional"] = !dpdi.is_delay_window; dp["isPositional"] = !dpdi.is_delay_window;
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
dp["dpdiSearchBandwidth"] = dpdi.freq_offset; dp["searchBandwidth"] = dpdi.freq_offset;
#endif #endif
dp["dpdiPositionStationLatitude"] = translateCoordinates(dpdi.latitude_station_grad, dpdi.latitude_station_minute); dp["positionStationLatitude"] = translateCoordinates(dpdi.latitude_station_grad, dpdi.latitude_station_minute);
dp["dpdiPositionStationLongitude"] = translateCoordinates(dpdi.longitude_station_grad, dpdi.longitude_station_minute); dp["positionStationLongitude"] = translateCoordinates(dpdi.longitude_station_grad, dpdi.longitude_station_minute);
dp["dpdiPositionSatelliteLongitude"] = translateCoordinates(dpdi.longitude_sattelite_grad, dpdi.longitude_sattelite_minute); dp["positionSatelliteLongitude"] = translateCoordinates(dpdi.longitude_sattelite_grad, dpdi.longitude_sattelite_minute);
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
dp["dpdiDelayMin"] = dpdi.min_delay; dp["delayMin"] = dpdi.min_delay;
dp["dpdiDelayMax"] = dpdi.max_delay; dp["delayMax"] = dpdi.max_delay;
#else #else
dp["dpdiDelay"] = dpdi.max_delay; dp["delay"] = dpdi.max_delay;
#endif #endif
} }
#endif #endif
@@ -908,6 +921,9 @@ nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
#endif #endif
default: bl["bucPowering"] = 0; default: bl["bucPowering"] = 0;
} }
#ifdef MODEM_IS_TDMA
bl["bucLoKhz"] = buclnb.lo_buc_inkHz;
#endif
bl["bucRefClk10M"] = buclnb.is_ref_10MHz_buc; bl["bucRefClk10M"] = buclnb.is_ref_10MHz_buc;
switch (buclnb.lnb) { switch (buclnb.lnb) {
@@ -917,6 +933,9 @@ nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
default: bl["lnbPowering"] = 0; default: bl["lnbPowering"] = 0;
} }
bl["lnbRefClk10M"] = buclnb.is_ref_10MHz_lnb; bl["lnbRefClk10M"] = buclnb.is_ref_10MHz_lnb;
#ifdef MODEM_IS_TDMA
bl["lnbLoKhz"] = buclnb.lo_lnb_inkHz;
#endif
bl["srvRefClk10M"] = buclnb.is_ref_10MHz_output; bl["srvRefClk10M"] = buclnb.is_ref_10MHz_output;
bl["bucLnbAutoStart"] = buclnb.is_save_current_state; bl["bucLnbAutoStart"] = buclnb.is_save_current_state;

View File

@@ -7,8 +7,6 @@
#include <fstream> #include <fstream>
#include <shared_mutex> #include <shared_mutex>
#include <string> #include <string>
//#include <boost/property_tree/ptree_fwd.hpp>
#include "common/nlohmann/json.hpp" #include "common/nlohmann/json.hpp"
@@ -30,7 +28,7 @@ namespace api_driver::obj {
* *
* @return {"en": bool, "logPeriodMs": int, "maxAgeMs": int} * @return {"en": bool, "logPeriodMs": int, "maxAgeMs": int}
*/ */
std::string getSettings(); nlohmann::json getSettings();
void setSettings(const nlohmann::json& data); void setSettings(const nlohmann::json& data);
void updateCallback(proxy::CpProxy& cp); void updateCallback(proxy::CpProxy& cp);
@@ -79,7 +77,7 @@ namespace api_driver::obj {
void loadDefaults(); void loadDefaults();
void updateCallback(proxy::CpProxy& cp); void updateCallback(proxy::CpProxy& cp);
void updateFromJson(nlohmann::json& data); void updateFromJson(const nlohmann::json& data);
void store(proxy::CpProxy& cp); void store(proxy::CpProxy& cp);
nlohmann::json asJson(); nlohmann::json asJson();
@@ -101,7 +99,7 @@ namespace api_driver::obj {
void loadDefaults(); void loadDefaults();
void updateCallback(proxy::CpProxy& cp); void updateCallback(proxy::CpProxy& cp);
void updateFromJson(nlohmann::json& data); void updateFromJson(const nlohmann::json& data);
void store(proxy::CpProxy& cp); void store(proxy::CpProxy& cp);
nlohmann::json asJson(); nlohmann::json asJson();
@@ -172,10 +170,8 @@ namespace api_driver::obj {
int32_t fCincFreqErrAcc{}; int32_t fCincFreqErrAcc{};
float fCincChannelDelay{}; float fCincChannelDelay{};
#endif #endif
#ifdef MODEM_IS_TDMA
double fTxCenterFreq; double fTxCenterFreq;
double fTxSymSpeed; double fTxSymSpeed;
#endif
TerminalState(); TerminalState();

View File

@@ -104,6 +104,8 @@ public:
static constexpr const char* INDEX_HTML = "/main-tdma.html"; static constexpr const char* INDEX_HTML = "/main-tdma.html";
#elif defined(MODEM_IS_SCPC) #elif defined(MODEM_IS_SCPC)
static constexpr const char* INDEX_HTML = "/main-scpc.html"; static constexpr const char* INDEX_HTML = "/main-scpc.html";
#elif defined(MODEM_IS_SHPS)
static constexpr const char* INDEX_HTML = "/main-shps.html";
#else #else
#error "Modem type not defined!" #error "Modem type not defined!"
#endif #endif
@@ -179,7 +181,7 @@ public:
try { try {
auto reqJson = nlohmann::json::parse(std::string(req.payload.begin(), req.payload.end())); auto reqJson = nlohmann::json::parse(std::string(req.payload.begin(), req.payload.end()));
auto u = auth.doAuth(reqJson["username"], reqJson["username"], req, rep); auto u = auth.doAuth(reqJson["username"], reqJson["password"], req, rep);
if (u == nullptr) { if (u == nullptr) {
throw std::runtime_error("invalid session"); throw std::runtime_error("invalid session");
} }
@@ -217,10 +219,21 @@ public:
http::server::stockReply(http::server::bad_request, rep); http::server::stockReply(http::server::bad_request, rep);
return; return;
} }
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
const auto result = api->loadTerminalState(); nlohmann::json resultJson;
try {
resultJson["status"] = "ok";
resultJson["state"] = api->loadTerminalState();
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/qos): Can't set QoS settings: " << e.what();
resultJson.clear();
resultJson["status"] = "error";
resultJson["error"] = e.what();
}
auto result = resultJson.dump();
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
})); }));
@@ -229,12 +242,22 @@ public:
http::server::stockReply(http::server::bad_request, rep); http::server::stockReply(http::server::bad_request, rep);
return; return;
} }
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
std::string result = R"({"settings":)"; nlohmann::json resultJson;
result += api->loadSettings();
result += "}"; try {
resultJson["status"] = "ok";
resultJson["settings"] = api->loadSettings();
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/get/settings): Can't get object: " << e.what();
resultJson.clear();
rep.status = http::server::internal_server_error;
resultJson["status"] = "error";
resultJson["error"] = e.what();
}
auto result = resultJson.dump();
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
})); }));
@@ -246,7 +269,20 @@ public:
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
const auto result = api->loadFirmwareVersion(); nlohmann::json resultJson;
try {
resultJson["status"] = "ok";
resultJson["firmware"] = api->loadFirmwareVersion();
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/get/aboutFirmware): Can't get object: " << e.what();
resultJson.clear();
rep.status = http::server::internal_server_error;
resultJson["status"] = "error";
resultJson["error"] = e.what();
}
auto result = resultJson.dump();
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
})); }));
@@ -451,7 +487,13 @@ public:
http::server::stockReply(http::server::bad_request, rep); http::server::stockReply(http::server::bad_request, rep);
return; return;
} }
this->upgradeOrRebootRunning = true;
rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
nlohmann::json resultJson;
try {
this->upgradeOrRebootRunning = true;
#ifdef MODEM_IS_TDMA #ifdef MODEM_IS_TDMA
if (req.url->params.find("ota") != req.url->params.end()) { if (req.url->params.find("ota") != req.url->params.end()) {
doTerminalUpgradeOta(); doTerminalUpgradeOta();
@@ -461,10 +503,15 @@ public:
#else #else
doTerminalUpgrade(); doTerminalUpgrade();
#endif #endif
rep.status = http::server::ok; resultJson["status"] = "ok";
rep.headers.clear(); } catch (std::exception& e) {
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/doFirmwareUpgrade): Error: " << e.what();
const auto result = api->loadFirmwareVersion(); resultJson.clear();
resultJson["status"] = "error";
resultJson["error"] = e.what();
}
auto result = resultJson.dump();
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
})); }));
@@ -483,32 +530,73 @@ public:
return; return;
} }
const auto func = req.url->params["f"]; const auto func = req.url->params["f"];
std::string result = R"({"status":"ok"})";
if (func == "SetDmaDebug") {
if (req.url->params.find("param") == req.url->params.end()) { http::server::stockReply(http::server::bad_request, rep); return; }
if (req.url->params.find("value") == req.url->params.end()) { http::server::stockReply(http::server::bad_request, rep); return; }
this->api->executeInApi([&](auto& cp) {
cp.setDmaDebug(req.url->params["param"], req.url->params["value"]);
});
} else if (func == "GetDmaDebug") {
if (req.url->params.find("param") == req.url->params.end()) { http::server::stockReply(http::server::bad_request, rep); return; }
this->api->executeInApi([&](auto& cp) {
nlohmann::json tmp;
tmp["status"] = "ok";
tmp["result"] = cp.getDmaDebug(req.url->params["param"]);
result = tmp.dump();
});
} else {
http::server::stockReply(http::server::not_implemented, rep);
return;
}
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
nlohmann::json resultJson;
try {
resultJson["status"] = "error";
if (func == "SetDmaDebug") {
if (req.url->params.find("param") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `param`";
} else if (req.url->params.find("value") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `value`";
} else {
this->api->executeInApi([&](auto& cp) {
cp.setDmaDebug(req.url->params["param"], req.url->params["value"]);
});
}
} else if (func == "GetDmaDebug") {
if (req.url->params.find("param") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `param`";
} else {
this->api->executeInApi([&](auto& cp) {
resultJson["status"] = "ok";
resultJson["result"] = cp.getDmaDebug(req.url->params["param"]);
});
}
} else if (func == "SetNetwork") {
if (req.url->params.find("param") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `param`";
} else if (req.url->params.find("value") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `value`";
} else {
this->api->executeInApi([&](auto& cp) {
cp.setNetwork(req.url->params["param"], req.url->params["value"]);
});
}
} else if (func == "GetNetwork") {
if (req.url->params.find("param") == req.url->params.end()) {
rep.status = http::server::bad_request;
resultJson["error"] = "missing required adgument: `param`";
} else {
this->api->executeInApi([&](auto& cp) {
resultJson["status"] = "ok";
resultJson["result"] = cp.getNetwork(req.url->params["param"]);
});
}
} else {
resultJson["error"] = "function not supported";
}
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/qos): Can't set QoS settings: " << e.what();
resultJson.clear();
resultJson["status"] = "error";
resultJson["error"] = e.what();
}
auto result = resultJson.dump();
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
})); }));
#ifdef API_OBJECT_DEBUG_METRICS_ENABLE #ifdef API_OBJECT_DEBUG_METRICS_ENABLE
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev/settings", this->auth, http::auth::User::DEVELOPER, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev/settings", this->auth, http::auth::User::DEVELOPER, [this](const auto& req, auto& rep) {
rep.status = http::server::ok;
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::text_plain)});
nlohmann::json resultJson; nlohmann::json resultJson;
try { try {
@@ -517,7 +605,7 @@ public:
resultJson["logstat"] = api->getLoggingStatisticsSettings(); resultJson["logstat"] = api->getLoggingStatisticsSettings();
} else if (req.method == "POST") { } else if (req.method == "POST") {
auto reqJson = nlohmann::json::parse(std::string(req.payload.begin(), req.payload.end())); auto reqJson = nlohmann::json::parse(std::string(req.payload.begin(), req.payload.end()));
api->setQosSettings(reqJson); api->setLoggingStatisticsSettings(reqJson);
resultJson["status"] = "ok"; resultJson["status"] = "ok";
resultJson["logstat"] = api->getLoggingStatisticsSettings(); resultJson["logstat"] = api->getLoggingStatisticsSettings();

View File

@@ -71,10 +71,10 @@ nlohmann::json api_driver::ApiDriver::loadSettings() const {
nlohmann::json res = daemon->getSettingsRxTx().asJson(); nlohmann::json res = daemon->getSettingsRxTx().asJson();
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE #ifdef API_OBJECT_QOS_SETTINGS_ENABLE
res.update(daemon->getQosSettings().asJson()); res["qos"] = (daemon->getQosSettings().asJson());
#endif #endif
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE #ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
res.update(daemon->getNetworkSettings().asJson()); res["network"] = (daemon->getNetworkSettings().asJson());
#endif #endif
return res; return res;
} }
@@ -107,7 +107,7 @@ void api_driver::ApiDriver::setDpdiSettings(const nlohmann::json& data) {
std::lock_guard _lapi(this->daemon->cpApiMutex); std::lock_guard _lapi(this->daemon->cpApiMutex);
this->daemon->cp.setDmaDebug("begin_save_config", ""); this->daemon->cp.setDmaDebug("begin_save_config", "");
rxtx.storeMainSettings(this->daemon->cp); rxtx.storeDpdiSettings(this->daemon->cp);
this->daemon->cp.setDmaDebug("save_config", ""); this->daemon->cp.setDmaDebug("save_config", "");
rxtx.updateCallback(this->daemon->cp); rxtx.updateCallback(this->daemon->cp);
{ {
@@ -116,17 +116,53 @@ void api_driver::ApiDriver::setDpdiSettings(const nlohmann::json& data) {
} }
#endif #endif
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
void api_driver::ApiDriver::setBucLnbSettings(const nlohmann::json& data) { void api_driver::ApiDriver::setBucLnbSettings(const nlohmann::json& data) {
// TODO auto rxtx = daemon->getSettingsRxTx();
} rxtx.updateBuclnbSettings(data);
std::lock_guard _lapi(this->daemon->cpApiMutex);
this->daemon->cp.setDmaDebug("begin_save_config", "");
rxtx.storeBuclnbSettings(this->daemon->cp);
this->daemon->cp.setDmaDebug("save_config", "");
rxtx.updateCallback(this->daemon->cp);
{
daemon->setSettingsRxTx(rxtx);
}
}
#endif
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE
void api_driver::ApiDriver::setQosSettings(const nlohmann::json& data) { void api_driver::ApiDriver::setQosSettings(const nlohmann::json& data) {
// TODO auto qos = daemon->getQosSettings();
} qos.updateFromJson(data);
void api_driver::ApiDriver::setNetworkSettings(const nlohmann::json& data) { std::lock_guard _lapi(this->daemon->cpApiMutex);
// TODO this->daemon->cp.setDmaDebug("begin_save_config", "");
qos.store(this->daemon->cp);
this->daemon->cp.setDmaDebug("save_config", "");
qos.updateCallback(this->daemon->cp);
{
daemon->setQosSettings(qos);
}
} }
#endif
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
void api_driver::ApiDriver::setNetworkSettings(const nlohmann::json& data) {
auto net = daemon->getNetworkSettings();
net.updateFromJson(data);
std::lock_guard _lapi(this->daemon->cpApiMutex);
this->daemon->cp.setDmaDebug("begin_save_config", "");
net.store(this->daemon->cp);
this->daemon->cp.setDmaDebug("save_config", "");
net.updateCallback(this->daemon->cp);
{
daemon->setNetworkSettings(net);
}
}
#endif
void api_driver::ApiDriver::resetDefaultSettings() { void api_driver::ApiDriver::resetDefaultSettings() {
daemon->resetDefaultSettings(); daemon->resetDefaultSettings();
@@ -150,7 +186,7 @@ std::string api_driver::ApiDriver::getOtaFileLocation() const {
#endif #endif
#ifdef MODEM_IS_SCPC #ifdef MODEM_IS_SCPC
std::string api_driver::ApiDriver::getLoggingStatisticsSettings() { nlohmann::json api_driver::ApiDriver::getLoggingStatisticsSettings() {
return this->daemon->statsLogs.getSettings(); return this->daemon->statsLogs.getSettings();
} }

View File

@@ -78,7 +78,7 @@ namespace api_driver {
void executeInApi(const std::function<void(proxy::CpProxy&)> &callback); void executeInApi(const std::function<void(proxy::CpProxy&)> &callback);
#ifdef API_OBJECT_DEBUG_METRICS_ENABLE #ifdef API_OBJECT_DEBUG_METRICS_ENABLE
std::string getLoggingStatisticsSettings(); nlohmann::json getLoggingStatisticsSettings();
void setLoggingStatisticsSettings(const nlohmann::json& data); void setLoggingStatisticsSettings(const nlohmann::json& data);
/** /**

View File

@@ -160,7 +160,7 @@
<h3>Параметры передачи</h3> <h3>Параметры передачи</h3>
<label> <label>
<span>Центральная частота, КГц</span> <span>Центральная частота, КГц</span>
<input type="text" v-model.lazy="paramRxtx.txCentralFreq" @change="e => paramRxtx.txCentralFreq = inputFormatNumber(inputFormatNumber(e.target.value, {min:950000,max:6000000,step:0.01}), {min:950000,max:6000000,step:0.01})"/> <input type="text" v-model.lazy="paramRxtx.txCentralFreq" @change="e => paramRxtx.txCentralFreq = inputFormatNumber(inputFormatNumber(e.target.value, {min:100000,max:6000000,step:0.01}), {min:100000,max:6000000,step:0.01})"/>
</label> </label>
<label> <label>
<span>Символьная скорость, Бод</span> <span>Символьная скорость, Бод</span>
@@ -169,12 +169,12 @@
<label> <label>
<span>Roll-off</span> <span>Roll-off</span>
<select v-model="paramRxtx.txRolloff"> <select v-model="paramRxtx.txRolloff">
<option :value="2">0.02</option> <option :value="20">0.02</option>
<option :value="5">0.05</option> <option :value="50">0.05</option>
<option :value="10">0.10</option> <option :value="100">0.10</option>
<option :value="15">0.15</option> <option :value="150">0.15</option>
<option :value="20">0.20</option> <option :value="200">0.20</option>
<option :value="25">0.25</option> <option :value="250">0.25</option>
</select> </select>
</label> </label>
<label> <label>
@@ -274,7 +274,7 @@
</label> </label>
<label><span>Минимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMinAttenuation" max="10" step="0.1"/></label> <label><span>Минимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMinAttenuation" max="10" step="0.1"/></label>
<label><span>Максимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMaxAttenuation" max="10" step="0.1"/></label> <label><span>Максимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMaxAttenuation" max="10" step="0.1"/></label>
<label><span>Требуемое ОСШ</span><input type="number" v-model="paramRxtx.aupcRequiredSnr" max="10" step="0.01"/></label> <label><span>Требуемое ОСШ</span><input type="number" v-model="paramRxtx.aupcRequiredSnr" max="30" step="0.01"/></label>
</div> </div>
<div class="settings-set-container"> <div class="settings-set-container">
<h3>Настройки приемника</h3> <h3>Настройки приемника</h3>
@@ -295,7 +295,7 @@
</label> </label>
<label> <label>
<span>Центральная частота, КГц</span> <span>Центральная частота, КГц</span>
<input type="text" v-model.lazy="paramRxtx.rxCentralFreq" @change="e => paramRxtx.rxCentralFreq = inputFormatNumber(inputFormatNumber(e.target.value, {min:950000,max:6000000,step:0.01}), {min:950000,max:6000000,step:0.01})"/> <input type="text" v-model.lazy="paramRxtx.rxCentralFreq" @change="e => paramRxtx.rxCentralFreq = inputFormatNumber(inputFormatNumber(e.target.value, {min:100000,max:6000000,step:0.01}), {min:100000,max:6000000,step:0.01})"/>
</label> </label>
<label> <label>
<span>Символьная скорость, Бод</span> <span>Символьная скорость, Бод</span>
@@ -304,12 +304,12 @@
<label> <label>
<span>Roll-off</span> <span>Roll-off</span>
<select v-model="paramRxtx.rxRolloff"> <select v-model="paramRxtx.rxRolloff">
<option :value="2">0.02</option> <option :value="20">0.02</option>
<option :value="5">0.05</option> <option :value="50">0.05</option>
<option :value="10">0.10</option> <option :value="100">0.10</option>
<option :value="15">0.15</option> <option :value="150">0.15</option>
<option :value="20">0.20</option> <option :value="200">0.20</option>
<option :value="25">0.25</option> <option :value="250">0.25</option>
</select> </select>
</label> </label>
<label> <label>
@@ -326,19 +326,19 @@
<div class="settings-set-container" v-show="paramRxtx.isCinC"> <div class="settings-set-container" v-show="paramRxtx.isCinC">
<label> <label>
<span>Метод расчета задержки</span> <span>Метод расчета задержки</span>
<select v-model="paramDpdi.dpdiIsPositional"> <select v-model="paramDpdi.isPositional">
<option :value="true">Позиционированием</option> <option :value="true">Позиционированием</option>
<option :value="false">Окном задержки</option> <option :value="false">Окном задержки</option>
</select> </select>
</label> </label>
<label><span>Полоса поиска, КГц ±</span><input type="number" v-model="paramDpdi.dpdiSearchBandwidth" max="100" step="1"/></label> <label><span>Полоса поиска, КГц ±</span><input type="number" v-model="paramDpdi.searchBandwidth" max="100" step="1"/></label>
<h2 v-show="paramDpdi.dpdiIsPositional === true">Настройки позиционирования</h2> <h2 v-show="paramDpdi.isPositional === true">Настройки позиционирования</h2>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Широта станции</span><input type="number" v-model="paramDpdi.dpdiPositionStationLatitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Широта станции</span><input type="number" v-model="paramDpdi.positionStationLatitude" min="-180" max="180" step="1e-06"/></label>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Долгота станции</span><input type="number" v-model="paramDpdi.dpdiPositionStationLongitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Долгота станции</span><input type="number" v-model="paramDpdi.positionStationLongitude" min="-180" max="180" step="1e-06"/></label>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Подспутниковая точка</span><input type="number" v-model="paramDpdi.dpdiPositionSatelliteLongitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Подспутниковая точка</span><input type="number" v-model="paramDpdi.positionSatelliteLongitude" min="-180" max="180" step="1e-06"/></label>
<h2 v-show="paramDpdi.dpdiIsPositional === false">Задержка до спутника</h2> <h2 v-show="paramDpdi.isPositional === false">Задержка до спутника</h2>
<label v-show="paramDpdi.dpdiIsPositional === false"><span>от, мс</span><input type="number" v-model="paramDpdi.dpdiDelayMin" max="400" step="0.1"/></label> <label v-show="paramDpdi.isPositional === false"><span>от, мс</span><input type="number" v-model="paramDpdi.delayMin" max="400" step="0.1"/></label>
<label v-show="paramDpdi.dpdiIsPositional === false"><span>до, мс</span><input type="number" v-model="paramDpdi.dpdiDelayMax" max="400" step="0.1"/></label> <label v-show="paramDpdi.isPositional === false"><span>до, мс</span><input type="number" v-model="paramDpdi.delayMax" max="400" step="0.1"/></label>
</div> </div>
<button class="action-button" @click="settingsSubmitDpdi()" v-show="paramRxtx.isCinC">Сохранить <span class="submit-spinner" v-show="submitStatus.dpdi"></span></button> <button class="action-button" @click="settingsSubmitDpdi()" v-show="paramRxtx.isCinC">Сохранить <span class="submit-spinner" v-show="submitStatus.dpdi"></span></button>
<h2>Настройки питания и опорного генератора</h2> <h2>Настройки питания и опорного генератора</h2>
@@ -489,38 +489,29 @@
</div> </div>
<button class="action-button" @click="settingsSubmitQoS()">Применить <span class="submit-spinner" v-show="submitStatusQos"></span></button> <button class="action-button" @click="settingsSubmitQoS()">Применить <span class="submit-spinner" v-show="submitStatusQos"></span></button>
<h2>Настройки TCP-акселерации</h2>
<div class="settings-set-container">
<label>
<span>Активировать акселерацию</span>
<span class="toggle-input"><input type="checkbox" v-model="paramTcpaccel.accelEn" /><span class="slider"></span></span>
</label>
<label><span>Максимальное количество соединений</span><input type="number" v-model="paramTcpaccel.accelMaxConnections" max="4000" step="1"/></label>
</div>
<button class="action-button" @click="settingsSubmitTcpaccel()">Сохранить <span class="submit-spinner" v-show="submitStatus.tcpaccel"></span></button>
</div> <div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete"> </div> <div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete">
<h2>Настройки сети</h2> <h2>Настройки сети</h2>
<div class="settings-set-container"> <div class="settings-set-container">
<h3>Настройки интерфейса управления</h3> <h3>Настройки интерфейса управления</h3>
<label> <label>
<span>Интерфейс управления (/24)</span> <span>Интерфейс управления (a.d.d.r/mask)</span>
<input v-model="paramNetwork.netManagementIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"> <input v-model="paramNetwork.managementIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$">
</label> </label>
<label> <label>
<span>Режим сети</span> <span>Режим сети</span>
<select v-model="paramNetwork.netIsL2"> <select v-model="paramNetwork.isL2">
<option :value="false">Маршрутизатор</option> <option :value="false">Маршрутизатор</option>
<option :value="true">Коммутатор</option> <option :value="true">Коммутатор</option>
</select> </select>
</label> </label>
<label v-show="paramNetwork.netIsL2 === false"> <label v-show="paramNetwork.isL2 === false">
<span>Интерфейс данных (/24)</span> <span>Интерфейс данных (/24)</span>
<input v-model="paramNetwork.netDataIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"> <input v-model="paramNetwork.dataIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
</label> </label>
<label><span>MTU интерфейса данных</span><input type="number" v-model="paramNetwork.netDataMtu" min="1500" max="2000" step="1"/></label> <label><span>MTU интерфейса данных</span><input type="number" v-model="paramNetwork.dataMtu" min="1500" max="2000" step="1"/></label>
<label> <label>
<span>Имя веб-сервера</span> <span>Имя веб-сервера</span>
<input v-model="paramNetwork.netServerName" type="text"> <input v-model="paramNetwork.serverName" type="text">
</label> </label>
</div> </div>
<button class="action-button" @click="settingsSubmitNetwork()">Сохранить <span class="submit-spinner" v-show="submitStatus.network"></span></button> <button class="action-button" @click="settingsSubmitNetwork()">Сохранить <span class="submit-spinner" v-show="submitStatus.network"></span></button>
@@ -542,6 +533,8 @@
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button> <button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
</div> </div>
<button class="action-button" @click="dumpAllSettings()">Сохранить бекап конфигурации</button>
<button class="dangerous-button" @click="restoreAllSettings()">Восстановить бекап конфигурации</button>
</div> </div>
<h2>Обновление ПО</h2> <h2>Обновление ПО</h2>
@@ -595,7 +588,6 @@
rxtx: false, rxtx: false,
dpdi: false, dpdi: false,
buclnb: false, buclnb: false,
tcpaccel: false,
network: false, network: false,
firmwareUpload: false, firmwareUpload: false,
firmwareUpgrade: false, firmwareUpgrade: false,
@@ -612,7 +604,7 @@
txIsTestInput: false, txIsTestInput: false,
txCentralFreq: 0, txCentralFreq: 0,
txBaudrate: 0, txBaudrate: 0,
txRolloff: 2, txRolloff: 20,
txGoldan: 0, txGoldan: 0,
txAttenuation: -40, txAttenuation: -40,
dvbServicePacketPeriod: 0, dvbServicePacketPeriod: 0,
@@ -635,17 +627,17 @@
rxSpectrumInversion: false, rxSpectrumInversion: false,
rxCentralFreq: 0, rxCentralFreq: 0,
rxBaudrate: 0, rxBaudrate: 0,
rxRolloff: 2, rxRolloff: 20,
rxGoldan: 0, rxGoldan: 0,
}, },
paramDpdi: { paramDpdi: {
dpdiIsPositional: true, isPositional: true,
dpdiSearchBandwidth: 0, searchBandwidth: 0,
dpdiPositionStationLatitude: -180, positionStationLatitude: -180,
dpdiPositionStationLongitude: -180, positionStationLongitude: -180,
dpdiPositionSatelliteLongitude: -180, positionSatelliteLongitude: -180,
dpdiDelayMin: 0, delayMin: 0,
dpdiDelayMax: 0, delayMax: 0,
}, },
paramBuclnb: { paramBuclnb: {
bucRefClk10M: false, bucRefClk10M: false,
@@ -655,16 +647,12 @@
srvRefClk10M: false, srvRefClk10M: false,
bucLnbAutoStart: false, bucLnbAutoStart: false,
}, },
paramTcpaccel: {
accelEn: false,
accelMaxConnections: 0,
},
paramNetwork: { paramNetwork: {
netManagementIp: null, managementIp: null,
netIsL2: false, isL2: false,
netDataIp: null, dataIp: null,
netDataMtu: 1500, dataMtu: 1500,
netServerName: null, serverName: null,
}, },
// ========== include end from 'common/all-params-data.js.j2' // ========== include end from 'common/all-params-data.js.j2'
@@ -841,13 +829,13 @@
if (this.submitStatus.dpdi) { return } if (this.submitStatus.dpdi) { return }
let query = { let query = {
"dpdiIsPositional": this.paramDpdi.dpdiIsPositional, "isPositional": this.paramDpdi.isPositional,
"dpdiSearchBandwidth": this.paramDpdi.dpdiSearchBandwidth, "searchBandwidth": this.paramDpdi.searchBandwidth,
"dpdiPositionStationLatitude": this.paramDpdi.dpdiPositionStationLatitude, "positionStationLatitude": this.paramDpdi.positionStationLatitude,
"dpdiPositionStationLongitude": this.paramDpdi.dpdiPositionStationLongitude, "positionStationLongitude": this.paramDpdi.positionStationLongitude,
"dpdiPositionSatelliteLongitude": this.paramDpdi.dpdiPositionSatelliteLongitude, "positionSatelliteLongitude": this.paramDpdi.positionSatelliteLongitude,
"dpdiDelayMin": this.paramDpdi.dpdiDelayMin, "delayMin": this.paramDpdi.delayMin,
"dpdiDelayMax": this.paramDpdi.dpdiDelayMax, "delayMax": this.paramDpdi.delayMax,
} }
this.submitStatus.dpdi = true this.submitStatus.dpdi = true
@@ -875,30 +863,16 @@
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) }) .catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
.finally(() => { this.submitStatus.buclnb = false }) .finally(() => { this.submitStatus.buclnb = false })
}, },
settingsSubmitTcpaccel() {
if (this.submitStatus.tcpaccel) { return }
let query = {
"accelEn": this.paramTcpaccel.accelEn,
"accelMaxConnections": this.paramTcpaccel.accelMaxConnections,
}
this.submitStatus.tcpaccel = true
fetch('/api/set/tcpaccel', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' })
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.updateTcpaccelSettings(vals) })
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
.finally(() => { this.submitStatus.tcpaccel = false })
},
settingsSubmitNetwork() { settingsSubmitNetwork() {
if (this.submitStatus.network) { return } if (this.submitStatus.network) { return }
{ if (!confirm("Применение этих настроек может сделать модем недоступным! Продолжить?")) return } { if (!confirm("Применение этих настроек может сделать модем недоступным! Продолжить?")) return }
let query = { let query = {
"netManagementIp": this.paramNetwork.netManagementIp, "managementIp": this.paramNetwork.managementIp,
"netIsL2": this.paramNetwork.netIsL2, "isL2": this.paramNetwork.isL2,
"netDataIp": this.paramNetwork.netDataIp, "dataIp": this.paramNetwork.dataIp,
"netDataMtu": this.paramNetwork.netDataMtu, "dataMtu": this.paramNetwork.dataMtu,
"netServerName": this.paramNetwork.netServerName, "serverName": this.paramNetwork.serverName,
} }
this.submitStatus.network = true this.submitStatus.network = true
@@ -910,70 +884,65 @@
updateRxtxSettings(vals) { updateRxtxSettings(vals) {
this.submitStatus.rxtx = false this.submitStatus.rxtx = false
this.paramRxtx.isCinC = vals["settings"]["isCinC"] this.paramRxtx.isCinC = vals["settings"]["rxtx"]["isCinC"]
this.paramRxtx.txEn = vals["settings"]["txEn"] this.paramRxtx.txEn = vals["settings"]["rxtx"]["txEn"]
this.paramRxtx.txAutoStart = vals["settings"]["txAutoStart"] this.paramRxtx.txAutoStart = vals["settings"]["rxtx"]["txAutoStart"]
this.paramRxtx.txModulatorIsTest = vals["settings"]["txModulatorIsTest"] this.paramRxtx.txModulatorIsTest = vals["settings"]["rxtx"]["txModulatorIsTest"]
this.paramRxtx.txIsTestInput = vals["settings"]["txIsTestInput"] this.paramRxtx.txIsTestInput = vals["settings"]["rxtx"]["txIsTestInput"]
this.paramRxtx.txCentralFreq = this.inputFormatNumber(vals["settings"]["txCentralFreq"], {min:950000,max:6000000,step:0.01}) this.paramRxtx.txCentralFreq = this.inputFormatNumber(vals["settings"]["rxtx"]["txCentralFreq"], {min:100000,max:6000000,step:0.01})
this.paramRxtx.txBaudrate = this.inputFormatNumber(vals["settings"]["txBaudrate"], {min:200000,max:54000000,}) this.paramRxtx.txBaudrate = this.inputFormatNumber(vals["settings"]["rxtx"]["txBaudrate"], {min:200000,max:54000000,})
this.paramRxtx.txRolloff = vals["settings"]["txRolloff"] this.paramRxtx.txRolloff = vals["settings"]["rxtx"]["txRolloff"]
this.paramRxtx.txGoldan = vals["settings"]["txGoldan"] this.paramRxtx.txGoldan = vals["settings"]["rxtx"]["txGoldan"]
this.paramRxtx.txAttenuation = vals["settings"]["txAttenuation"] this.paramRxtx.txAttenuation = vals["settings"]["rxtx"]["txAttenuation"]
this.paramRxtx.dvbServicePacketPeriod = vals["settings"]["dvbServicePacketPeriod"] this.paramRxtx.dvbServicePacketPeriod = vals["settings"]["rxtx"]["dvbServicePacketPeriod"]
this.paramRxtx.dvbIsAcm = vals["settings"]["dvbIsAcm"] this.paramRxtx.dvbIsAcm = vals["settings"]["rxtx"]["dvbIsAcm"]
this.paramRxtx.txFrameSizeNormal = vals["settings"]["txFrameSizeNormal"] this.paramRxtx.txFrameSizeNormal = vals["settings"]["rxtx"]["txFrameSizeNormal"]
this.paramRxtx.txIsPilots = vals["settings"]["txIsPilots"] this.paramRxtx.txIsPilots = vals["settings"]["rxtx"]["txIsPilots"]
this.paramRxtx.dvbCcmModulation = vals["settings"]["dvbCcmModulation"] this.paramRxtx.dvbCcmModulation = vals["settings"]["rxtx"]["dvbCcmModulation"]
this.paramRxtx.dvbCcmSpeed = vals["settings"]["dvbCcmSpeed"] this.paramRxtx.dvbCcmSpeed = vals["settings"]["rxtx"]["dvbCcmSpeed"]
this.paramRxtx.dvbAcmMinModulation = vals["settings"]["dvbAcmMinModulation"] this.paramRxtx.dvbAcmMinModulation = vals["settings"]["rxtx"]["dvbAcmMinModulation"]
this.paramRxtx.dvbAcmMinSpeed = vals["settings"]["dvbAcmMinSpeed"] this.paramRxtx.dvbAcmMinSpeed = vals["settings"]["rxtx"]["dvbAcmMinSpeed"]
this.paramRxtx.dvbAcmMaxModulation = vals["settings"]["dvbAcmMaxModulation"] this.paramRxtx.dvbAcmMaxModulation = vals["settings"]["rxtx"]["dvbAcmMaxModulation"]
this.paramRxtx.dvbAcmMaxSpeed = vals["settings"]["dvbAcmMaxSpeed"] this.paramRxtx.dvbAcmMaxSpeed = vals["settings"]["rxtx"]["dvbAcmMaxSpeed"]
this.paramRxtx.dvbSnrReserve = vals["settings"]["dvbSnrReserve"] this.paramRxtx.dvbSnrReserve = vals["settings"]["rxtx"]["dvbSnrReserve"]
this.paramRxtx.aupcEn = vals["settings"]["aupcEn"] this.paramRxtx.aupcEn = vals["settings"]["rxtx"]["aupcEn"]
this.paramRxtx.aupcMinAttenuation = vals["settings"]["aupcMinAttenuation"] this.paramRxtx.aupcMinAttenuation = vals["settings"]["rxtx"]["aupcMinAttenuation"]
this.paramRxtx.aupcMaxAttenuation = vals["settings"]["aupcMaxAttenuation"] this.paramRxtx.aupcMaxAttenuation = vals["settings"]["rxtx"]["aupcMaxAttenuation"]
this.paramRxtx.aupcRequiredSnr = vals["settings"]["aupcRequiredSnr"] this.paramRxtx.aupcRequiredSnr = vals["settings"]["rxtx"]["aupcRequiredSnr"]
this.paramRxtx.rxAgcEn = vals["settings"]["rxAgcEn"] this.paramRxtx.rxAgcEn = vals["settings"]["rxtx"]["rxAgcEn"]
this.paramRxtx.rxManualGain = vals["settings"]["rxManualGain"] this.paramRxtx.rxManualGain = vals["settings"]["rxtx"]["rxManualGain"]
this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxSpectrumInversion"] this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxtx"]["rxSpectrumInversion"]
this.paramRxtx.rxCentralFreq = this.inputFormatNumber(vals["settings"]["rxCentralFreq"], {min:950000,max:6000000,step:0.01}) this.paramRxtx.rxCentralFreq = this.inputFormatNumber(vals["settings"]["rxtx"]["rxCentralFreq"], {min:100000,max:6000000,step:0.01})
this.paramRxtx.rxBaudrate = this.inputFormatNumber(vals["settings"]["rxBaudrate"], {min:200000,max:54000000,}) this.paramRxtx.rxBaudrate = this.inputFormatNumber(vals["settings"]["rxtx"]["rxBaudrate"], {min:200000,max:54000000,})
this.paramRxtx.rxRolloff = vals["settings"]["rxRolloff"] this.paramRxtx.rxRolloff = vals["settings"]["rxtx"]["rxRolloff"]
this.paramRxtx.rxGoldan = vals["settings"]["rxGoldan"] this.paramRxtx.rxGoldan = vals["settings"]["rxtx"]["rxGoldan"]
}, },
updateDpdiSettings(vals) { updateDpdiSettings(vals) {
this.submitStatus.dpdi = false this.submitStatus.dpdi = false
this.paramDpdi.dpdiIsPositional = vals["settings"]["dpdiIsPositional"] this.paramDpdi.isPositional = vals["settings"]["dpdi"]["isPositional"]
this.paramDpdi.dpdiSearchBandwidth = vals["settings"]["dpdiSearchBandwidth"] this.paramDpdi.searchBandwidth = vals["settings"]["dpdi"]["searchBandwidth"]
this.paramDpdi.dpdiPositionStationLatitude = vals["settings"]["dpdiPositionStationLatitude"] this.paramDpdi.positionStationLatitude = vals["settings"]["dpdi"]["positionStationLatitude"]
this.paramDpdi.dpdiPositionStationLongitude = vals["settings"]["dpdiPositionStationLongitude"] this.paramDpdi.positionStationLongitude = vals["settings"]["dpdi"]["positionStationLongitude"]
this.paramDpdi.dpdiPositionSatelliteLongitude = vals["settings"]["dpdiPositionSatelliteLongitude"] this.paramDpdi.positionSatelliteLongitude = vals["settings"]["dpdi"]["positionSatelliteLongitude"]
this.paramDpdi.dpdiDelayMin = vals["settings"]["dpdiDelayMin"] this.paramDpdi.delayMin = vals["settings"]["dpdi"]["delayMin"]
this.paramDpdi.dpdiDelayMax = vals["settings"]["dpdiDelayMax"] this.paramDpdi.delayMax = vals["settings"]["dpdi"]["delayMax"]
}, },
updateBuclnbSettings(vals) { updateBuclnbSettings(vals) {
this.submitStatus.buclnb = false this.submitStatus.buclnb = false
this.paramBuclnb.bucRefClk10M = vals["settings"]["bucRefClk10M"] this.paramBuclnb.bucRefClk10M = vals["settings"]["buclnb"]["bucRefClk10M"]
this.paramBuclnb.bucPowering = vals["settings"]["bucPowering"] this.paramBuclnb.bucPowering = vals["settings"]["buclnb"]["bucPowering"]
this.paramBuclnb.lnbRefClk10M = vals["settings"]["lnbRefClk10M"] this.paramBuclnb.lnbRefClk10M = vals["settings"]["buclnb"]["lnbRefClk10M"]
this.paramBuclnb.lnbPowering = vals["settings"]["lnbPowering"] this.paramBuclnb.lnbPowering = vals["settings"]["buclnb"]["lnbPowering"]
this.paramBuclnb.srvRefClk10M = vals["settings"]["srvRefClk10M"] this.paramBuclnb.srvRefClk10M = vals["settings"]["buclnb"]["srvRefClk10M"]
this.paramBuclnb.bucLnbAutoStart = vals["settings"]["bucLnbAutoStart"] this.paramBuclnb.bucLnbAutoStart = vals["settings"]["buclnb"]["bucLnbAutoStart"]
},
updateTcpaccelSettings(vals) {
this.submitStatus.tcpaccel = false
this.paramTcpaccel.accelEn = vals["settings"]["accelEn"]
this.paramTcpaccel.accelMaxConnections = vals["settings"]["accelMaxConnections"]
}, },
updateNetworkSettings(vals) { updateNetworkSettings(vals) {
this.submitStatus.network = false this.submitStatus.network = false
this.paramNetwork.netManagementIp = vals["settings"]["netManagementIp"] this.paramNetwork.managementIp = vals["settings"]["network"]["managementIp"]
this.paramNetwork.netIsL2 = vals["settings"]["netIsL2"] this.paramNetwork.isL2 = vals["settings"]["network"]["isL2"]
this.paramNetwork.netDataIp = vals["settings"]["netDataIp"] this.paramNetwork.dataIp = vals["settings"]["network"]["dataIp"]
this.paramNetwork.netDataMtu = vals["settings"]["netDataMtu"] this.paramNetwork.dataMtu = vals["settings"]["network"]["dataMtu"]
this.paramNetwork.netServerName = vals["settings"]["netServerName"] this.paramNetwork.serverName = vals["settings"]["network"]["serverName"]
}, },
// ========== include end from 'common/all-params-methods.js.j2' // ========== include end from 'common/all-params-methods.js.j2'
@@ -998,53 +967,52 @@
} }
this.lastUpdateTime = new Date(); this.lastUpdateTime = new Date();
this.initState = vals["mainState"]["initState"] this.initState = vals["state"]["initState"]
this.isCinC = vals["mainState"]["isCinC"] this.testState = vals["state"]["testState"]
this.isCinC = vals["state"]["isCinC"]
this.statRx.state = vals["mainState"]["rx.state"] this.statRx.state = vals["state"]["rx"]["state"]
this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"] this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"]
this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"] this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"]
this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"] this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"]
this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"] this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"]
this.statRx.snr = vals["mainState"]["rx.snr"] this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10
this.statRx.rssi = vals["mainState"]["rx.rssi"] this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10
this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"]) this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"])
this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"] this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"]
this.statRx.isPilots = vals["mainState"]["rx.isPilots"] this.statRx.isPilots = vals["state"]["rx"]["isPilots"]
this.statRx.symError = vals["mainState"]["rx.symError"] this.statRx.symError = vals["state"]["rx"]["symError"]
this.statRx.freqErr = vals["mainState"]["rx.freqErr"] this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100
this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"] this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100
this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"] this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"]
this.statRx.pllError = vals["mainState"]["rx.pllError"] this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100
this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"] this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100
this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"] this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100
this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"] this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"]
this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"] this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"]
this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"] this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"]
this.statTx.state = vals["mainState"]["tx.state"] this.statTx.state = vals["state"]["tx"]["state"]
this.statTx.snr = vals["mainState"]["tx.snr"] this.statTx.snr = Math.round(vals["state"]["tx"]["snr"] * 100) / 100
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"])
this.statTx.frameSizeNormal = vals["mainState"]["tx.frameSizeNormal"] this.statTx.frameSizeNormal = vals["state"]["tx"]["frameSizeNormal"]
this.statTx.isPilots = vals["mainState"]["tx.isPilots"] this.statTx.isPilots = vals["state"]["tx"]["isPilots"]
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100
this.statCinc.occ = vals["mainState"]["cinc.occ"] this.statCinc.occ = vals["state"]["cinc"]["occ"]
this.statCinc.correlator = vals["mainState"]["cinc.correlator"] this.statCinc.correlator = vals["state"]["cinc"]["correlator"]
this.statCinc.correlatorFails = vals["mainState"]["cinc.correlatorFails"] this.statCinc.correlatorFails = vals["state"]["cinc"]["correlatorFails"]
this.statCinc.freqErr = vals["mainState"]["cinc.freqErr"] this.statCinc.freqErr = Math.round(vals["state"]["cinc"]["freqErr"] * 100) / 100
this.statCinc.freqErrAcc = vals["mainState"]["cinc.freqErrAcc"] this.statCinc.freqErrAcc = Math.round(vals["state"]["cinc"]["freqErrAcc"] * 100) / 100
this.statCinc.channelDelay = vals["mainState"]["cinc.channelDelay"] this.statCinc.channelDelay = vals["state"]["cinc"]["channelDelay"]
this.statDevice.adrv = vals["mainState"]["device.adrv"] this.statDevice.adrv = vals["state"]["device"]["adrv"]
this.statDevice.zynq = vals["mainState"]["device.zynq"] this.statDevice.zynq = vals["state"]["device"]["zynq"]
this.statDevice.fpga = vals["mainState"]["device.fpga"] this.statDevice.fpga = vals["state"]["device"]["fpga"]
this.testState = vals["mainState"]["testState"]
// аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид
let uptime = vals["sysinfo"]["uptime"] let uptime = vals["state"]["device"]["uptime"]
if (uptime) { if (uptime) {
let secs = uptime % 60; uptime = Math.floor(uptime / 60) let secs = uptime % 60; uptime = Math.floor(uptime / 60)
let mins = uptime % 60; uptime = Math.floor(uptime / 60) let mins = uptime % 60; uptime = Math.floor(uptime / 60)
@@ -1056,11 +1024,11 @@
} else { } else {
this.statOs.uptime = '?' this.statOs.uptime = '?'
} }
this.statOs.load1 = vals["sysinfo"]["load1min"] this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100
this.statOs.load5 = vals["sysinfo"]["load5min"] this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100
this.statOs.load15 = vals["sysinfo"]["load15min"] this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100
this.statOs.totalram = vals["sysinfo"]["totalram"] this.statOs.totalram = vals["state"]["device"]["totalram"]
this.statOs.freeram = vals["sysinfo"]["freeram"] this.statOs.freeram = vals["state"]["device"]["freeram"]
}, },
resetPacketsStatistics() { resetPacketsStatistics() {
@@ -1156,15 +1124,17 @@
} }
let query = { let query = {
"en": this.paramQos.en, "en": this.paramQos.en,
"rt1": [], "profile": {
"rt2": [], "rt1": [],
"rt3": [], "rt2": [],
"cd": [] "rt3": [],
"cd": []
}
} }
for (let i = 0; i < this.paramQos.rt1.length; i++) { query.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) } for (let i = 0; i < this.paramQos.rt1.length; i++) { query.profile.rt1.push(_translateQosClass('rt', this.paramQos.rt1[i])) }
for (let i = 0; i < this.paramQos.rt2.length; i++) { query.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) } for (let i = 0; i < this.paramQos.rt2.length; i++) { query.profile.rt2.push(_translateQosClass('rt', this.paramQos.rt2[i])) }
for (let i = 0; i < this.paramQos.rt3.length; i++) { query.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) } for (let i = 0; i < this.paramQos.rt3.length; i++) { query.profile.rt3.push(_translateQosClass('rt', this.paramQos.rt3[i])) }
for (let i = 0; i < this.paramQos.cd.length; i++) { query.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) } for (let i = 0; i < this.paramQos.cd.length; i++) { query.profile.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) }
//console.log(query) //console.log(query)
fetch('/api/set/qos', { fetch('/api/set/qos', {
@@ -1185,9 +1155,9 @@
updateQosSettings(vals) { updateQosSettings(vals) {
this.submitStatusQos = false this.submitStatusQos = false
this.paramQos.en = vals["settings"]["qosEnabled"] this.paramQos.en = vals["settings"]["qos"]["en"]
const qosProfile = vals["settings"]["qosProfile"] const qosProfile = vals["settings"]["qos"]["profile"]
if (qosProfile !== null && qosProfile !== undefined) { if (qosProfile !== null && qosProfile !== undefined) {
this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length) this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length)
this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length) this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length)
@@ -1395,6 +1365,133 @@
} }
this.submitStatus.modemReboot = 30 this.submitStatus.modemReboot = 30
fetch('/api/reboot', { method: 'POST' }).then((r) => {}) fetch('/api/reboot', { method: 'POST' }).then((r) => {})
},
async restoreAllSettings() {
// Порядок применения настроек
const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network'];
// 1. Чтение JSON-файла, выбранного пользователем
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.json';
const filePromise = new Promise((resolve, reject) => {
fileInput.onchange = e => {
const file = e.target.files[0];
if (!file) {
reject(new Error('Файл не выбран'));
return;
}
const reader = new FileReader();
reader.onload = event => {
try {
const jsonData = JSON.parse(event.target.result);
resolve(jsonData);
} catch (error) {
reject(new Error('Ошибка парсинга JSON'));
}
};
reader.onerror = () => reject(new Error('Ошибка чтения файла'));
reader.readAsText(file);
};
fileInput.click();
});
try {
const settingsToApply = await filePromise;
const errors = [];
// 2. Перебор групп параметров в заданном порядке
for (const groupName of settingsApplyOrder) {
if (!settingsToApply.hasOwnProperty(groupName)) {
continue; // Пропускаем группы, которых нет в файле
}
const groupSettings = settingsToApply[groupName];
if (typeof groupSettings !== 'object' || groupSettings === null) {
continue;
}
try {
// 2.1. POST-запрос для применения группы параметров
const postResponse = await fetch(`/api/set/${groupName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(groupSettings)
});
if (!postResponse.ok) {
throw new Error(`HTTP error ${postResponse.status}`);
}
const postResult = await postResponse.json();
if (postResult.status !== 'ok') {
throw new Error(`API error: ${postResult.message || 'unknown error'}`);
}
// 2.2. Проверка примененных параметров
const getResponse = await fetch('/api/get/settings', { method: 'GET' });
if (!getResponse.ok) {
throw new Error(`HTTP error ${getResponse.status}`);
}
const fetchSettingsResult = await getResponse.json();
if (fetchSettingsResult.status !== 'ok') {
throw new Error('Не удалось получить текущие настройки');
}
// Проверка соответствия параметров
const appliedGroup = fetchSettingsResult.settings[groupName] || {};
const failedSettings = [];
for (const [key, value] of Object.entries(groupSettings)) {
if (appliedGroup[key] !== value) {
failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`);
}
}
if (failedSettings.length > 0) {
throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`);
}
} catch (groupError) {
errors.push(`Группа ${groupName}: ${groupError.message}`);
}
}
// 3. Показ ошибок, если они есть
if (errors.length > 0) {
const errorMessage = errors.join('\n\n') +
'\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.';
alert(errorMessage);
}
} catch (error) {
alert(`Ошибка при восстановлении настроек: ${error.message}`);
return;
}
// 4. Перезагрузка страницы
location.reload();
},
async dumpAllSettings() {
function downloadAsFile(data, filename) {
let a = document.createElement("a");
let file = new Blob([data], {type: 'application/json'});
a.href = URL.createObjectURL(file);
a.download = filename;
a.click();
}
const response = await fetch('/api/get/settings', { method: 'GET' })
if (response.ok) {
const jres = await response.json()
if (jres["status"] === "ok") {
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2' }, // ========== include end from 'common/admin-methods.js.j2'
@@ -1406,7 +1503,6 @@
this.updateRxtxSettings(vals) this.updateRxtxSettings(vals)
this.updateDpdiSettings(vals) this.updateDpdiSettings(vals)
this.updateBuclnbSettings(vals) this.updateBuclnbSettings(vals)
this.updateTcpaccelSettings(vals)
this.updateNetworkSettings(vals) this.updateNetworkSettings(vals)
this.updateQosSettings(vals) this.updateQosSettings(vals)
@@ -1443,11 +1539,11 @@
try { try {
const fr = await fetch("/api/get/aboutFirmware") const fr = await fetch("/api/get/aboutFirmware")
const d = await fr.json() const d = await fr.json()
this.about.firmwareVersion = d["fw.version"] this.about.firmwareVersion = d["firmware"]["version"]
this.about.modemUid = d["fw.modemId"] this.about.modemUid = d["firmware"]["modemId"]
this.about.modemSn = d["fw.modemSn"] this.about.modemSn = d["firmware"]["modemSn"]
this.about.macManagement = d["fw.macMang"] this.about.macManagement = d["firmware"]["macMang"]
this.about.macData = d["fw.macData"] this.about.macData = d["firmware"]["macData"]
} catch (e) { } catch (e) {
console.log('Ошибка загрузки версии ПО', e) console.log('Ошибка загрузки версии ПО', e)
} }

View File

@@ -135,29 +135,32 @@
</select> </select>
</label> </label>
<h3>Параметры передачи</h3> <h3>Параметры передачи</h3>
<label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.txCentralFreq" min="950000" max="6000000" step="0.01"/></label> <label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.txCentralFreq" min="100000" max="6000000" step="0.01"/></label>
<label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.txBaudrate" min="200000" max="54000000"/></label> <label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.txBaudrate" min="200000" max="54000000"/></label>
<label> <label>
<span>Roll-off</span> <span>Roll-off</span>
<select v-model="paramRxtx.txRolloff"> <select v-model="paramRxtx.txRolloff">
<option :value="2">0.02</option> <option :value="20">0.02</option>
<option :value="5">0.05</option> <option :value="50">0.05</option>
<option :value="10">0.10</option> <option :value="100">0.10</option>
<option :value="15">0.15</option> <option :value="150">0.15</option>
<option :value="20">0.20</option> <option :value="200">0.20</option>
<option :value="25">0.25</option> <option :value="250">0.25</option>
</select> </select>
</label> </label>
<label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.txSpreadCoef" min="-1000" max="1000" step="0.01"/></label> <label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.txSpreadCoef" min="-1000" max="1000" step="0.01"/></label>
<label>
<span>Номер последовательности Голда</span>
<select v-model="paramRxtx.txGoldan">
<option :value="0">0</option>
<option :value="1">1</option>
</select>
</label>
<label><span>Ослабление, дБ</span><input type="number" v-model="paramRxtx.txAttenuation" min="-40" step="0.25"/></label> <label><span>Ослабление, дБ</span><input type="number" v-model="paramRxtx.txAttenuation" min="-40" step="0.25"/></label>
</div> </div>
<div class="settings-set-container">
<h3>Авто-регулировка мощности</h3>
<label>
<span>Авто-регулировка мощности</span>
<span class="toggle-input"><input type="checkbox" v-model="paramRxtx.aupcEn" /><span class="slider"></span></span>
</label>
<label><span>Минимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMinAttenuation" max="10" step="0.1"/></label>
<label><span>Максимальное ослабление, дБ</span><input type="number" v-model="paramRxtx.aupcMaxAttenuation" max="10" step="0.1"/></label>
<label><span>Требуемое ОСШ</span><input type="number" v-model="paramRxtx.aupcRequiredSnr" max="30" step="0.01"/></label>
</div>
<div class="settings-set-container"> <div class="settings-set-container">
<h3>Настройки приемника</h3> <h3>Настройки приемника</h3>
<label> <label>
@@ -175,27 +178,20 @@
<span>Инверсия спектра</span> <span>Инверсия спектра</span>
<span class="toggle-input"><input type="checkbox" v-model="paramRxtx.rxSpectrumInversion" /><span class="slider"></span></span> <span class="toggle-input"><input type="checkbox" v-model="paramRxtx.rxSpectrumInversion" /><span class="slider"></span></span>
</label> </label>
<label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.rxCentralFreq" min="950000" max="6000000" step="0.01"/></label> <label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.rxCentralFreq" min="100000" max="6000000" step="0.01"/></label>
<label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.rxBaudrate" min="200000" max="54000000"/></label> <label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.rxBaudrate" min="200000" max="54000000"/></label>
<label> <label>
<span>Roll-off</span> <span>Roll-off</span>
<select v-model="paramRxtx.rxRolloff"> <select v-model="paramRxtx.rxRolloff">
<option :value="2">0.02</option> <option :value="20">0.02</option>
<option :value="5">0.05</option> <option :value="50">0.05</option>
<option :value="10">0.10</option> <option :value="100">0.10</option>
<option :value="15">0.15</option> <option :value="150">0.15</option>
<option :value="20">0.20</option> <option :value="200">0.20</option>
<option :value="25">0.25</option> <option :value="250">0.25</option>
</select> </select>
</label> </label>
<label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.rxSpreadCoef" min="-1000" max="1000" step="0.01"/></label> <label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.rxSpreadCoef" min="-1000" max="1000" step="0.01"/></label>
<label>
<span>Номер последовательности Голда</span>
<select v-model="paramRxtx.rxGoldan">
<option :value="0">0</option>
<option :value="1">1</option>
</select>
</label>
</div> </div>
</div> </div>
<button class="action-button" @click="settingsSubmitRxtx()">Сохранить <span class="submit-spinner" v-show="submitStatus.rxtx"></span></button> <button class="action-button" @click="settingsSubmitRxtx()">Сохранить <span class="submit-spinner" v-show="submitStatus.rxtx"></span></button>
@@ -246,6 +242,31 @@
</div> </div>
<button class="action-button" @click="settingsSubmitBuclnb()">Сохранить <span class="submit-spinner" v-show="submitStatus.buclnb"></span></button> <button class="action-button" @click="settingsSubmitBuclnb()">Сохранить <span class="submit-spinner" v-show="submitStatus.buclnb"></span></button>
</div> <div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete"> </div> <div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete">
<h2>Настройки сети</h2>
<div class="settings-set-container">
<h3>Настройки интерфейса управления</h3>
<label>
<span>Интерфейс управления (a.d.d.r/mask)</span>
<input v-model="paramNetwork.managementIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$">
</label>
<label>
<span>Режим сети</span>
<select v-model="paramNetwork.isL2">
<option :value="false">Маршрутизатор</option>
<option :value="true">Коммутатор</option>
</select>
</label>
<label v-show="paramNetwork.isL2 === false">
<span>Интерфейс данных (/24)</span>
<input v-model="paramNetwork.dataIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$">
</label>
<label><span>MTU интерфейса данных</span><input type="number" v-model="paramNetwork.dataMtu" min="1500" max="2000" step="1"/></label>
<label>
<span>Имя веб-сервера</span>
<input v-model="paramNetwork.serverName" type="text">
</label>
</div>
<button class="action-button" @click="settingsSubmitNetwork()">Сохранить <span class="submit-spinner" v-show="submitStatus.network"></span></button>
<h2>Система</h2> <h2>Система</h2>
<div class="settings-set-container statistics-container"> <div class="settings-set-container statistics-container">
@@ -264,6 +285,8 @@
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button> <button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
</div> </div>
<button class="action-button" @click="dumpAllSettings()">Сохранить бекап конфигурации</button>
<button class="dangerous-button" @click="restoreAllSettings()">Восстановить бекап конфигурации</button>
</div> </div>
<h2>Обновление ПО</h2> <h2>Обновление ПО</h2>
@@ -316,6 +339,7 @@
submitStatus: { submitStatus: {
rxtx: false, rxtx: false,
buclnb: false, buclnb: false,
network: false,
firmwareUpload: false, firmwareUpload: false,
firmwareUpgrade: false, firmwareUpgrade: false,
// когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю // когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю
@@ -328,20 +352,22 @@
txAutoStart: false, txAutoStart: false,
txModulatorIsTest: false, txModulatorIsTest: false,
txIsTestInput: false, txIsTestInput: false,
txCentralFreq: 950000, txCentralFreq: 100000,
txBaudrate: 200000, txBaudrate: 200000,
txRolloff: 2, txRolloff: 20,
txSpreadCoef: -1000, txSpreadCoef: -1000,
txGoldan: 0,
txAttenuation: -40, txAttenuation: -40,
aupcEn: false,
aupcMinAttenuation: 0,
aupcMaxAttenuation: 0,
aupcRequiredSnr: 0,
rxAgcEn: false, rxAgcEn: false,
rxManualGain: -40, rxManualGain: -40,
rxSpectrumInversion: false, rxSpectrumInversion: false,
rxCentralFreq: 950000, rxCentralFreq: 100000,
rxBaudrate: 200000, rxBaudrate: 200000,
rxRolloff: 2, rxRolloff: 20,
rxSpreadCoef: -1000, rxSpreadCoef: -1000,
rxGoldan: 0,
}, },
paramBuclnb: { paramBuclnb: {
bucRefClk10M: false, bucRefClk10M: false,
@@ -351,6 +377,13 @@
srvRefClk10M: false, srvRefClk10M: false,
bucLnbAutoStart: false, bucLnbAutoStart: false,
}, },
paramNetwork: {
managementIp: null,
isL2: false,
dataIp: null,
dataMtu: 1500,
serverName: null,
},
// ========== include end from 'common/all-params-data.js.j2' // ========== include end from 'common/all-params-data.js.j2'
// ========== include from 'common/monitoring-data.js.j2' // ========== include from 'common/monitoring-data.js.j2'
@@ -473,8 +506,11 @@
"txBaudrate": this.paramRxtx.txBaudrate, "txBaudrate": this.paramRxtx.txBaudrate,
"txRolloff": this.paramRxtx.txRolloff, "txRolloff": this.paramRxtx.txRolloff,
"txSpreadCoef": this.paramRxtx.txSpreadCoef, "txSpreadCoef": this.paramRxtx.txSpreadCoef,
"txGoldan": this.paramRxtx.txGoldan,
"txAttenuation": this.paramRxtx.txAttenuation, "txAttenuation": this.paramRxtx.txAttenuation,
"aupcEn": this.paramRxtx.aupcEn,
"aupcMinAttenuation": this.paramRxtx.aupcMinAttenuation,
"aupcMaxAttenuation": this.paramRxtx.aupcMaxAttenuation,
"aupcRequiredSnr": this.paramRxtx.aupcRequiredSnr,
"rxAgcEn": this.paramRxtx.rxAgcEn, "rxAgcEn": this.paramRxtx.rxAgcEn,
"rxManualGain": this.paramRxtx.rxManualGain, "rxManualGain": this.paramRxtx.rxManualGain,
"rxSpectrumInversion": this.paramRxtx.rxSpectrumInversion, "rxSpectrumInversion": this.paramRxtx.rxSpectrumInversion,
@@ -482,7 +518,6 @@
"rxBaudrate": this.paramRxtx.rxBaudrate, "rxBaudrate": this.paramRxtx.rxBaudrate,
"rxRolloff": this.paramRxtx.rxRolloff, "rxRolloff": this.paramRxtx.rxRolloff,
"rxSpreadCoef": this.paramRxtx.rxSpreadCoef, "rxSpreadCoef": this.paramRxtx.rxSpreadCoef,
"rxGoldan": this.paramRxtx.rxGoldan,
} }
this.submitStatus.rxtx = true this.submitStatus.rxtx = true
@@ -510,36 +545,64 @@
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) }) .catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
.finally(() => { this.submitStatus.buclnb = false }) .finally(() => { this.submitStatus.buclnb = false })
}, },
settingsSubmitNetwork() {
if (this.submitStatus.network) { return }
{ if (!confirm("Применение этих настроек может сделать модем недоступным! Продолжить?")) return }
let query = {
"managementIp": this.paramNetwork.managementIp,
"isL2": this.paramNetwork.isL2,
"dataIp": this.paramNetwork.dataIp,
"dataMtu": this.paramNetwork.dataMtu,
"serverName": this.paramNetwork.serverName,
}
this.submitStatus.network = true
fetch('/api/set/network', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' })
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.updateNetworkSettings(vals) })
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
.finally(() => { this.submitStatus.network = false })
},
updateRxtxSettings(vals) { updateRxtxSettings(vals) {
this.submitStatus.rxtx = false this.submitStatus.rxtx = false
this.paramRxtx.txEn = vals["settings"]["txEn"] this.paramRxtx.txEn = vals["settings"]["rxtx"]["txEn"]
this.paramRxtx.txAutoStart = vals["settings"]["txAutoStart"] this.paramRxtx.txAutoStart = vals["settings"]["rxtx"]["txAutoStart"]
this.paramRxtx.txModulatorIsTest = vals["settings"]["txModulatorIsTest"] this.paramRxtx.txModulatorIsTest = vals["settings"]["rxtx"]["txModulatorIsTest"]
this.paramRxtx.txIsTestInput = vals["settings"]["txIsTestInput"] this.paramRxtx.txIsTestInput = vals["settings"]["rxtx"]["txIsTestInput"]
this.paramRxtx.txCentralFreq = vals["settings"]["txCentralFreq"] this.paramRxtx.txCentralFreq = vals["settings"]["rxtx"]["txCentralFreq"]
this.paramRxtx.txBaudrate = vals["settings"]["txBaudrate"] this.paramRxtx.txBaudrate = vals["settings"]["rxtx"]["txBaudrate"]
this.paramRxtx.txRolloff = vals["settings"]["txRolloff"] this.paramRxtx.txRolloff = vals["settings"]["rxtx"]["txRolloff"]
this.paramRxtx.txSpreadCoef = vals["settings"]["txSpreadCoef"] this.paramRxtx.txSpreadCoef = vals["settings"]["rxtx"]["txSpreadCoef"]
this.paramRxtx.txGoldan = vals["settings"]["txGoldan"] this.paramRxtx.txAttenuation = vals["settings"]["rxtx"]["txAttenuation"]
this.paramRxtx.txAttenuation = vals["settings"]["txAttenuation"] this.paramRxtx.aupcEn = vals["settings"]["rxtx"]["aupcEn"]
this.paramRxtx.rxAgcEn = vals["settings"]["rxAgcEn"] this.paramRxtx.aupcMinAttenuation = vals["settings"]["rxtx"]["aupcMinAttenuation"]
this.paramRxtx.rxManualGain = vals["settings"]["rxManualGain"] this.paramRxtx.aupcMaxAttenuation = vals["settings"]["rxtx"]["aupcMaxAttenuation"]
this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxSpectrumInversion"] this.paramRxtx.aupcRequiredSnr = vals["settings"]["rxtx"]["aupcRequiredSnr"]
this.paramRxtx.rxCentralFreq = vals["settings"]["rxCentralFreq"] this.paramRxtx.rxAgcEn = vals["settings"]["rxtx"]["rxAgcEn"]
this.paramRxtx.rxBaudrate = vals["settings"]["rxBaudrate"] this.paramRxtx.rxManualGain = vals["settings"]["rxtx"]["rxManualGain"]
this.paramRxtx.rxRolloff = vals["settings"]["rxRolloff"] this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxtx"]["rxSpectrumInversion"]
this.paramRxtx.rxSpreadCoef = vals["settings"]["rxSpreadCoef"] this.paramRxtx.rxCentralFreq = vals["settings"]["rxtx"]["rxCentralFreq"]
this.paramRxtx.rxGoldan = vals["settings"]["rxGoldan"] this.paramRxtx.rxBaudrate = vals["settings"]["rxtx"]["rxBaudrate"]
this.paramRxtx.rxRolloff = vals["settings"]["rxtx"]["rxRolloff"]
this.paramRxtx.rxSpreadCoef = vals["settings"]["rxtx"]["rxSpreadCoef"]
}, },
updateBuclnbSettings(vals) { updateBuclnbSettings(vals) {
this.submitStatus.buclnb = false this.submitStatus.buclnb = false
this.paramBuclnb.bucRefClk10M = vals["settings"]["bucRefClk10M"] this.paramBuclnb.bucRefClk10M = vals["settings"]["buclnb"]["bucRefClk10M"]
this.paramBuclnb.bucPowering = vals["settings"]["bucPowering"] this.paramBuclnb.bucPowering = vals["settings"]["buclnb"]["bucPowering"]
this.paramBuclnb.lnbRefClk10M = vals["settings"]["lnbRefClk10M"] this.paramBuclnb.lnbRefClk10M = vals["settings"]["buclnb"]["lnbRefClk10M"]
this.paramBuclnb.lnbPowering = vals["settings"]["lnbPowering"] this.paramBuclnb.lnbPowering = vals["settings"]["buclnb"]["lnbPowering"]
this.paramBuclnb.srvRefClk10M = vals["settings"]["srvRefClk10M"] this.paramBuclnb.srvRefClk10M = vals["settings"]["buclnb"]["srvRefClk10M"]
this.paramBuclnb.bucLnbAutoStart = vals["settings"]["bucLnbAutoStart"] this.paramBuclnb.bucLnbAutoStart = vals["settings"]["buclnb"]["bucLnbAutoStart"]
},
updateNetworkSettings(vals) {
this.submitStatus.network = false
this.paramNetwork.managementIp = vals["settings"]["network"]["managementIp"]
this.paramNetwork.isL2 = vals["settings"]["network"]["isL2"]
this.paramNetwork.dataIp = vals["settings"]["network"]["dataIp"]
this.paramNetwork.dataMtu = vals["settings"]["network"]["dataMtu"]
this.paramNetwork.serverName = vals["settings"]["network"]["serverName"]
}, },
// ========== include end from 'common/all-params-methods.js.j2' // ========== include end from 'common/all-params-methods.js.j2'
@@ -564,44 +627,43 @@
} }
this.lastUpdateTime = new Date(); this.lastUpdateTime = new Date();
this.initState = vals["mainState"]["initState"] this.initState = vals["state"]["initState"]
this.testState = vals["state"]["testState"]
this.statRx.state = vals["mainState"]["rx.state"] this.statRx.state = vals["state"]["rx"]["state"]
this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"] this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"]
this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"] this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"]
this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"] this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"]
this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"] this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"]
this.statRx.snr = vals["mainState"]["rx.snr"] this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10
this.statRx.rssi = vals["mainState"]["rx.rssi"] this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10
this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"]) this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"])
this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"] this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"]
this.statRx.isPilots = vals["mainState"]["rx.isPilots"] this.statRx.isPilots = vals["state"]["rx"]["isPilots"]
this.statRx.symError = vals["mainState"]["rx.symError"] this.statRx.symError = vals["state"]["rx"]["symError"]
this.statRx.freqErr = vals["mainState"]["rx.freqErr"] this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100
this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"] this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100
this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"] this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"]
this.statRx.pllError = vals["mainState"]["rx.pllError"] this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100
this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"] this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100
this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"] this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100
this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"] this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"]
this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"] this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"]
this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"] this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"]
this.statTx.state = vals["mainState"]["tx.state"] this.statTx.state = vals["state"]["tx"]["state"]
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"])
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100
this.statTx.centerFreq = vals["mainState"]["tx.centerFreq"] this.statTx.centerFreq = vals["state"]["tx"]["centerFreq"]
this.statTx.symSpeed = vals["mainState"]["tx.symSpeed"] this.statTx.symSpeed = vals["state"]["tx"]["symSpeed"]
this.statDevice.adrv = vals["mainState"]["device.adrv"] this.statDevice.adrv = vals["state"]["device"]["adrv"]
this.statDevice.zynq = vals["mainState"]["device.zynq"] this.statDevice.zynq = vals["state"]["device"]["zynq"]
this.statDevice.fpga = vals["mainState"]["device.fpga"] this.statDevice.fpga = vals["state"]["device"]["fpga"]
this.testState = vals["mainState"]["testState"]
// аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид
let uptime = vals["sysinfo"]["uptime"] let uptime = vals["state"]["device"]["uptime"]
if (uptime) { if (uptime) {
let secs = uptime % 60; uptime = Math.floor(uptime / 60) let secs = uptime % 60; uptime = Math.floor(uptime / 60)
let mins = uptime % 60; uptime = Math.floor(uptime / 60) let mins = uptime % 60; uptime = Math.floor(uptime / 60)
@@ -613,11 +675,11 @@
} else { } else {
this.statOs.uptime = '?' this.statOs.uptime = '?'
} }
this.statOs.load1 = vals["sysinfo"]["load1min"] this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100
this.statOs.load5 = vals["sysinfo"]["load5min"] this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100
this.statOs.load15 = vals["sysinfo"]["load15min"] this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100
this.statOs.totalram = vals["sysinfo"]["totalram"] this.statOs.totalram = vals["state"]["device"]["totalram"]
this.statOs.freeram = vals["sysinfo"]["freeram"] this.statOs.freeram = vals["state"]["device"]["freeram"]
}, },
resetPacketsStatistics() { resetPacketsStatistics() {
@@ -696,6 +758,133 @@
} }
this.submitStatus.modemReboot = 30 this.submitStatus.modemReboot = 30
fetch('/api/reboot', { method: 'POST' }).then((r) => {}) fetch('/api/reboot', { method: 'POST' }).then((r) => {})
},
async restoreAllSettings() {
// Порядок применения настроек
const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network'];
// 1. Чтение JSON-файла, выбранного пользователем
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.json';
const filePromise = new Promise((resolve, reject) => {
fileInput.onchange = e => {
const file = e.target.files[0];
if (!file) {
reject(new Error('Файл не выбран'));
return;
}
const reader = new FileReader();
reader.onload = event => {
try {
const jsonData = JSON.parse(event.target.result);
resolve(jsonData);
} catch (error) {
reject(new Error('Ошибка парсинга JSON'));
}
};
reader.onerror = () => reject(new Error('Ошибка чтения файла'));
reader.readAsText(file);
};
fileInput.click();
});
try {
const settingsToApply = await filePromise;
const errors = [];
// 2. Перебор групп параметров в заданном порядке
for (const groupName of settingsApplyOrder) {
if (!settingsToApply.hasOwnProperty(groupName)) {
continue; // Пропускаем группы, которых нет в файле
}
const groupSettings = settingsToApply[groupName];
if (typeof groupSettings !== 'object' || groupSettings === null) {
continue;
}
try {
// 2.1. POST-запрос для применения группы параметров
const postResponse = await fetch(`/api/set/${groupName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(groupSettings)
});
if (!postResponse.ok) {
throw new Error(`HTTP error ${postResponse.status}`);
}
const postResult = await postResponse.json();
if (postResult.status !== 'ok') {
throw new Error(`API error: ${postResult.message || 'unknown error'}`);
}
// 2.2. Проверка примененных параметров
const getResponse = await fetch('/api/get/settings', { method: 'GET' });
if (!getResponse.ok) {
throw new Error(`HTTP error ${getResponse.status}`);
}
const fetchSettingsResult = await getResponse.json();
if (fetchSettingsResult.status !== 'ok') {
throw new Error('Не удалось получить текущие настройки');
}
// Проверка соответствия параметров
const appliedGroup = fetchSettingsResult.settings[groupName] || {};
const failedSettings = [];
for (const [key, value] of Object.entries(groupSettings)) {
if (appliedGroup[key] !== value) {
failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`);
}
}
if (failedSettings.length > 0) {
throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`);
}
} catch (groupError) {
errors.push(`Группа ${groupName}: ${groupError.message}`);
}
}
// 3. Показ ошибок, если они есть
if (errors.length > 0) {
const errorMessage = errors.join('\n\n') +
'\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.';
alert(errorMessage);
}
} catch (error) {
alert(`Ошибка при восстановлении настроек: ${error.message}`);
return;
}
// 4. Перезагрузка страницы
location.reload();
},
async dumpAllSettings() {
function downloadAsFile(data, filename) {
let a = document.createElement("a");
let file = new Blob([data], {type: 'application/json'});
a.href = URL.createObjectURL(file);
a.download = filename;
a.click();
}
const response = await fetch('/api/get/settings', { method: 'GET' })
if (response.ok) {
const jres = await response.json()
if (jres["status"] === "ok") {
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2' }, // ========== include end from 'common/admin-methods.js.j2'
@@ -706,6 +895,7 @@
this.settingFetchComplete = true this.settingFetchComplete = true
this.updateRxtxSettings(vals) this.updateRxtxSettings(vals)
this.updateBuclnbSettings(vals) this.updateBuclnbSettings(vals)
this.updateNetworkSettings(vals)
if ('netServerName' in vals['settings']) { if ('netServerName' in vals['settings']) {
document.getElementsByTagName('title')[0].innerText = vals['settings']['netServerName'] document.getElementsByTagName('title')[0].innerText = vals['settings']['netServerName']
@@ -740,11 +930,11 @@
try { try {
const fr = await fetch("/api/get/aboutFirmware") const fr = await fetch("/api/get/aboutFirmware")
const d = await fr.json() const d = await fr.json()
this.about.firmwareVersion = d["fw.version"] this.about.firmwareVersion = d["firmware"]["version"]
this.about.modemUid = d["fw.modemId"] this.about.modemUid = d["firmware"]["modemId"]
this.about.modemSn = d["fw.modemSn"] this.about.modemSn = d["firmware"]["modemSn"]
this.about.macManagement = d["fw.macMang"] this.about.macManagement = d["firmware"]["macMang"]
this.about.macData = d["fw.macData"] this.about.macData = d["firmware"]["macData"]
} catch (e) { } catch (e) {
console.log('Ошибка загрузки версии ПО', e) console.log('Ошибка загрузки версии ПО', e)
} }

View File

@@ -158,12 +158,12 @@
<label> <label>
<span>Roll-off</span> <span>Roll-off</span>
<select v-model="paramRxtx.rxRolloff"> <select v-model="paramRxtx.rxRolloff">
<option :value="2">0.02</option> <option :value="20">0.02</option>
<option :value="5">0.05</option> <option :value="50">0.05</option>
<option :value="10">0.10</option> <option :value="100">0.10</option>
<option :value="15">0.15</option> <option :value="150">0.15</option>
<option :value="20">0.20</option> <option :value="200">0.20</option>
<option :value="25">0.25</option> <option :value="250">0.25</option>
</select> </select>
</label> </label>
</div> </div>
@@ -173,16 +173,16 @@
<div class="settings-set-container"> <div class="settings-set-container">
<label> <label>
<span>Метод расчета задержки</span> <span>Метод расчета задержки</span>
<select v-model="paramDpdi.dpdiIsPositional"> <select v-model="paramDpdi.isPositional">
<option :value="true">Позиционированием</option> <option :value="true">Позиционированием</option>
<option :value="false">Окном задержки</option> <option :value="false">Окном задержки</option>
</select> </select>
</label> </label>
<h2 v-show="paramDpdi.dpdiIsPositional === true">Настройки позиционирования</h2> <h2 v-show="paramDpdi.isPositional === true">Настройки позиционирования</h2>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Широта станции</span><input type="number" v-model="paramDpdi.dpdiPositionStationLatitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Широта станции</span><input type="number" v-model="paramDpdi.positionStationLatitude" min="-180" max="180" step="1e-06"/></label>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Долгота станции</span><input type="number" v-model="paramDpdi.dpdiPositionStationLongitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Долгота станции</span><input type="number" v-model="paramDpdi.positionStationLongitude" min="-180" max="180" step="1e-06"/></label>
<label v-show="paramDpdi.dpdiIsPositional === true"><span>Подспутниковая точка</span><input type="number" v-model="paramDpdi.dpdiPositionSatelliteLongitude" min="-180" max="180" step="1e-06"/></label> <label v-show="paramDpdi.isPositional === true"><span>Подспутниковая точка</span><input type="number" v-model="paramDpdi.positionSatelliteLongitude" min="-180" max="180" step="1e-06"/></label>
<label v-show="paramDpdi.dpdiIsPositional === false"><span>Задержка до спутника, мс</span><input type="number" v-model="paramDpdi.dpdiDelay" max="400" step="0.1"/></label> <label v-show="paramDpdi.isPositional === false"><span>Задержка до спутника, мс</span><input type="number" v-model="paramDpdi.delay" max="400" step="0.1"/></label>
</div> </div>
<button class="action-button" @click="settingsSubmitDpdi()">Сохранить <span class="submit-spinner" v-show="submitStatus.dpdi"></span></button> <button class="action-button" @click="settingsSubmitDpdi()">Сохранить <span class="submit-spinner" v-show="submitStatus.dpdi"></span></button>
<h2>Настройки питания и опорного генератора</h2> <h2>Настройки питания и опорного генератора</h2>
@@ -200,6 +200,10 @@
<option :value="24">24В</option> <option :value="24">24В</option>
</select> </select>
</label> </label>
<label>
<span>Частота LO, кГц</span>
<input type="text" v-model.lazy="paramBuclnb.bucLoKhz" @change="e => paramBuclnb.bucLoKhz = inputFormatNumber(inputFormatNumber(e.target.value, {max:40000000,step:1}), {max:40000000,step:1})"/>
</label>
</div> </div>
<div class="settings-set-container"> <div class="settings-set-container">
<h3>Настройки LNB</h3> <h3>Настройки LNB</h3>
@@ -216,6 +220,10 @@
<option :value="24">24В</option> <option :value="24">24В</option>
</select> </select>
</label> </label>
<label>
<span>Частота LO, кГц</span>
<input type="text" v-model.lazy="paramBuclnb.lnbLoKhz" @change="e => paramBuclnb.lnbLoKhz = inputFormatNumber(inputFormatNumber(e.target.value, {max:40000000,step:1}), {max:40000000,step:1})"/>
</label>
</div> </div>
<div class="settings-set-container"> <div class="settings-set-container">
<h3>Сервисные настройки</h3> <h3>Сервисные настройки</h3>
@@ -235,16 +243,16 @@
<div class="settings-set-container"> <div class="settings-set-container">
<label> <label>
<span>Пароль для входа в сеть ЦЗС</span> <span>Пароль для входа в сеть ЦЗС</span>
<input v-model="paramNetwork.netCesPassword" type="text"> <input v-model="paramNetwork.cesPassword" type="text">
</label> </label>
<h3>Настройки интерфейса управления</h3> <h3>Настройки интерфейса управления</h3>
<label> <label>
<span>IP Интерфейса управления (/24)</span> <span>Интерфейс управления (a.d.d.r/mask)</span>
<input v-model="paramNetwork.netManagementIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$"> <input v-model="paramNetwork.managementIp" required type="text" pattern="^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$">
</label> </label>
<label> <label>
<span>Имя веб-сервера</span> <span>Имя веб-сервера</span>
<input v-model="paramNetwork.netServerName" type="text"> <input v-model="paramNetwork.serverName" type="text">
</label> </label>
</div> </div>
<button class="action-button" @click="settingsSubmitNetwork()">Сохранить <span class="submit-spinner" v-show="submitStatus.network"></span></button> <button class="action-button" @click="settingsSubmitNetwork()">Сохранить <span class="submit-spinner" v-show="submitStatus.network"></span></button>
@@ -266,6 +274,8 @@
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button> <button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
</div> </div>
<button class="action-button" @click="dumpAllSettings()">Сохранить бекап конфигурации</button>
<button class="dangerous-button" @click="restoreAllSettings()">Восстановить бекап конфигурации</button>
</div> </div>
<h2>Обновление ПО</h2> <h2>Обновление ПО</h2>
@@ -340,27 +350,29 @@
rxSpectrumInversion: false, rxSpectrumInversion: false,
rxCentralFreq: 0, rxCentralFreq: 0,
rxBaudrate: 0, rxBaudrate: 0,
rxRolloff: 2, rxRolloff: 20,
}, },
paramBuclnb: { paramBuclnb: {
bucRefClk10M: false, bucRefClk10M: false,
bucPowering: 0, bucPowering: 0,
bucLoKhz: 0,
lnbRefClk10M: false, lnbRefClk10M: false,
lnbPowering: 0, lnbPowering: 0,
lnbLoKhz: 0,
srvRefClk10M: false, srvRefClk10M: false,
bucLnbAutoStart: false, bucLnbAutoStart: false,
}, },
paramDpdi: { paramDpdi: {
dpdiIsPositional: true, isPositional: true,
dpdiPositionStationLatitude: -180, positionStationLatitude: -180,
dpdiPositionStationLongitude: -180, positionStationLongitude: -180,
dpdiPositionSatelliteLongitude: -180, positionSatelliteLongitude: -180,
dpdiDelay: 0, delay: 0,
}, },
paramNetwork: { paramNetwork: {
netCesPassword: null, cesPassword: null,
netManagementIp: null, managementIp: null,
netServerName: null, serverName: null,
}, },
// ========== include end from 'common/all-params-data.js.j2' // ========== include end from 'common/all-params-data.js.j2'
@@ -503,8 +515,10 @@
let query = { let query = {
"bucRefClk10M": this.paramBuclnb.bucRefClk10M, "bucRefClk10M": this.paramBuclnb.bucRefClk10M,
"bucPowering": this.paramBuclnb.bucPowering, "bucPowering": this.paramBuclnb.bucPowering,
"bucLoKhz": parseFloat(this.paramBuclnb.bucLoKhz.replace(/[^0-9,.]/g, '').replace(',', '.')),
"lnbRefClk10M": this.paramBuclnb.lnbRefClk10M, "lnbRefClk10M": this.paramBuclnb.lnbRefClk10M,
"lnbPowering": this.paramBuclnb.lnbPowering, "lnbPowering": this.paramBuclnb.lnbPowering,
"lnbLoKhz": parseFloat(this.paramBuclnb.lnbLoKhz.replace(/[^0-9,.]/g, '').replace(',', '.')),
"srvRefClk10M": this.paramBuclnb.srvRefClk10M, "srvRefClk10M": this.paramBuclnb.srvRefClk10M,
"bucLnbAutoStart": this.paramBuclnb.bucLnbAutoStart, "bucLnbAutoStart": this.paramBuclnb.bucLnbAutoStart,
} }
@@ -519,11 +533,11 @@
if (this.submitStatus.dpdi) { return } if (this.submitStatus.dpdi) { return }
let query = { let query = {
"dpdiIsPositional": this.paramDpdi.dpdiIsPositional, "isPositional": this.paramDpdi.isPositional,
"dpdiPositionStationLatitude": this.paramDpdi.dpdiPositionStationLatitude, "positionStationLatitude": this.paramDpdi.positionStationLatitude,
"dpdiPositionStationLongitude": this.paramDpdi.dpdiPositionStationLongitude, "positionStationLongitude": this.paramDpdi.positionStationLongitude,
"dpdiPositionSatelliteLongitude": this.paramDpdi.dpdiPositionSatelliteLongitude, "positionSatelliteLongitude": this.paramDpdi.positionSatelliteLongitude,
"dpdiDelay": this.paramDpdi.dpdiDelay, "delay": this.paramDpdi.delay,
} }
this.submitStatus.dpdi = true this.submitStatus.dpdi = true
@@ -537,9 +551,9 @@
{ if (!confirm("Применение этих настроек может сделать модем недоступным! Продолжить?")) return } { if (!confirm("Применение этих настроек может сделать модем недоступным! Продолжить?")) return }
let query = { let query = {
"netCesPassword": this.paramNetwork.netCesPassword, "cesPassword": this.paramNetwork.cesPassword,
"netManagementIp": this.paramNetwork.netManagementIp, "managementIp": this.paramNetwork.managementIp,
"netServerName": this.paramNetwork.netServerName, "serverName": this.paramNetwork.serverName,
} }
this.submitStatus.network = true this.submitStatus.network = true
@@ -551,39 +565,41 @@
updateRxtxSettings(vals) { updateRxtxSettings(vals) {
this.submitStatus.rxtx = false this.submitStatus.rxtx = false
this.paramRxtx.txEn = vals["settings"]["txEn"] this.paramRxtx.txEn = vals["settings"]["rxtx"]["txEn"]
this.paramRxtx.txModulatorIsTest = vals["settings"]["txModulatorIsTest"] this.paramRxtx.txModulatorIsTest = vals["settings"]["rxtx"]["txModulatorIsTest"]
this.paramRxtx.txCentralFreq = this.inputFormatNumber(vals["settings"]["txCentralFreq"], {min:900000,step:0.01}) this.paramRxtx.txCentralFreq = this.inputFormatNumber(vals["settings"]["rxtx"]["txCentralFreq"], {min:900000,step:0.01})
this.paramRxtx.txAttenuation = vals["settings"]["txAttenuation"] this.paramRxtx.txAttenuation = vals["settings"]["rxtx"]["txAttenuation"]
this.paramRxtx.rxAgcEn = vals["settings"]["rxAgcEn"] this.paramRxtx.rxAgcEn = vals["settings"]["rxtx"]["rxAgcEn"]
this.paramRxtx.rxManualGain = vals["settings"]["rxManualGain"] this.paramRxtx.rxManualGain = vals["settings"]["rxtx"]["rxManualGain"]
this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxSpectrumInversion"] this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxtx"]["rxSpectrumInversion"]
this.paramRxtx.rxCentralFreq = this.inputFormatNumber(vals["settings"]["rxCentralFreq"], {min:900000,step:0.01}) this.paramRxtx.rxCentralFreq = this.inputFormatNumber(vals["settings"]["rxtx"]["rxCentralFreq"], {min:900000,step:0.01})
this.paramRxtx.rxBaudrate = this.inputFormatNumber(vals["settings"]["rxBaudrate"], {min:200000,max:54000000,step:1}) this.paramRxtx.rxBaudrate = this.inputFormatNumber(vals["settings"]["rxtx"]["rxBaudrate"], {min:200000,max:54000000,step:1})
this.paramRxtx.rxRolloff = vals["settings"]["rxRolloff"] this.paramRxtx.rxRolloff = vals["settings"]["rxtx"]["rxRolloff"]
}, },
updateBuclnbSettings(vals) { updateBuclnbSettings(vals) {
this.submitStatus.buclnb = false this.submitStatus.buclnb = false
this.paramBuclnb.bucRefClk10M = vals["settings"]["bucRefClk10M"] this.paramBuclnb.bucRefClk10M = vals["settings"]["buclnb"]["bucRefClk10M"]
this.paramBuclnb.bucPowering = vals["settings"]["bucPowering"] this.paramBuclnb.bucPowering = vals["settings"]["buclnb"]["bucPowering"]
this.paramBuclnb.lnbRefClk10M = vals["settings"]["lnbRefClk10M"] this.paramBuclnb.bucLoKhz = this.inputFormatNumber(vals["settings"]["buclnb"]["bucLoKhz"], {max:40000000,step:1})
this.paramBuclnb.lnbPowering = vals["settings"]["lnbPowering"] this.paramBuclnb.lnbRefClk10M = vals["settings"]["buclnb"]["lnbRefClk10M"]
this.paramBuclnb.srvRefClk10M = vals["settings"]["srvRefClk10M"] this.paramBuclnb.lnbPowering = vals["settings"]["buclnb"]["lnbPowering"]
this.paramBuclnb.bucLnbAutoStart = vals["settings"]["bucLnbAutoStart"] this.paramBuclnb.lnbLoKhz = this.inputFormatNumber(vals["settings"]["buclnb"]["lnbLoKhz"], {max:40000000,step:1})
this.paramBuclnb.srvRefClk10M = vals["settings"]["buclnb"]["srvRefClk10M"]
this.paramBuclnb.bucLnbAutoStart = vals["settings"]["buclnb"]["bucLnbAutoStart"]
}, },
updateDpdiSettings(vals) { updateDpdiSettings(vals) {
this.submitStatus.dpdi = false this.submitStatus.dpdi = false
this.paramDpdi.dpdiIsPositional = vals["settings"]["dpdiIsPositional"] this.paramDpdi.isPositional = vals["settings"]["dpdi"]["isPositional"]
this.paramDpdi.dpdiPositionStationLatitude = vals["settings"]["dpdiPositionStationLatitude"] this.paramDpdi.positionStationLatitude = vals["settings"]["dpdi"]["positionStationLatitude"]
this.paramDpdi.dpdiPositionStationLongitude = vals["settings"]["dpdiPositionStationLongitude"] this.paramDpdi.positionStationLongitude = vals["settings"]["dpdi"]["positionStationLongitude"]
this.paramDpdi.dpdiPositionSatelliteLongitude = vals["settings"]["dpdiPositionSatelliteLongitude"] this.paramDpdi.positionSatelliteLongitude = vals["settings"]["dpdi"]["positionSatelliteLongitude"]
this.paramDpdi.dpdiDelay = vals["settings"]["dpdiDelay"] this.paramDpdi.delay = vals["settings"]["dpdi"]["delay"]
}, },
updateNetworkSettings(vals) { updateNetworkSettings(vals) {
this.submitStatus.network = false this.submitStatus.network = false
this.paramNetwork.netCesPassword = vals["settings"]["netCesPassword"] this.paramNetwork.cesPassword = vals["settings"]["network"]["cesPassword"]
this.paramNetwork.netManagementIp = vals["settings"]["netManagementIp"] this.paramNetwork.managementIp = vals["settings"]["network"]["managementIp"]
this.paramNetwork.netServerName = vals["settings"]["netServerName"] this.paramNetwork.serverName = vals["settings"]["network"]["serverName"]
}, },
// ========== include end from 'common/all-params-methods.js.j2' // ========== include end from 'common/all-params-methods.js.j2'
@@ -608,47 +624,46 @@
} }
this.lastUpdateTime = new Date(); this.lastUpdateTime = new Date();
this.initState = vals["mainState"]["initState"] this.initState = vals["state"]["initState"]
this.testState = vals["state"]["testState"]
this.statRx.state = vals["mainState"]["rx.state"] this.statRx.state = vals["state"]["rx"]["state"]
this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"] this.statRx.sym_sync_lock = vals["state"]["rx"]["sym_sync_lock"]
this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"] this.statRx.freq_search_lock = vals["state"]["rx"]["freq_search_lock"]
this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"] this.statRx.afc_lock = vals["state"]["rx"]["afc_lock"]
this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"] this.statRx.pkt_sync = vals["state"]["rx"]["pkt_sync"]
this.statRx.snr = vals["mainState"]["rx.snr"] this.statRx.snr = Math.round(vals["state"]["rx"]["snr"] * 10) / 10
this.statRx.rssi = vals["mainState"]["rx.rssi"] this.statRx.rssi = Math.round(vals["state"]["rx"]["rssi"] * 10) / 10
this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"]) this.statRx.modcod = modcodToStr(vals["state"]["rx"]["modcod"])
this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"] this.statRx.frameSizeNormal = vals["state"]["rx"]["frameSizeNormal"]
this.statRx.isPilots = vals["mainState"]["rx.isPilots"] this.statRx.isPilots = vals["state"]["rx"]["isPilots"]
this.statRx.symError = vals["mainState"]["rx.symError"] this.statRx.symError = vals["state"]["rx"]["symError"]
this.statRx.freqErr = vals["mainState"]["rx.freqErr"] this.statRx.freqErr = Math.round(vals["state"]["rx"]["freqErr"] * 100) / 100
this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"] this.statRx.freqErrAcc = Math.round(vals["state"]["rx"]["freqErrAcc"] * 100) / 100
this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"] this.statRx.inputSignalLevel = vals["state"]["rx"]["inputSignalLevel"]
this.statRx.pllError = vals["mainState"]["rx.pllError"] this.statRx.pllError = Math.round(vals["state"]["rx"]["pllError"] * 100) / 100
this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"] this.statRx.speedOnRxKbit = Math.round(vals["state"]["rx"]["speedOnRxKbit"] * 100) / 100
this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"] this.statRx.speedOnIifKbit = Math.round(vals["state"]["rx"]["speedOnIifKbit"] * 100) / 100
this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"] this.statRx.packetsOk = vals["state"]["rx"]["packetsOk"]
this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"] this.statRx.packetsBad = vals["state"]["rx"]["packetsBad"]
this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"] this.statRx.packetsDummy = vals["state"]["rx"]["packetsDummy"]
this.statTx.state = vals["mainState"]["tx.state"] this.statTx.state = vals["state"]["tx"]["state"]
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"]) this.statTx.modcod = modcodToStr(vals["state"]["tx"]["modcod"])
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"] this.statTx.speedOnTxKbit = Math.round(vals["state"]["tx"]["speedOnTxKbit"] * 100) / 100
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"] this.statTx.speedOnIifKbit = Math.round(vals["state"]["tx"]["speedOnIifKbit"] * 100) / 100
this.statTx.centerFreq = vals["mainState"]["tx.centerFreq"] this.statTx.centerFreq = vals["state"]["tx"]["centerFreq"]
this.statTx.symSpeed = vals["mainState"]["tx.symSpeed"] this.statTx.symSpeed = vals["state"]["tx"]["symSpeed"]
this.statDevice.adrv = vals["mainState"]["device.adrv"] this.statDevice.adrv = vals["state"]["device"]["adrv"]
this.statDevice.zynq = vals["mainState"]["device.zynq"] this.statDevice.zynq = vals["state"]["device"]["zynq"]
this.statDevice.fpga = vals["mainState"]["device.fpga"] this.statDevice.fpga = vals["state"]["device"]["fpga"]
this.statDevice.upgradeStatus = vals["mainState"]["device.upgradeStatus"] this.statDevice.upgradeStatus = vals["state"]["device"]["upgradeStatus"]
this.statDevice.upgradePercent = vals["mainState"]["device.upgradePercent"] this.statDevice.upgradePercent = vals["state"]["device"]["upgradePercent"]
this.statDevice.upgradeImage = vals["mainState"]["device.upgradeImage"] this.statDevice.upgradeImage = vals["state"]["device"]["upgradeImage"]
this.testState = vals["mainState"]["testState"]
// аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид // аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид
let uptime = vals["sysinfo"]["uptime"] let uptime = vals["state"]["device"]["uptime"]
if (uptime) { if (uptime) {
let secs = uptime % 60; uptime = Math.floor(uptime / 60) let secs = uptime % 60; uptime = Math.floor(uptime / 60)
let mins = uptime % 60; uptime = Math.floor(uptime / 60) let mins = uptime % 60; uptime = Math.floor(uptime / 60)
@@ -660,11 +675,11 @@
} else { } else {
this.statOs.uptime = '?' this.statOs.uptime = '?'
} }
this.statOs.load1 = vals["sysinfo"]["load1min"] this.statOs.load1 = Math.round(vals["state"]["device"]["load1min"] * 100) / 100
this.statOs.load5 = vals["sysinfo"]["load5min"] this.statOs.load5 = Math.round(vals["state"]["device"]["load5min"] * 100) / 100
this.statOs.load15 = vals["sysinfo"]["load15min"] this.statOs.load15 = Math.round(vals["state"]["device"]["load15min"] * 100) / 100
this.statOs.totalram = vals["sysinfo"]["totalram"] this.statOs.totalram = vals["state"]["device"]["totalram"]
this.statOs.freeram = vals["sysinfo"]["freeram"] this.statOs.freeram = vals["state"]["device"]["freeram"]
}, },
resetPacketsStatistics() { resetPacketsStatistics() {
@@ -753,6 +768,133 @@
} }
this.submitStatus.modemReboot = 30 this.submitStatus.modemReboot = 30
fetch('/api/reboot', { method: 'POST' }).then((r) => {}) fetch('/api/reboot', { method: 'POST' }).then((r) => {})
},
async restoreAllSettings() {
// Порядок применения настроек
const settingsApplyOrder = ['qos', 'tcpaccel', 'dpdi', 'rxtx', 'buclnb', 'network'];
// 1. Чтение JSON-файла, выбранного пользователем
const fileInput = document.createElement('input');
fileInput.type = 'file';
fileInput.accept = '.json';
const filePromise = new Promise((resolve, reject) => {
fileInput.onchange = e => {
const file = e.target.files[0];
if (!file) {
reject(new Error('Файл не выбран'));
return;
}
const reader = new FileReader();
reader.onload = event => {
try {
const jsonData = JSON.parse(event.target.result);
resolve(jsonData);
} catch (error) {
reject(new Error('Ошибка парсинга JSON'));
}
};
reader.onerror = () => reject(new Error('Ошибка чтения файла'));
reader.readAsText(file);
};
fileInput.click();
});
try {
const settingsToApply = await filePromise;
const errors = [];
// 2. Перебор групп параметров в заданном порядке
for (const groupName of settingsApplyOrder) {
if (!settingsToApply.hasOwnProperty(groupName)) {
continue; // Пропускаем группы, которых нет в файле
}
const groupSettings = settingsToApply[groupName];
if (typeof groupSettings !== 'object' || groupSettings === null) {
continue;
}
try {
// 2.1. POST-запрос для применения группы параметров
const postResponse = await fetch(`/api/set/${groupName}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(groupSettings)
});
if (!postResponse.ok) {
throw new Error(`HTTP error ${postResponse.status}`);
}
const postResult = await postResponse.json();
if (postResult.status !== 'ok') {
throw new Error(`API error: ${postResult.message || 'unknown error'}`);
}
// 2.2. Проверка примененных параметров
const getResponse = await fetch('/api/get/settings', { method: 'GET' });
if (!getResponse.ok) {
throw new Error(`HTTP error ${getResponse.status}`);
}
const fetchSettingsResult = await getResponse.json();
if (fetchSettingsResult.status !== 'ok') {
throw new Error('Не удалось получить текущие настройки');
}
// Проверка соответствия параметров
const appliedGroup = fetchSettingsResult.settings[groupName] || {};
const failedSettings = [];
for (const [key, value] of Object.entries(groupSettings)) {
if (appliedGroup[key] !== value) {
failedSettings.push(`${key} (ожидалось: ${value}, получено: ${appliedGroup[key]})`);
}
}
if (failedSettings.length > 0) {
throw new Error(`Не совпадают параметры: ${failedSettings.join(', ')}`);
}
} catch (groupError) {
errors.push(`Группа ${groupName}: ${groupError.message}`);
}
}
// 3. Показ ошибок, если они есть
if (errors.length > 0) {
const errorMessage = errors.join('\n\n') +
'\n\nНекоторые настройки могли примениться некорректно.\nСтраница будет перезагружена.';
alert(errorMessage);
}
} catch (error) {
alert(`Ошибка при восстановлении настроек: ${error.message}`);
return;
}
// 4. Перезагрузка страницы
location.reload();
},
async dumpAllSettings() {
function downloadAsFile(data, filename) {
let a = document.createElement("a");
let file = new Blob([data], {type: 'application/json'});
a.href = URL.createObjectURL(file);
a.download = filename;
a.click();
}
const response = await fetch('/api/get/settings', { method: 'GET' })
if (response.ok) {
const jres = await response.json()
if (jres["status"] === "ok") {
downloadAsFile(JSON.stringify(jres["settings"], null, 4), "backup-" + this.about.firmwareVersion + "-" + this.about.modemSn + ".json")
}
}
}, // ========== include end from 'common/admin-methods.js.j2' }, // ========== include end from 'common/admin-methods.js.j2'
@@ -799,11 +941,11 @@
try { try {
const fr = await fetch("/api/get/aboutFirmware") const fr = await fetch("/api/get/aboutFirmware")
const d = await fr.json() const d = await fr.json()
this.about.firmwareVersion = d["fw.version"] this.about.firmwareVersion = d["firmware"]["version"]
this.about.modemUid = d["fw.modemId"] this.about.modemUid = d["firmware"]["modemId"]
this.about.modemSn = d["fw.modemSn"] this.about.modemSn = d["firmware"]["modemSn"]
this.about.macManagement = d["fw.macMang"] this.about.macManagement = d["firmware"]["macMang"]
this.about.macData = d["fw.macData"] this.about.macData = d["firmware"]["macData"]
} catch (e) { } catch (e) {
console.log('Ошибка загрузки версии ПО', e) console.log('Ошибка загрузки версии ПО', e)
} }