Compare commits
11 Commits
4df06ee57b
...
e313027759
Author | SHA1 | Date | |
---|---|---|---|
e313027759 | |||
136d8dbb5b | |||
456faedf7d | |||
2c9d513613 | |||
46497bfda0 | |||
0982544c2e | |||
5a94f9a4fd | |||
25a3b11ba8 | |||
bf2d374705 | |||
a7242c186d | |||
44aec3a114 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -5,3 +5,7 @@ cert.pem
|
|||||||
key.pem
|
key.pem
|
||||||
dh.pem
|
dh.pem
|
||||||
/web-action
|
/web-action
|
||||||
|
|
||||||
|
# эти файлы после генерации должны быть перемещены в `/static`
|
||||||
|
front-generator/main-scpc.html
|
||||||
|
front-generator/main-tdma.html
|
||||||
|
@ -1,74 +1,336 @@
|
|||||||
{
|
{
|
||||||
"monitoring-params": {},
|
|
||||||
"params": {
|
|
||||||
"rxtx": {
|
|
||||||
"rx.en": {
|
|
||||||
"model": "w:switch",
|
|
||||||
"label": "Включить передатчик"
|
|
||||||
},
|
|
||||||
"rx.isTestInputData": {
|
|
||||||
"model": "w:select",
|
|
||||||
"label": "Включить передатчик",
|
|
||||||
"items": [
|
|
||||||
{"value": "false", "label": "Ethernet"},
|
|
||||||
{"value": "true", "label": "Тест (CW)"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"rx.freqKhz": {
|
|
||||||
"model": "w:number",
|
|
||||||
"number.type": "int",
|
|
||||||
"number.step": 1,
|
|
||||||
"number.min": 500000,
|
|
||||||
"number.max": 15000000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"modem_types": {
|
"modem_types": {
|
||||||
"tdma": {
|
"tdma": {
|
||||||
"modem_name": "RCSM-101 TDMA",
|
"modem_name": "RCSM-101 TDMA",
|
||||||
"groupsList": ["rxtx"],
|
"dangerousParamGroups": {
|
||||||
|
"buclnb": "Применение неправильных настроек может вывести из строя оборудование! Продолжить?",
|
||||||
|
"network": "Применение этих настроек может сделать модем недоступным! Продолжить?"
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"rxtx": [
|
||||||
|
{"widget": "h2", "label": "Настройки приема/передачи"},
|
||||||
|
{
|
||||||
|
"widget": "flex-container",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки передатчика"},
|
||||||
|
{"widget": "checkbox", "label": "Включить передатчик", "name": "txEn"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Входные данные", "name": "txIsTestInput",
|
||||||
|
"values": [
|
||||||
|
{"label": "SCPC", "value": "false"},
|
||||||
|
{"label": "Тест", "value": "true"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{"widget": "number", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 900000, "step": 0.01, "v_show": "paramRxrx.txIsTestInput"},
|
||||||
|
{"widget": "number", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 0, "step": 1, "v_show": "paramRxrx.txIsTestInput"},
|
||||||
|
{"widget": "number", "label": "Ослабление, дБ", "name": "txAttenuation", "min": 0, "step": 1}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{ "widget": "h3", "label": "Настройки приемника" },
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим управления усилением", "name": "rxAgcEn",
|
||||||
|
"values": [
|
||||||
|
{"label": "АРУ", "value": "true"},
|
||||||
|
{"label": "РРУ", "value": "false"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{"widget": "number", "label": "Ручное усиление, дБ", "name": "rxManualGain", "v_show": "!paramRxtx.rxAgcEn", "min": -40},
|
||||||
|
{"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"},
|
||||||
|
{"widget": "number", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 900000, "step": 0.01},
|
||||||
|
{"widget": "number", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 0, "step": 1},
|
||||||
|
{
|
||||||
|
"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"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buclnb": [
|
||||||
|
{"widget": "h2", "label": "Настройки питания и опорного генератора"},
|
||||||
|
{
|
||||||
|
"widget": "flex-container",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки BUC"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц", "name": "bucRefClk10M"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Питание BUC", "name": "bucPowering",
|
||||||
|
"values": [
|
||||||
|
{"label": "Выкл", "value": "0"},
|
||||||
|
{"label": "24В", "value": "24"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки LNB"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц", "name": "lnbRefClk10M"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Питание LNB", "name": "lnbPowering",
|
||||||
|
"values": [
|
||||||
|
{"label": "Выкл", "value": "0"},
|
||||||
|
{"label": "13В", "value": "13"},
|
||||||
|
{"label": "18В", "value": "18"},
|
||||||
|
{"label": "24В", "value": "24"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Сервисные настройки"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц на 'Выход 10МГц'", "name": "srvRefClk10M"},
|
||||||
|
{"widget": "checkbox", "label": "Автозапуск BUC и LNB при включении", "name": "bucLnbAutoStart"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"network": [
|
||||||
|
{"widget": "h2", "label": "Настройки сети"},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки интерфейса управления"},
|
||||||
|
{"widget": "ip-address", "label": "Интерфейс управления (/24)", "name": "netManagementIp"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим сети", "name": "netIsL2",
|
||||||
|
"values": [{"label": "Маршрутизатор", "value": "false"}, {"label": "Коммутатор", "value": "true"}]
|
||||||
|
},
|
||||||
|
{"widget": "ip-address", "label": "Интерфейс данных (/24)", "name": "netDataIp", "v_show": "paramNetwork.netIsL2 === false"},
|
||||||
|
{"widget": "number", "label": "MTU интерфейса данных", "name": "netDataMtu", "min": 1500, "step": 1, "max": 2000}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"tabs": [
|
"tabs": [
|
||||||
{
|
{"name": "monitoring", "desc": "Мониторинг"},
|
||||||
"name": "monitoring",
|
{"name": "setup", "desc": "Настройки"},
|
||||||
"desc": "Мониторинг"
|
{"name": "admin", "desc": "Администрирование"}
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "setup",
|
|
||||||
"desc": "Настройки",
|
|
||||||
"widgets": [
|
|
||||||
{"group": "html", "name": "h3", "payload": "Настройки передатчика"},
|
|
||||||
{"group": "rxtx", "name": "rx.en"},
|
|
||||||
{"group": "rxtx", "name": "rx.isTestInputData"},
|
|
||||||
{"group": "html", "name": "h3", "payload": "Параметры передачи"},
|
|
||||||
{"group": "rxtx", "name": "rx.freqKhz"}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "admin",
|
|
||||||
"desc": "Администрирование"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"scpc": {
|
"scpc": {
|
||||||
"modem_name": "RCSM-101",
|
"modem_name": "RCSM-101",
|
||||||
"groupsList": ["rxtx"],
|
"dangerousParamGroups": {
|
||||||
|
"buclnb": "Применение неправильных настроек может вывести из строя оборудование! Продолжить?",
|
||||||
|
"network": "Применение этих настроек может сделать модем недоступным! Продолжить?"
|
||||||
|
},
|
||||||
|
"params": {
|
||||||
|
"rxtx": [
|
||||||
|
{"widget": "h2", "label": "Настройки приема/передачи"},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим работы", "name": "isCinC",
|
||||||
|
"values": [{"label": "SCPC", "value": "false"}, {"label": "CinC", "value": "true"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "flex-container",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки передатчика"},
|
||||||
|
{"widget": "checkbox", "label": "Включить передатчик", "name": "txEn"},
|
||||||
|
{"widget": "checkbox", "label": "Автоматический запуск передатчика", "name": "txAutoStart"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим работы модулятора", "name": "txModulatorIsTest",
|
||||||
|
"values": [{"label": "Нормальный", "value": "false"}, {"label": "Тест (CW)", "value": "true"}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Входные данные", "name": "txIsTestInput",
|
||||||
|
"values": [{"label": "SCPC", "value": "false"}, {"label": "Тест", "value": "true"}]
|
||||||
|
},
|
||||||
|
{"widget": "h3", "label": "Параметры передачи"},
|
||||||
|
{"widget": "number", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 900000, "step": 0.01},
|
||||||
|
{"widget": "number", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 0, "step": 1},
|
||||||
|
{
|
||||||
|
"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"}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Номер последовательности Голда", "name": "txGoldan",
|
||||||
|
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
|
||||||
|
},
|
||||||
|
{"widget": "number", "label": "Ослабление, дБ", "name": "txAttenuation", "min": 0, "step": 1}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Режим работы DVB-S2"},
|
||||||
|
{"widget": "number", "label": "Период служебных пакетов, сек", "name": "dvbServicePacketPeriod", "min": 0, "step": 1, "max": 60},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим модуляции", "name": "dvbIsAcm",
|
||||||
|
"values": [{"label": "CCM", "value": "false"}, {"label": "ACM", "value": "true"}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Размер кадра", "name": "txFrameSizeNormal",
|
||||||
|
"values": [{"label": "normal", "value": "true"}, {"label": "short", "value": "false"}]
|
||||||
|
},
|
||||||
|
{"widget": "modulation-modcod", "label": "Модуляция", "name": "dvbCcm", "v_show": "paramRxtx.dvbIsAcm === false"},
|
||||||
|
{"widget": "modulation-speed", "label": "Скорость кода", "name": "dvbCcm", "v_show": "paramRxtx.dvbIsAcm === false"},
|
||||||
|
{"widget": "watch", "label": "Текущий модкод", "model": "statRx.modcod", "v_show": "paramRxtx.dvbIsAcm === true"},
|
||||||
|
{"widget": "modulation-modcod", "label": "Модуляция (мин. режим)", "name": "dvbAcmMin", "v_show": "paramRxtx.dvbIsAcm === true"},
|
||||||
|
{"widget": "modulation-speed", "label": "Скорость кода (мин. режим)", "name": "dvbAcmMin", "v_show": "paramRxtx.dvbIsAcm === true"},
|
||||||
|
{"widget": "modulation-modcod", "label": "Модуляция (макс. режим)", "name": "dvbAcmMax", "v_show": "paramRxtx.dvbIsAcm === true"},
|
||||||
|
{"widget": "modulation-speed", "label": "Скорость кода (макс. режим)", "name": "dvbAcmMax", "v_show": "paramRxtx.dvbIsAcm === true"},
|
||||||
|
{"widget": "number", "label": "Запас ОСШ, дБ", "name": "dvbSnrReserve", "min": 0, "step": 0.01, "max": 10}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Авто-регулировка мощности"},
|
||||||
|
{"widget": "checkbox", "label": "Авто-регулировка мощности", "name": "aupcEn"},
|
||||||
|
{"widget": "number", "label": "Минимальное ослабление, дБ", "name": "aupcMinAttenuation", "min": 0, "step": 0.01, "max": 10},
|
||||||
|
{"widget": "number", "label": "Максимальное ослабление, дБ", "name": "aupcMaxAttenuation", "min": 0, "step": 0.01, "max": 10},
|
||||||
|
{"widget": "number", "label": "Требуемое ОСШ", "name": "aupcRequiredSnr", "min": 0, "step": 0.01, "max": 10}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки приемника"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим управления усилением", "name": "rxAgcEn",
|
||||||
|
"values": [{"label": "РРУ", "value": "false"}, {"label": "АРУ", "value": "true"}]
|
||||||
|
},
|
||||||
|
{"widget": "number", "label": "Усиление, дБ", "name": "rxManualGain", "min": -40, "step": 0.01, "max": 40, "v_show": "paramRxtx.rxAgcEn === false"},
|
||||||
|
{"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"},
|
||||||
|
{"widget": "number", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 900000, "step": 0.01},
|
||||||
|
{"widget": "number", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 0, "step": 1},
|
||||||
|
{
|
||||||
|
"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"}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Номер последовательности Голда", "name": "rxGoldan",
|
||||||
|
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"cinc": [
|
||||||
|
{"widget": "h2", "label": "Настройки режима CinC", "v_show": "paramRxtx.isCinC"},
|
||||||
|
{
|
||||||
|
"widget": "settings-container", "v_show": "paramRxtx.isCinC",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Метод расчета задержки", "name": "cincIsPositional",
|
||||||
|
"values": [
|
||||||
|
{"label": "Позиционированием", "value": "true"},
|
||||||
|
{"label": "Окном задержки", "value": "false"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{"widget": "number", "label": "Полоса поиска, КГц ±", "name": "cincSearchBandwidth", "min": 0, "step": 1, "max": 100},
|
||||||
|
{"widget": "h2", "label": "Настройки позиционирования", "v_show": "paramCinc.cincIsPositional === true"},
|
||||||
|
{"widget": "number", "label": "Широта станции", "name": "cincPositionStationLatitude", "v_show": "paramCinc.cincIsPositional === true", "min": -180, "step": 0.000001, "max": 180},
|
||||||
|
{"widget": "number", "label": "Долгота станции", "name": "cincPositionStationLongitude", "v_show": "paramCinc.cincIsPositional === true", "min": -180, "step": 0.000001, "max": 180},
|
||||||
|
{"widget": "number", "label": "Подспутниковая точка", "name": "cincPositionSatelliteLongitude", "v_show": "paramCinc.cincIsPositional === true", "min": -180, "step": 0.000001, "max": 180},
|
||||||
|
{"widget": "h2", "label": "Задержка до спутника", "v_show": "paramCinc.cincIsPositional === false"},
|
||||||
|
{"widget": "number", "label": "от, мс", "name": "cincDelayMin", "v_show": "paramCinc.cincIsPositional === false", "min": 0, "step": 0.1, "max": 400},
|
||||||
|
{"widget": "number", "label": "до, мс", "name": "cincDelayMax", "v_show": "paramCinc.cincIsPositional === false", "min": 0, "step": 0.1, "max": 400}]
|
||||||
|
},
|
||||||
|
{"widget": "submit", "v_show": "paramRxtx.isCinC"}
|
||||||
|
],
|
||||||
|
"buclnb": [
|
||||||
|
{"widget": "h2", "label": "Настройки питания и опорного генератора"},
|
||||||
|
{
|
||||||
|
"widget": "flex-container",
|
||||||
|
"childs": [
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки BUC"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц", "name": "bucRefClk10M"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Питание BUC", "name": "bucPowering",
|
||||||
|
"values": [
|
||||||
|
{"label": "Выкл", "value": "0"},
|
||||||
|
{"label": "24В", "value": "24"},
|
||||||
|
{"label": "48В", "value": "48"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки LNB"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц", "name": "lnbRefClk10M"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Питание LNB", "name": "lnbPowering",
|
||||||
|
"values": [
|
||||||
|
{"label": "Выкл", "value": "0"},
|
||||||
|
{"label": "13В", "value": "13"},
|
||||||
|
{"label": "18В", "value": "18"},
|
||||||
|
{"label": "24В", "value": "24"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Сервисные настройки"},
|
||||||
|
{"widget": "checkbox", "label": "Подача опоры 10МГц на 'Выход 10МГц'", "name": "srvRefClk10M"},
|
||||||
|
{"widget": "checkbox", "label": "Автозапуск BUC и LNB при включении", "name": "bucLnbAutoStart"}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"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": [
|
||||||
|
{"widget": "h2", "label": "Настройки сети"},
|
||||||
|
{
|
||||||
|
"widget": "settings-container",
|
||||||
|
"childs": [
|
||||||
|
{"widget": "h3", "label": "Настройки интерфейса управления"},
|
||||||
|
{"widget": "ip-address", "label": "Интерфейс управления (/24)", "name": "netManagementIp"},
|
||||||
|
{
|
||||||
|
"widget": "select", "label": "Режим сети", "name": "netIsL2",
|
||||||
|
"values": [{"label": "Маршрутизатор", "value": "false"}, {"label": "Коммутатор", "value": "true"}]
|
||||||
|
},
|
||||||
|
{"widget": "ip-address", "label": "Интерфейс данных (/24)", "name": "netDataIp", "v_show": "paramNetwork.netIsL2 === false"},
|
||||||
|
{"widget": "number", "label": "MTU интерфейса данных", "name": "netDataMtu", "min": 1500, "step": 1, "max": 2000}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
"tabs": [
|
"tabs": [
|
||||||
{
|
{"name": "monitoring", "desc": "Мониторинг"},
|
||||||
"name": "monitoring",
|
{"name": "setup", "desc": "Настройки"},
|
||||||
"desc": "Мониторинг"
|
{"name": "qos", "desc": "QoS"},
|
||||||
},
|
{"name": "admin", "desc": "Администрирование"}
|
||||||
{
|
|
||||||
"name": "setup",
|
|
||||||
"desc": "Настройки"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "qos",
|
|
||||||
"desc": "QoS"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "admin",
|
|
||||||
"desc": "Администрирование"
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,90 @@
|
|||||||
import json
|
import json
|
||||||
|
|
||||||
from jinja2 import Environment, FileSystemLoader
|
from jinja2 import Environment, FileSystemLoader
|
||||||
import sys
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
|
with open('render-params.json') as f:
|
||||||
|
GLOBAL_CONFIG = json.load(f)
|
||||||
|
|
||||||
|
|
||||||
|
def extract_param_names(mc):
|
||||||
|
result = []
|
||||||
|
|
||||||
|
def helper_extract(widget):
|
||||||
|
if 'childs' in widget:
|
||||||
|
r = []
|
||||||
|
for child in widget['childs']:
|
||||||
|
r += helper_extract(child)
|
||||||
|
return r
|
||||||
|
elif 'name' in widget:
|
||||||
|
match widget['widget']:
|
||||||
|
case 'select': return [{"name": widget['name'], "initValue": widget['values'][0]['value']}]
|
||||||
|
case 'checkbox': return [{"name": widget['name'], "initValue": 'false'}]
|
||||||
|
case 'number': return [{"name": widget['name'], "initValue": widget['min'] if widget['min'] else '0'}]
|
||||||
|
case 'modulation-modcod': return [{"name": widget['name'] + "Modulation", "initValue": '"QPSK"'}]
|
||||||
|
case 'modulation-speed': return [{"name": widget['name'] + "Speed", "initValue": '"1/4"'}]
|
||||||
|
case 'watch': return []
|
||||||
|
|
||||||
|
return [{"name": widget['name'], "initValue": 'null'}]
|
||||||
|
return []
|
||||||
|
|
||||||
|
for cat in mc['params']:
|
||||||
|
ws = []
|
||||||
|
for w in mc['params'][cat]:
|
||||||
|
ws += helper_extract(w)
|
||||||
|
# ws.sort(key=lambda k: k['name'])
|
||||||
|
result.append({
|
||||||
|
"group": cat,
|
||||||
|
"params": ws
|
||||||
|
})
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def add_submit_widgets(params):
|
||||||
|
def find_submit(w):
|
||||||
|
if w['widget'] == 'submit':
|
||||||
|
return True
|
||||||
|
if 'childs' in w:
|
||||||
|
for c in w['childs']:
|
||||||
|
if find_submit(c):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
for group in params:
|
||||||
|
wid_found = False
|
||||||
|
for wid in params[group]:
|
||||||
|
if find_submit(wid):
|
||||||
|
wid_found = True
|
||||||
|
break
|
||||||
|
if wid_found:
|
||||||
|
continue
|
||||||
|
|
||||||
|
params[group].append({"widget": "submit"})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def extract_param_groups(mc):
|
||||||
|
return [k for k in mc['params']]
|
||||||
|
|
||||||
|
|
||||||
def build_modem_env(modem):
|
def build_modem_env(modem):
|
||||||
with open('render-params.json') as f:
|
if modem not in GLOBAL_CONFIG['modem_types']:
|
||||||
config = json.load(f)
|
|
||||||
if modem not in config['modem_types']:
|
|
||||||
raise RuntimeError(f"Modem '{modem}' is not exist in config!")
|
raise RuntimeError(f"Modem '{modem}' is not exist in config!")
|
||||||
|
|
||||||
mc = config['modem_types'][modem]
|
mc = GLOBAL_CONFIG['modem_types'][modem]
|
||||||
|
|
||||||
|
add_submit_widgets(mc['params'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
"modem": modem,
|
||||||
"modem_name": mc['modem_name'],
|
"modem_name": mc['modem_name'],
|
||||||
"header_tabs": mc['tabs'],
|
"header_tabs": mc['tabs'],
|
||||||
"js_tabs_array": str([t['name'] for t in mc['tabs']]),
|
"tab_names_array": [t['name'] for t in mc['tabs']],
|
||||||
"params": {"groupsList": mc["groupsList"]} | config["params"]
|
"params": mc["params"],
|
||||||
|
"dangerousParamGroups": mc["dangerousParamGroups"] if 'dangerousParamGroups' in mc else {},
|
||||||
|
"paramGroups": extract_param_names(mc),
|
||||||
|
"paramGroupsList": extract_param_groups(mc),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -32,8 +100,8 @@ def render_modem(modem):
|
|||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
if len(sys.argv) != 2:
|
for mt in GLOBAL_CONFIG['modem_types']:
|
||||||
print(f"Usage: {sys.argv[0]} <scpc|tdma>")
|
print(f'Generating {mt} modem...')
|
||||||
|
render_modem(mt)
|
||||||
render_modem(sys.argv[1])
|
os.system(f'cp -u main-{mt}.html ../static')
|
||||||
|
|
||||||
|
62
front-generator/template/common/admin-methods.js.j2
Normal file
62
front-generator/template/common/admin-methods.js.j2
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
async settingsUploadUpdate() {
|
||||||
|
if (!this.uploadFw.filename) {
|
||||||
|
alert('Выберите файл для загрузки');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readFileAsArrayBuffer(fileName) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (!fileName) { reject(`Файл не выбран`); return }
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => { resolve(reader.result) }
|
||||||
|
reader.onerror = (e) => { reject(e) }
|
||||||
|
reader.readAsArrayBuffer(fileName)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.submitStatus.firmwareUpload = true
|
||||||
|
this.uploadFw.progress = 0
|
||||||
|
const blob = await readFileAsArrayBuffer(this.uploadFw.filename)
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
xhr.upload.addEventListener("progress", (event) => {
|
||||||
|
if (event.lengthComputable) {
|
||||||
|
this.uploadFw.progress = Math.round((event.loaded / event.total) * 1000) / 10;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
xhr.addEventListener("loadend", () => {
|
||||||
|
this.uploadFw.progress = 100
|
||||||
|
const rep = JSON.parse(xhr.responseText);
|
||||||
|
this.uploadFw.sha256 = rep['sha256']
|
||||||
|
resolve(xhr.readyState === 4 && xhr.status === 200);
|
||||||
|
});
|
||||||
|
xhr.open("PUT", "/api/firmwareUpdate", true);
|
||||||
|
xhr.setRequestHeader("Content-Type", "application/octet-stream");
|
||||||
|
xhr.send(blob);
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
alert(`Ошибка загрузки файла: ${e}`);
|
||||||
|
}
|
||||||
|
this.submitStatus.firmwareUpload = false
|
||||||
|
},
|
||||||
|
|
||||||
|
async settingsPerformFirmwareUpgrade() {
|
||||||
|
if (this.submitStatus.firmwareUpgrade) { return }
|
||||||
|
this.submitStatus.firmwareUpgrade = true
|
||||||
|
try {
|
||||||
|
await fetch('/api/doFirmwareUpgrade', { method: 'POST' })
|
||||||
|
} catch (e) {
|
||||||
|
console.log("failed to perform upgrade firmware: ", e)
|
||||||
|
}
|
||||||
|
this.submitStatus.firmwareUpgrade = false
|
||||||
|
},
|
||||||
|
|
||||||
|
doModemReboot() {
|
||||||
|
if (this.submitStatus.modemReboot !== null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.submitStatus.modemReboot = 30
|
||||||
|
fetch('/api/reboot', { method: 'POST' }).then((r) => {})
|
||||||
|
},
|
34
front-generator/template/common/admin.html.j2
Normal file
34
front-generator/template/common/admin.html.j2
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{% from 'common/widgets.j2' import build_widget %}
|
||||||
|
<div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete">
|
||||||
|
{% if 'network' in params %}
|
||||||
|
{% for w in params['network'] %}{{ build_widget('network', w) | indent(12, true) }}{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% raw %}
|
||||||
|
<h2>Система</h2>
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Версия ПО</th><td>{{ about.firmwareVersion }}</td></tr>
|
||||||
|
<tr><th>ID модема</th><td>{{ about.modemUid }}</td></tr>
|
||||||
|
<tr><th>Серийный номер</th><td>{{ about.modemSn }}</td></tr>
|
||||||
|
<tr><th>MAC интерфейса управления</th><td>{{ about.macManagement }}</td></tr>
|
||||||
|
<tr><th>MAC интерфейса управления</th><td>{{ about.macData }}</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<div>
|
||||||
|
<button class="dangerous-button" @click="doModemReboot()">Перезагрузить модем <span class="submit-spinner" v-show="submitStatus.modemReboot !== null"></span></button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Обновление ПО</h3>
|
||||||
|
<label>
|
||||||
|
<span>Файл {{ this.uploadFw.progress !== null ? `(${this.uploadFw.progress}%)` : '' }}</span>
|
||||||
|
<input type="file" accept="application/zip" @change="(e) => { this.uploadFw.filename = e.target.files[0] }">
|
||||||
|
<span v-if="uploadFw.sha256 !== null">SHA256: {{ uploadFw.sha256 }}</span>
|
||||||
|
</label>
|
||||||
|
<button class="action-button" @click="settingsUploadUpdate()">Загрузить<span class="submit-spinner" v-show="submitStatus.firmwareUpload"></span></button>
|
||||||
|
<button class="dangerous-button" v-show="uploadFw.sha256 !== null" @click="settingsPerformFirmwareUpgrade()">Обновить встроенное ПО <span class="submit-spinner" v-show="submitStatus.firmwareUpgrade"></span></button>
|
||||||
|
</div>{% endraw %}
|
||||||
|
</div>
|
7
front-generator/template/common/all-params-data.js.j2
Normal file
7
front-generator/template/common/all-params-data.js.j2
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{% for g in paramGroups %}
|
||||||
|
param{{ g['group'] | title }}: {
|
||||||
|
{% for p in g['params'] %}
|
||||||
|
{{ p['name'] }}: {{ p['initValue'] }},
|
||||||
|
{% endfor %}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
29
front-generator/template/common/all-params-methods.js.j2
Normal file
29
front-generator/template/common/all-params-methods.js.j2
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
{% for g in paramGroups %}
|
||||||
|
settingsSubmit{{ g['group'] | title }}() {
|
||||||
|
if (this.submitStatus.{{ g['group'] }}) { return }
|
||||||
|
{% if g['group'] in dangerousParamGroups %}
|
||||||
|
{ if (!confirm("{{ dangerousParamGroups[g['group']] }}")) return }
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
let query = {
|
||||||
|
{% for p in g['params'] %}
|
||||||
|
"{{ p['name'] }}": this.param{{ g['group'] | title }}.{{ p['name'] }},
|
||||||
|
{% endfor %}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.submitStatus.{{ g['group'] }} = true
|
||||||
|
fetch('/api/set/{{ g["group"] }}', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query) })
|
||||||
|
.then(async (resp) => { this.update{{ g['group'] | title }}Settings(await resp.json()) })
|
||||||
|
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
|
||||||
|
.finally(() => { this.submitStatus.{{ g['group'] }} = false })
|
||||||
|
},
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
{% for g in paramGroups %}
|
||||||
|
update{{ g['group'] | title }}Settings(vals) {
|
||||||
|
this.submitStatus.{{ g['group'] }} = false
|
||||||
|
{% for p in g['params'] %}
|
||||||
|
this.param{{ g['group'] | title }}.{{ p['name'] }} = vals["settings"]["{{ p['name'] }}"]
|
||||||
|
{% endfor %}
|
||||||
|
},
|
||||||
|
{% endfor %}
|
47
front-generator/template/common/monitoring-data.js.j2
Normal file
47
front-generator/template/common/monitoring-data.js.j2
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
statRx: {
|
||||||
|
// индикаторы
|
||||||
|
state: '?', // общее состояние
|
||||||
|
sym_sync_lock: '?', // захват символьной
|
||||||
|
freq_search_lock: '?', // Захват поиска по частоте
|
||||||
|
afc_lock: '?', // захват ФАПЧ
|
||||||
|
pkt_sync: '?', // захват пакетной синхронизации
|
||||||
|
|
||||||
|
// куча других параметров, идет в том же порядке, что и в таблице
|
||||||
|
snr: '?', rssi: '?',
|
||||||
|
modcod: '?', frameSizeNormal: '?',
|
||||||
|
isPilots: '?',
|
||||||
|
symError: '?',
|
||||||
|
freqErr: '?', freqErrAcc: '?',
|
||||||
|
inputSignalLevel: '?',
|
||||||
|
pllError: '?',
|
||||||
|
speedOnRxKbit: '?',
|
||||||
|
speedOnIifKbit: '?',
|
||||||
|
|
||||||
|
// статистика пакетов
|
||||||
|
packetsOk: '?', packetsBad: '?', packetsDummy: '?',
|
||||||
|
},
|
||||||
|
statTx: {
|
||||||
|
// состояние
|
||||||
|
state: '?',
|
||||||
|
|
||||||
|
// прочие поля
|
||||||
|
{% if modem == 'scpc' %}
|
||||||
|
snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?',
|
||||||
|
{% else %}
|
||||||
|
modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?',
|
||||||
|
{% endif %}
|
||||||
|
},
|
||||||
|
{% if modem == 'scpc' %}
|
||||||
|
statCinc: {
|
||||||
|
occ: '?',
|
||||||
|
correlator: null,
|
||||||
|
correlatorFails: '?',
|
||||||
|
freqErr: '?', freqErrAcc: '?',
|
||||||
|
channelDelay: '?'
|
||||||
|
},
|
||||||
|
{% endif %}
|
||||||
|
statDevice: { // температурные датчики
|
||||||
|
adrv: 0, zynq: 0, fpga: 0
|
||||||
|
},
|
||||||
|
statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'},
|
||||||
|
|
102
front-generator/template/common/monitoring-methods.js.j2
Normal file
102
front-generator/template/common/monitoring-methods.js.j2
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
updateStatistics(vals) {
|
||||||
|
function modcodToStr(modcod) {
|
||||||
|
// модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf
|
||||||
|
const modcods = [
|
||||||
|
"DUMMY",
|
||||||
|
"QPSK 1/4", "QPSK 1/3", "QPSK 2/5", "QPSK 1/2", "QPSK 3/5", "QPSK 2/3", "QPSK 3/4", "QPSK 4/5", "QPSK 5/6", "QPSK 8/9", "QPSK 9/10",
|
||||||
|
"8PSK 3/5", "8PSK 2/3", "8PSK 3/4", "8PSK 5/6", "8PSK 8/9", "8PSK 9/10",
|
||||||
|
"16APSK 2/3", "16APSK 3/4", "16APSK 4/5", "16APSK 5/6", "16APSK 8/9", "16APSK 9/10",
|
||||||
|
"32APSK 3/4", "32APSK 4/5", "32APSK 5/6", "32APSK 8/9", "32APSK 9/10",
|
||||||
|
]
|
||||||
|
if (typeof modcod != "number" || modcod < 0 || modcod >= modcod.length) {
|
||||||
|
return "?";
|
||||||
|
}
|
||||||
|
return modcods[modcod]
|
||||||
|
}
|
||||||
|
|
||||||
|
this.lastUpdateTime = new Date();
|
||||||
|
this.initState = vals["mainState"]["initState"]
|
||||||
|
{% if modem == 'scpc' %}
|
||||||
|
this.isCinC = vals["mainState"]["isCinC"]
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
this.statRx.state = vals["mainState"]["rx.state"]
|
||||||
|
this.statRx.sym_sync_lock = vals["mainState"]["rx.sym_sync_lock"]
|
||||||
|
this.statRx.freq_search_lock = vals["mainState"]["rx.freq_search_lock"]
|
||||||
|
this.statRx.afc_lock = vals["mainState"]["rx.afc_lock"]
|
||||||
|
this.statRx.pkt_sync = vals["mainState"]["rx.pkt_sync"]
|
||||||
|
this.statRx.snr = vals["mainState"]["rx.snr"]
|
||||||
|
this.statRx.rssi = vals["mainState"]["rx.rssi"]
|
||||||
|
this.statRx.modcod = modcodToStr(vals["mainState"]["rx.modcod"])
|
||||||
|
this.statRx.frameSizeNormal = vals["mainState"]["rx.frameSizeNormal"]
|
||||||
|
this.statRx.isPilots = vals["mainState"]["rx.isPilots"]
|
||||||
|
this.statRx.symError = vals["mainState"]["rx.symError"]
|
||||||
|
this.statRx.freqErr = vals["mainState"]["rx.freqErr"]
|
||||||
|
this.statRx.freqErrAcc = vals["mainState"]["rx.freqErrAcc"]
|
||||||
|
this.statRx.inputSignalLevel = vals["mainState"]["rx.inputSignalLevel"]
|
||||||
|
this.statRx.pllError = vals["mainState"]["rx.pllError"]
|
||||||
|
this.statRx.speedOnRxKbit = vals["mainState"]["rx.speedOnRxKbit"]
|
||||||
|
this.statRx.speedOnIifKbit = vals["mainState"]["rx.speedOnIifKbit"]
|
||||||
|
this.statRx.packetsOk = vals["mainState"]["rx.packetsOk"]
|
||||||
|
this.statRx.packetsBad = vals["mainState"]["rx.packetsBad"]
|
||||||
|
this.statRx.packetsDummy = vals["mainState"]["rx.packetsDummy"]
|
||||||
|
|
||||||
|
{% if modem == 'scpc' %}
|
||||||
|
this.statTx.state = vals["mainState"]["tx.state"]
|
||||||
|
this.statTx.snr = vals["mainState"]["tx.snr"]
|
||||||
|
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"])
|
||||||
|
this.statTx.frameSizeNormal = vals["mainState"]["tx.frameSizeNormal"]
|
||||||
|
this.statTx.isPilots = vals["mainState"]["tx.isPilots"]
|
||||||
|
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"]
|
||||||
|
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"]
|
||||||
|
|
||||||
|
this.statCinc.occ = vals["mainState"]["cinc.occ"]
|
||||||
|
this.statCinc.correlator = vals["mainState"]["cinc.correlator"]
|
||||||
|
this.statCinc.correlatorFails = vals["mainState"]["cinc.correlatorFails"]
|
||||||
|
this.statCinc.freqErr = vals["mainState"]["cinc.freqErr"]
|
||||||
|
this.statCinc.freqErrAcc = vals["mainState"]["cinc.freqErrAcc"]
|
||||||
|
this.statCinc.channelDelay = vals["mainState"]["cinc.channelDelay"]
|
||||||
|
{% else %}
|
||||||
|
this.statTx.state = vals["mainState"]["tx.state"]
|
||||||
|
this.statTx.modcod = modcodToStr(vals["mainState"]["tx.modcod"])
|
||||||
|
this.statTx.speedOnTxKbit = vals["mainState"]["tx.speedOnTxKbit"]
|
||||||
|
this.statTx.speedOnIifKbit = vals["mainState"]["tx.speedOnIifKbit"]
|
||||||
|
this.statTx.centerFreq = vals["mainState"]["tx.centerFreq"]
|
||||||
|
this.statTx.symSpeed = vals["mainState"]["tx.symSpeed"]
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
this.statDevice.adrv = vals["mainState"]["device.adrv"]
|
||||||
|
this.statDevice.zynq = vals["mainState"]["device.zynq"]
|
||||||
|
this.statDevice.fpga = vals["mainState"]["device.fpga"]
|
||||||
|
|
||||||
|
this.testState = vals["mainState"]["testState"]
|
||||||
|
|
||||||
|
// аптайм приходит в секундах, надо преобразовать его в человеко-читаемый вид
|
||||||
|
let uptime = vals["sysinfo"]["uptime"]
|
||||||
|
if (uptime) {
|
||||||
|
let secs = uptime % 60; uptime = Math.floor(uptime / 60)
|
||||||
|
let mins = uptime % 60; uptime = Math.floor(uptime / 60)
|
||||||
|
let hours = uptime % 24
|
||||||
|
uptime = Math.floor( uptime / 24)
|
||||||
|
let res = `${hours}:${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
|
||||||
|
if (uptime > 0) { res = `${uptime} days, ` + res }
|
||||||
|
this.statOs.uptime = res
|
||||||
|
} else {
|
||||||
|
this.statOs.uptime = '?'
|
||||||
|
}
|
||||||
|
this.statOs.load1 = vals["sysinfo"]["load1min"]
|
||||||
|
this.statOs.load5 = vals["sysinfo"]["load5min"]
|
||||||
|
this.statOs.load15 = vals["sysinfo"]["load15min"]
|
||||||
|
this.statOs.totalram = vals["sysinfo"]["totalram"]
|
||||||
|
this.statOs.freeram = vals["sysinfo"]["freeram"]
|
||||||
|
},
|
||||||
|
|
||||||
|
resetPacketsStatistics() {
|
||||||
|
fetch('/api/resetPacketStatistics', {
|
||||||
|
method: 'POST'
|
||||||
|
}).then(() => {
|
||||||
|
this.statRx.packetsOk = 0
|
||||||
|
this.statRx.packetsBad = 0
|
||||||
|
this.statRx.packetsDummy = 0
|
||||||
|
})
|
||||||
|
},
|
84
front-generator/template/common/monitoring.html.j2
Normal file
84
front-generator/template/common/monitoring.html.j2
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
{% raw %}
|
||||||
|
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<h2>Статистика приема</h2>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Прием</th><td><span :class="{ indicator_bad: statRx.state === false, indicator_good: statRx.state === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Захват символьной</th><td><span :class="{ indicator_bad: statRx.sym_sync_lock === false, indicator_good: statRx.sym_sync_lock === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Захват ФАПЧ</th><td><span :class="{ indicator_bad: statRx.afc_lock === false, indicator_good: statRx.afc_lock === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Захват поиска по частоте</th><td><span :class="{ indicator_bad: statRx.freq_search_lock === false, indicator_good: statRx.freq_search_lock === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Захват пакетной синхр.</th><td><span :class="{ indicator_bad: statRx.pkt_sync === false, indicator_good: statRx.pkt_sync === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>SNR/RSSI</th><td>{{ statRx.snr }} / {{ statRx.rssi }}</td></tr>
|
||||||
|
<tr><th>Modcod</th><td>{{ statRx.modcod }}</td></tr>
|
||||||
|
<tr><th>Размер кадра</th><td>{{ statRx.frameSizeNormal ? 'normal' : 'short' }}</td></tr>
|
||||||
|
<tr><th>Пилот-символы</th><td>{{ statRx.isPilots ? 'pilots' : 'no pilots' }}</td></tr>
|
||||||
|
<tr><th>Символьная ошибка</th><td>{{ statRx.symError }}</td></tr>
|
||||||
|
<tr><th>Грубая/точная част. ошибка, Гц</th><td>{{ statRx.freqErr }} / {{ statRx.freqErrAcc }}</td></tr>
|
||||||
|
<tr><th>Ур. входного сигнала</th><td>{{ statRx.inputSignalLevel }}</td></tr>
|
||||||
|
<tr><th>Ошибка ФАПЧ</th><td>{{ statRx.pllError }}</td></tr>
|
||||||
|
<tr><th>Инф. скорость на приеме</th><td>{{ statRx.speedOnRxKbit }} kbit/s</td></tr>
|
||||||
|
<tr><th>Инф. скорость на интерфейсе</th><td>{{ statRx.speedOnIifKbit }} kbit/s</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p> Статистика пакетов </p>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Качественных пакетов</th><td>{{ statRx.packetsOk }}</td></tr>
|
||||||
|
<tr><th>Поврежденных пакетов</th><td>{{ statRx.packetsBad }}</td></tr>
|
||||||
|
<tr><th>DUMMY</th><td>{{ statRx.packetsDummy }}</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<button class="action-button" @click="resetPacketsStatistics()"> Сброс статистики </button>
|
||||||
|
</div>
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<h2>Статистика передачи</h2>{% endraw %}{% if modem == 'scpc' %}{% raw %}
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Передача</th><td><span :class="{ indicator_bad: statTx.state === false, indicator_good: statTx.state === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>ОСШ дальнего приема</th><td>{{ statTx.snr }}</td></tr>
|
||||||
|
<tr><th>Modcod</th><td>{{ statTx.modcod }}</td></tr>
|
||||||
|
<tr><th>Размер кадра</th><td>{{ statTx.frameSizeNormal ? 'normal' : 'short' }}</td></tr>
|
||||||
|
<tr><th>Пилот-символы</th><td>{{ statTx.isPilots ? 'pilots' : 'no pilots' }}</td></tr>
|
||||||
|
<tr><th>Инф. скорость на передаче</th><td>{{ statTx.speedOnTxKbit }} kbit/s</td></tr>
|
||||||
|
<tr><th>Инф. скорость на интерфейсе</th><td>{{ statTx.speedOnIifKbit }} kbit/s</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>{% endraw %}{% else %}{% raw %}
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Передача</th><td><span :class="{ indicator_bad: statTx.state === false, indicator_good: statTx.state === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Modcod</th><td>{{ statTx.modcod }}</td></tr>
|
||||||
|
<tr><th>Инф. скорость на передаче</th><td>{{ statTx.speedOnTxKbit }} kbit/s</td></tr>
|
||||||
|
<tr><th>Инф. скорость на интерфейсе</th><td>{{ statTx.speedOnIifKbit }} kbit/s</td></tr>
|
||||||
|
<tr><th>Центральная частота</th><td>{{ statTx.centerFreq }} kHz</td></tr>
|
||||||
|
<tr><th>Символьная скорость</th><td>{{ statTx.symSpeed }} ksymb</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>{% endraw %}{% endif %}{% raw %}
|
||||||
|
</div>{% endraw %}{% if modem == 'scpc' %}{% raw %}
|
||||||
|
<div class="settings-set-container" v-if="paramRxtx.isCinC === true">
|
||||||
|
<h2>Статистика режима CinC</h2>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>ОСС</th><td>{{ statCinc.occ }}</td></tr>
|
||||||
|
<tr><th>Захват коррелятора</th><td><span :class="{ indicator_bad: statCinc.correlator === false, indicator_good: statCinc.correlator === true, indicator: true }"></span></td></tr>
|
||||||
|
<tr><th>Кол-во срывов коррелятора</th><td>{{ statCinc.correlatorFails }}</td></tr>
|
||||||
|
<tr><th>Грубая/точная част. ошибка, Гц</th><td>{{ statCinc.freqErr }} / {{ statCinc.freqErrAcc }}</td></tr>
|
||||||
|
<tr><th>Задержка в канале, мс</th><td>{{ statCinc.channelDelay }}</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>{% endraw %}{% endif %}{% raw %}
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<h2>Состояние устройства</h2>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr><th>Температура ADRV</th><td>{{ statDevice.adrv }} °C</td></tr>
|
||||||
|
<tr><th>Температура ZYNQ</th><td>{{ statDevice.zynq }} °C</td></tr>
|
||||||
|
<tr><th>Температура FPGA</th><td>{{ statDevice.fpga }} °C</td></tr>
|
||||||
|
<tr><th>Uptime</th><td>{{ statOs.uptime }}</td></tr>
|
||||||
|
<tr><th>Load average</th><td>{{ statOs.load1 }} {{ statOs.load5 }} {{ statOs.load15 }}</td></tr>
|
||||||
|
<tr><th>RAM total/free</th><td>{{ statOs.totalram }}Mb/{{ statOs.freeram }}Mb</td></tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endraw %}
|
8
front-generator/template/common/qos-data.js.j2
Normal file
8
front-generator/template/common/qos-data.js.j2
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
submitStatusQos: false,
|
||||||
|
paramQos: {
|
||||||
|
en: false,
|
||||||
|
rt1: [],
|
||||||
|
rt2: [],
|
||||||
|
rt3: [],
|
||||||
|
cd: [],
|
||||||
|
},
|
221
front-generator/template/common/qos-methods.js.j2
Normal file
221
front-generator/template/common/qos-methods.js.j2
Normal file
@ -0,0 +1,221 @@
|
|||||||
|
settingsSubmitQoS() {
|
||||||
|
if (this.submitStatusQos) { return }
|
||||||
|
this.submitStatusQos = true
|
||||||
|
function _translateQosClass(trafficClass, qc) {
|
||||||
|
let res = {
|
||||||
|
cir: qc['cir'],
|
||||||
|
description: qc['description'],
|
||||||
|
filters: []
|
||||||
|
}
|
||||||
|
if (trafficClass === 'cd') {
|
||||||
|
res.pir = qc.pir
|
||||||
|
}
|
||||||
|
if (!qc.isEnabled) {
|
||||||
|
res.disabled = true
|
||||||
|
}
|
||||||
|
for (const fi in qc.filters) {
|
||||||
|
let filter = {}
|
||||||
|
if (qc['filters'][fi].vlan !== "") { filter['vlan'] = qc['filters'][fi].vlan }
|
||||||
|
if (qc['filters'][fi].proto.length > 0) {
|
||||||
|
let tmp = "";
|
||||||
|
for (let pid = 0; pid < qc['filters'][fi].proto.length; pid++) {
|
||||||
|
if (pid !== 0) { tmp += ',' }
|
||||||
|
tmp += qc['filters'][fi].proto[pid]
|
||||||
|
}
|
||||||
|
filter['proto'] = tmp
|
||||||
|
}
|
||||||
|
if (qc['filters'][fi].sport !== "") { filter['sport'] = qc['filters'][fi].sport }
|
||||||
|
if (qc['filters'][fi].dport !== "") { filter['dport'] = qc['filters'][fi].dport }
|
||||||
|
if (qc['filters'][fi].ip_src !== "") { filter['ip_src'] = qc['filters'][fi].ip_src }
|
||||||
|
if (qc['filters'][fi].ip_dest !== "") { filter['ip_dest'] = qc['filters'][fi].ip_dest }
|
||||||
|
if (qc['filters'][fi].dscp !== "") { filter['dscp'] = qc['filters'][fi].dscp }
|
||||||
|
|
||||||
|
if (Object.keys(filter).length === 0) { continue }
|
||||||
|
if (!qc.filters[fi].isEnabled) { filter['disabled'] = true }
|
||||||
|
|
||||||
|
res.filters.push(filter)
|
||||||
|
}
|
||||||
|
if (res.filters.length === 0) {
|
||||||
|
// автоматическое выключение класса, если правил нет
|
||||||
|
res.disabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
let query = {
|
||||||
|
"en": this.paramQos.en,
|
||||||
|
"rt1": [],
|
||||||
|
"rt2": [],
|
||||||
|
"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.rt2.length; i++) { query.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.cd.length; i++) { query.cd.push(_translateQosClass('rt', this.paramQos.cd[i])) }
|
||||||
|
|
||||||
|
//console.log(query)
|
||||||
|
fetch('/api/set/qos', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(query)
|
||||||
|
}).then(async (resp) => {
|
||||||
|
this.submitStatusQos = false
|
||||||
|
this.updateQosSettings(await resp.json())
|
||||||
|
}).catch((reason) => {
|
||||||
|
this.submitStatusQos = false
|
||||||
|
alert(`Ошибка при применении настроек: ${reason}`)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
updateQosSettings(vals) {
|
||||||
|
this.submitStatusQos = false
|
||||||
|
this.paramQos.en = vals["settings"]["qos.enabled"]
|
||||||
|
|
||||||
|
const qosProfile = vals["settings"]["qos.profile"]
|
||||||
|
if (qosProfile !== null && qosProfile !== undefined) {
|
||||||
|
this.paramQos.rt1 = [] // .splice(0, this.paramQos.rt1.length)
|
||||||
|
this.paramQos.rt2 = [] // .splice(0, this.paramQos.rt2.length)
|
||||||
|
this.paramQos.rt3 = [] // .splice(0, this.paramQos.rt3.length)
|
||||||
|
this.paramQos.cd = [] // .splice(0, this.paramQos.cd.length)
|
||||||
|
|
||||||
|
for (let trafficClass in qosProfile) {
|
||||||
|
if (['rt1', 'rt2', 'rt3', 'cd'].indexOf(trafficClass) < 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Array.isArray(qosProfile[trafficClass])) {
|
||||||
|
for (let i = 0; i < qosProfile[trafficClass].length; i++) {
|
||||||
|
const qc = qosProfile[trafficClass][i]
|
||||||
|
let result = {
|
||||||
|
isEnabled: !qc.hasOwnProperty('disabled'),
|
||||||
|
cir: qc['cir'],
|
||||||
|
pir: 0,
|
||||||
|
description: qc['description'],
|
||||||
|
filters: []
|
||||||
|
}
|
||||||
|
if (trafficClass === 'cd') {
|
||||||
|
if (qc['pir']) {
|
||||||
|
result.pir = qc['pir']
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let fi = 0; fi < qc['filters'].length; fi++) {
|
||||||
|
result.filters.push({
|
||||||
|
isEnabled: !qc['filters'][fi].hasOwnProperty('disabled'),
|
||||||
|
vlan: qc['filters'][fi].hasOwnProperty('vlan') ? qc['filters'][fi]['vlan'] : '',
|
||||||
|
proto: qc['filters'][fi].hasOwnProperty('proto') ? qc['filters'][fi]['proto'].split(',') : [],
|
||||||
|
sport: qc['filters'][fi].hasOwnProperty('sport') ? qc['filters'][fi]['sport'] : '',
|
||||||
|
dport: qc['filters'][fi].hasOwnProperty('dport') ? qc['filters'][fi]['dport'] : '',
|
||||||
|
ip_src: qc['filters'][fi].hasOwnProperty('ip_src') ? qc['filters'][fi]['ip_src'] : '',
|
||||||
|
ip_dest: qc['filters'][fi].hasOwnProperty('ip_dest') ? qc['filters'][fi]['ip_dest'] : '',
|
||||||
|
dscp: qc['filters'][fi].hasOwnProperty('dscp') ? qc['filters'][fi]['dscp'] : ''
|
||||||
|
})
|
||||||
|
}
|
||||||
|
switch (trafficClass) {
|
||||||
|
case 'rt1': this.paramQos.rt1.push(result); break
|
||||||
|
case 'rt2': this.paramQos.rt2.push(result); break
|
||||||
|
case 'rt3': this.paramQos.rt3.push(result); break
|
||||||
|
case 'cd': this.paramQos.cd.push(result); break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qosAddClass(name) {
|
||||||
|
let res = {
|
||||||
|
isEnabled: true,
|
||||||
|
cir: 0,
|
||||||
|
pir: 0,
|
||||||
|
description: "",
|
||||||
|
filters: []
|
||||||
|
}
|
||||||
|
switch (name) {
|
||||||
|
case 'rt1': this.paramQos.rt1.push(res); break
|
||||||
|
case 'rt2': this.paramQos.rt2.push(res); break
|
||||||
|
case 'rt3': this.paramQos.rt3.push(res); break
|
||||||
|
case 'cd': this.paramQos.cd.push(res); break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qosClassAddRule(name, index) {
|
||||||
|
let rule = {
|
||||||
|
isEnabled: true,
|
||||||
|
vlan: "",
|
||||||
|
proto: [],
|
||||||
|
sport: "",
|
||||||
|
dport: "",
|
||||||
|
ip_src: "",
|
||||||
|
ip_dest: "",
|
||||||
|
dscp: ""
|
||||||
|
}
|
||||||
|
switch (name) {
|
||||||
|
case 'rt1': this.paramQos.rt1[index].filters.push(rule); break
|
||||||
|
case 'rt2': this.paramQos.rt2[index].filters.push(rule); break
|
||||||
|
case 'rt3': this.paramQos.rt3[index].filters.push(rule); break
|
||||||
|
case 'cd': this.paramQos.cd[index].filters.push(rule); break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qosDelClass(name, index) {
|
||||||
|
switch (name) {
|
||||||
|
case 'rt1': this.paramQos.rt1.splice(index, 1); break
|
||||||
|
case 'rt2': this.paramQos.rt2.splice(index, 1); break
|
||||||
|
case 'rt3': this.paramQos.rt3.splice(index, 1); break
|
||||||
|
case 'cd': this.paramQos.cd.splice(index, 1); break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qosDelFilter(name, index, filterIndex) {
|
||||||
|
switch (name) {
|
||||||
|
case 'rt1': this.paramQos.rt1[index].filters.splice(filterIndex, 1); break
|
||||||
|
case 'rt2': this.paramQos.rt2[index].filters.splice(filterIndex, 1); break
|
||||||
|
case 'rt3': this.paramQos.rt3[index].filters.splice(filterIndex, 1); break
|
||||||
|
case 'cd': this.paramQos.cd[index].filters.splice(filterIndex, 1); break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
qosGenerateRuleDescription(filter) {
|
||||||
|
// попытка 1: просто отобразить все фильтры
|
||||||
|
let result = ""
|
||||||
|
let isFirst = true;
|
||||||
|
for (const key in filter) {
|
||||||
|
if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (isFirst) {
|
||||||
|
isFirst = false;
|
||||||
|
} else {
|
||||||
|
result += '; '
|
||||||
|
}
|
||||||
|
result += `${key}: ${filter[key]}`
|
||||||
|
}
|
||||||
|
if (result === "") {
|
||||||
|
return "пустой"
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxResultLen = 60
|
||||||
|
|
||||||
|
if (result.length > maxResultLen) {
|
||||||
|
// попытка 2, отобразить что вообще в этом фильтре использовалось
|
||||||
|
result = ""
|
||||||
|
isFirst = true;
|
||||||
|
for (const key in filter) {
|
||||||
|
if (key === "isEnabled" || !filter[key] || (key === "proto" && filter['proto'].length === 0)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (isFirst) {
|
||||||
|
isFirst = false;
|
||||||
|
} else {
|
||||||
|
result += ', '
|
||||||
|
}
|
||||||
|
result += `${key}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
},
|
||||||
|
|
107
front-generator/template/common/qos.html.j2
Normal file
107
front-generator/template/common/qos.html.j2
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
{% from 'common/widgets.j2' import build_widget %}
|
||||||
|
{% raw %}
|
||||||
|
<div class="tabs-body-item" v-if="activeTab === 'qos' && settingFetchComplete">
|
||||||
|
<h2>Настройки QoS</h2>
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<label>
|
||||||
|
<span>Активировать QoS</span>
|
||||||
|
<span class="toggle-input"><input type="checkbox" v-model="paramQos.en" /><span class="slider"></span></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div v-for="classesGroup in ['rt1', 'rt2', 'rt3', 'cd']">
|
||||||
|
<h3>Классы {{ classesGroup.toUpperCase() }} <button class="action-button" @click="qosAddClass(classesGroup)"> + </button></h3>
|
||||||
|
<details v-for="(qosClass, index) in paramQos[classesGroup]" :key="index" class="settings-set-container">
|
||||||
|
<summary>
|
||||||
|
<span v-if="classesGroup === 'cd'">#{{ index }} CIR={{ qosClass.cir }}кбит, PIR={{ qosClass.pir }}кбит {{ qosClass.description }}</span>
|
||||||
|
<span v-if="classesGroup !== 'cd'">#{{ index }} CBR={{ qosClass.cir }}кбит {{ qosClass.description }}</span>
|
||||||
|
<span class="summary-actions">
|
||||||
|
<label>
|
||||||
|
<span class="toggle-input">
|
||||||
|
<input type="checkbox" v-model="qosClass.isEnabled" />
|
||||||
|
<span class="slider"></span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<label>
|
||||||
|
<span v-if="classesGroup === 'cd'">CIR</span> <span v-if="classesGroup !== 'cd'">CBR</span>
|
||||||
|
<input v-model="qosClass.cir" type="number"/>
|
||||||
|
</label>
|
||||||
|
<label v-if="classesGroup === 'cd'">
|
||||||
|
<span>PIR</span>
|
||||||
|
<input v-model="qosClass.pir" type="number"/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Описание</span>
|
||||||
|
<input v-model="qosClass.description"/>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<h3>Фильтры ({{ qosClass.filters.length }})</h3>
|
||||||
|
<div>
|
||||||
|
<button class="action-button" @click="qosClassAddRule(classesGroup, index)">Добавить правило</button>
|
||||||
|
</div>
|
||||||
|
<details v-for="(filter, filterIndex) in qosClass.filters" :key="filterIndex" class="settings-set-container">
|
||||||
|
<summary>
|
||||||
|
<span>#{{ filterIndex }} {{ qosGenerateRuleDescription(filter) }}</span>
|
||||||
|
<span class="summary-actions">
|
||||||
|
<label>
|
||||||
|
<span class="toggle-input">
|
||||||
|
<input type="checkbox" v-model="filter.isEnabled" />
|
||||||
|
<span class="slider"></span>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<button class="dangerous-button" @click="qosDelFilter(classesGroup, index, filterIndex)">Del</button>
|
||||||
|
</span>
|
||||||
|
</summary>
|
||||||
|
<label>
|
||||||
|
<span>VLAN ID</span>
|
||||||
|
<!-- singleVlanExpr: (([0-9]{1,4}-[0-9]{1,4})|([0-9]{1,4}))-->
|
||||||
|
<!-- expr: ^(((single,)+single)|single)$-->
|
||||||
|
<input v-model="filter.vlan" type="text" pattern="^((((([0-9]{1,4}-[0-9]{1,4})|([0-9]{1,4})),)+(([0-9]{1,4}-[0-9]{1,4})|([0-9]{1,4})))|(([0-9]{1,4}-[0-9]{1,4})|([0-9]{1,4})))$">
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<span>Протокол L3</span>
|
||||||
|
<label class="l3-proto-label"><span>AH:</span><input type="checkbox" value="ah" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>COMP:</span><input type="checkbox" value="comp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>DCCP:</span><input type="checkbox" value="dccp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>ESP:</span><input type="checkbox" value="esp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>ICMP:</span><input type="checkbox" value="icmp" v-model="filter.proto"></label>
|
||||||
|
<!-- <label class="l3-proto-label"><span>ICMPV6:</span><input type="checkbox" value="icmpv6" v-model="filter.proto"></label>-->
|
||||||
|
<label class="l3-proto-label"><span>SCTP:</span><input type="checkbox" value="sctp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>TCP:</span><input type="checkbox" value="tcp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>UDP:</span><input type="checkbox" value="udp" v-model="filter.proto"></label>
|
||||||
|
<label class="l3-proto-label"><span>UDPLITE:</span><input type="checkbox" value="udplite" v-model="filter.proto"></label>
|
||||||
|
</div>
|
||||||
|
<label>
|
||||||
|
<span>Порт источника</span>
|
||||||
|
<input v-model="filter.sport" type="text" pattern="^((((([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})),)+(([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})))|(([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})))$">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Порт назначения</span>
|
||||||
|
<input v-model="filter.dport" type="text" pattern="^((((([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})),)+(([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})))|(([0-9]{1,5}-[0-9]{1,5})|([0-9]{1,5})))$">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>IP источника</span>
|
||||||
|
<input v-model="filter.ip_src" type="text">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>IP назначения</span>
|
||||||
|
<input v-model="filter.ip_dest" type="text">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Метка IP.DSCP</span>
|
||||||
|
<input v-model="filter.dscp" type="text">
|
||||||
|
</label>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<button class="dangerous-button" @click="qosDelClass(classesGroup, index)">Удалить класс QoS</button>
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
</div>
|
||||||
|
<button class="action-button" @click="settingsSubmitQoS()">Применить <span class="submit-spinner" v-show="submitStatusQos"></span></button>
|
||||||
|
|
||||||
|
{% endraw %}{% if 'tcpaccel' in params %}
|
||||||
|
{% for w in params['tcpaccel'] %}{{ build_widget('tcpaccel', w) | indent(12, true) }}{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
8
front-generator/template/common/setup.html.j2
Normal file
8
front-generator/template/common/setup.html.j2
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{% from 'common/widgets.j2' import build_widget %}
|
||||||
|
<div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete">
|
||||||
|
{% for cat in ['rxtx', 'cinc', 'buclnb'] %}
|
||||||
|
{% if cat in params %}
|
||||||
|
{% for w in params[cat] %}{{ build_widget(cat, w) | indent(12, true) }}{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
63
front-generator/template/common/widgets.j2
Normal file
63
front-generator/template/common/widgets.j2
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{% macro build_widget_checkbox(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
<span>{{ widget.label }}</span>
|
||||||
|
<span class="toggle-input"><input type="checkbox" v-model="param{{ param_group | title }}.{{ widget.name }}" /><span class="slider"></span></span>
|
||||||
|
</label>{% endmacro %}
|
||||||
|
|
||||||
|
{# https://ru.stackoverflow.com/questions/1241064 #}
|
||||||
|
{% macro build_widget_number(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}><span>{{ widget.label }}</span><input type="number" v-model="param{{ param_group | title }}.{{ widget.name }}"{% if widget['min'] %} min="{{ widget['min'] }}"{% endif %}{% if widget['max'] %} max="{{ widget['max'] }}"{% endif %}{% if widget['step'] %} step="{{ widget['step'] }}"{% endif %}/></label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_select(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
<span>{{ widget.label }}</span>
|
||||||
|
<select v-model="param{{ param_group | title }}.{{ widget.name }}">
|
||||||
|
{% for opt in widget['values'] %} <option :value="{{ opt.value }}">{{ opt.label }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_watch(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}><span>{{ widget.label }}</span><input type="text" readonly v-model="{{ widget.model }}"/></label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_modulation_modcod(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
<span>{{ widget.label }}</span>
|
||||||
|
<select v-model="param{{ param_group | title }}.{{ widget.name }}Modulation" @change="param{{ param_group | title }}.{{ widget.name }}Speed = correctModcodSpeed(param{{ param_group | title }}.{{ widget.name }}Modulation, param{{ param_group | title }}.{{ widget.name }}Speed)">
|
||||||
|
<option :value="'qpsk'">QPSK</option>
|
||||||
|
<option :value="'8psk'">8PSK</option>
|
||||||
|
<option :value="'16apsk'">16APSK</option>
|
||||||
|
<option :value="'32apsk'">32APSK</option>
|
||||||
|
</select>
|
||||||
|
</label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_modulation_speed(param_group, widget) %}<label{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
<span>{{ widget.label }}</span>
|
||||||
|
<select v-model="param{{ param_group | title }}.{{ widget.name }}Speed">
|
||||||
|
<option v-for="speed in getAvailableModcods(param{{ param_group | title }}.{{ widget.name }}Modulation)" v-bind:value="speed">{{ '{{' }} speed {{ '}}' }}</option>
|
||||||
|
</select>
|
||||||
|
</label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_flex_container(param_group, widget) %}<div class="tabs-item-flex-container"{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
{% for w in widget.childs %}{{ build_widget(param_group, w) | indent(4, true) }}{% endfor %}
|
||||||
|
</div>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_settings_container(param_group, widget) %}<div class="settings-set-container"{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>
|
||||||
|
{% for w in widget.childs %}{{ build_widget(param_group, w) | indent(4, true) }}{% endfor %}
|
||||||
|
</div>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget_ip_address(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]?)$">
|
||||||
|
</label>{% endmacro %}
|
||||||
|
|
||||||
|
{% macro build_widget(param_group, widget) %}{% if widget.widget == 'flex-container' %}{{ build_widget_flex_container(param_group, widget) }}
|
||||||
|
{% elif widget.widget == 'settings-container' %}{{ build_widget_settings_container(param_group, widget) }}
|
||||||
|
{% elif widget.widget == 'h2' %}<h2{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>{{ widget.label }}</h2>
|
||||||
|
{% elif widget.widget == 'h3' %}<h3{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>{{ widget.label }}</h3>
|
||||||
|
{% elif widget.widget == 'submit' %}<button class="action-button" @click="settingsSubmit{{ param_group | title }}()"{% if widget.v_show %} v-show="{{ widget.v_show }}"{% endif %}>Сохранить <span class="submit-spinner" v-show="submitStatus.{{ param_group }}"></span></button>
|
||||||
|
{% elif widget.widget == 'checkbox' %}{{ build_widget_checkbox(param_group, widget) }}
|
||||||
|
{% elif widget.widget == 'number' %}{{ build_widget_number(param_group, widget) }}
|
||||||
|
{% elif widget.widget == 'watch' %}{{ build_widget_watch(param_group, widget) }}
|
||||||
|
{% elif widget.widget == 'select' %}{{ build_widget_select(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 == 'ip-address' %}{{ build_widget_ip_address(param_group, widget) }}
|
||||||
|
{% else %}<p>Widget '{{ widget.widget }}' not defined!</p><p>{{ widget }}</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endmacro %}
|
@ -1,139 +0,0 @@
|
|||||||
{% raw %}// для обновления высоты хидера
|
|
||||||
function updateHeaderHeight() { const header = document.querySelector('header'); document.body.style.setProperty('--header-height', `${header.offsetHeight}px`); }
|
|
||||||
window.addEventListener('load', updateHeaderHeight); window.addEventListener('resize', updateHeaderHeight);
|
|
||||||
|
|
||||||
function getCurrentTab() {
|
|
||||||
const sl = window.location.hash.slice(1)
|
|
||||||
if (availableTabs.indexOf(sl) >= 0) {
|
|
||||||
return sl
|
|
||||||
}
|
|
||||||
return defaultTab
|
|
||||||
}
|
|
||||||
|
|
||||||
function modcodToStr(modcod) {
|
|
||||||
// модкоды из раздела 5.5.2.2 https://www.etsi.org/deliver/etsi_en/302300_302399/302307/01.01.02_60/en_302307v010102p.pdf
|
|
||||||
|
|
||||||
// NOTE модкоды со скоростью хода 3/5 не работают
|
|
||||||
const modcods = [
|
|
||||||
"DUMMY",
|
|
||||||
"QPSK 1/4",
|
|
||||||
"QPSK 1/3",
|
|
||||||
"QPSK 2/5",
|
|
||||||
"QPSK 1/2",
|
|
||||||
"QPSK 3/5", // отключено
|
|
||||||
"QPSK 2/3",
|
|
||||||
"QPSK 3/4",
|
|
||||||
"QPSK 4/5",
|
|
||||||
"QPSK 5/6",
|
|
||||||
"QPSK 8/9",
|
|
||||||
"QPSK 9/10",
|
|
||||||
|
|
||||||
"8PSK 3/5", // отключено
|
|
||||||
"8PSK 2/3",
|
|
||||||
"8PSK 3/4",
|
|
||||||
"8PSK 5/6",
|
|
||||||
"8PSK 8/9",
|
|
||||||
"8PSK 9/10",
|
|
||||||
|
|
||||||
"16APSK 2/3",
|
|
||||||
"16APSK 3/4",
|
|
||||||
"16APSK 4/5",
|
|
||||||
"16APSK 5/6",
|
|
||||||
"16APSK 8/9",
|
|
||||||
"16APSK 9/10",
|
|
||||||
|
|
||||||
"32APSK 3/4",
|
|
||||||
"32APSK 4/5",
|
|
||||||
"32APSK 5/6",
|
|
||||||
"32APSK 8/9",
|
|
||||||
"32APSK 9/10",
|
|
||||||
]
|
|
||||||
if (typeof modcod != "number" || modcod < 0 || modcod >= modcod.length) {
|
|
||||||
return "?";
|
|
||||||
}
|
|
||||||
return modcods[modcod]
|
|
||||||
}
|
|
||||||
|
|
||||||
function toModcod(modulation, speed) {
|
|
||||||
switch (modulation.toLowerCase()) {
|
|
||||||
case 'qpsk':
|
|
||||||
switch (speed) {
|
|
||||||
case '1/4': return 1
|
|
||||||
case '1/3': return 2
|
|
||||||
case '2/5': return 3
|
|
||||||
case '1/2': return 4
|
|
||||||
case '3/5': return 5 // отключено
|
|
||||||
case '2/3': return 6
|
|
||||||
case '3/4': return 7
|
|
||||||
case '4/5': return 8
|
|
||||||
case '5/6': return 9
|
|
||||||
case '8/9': return 10
|
|
||||||
case '9/10': return 11
|
|
||||||
default: return 1 // минимальная скорость
|
|
||||||
}
|
|
||||||
case '8psk':
|
|
||||||
switch (speed) {
|
|
||||||
case '3/5': return 12 // отключено
|
|
||||||
case '2/3': return 13
|
|
||||||
case '3/4': return 14
|
|
||||||
case '5/6': return 15
|
|
||||||
case '8/9': return 16
|
|
||||||
case '9/10': return 17
|
|
||||||
default: return 13 // минимальная скорость
|
|
||||||
}
|
|
||||||
case '16apsk':
|
|
||||||
switch (speed) {
|
|
||||||
case '2/3': return 18
|
|
||||||
case '3/4': return 19
|
|
||||||
case '4/5': return 20
|
|
||||||
case '5/6': return 21
|
|
||||||
case '8/9': return 22
|
|
||||||
case '9/10': return 23
|
|
||||||
default: return 18 // минимальная скорость
|
|
||||||
}
|
|
||||||
case '32apsk':
|
|
||||||
switch (speed) {
|
|
||||||
case '3/4': return 24
|
|
||||||
case '4/5': return 25
|
|
||||||
case '5/6': return 26
|
|
||||||
case '8/9': return 27
|
|
||||||
case '9/10': return 28
|
|
||||||
default: return 24
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function extractModulationAndSpeedFromModcod(modcod) {
|
|
||||||
switch (modcod) {
|
|
||||||
case 1: return { modulation: 'qpsk', speed: '1/4' }
|
|
||||||
case 2: return { modulation: 'qpsk', speed: '1/3' }
|
|
||||||
case 3: return { modulation: 'qpsk', speed: '2/5' }
|
|
||||||
case 4: return { modulation: 'qpsk', speed: '1/2' }
|
|
||||||
case 5: return { modulation: 'qpsk', speed: '3/5' }
|
|
||||||
case 6: return { modulation: 'qpsk', speed: '2/3' }
|
|
||||||
case 7: return { modulation: 'qpsk', speed: '3/4' }
|
|
||||||
case 8: return { modulation: 'qpsk', speed: '4/5' }
|
|
||||||
case 9: return { modulation: 'qpsk', speed: '5/6' }
|
|
||||||
case 10: return { modulation: 'qpsk', speed: '8/9' }
|
|
||||||
case 11: return { modulation: 'qpsk', speed: '9/10' }
|
|
||||||
case 12: return { modulation: '8psk', speed: '3/5' }
|
|
||||||
case 13: return { modulation: '8psk', speed: '2/3' }
|
|
||||||
case 14: return { modulation: '8psk', speed: '3/4' }
|
|
||||||
case 15: return { modulation: '8psk', speed: '5/6' }
|
|
||||||
case 16: return { modulation: '8psk', speed: '8/9' }
|
|
||||||
case 17: return { modulation: '8psk', speed: '9/10' }
|
|
||||||
case 18: return { modulation: '16apsk', speed: '2/3' }
|
|
||||||
case 19: return { modulation: '16apsk', speed: '3/4' }
|
|
||||||
case 20: return { modulation: '16apsk', speed: '4/5' }
|
|
||||||
case 21: return { modulation: '16apsk', speed: '5/6' }
|
|
||||||
case 22: return { modulation: '16apsk', speed: '8/9' }
|
|
||||||
case 23: return { modulation: '16apsk', speed: '9/10' }
|
|
||||||
case 24: return { modulation: '32apsk', speed: '3/4' }
|
|
||||||
case 25: return { modulation: '32apsk', speed: '4/5' }
|
|
||||||
case 26: return { modulation: '32apsk', speed: '5/6' }
|
|
||||||
case 27: return { modulation: '32apsk', speed: '8/9' }
|
|
||||||
case 28: return { modulation: '32apsk', speed: '9/10' }
|
|
||||||
}
|
|
||||||
return { modulation: 'qpsk', speed: '1/4' }
|
|
||||||
}
|
|
||||||
{% endraw %}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
|||||||
isCinC: false,
|
|
||||||
|
|
||||||
// false - означает что статистика не отправляется, true - отправляется
|
|
||||||
submitStatus: {
|
|
||||||
{% for pg in params.groupsList %}
|
|
||||||
{{ pg }}: false,
|
|
||||||
{% endfor %}
|
|
||||||
firmwareUpload: false,
|
|
||||||
firmwareUpgrade: false,
|
|
||||||
// когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю
|
|
||||||
modemReboot: null
|
|
||||||
},
|
|
||||||
|
|
||||||
stat: {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
stat_rx: {
|
|
||||||
// индикаторы
|
|
||||||
state: '?', // общее состояние
|
|
||||||
sym_sync_lock: '?', // захват символьной
|
|
||||||
freq_search_lock: '?', // Захват поиска по частоте
|
|
||||||
afc_lock: '?', // захват ФАПЧ
|
|
||||||
pkt_sync: '?', // захват пакетной синхронизации
|
|
||||||
|
|
||||||
// куча других параметров, идет в том же порядке, что и в таблице
|
|
||||||
snr: '?', rssi: '?',
|
|
||||||
modcod: '?', frameSizeNormal: '?',
|
|
||||||
isPilots: '?',
|
|
||||||
symError: '?',
|
|
||||||
freqErr: '?', freqErrAcc: '?',
|
|
||||||
inputSignalLevel: '?',
|
|
||||||
pllError: '?',
|
|
||||||
speedOnRxKbit: '?',
|
|
||||||
speedOnIifKbit: '?',
|
|
||||||
|
|
||||||
// статистика пакетов
|
|
||||||
packetsOk: '?', packetsBad: '?', packetsDummy: '?',
|
|
||||||
},
|
|
||||||
stat_tx: {
|
|
||||||
// состояние
|
|
||||||
state: '?',
|
|
||||||
|
|
||||||
// прочие поля
|
|
||||||
snr: '?', modcod: '?', frameSizeNormal: '?', isPilots: '?', speedOnTxKbit: '?', speedOnIifKbit: '?',
|
|
||||||
},
|
|
||||||
stat_cinc: {
|
|
||||||
occ: '?',
|
|
||||||
correlator: null,
|
|
||||||
correlatorFails: '?',
|
|
||||||
freqErr: '?', freqErrAcc: '?',
|
|
||||||
channelDelay: '?'
|
|
||||||
},
|
|
||||||
stat_device: { // температурные датчики
|
|
||||||
adrv: 0, zynq: 0, fpga: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
param: {
|
|
||||||
general: {
|
|
||||||
isCinC: Boolean,
|
|
||||||
txEn: Boolean, // включен/выключен
|
|
||||||
modulatorMode: 'normal', // режим работы модулятора
|
|
||||||
autoStartTx: Boolean, // было "режим работы передатчика"
|
|
||||||
isTestInputData: Boolean, // входные данные: eth или test
|
|
||||||
},
|
|
||||||
tx: {
|
|
||||||
attenuation: Number, // ослабление
|
|
||||||
rolloff: Number,
|
|
||||||
cymRate: Number,
|
|
||||||
centerFreq: Number,
|
|
||||||
},
|
|
||||||
dvbs2: {
|
|
||||||
mode: null, // ccm/acm
|
|
||||||
frameSizeNormal: null, // 'normal' / 'short'
|
|
||||||
// isPilots: false,
|
|
||||||
|
|
||||||
// CCM
|
|
||||||
ccm_modulation: null,
|
|
||||||
ccm_speed: null,
|
|
||||||
|
|
||||||
// ACM
|
|
||||||
acm_maxModulation: null,
|
|
||||||
acm_maxSpeed: null,
|
|
||||||
acm_minModulation: null,
|
|
||||||
acm_minSpeed: null,
|
|
||||||
|
|
||||||
snrReserve: null,
|
|
||||||
servicePacketPeriod: null,
|
|
||||||
},
|
|
||||||
// авто-регулировка мощности
|
|
||||||
acm: {
|
|
||||||
en: false,
|
|
||||||
maxAttenuation: null,
|
|
||||||
minAttenuation: null,
|
|
||||||
requiredSnr: null,
|
|
||||||
},
|
|
||||||
rx: {
|
|
||||||
gainMode: null, // 'auto'/'manual' режим управления усилением
|
|
||||||
manualGain: 0, // усиление, только для ручного режима
|
|
||||||
spectrumInversion: false,
|
|
||||||
rolloff: 0,
|
|
||||||
cymRate: 100000,
|
|
||||||
centerFreq: 1200000.0,
|
|
||||||
},
|
|
||||||
|
|
||||||
cinc: {
|
|
||||||
mode: null, // 'positional' | 'delay'
|
|
||||||
searchBandwidth: 0, // полоса поиска в кГц
|
|
||||||
position: {
|
|
||||||
station: {
|
|
||||||
latitude: 0,
|
|
||||||
longitude: 0
|
|
||||||
},
|
|
||||||
satelliteLongitude: 0,
|
|
||||||
},
|
|
||||||
delayMin: 0,
|
|
||||||
delayMax: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
buc: {
|
|
||||||
refClk10M: false, // подача опоры 10MHz
|
|
||||||
powering: 0 // 0, 24, 48
|
|
||||||
},
|
|
||||||
lnb: {
|
|
||||||
refClk10M: false, // подача опоры 10MHz
|
|
||||||
powering: 0 // 0, 13, 18, 24
|
|
||||||
},
|
|
||||||
serviceSettings: {
|
|
||||||
refClk10M: false, // подача опоры 10MHz
|
|
||||||
autoStart: false
|
|
||||||
},
|
|
||||||
|
|
||||||
network: {
|
|
||||||
managementIp: '', // 0.0.0.0/24
|
|
||||||
managementGateway: '',
|
|
||||||
mode: String, // l2 | l3
|
|
||||||
dataIp: '', //
|
|
||||||
dataMtu: 1500
|
|
||||||
},
|
|
||||||
debugSend: {
|
|
||||||
en: false,
|
|
||||||
receiverIp: '0.0.0.0', // 0.0.0.0
|
|
||||||
portCinC: 0,
|
|
||||||
portData: 0,
|
|
||||||
timeout: 0
|
|
||||||
},
|
|
||||||
|
|
||||||
qos: {
|
|
||||||
en: false,
|
|
||||||
rt1: [],
|
|
||||||
rt2: [],
|
|
||||||
rt3: [],
|
|
||||||
cd: [],
|
|
||||||
},
|
|
||||||
|
|
||||||
tcpAccel: {
|
|
||||||
en: false,
|
|
||||||
maxConnections: 128
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
uploadFw: {
|
|
||||||
progress: null,
|
|
||||||
filename: null,
|
|
||||||
sha256: null
|
|
||||||
},
|
|
||||||
|
|
||||||
// эти "настройки" - read only
|
|
||||||
about: {
|
|
||||||
firmwareVersion: '?',
|
|
||||||
modemUid: '?',
|
|
||||||
modemSn: '?',
|
|
||||||
macManagement: '?',
|
|
||||||
macData: '?',
|
|
||||||
},
|
|
||||||
|
|
||||||
testState: false,
|
|
||||||
initState: '',
|
|
||||||
lastUpdateTime: new Date(),
|
|
||||||
activeTab: getCurrentTab(),
|
|
||||||
settingFetchComplete: false,
|
|
54
src/main.cpp
54
src/main.cpp
@ -132,7 +132,11 @@ public:
|
|||||||
auth.users.emplace_back(std::make_shared<http::auth::User>("admin", "", http::auth::User::SUPERUSER));
|
auth.users.emplace_back(std::make_shared<http::auth::User>("admin", "", http::auth::User::SUPERUSER));
|
||||||
|
|
||||||
sf->registerFile(staticFilesPath + "/favicon.png", FAVICON_ICO, mime_types::image_png, true);
|
sf->registerFile(staticFilesPath + "/favicon.png", FAVICON_ICO, mime_types::image_png, true);
|
||||||
|
#ifdef USE_DEBUG
|
||||||
sf->registerFile(staticFilesPath + VUE_JS, VUE_JS, mime_types::javascript, true);
|
sf->registerFile(staticFilesPath + VUE_JS, VUE_JS, mime_types::javascript, true);
|
||||||
|
#else
|
||||||
|
sf->registerFile(staticFilesPath + "/js/vue.prod.js", VUE_JS, mime_types::javascript, true);
|
||||||
|
#endif
|
||||||
sf->registerFile(staticFilesPath + STYLE_CSS, STYLE_CSS, mime_types::text_css, true);
|
sf->registerFile(staticFilesPath + STYLE_CSS, STYLE_CSS, mime_types::text_css, true);
|
||||||
sf->registerFile(staticFilesPath + FIELDS_CSS, FIELDS_CSS, mime_types::text_css, true);
|
sf->registerFile(staticFilesPath + FIELDS_CSS, FIELDS_CSS, mime_types::text_css, true);
|
||||||
sf->registerFile(staticFilesPath + INDEX_HTML, INDEX_HTML, mime_types::text_html, false);
|
sf->registerFile(staticFilesPath + INDEX_HTML, INDEX_HTML, mime_types::text_html, false);
|
||||||
@ -282,7 +286,7 @@ public:
|
|||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/bucLnb", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/buclnb", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
||||||
if (req.method != "POST") {
|
if (req.method != "POST") {
|
||||||
http::server::stockReply(http::server::bad_request, rep);
|
http::server::stockReply(http::server::bad_request, rep);
|
||||||
}
|
}
|
||||||
@ -304,7 +308,7 @@ public:
|
|||||||
result += "}";
|
result += "}";
|
||||||
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());
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/bucLnb): Can't set settings: " << e.what();
|
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/buclnb): Can't set BUC LNB settings: " << e.what();
|
||||||
const std::string result = R"({"status":"error"})";
|
const std::string result = R"({"status":"error"})";
|
||||||
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());
|
||||||
}
|
}
|
||||||
@ -388,35 +392,7 @@ public:
|
|||||||
result += "}";
|
result += "}";
|
||||||
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());
|
||||||
} catch (std::exception& e) {
|
} catch (std::exception& e) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/rxtx): Can't set RX/TX settings: " << e.what();
|
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/network): Can't set network settings: " << e.what();
|
||||||
const std::string result = R"({"status":"error"})";
|
|
||||||
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/debugSend", this->auth, http::auth::User::EDIT_SETTINGS, [this](const auto& req, auto& rep) {
|
|
||||||
if (req.method != "POST") {
|
|
||||||
http::server::stockReply(http::server::bad_request, rep);
|
|
||||||
}
|
|
||||||
|
|
||||||
rep.status = http::server::ok;
|
|
||||||
rep.headers.clear();
|
|
||||||
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
|
|
||||||
|
|
||||||
try {
|
|
||||||
std::stringstream ss;
|
|
||||||
ss.str(std::string(req.payload.begin(), req.payload.end()));
|
|
||||||
boost::property_tree::ptree pt;
|
|
||||||
read_json(ss, pt);
|
|
||||||
|
|
||||||
api->setDebugSendSettings(pt);
|
|
||||||
|
|
||||||
std::string result = R"({"status":"ok","settings":)";
|
|
||||||
result += api->loadSettings();
|
|
||||||
result += "}";
|
|
||||||
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
|
|
||||||
} catch (std::exception& e) {
|
|
||||||
BOOST_LOG_TRIVIAL(error) << "WebHandle(/api/set/rxtx): Can't set RX/TX settings: " << e.what();
|
|
||||||
const std::string result = R"({"status":"error"})";
|
const std::string result = R"({"status":"error"})";
|
||||||
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());
|
||||||
}
|
}
|
||||||
@ -481,16 +457,16 @@ public:
|
|||||||
|
|
||||||
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
||||||
boost::ignore_unused(req);
|
boost::ignore_unused(req);
|
||||||
sf->serve(INTERNET_JPG, rep);
|
sf->serve(DEV_HTML, rep);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev/fetchParams", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
// s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/dev/fetchParams", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
|
||||||
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"({"status":"ok","fwsize":)";
|
// std::string result = R"({"status":"ok","fwsize":)";
|
||||||
result += std::to_string(req.payload.size());
|
// result += std::to_string(req.payload.size());
|
||||||
result += R"(,"sha256":")";
|
// result += R"(,"sha256":")";
|
||||||
result += "\"}";
|
// result += "\"}";
|
||||||
}));
|
// }));
|
||||||
}
|
}
|
||||||
|
|
||||||
~ServerResources() = default;
|
~ServerResources() = default;
|
||||||
|
@ -16,48 +16,48 @@ typedef boost::property_tree::ptree::path_type json_path;
|
|||||||
|
|
||||||
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
|
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
|
||||||
|
|
||||||
static int calculateSubnetMask(const std::string& subnet_mask) {
|
// static int calculateSubnetMask(const std::string& subnet_mask) {
|
||||||
int mask = 0;
|
// int mask = 0;
|
||||||
std::istringstream iss(subnet_mask);
|
// std::istringstream iss(subnet_mask);
|
||||||
std::string octet;
|
// std::string octet;
|
||||||
while (std::getline(iss, octet, '.')) {
|
// while (std::getline(iss, octet, '.')) {
|
||||||
int octet_value = std::stoi(octet);
|
// int octet_value = std::stoi(octet);
|
||||||
for (int i = 7; i >= 0; i--) {
|
// for (int i = 7; i >= 0; i--) {
|
||||||
if (octet_value & (1 << i)) {
|
// if (octet_value & (1 << i)) {
|
||||||
mask++;
|
// mask++;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return mask;
|
// return mask;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
|
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
|
||||||
*/
|
*/
|
||||||
std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
|
// std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
|
||||||
auto pos = input.find('/');
|
// auto pos = input.find('/');
|
||||||
if (pos == std::string::npos) {
|
// if (pos == std::string::npos) {
|
||||||
// Обработка ошибки: нет символа '/'
|
// // Обработка ошибки: нет символа '/'
|
||||||
throw std::runtime_error("address not contains mask");
|
// throw std::runtime_error("address not contains mask");
|
||||||
}
|
// }
|
||||||
std::string ip = input.substr(0, pos);
|
// std::string ip = input.substr(0, pos);
|
||||||
const unsigned int mask_int = std::stoul(input.substr(pos + 1));
|
// const unsigned int mask_int = std::stoul(input.substr(pos + 1));
|
||||||
|
//
|
||||||
if (mask_int > 32) {
|
// if (mask_int > 32) {
|
||||||
throw std::runtime_error("invalid mask");
|
// throw std::runtime_error("invalid mask");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
|
// std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
|
||||||
std::string mask_str;
|
// std::string mask_str;
|
||||||
|
//
|
||||||
for (unsigned int i = 0; i < 4; ++i) {
|
// for (unsigned int i = 0; i < 4; ++i) {
|
||||||
std::string octet = mask_binary.substr(i * 8u, 8);
|
// std::string octet = mask_binary.substr(i * 8u, 8);
|
||||||
int octet_value = std::stoi(octet, nullptr, 2);
|
// int octet_value = std::stoi(octet, nullptr, 2);
|
||||||
mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
|
// mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return std::make_pair(ip, mask_str);
|
// 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) {
|
||||||
@ -67,7 +67,8 @@ static inline void rtrim(std::string &s) {
|
|||||||
|
|
||||||
class TerminalNetworkSettings {
|
class TerminalNetworkSettings {
|
||||||
public:
|
public:
|
||||||
std::string managementIp, managementGateway, mode, dataIp;
|
std::string managementIp, managementGateway, dataIp;
|
||||||
|
bool isL2 = true;
|
||||||
unsigned int dataMtu = 1500;
|
unsigned int dataMtu = 1500;
|
||||||
|
|
||||||
TerminalNetworkSettings() = default;
|
TerminalNetworkSettings() = default;
|
||||||
@ -77,10 +78,10 @@ public:
|
|||||||
TerminalNetworkSettings& operator= (const TerminalNetworkSettings& src) = default;
|
TerminalNetworkSettings& operator= (const TerminalNetworkSettings& src) = default;
|
||||||
|
|
||||||
void loadDefaults() {
|
void loadDefaults() {
|
||||||
managementIp = "0.0.0.0/0";
|
managementIp = "0.0.0.0";
|
||||||
managementGateway = "";
|
managementGateway = "";
|
||||||
mode = "l2";
|
isL2 = true;
|
||||||
dataIp = "0.0.0.0/0";
|
dataIp = "0.0.0.0";
|
||||||
dataMtu = 1500;
|
dataMtu = 1500;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -193,21 +194,22 @@ private:
|
|||||||
|
|
||||||
void updateNetworkSettings() {
|
void updateNetworkSettings() {
|
||||||
TerminalNetworkSettings s;
|
TerminalNetworkSettings s;
|
||||||
std::string tmp;
|
|
||||||
std::lock_guard lock(this->cpApiMutex);
|
std::lock_guard lock(this->cpApiMutex);
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &tmp));
|
logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp));
|
||||||
s.managementIp = tmp + "/";
|
// s.managementIp = tmp + "/";
|
||||||
tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp));
|
// tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp));
|
||||||
s.managementIp += std::to_string(calculateSubnetMask(tmp));
|
// s.managementIp += std::to_string(calculateSubnetMask(tmp));
|
||||||
tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway)); s.managementGateway = tmp;
|
logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway));
|
||||||
tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp));
|
std::string nm; logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &nm));
|
||||||
if (tmp == "tun") {
|
if (nm == "tun") {
|
||||||
s.mode = "l3";
|
s.isL2 = false;
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp));
|
logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp));
|
||||||
s.dataIp += "/24";
|
// s.dataIp += "/24";
|
||||||
} else {
|
} else {
|
||||||
s.mode = "l2";
|
s.isL2 = true;
|
||||||
s.dataIp = "0.0.0.0/24";
|
// s.dataIp = "0.0.0.0/24";
|
||||||
|
s.dataIp = "0.0.0.0";
|
||||||
}
|
}
|
||||||
s.dataMtu = 1500;
|
s.dataMtu = 1500;
|
||||||
|
|
||||||
@ -564,41 +566,39 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) {
|
void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) {
|
||||||
const auto mang = splitIpAndMask(s.managementIp);
|
// const auto mang = splitIpAndMask();
|
||||||
std::pair<std::string, std::string> data;
|
// std::pair<std::string, std::string> data;
|
||||||
bool isL2;
|
// if (!s.isL2) {
|
||||||
if (s.mode == "l2") { isL2 = true; }
|
// data = splitIpAndMask(s.dataIp);
|
||||||
else if (s.mode == "l3") { isL2 = false; data = splitIpAndMask(s.dataIp); }
|
// }
|
||||||
else { throw std::runtime_error("invalid mode"); }
|
|
||||||
|
|
||||||
std::lock_guard lock(this->cpApiMutex);
|
std::lock_guard lock(this->cpApiMutex);
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mode)", CP_SetNetwork(sid, "mode", isL2 ? "tap" : "tun"));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mode)", CP_SetNetwork(sid, "mode", s.isL2 ? "tap" : "tun"));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(addr)", CP_SetNetwork(sid, "addr", mang.first.c_str()));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(addr)", CP_SetNetwork(sid, "addr", s.managementIp.c_str()));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mask)", CP_SetNetwork(sid, "mask", mang.second.c_str()));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mask)", CP_SetNetwork(sid, "mask", "255.255.255.0"));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(gateway)", CP_SetNetwork(sid, "gateway", s.managementGateway.c_str()));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(gateway)", CP_SetNetwork(sid, "gateway", s.managementGateway.c_str()));
|
||||||
if (!isL2) {
|
if (!s.isL2) {
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(data_addr)", CP_SetNetwork(sid, "data_addr", data.first.c_str()));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(data_addr)", CP_SetNetwork(sid, "data_addr", s.dataIp.c_str()));
|
||||||
// TODO маска не устанавливается, потому что в API этого нет
|
// TODO маска не устанавливается, потому что в API этого нет
|
||||||
}
|
}
|
||||||
// TODO MTU не устанавливается, потому что в API этого нет
|
// TODO MTU не устанавливается, потому что в API этого нет
|
||||||
|
|
||||||
if (readback) {
|
if (readback) {
|
||||||
std::string tmp;
|
|
||||||
s.loadDefaults();
|
s.loadDefaults();
|
||||||
s.managementIp.clear();
|
s.managementIp.clear();
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp));
|
// logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp));
|
||||||
s.managementIp += "/";
|
// s.managementIp += "/";
|
||||||
s.managementIp += std::to_string(calculateSubnetMask(tmp));
|
// s.managementIp += std::to_string(calculateSubnetMask(tmp));
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway));
|
||||||
tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp));
|
std::string nm; logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &nm));
|
||||||
if (tmp == "tun") {
|
if (nm == "tun") {
|
||||||
s.mode = "l3";
|
s.isL2 = false;
|
||||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp));
|
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp));
|
||||||
} else {
|
} else {
|
||||||
s.mode = "l2";
|
s.isL2 = true;
|
||||||
s.dataIp = "0.0.0.0/24";
|
s.dataIp = "0.0.0.0";
|
||||||
}
|
}
|
||||||
s.dataMtu = 1500;
|
s.dataMtu = 1500;
|
||||||
{
|
{
|
||||||
@ -778,7 +778,7 @@ std::string api_driver::ApiDriver::loadTerminalState() const {
|
|||||||
result << ",\"cinc.correlatorFails\":" << cinc.cnt_bad_lock;
|
result << ",\"cinc.correlatorFails\":" << cinc.cnt_bad_lock;
|
||||||
result << ",\"cinc.freqErr\":" << cinc.freq_error_offset;
|
result << ",\"cinc.freqErr\":" << cinc.freq_error_offset;
|
||||||
result << ",\"cinc.freqErrAcc\":" << cinc.freq_fine_estimate;
|
result << ",\"cinc.freqErrAcc\":" << cinc.freq_fine_estimate;
|
||||||
result << ",\"cinc.channelDelay\":"; writeDouble(result, cinc.delay_dpdi, 1);
|
result << ",\"cinc.channelDelay\":" << cinc.delay_dpdi;
|
||||||
} else {
|
} else {
|
||||||
result << R"(,"cinc.correlator":null)";
|
result << R"(,"cinc.correlator":null)";
|
||||||
}
|
}
|
||||||
@ -799,6 +799,59 @@ void api_driver::ApiDriver::resetPacketStatistics() const {
|
|||||||
this->daemon->resetPacketStatistics();
|
this->daemon->resetPacketStatistics();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODEM_IS_SCPC
|
||||||
|
struct ModcodDef_t {const char* modulation; const char* speed;};
|
||||||
|
const static ModcodDef_t ModcodDefs[] = {
|
||||||
|
{.modulation = "dummy", .speed = "0"},
|
||||||
|
{.modulation = "qpsk", .speed = "1/4"},
|
||||||
|
{.modulation = "qpsk", .speed = "1/3"},
|
||||||
|
{.modulation = "qpsk", .speed = "2/5"},
|
||||||
|
{.modulation = "qpsk", .speed = "1/2"},
|
||||||
|
{.modulation = "qpsk", .speed = "3/5"},
|
||||||
|
{.modulation = "qpsk", .speed = "2/3"},
|
||||||
|
{.modulation = "qpsk", .speed = "3/4"},
|
||||||
|
{.modulation = "qpsk", .speed = "4/5"},
|
||||||
|
{.modulation = "qpsk", .speed = "5/6"},
|
||||||
|
{.modulation = "qpsk", .speed = "8/9"},
|
||||||
|
{.modulation = "qpsk", .speed = "9/10"},
|
||||||
|
{.modulation = "8psk", .speed = "3/5"},
|
||||||
|
{.modulation = "8psk", .speed = "2/3"},
|
||||||
|
{.modulation = "8psk", .speed = "3/4"},
|
||||||
|
{.modulation = "8psk", .speed = "5/6"},
|
||||||
|
{.modulation = "8psk", .speed = "8/9"},
|
||||||
|
{.modulation = "8psk", .speed = "9/10"},
|
||||||
|
{.modulation = "16apsk", .speed = "2/3"},
|
||||||
|
{.modulation = "16apsk", .speed = "3/4"},
|
||||||
|
{.modulation = "16apsk", .speed = "4/5"},
|
||||||
|
{.modulation = "16apsk", .speed = "5/6"},
|
||||||
|
{.modulation = "16apsk", .speed = "8/9"},
|
||||||
|
{.modulation = "16apsk", .speed = "9/10"},
|
||||||
|
{.modulation = "32apsk", .speed = "3/4"},
|
||||||
|
{.modulation = "32apsk", .speed = "4/5"},
|
||||||
|
{.modulation = "32apsk", .speed = "5/6"},
|
||||||
|
{.modulation = "32apsk", .speed = "8/9"},
|
||||||
|
{.modulation = "32apsk", .speed = "9/10"},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* extractModcodModulation(uint32_t modcod, bool defaultQpsk1_4 = true) {
|
||||||
|
modcod >>= 2;
|
||||||
|
const auto* d = defaultQpsk1_4 ? ModcodDefs : ModcodDefs + 1;
|
||||||
|
if (modcod < 28) {
|
||||||
|
d = ModcodDefs + modcod;
|
||||||
|
}
|
||||||
|
return d->modulation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char* extractModcodSpeed(uint32_t modcod, bool defaultQpsk1_4 = true) {
|
||||||
|
modcod >>= 2;
|
||||||
|
const auto* d = defaultQpsk1_4 ? ModcodDefs : ModcodDefs + 1;
|
||||||
|
if (modcod < 28) {
|
||||||
|
d = ModcodDefs + modcod;
|
||||||
|
}
|
||||||
|
return d->speed;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string api_driver::ApiDriver::loadSettings() const {
|
std::string api_driver::ApiDriver::loadSettings() const {
|
||||||
if (daemon == nullptr) {
|
if (daemon == nullptr) {
|
||||||
return R"({"error": "api daemon not started!"})";
|
return R"({"error": "api daemon not started!"})";
|
||||||
@ -818,93 +871,92 @@ std::string api_driver::ApiDriver::loadSettings() const {
|
|||||||
daemon->getNetworkSettings(network);
|
daemon->getNetworkSettings(network);
|
||||||
|
|
||||||
std::stringstream result;
|
std::stringstream result;
|
||||||
|
result << "{\n\"txAutoStart\":" << boolAsStr(modSettings.is_save_current_state);
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
result << "{\n\"general.isCinC\":" << boolAsStr(modSettings.is_cinc);
|
result << ",\"txModulatorIsTest\":" << boolAsStr(!modSettings.is_carrier);
|
||||||
result << ",\"general.txEn\":" << boolAsStr(modSettings.tx_is_on);
|
#endif
|
||||||
result << ",\"general.modulatorMode\":" << (modSettings.is_carrier ? "\"normal\"" : "\"test\"");
|
result << ",\"txIsTestInput\":" << boolAsStr(modSettings.is_test_data);
|
||||||
result << ",\"general.autoStartTx\":" << boolAsStr(modSettings.is_save_current_state);
|
result << ",\"txCentralFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz);
|
||||||
result << ",\"general.isTestInputData\":" << boolAsStr(modSettings.is_test_data);
|
result << ",\"txBaudrate\":" << modSettings.baudrate;
|
||||||
result << ",\n\"tx.attenuation\":"; writeDouble(result, modSettings.attenuation);
|
result << ",\"txRolloff\":" << static_cast<int>(modSettings.rollof * 100);
|
||||||
result << ",\"tx.rolloff\":" << static_cast<int>(modSettings.rollof * 100);
|
#ifdef MODEM_IS_SCPC
|
||||||
result << ",\"tx.goldan\":" << static_cast<int>(modSettings.qold_seq_is_active);
|
result << ",\"txGoldan\":" << static_cast<int>(modSettings.qold_seq_is_active);
|
||||||
result << ",\"tx.cymRate\":" << modSettings.baudrate;
|
#endif
|
||||||
result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3);
|
result << ",\"txAttenuation\":"; writeDouble(result, modSettings.attenuation);
|
||||||
result << ",\"dvbs2.frameSizeNormal\":" << boolAsStr(!(modSettings.modcod_tx & 2));
|
|
||||||
result << ",\"dvbs2.ccm_modcod\":" << (modSettings.modcod_tx >> 2);
|
|
||||||
|
|
||||||
// result << ",\"dvbs2.isPilots\":" << "null";
|
#ifdef MODEM_IS_SCPC
|
||||||
result << ",\n\"dvbs2.isAcm\":" << boolAsStr(acmSettings.enable);
|
result << ",\n\"isCinC\":" << boolAsStr(modSettings.is_cinc);
|
||||||
result << ",\"dvbs2.acm_maxModcod\":" << (acmSettings.max_modcod >> 2);
|
result << ",\n\"dvbServicePacketPeriod\":" << acmSettings.period_pack;
|
||||||
result << ",\"dvbs2.acm_minModcod\":" << (acmSettings.min_modcod >> 2);
|
result << ",\"dvbIsAcm\":" << boolAsStr(acmSettings.enable);
|
||||||
result << ",\"dvbs2.snrReserve\":"; writeDouble(result, acmSettings.snr_treashold_acm);
|
result << ",\"txFrameSizeNormal\":" << boolAsStr((modSettings.modcod_tx & 2) == 0);
|
||||||
result << ",\"dvbs2.servicePacketPeriod\":" << acmSettings.period_pack;
|
|
||||||
|
|
||||||
result << ",\n\"acm.en\":" << boolAsStr(acmSettings.enable_auto_atten);
|
result << R"(,"dvbCcmModulation":")" << extractModcodModulation(modSettings.modcod_tx) << "\"";
|
||||||
result << ",\"acm.maxAttenuation\":"; writeDouble(result, acmSettings.max_attenuation);
|
result << R"(,"dvbCcmSpeed":")" << extractModcodSpeed(modSettings.modcod_tx) << "\"";
|
||||||
result << ",\"acm.minAttenuation\":"; writeDouble(result, acmSettings.min_attenuation);
|
result << R"(,"dvbAcmMinModulation":")" << extractModcodModulation(acmSettings.min_modcod) << "\"";
|
||||||
result << ",\"acm.requiredSnr\":"; writeDouble(result, acmSettings.snr_treashold);
|
result << R"(,"dvbAcmMinSpeed":")" << extractModcodSpeed(acmSettings.min_modcod) << "\"";
|
||||||
|
result << R"(,"dvbAcmMaxModulation":")" << extractModcodModulation(acmSettings.max_modcod) << "\"";
|
||||||
|
result << R"(,"dvbAcmMaxSpeed":")" << extractModcodSpeed(acmSettings.max_modcod) << "\"";
|
||||||
|
result << ",\"dvbSnrReserve\":"; writeDouble(result, acmSettings.snr_treashold_acm);
|
||||||
|
|
||||||
result << ",\n\"rx.gainMode\":" << (demodSettings.is_aru_on ? "\"auto\"" : "\"manual\"");
|
result << ",\n\"aupcEn\":" << boolAsStr(acmSettings.enable_auto_atten);
|
||||||
result << ",\"rx.manualGain\":"; writeDouble(result, demodSettings.gain);
|
result << ",\"aupcMinAttenuation\":"; writeDouble(result, acmSettings.min_attenuation);
|
||||||
result << ",\"rx.spectrumInversion\":" << boolAsStr(demodSettings.is_rvt_iq);
|
result << ",\"aupcMaxAttenuation\":"; writeDouble(result, acmSettings.max_attenuation);
|
||||||
result << ",\"rx.rolloff\":" << static_cast<int>(demodSettings.rollof * 100);
|
result << ",\"aupcRequiredSnr\":"; writeDouble(result, acmSettings.snr_treashold);
|
||||||
result << ",\"rx.goldan\":" << static_cast<int>(demodSettings.qold_seq_is_active);
|
|
||||||
result << ",\"rx.cymRate\":" << demodSettings.baudrate;
|
|
||||||
result << ",\"rx.centerFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz);
|
|
||||||
|
|
||||||
result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\"");
|
result << ",\n\"cincIsPositional\":" << boolAsStr(!dpdiSettings.is_delay_window);
|
||||||
result << ",\"cinc.searchBandwidth\":" << dpdiSettings.freq_offset; // полоса поиска в кГц
|
result << ",\"cincSearchBandwidth\":" << dpdiSettings.freq_offset; // полоса поиска в кГц
|
||||||
result << ",\"cinc.position.station.latitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.latitude_station_grad, dpdiSettings.latitude_station_minute), 6);
|
result << ",\"cincPositionStationLatitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.latitude_station_grad, dpdiSettings.latitude_station_minute), 6);
|
||||||
result << ",\"cinc.position.station.longitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_station_grad, dpdiSettings.longitude_station_minute), 6);
|
result << ",\"cincPositionStationLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_station_grad, dpdiSettings.longitude_station_minute), 6);
|
||||||
result << ",\"cinc.position.satelliteLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_sattelite_grad, dpdiSettings.longitude_sattelite_minute), 6);
|
result << ",\"cincPositionSatelliteLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_sattelite_grad, dpdiSettings.longitude_sattelite_minute), 6);
|
||||||
result << ",\"cinc.delayMin\":" << dpdiSettings.min_delay;
|
result << ",\"cincDelayMin\":" << dpdiSettings.min_delay;
|
||||||
result << ",\"cinc.delayMax\":" << dpdiSettings.max_delay;
|
result << ",\"cincDelayMax\":" << dpdiSettings.max_delay;
|
||||||
#else
|
|
||||||
result << "{\n\"tx.txEn\":" << boolAsStr(modSettings.tx_is_on);
|
|
||||||
result << ",\"tx.isTestInputData\":" << boolAsStr(modSettings.is_test_data);
|
|
||||||
result << ",\"tx.cymRate\":" << modSettings.baudrate;
|
|
||||||
result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3);
|
|
||||||
result << ",\"tx.attenuation\":"; writeDouble(result, modSettings.attenuation);
|
|
||||||
|
|
||||||
result << ",\n\"rx.gainMode\":" << (demodSettings.is_aru_on ? "\"auto\"" : "\"manual\"");
|
|
||||||
result << ",\"rx.manualGain\":"; writeDouble(result, demodSettings.gain);
|
|
||||||
result << ",\"rx.spectrumInversion\":" << boolAsStr(demodSettings.is_rvt_iq);
|
|
||||||
result << ",\"rx.rolloff\":" << static_cast<int>(demodSettings.rollof * 100);
|
|
||||||
result << ",\"rx.cymRate\":" << demodSettings.baudrate;
|
|
||||||
result << ",\"rx.centerFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc);
|
result << ",\n\"rxAgcEn\":" << boolAsStr(demodSettings.is_aru_on);
|
||||||
|
result << ",\"rxSpectrumInversion\":" << boolAsStr(demodSettings.is_rvt_iq);
|
||||||
|
result << ",\"rxManualGain\":"; writeDouble(result, demodSettings.gain);
|
||||||
|
result << ",\"rxCentralFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz);
|
||||||
|
result << ",\"rxBaudrate\":" << demodSettings.baudrate;
|
||||||
|
result << ",\"rxRolloff\":" << static_cast<int>(demodSettings.rollof * 100);
|
||||||
|
#ifdef MODEM_IS_SCPC
|
||||||
|
result << ",\"txGoldan\":" << static_cast<int>(demodSettings.qold_seq_is_active);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// BUC LNB
|
||||||
|
result << ",\n\"bucRefClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc);
|
||||||
switch (bucLnb.buc) {
|
switch (bucLnb.buc) {
|
||||||
case voltage_buc::_24V: result << ",\"buc.powering\":24"; break;
|
case voltage_buc::_24V: result << ",\"bucPowering\":24"; break;
|
||||||
case voltage_buc::_48V: result << ",\"buc.powering\":48"; break;
|
#ifdef MODEM_IS_SCPC
|
||||||
|
case voltage_buc::_48V: result << ",\"bucPowering\":48"; break;
|
||||||
|
#endif
|
||||||
case voltage_buc::DISABLE:
|
case voltage_buc::DISABLE:
|
||||||
default: result << ",\"buc.powering\":0";
|
default: result << ",\"bucPowering\":0";
|
||||||
}
|
}
|
||||||
|
|
||||||
result << ",\n\"lnb.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_lnb);
|
result << ",\"lnbRefClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_lnb);
|
||||||
switch (bucLnb.lnb) {
|
switch (bucLnb.lnb) {
|
||||||
case voltage_lnb::_13V: result << ",\"lnb.powering\":13"; break;
|
case voltage_lnb::_13V: result << ",\"lnbPowering\":13"; break;
|
||||||
case voltage_lnb::_18V: result << ",\"lnb.powering\":18"; break;
|
case voltage_lnb::_18V: result << ",\"lnbPowering\":18"; break;
|
||||||
case voltage_lnb::_24V: result << ",\"lnb.powering\":24"; break;
|
case voltage_lnb::_24V: result << ",\"lnbPowering\":24"; break;
|
||||||
case voltage_lnb::DISABLE:
|
case voltage_lnb::DISABLE:
|
||||||
default: result << ",\"lnb.powering\":0";
|
default: result << ",\"lnbPowering\":0";
|
||||||
}
|
}
|
||||||
|
|
||||||
result << ",\n\"serviceSettings.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_output);
|
result << ",\"srvRefClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_output);
|
||||||
result << ",\"serviceSettings.autoStart\":" << boolAsStr(bucLnb.is_save_current_state);
|
result << ",\"bucLnbAutoStart\":" << boolAsStr(bucLnb.is_save_current_state);
|
||||||
|
|
||||||
|
// QoS
|
||||||
bool qosEnabled = false; std::string qosClasses;
|
bool qosEnabled = false; std::string qosClasses;
|
||||||
daemon->getQosSettings(qosEnabled, qosClasses);
|
daemon->getQosSettings(qosEnabled, qosClasses);
|
||||||
result << ",\n\"qos.enabled\":" << boolAsStr(qosEnabled);
|
result << ",\n\"qosEnabled\":" << boolAsStr(qosEnabled);
|
||||||
result << ",\"qos.profile\":" << qosClasses;
|
result << ",\"qosProfile\":" << qosClasses;
|
||||||
|
|
||||||
// сеть
|
// сеть
|
||||||
result << ",\"network.managementIp\":\n" << buildEscapedString(network.managementIp);
|
result << ",\"netManagementIp\":\n" << buildEscapedString(network.managementIp);
|
||||||
result << ",\"network.managementGateway\":\n" << buildEscapedString(network.managementGateway);
|
result << ",\"netIsL2\":\n" << boolAsStr(network.isL2);
|
||||||
result << ",\"network.mode\":\n" << buildEscapedString(network.mode);
|
result << ",\"netManagementGateway\":\n" << buildEscapedString(network.managementGateway);
|
||||||
result << ",\"network.dataIp\":\n" << buildEscapedString(network.dataIp);
|
result << ",\"netDataIp\":\n" << buildEscapedString(network.dataIp);
|
||||||
result << ",\"network.dataMtu\":\n" << network.dataMtu;
|
result << ",\"netDataMtu\":\n" << network.dataMtu;
|
||||||
|
|
||||||
result << "}";
|
result << "}";
|
||||||
return result.str();
|
return result.str();
|
||||||
@ -926,66 +978,81 @@ std::string api_driver::ApiDriver::loadFirmwareVersion() const {
|
|||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MODEM_IS_SCPC
|
||||||
|
static uint32_t buildModcodFromPt(const boost::property_tree::ptree& pt, const std::string& name, bool isShortFrame) {
|
||||||
|
uint32_t modcod = 0;
|
||||||
|
const auto mod = pt.get<std::string>(name + "Modulation");
|
||||||
|
const auto speed = pt.get<std::string>(name + "Speed");
|
||||||
|
uint32_t _index = 0;
|
||||||
|
for (const auto& m: ModcodDefs) {
|
||||||
|
if (mod == m.modulation) {
|
||||||
|
if (modcod == 0) modcod = _index;
|
||||||
|
if (speed == m.speed) {
|
||||||
|
modcod = _index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_index++;
|
||||||
|
}
|
||||||
|
return (modcod << 2) | (isShortFrame ? 2 : 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
|
void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
|
||||||
modulator_settings mod{};
|
modulator_settings mod{};
|
||||||
demodulator_settings demod{};
|
demodulator_settings demod{};
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
ACM_parameters_serv_ acm{};
|
ACM_parameters_serv_ acm{};
|
||||||
|
daemon->getSettings(&mod, &demod, &acm, nullptr, nullptr);
|
||||||
|
#else
|
||||||
|
daemon->getSettings(&mod, &demod, nullptr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// для модулятора
|
// для модулятора
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
mod.is_cinc = pt.get<bool>(json_path("general.isCinC", '/'));
|
mod.is_cinc = pt.get<bool>("isCinC");
|
||||||
mod.tx_is_on = pt.get<bool>(json_path("general.txEn", '/'));
|
#endif
|
||||||
auto tmp = pt.get<std::string>(json_path("general.modulatorMode", '/'));
|
mod.tx_is_on = pt.get<bool>("txEn");
|
||||||
if (tmp == "normal") { mod.is_carrier = true; }
|
#ifdef MODEM_IS_SCPC
|
||||||
else if (tmp == "test") { mod.is_carrier = false; }
|
mod.is_save_current_state = pt.get<bool>("txAutoStart");
|
||||||
else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong carrier mode: " + tmp); }
|
mod.is_carrier = !pt.get<bool>("txModulatorIsTest");
|
||||||
mod.is_save_current_state = pt.get<bool>(json_path("general.autoStartTx", '/'));
|
#endif
|
||||||
mod.is_test_data = pt.get<bool>(json_path("general.isTestInputData", '/'));
|
mod.is_test_data = pt.get<bool>("txIsTestInput");
|
||||||
mod.attenuation = pt.get<double>(json_path("tx.attenuation", '/'));
|
mod.central_freq_in_kGz = pt.get<double>("txCentralFreq");
|
||||||
mod.rollof = pt.get<double>(json_path("tx.rolloff", '/')) / 100.0;
|
mod.baudrate = pt.get<uint32_t>("txBaudrate");
|
||||||
mod.qold_seq_is_active = pt.get<int>(json_path("tx.goldan", '/'));
|
mod.rollof = pt.get<int>("txRolloff") / 100.0;
|
||||||
mod.baudrate = pt.get<uint32_t>(json_path("tx.cymRate", '/'));
|
#ifdef MODEM_IS_SCPC
|
||||||
mod.central_freq_in_kGz = pt.get<double>(json_path("tx.centerFreq", '/'));
|
mod.qold_seq_is_active = pt.get<bool>("txGoldan");
|
||||||
|
#endif
|
||||||
|
mod.attenuation = pt.get<double>("txAttenuation");
|
||||||
|
|
||||||
const bool acmIsShortFrame = !pt.get<bool>(json_path("dvbs2.frameSizeNormal", '/'));
|
#ifdef MODEM_IS_SCPC
|
||||||
mod.modcod_tx = (pt.get<uint32_t>(json_path("dvbs2.ccm_modcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
|
const bool acmIsShortFrame = !pt.get<bool>("txFrameSizeNormal");
|
||||||
#else
|
mod.modcod_tx = buildModcodFromPt(pt, "dvbCcm", acmIsShortFrame);
|
||||||
mod.tx_is_on = pt.get<bool>(json_path("tx.txEn", '/'));
|
|
||||||
mod.is_test_data = pt.get<bool>(json_path("tx.isTestInputData", '/'));
|
|
||||||
mod.central_freq_in_kGz = pt.get<double>(json_path("tx.centerFreq", '/'));
|
|
||||||
mod.baudrate = pt.get<uint32_t>(json_path("tx.cymRate", '/'));
|
|
||||||
mod.attenuation = pt.get<double>(json_path("tx.attenuation", '/'));
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// демодулятор
|
// демодулятор
|
||||||
|
demod.is_aru_on = pt.get<bool>("rxAgcEn");
|
||||||
|
demod.gain = pt.get<bool>("rxManualGain");
|
||||||
|
demod.is_rvt_iq = pt.get<bool>("aupcEn");
|
||||||
|
demod.central_freq_in_kGz = pt.get<double>("rxCentralFreq");
|
||||||
|
demod.baudrate = pt.get<uint32_t>("rxBaudrate");
|
||||||
|
demod.rollof = pt.get<int>("rxRolloff") / 100.0;
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
tmp = pt.get<std::string>(json_path("rx.gainMode", '/'));
|
demod.qold_seq_is_active = pt.get<bool>("rxGoldan");
|
||||||
demod.qold_seq_is_active = pt.get<int>(json_path("rx.goldan", '/'));
|
|
||||||
#else
|
|
||||||
auto tmp = pt.get<std::string>(json_path("rx.gainMode", '/'));
|
|
||||||
#endif
|
#endif
|
||||||
if (tmp == "auto") { demod.is_aru_on = true; }
|
|
||||||
else if (tmp == "manual") { demod.is_aru_on = false; }
|
|
||||||
else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong gain mode: " + tmp); }
|
|
||||||
demod.gain = pt.get<double>(json_path("rx.manualGain", '/'));
|
|
||||||
demod.baudrate = pt.get<uint32_t>(json_path("rx.cymRate", '/'));
|
|
||||||
demod.is_rvt_iq = pt.get<bool>(json_path("rx.spectrumInversion", '/'));
|
|
||||||
demod.rollof = pt.get<double>(json_path("rx.rolloff", '/')) / 100.0;
|
|
||||||
demod.central_freq_in_kGz = pt.get<double>(json_path("rx.centerFreq", '/'));
|
|
||||||
|
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
// ACM
|
// ACM
|
||||||
acm.enable = pt.get<bool>(json_path("dvbs2.isAcm", '/'));
|
acm.period_pack = pt.get<uint32_t>("dvbServicePacketPeriod");
|
||||||
acm.max_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_maxModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
|
acm.enable = pt.get<bool>("rxAgcEn");
|
||||||
acm.min_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_minModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
|
acm.min_modcod = buildModcodFromPt(pt, "dvbAcmMin", acmIsShortFrame);
|
||||||
acm.snr_treashold_acm = pt.get<double>(json_path("dvbs2.snrReserve", '/')); // запас ОСШ
|
acm.max_modcod = buildModcodFromPt(pt, "dvbAcmMax", acmIsShortFrame);
|
||||||
acm.period_pack = pt.get<uint32_t>(json_path("dvbs2.servicePacketPeriod", '/'));
|
acm.snr_treashold_acm = pt.get<double>("dvbSnrReserve"); // запас ОСШ
|
||||||
acm.enable_auto_atten = pt.get<bool>(json_path("acm.en", '/'));
|
acm.enable_auto_atten = pt.get<bool>(json_path("aupcEn", '/'));
|
||||||
acm.max_attenuation = pt.get<double>(json_path("acm.maxAttenuation", '/'));
|
acm.min_attenuation = pt.get<int>("aupcMinAttenuation");
|
||||||
acm.min_attenuation = pt.get<double>(json_path("acm.minAttenuation", '/'));
|
acm.max_attenuation = pt.get<int>("aupcMaxAttenuation");
|
||||||
acm.snr_treashold = pt.get<double>(json_path("acm.requiredSnr", '/')); // требуемый ОСШ
|
acm.snr_treashold = pt.get<double>("aupcRequiredSnr");
|
||||||
|
|
||||||
daemon->setSettingsRxTx(mod, demod, acm);
|
daemon->setSettingsRxTx(mod, demod, acm);
|
||||||
#else
|
#else
|
||||||
@ -997,30 +1064,23 @@ void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
|
|||||||
void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) {
|
void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) {
|
||||||
DPDI_parmeters s{};
|
DPDI_parmeters s{};
|
||||||
|
|
||||||
//result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\"");
|
s.is_delay_window = !pt.get<bool>("cincIsPositional");
|
||||||
auto tmp = pt.get<std::string>(json_path("cinc.mode", '/'));
|
s.freq_offset = pt.get<uint32_t>("cincSearchBandwidth");
|
||||||
if (tmp == "delay") { s.is_delay_window = true; }
|
|
||||||
else if (tmp == "positional") { s.is_delay_window = false; }
|
|
||||||
else {
|
|
||||||
throw std::runtime_error("Wrong CinC mode: " + tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.station.latitude", '/')));
|
auto ctmp = translateCoordinates(pt.get<double>("cincPositionStationLatitude"));
|
||||||
s.latitude_station_grad = std::get<0>(ctmp);
|
s.latitude_station_grad = std::get<0>(ctmp);
|
||||||
s.latitude_station_minute = std::get<1>(ctmp);
|
s.latitude_station_minute = std::get<1>(ctmp);
|
||||||
|
|
||||||
ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.station.longitude", '/')));
|
ctmp = translateCoordinates(pt.get<double>("cincPositionStationLongitude"));
|
||||||
s.longitude_station_grad = std::get<0>(ctmp);
|
s.longitude_station_grad = std::get<0>(ctmp);
|
||||||
s.longitude_station_minute = std::get<1>(ctmp);
|
s.longitude_station_minute = std::get<1>(ctmp);
|
||||||
|
|
||||||
ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.satelliteLongitude", '/')));
|
ctmp = translateCoordinates(pt.get<double>("cincPositionSatelliteLongitude"));
|
||||||
s.longitude_sattelite_grad = std::get<0>(ctmp);
|
s.longitude_sattelite_grad = std::get<0>(ctmp);
|
||||||
s.longitude_sattelite_minute = std::get<1>(ctmp);
|
s.longitude_sattelite_minute = std::get<1>(ctmp);
|
||||||
|
|
||||||
s.max_delay = pt.get<uint32_t>(json_path("cinc.delayMax", '/'));
|
s.min_delay = pt.get<uint32_t>("cincDelayMin");
|
||||||
s.min_delay = pt.get<uint32_t>(json_path("cinc.delayMin", '/'));
|
s.max_delay = pt.get<uint32_t>("cincDelayMax");
|
||||||
|
|
||||||
s.freq_offset = pt.get<uint32_t>(json_path("cinc.searchBandwidth", '/'));
|
|
||||||
|
|
||||||
this->daemon->setSettingsCinc(s);
|
this->daemon->setSettingsCinc(s);
|
||||||
}
|
}
|
||||||
@ -1028,19 +1088,13 @@ void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) {
|
|||||||
|
|
||||||
void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) {
|
void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) {
|
||||||
buc_lnb_settings s{};
|
buc_lnb_settings s{};
|
||||||
|
#ifdef MODEM_IS_SCPC
|
||||||
|
daemon->getSettings(nullptr, nullptr, nullptr, nullptr, &s);
|
||||||
|
#else
|
||||||
|
daemon->getSettings(nullptr, nullptr, &s);
|
||||||
|
#endif
|
||||||
|
|
||||||
auto tmp = pt.get<int>(json_path("lnb.powering", '/'));
|
auto tmp = pt.get<int>("bucPowering");
|
||||||
switch (tmp) {
|
|
||||||
case 13: s.lnb = voltage_lnb::_13V; break;
|
|
||||||
case 18: s.lnb = voltage_lnb::_18V; break;
|
|
||||||
case 24: s.lnb = voltage_lnb::_24V; break;
|
|
||||||
case 0:
|
|
||||||
default:
|
|
||||||
s.lnb = voltage_lnb::DISABLE;
|
|
||||||
}
|
|
||||||
s.is_ref_10MHz_lnb = pt.get<bool>(json_path("lnb.refClk10M", '/'));
|
|
||||||
|
|
||||||
tmp = pt.get<int>(json_path("buc.powering", '/'));
|
|
||||||
switch (tmp) {
|
switch (tmp) {
|
||||||
case 24: s.buc = voltage_buc::_24V; break;
|
case 24: s.buc = voltage_buc::_24V; break;
|
||||||
#ifdef MODEM_IS_SCPC
|
#ifdef MODEM_IS_SCPC
|
||||||
@ -1050,11 +1104,21 @@ void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) {
|
|||||||
default:
|
default:
|
||||||
s.lnb = voltage_lnb::DISABLE;
|
s.lnb = voltage_lnb::DISABLE;
|
||||||
}
|
}
|
||||||
|
s.is_ref_10MHz_buc = pt.get<bool>("bucRefClk10M");
|
||||||
|
|
||||||
s.is_ref_10MHz_buc = pt.get<bool>(json_path("buc.refClk10M", '/'));
|
tmp = pt.get<int>("lnbPowering");
|
||||||
|
switch (tmp) {
|
||||||
|
case 13: s.lnb = voltage_lnb::_13V; break;
|
||||||
|
case 18: s.lnb = voltage_lnb::_18V; break;
|
||||||
|
case 24: s.lnb = voltage_lnb::_24V; break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
s.lnb = voltage_lnb::DISABLE;
|
||||||
|
}
|
||||||
|
s.is_ref_10MHz_lnb = pt.get<bool>("lnbRefClk10M");
|
||||||
|
|
||||||
s.is_ref_10MHz_output = pt.get<bool>(json_path("serviceSettings.refClk10M", '/'));
|
s.is_ref_10MHz_output = pt.get<bool>("srvRefClk10M");
|
||||||
s.is_save_current_state = pt.get<bool>(json_path("serviceSettings.autoStart", '/'));
|
s.is_save_current_state = pt.get<bool>("bucLnbAutoStart");
|
||||||
|
|
||||||
this->daemon->setSettingsBucLnb(s);
|
this->daemon->setSettingsBucLnb(s);
|
||||||
}
|
}
|
||||||
@ -1071,19 +1135,17 @@ void api_driver::ApiDriver::setQosSettings(boost::property_tree::ptree &pt) {
|
|||||||
|
|
||||||
void api_driver::ApiDriver::setNetworkSettings(boost::property_tree::ptree &pt) {
|
void api_driver::ApiDriver::setNetworkSettings(boost::property_tree::ptree &pt) {
|
||||||
TerminalNetworkSettings s;
|
TerminalNetworkSettings s;
|
||||||
s.managementIp = pt.get<std::string>(json_path("network.managementIp", '/'));
|
daemon->getNetworkSettings(s);
|
||||||
s.managementGateway = pt.get<std::string>(json_path("network.managementGateway", '/'));
|
|
||||||
s.mode = pt.get<std::string>(json_path("network.mode", '/'));
|
s.managementIp = pt.get<std::string>("netManagementIp");
|
||||||
s.dataIp = pt.get<std::string>(json_path("network.dataIp", '/'));
|
// s.managementGateway = pt.get<std::string>(json_path("network.managementGateway", '/'));
|
||||||
s.dataMtu = pt.get<unsigned int>(json_path("network.dataMtu", '/'));
|
s.isL2 = pt.get<bool>("netIsL2");
|
||||||
|
s.dataIp = pt.get<std::string>("netDataIp");
|
||||||
|
s.dataMtu = pt.get<unsigned int>("netDataMtu");
|
||||||
|
|
||||||
daemon->setNetworkSettings(s);
|
daemon->setNetworkSettings(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void api_driver::ApiDriver::setDebugSendSettings(boost::property_tree::ptree &pt) {
|
|
||||||
boost::ignore_unused(pt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void api_driver::ApiDriver::resetDefaultSettings() {
|
void api_driver::ApiDriver::resetDefaultSettings() {
|
||||||
daemon->resetDefaultSettings();
|
daemon->resetDefaultSettings();
|
||||||
}
|
}
|
||||||
@ -1102,35 +1164,34 @@ std::string api_driver::ApiDriver::loadSysInfo() {
|
|||||||
struct sysinfo info{};
|
struct sysinfo info{};
|
||||||
sysinfo(&info);
|
sysinfo(&info);
|
||||||
|
|
||||||
struct sysinfo {
|
// struct sysinfo {
|
||||||
long uptime; /* Seconds since boot */
|
// long uptime; /* Seconds since boot */
|
||||||
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
|
// unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
|
||||||
unsigned long totalram; /* Total usable main memory size */
|
// unsigned long totalram; /* Total usable main memory size */
|
||||||
unsigned long freeram; /* Available memory size */
|
// unsigned long freeram; /* Available memory size */
|
||||||
unsigned long sharedram; /* Amount of shared memory */
|
// unsigned long sharedram; /* Amount of shared memory */
|
||||||
unsigned long bufferram; /* Memory used by buffers */
|
// unsigned long bufferram; /* Memory used by buffers */
|
||||||
unsigned long totalswap; /* Total swap space size */
|
// unsigned long totalswap; /* Total swap space size */
|
||||||
unsigned long freeswap; /* Swap space still available */
|
// unsigned long freeswap; /* Swap space still available */
|
||||||
unsigned short procs; /* Number of current processes */
|
// unsigned short procs; /* Number of current processes */
|
||||||
unsigned long totalhigh; /* Total high memory size */
|
// unsigned long totalhigh; /* Total high memory size */
|
||||||
unsigned long freehigh; /* Available high memory size */
|
// unsigned long freehigh; /* Available high memory size */
|
||||||
unsigned int mem_unit; /* Memory unit size in bytes */
|
// unsigned int mem_unit; /* Memory unit size in bytes */
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
double f_load = 1.0 / (1 << SI_LOAD_SHIFT);
|
||||||
|
|
||||||
result << "{\n\"uptime\":" << info.uptime;
|
result << "{\n\"uptime\":" << info.uptime;
|
||||||
result << ",\"load1min\":" << info.loads[0];
|
result << ",\"load1min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[0]), 2);
|
||||||
result << ",\"load5min\":" << info.loads[1];
|
result << ",\"load5min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[1]), 2);
|
||||||
result << ",\"load15min\":" << info.loads[2];
|
result << ",\"load15min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[2]), 2);
|
||||||
result << ",\"totalram\":" << info.totalram;
|
result << ",\"totalram\":" << ((info.totalram * info.mem_unit) >> 20); // Mb
|
||||||
result << ",\"freeram\":" << info.freeram;
|
result << ",\"freeram\":" << ((info.freeram * info.mem_unit) >> 20); // Mb
|
||||||
result << ",\"sharedram\":" << info.sharedram;
|
// result << ",\"sharedram\":" << ((info.sharedram * info.mem_unit) >> 20); // Mb
|
||||||
result << ",\"bufferram\":" << info.bufferram;
|
// result << ",\"bufferram\":" << ((info.bufferram * info.mem_unit) >> 20); // Mb
|
||||||
result << ",\"totalswap\":" << info.totalswap;
|
// result << ",\"totalswap\":" << info.totalswap * info.mem_unit;
|
||||||
result << ",\"freeswap\":" << info.freeswap;
|
// result << ",\"freeswap\":" << info.freeswap * info.mem_unit;
|
||||||
result << ",\"procs\":" << static_cast<long>(info.procs);
|
result << ",\"procs\":" << static_cast<long>(info.procs);
|
||||||
result << ",\"totalhigh\":" << info.totalhigh;
|
|
||||||
result << ",\"freehigh\":" << info.freehigh;
|
|
||||||
result << ",\"mem_unit\":" << info.mem_unit;
|
|
||||||
result << "\n}";
|
result << "\n}";
|
||||||
return result.str();
|
return result.str();
|
||||||
}
|
}
|
||||||
|
@ -64,8 +64,6 @@ namespace api_driver {
|
|||||||
|
|
||||||
void setNetworkSettings(boost::property_tree::ptree & pt);
|
void setNetworkSettings(boost::property_tree::ptree & pt);
|
||||||
|
|
||||||
void setDebugSendSettings(boost::property_tree::ptree & pt);
|
|
||||||
|
|
||||||
void resetDefaultSettings();
|
void resetDefaultSettings();
|
||||||
|
|
||||||
void executeInApi(const std::function<void(TSID sid)>& callback);
|
void executeInApi(const std::function<void(TSID sid)>& callback);
|
||||||
|
@ -2,9 +2,103 @@
|
|||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Title</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>RSCM-101</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="/style.css">
|
||||||
|
<link rel="stylesheet" type="text/css" href="/fields.css">
|
||||||
|
<style>
|
||||||
|
header {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
z-index: 10;
|
||||||
|
background: var(--bg-selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
body { /* значение по-умолчанию */ --header-height: 60px; }
|
||||||
|
|
||||||
|
#content {
|
||||||
|
padding-top: var(--header-height);
|
||||||
|
}
|
||||||
|
|
||||||
|
.l3-proto-label {
|
||||||
|
margin: 0 0 0 0.5em;
|
||||||
|
}
|
||||||
|
.l3-proto-label > * {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
.l3-proto-label input[type=checkbox] {
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="app" hidden>
|
||||||
|
<header>
|
||||||
|
<span class="nav-bar-element">Прием: <span :class="{ indicator_bad: stat_rx.state === false, indicator_good: stat_rx.state === true, indicator: true }"></span></span>
|
||||||
|
<span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span>
|
||||||
|
<div class="tabs-header">
|
||||||
|
<span style="font-weight:bold">RSCM-101</span>
|
||||||
|
<a href="#monitoring" class="tabs-btn" @click="activeTab = 'monitoring'" :class="{ active: activeTab === 'monitoring' }">Мониторинг</a>
|
||||||
|
<a href="#setup" class="tabs-btn" @click="activeTab = 'setup'" :class="{ active: activeTab === 'setup' }">Настройки</a>
|
||||||
|
<a href="#qos" class="tabs-btn" @click="activeTab = 'qos'" :class="{ active: activeTab === 'qos' }">QoS</a>
|
||||||
|
<a href="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
|
||||||
|
<a href="/logout" class="tabs-btn">Выход</a>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
<div id="content">
|
||||||
|
<p>Прием: <span :class="{ indicator_bad: stat_rx.state === false, indicator_good: stat_rx.state === true, indicator: true }"></span></p>
|
||||||
|
<p>Скорость: <span>{{ stat_rx.speedOnRxKbit }}</span></p>
|
||||||
|
|
||||||
|
<h2>Настройки</h2>
|
||||||
|
<div class="settings-set-container">
|
||||||
|
<label>
|
||||||
|
<span>Режим работы</span>
|
||||||
|
<select v-model="param.general.isCinC">
|
||||||
|
<option :value="false">SCPC</option>
|
||||||
|
<option :value="true">CinC</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<span>Полоса поиска, кгц ±</span>
|
||||||
|
<input v-model="param.num" type="number" min="0" max="100" step="1"/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="/js/vue.js"></script>
|
||||||
|
<script>
|
||||||
|
const app = Vue.createApp({
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
stat_rx: {
|
||||||
|
state: false,
|
||||||
|
},
|
||||||
|
param: {
|
||||||
|
general: {
|
||||||
|
isCinC: true,
|
||||||
|
isTestInputData: false,
|
||||||
|
modulatorMode: 'test'
|
||||||
|
},
|
||||||
|
num: 1
|
||||||
|
},
|
||||||
|
|
||||||
|
initState: '?',
|
||||||
|
activeTab: 'setup'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
document.getElementById("app").removeAttribute("hidden")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
app.mount('#app')
|
||||||
|
</script>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -135,7 +135,7 @@ select * {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.settings-set-container th, .settings-set-container td {
|
.settings-set-container th, .settings-set-container td {
|
||||||
border-bottom: solid 1px var(--text-color2);
|
border-bottom: solid 1px var(--bg-element);
|
||||||
}
|
}
|
||||||
.settings-set-container table { border-collapse: collapse; }
|
.settings-set-container table { border-collapse: collapse; }
|
||||||
|
|
||||||
|
29805
static/js/vue.js
29805
static/js/vue.js
File diff suppressed because it is too large
Load Diff
9
static/js/vue.prod.js
Normal file
9
static/js/vue.prod.js
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user