Compare commits

...

29 Commits

Author SHA1 Message Date
479200df9e изменил формат аптайма 2025-01-09 12:49:59 +03:00
20cf08e2a1 добавил получение sysinfo и вывод аптайма в веб-морде 2025-01-09 12:02:42 +03:00
ab654a754c патч для переподключения к API в случае ошибок 2025-01-09 11:28:35 +03:00
8990fed8f0 зачатки страницы для разработчиков 2024-12-28 16:42:14 +03:00
be6c8023c5 добавил защиту от двойного обновления прошивки, добавил настройки TCP-акселерации в веб (они пока не работает из-за API) 2024-12-28 16:41:58 +03:00
24cb1061a7 добавил отключенную скорость кода 3/5 2024-12-28 11:20:37 +03:00
77ba05e407 косметические исправления: увеличил шрифт, убрал жирный шрифт в таблицах 2024-12-25 11:05:22 +03:00
f3454897d8 исправление полей в SCPC модеме 2024-12-24 17:21:04 +03:00
dc4e37eb8a Merge branch 'refs/heads/dev-scpc-new-rolloff' 2024-12-23 13:57:59 +03:00
522abee794 косметические исправления страниц 2024-12-23 12:52:52 +03:00
8278e4119f косметические исправления страниц 2024-12-23 09:48:02 +03:00
0a3a282d0f некоторые нововведения в front-generator 2024-12-23 09:40:43 +03:00
3d97824ee7 фикс модкода CCM 2024-12-23 09:39:50 +03:00
55fa498dc1 обновил поле rolloff 2024-12-16 09:39:39 +03:00
f5c5caa31c добавил зачатки front-generator, исправил мелкий баг QoS 2024-12-16 09:30:16 +03:00
833374a80e сделал API статической библиотекой 2024-11-29 17:52:25 +03:00
b67011b9a3 добавил получение статуса из API вместе со статистикой 2024-11-29 17:37:25 +03:00
91e9c0301e фикс: билд SCPC модема 2024-11-29 15:12:27 +03:00
98dcc06a6a логгирование ошибок API (установка параметров) 2024-11-29 15:04:38 +03:00
e0aacfe8aa логгирование ошибок API на всех периодических запросах 2024-11-29 14:11:36 +03:00
3e4ffc8281 изменил логику подключения к API 2024-11-29 13:36:39 +03:00
1f8ea04f43 добавил динамическую линковку для boost::log 2024-11-28 17:43:41 +03:00
ad6d734f4a скрыл ржачную картинку 2024-11-28 16:58:57 +03:00
6d79d60eb1 исправил надпись 2024-11-28 16:56:34 +03:00
572a2583f0 логика работы TDMA 2024-11-28 16:56:20 +03:00
925fec6dda добавил фронт для TDMA 2024-11-28 14:57:29 +03:00
5f3d5791da исправление замечаний от Кости 2024-11-27 11:20:55 +03:00
c05a9cff7a добавил повторные попытки подключения к API, если не удалось подключиться 2024-11-15 15:49:20 +03:00
dff0ba1cd3 фикс: центральная частота 2024-11-15 15:37:08 +03:00
18 changed files with 3986 additions and 492 deletions

View File

@@ -15,6 +15,16 @@ else()
message(FATAL_ERROR "You must set build type \"Debug\" or \"Release\". Another build types not supported!") message(FATAL_ERROR "You must set build type \"Debug\" or \"Release\". Another build types not supported!")
endif() endif()
if("${MODEM_TYPE}" STREQUAL "SCPC")
add_definitions(-DMODEM_IS_SCPC)
message(STATUS "Selected SCPC modem")
elseif ("${MODEM_TYPE}" STREQUAL "TDMA")
add_definitions(-DMODEM_IS_TDMA)
message(STATUS "Selected TDMA modem")
else()
message(FATAL_ERROR "You must set `MODEM_TYPE` \"SCPC\" or \"TDMA\"!")
endif()
add_compile_options(-Wall -Wextra -Wsign-conversion) add_compile_options(-Wall -Wextra -Wsign-conversion)
# максимальный размер тела запроса 200mb # максимальный размер тела запроса 200mb
@@ -47,6 +57,8 @@ add_executable(terminal-web-server
src/auth/utils.h src/auth/utils.h
) )
add_definitions(-DBOOST_LOG_DYN_LINK)
find_package(Boost 1.53.0 COMPONENTS system thread filesystem log log_setup REQUIRED) find_package(Boost 1.53.0 COMPONENTS system thread filesystem log log_setup REQUIRED)
find_package(OpenSSL REQUIRED) find_package(OpenSSL REQUIRED)
target_link_libraries(terminal-web-server ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} terminal-client-api) target_link_libraries(terminal-web-server ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} terminal-client-api)

View File

@@ -15,14 +15,14 @@ set(CMAKE_CXX_FLAGS -fPIC)
set(default_build_type "Release") set(default_build_type "Release")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0 -fprofile-arcs -ftest-coverage") set(CMAKE_CXX_FLAGS_DEBUG "-ggdb -O0")
set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s -DNDEBUG ") set(CMAKE_CXX_FLAGS_RELEASE "-O2 -s -DNDEBUG ")
message(${CMAKE_CXX_FLAGS}) message(${CMAKE_CXX_FLAGS})
message("CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE}) message("CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE})
message(${CMAKE_CXX_FLAGS}) message(${CMAKE_CXX_FLAGS})
add_library(terminal-client-api SHARED add_library(terminal-client-api STATIC
client/main.cpp client/main.cpp
client/sock_client.cpp client/sock_client.cpp
client/system_client.cpp client/system_client.cpp

View File

@@ -0,0 +1,75 @@
{
"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": {
"tdma": {
"modem_name": "RCSM-101 TDMA",
"groupsList": ["rxtx"],
"tabs": [
{
"name": "monitoring",
"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": {
"modem_name": "RCSM-101",
"groupsList": ["rxtx"],
"tabs": [
{
"name": "monitoring",
"desc": "Мониторинг"
},
{
"name": "setup",
"desc": "Настройки"
},
{
"name": "qos",
"desc": "QoS"
},
{
"name": "admin",
"desc": "Администрирование"
}
]
}
}
}

39
front-generator/render.py Normal file
View File

@@ -0,0 +1,39 @@
import json
from jinja2 import Environment, FileSystemLoader
import sys
def build_modem_env(modem):
with open('render-params.json') as f:
config = json.load(f)
if modem not in config['modem_types']:
raise RuntimeError(f"Modem '{modem}' is not exist in config!")
mc = config['modem_types'][modem]
return {
"modem_name": mc['modem_name'],
"header_tabs": mc['tabs'],
"js_tabs_array": str([t['name'] for t in mc['tabs']]),
"params": {"groupsList": mc["groupsList"]} | config["params"]
}
def render_modem(modem):
loader = FileSystemLoader('template')
env = Environment(loader=loader, trim_blocks=True, lstrip_blocks=True)
template = env.get_template('main.html')
context = build_modem_env(modem)
with open(f"main-{modem}.html", "w") as f:
f.write(template.render(context))
if __name__ == '__main__':
if len(sys.argv) != 2:
print(f"Usage: {sys.argv[0]} <scpc|tdma>")
render_modem(sys.argv[1])

View File

@@ -0,0 +1,139 @@
{% 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 %}

View File

@@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>RSCM-101</title> <title>{{ modem_name }}</title>
<link rel="stylesheet" type="text/css" href="/style.css"> <link rel="stylesheet" type="text/css" href="/style.css">
<link rel="stylesheet" type="text/css" href="/fields.css"> <link rel="stylesheet" type="text/css" href="/fields.css">
<style> <style>{% raw %}
header { header {
position: fixed; position: fixed;
top: 0; top: 0;
@@ -31,27 +31,27 @@
.l3-proto-label input[type=checkbox] { .l3-proto-label input[type=checkbox] {
width: auto; width: auto;
} }
{% endraw %}
</style> </style>
</head> </head>
<body> <body>
<div id="app" hidden> <div id="app" hidden>
<header> <header>{% raw %}
<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="nav-bar-element">Прием: <span :class="{ indicator_bad: stat_rx.state === false, indicator_good: stat_rx.state === true, indicator: true }"></span></span>
<span class="nav-bar-element">Передача: <span :class="{ indicator_good: stat_tx.state === true, indicator: true }"></span></span> <span class="nav-bar-element">Передача: <span :class="{ indicator_good: stat_tx.state === true, indicator: true }"></span></span>
<span class="nav-bar-element">Тест: <span :class="{ indicator_good: (param.general.isTestInputData === true || param.general.modulatorMode === 'test'), indicator: true }"></span></span> <span class="nav-bar-element">Тест: <span :class="{ indicator_good: (param.general.isTestInputData === true || param.general.modulatorMode === 'test'), indicator: true }"></span></span>
<!-- Последнее обновление: {{ lastUpdateTime }}--> <!-- Последнее обновление: {{ lastUpdateTime }}-->
<span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span> <span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span>
{% endraw %}
<div class="tabs-header"> <div class="tabs-header">
<span style="font-weight:bold">RSCM-101</span> <span style="font-weight:bold">{{ modem_name }}</span>
<a href="#monitoring" class="tabs-btn" @click="activeTab = 'monitoring'" :class="{ active: activeTab === 'monitoring' }">Мониторинг</a> {% for tab in header_tabs %}
<a href="#setup" class="tabs-btn" @click="activeTab = 'setup'" :class="{ active: activeTab === 'setup' }">Настройки</a> <a href="#{{ tab.name }}" class="tabs-btn" @click="activeTab = '{{ tab.name }}'" :class="{{ '{' }} active: activeTab === '{{ tab.name }}' {{ '}' }}">{{ tab.description }}</a>
<a href="#qos" class="tabs-btn" @click="activeTab = 'qos'" :class="{ active: activeTab === 'qos' }">QoS</a> {% endfor %}
<a href="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
<a href="/logout" class="tabs-btn">Выход</a>
</div> </div>
</header> </header>
{% raw %}
<div id="content"> <div id="content">
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'"> <div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
<div class="settings-set-container"> <div class="settings-set-container">
@@ -122,6 +122,7 @@
</table> </table>
</div> </div>
</div> </div>
<div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete"> <div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete">
<h2>Настройки приема/передачи</h2> <h2>Настройки приема/передачи</h2>
<div class="settings-set-container"> <div class="settings-set-container">
@@ -167,7 +168,7 @@
<h3>Параметры передачи</h3> <h3>Параметры передачи</h3>
<label> <label>
<span>Центральная частота, КГц</span> <span>Центральная частота, КГц</span>
<input v-model="param.tx.centerFreq" type="number"/> <input v-model="param.tx.centerFreq" type="number" step="0.01"/>
</label> </label>
<label> <label>
<span>Символьная скорость, Бод</span> <span>Символьная скорость, Бод</span>
@@ -219,7 +220,7 @@
<label v-show="param.dvbs2.mode === 'ccm'"> <label v-show="param.dvbs2.mode === 'ccm'">
<span>Модуляция</span> <span>Модуляция</span>
<select v-model="param.dvbs2.ccm_modulation"> <select v-model="param.dvbs2.ccm_modulation" @change="param.dvbs2.ccm_speed = correctModcodSpeed(param.dvbs2.ccm_modulation, param.dvbs2.ccm_speed)">
<option value="qpsk">QPSK</option> <option value="qpsk">QPSK</option>
<option value="8psk">8PSK</option> <option value="8psk">8PSK</option>
<option value="16apsk">16APSK</option> <option value="16apsk">16APSK</option>
@@ -240,7 +241,7 @@
<label v-show="param.dvbs2.mode === 'acm'"> <label v-show="param.dvbs2.mode === 'acm'">
<span>Модуляция (макс. режим)</span> <span>Модуляция (макс. режим)</span>
<select v-model="param.dvbs2.acm_maxModulation"> <select v-model="param.dvbs2.acm_maxModulation" @change="param.dvbs2.acm_maxSpeed = correctModcodSpeed(param.dvbs2.acm_maxModulation, param.dvbs2.acm_maxSpeed)">
<option value="qpsk">QPSK</option> <option value="qpsk">QPSK</option>
<option value="8psk">8PSK</option> <option value="8psk">8PSK</option>
<option value="16apsk">16APSK</option> <option value="16apsk">16APSK</option>
@@ -255,7 +256,7 @@
</label> </label>
<label v-show="param.dvbs2.mode === 'acm'"> <label v-show="param.dvbs2.mode === 'acm'">
<span>Модуляция (мин. режим)</span> <span>Модуляция (мин. режим)</span>
<select v-model="param.dvbs2.acm_minModulation"> <select v-model="param.dvbs2.acm_minModulation" @change="param.dvbs2.acm_minSpeed = correctModcodSpeed(param.dvbs2.acm_minModulation, param.dvbs2.acm_minSpeed)">
<option value="qpsk">QPSK</option> <option value="qpsk">QPSK</option>
<option value="8psk">8PSK</option> <option value="8psk">8PSK</option>
<option value="16apsk">16APSK</option> <option value="16apsk">16APSK</option>
@@ -316,7 +317,7 @@
</label> </label>
<label> <label>
<span>Центральная частота, кГц</span> <span>Центральная частота, кГц</span>
<input v-model="param.rx.centerFreq" type="number"/> <input v-model="param.rx.centerFreq" type="number" step="0.01"/>
</label> </label>
<label> <label>
<span>Символьная скорость, Бод</span> <span>Символьная скорость, Бод</span>
@@ -591,7 +592,7 @@
<input v-model="param.debugSend.receiverIp" required type="text" pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}"> <input v-model="param.debugSend.receiverIp" required type="text" pattern="^([0-9]{1,3}\.){3}[0-9]{1,3}">
</label> </label>
<label> <label>
<span>Порт для CinC</span> <span>Порт для данных</span>
<input v-model="param.debugSend.portCinC" type="number" min="0" max="65535"> <input v-model="param.debugSend.portCinC" type="number" min="0" max="65535">
</label> </label>
<label> <label>
@@ -616,7 +617,7 @@
</tbody> </tbody>
</table> </table>
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/reboot', { method: 'POST' }).then((r) => { window.location.reload(); })">Перезагрузить модем</button> <button class="dangerous-button" @click="doModemReboot()">Перезагрузить модем <span class="submit-spinner" v-show="submitStatus.modemReboot !== null"></span></button>
</div> </div>
<div> <div>
<button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button> <button class="dangerous-button" onclick="fetch('/api/resetSettings', { method: 'POST' }).then((r) => { window.location.reload(); })">Сбросить модем до заводских настроек</button>
@@ -634,336 +635,20 @@
</div> </div>
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p> <p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
</div> </div>
{% endraw %}
</div> </div>
<script src="/js/vue.js"></script> <script src="/js/vue.js"></script>
<script> <script>
function updateHeaderHeight() {
const header = document.querySelector('header');
document.body.style.setProperty('--header-height', `${header.offsetHeight}px`);
}
window.addEventListener('load', updateHeaderHeight);
window.addEventListener('resize', updateHeaderHeight);
// const router = useRouter(); // const router = useRouter();
const availableTabs = ['monitoring', 'setup', 'qos', 'admin'] const availableTabs = {{ js_tabs_array }}
const defaultTab = availableTabs[0] const defaultTab = availableTabs[0]
function getCurrentTab() { {% include 'default-js.js' %}
const sl = window.location.hash.slice(1) {% raw %}
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/1': 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 12 // минимальная скорость
}
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' }
}
const app = new Vue({ const app = new Vue({
el: '#app', el: '#app',
data: { data: {
isCinC: false, {% endraw %}{% include 'vue-data.js' %}{% raw %}
// false - означает что статистика не отправляется, true - отправляется
submitStatus: {
rxTx: false,
cinc: false,
bucLnb: false,
qos: false,
network: false,
debugSend: false,
tcpAccel: false,
firmwareUpload: false,
firmwareUpgrade: false
},
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
}, },
methods: { methods: {
getAvailableModcods(modulation) { getAvailableModcods(modulation) {
@@ -1081,7 +766,7 @@
body: JSON.stringify(query) body: JSON.stringify(query)
}).then(async (resp) => { }).then(async (resp) => {
this.submitStatus.rxTx = false this.submitStatus.rxTx = false
this.updateCincSettings(await resp.json()) this.updateRxTxSettings(await resp.json())
}).catch((reason) => { }).catch((reason) => {
this.submitStatus.rxTx = false this.submitStatus.rxTx = false
alert(`Ошибка при применении настроек: ${reason}`) alert(`Ошибка при применении настроек: ${reason}`)
@@ -1600,17 +1285,49 @@
} }
return result return result
},
correctModcodSpeed(modulation, speed) {
const mod = modulation.toLowerCase()
const available = {
"qpsk": ['1/4', '1/3', '2/5', '1/2', '3/5', '2/3', '3/4', '4/5', '5/6', '8/9', '9/10'],
"8psk": ['2/3', '3/4', '5/6', '8/9', '9/10'],
"16apsk": ['2/3', '3/4', '4/5', '5/6', '8/9', '9/10'],
"32apsk": ['3/4', '4/5', '5/6', '8/9', '9/10']
}
if (mod in available) {
if (available[mod].indexOf(speed) >= 0) {
return speed
}
return available[mod][0]
}
return ""
},
doModemReboot() {
if (this.submitStatus.modemReboot !== null) {
return
}
this.submitStatus.modemReboot = 30
fetch('/api/reboot', { method: 'POST' }).then((r) => {})
} }
}, },
mounted() { mounted() {
const doFetchStatistics = async () => { const doFetchStatistics = async () => {
try { if (this.submitStatus.modemReboot !== null) {
let d = await fetch("/api/get/statistics") this.initState = `Перезагрузка модема... Осталось ${this.submitStatus.modemReboot} сек`
this.updateStatistics(await d.json()) this.submitStatus.modemReboot--
} catch (e) { if (this.submitStatus.modemReboot <= 0) {
this.initState = "Ошибка обновления статистики" window.location.reload()
}
} else {
try {
let d = await fetch("/api/get/statistics")
this.updateStatistics(await d.json())
} catch (e) {
this.initState = "Ошибка обновления статистики"
}
} }
setTimeout(() => { setTimeout(() => {
doFetchStatistics() doFetchStatistics()
}, 1000) }, 1000)
@@ -1638,6 +1355,7 @@
document.getElementById("app").removeAttribute("hidden") document.getElementById("app").removeAttribute("hidden")
} }
}) })
//{% endraw %}
</script> </script>
</body> </body>
</html> </html>

View File

@@ -0,0 +1,181 @@
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,

View File

@@ -84,6 +84,8 @@ class ServerResources {
std::unique_ptr<api_driver::ApiDriver> api; std::unique_ptr<api_driver::ApiDriver> api;
http::auth::AuthProvider auth{}; http::auth::AuthProvider auth{};
bool upgradeOrRebootRunning = false;
static void onUploadFirmware(const http::server::Request& req) { static void onUploadFirmware(const http::server::Request& req) {
std::ofstream f("/tmp/firmware.zip", std::ios::binary); std::ofstream f("/tmp/firmware.zip", std::ios::binary);
@@ -104,16 +106,23 @@ class ServerResources {
} }
public: public:
static constexpr const char* INDEX_HTML = "/main.html"; #if defined(MODEM_IS_TDMA)
static constexpr const char* INDEX_HTML = "/main-tdma.html";
#elif defined(MODEM_IS_SCPC)
static constexpr const char* INDEX_HTML = "/main-scpc.html";
#else
#error "Modem type not defined!"
#endif
static constexpr const char* LOGIN_HTML = "/login.html"; static constexpr const char* LOGIN_HTML = "/login.html";
// картинки, их даже можно кешировать // картинки, их даже можно кешировать
static constexpr const char* FAVICON_ICO = "/favicon.png"; static constexpr const char* FAVICON_ICO = "/favicon.ico";
static constexpr const char* VUE_JS = "/js/vue.js"; // это тоже можно кешировать static constexpr const char* VUE_JS = "/js/vue.js"; // это тоже можно кешировать
// а эти стили нельзя кешировать в отладочной версии // а эти стили нельзя кешировать в отладочной версии
static constexpr const char* STYLE_CSS = "/style.css"; static constexpr const char* STYLE_CSS = "/style.css";
static constexpr const char* FIELDS_CSS = "/fields.css"; static constexpr const char* FIELDS_CSS = "/fields.css";
static constexpr const char* INTERNET_JPG = "/internet.jpg";
ServerResources(const ServerResources&) = delete; ServerResources(const ServerResources&) = delete;
@@ -121,12 +130,13 @@ public:
api->startDaemon(); api->startDaemon();
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_ICO, FAVICON_ICO, mime_types::image_png, true); sf->registerFile(staticFilesPath + "/favicon.png", FAVICON_ICO, mime_types::image_png, true);
sf->registerFile(staticFilesPath + VUE_JS, VUE_JS, mime_types::javascript, true); sf->registerFile(staticFilesPath + VUE_JS, VUE_JS, mime_types::javascript, true);
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);
sf->registerFile(staticFilesPath + LOGIN_HTML, LOGIN_HTML, mime_types::text_html, true); sf->registerFile(staticFilesPath + LOGIN_HTML, LOGIN_HTML, mime_types::text_html, true);
sf->registerFile(staticFilesPath + INTERNET_JPG, INTERNET_JPG, mime_types::image_jpeg, true);
} }
void registerResources(http::server::Server& s) { void registerResources(http::server::Server& s) {
@@ -180,10 +190,11 @@ public:
} }
})); }));
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/favicon.ico", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(FAVICON_ICO, rep); })); s.resources.emplace_back(std::make_unique<http::resource::GenericResource>(FAVICON_ICO, [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(FAVICON_ICO, rep); }));
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/style.css", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(STYLE_CSS, rep); })); s.resources.emplace_back(std::make_unique<http::resource::GenericResource>(STYLE_CSS, [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(STYLE_CSS, rep); }));
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/fields.css", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(FIELDS_CSS, rep); })); s.resources.emplace_back(std::make_unique<http::resource::GenericResource>(FIELDS_CSS, [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(FIELDS_CSS, rep); }));
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>("/js/vue.js", [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(VUE_JS, rep); })); s.resources.emplace_back(std::make_unique<http::resource::GenericResource>(VUE_JS, [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(VUE_JS, rep); }));
s.resources.emplace_back(std::make_unique<http::resource::GenericResource>(INTERNET_JPG, [this](const auto& req, auto& rep) { boost::ignore_unused(req); sf->serve(INTERNET_JPG, rep); }));
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/get/statistics", this->auth, http::auth::User::WATCH_STATISTICS, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/get/statistics", this->auth, http::auth::User::WATCH_STATISTICS, [this](const auto& req, auto& rep) {
if (req.method != "GET") { if (req.method != "GET") {
@@ -195,6 +206,8 @@ public:
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"({"mainState":)"; std::string result = R"({"mainState":)";
result += api->loadTerminalState(); result += api->loadTerminalState();
result += R"(,"sysinfo":)";
result += api->loadSysInfo();
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());
})); }));
@@ -293,7 +306,7 @@ public:
rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size()); rep.content.insert(rep.content.end(), result.c_str(), result.c_str() + result.size());
} }
})); }));
#ifdef MODEM_IS_SCPC
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/cinc", this->auth, http::auth::User::EDIT_SETTINGS, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/cinc", this->auth, http::auth::User::EDIT_SETTINGS, [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);
@@ -321,7 +334,7 @@ public:
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());
} }
})); }));
#endif
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/rxtx", this->auth, http::auth::User::EDIT_SETTINGS, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/set/rxtx", this->auth, http::auth::User::EDIT_SETTINGS, [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);
@@ -406,7 +419,7 @@ public:
} }
})); }));
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/reboot", this->auth, 0, [](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/reboot", this->auth, 0, [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);
} }
@@ -415,6 +428,7 @@ public:
rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)}); rep.headers.push_back({.name = "Content-Type", .value = toString(mime_types::json)});
const std::string result = R"({"status":"ok"})"; const std::string result = R"({"status":"ok"})";
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());
this->upgradeOrRebootRunning = true;
system(REBOOT_COMMAND); system(REBOOT_COMMAND);
})); }));
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/resetSettings", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/resetSettings", this->auth, http::auth::User::SUPERUSER, [this](const auto& req, auto& rep) {
@@ -430,10 +444,11 @@ public:
system(REBOOT_COMMAND); system(REBOOT_COMMAND);
})); }));
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/firmwareUpdate", this->auth, http::auth::User::UPDATE_FIRMWARE, [](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/firmwareUpdate", this->auth, http::auth::User::UPDATE_FIRMWARE, [this](const auto& req, auto& rep) {
if (req.method != "PUT") { if (req.method != "PUT") {
http::server::stockReply(http::server::bad_request, rep); http::server::stockReply(http::server::bad_request, rep);
} }
this->upgradeOrRebootRunning = true;
onUploadFirmware(req); onUploadFirmware(req);
rep.status = http::server::ok; rep.status = http::server::ok;
@@ -445,12 +460,14 @@ public:
result += http::utils::sha256(req.payload.data(), req.payload.size()); result += http::utils::sha256(req.payload.data(), req.payload.size());
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());
this->upgradeOrRebootRunning = false;
})); }));
s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/doFirmwareUpgrade", this->auth, http::auth::User::UPDATE_FIRMWARE, [this](const auto& req, auto& rep) { s.resources.emplace_back(std::make_unique<http::auth::AuthRequiredResource>("/api/doFirmwareUpgrade", this->auth, http::auth::User::UPDATE_FIRMWARE, [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);
} }
this->upgradeOrRebootRunning = true;
doTerminalUpgrade(); doTerminalUpgrade();
rep.status = http::server::ok; rep.status = http::server::ok;
rep.headers.clear(); rep.headers.clear();
@@ -458,6 +475,19 @@ public:
const auto result = api->loadFirmwareVersion(); const auto result = api->loadFirmwareVersion();
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());
})); }));
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);
sf->serve(INTERNET_JPG, 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)});
std::string result = R"({"status":"ok","fwsize":)";
result += std::to_string(req.payload.size());
result += R"(,"sha256":")";
result += "\"}";
}));
} }
~ServerResources() = default; ~ServerResources() = default;

View File

@@ -8,8 +8,9 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
#include <boost/property_tree/json_parser.hpp> #include <boost/property_tree/json_parser.hpp>
#include <sys/sysinfo.h>
#include "../dependencies/control_system/common/protocol_commands.h"
typedef boost::property_tree::ptree::path_type json_path; typedef boost::property_tree::ptree::path_type json_path;
@@ -95,30 +96,29 @@ public:
TerminalFirmwareVersion& operator= (const TerminalFirmwareVersion& src) = default; TerminalFirmwareVersion& operator= (const TerminalFirmwareVersion& src) = default;
}; };
static std::ostream& operator<<(std::ostream& out, CP_Result result) {
switch (result) {
case OK: out << "OK"; break;
case TIMEOUT: out << "TIMEOUT"; break;
case ERROR: out << "ERROR"; break;
case ABORT: out << "ABORT"; break;
case BUSY: out << "BUSY"; break;
default:
out << static_cast<int>(result);
}
return out;
}
/** /**
* Этот демон нужен для того, чтобы получать статистику из API, а так же корректно сохранять настройки * Этот демон нужен для того, чтобы получать статистику из API, а так же корректно сохранять настройки
*/ */
class api_driver::TerminalApiDaemon { class api_driver::TerminalApiDaemon {
private: private:
CP_Result lastCpError = OK;
void updateFirmwareSettings() { void logCpApiError(const char* desc, CP_Result err) {
std::string version, chip_id, sn, mac0, mac1; if (err != OK) {
std::lock_guard lock(this->cpApiMutex); BOOST_LOG_TRIVIAL(error) << "CP API error in " << desc << ": " << err;
this->lastCpError = err;
CP_GetNetwork(sid, "version", &version);
CP_GetNetwork(sid, "chip_id", &chip_id);
rtrim(chip_id);
CP_GetNetwork(sid, "serial", &sn);
CP_GetNetwork(sid, "mac_eth0", &mac0);
CP_GetNetwork(sid, "mac_eth1", &mac1);
{
std::lock_guard lock2(this->firmwareMutex);
this->firmware.version = version;
this->firmware.modemId = chip_id;
this->firmware.modemSn = sn;
this->firmware.macMang = mac0;
this->firmware.macData = mac1;
} }
} }
@@ -126,23 +126,36 @@ private:
modulator_state modulator{}; modulator_state modulator{};
demodulator_state demodulator{}; demodulator_state demodulator{};
device_state device{}; device_state device{};
#ifdef MODEM_IS_SCPC
CinC_state cinc{}; CinC_state cinc{};
#endif
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_GetModulatorState(sid, modulator); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetModulatorState()", CP_GetModulatorState(sid, modulator));
CP_GetDemodulatorState(sid, demodulator); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDemodulatorState()", CP_GetDemodulatorState(sid, demodulator));
CP_GetDeviceState(sid, device); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDeviceState()", CP_GetDeviceState(sid, device));
#ifdef MODEM_IS_TDMA
std::string tmpDevState;
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDmaDebug(status_init)", CP_GetDmaDebug(sid, "status_init", &tmpDevState));
#endif
#ifdef MODEM_IS_SCPC
bool isCinC = getIsCinC(); bool isCinC = getIsCinC();
if (isCinC) { if (isCinC) {
CP_GetCinCState(sid, cinc); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetCinCState()", CP_GetCinCState(sid, cinc));
} }
#endif
{ {
std::lock_guard lock2(this->stateMutex); std::lock_guard lock2(this->stateMutex);
this->modState = modulator; this->modState = modulator;
this->demodState = demodulator; this->demodState = demodulator;
this->devState = device; this->devState = device;
#ifdef MODEM_IS_TDMA
this->deviceInitState = tmpDevState;
#endif
#ifdef MODEM_IS_SCPC
this->cincState = cinc; this->cincState = cinc;
#endif
} }
} }
@@ -151,23 +164,29 @@ private:
// uint32_t modulatorModcod; // uint32_t modulatorModcod;
// CP_GetModulatorParams(sid, "modcod", &modulatorModcod); // CP_GetModulatorParams(sid, "modcod", &modulatorModcod);
demodulator_settings demod{}; demodulator_settings demod{};
#ifdef MODEM_IS_SCPC
ACM_parameters_serv_ acm{}; ACM_parameters_serv_ acm{};
DPDI_parmeters dpdi{}; DPDI_parmeters dpdi{};
#endif
buc_lnb_settings bucLnb{}; buc_lnb_settings bucLnb{};
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_GetModulatorSettings(sid, mod); logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetModulatorSettings()", CP_GetModulatorSettings(sid, mod));
CP_GetDemodulatorSettings(sid, demod); logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDemodulatorSettings()", CP_GetDemodulatorSettings(sid, demod));
CP_GetAcmParams(sid, &acm); #ifdef MODEM_IS_SCPC
CP_GetDpdiParams(sid, &dpdi); logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetAcmParams()", CP_GetAcmParams(sid, &acm));
CP_GetBUC_LNB_settings(sid, bucLnb); logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDpdiParams()", CP_GetDpdiParams(sid, &dpdi));
#endif
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(sid, bucLnb));
{ {
std::lock_guard lock2(this->settingsMutex); std::lock_guard lock2(this->settingsMutex);
this->modSettings = mod; this->modSettings = mod;
this->demodSettings = demod; this->demodSettings = demod;
#ifdef MODEM_IS_SCPC
this->acmSettings = acm; this->acmSettings = acm;
this->dpdiSettings = dpdi; this->dpdiSettings = dpdi;
#endif
this->bucLnbSettings = bucLnb; this->bucLnbSettings = bucLnb;
} }
} }
@@ -176,15 +195,15 @@ private:
TerminalNetworkSettings s; TerminalNetworkSettings s;
std::string tmp; std::string tmp;
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_GetNetwork(sid, "addr", &tmp); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &tmp));
s.managementIp = tmp + "/"; s.managementIp = tmp + "/";
tmp.clear(); 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(); CP_GetNetwork(sid, "gateway", &s.managementGateway); s.managementGateway = tmp; tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway)); s.managementGateway = tmp;
tmp.clear(); CP_GetNetwork(sid, "mode", &tmp); tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp));
if (tmp == "tun") { if (tmp == "tun") {
s.mode = "l3"; s.mode = "l3";
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.mode = "l2";
@@ -201,7 +220,7 @@ private:
void updateQos() { void updateQos() {
bool tmp1; std::string tmp2; bool tmp1; std::string tmp2;
std::scoped_lock lock{this->cpApiMutex}; std::scoped_lock lock{this->cpApiMutex};
CP_GetQoSSettings(this->sid, tmp2, tmp1); logCpApiError("api_driver::TerminalApiDaemon::updateQos()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
{ {
std::lock_guard lock2(this->qosSettingsMutex); std::lock_guard lock2(this->qosSettingsMutex);
this->qosEnabled = tmp1; this->qosEnabled = tmp1;
@@ -209,9 +228,52 @@ private:
} }
} }
void connectToApi() {
{
std::lock_guard _lock(this->stateMutex);
this->deviceInitState = "Not connected to API";
}
unsigned int access{};
for (int connectAttempt = 0;; connectAttempt++) {
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): Try to connect api (attempt " << connectAttempt << ")...";
auto res = CP_Login("admin", "pass", &sid, &access);
logCpApiError(R"(api_driver::TerminalApiDaemon::connectToApi()->CP_Login("admin", "pass"))", res);
if (res != OK) {
boost::this_thread::sleep_for(boost::chrono::duration(boost::chrono::milliseconds(1000)));
} else {
break;
}
}
std::string tmp;
logCpApiError("api_driver::TerminalApiDaemon::run()->CP_GetDmaDebug(status_init)", CP_GetDmaDebug(sid, "status_init", &tmp));
{
std::lock_guard _lock(this->stateMutex);
this->deviceInitState = tmp;
}
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): Success connect!";
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): API status: " << tmp;
TerminalFirmwareVersion f;
logCpApiError("api_driver::TerminalApiDaemon::connectToApi()->CP_GetNetwork(version)", CP_GetNetwork(sid, "version", &f.version));
logCpApiError("api_driver::TerminalApiDaemon::connectToApi()->CP_GetNetwork(chip_id)", CP_GetNetwork(sid, "chip_id", &f.modemId));
rtrim(f.modemId);
logCpApiError("api_driver::TerminalApiDaemon::connectToApi()->CP_GetNetwork(serial)", CP_GetNetwork(sid, "serial", &f.modemSn));
logCpApiError("api_driver::TerminalApiDaemon::connectToApi()->CP_GetNetwork(mac_eth0)", CP_GetNetwork(sid, "mac_eth0", &f.macMang));
logCpApiError("api_driver::TerminalApiDaemon::connectToApi()->CP_GetNetwork(mac_eth1)", CP_GetNetwork(sid, "mac_eth1", &f.macData));
{
std::lock_guard _lock(this->firmwareMutex);
this->firmware = f;
}
this->lastCpError = OK;
}
void run() { void run() {
// это демон, который в бесконечном цикле опрашивает API // это демон, который в бесконечном цикле опрашивает API
updateFirmwareSettings(); this->connectToApi();
struct IntervalUpdate_t { struct IntervalUpdate_t {
int64_t lastUpdate; int64_t lastUpdate;
@@ -273,6 +335,12 @@ private:
}; };
while (true) { while (true) {
if (this->lastCpError == ERROR || this->lastCpError == TIMEOUT) {
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::run(): close current daemon session caused error " << this->lastCpError;
CP_Logout(this->sid);
this->connectToApi();
}
int64_t sleepTime = 60000; // минута по-умолчанию int64_t sleepTime = 60000; // минута по-умолчанию
auto now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count(); auto now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
for (auto& u: updaters) { for (auto& u: updaters) {
@@ -291,20 +359,22 @@ private:
} }
} }
std::shared_mutex firmwareMutex;
TerminalFirmwareVersion firmware;
std::shared_mutex stateMutex; std::shared_mutex stateMutex;
modulator_state modState{}; modulator_state modState{};
demodulator_state demodState{}; demodulator_state demodState{};
device_state devState{}; device_state devState{};
std::string deviceInitState;
#ifdef MODEM_IS_SCPC
CinC_state cincState{}; CinC_state cincState{};
#endif
std::shared_mutex settingsMutex; std::shared_mutex settingsMutex;
modulator_settings modSettings{}; modulator_settings modSettings{};
demodulator_settings demodSettings{}; demodulator_settings demodSettings{};
#ifdef MODEM_IS_SCPC
ACM_parameters_serv_ acmSettings{}; ACM_parameters_serv_ acmSettings{};
DPDI_parmeters dpdiSettings{}; DPDI_parmeters dpdiSettings{};
#endif
buc_lnb_settings bucLnbSettings{}; buc_lnb_settings bucLnbSettings{};
std::shared_mutex networkSettingsMutex; std::shared_mutex networkSettingsMutex;
@@ -314,15 +384,24 @@ private:
bool qosEnabled; bool qosEnabled;
std::string qosClassesJson; std::string qosClassesJson;
std::shared_mutex firmwareMutex;
TerminalFirmwareVersion firmware;
public: public:
std::mutex cpApiMutex; std::mutex cpApiMutex;
TSID sid; TSID sid;
boost::thread daemon; boost::thread daemon;
explicit TerminalApiDaemon(TSID sid): qosEnabled(false), sid(sid), daemon([this]() { this->run(); }) { explicit TerminalApiDaemon(): deviceInitState("Not connected to API"), qosEnabled(false), sid(0), daemon([this]() { this->run(); }) {
this->qosClassesJson = DEFAULT_QOS_CLASSES; this->qosClassesJson = DEFAULT_QOS_CLASSES;
} }
std::string getDeviceInitState() {
std::shared_lock lock(this->stateMutex);
return this->deviceInitState;
}
#ifdef MODEM_IS_SCPC
/** /**
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. * Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
* @param mod статистика модулятра * @param mod статистика модулятра
@@ -339,10 +418,27 @@ public:
if (cinc) { *cinc = this->cincState; } if (cinc) { *cinc = this->cincState; }
} }
} }
#else
/**
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
* @param mod статистика модулятра
* @param demod статистика демодулятора
* @param dev статистика устройства (температуры)
*/
void getState(modulator_state* mod, demodulator_state* demod, device_state* dev) {
if (mod != nullptr || demod != nullptr || dev != nullptr) {
std::shared_lock lock(this->stateMutex);
if (mod) { *mod = this->modState; }
if (demod) { *demod = this->demodState; }
if (dev) { *dev = this->devState; }
}
}
#endif
/** /**
* Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. * Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
*/ */
#ifdef MODEM_IS_SCPC
void getSettings(modulator_settings* mod, demodulator_settings* demod, ACM_parameters_serv_* acm, DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) { void getSettings(modulator_settings* mod, demodulator_settings* demod, ACM_parameters_serv_* acm, DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) {
if (mod || demod || acm || dpdi || bucLnb) { if (mod || demod || acm || dpdi || bucLnb) {
std::shared_lock lock(this->settingsMutex); std::shared_lock lock(this->settingsMutex);
@@ -353,11 +449,23 @@ public:
if (bucLnb) { *bucLnb = this->bucLnbSettings; } if (bucLnb) { *bucLnb = this->bucLnbSettings; }
} }
} }
#else
void getSettings(modulator_settings* mod, demodulator_settings* demod, buc_lnb_settings* bucLnb) {
if (mod || demod || bucLnb) {
std::shared_lock lock(this->settingsMutex);
if (mod) { *mod = this->modSettings; }
if (demod) { *demod = this->demodSettings; }
if (bucLnb) { *bucLnb = this->bucLnbSettings; }
}
}
#endif
#ifdef MODEM_IS_SCPC
bool getIsCinC() { bool getIsCinC() {
std::shared_lock lock(this->settingsMutex); std::shared_lock lock(this->settingsMutex);
return modSettings.is_cinc; return modSettings.is_cinc;
} }
#endif
void getNetworkSettings(TerminalNetworkSettings& dest) { void getNetworkSettings(TerminalNetworkSettings& dest) {
std::shared_lock lock(this->networkSettingsMutex); std::shared_lock lock(this->networkSettingsMutex);
@@ -370,21 +478,17 @@ public:
json = this->qosClassesJson; json = this->qosClassesJson;
} }
void getFirmwareVersion(TerminalFirmwareVersion& fw) { #ifdef MODEM_IS_SCPC
std::lock_guard lock2(this->firmwareMutex);
fw = this->firmware;
}
void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, ACM_parameters_serv_& acm, bool readback = true) { void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, ACM_parameters_serv_& acm, bool readback = true) {
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetModulatorSettings(this->sid, mod); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetModulatorSettings()", CP_SetModulatorSettings(this->sid, mod));
CP_SetDemodulatorSettings(this->sid, demod); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDemodulatorSettings()", CP_SetDemodulatorSettings(this->sid, demod));
CP_SetAcmParams(this->sid, acm); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetAcmParams()", CP_SetAcmParams(this->sid, acm));
if (readback) { if (readback) {
CP_GetModulatorSettings(this->sid, mod); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetModulatorSettings()", CP_GetModulatorSettings(this->sid, mod));
CP_GetDemodulatorSettings(this->sid, demod); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetDemodulatorSettings()", CP_GetDemodulatorSettings(this->sid, demod));
CP_GetAcmParams(this->sid, &acm); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetAcmParams()", CP_GetAcmParams(this->sid, &acm));
{ {
std::lock_guard lock2{this->settingsMutex}; std::lock_guard lock2{this->settingsMutex};
this->modSettings = mod; this->modSettings = mod;
@@ -392,51 +496,71 @@ public:
this->acmSettings = acm; this->acmSettings = acm;
} }
} }
CP_SetDmaDebug(sid, "save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
} }
#else
void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, bool readback = true) {
std::lock_guard lock(this->cpApiMutex);
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetModulatorSettings()", CP_SetModulatorSettings(this->sid, mod));
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDemodulatorSettings()", CP_SetDemodulatorSettings(this->sid, demod));
if (readback) {
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetModulatorSettings()", CP_GetModulatorSettings(this->sid, mod));
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetDemodulatorSettings()", CP_GetDemodulatorSettings(this->sid, demod));
{
std::lock_guard lock2{this->settingsMutex};
this->modSettings = mod;
this->demodSettings = demod;
}
}
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
}
#endif
#ifdef MODEM_IS_SCPC
void setSettingsCinc(DPDI_parmeters& s, bool readback = true) { void setSettingsCinc(DPDI_parmeters& s, bool readback = true) {
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetDpdiParams(sid, s); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDpdiParams()", CP_SetDpdiParams(sid, s));
if (readback) { if (readback) {
CP_GetDpdiParams(this->sid, &s); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_GetDpdiParams()", CP_GetDpdiParams(this->sid, &s));
{ {
std::lock_guard lock2{this->settingsMutex}; std::lock_guard lock2{this->settingsMutex};
this->dpdiSettings = s; this->dpdiSettings = s;
} }
} }
CP_SetDmaDebug(sid, "save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
} }
#endif
void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true) { void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true) {
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetBUC_LNB_settings(this->sid, bucLnb); logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetBUC_LNB_settings()", CP_SetBUC_LNB_settings(this->sid, bucLnb));
if (readback) { if (readback) {
CP_GetBUC_LNB_settings(this->sid, bucLnb); logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(this->sid, bucLnb));
{ {
std::lock_guard lock2{this->settingsMutex}; std::lock_guard lock2{this->settingsMutex};
this->bucLnbSettings = bucLnb; this->bucLnbSettings = bucLnb;
} }
} }
CP_SetDmaDebug(sid, "save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
} }
void setQosSettings(bool enabled, const std::string& str, bool readback = true) { void setQosSettings(bool enabled, const std::string& str, bool readback = true) {
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetQoSSettings(this->sid, str, enabled); logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetQoSSettings()", CP_SetQoSSettings(this->sid, str, enabled));
if (readback) { if (readback) {
bool tmp1; std::string tmp2; bool tmp1; std::string tmp2;
CP_GetQoSSettings(this->sid, tmp2, tmp1); logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
{ {
std::lock_guard lock2(this->qosSettingsMutex); std::lock_guard lock2(this->qosSettingsMutex);
this->qosEnabled = tmp1; this->qosEnabled = tmp1;
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2; this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
} }
} }
CP_SetDmaDebug(sid, "save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
} }
void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) { void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) {
@@ -448,13 +572,13 @@ public:
else { throw std::runtime_error("invalid mode"); } else { throw std::runtime_error("invalid mode"); }
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetNetwork(sid, "mode", isL2 ? "tap" : "tun"); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mode)", CP_SetNetwork(sid, "mode", isL2 ? "tap" : "tun"));
CP_SetNetwork(sid, "addr", mang.first.c_str()); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(addr)", CP_SetNetwork(sid, "addr", mang.first.c_str()));
CP_SetNetwork(sid, "mask", mang.second.c_str()); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mask)", CP_SetNetwork(sid, "mask", mang.second.c_str()));
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 (!isL2) {
CP_SetNetwork(sid, "data_addr", data.first.c_str()); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(data_addr)", CP_SetNetwork(sid, "data_addr", data.first.c_str()));
// TODO маска не устанавливается, потому что в API этого нет // TODO маска не устанавливается, потому что в API этого нет
} }
// TODO MTU не устанавливается, потому что в API этого нет // TODO MTU не устанавливается, потому что в API этого нет
@@ -463,15 +587,15 @@ public:
std::string tmp; std::string tmp;
s.loadDefaults(); s.loadDefaults();
s.managementIp.clear(); s.managementIp.clear();
CP_GetNetwork(sid, "addr", &s.managementIp); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp));
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));
CP_GetNetwork(sid, "gateway", &s.managementGateway); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway));
tmp.clear(); CP_GetNetwork(sid, "mode", &tmp); tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp));
if (tmp == "tun") { if (tmp == "tun") {
s.mode = "l3"; s.mode = "l3";
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.mode = "l2";
s.dataIp = "0.0.0.0/24"; s.dataIp = "0.0.0.0/24";
@@ -482,20 +606,25 @@ public:
this->networkSettings = s; this->networkSettings = s;
} }
} }
CP_SetDmaDebug(sid, "save_config", ""); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
}
TerminalFirmwareVersion getFirmware() {
std::shared_lock lock(this->firmwareMutex);
return firmware;
} }
void resetPacketStatistics() { void resetPacketStatistics() {
std::string tmp; std::string tmp;
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_GetDmaDebug(sid, "reset_cnt_rx", &tmp); logCpApiError("api_driver::TerminalApiDaemon::resetPacketStatistics()->CP_GetDmaDebug(reset_cnt_rx)", CP_GetDmaDebug(sid, "reset_cnt_rx", &tmp));
} }
void resetDefaultSettings() { void resetDefaultSettings() {
std::lock_guard lock(this->cpApiMutex); std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", " "); logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
CP_SetDmaDebug(sid, "default_params", ""); logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(default_params)", CP_SetDmaDebug(sid, "default_params", ""));
CP_SetDmaDebug(sid, "save_config", " "); logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
} }
~TerminalApiDaemon() { ~TerminalApiDaemon() {
@@ -509,17 +638,11 @@ public:
}; };
api_driver::ApiDriver::ApiDriver() { api_driver::ApiDriver::ApiDriver() = default;
}
void api_driver::ApiDriver::startDaemon() { void api_driver::ApiDriver::startDaemon() {
if (daemon == nullptr) { if (daemon == nullptr) {
TSID sid{}; daemon = std::make_unique<TerminalApiDaemon>();
unsigned int access{};
CP_Login("admin", "pass", &sid, &access);
CP_GetDmaDebug(sid, "status_init", &deviceInitState);
daemon = std::make_unique<TerminalApiDaemon>(sid);
BOOST_LOG_TRIVIAL(info) << "api_driver::ApiDriver::startDaemon(): API daemon succes started!"; BOOST_LOG_TRIVIAL(info) << "api_driver::ApiDriver::startDaemon(): API daemon succes started!";
} }
} }
@@ -545,7 +668,7 @@ void writeDouble(std::ostream& out, double value, int prec = 2) {
out << std::fixed << std::setprecision(prec) << value; out << std::fixed << std::setprecision(prec) << value;
} }
} }
#ifdef MODEM_IS_SCPC
double translateCoordinates(uint8_t deg, uint8_t min) { double translateCoordinates(uint8_t deg, uint8_t min) {
return static_cast<double>(deg) + static_cast<double>(min) / 60; return static_cast<double>(deg) + static_cast<double>(min) / 60;
} }
@@ -556,6 +679,7 @@ std::tuple<uint8_t, uint8_t> translateCoordinates(double abs) {
auto min = static_cast<uint8_t>(min_double); auto min = static_cast<uint8_t>(min_double);
return std::make_tuple(deg, min); return std::make_tuple(deg, min);
} }
#endif
std::string api_driver::ApiDriver::loadTerminalState() const { std::string api_driver::ApiDriver::loadTerminalState() const {
@@ -564,34 +688,42 @@ std::string api_driver::ApiDriver::loadTerminalState() const {
} }
std::stringstream result; std::stringstream result;
result << "{\n\"initState\":" << buildEscapedString(this->deviceInitState); result << "{\n\"initState\":" << buildEscapedString(daemon->getDeviceInitState());
modulator_state modulator{}; modulator_state modulator{};
demodulator_state demodulator{}; demodulator_state demodulator{};
device_state device{}; device_state device{};
#ifdef MODEM_IS_SCPC
CinC_state cinc{}; CinC_state cinc{};
daemon->getState(&modulator, &demodulator, &device, &cinc); daemon->getState(&modulator, &demodulator, &device, &cinc);
const bool isCinC = this->daemon->getIsCinC(); const bool isCinC = this->daemon->getIsCinC();
#else
daemon->getState(&modulator, &demodulator, &device);
#endif
#ifdef MODEM_IS_SCPC
result << ",\"isCinC\":" << boolAsStr(isCinC); result << ",\"isCinC\":" << boolAsStr(isCinC);
#endif
// формируем структуру для TX // формируем структуру для TX
result << ",\n\"tx.state\":" << boolAsStr(modulator.is_tx_on); result << ",\n\"tx.state\":" << boolAsStr(modulator.is_tx_on);
result << ",\"tx.modcod\":" << modulator.modcod; result << ",\"tx.modcod\":" << modulator.modcod;
#ifdef MODEM_IS_SCPC
result << ",\"tx.snr\":"; writeDouble(result, modulator.snr_remote); result << ",\"tx.snr\":"; writeDouble(result, modulator.snr_remote);
if (modulator.is_short) { if (modulator.is_short) { result << R"(,"tx.frameSizeNormal":false)"; }
result << R"(,"tx.frameSizeNormal":false)"; else { result << R"(,"tx.frameSizeNormal":true)"; }
} else {
result << R"(,"tx.frameSizeNormal":true)";
}
if (modulator.is_pilots) { if (modulator.is_pilots) { result << R"(,"tx.isPilots":true)"; }
result << R"(,"tx.isPilots":true)"; else { result << R"(,"tx.isPilots":false)"; }
} else { #else
result << R"(,"tx.isPilots":false)"; {
modulator_settings modSet{};
daemon->getSettings(&modSet, nullptr, nullptr);
result << ",\"tx.centerFreq\":"; writeDouble(result, modSet.central_freq_in_kGz);
result << ",\"tx.symSpeed\":"; writeDouble(result, (static_cast<double>(modSet.baudrate) / 1000.0));
} }
#endif
result << ",\"tx.speedOnTxKbit\":"; writeDouble(result, static_cast<double>(modulator.speed_in_bytes_tx) / 128.0); result << ",\"tx.speedOnTxKbit\":"; writeDouble(result, static_cast<double>(modulator.speed_in_bytes_tx) / 128.0);
result << ",\"tx.speedOnIifKbit\":"; writeDouble(result, (static_cast<double>(modulator.speed_in_bytes_tx_iface) / 128.0)); result << ",\"tx.speedOnIifKbit\":"; writeDouble(result, (static_cast<double>(modulator.speed_in_bytes_tx_iface) / 128.0));
@@ -629,6 +761,7 @@ std::string api_driver::ApiDriver::loadTerminalState() const {
result << ",\"rx.packetsBad\":" << demodulator.packet_bad_cnt; result << ",\"rx.packetsBad\":" << demodulator.packet_bad_cnt;
result << ",\"rx.packetsDummy\":" << demodulator.dummy_cnt; result << ",\"rx.packetsDummy\":" << demodulator.dummy_cnt;
#ifdef MODEM_IS_SCPC
// формируем структуру для CinC // формируем структуру для CinC
if (isCinC) { if (isCinC) {
if (modulator.is_tx_on) { if (modulator.is_tx_on) {
@@ -649,6 +782,7 @@ std::string api_driver::ApiDriver::loadTerminalState() const {
} else { } else {
result << R"(,"cinc.correlator":null)"; result << R"(,"cinc.correlator":null)";
} }
#endif
// структура температур девайса // структура температур девайса
result << ",\n\"device.adrv\":"; writeDouble(result, device.adrv_temp, 1); result << ",\n\"device.adrv\":"; writeDouble(result, device.adrv_temp, 1);
@@ -672,14 +806,19 @@ std::string api_driver::ApiDriver::loadSettings() const {
modulator_settings modSettings{}; modulator_settings modSettings{};
demodulator_settings demodSettings{}; demodulator_settings demodSettings{};
ACM_parameters_serv_ acmSettings{};
DPDI_parmeters dpdiSettings{};
buc_lnb_settings bucLnb{}; buc_lnb_settings bucLnb{};
TerminalNetworkSettings network; TerminalNetworkSettings network;
#ifdef MODEM_IS_SCPC
ACM_parameters_serv_ acmSettings{};
DPDI_parmeters dpdiSettings{};
daemon->getSettings(&modSettings, &demodSettings, &acmSettings, &dpdiSettings, &bucLnb); daemon->getSettings(&modSettings, &demodSettings, &acmSettings, &dpdiSettings, &bucLnb);
#else
daemon->getSettings(&modSettings, &demodSettings, &bucLnb);
#endif
daemon->getNetworkSettings(network); daemon->getNetworkSettings(network);
std::stringstream result; std::stringstream result;
#ifdef MODEM_IS_SCPC
result << "{\n\"general.isCinC\":" << boolAsStr(modSettings.is_cinc); result << "{\n\"general.isCinC\":" << boolAsStr(modSettings.is_cinc);
result << ",\"general.txEn\":" << boolAsStr(modSettings.tx_is_on); result << ",\"general.txEn\":" << boolAsStr(modSettings.tx_is_on);
result << ",\"general.modulatorMode\":" << (modSettings.is_carrier ? "\"normal\"" : "\"test\""); result << ",\"general.modulatorMode\":" << (modSettings.is_carrier ? "\"normal\"" : "\"test\"");
@@ -690,7 +829,7 @@ std::string api_driver::ApiDriver::loadSettings() const {
result << ",\"tx.cymRate\":" << modSettings.baudrate; result << ",\"tx.cymRate\":" << modSettings.baudrate;
result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3); result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3);
result << ",\"dvbs2.frameSizeNormal\":" << boolAsStr(!(modSettings.modcod_tx & 2)); result << ",\"dvbs2.frameSizeNormal\":" << boolAsStr(!(modSettings.modcod_tx & 2));
result << ",\"dvbs2.ccm_modcod\":" << (modSettings.modcod_tx >> 4); result << ",\"dvbs2.ccm_modcod\":" << (modSettings.modcod_tx >> 2);
// result << ",\"dvbs2.isPilots\":" << "null"; // result << ",\"dvbs2.isPilots\":" << "null";
result << ",\n\"dvbs2.isAcm\":" << boolAsStr(acmSettings.enable); result << ",\n\"dvbs2.isAcm\":" << boolAsStr(acmSettings.enable);
@@ -718,6 +857,20 @@ std::string api_driver::ApiDriver::loadSettings() const {
result << ",\"cinc.position.satelliteLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_sattelite_grad, dpdiSettings.longitude_sattelite_minute), 6); result << ",\"cinc.position.satelliteLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_sattelite_grad, dpdiSettings.longitude_sattelite_minute), 6);
result << ",\"cinc.delayMin\":" << dpdiSettings.min_delay; result << ",\"cinc.delayMin\":" << dpdiSettings.min_delay;
result << ",\"cinc.delayMax\":" << dpdiSettings.max_delay; result << ",\"cinc.delayMax\":" << 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
result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc); result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc);
switch (bucLnb.buc) { switch (bucLnb.buc) {
@@ -760,9 +913,8 @@ std::string api_driver::ApiDriver::loadFirmwareVersion() const {
return R"({"error": "api daemon not started!"})"; return R"({"error": "api daemon not started!"})";
} }
TerminalFirmwareVersion firmware;
daemon->getFirmwareVersion(firmware);
std::stringstream result; std::stringstream result;
auto firmware = daemon->getFirmware();
result << "{\n\"fw.version\":" << buildEscapedString(firmware.version); result << "{\n\"fw.version\":" << buildEscapedString(firmware.version);
result << ",\"fw.modemId\":" << buildEscapedString(firmware.modemId); result << ",\"fw.modemId\":" << buildEscapedString(firmware.modemId);
result << ",\"fw.modemSn\":" << buildEscapedString(firmware.modemSn); result << ",\"fw.modemSn\":" << buildEscapedString(firmware.modemSn);
@@ -775,9 +927,12 @@ std::string api_driver::ApiDriver::loadFirmwareVersion() const {
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
ACM_parameters_serv_ acm{}; ACM_parameters_serv_ acm{};
#endif
// для модулятора // для модулятора
#ifdef MODEM_IS_SCPC
mod.is_cinc = pt.get<bool>(json_path("general.isCinC", '/')); mod.is_cinc = pt.get<bool>(json_path("general.isCinC", '/'));
mod.tx_is_on = pt.get<bool>(json_path("general.txEn", '/')); mod.tx_is_on = pt.get<bool>(json_path("general.txEn", '/'));
auto tmp = pt.get<std::string>(json_path("general.modulatorMode", '/')); auto tmp = pt.get<std::string>(json_path("general.modulatorMode", '/'));
@@ -791,11 +946,22 @@ void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
mod.baudrate = pt.get<uint32_t>(json_path("tx.cymRate", '/')); mod.baudrate = pt.get<uint32_t>(json_path("tx.cymRate", '/'));
mod.central_freq_in_kGz = pt.get<double>(json_path("tx.centerFreq", '/')); mod.central_freq_in_kGz = pt.get<double>(json_path("tx.centerFreq", '/'));
const bool acmIsShortFrame = pt.get<bool>(json_path("dvbs2.frameSizeNormal", '/')); const bool acmIsShortFrame = !pt.get<bool>(json_path("dvbs2.frameSizeNormal", '/'));
mod.modcod_tx = (pt.get<uint32_t>(json_path("dvbs2.ccm_modcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0); mod.modcod_tx = (pt.get<uint32_t>(json_path("dvbs2.ccm_modcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
#else
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
// демодулятор // демодулятор
#ifdef MODEM_IS_SCPC
tmp = pt.get<std::string>(json_path("rx.gainMode", '/')); tmp = pt.get<std::string>(json_path("rx.gainMode", '/'));
#else
auto tmp = pt.get<std::string>(json_path("rx.gainMode", '/'));
#endif
if (tmp == "auto") { demod.is_aru_on = true; } if (tmp == "auto") { demod.is_aru_on = true; }
else if (tmp == "manual") { demod.is_aru_on = false; } else if (tmp == "manual") { demod.is_aru_on = false; }
else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong gain mode: " + tmp); } else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong gain mode: " + tmp); }
@@ -805,6 +971,7 @@ void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
demod.rollof = pt.get<double>(json_path("rx.rolloff", '/')) / 100.0; demod.rollof = pt.get<double>(json_path("rx.rolloff", '/')) / 100.0;
demod.central_freq_in_kGz = pt.get<double>(json_path("rx.centerFreq", '/')); demod.central_freq_in_kGz = pt.get<double>(json_path("rx.centerFreq", '/'));
#ifdef MODEM_IS_SCPC
// ACM // ACM
acm.enable = pt.get<bool>(json_path("dvbs2.isAcm", '/')); acm.enable = pt.get<bool>(json_path("dvbs2.isAcm", '/'));
acm.max_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_maxModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0); acm.max_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_maxModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
@@ -817,8 +984,12 @@ void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
acm.snr_treashold = pt.get<double>(json_path("acm.requiredSnr", '/')); // требуемый ОСШ acm.snr_treashold = pt.get<double>(json_path("acm.requiredSnr", '/')); // требуемый ОСШ
daemon->setSettingsRxTx(mod, demod, acm); daemon->setSettingsRxTx(mod, demod, acm);
#else
daemon->setSettingsRxTx(mod, demod);
#endif
} }
#ifdef MODEM_IS_SCPC
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{};
@@ -845,8 +1016,11 @@ void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) {
s.max_delay = pt.get<uint32_t>(json_path("cinc.delayMax", '/')); s.max_delay = pt.get<uint32_t>(json_path("cinc.delayMax", '/'));
s.min_delay = pt.get<uint32_t>(json_path("cinc.delayMin", '/')); s.min_delay = pt.get<uint32_t>(json_path("cinc.delayMin", '/'));
s.freq_offset = pt.get<uint32_t>(json_path("cinc.searchBandwidth", '/'));
this->daemon->setSettingsCinc(s); this->daemon->setSettingsCinc(s);
} }
#endif
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{};
@@ -865,7 +1039,9 @@ void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) {
tmp = pt.get<int>(json_path("buc.powering", '/')); 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
case 48: s.buc = voltage_buc::_48V; break; case 48: s.buc = voltage_buc::_48V; break;
#endif
case 0: case 0:
default: default:
s.lnb = voltage_lnb::DISABLE; s.lnb = voltage_lnb::DISABLE;
@@ -917,4 +1093,42 @@ void api_driver::ApiDriver::executeInApi(const std::function<void(TSID sid)>& ca
} }
} }
std::string api_driver::ApiDriver::loadSysInfo() {
std::stringstream result;
struct sysinfo info{};
sysinfo(&info);
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* Swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
};
result << "{\n\"uptime\":" << info.uptime;
result << ",\"load1min\":" << info.loads[0];
result << ",\"load5min\":" << info.loads[1];
result << ",\"load15min\":" << info.loads[2];
result << ",\"totalram\":" << info.totalram;
result << ",\"freeram\":" << info.freeram;
result << ",\"sharedram\":" << info.sharedram;
result << ",\"bufferram\":" << info.bufferram;
result << ",\"totalswap\":" << info.totalswap;
result << ",\"freeswap\":" << info.freeswap;
result << ",\"procs\":" << static_cast<long>(info.procs);
result << ",\"totalhigh\":" << info.totalhigh;
result << ",\"freehigh\":" << info.freehigh;
result << ",\"mem_unit\":" << info.mem_unit;
result << "\n}";
return result.str();
}
api_driver::ApiDriver::~ApiDriver() = default; api_driver::ApiDriver::~ApiDriver() = default;

View File

@@ -46,11 +46,12 @@ namespace api_driver {
*/ */
void setRxTxSettings(boost::property_tree::ptree &pt); void setRxTxSettings(boost::property_tree::ptree &pt);
#ifdef MODEM_IS_SCPC
/** /**
* Установить настройки CinC, readback можно получить используя loadTerminalState. * Установить настройки CinC, readback можно получить используя loadTerminalState.
*/ */
void setCincSettings(boost::property_tree::ptree &pt); void setCincSettings(boost::property_tree::ptree &pt);
#endif
/** /**
* Установить настройки BUC и LNB, readback можно получить используя loadTerminalState. * Установить настройки BUC и LNB, readback можно получить используя loadTerminalState.
*/ */
@@ -69,10 +70,11 @@ namespace api_driver {
void executeInApi(const std::function<void(TSID sid)>& callback); void executeInApi(const std::function<void(TSID sid)>& callback);
static std::string loadSysInfo();
~ApiDriver(); ~ApiDriver();
private: private:
std::string deviceInitState;
std::unique_ptr<TerminalApiDaemon> daemon; std::unique_ptr<TerminalApiDaemon> daemon;
}; };
} }

16
static/dev-params.json Normal file
View File

@@ -0,0 +1,16 @@
{
"params": [
{
"label": "Запись пакетов",
"name": "log_bool",
"widget": "checkbox",
"function": "DmaDebug"
},
{
"label": "Unused test",
"name": "log_bool",
"widget": "checkbox",
"function": "DmaDebug"
}
]
}

10
static/dev.html Normal file
View File

@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>

View File

@@ -7,7 +7,6 @@
} }
.tabs-btn { .tabs-btn {
text-decoration: none; text-decoration: none;
font-size: 18px;
border: none; border: none;
padding: 10px 25px; padding: 10px 25px;
text-align: center; text-align: center;
@@ -87,6 +86,7 @@
.settings-set-container th { .settings-set-container th {
text-align: left; text-align: left;
font-weight: normal;
padding-right: 1em; padding-right: 1em;
} }
.settings-set-container td { .settings-set-container td {

BIN
static/internet.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

View File

@@ -725,30 +725,30 @@
}; };
} }
/****************************************************************************** /******************************************************************************
Copyright (c) Microsoft Corporation. Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE. PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */ ***************************************************************************** */
var __assign = function() { var __assign = function() {
__assign = Object.assign || function __assign(t) { __assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) { for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i]; s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
} }
return t; return t;
}; };
return __assign.apply(this, arguments); return __assign.apply(this, arguments);
}; };
var uid$2 = 0; var uid$2 = 0;

1700
static/main-scpc.html Normal file

File diff suppressed because it is too large Load Diff

1351
static/main-tdma.html Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -53,6 +53,13 @@ body {
margin: 0.5em; margin: 0.5em;
} }
/* увеличение размера шрифтов */
* { font-size: large; }
h1 { font-size: xxx-large; }
h2 { font-size: xx-large; }
h3 { font-size: larger; }
/* ========== MAIN STYLES ========== */ /* ========== MAIN STYLES ========== */
.value-good { .value-good {