Compare commits
No commits in common. "3e38e77069604de9507563ff0b6bf1e0ac184ca1" and "17cdd692071bb22dd0d56a422dd22946112181b5" have entirely different histories.
3e38e77069
...
17cdd69207
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,7 +7,8 @@ dh.pem
|
||||
/web-action
|
||||
|
||||
# эти файлы после генерации должны быть перемещены в `/static`
|
||||
front-generator/main-*.html
|
||||
front-generator/main-scpc.html
|
||||
front-generator/main-tdma.html
|
||||
|
||||
# логи сервера в релизной версии
|
||||
http_server_*.log
|
||||
|
@ -1,8 +1,8 @@
|
||||
stages:
|
||||
- build
|
||||
- deploy
|
||||
|
||||
test for build:
|
||||
stage: build
|
||||
stage: deploy
|
||||
image: localhost:5000/cpp-test-universal:latest
|
||||
tags:
|
||||
- cpp-test-universal
|
||||
@ -13,14 +13,10 @@ test for build:
|
||||
- git submodule update
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=TDMA -B cmake-build-debug-tdma
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SCPC -B cmake-build-debug-scpc
|
||||
- cmake -DCMAKE_BUILD_TYPE=Debug -DMODEM_TYPE=SHPS -B cmake-build-debug-shps
|
||||
- cmake -DCMAKE_BUILD_TYPE=Release -DMODEM_TYPE=TDMA -B cmake-build-release-tdma
|
||||
- cmake -DCMAKE_BUILD_TYPE=Release -DMODEM_TYPE=SCPC -B cmake-build-release-scpc
|
||||
- cmake -DCMAKE_BUILD_TYPE=Release -DMODEM_TYPE=SHPS -B cmake-build-release-shps
|
||||
- cmake --build cmake-build-debug-tdma -j 4
|
||||
- cmake --build cmake-build-debug-scpc -j 4
|
||||
- cmake --build cmake-build-debug-shps -j 4
|
||||
- cmake --build cmake-build-release-tdma -j 4
|
||||
- cmake --build cmake-build-release-scpc -j 4
|
||||
- cmake --build cmake-build-release-shps -j 4
|
||||
|
||||
|
@ -21,11 +21,8 @@ if("${MODEM_TYPE}" STREQUAL "SCPC")
|
||||
elseif ("${MODEM_TYPE}" STREQUAL "TDMA")
|
||||
add_definitions(-DMODEM_IS_TDMA)
|
||||
message(STATUS "Selected TDMA modem")
|
||||
elseif ("${MODEM_TYPE}" STREQUAL "SHPS")
|
||||
add_definitions(-DMODEM_IS_SHPS)
|
||||
message(STATUS "Selected TDMA modem")
|
||||
else()
|
||||
message(FATAL_ERROR "You must set `MODEM_TYPE` \"SCPC\" or \"TDMA\" or \"SHPS\"!")
|
||||
message(FATAL_ERROR "You must set `MODEM_TYPE` \"SCPC\" or \"TDMA\"!")
|
||||
endif()
|
||||
|
||||
SET(PROJECT_GIT_REVISION "0")
|
||||
@ -57,12 +54,6 @@ add_subdirectory(dependencies/control_system_client)
|
||||
include_directories(src/)
|
||||
|
||||
add_executable(terminal-web-server
|
||||
src/api-driver/daemon.h
|
||||
src/api-driver/daemon.cpp
|
||||
src/api-driver/proxy.h
|
||||
src/api-driver/proxy.cpp
|
||||
src/api-driver/structs.h
|
||||
src/api-driver/structs.cpp
|
||||
src/server/mime_types.hpp
|
||||
src/server/mime_types.cpp
|
||||
src/server/request_parser.hpp
|
||||
@ -86,7 +77,6 @@ add_executable(terminal-web-server
|
||||
src/auth/utils.cpp
|
||||
src/auth/utils.h
|
||||
src/version.h
|
||||
src/api-driver/stricts-enable.h
|
||||
)
|
||||
|
||||
add_definitions(-DBOOST_LOG_DYN_LINK)
|
||||
|
@ -350,128 +350,6 @@
|
||||
{"name": "qos", "desc": "QoS"},
|
||||
{"name": "admin", "desc": "Администрирование"}
|
||||
]
|
||||
},
|
||||
"shps": {
|
||||
"modem_name": "ШПС Модем",
|
||||
"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": "checkbox", "label": "Автоматический запуск передатчика", "name": "txAutoStart"},
|
||||
{
|
||||
"widget": "select", "label": "Режим работы модулятора", "name": "txModulatorIsTest",
|
||||
"values": [{"label": "Нормальный", "value": "false"}, {"label": "Тест (CW)", "value": "true"}]
|
||||
},
|
||||
{
|
||||
"widget": "select", "label": "Входные данные", "name": "txIsTestInput",
|
||||
"values": [{"label": "Ethernet", "value": "false"}, {"label": "Тест", "value": "true"}]
|
||||
},
|
||||
{"widget": "h3", "label": "Параметры передачи"},
|
||||
{"widget": "number", "label": "Центральная частота, КГц", "name": "txCentralFreq", "min": 950000, "max": 6000000, "step": 0.01},
|
||||
{"widget": "number", "label": "Символьная скорость, Бод", "name": "txBaudrate", "min": 200000, "max": 54000000},
|
||||
{
|
||||
"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": "number", "label": "Коэф. расширения", "name": "txSpreadCoef", "max": 1000, "min": -1000, "step": 0.01},
|
||||
{
|
||||
"widget": "select", "label": "Номер последовательности Голда", "name": "txGoldan",
|
||||
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
|
||||
},
|
||||
{"widget": "number", "label": "Ослабление, дБ", "name": "txAttenuation", "max": 0, "min": -40, "step": 0.25}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widget": "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": "watch-expr", "label": "Текущее усиление", "expr": "paramRxtx.rxManualGain", "v_show": "paramRxtx.rxAgcEn === true"},
|
||||
{"widget": "checkbox", "label": "Инверсия спектра", "name": "rxSpectrumInversion"},
|
||||
{"widget": "number", "label": "Центральная частота, КГц", "name": "rxCentralFreq", "min": 950000, "max": 6000000, "step": 0.01},
|
||||
{"widget": "number", "label": "Символьная скорость, Бод", "name": "rxBaudrate", "min": 200000, "max": 54000000},
|
||||
{
|
||||
"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": "number", "label": "Коэф. расширения", "name": "rxSpreadCoef", "max": 1000, "min": -1000, "step": 0.01},
|
||||
{
|
||||
"widget": "select", "label": "Номер последовательности Голда", "name": "rxGoldan",
|
||||
"values": [{"label": "0", "value": "0"}, {"label": "1", "value": "1"}]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"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"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"tabs": [
|
||||
{"name": "monitoring", "desc": "Мониторинг"},
|
||||
{"name": "setup", "desc": "Настройки"},
|
||||
{"name": "admin", "desc": "Администрирование"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
@ -1,472 +0,0 @@
|
||||
//
|
||||
// Created by vlad on 03.04.2025.
|
||||
//
|
||||
|
||||
#include "daemon.h"
|
||||
|
||||
#include <boost/thread/pthread/thread_data.hpp>
|
||||
|
||||
|
||||
void api_driver::TerminalApiDaemon::connectToApi() {
|
||||
{
|
||||
std::lock_guard _lock(this->stateMutex);
|
||||
this->state.fInitState = "Not connected to API";
|
||||
}
|
||||
#if defined(MODEM_IS_SCPC) || defined(MODEM_IS_TDMA)
|
||||
{
|
||||
std::lock_guard _lock(this->settingsMutex);
|
||||
this->settingsNetwork.loadDefaults();
|
||||
}
|
||||
#endif
|
||||
|
||||
for (int connectAttempt = 0;; connectAttempt++) {
|
||||
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): Try to connect api (attempt " << connectAttempt << ")...";
|
||||
try {
|
||||
cp.connect();
|
||||
|
||||
std::string tmp = cp.getDmaDebug("status_init");
|
||||
{
|
||||
std::lock_guard _lock(this->stateMutex);
|
||||
this->state.fInitState = tmp;
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): Success connect!";
|
||||
BOOST_LOG_TRIVIAL(info) << "api_driver::TerminalApiDaemon::connectToApi(): API status: " << tmp;
|
||||
|
||||
obj::TerminalFirmwareVersion f;
|
||||
f.load(cp);
|
||||
|
||||
{
|
||||
std::lock_guard _lock(this->firmwareMutex);
|
||||
this->firmware = f;
|
||||
}
|
||||
|
||||
cp.lastCpError = OK;
|
||||
break;
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::connectToApi(): connect error " << e.what();
|
||||
}
|
||||
boost::this_thread::sleep_for(boost::chrono::duration(boost::chrono::milliseconds(1000)));
|
||||
}
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::run() {
|
||||
// это демон, который в бесконечном цикле опрашивает API
|
||||
this->connectToApi();
|
||||
|
||||
struct {
|
||||
obj::CpUpdatebleObject* u;
|
||||
std::function<void ()> c;
|
||||
} updaters[] = {
|
||||
#if API_OBJECT_NETWORK_SETTINGS_ENABLE
|
||||
// обновление логов
|
||||
{.u = &statsLogs, .c = [this]() {
|
||||
try {
|
||||
{
|
||||
std::lock_guard _alock(this->cpApiMutex);
|
||||
this->statsLogs.updateCallback(cp);
|
||||
}
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon->statsLogs.putItem(): success write statistics state to log!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon->statsLogs.putItem() failed to log: " << e.what();
|
||||
}
|
||||
}},
|
||||
#endif
|
||||
// обновление статистики
|
||||
{.u = state, .c = [this]() {
|
||||
try {
|
||||
std::lock_guard _alock(this->cpApiMutex);
|
||||
std::lock_guard _slock(this->stateMutex);
|
||||
state.updateCallback(cp);
|
||||
stateDev.updateCallback(cp);
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateState(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateState(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша настроек
|
||||
{.lastUpdate = 0, .periodMs = CACHE_SETTINGS_UPDATE_MS, .c = [this]() {
|
||||
try {
|
||||
this->updateSettings();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateSettings(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateSettings(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша настроек сети (делается отдельно)
|
||||
{.lastUpdate = 0, .periodMs = CACHE_SETTINGS_UPDATE_MS, .c = [this]() {
|
||||
try {
|
||||
this->updateNetworkSettings();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateNetworkSettings(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateNetworkSettings(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша QoS
|
||||
{.lastUpdate = 0, .periodMs = CACHE_QOS_UPDATE_MS, .c = [this]() {
|
||||
try {
|
||||
this->updateQos();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateQos(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateQos(): " << e.what();
|
||||
}
|
||||
}}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
#ifdef MODEM_IS_SCPC
|
||||
updaters[0].periodMs = this->statsLogs.logEn ? this->statsLogs.logPeriodMs.load() : -1;
|
||||
#endif
|
||||
int64_t sleepTime = 60000; // минута по-умолчанию
|
||||
auto now = TIME_NOW();
|
||||
for (auto& u: updaters) {
|
||||
if (u.checkNeedUpdate(now)) {
|
||||
auto targetTime = u.lastUpdate + u.periodMs;
|
||||
if (targetTime + SLEEP_THRESHOLD <= now && targetTime - SLEEP_THRESHOLD >= now) {
|
||||
u.lastUpdate = targetTime;
|
||||
} else {
|
||||
u.lastUpdate = now;
|
||||
}
|
||||
|
||||
u.callback();
|
||||
now = TIME_NOW();
|
||||
}
|
||||
if (u.periodMs >= 0) {
|
||||
sleepTime = std::min(sleepTime, u.getNextUpdate(now));
|
||||
}
|
||||
}
|
||||
|
||||
if (sleepTime > 0) {
|
||||
boost::this_thread::sleep_for(boost::chrono::duration(boost::chrono::milliseconds(sleepTime)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
api_driver::TerminalApiDaemon::TerminalApiDaemon(): daemon([this]() { this->run(); }) {}
|
||||
|
||||
void api_driver::TerminalApiDaemon::getState(obj::TerminalState &dest) {
|
||||
std::shared_lock _lock(state);
|
||||
dest = state;
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::getDeviceState(obj::TerminalDeviceState &dest) {
|
||||
std::shared_lock _lock(state);
|
||||
dest = stateDev;
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::getSettingsRxTx(obj::TerminalRxTxSettings &dest) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::getNetworkSettings(obj::TerminalNetworkSettings &dest) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::getQosSettings(bool &isEnabled, std::string &json) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::setSettingsRxTx(obj::TerminalRxTxSettings &s, bool readback) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::setSettingsDpdi(DPDI_parmeters &s, bool readback) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::setSettingsBucLnb(buc_lnb_settings &bucLnb, bool readback) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::setQosSettings(bool enabled, const std::string &str, bool readback) {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::setNetworkSettings(obj::TerminalNetworkSettings &s, bool readback) {
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalFirmwareVersion api_driver::TerminalApiDaemon::getFirmware() {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::resetPacketStatistics() {
|
||||
}
|
||||
|
||||
void api_driver::TerminalApiDaemon::resetDefaultSettings() {
|
||||
}
|
||||
|
||||
api_driver::TerminalApiDaemon::~TerminalApiDaemon() {
|
||||
try {
|
||||
daemon.interrupt();
|
||||
daemon.try_join_for(boost::chrono::seconds(2));
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::~TerminalApiDaemon(): " << e.what();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/**
|
||||
* Этот демон нужен для того, чтобы получать статистику из API, а так же корректно сохранять настройки
|
||||
*/
|
||||
class api_driver::TerminalApiDaemon {
|
||||
void updateState() {
|
||||
obj::TerminalDeviceState s;
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
try {
|
||||
s.updateCallback(cp);
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->stateMutex);
|
||||
this->state = s;
|
||||
#ifdef MODEM_IS_TDMA
|
||||
this->state.fInitState = tmpDevState;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void updateSettings() {
|
||||
modulator_settings mod{};
|
||||
// uint32_t modulatorModcod;
|
||||
// CP_GetModulatorParams(sid, "modcod", &modulatorModcod);
|
||||
demodulator_settings demod{};
|
||||
#ifdef MODEM_IS_SCPC
|
||||
ACM_parameters_serv_ acm{};
|
||||
#endif
|
||||
DPDI_parmeters dpdi{};
|
||||
buc_lnb_settings bucLnb{};
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetModulatorSettings()", CP_GetModulatorSettings(sid, mod));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDemodulatorSettings()", CP_GetDemodulatorSettings(sid, demod));
|
||||
#ifdef MODEM_IS_SCPC
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetAcmParams()", CP_GetAcmParams(sid, &acm));
|
||||
#endif
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDpdiParams()", CP_GetDpdiParams(sid, &dpdi));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(sid, bucLnb));
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->settingsMutex);
|
||||
this->modSettings = mod;
|
||||
this->demodSettings = demod;
|
||||
#ifdef MODEM_IS_SCPC
|
||||
this->acmSettings = acm;
|
||||
#endif
|
||||
this->dpdiSettings = dpdi;
|
||||
this->bucLnbSettings = bucLnb;
|
||||
}
|
||||
}
|
||||
|
||||
void updateNetworkSettings() {
|
||||
obj::TerminalNetworkSettings s;
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
unsafeLoadNetworkSettings(s);
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->networkSettingsMutex);
|
||||
this->networkSettings = s;
|
||||
}
|
||||
}
|
||||
|
||||
void updateQos() {
|
||||
bool tmp1; std::string tmp2;
|
||||
std::scoped_lock lock{this->cpApiMutex};
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateQos()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
|
||||
{
|
||||
std::lock_guard lock2(this->qosSettingsMutex);
|
||||
this->qosEnabled = tmp1;
|
||||
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
*/
|
||||
TerminalDeviceState getState() {
|
||||
TerminalDeviceState s;
|
||||
{
|
||||
std::shared_lock lock(this->stateMutex);
|
||||
s = this->state;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
/**
|
||||
* Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
*/
|
||||
void getSettings(
|
||||
modulator_settings* mod, demodulator_settings* demod,
|
||||
#ifdef MODEM_IS_SCPC
|
||||
ACM_parameters_serv_* acm,
|
||||
#endif
|
||||
DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) {
|
||||
if (mod || demod ||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
acm ||
|
||||
#endif
|
||||
dpdi || bucLnb) {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
if (mod) { *mod = this->modSettings; }
|
||||
if (demod) { *demod = this->demodSettings; }
|
||||
#ifdef MODEM_IS_SCPC
|
||||
if (acm) { *acm = this->acmSettings; }
|
||||
#endif
|
||||
if (dpdi) { *dpdi = this->dpdiSettings; }
|
||||
if (bucLnb) { *bucLnb = this->bucLnbSettings; }
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
bool getIsCinC() {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
return modSettings.is_cinc;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isTest() {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
return modSettings.tx_is_on && (!modSettings.is_carrier
|
||||
#ifdef MODEM_IS_SCPC
|
||||
|| this->modSettings.is_test_data
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void getNetworkSettings(TerminalNetworkSettings& dest) {
|
||||
std::shared_lock lock(this->networkSettingsMutex);
|
||||
dest = this->networkSettings;
|
||||
}
|
||||
|
||||
void getQosSettings(bool& isEnabled, std::string& json) {
|
||||
std::shared_lock lock(this->qosSettingsMutex);
|
||||
isEnabled = this->qosEnabled;
|
||||
json = this->qosClassesJson;
|
||||
}
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, ACM_parameters_serv_& acm, 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));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetAcmParams()", CP_SetAcmParams(this->sid, acm));
|
||||
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));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetAcmParams()", CP_GetAcmParams(this->sid, &acm));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->modSettings = mod;
|
||||
this->demodSettings = demod;
|
||||
this->acmSettings = acm;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
void setSettingsDpdi(DPDI_parmeters& s, bool readback = true) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDpdiParams()", CP_SetDpdiParams(sid, s));
|
||||
if (readback) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_GetDpdiParams()", CP_GetDpdiParams(this->sid, &s));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->dpdiSettings = s;
|
||||
}
|
||||
}
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetBUC_LNB_settings()", CP_SetBUC_LNB_settings(this->sid, bucLnb));
|
||||
if (readback) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(this->sid, bucLnb));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->bucLnbSettings = bucLnb;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetQoSSettings()", CP_SetQoSSettings(this->sid, str, enabled));
|
||||
if (readback) {
|
||||
bool tmp1; std::string tmp2;
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
|
||||
{
|
||||
std::lock_guard lock2(this->qosSettingsMutex);
|
||||
this->qosEnabled = tmp1;
|
||||
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
|
||||
}
|
||||
}
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) {
|
||||
// const auto mang = splitIpAndMask();
|
||||
// std::pair<std::string, std::string> data;
|
||||
// if (!s.isL2) {
|
||||
// data = splitIpAndMask(s.dataIp);
|
||||
// }
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
unsafStoreNetworkSettings(s);
|
||||
|
||||
if (readback) {
|
||||
unsafeLoadNetworkSettings(s);
|
||||
{
|
||||
std::lock_guard lock2(this->networkSettingsMutex);
|
||||
this->networkSettings = s;
|
||||
}
|
||||
}
|
||||
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() {
|
||||
std::string tmp;
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetPacketStatistics()->CP_GetDmaDebug(reset_cnt_rx)", CP_GetDmaDebug(sid, "reset_cnt_rx", &tmp));
|
||||
}
|
||||
|
||||
void resetDefaultSettings() {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(default_params)", CP_SetDmaDebug(sid, "default_params", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
};
|
@ -1,80 +0,0 @@
|
||||
#ifndef DAEMON_H
|
||||
#define DAEMON_H
|
||||
|
||||
#include <boost/thread/detail/thread.hpp>
|
||||
|
||||
#include "proxy.h"
|
||||
#include "api-driver/structs.h"
|
||||
|
||||
namespace api_driver {
|
||||
class TerminalApiDaemon {
|
||||
std::mutex cpApiMutex;
|
||||
boost::thread daemon;
|
||||
proxy::CpProxy cp;
|
||||
|
||||
void connectToApi();
|
||||
|
||||
void run();
|
||||
|
||||
std::shared_mutex stateMutex;
|
||||
obj::TerminalState state;
|
||||
obj::TerminalDeviceState stateDev;
|
||||
|
||||
std::shared_mutex settingsMutex;
|
||||
obj::TerminalRxTxSettings settingsRxTx;
|
||||
#if API_OBJECT_NETWORK_SETTINGS_ENABLE
|
||||
obj::TerminalNetworkSettings settingsNetwork;
|
||||
#endif
|
||||
#if API_OBJECT_QOS_SETTINGS_ENABLE
|
||||
obj::TerminalQosSettings settingsQos;
|
||||
#endif
|
||||
|
||||
std::shared_mutex firmwareMutex;
|
||||
obj::TerminalFirmwareVersion firmware;
|
||||
|
||||
public:
|
||||
#if API_OBJECT_STATISTICS_ENABLE
|
||||
obj::StatisticsLogger statsLogs;
|
||||
#endif
|
||||
|
||||
explicit TerminalApiDaemon();
|
||||
|
||||
std::string getDeviceInitState();
|
||||
|
||||
/**
|
||||
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
*/
|
||||
void getState(obj::TerminalState& dest);
|
||||
void getDeviceState(obj::TerminalDeviceState& dest);
|
||||
|
||||
// /**
|
||||
// * Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
// */
|
||||
void getSettingsRxTx(obj::TerminalRxTxSettings& dest);
|
||||
|
||||
void getNetworkSettings(obj::TerminalNetworkSettings& dest);
|
||||
|
||||
void getQosSettings(bool& isEnabled, std::string& json);
|
||||
|
||||
void setSettingsRxTx(obj::TerminalRxTxSettings& s, bool readback = true);
|
||||
|
||||
void setSettingsDpdi(DPDI_parmeters& s, bool readback = true);
|
||||
|
||||
void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true);
|
||||
|
||||
void setQosSettings(bool enabled, const std::string& str, bool readback = true);
|
||||
|
||||
void setNetworkSettings(obj::TerminalNetworkSettings& s, bool readback = true);
|
||||
|
||||
obj::TerminalFirmwareVersion getFirmware();
|
||||
|
||||
void resetPacketStatistics();
|
||||
|
||||
void resetDefaultSettings();
|
||||
|
||||
~TerminalApiDaemon();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //DAEMON_H
|
@ -1,10 +0,0 @@
|
||||
#include "proxy.h"
|
||||
|
||||
//#define CPAPI_PROXY_CALL(proxy, func, ...) do { auto _res = func(proxy.sid, __VA_ARGS__); if (_res != OK) { BOOST_LOG_TRIVIAL(error) << "CP API error in " #func "(" #__VA_ARGS__ "): " << _res; } } while (0)
|
||||
// void foo() {
|
||||
// api_driver::proxy::CpProxy proxy;
|
||||
// std::string tmp;
|
||||
// CPAPI_PROXY_CALL(proxy, CP_GetDmaDebug, "fuck", &tmp);
|
||||
// }
|
||||
|
||||
|
@ -1,58 +0,0 @@
|
||||
#ifndef PROXY_H
|
||||
#define PROXY_H
|
||||
|
||||
#include "api-driver/stricts-enable.h"
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <terminal_api/ControlProtoCInterface.h>
|
||||
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, CP_Result result);
|
||||
|
||||
|
||||
namespace api_driver::proxy {
|
||||
class CpProxy {
|
||||
public:
|
||||
TSID sid;
|
||||
CP_Result lastCpError = OK;
|
||||
CpProxy();
|
||||
CpProxy(TSID s);
|
||||
|
||||
/**
|
||||
* Вызывает процедуру подключения к CP_API. Бросает исключение, если не удалось подключиться.
|
||||
*/
|
||||
void connect();
|
||||
|
||||
/**
|
||||
* Процедура отключения от API, после ее вызова запрещается использовать CP_API
|
||||
*/
|
||||
void disconnect();
|
||||
|
||||
std::string getDmaDebug(const std::string& arg);
|
||||
|
||||
std::string getNetwork(const std::string& param);
|
||||
void setNetwork(const std::string& param, const std::string& value);
|
||||
|
||||
void getModState(modulator_state& dest);
|
||||
void getModSettings(modulator_settings& dest);
|
||||
void setModSettings(modulator_settings& dest);
|
||||
|
||||
void getDemodState(demodulator_state& dest);
|
||||
void getDemodSettings(demodulator_settings& dest);
|
||||
void setDemodSettings(demodulator_settings& dest);
|
||||
|
||||
void getDeviceState(device_state& dest);
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
void getCincState(CinC_state& dest);
|
||||
#endif
|
||||
|
||||
#if API_OBJECT_STATISTICS_ENABLE
|
||||
void getDebugMetrics(debug_metrics& dest);
|
||||
#endif
|
||||
|
||||
~CpProxy();
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PROXY_H
|
@ -1,8 +0,0 @@
|
||||
#ifndef API_DRIVER_STRICTS_ENABLE_H
|
||||
#define API_DRIVER_STRICTS_ENABLE_H
|
||||
|
||||
#define API_OBJECT_STATISTICS_ENABLE defined(MODEM_IS_SCPC)
|
||||
#define API_OBJECT_NETWORK_SETTINGS_ENABLE defined(MODEM_IS_SCPC) || defined(MODEM_IS_TDMA)
|
||||
#define API_OBJECT_QOS_SETTINGS_ENABLE defined(MODEM_IS_SCPC) || defined(MODEM_IS_TDMA)
|
||||
|
||||
#endif //API_DRIVER_STRICTS_ENABLE_H
|
@ -1,559 +0,0 @@
|
||||
#include "api-driver/structs.h"
|
||||
#include "api-driver/proxy.h"
|
||||
|
||||
#include <iomanip>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
||||
|
||||
#define TIME_NOW() std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count()
|
||||
|
||||
typedef boost::property_tree::ptree::path_type json_path;
|
||||
|
||||
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
|
||||
// пороговое значение сна
|
||||
|
||||
// static int calculateSubnetMask(const std::string& subnet_mask) {
|
||||
// int mask = 0;
|
||||
// std::istringstream iss(subnet_mask);
|
||||
// std::string octet;
|
||||
// while (std::getline(iss, octet, '.')) {
|
||||
// int octet_value = std::stoi(octet);
|
||||
// for (int i = 7; i >= 0; i--) {
|
||||
// if (octet_value & (1 << i)) {
|
||||
// mask++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return mask;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
|
||||
*/
|
||||
// std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
|
||||
// auto pos = input.find('/');
|
||||
// if (pos == std::string::npos) {
|
||||
// // Обработка ошибки: нет символа '/'
|
||||
// throw std::runtime_error("address not contains mask");
|
||||
// }
|
||||
// std::string ip = input.substr(0, pos);
|
||||
// const unsigned int mask_int = std::stoul(input.substr(pos + 1));
|
||||
//
|
||||
// if (mask_int > 32) {
|
||||
// throw std::runtime_error("invalid mask");
|
||||
// }
|
||||
//
|
||||
// std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
|
||||
// std::string mask_str;
|
||||
//
|
||||
// for (unsigned int i = 0; i < 4; ++i) {
|
||||
// std::string octet = mask_binary.substr(i * 8u, 8);
|
||||
// int octet_value = std::stoi(octet, nullptr, 2);
|
||||
// mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
|
||||
// }
|
||||
//
|
||||
// return std::make_pair(ip, mask_str);
|
||||
// }
|
||||
static inline void rtrim(std::string &s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), s.end());
|
||||
}
|
||||
static inline const char* boolAsStr(bool value) {
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
std::string makeTimepointFromMillis(int64_t unix_time_ms) {
|
||||
// Преобразуем миллисекунды в микросекунды для std::chrono
|
||||
auto time_point = std::chrono::time_point<std::chrono::system_clock,
|
||||
std::chrono::microseconds>(std::chrono::microseconds(unix_time_ms * 1000));
|
||||
|
||||
auto tp = std::chrono::system_clock::to_time_t(time_point);
|
||||
tm* t = std::localtime(&tp);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::put_time(t, "%Y-%m-%d %H:%M:%S");
|
||||
auto ms = (unix_time_ms % 1000);
|
||||
ss << '.' << std::setw(3) << std::setfill('0') << ms;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
|
||||
bool api_driver::obj::CpUpdatebleObject::checkNeedUpdate(int64_t now) const {
|
||||
if (updatePeriodMs < 0) return false;
|
||||
// тут нет смысла спать меньше чем на 20мс, поэтому можно разрешить чтение на некоторое время раньше
|
||||
return now - lastUpdate >= (updatePeriodMs - 20);
|
||||
}
|
||||
int64_t api_driver::obj::CpUpdatebleObject::getNextUpdate(int64_t now) const {
|
||||
if (checkNeedUpdate(now)) {
|
||||
return 0;
|
||||
}
|
||||
auto next = now - lastUpdate;
|
||||
return next < 0 ? 0 : next;
|
||||
}
|
||||
api_driver::obj::CpUpdatebleObject::~CpUpdatebleObject() = default;
|
||||
|
||||
#if API_OBJECT_STATISTICS_ENABLE
|
||||
api_driver::obj::StatisticsLogger::StatisticsLogger(): timeStart(TIME_NOW()) {}
|
||||
|
||||
std::string api_driver::obj::StatisticsLogger::getSettings() {
|
||||
std::lock_guard _lock(mutex);
|
||||
std::stringstream res;
|
||||
res << "{\"en\":" << boolAsStr(this->logEn);
|
||||
res << ",\"logPeriodMs\":" << logPeriodMs;
|
||||
res << ",\"maxAgeMs\":" << maxAgeMs;
|
||||
res << '}';
|
||||
return res.str();
|
||||
}
|
||||
|
||||
void api_driver::obj::StatisticsLogger::setSettings(boost::property_tree::ptree &pt) {
|
||||
const bool newEn = pt.get<bool>("en");
|
||||
const int newInterval = pt.get<int>("logPeriodMs");
|
||||
const int newMaxAgeMs = pt.get<int>("maxAgeMs");
|
||||
|
||||
std::lock_guard _lock(this->mutex);
|
||||
this->logPeriodMs = newInterval;
|
||||
this->maxAgeMs = newMaxAgeMs;
|
||||
|
||||
if (newEn != this->logEn) {
|
||||
if (newEn) {
|
||||
this->logFile.open(LOG_FILENAME, std::ios::out);
|
||||
if (this->logFile.is_open()) {
|
||||
const auto* header = "timestamp\tcnt ok\tcnt bad\tfine freq dem\tcrs freq dem\tcrs freq compensator\tcrs time est\tfine time est\tmax level corr\tcurrent delay\tSNR\tcurrent modcod\tfine freq compensator\tind freq grb\tind freq tochn\tind filt adapt\tfilter corr cinc\tcorr cnt\tRSS\tcor erl\tcor lat\tgc gain\tpower pl rx\n";
|
||||
this->logFile.write(header, static_cast<std::streamsize>(strlen(header)));
|
||||
this->logEn = true;
|
||||
this->timeStart = TIME_NOW();
|
||||
}
|
||||
} else {
|
||||
if (this->logFile.is_open()) {
|
||||
this->logFile.close();
|
||||
}
|
||||
this->logEn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void api_driver::obj::StatisticsLogger::updateCallback(proxy::CpProxy &cp) {
|
||||
|
||||
}
|
||||
|
||||
void api_driver::obj::StatisticsLogger::putItem(const debug_metrics &item) {
|
||||
std::lock_guard _lock(this->mutex);
|
||||
if (!logEn) return;
|
||||
if (this->logFile.is_open()) {
|
||||
std::stringstream res;
|
||||
res << makeTimepointFromMillis(TIME_NOW()) << '\t';
|
||||
res << item.cnt_ok << '\t';
|
||||
res << item.cnt_bad << '\t';
|
||||
res << item.fine_freq_dem << '\t';
|
||||
res << item.crs_freq_dem << '\t';
|
||||
res << item.crs_freq_compensator << '\t';
|
||||
res << item.crs_time_est << '\t';
|
||||
res << item.fine_time_est << '\t';
|
||||
res << item.max_level_corr << '\t';
|
||||
res << item.current_delay << '\t';
|
||||
res << item.SNR << '\t';
|
||||
res << item.current_modcod << '\t';
|
||||
res << item.fine_freq_compensator << '\t';
|
||||
res << item.ind_freq_grb << '\t';
|
||||
res << item.ind_freq_tochn << '\t';
|
||||
res << item.ind_filt_adapt << '\t';
|
||||
res << item.filter_corr_cinc << '\t';
|
||||
res << item.corr_cnt << '\t';
|
||||
res << item.RSS << '\t';
|
||||
res << item.cor_erl << '\t';
|
||||
res << item.cor_lat << '\t';
|
||||
res << item.gc_gain << '\t';
|
||||
res << item.power_pl_rx << '\n';
|
||||
|
||||
const auto out = res.str();
|
||||
this->logFile.write(out.c_str(), static_cast<std::streamsize>(out.length()));
|
||||
this->logFile.flush();
|
||||
}
|
||||
}
|
||||
|
||||
api_driver::obj::StatisticsLogger::~StatisticsLogger() = default;
|
||||
#endif
|
||||
|
||||
#if API_OBJECT_NETWORK_SETTINGS_ENABLE
|
||||
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings() { loadDefaults(); }
|
||||
|
||||
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const TerminalNetworkSettings &src) = default;
|
||||
|
||||
api_driver::obj::TerminalNetworkSettings & api_driver::obj::TerminalNetworkSettings::operator=(const TerminalNetworkSettings &src) {
|
||||
managementIp = src.managementIp;
|
||||
managementGateway = src.managementGateway;
|
||||
dataIp = src.dataIp;
|
||||
serverName = src.serverName;
|
||||
isL2 = src.isL2;
|
||||
dataMtu = src.dataMtu;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalNetworkSettings::loadDefaults() {
|
||||
managementIp = "0.0.0.0";
|
||||
managementGateway = "";
|
||||
isL2 = true;
|
||||
dataIp = "0.0.0.0";
|
||||
dataMtu = 1500;
|
||||
serverName = DEFAULT_SERVER_NAME;
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalNetworkSettings::updateCallback(proxy::CpProxy &cp) {
|
||||
loadDefaults();
|
||||
try {
|
||||
managementIp = cp.getNetwork("addr");
|
||||
// s.managementIp += "/";
|
||||
// s.managementIp += std::to_string(calculateSubnetMask(cp.getNetwork("mask")));
|
||||
|
||||
managementGateway = cp.getNetwork("gateway");
|
||||
if (cp.getNetwork("mode") == "tun") {
|
||||
isL2 = false;
|
||||
dataIp = cp.getNetwork("addr_data");
|
||||
} else {
|
||||
isL2 = true;
|
||||
}
|
||||
dataMtu = 1500;
|
||||
serverName = cp.getNetwork("name_serv");
|
||||
if (serverName.empty()) {
|
||||
serverName = DEFAULT_SERVER_NAME;
|
||||
}
|
||||
} catch (std::exception& e) {
|
||||
throw std::runtime_error(std::string("api_driver::obj::TerminalNetworkSettings::updateCallback() error: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalNetworkSettings::updateFromPt(boost::property_tree::ptree &pt) {
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalNetworkSettings::store(proxy::CpProxy& cp) {
|
||||
try {
|
||||
cp.setNetwork("mode", isL2 ? "tap" : "tun");
|
||||
cp.setNetwork("addr", managementIp);
|
||||
|
||||
if (!isL2) {
|
||||
cp.setNetwork("addr_data", dataIp);
|
||||
}
|
||||
cp.setNetwork("mask", "255.255.255.0");
|
||||
cp.setNetwork("gateway", managementGateway);
|
||||
|
||||
// cp.setNetwork("data_mtu", std::to_string(dataMtu));
|
||||
|
||||
cp.setNetwork("name_serv", serverName);
|
||||
} catch (std::exception& e) {
|
||||
throw std::runtime_error(std::string("api_driver::obj::TerminalNetworkSettings::store() error: ") + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
std::string api_driver::obj::TerminalNetworkSettings::asJson() {
|
||||
std::stringstream out;
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalNetworkSettings::~TerminalNetworkSettings() = default;
|
||||
#endif
|
||||
|
||||
#if API_OBJECT_QOS_SETTINGS_ENABLE
|
||||
api_driver::obj::TerminalQosSettings::TerminalQosSettings() {
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalQosSettings::TerminalQosSettings(const TerminalQosSettings &src) {
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalQosSettings & api_driver::obj::TerminalQosSettings::operator=(const TerminalQosSettings &src) {
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalQosSettings::loadDefaults() {
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalQosSettings::updateCallback(proxy::CpProxy &cp) {
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalQosSettings::updateFromPt(boost::property_tree::ptree &pt) {
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalQosSettings::store(proxy::CpProxy &cp) {
|
||||
}
|
||||
|
||||
std::string api_driver::obj::TerminalQosSettings::asJson() {
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalQosSettings::~TerminalQosSettings() {
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void api_driver::obj::TerminalState::updateCallback(proxy::CpProxy& cp) {
|
||||
modulator_state mod{};
|
||||
demodulator_state demod{};
|
||||
#ifdef MODEM_IS_SCPC
|
||||
CinC_state cinc{};
|
||||
#endif
|
||||
try {
|
||||
cp.getModState(mod);
|
||||
cp.getDemodState(demod);
|
||||
#ifdef MODEM_IS_SCPC
|
||||
// CinC state прописывается в настройках
|
||||
{
|
||||
|
||||
}
|
||||
cp.getCincState(cinc);
|
||||
#endif
|
||||
#ifdef MODEM_IS_TDMA
|
||||
fInitState = cp.getDmaDebug("status_init");
|
||||
#endif
|
||||
} catch (std::exception& e) {
|
||||
throw std::runtime_error(std::string("api_driver::obj::TerminalState::updateCallback() error: ") + e.what());
|
||||
}
|
||||
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
|
||||
bool isCinC = getIsCinC();
|
||||
if (isCinC) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetCinCState()", CP_GetCinCState(sid, cinc));
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
#ifdef MODEM_IS_TDMA
|
||||
this->fInitState = tmpDevState;
|
||||
#endif
|
||||
this->fTxState = modulator.is_tx_on;
|
||||
this->fTxModcod = modulator.modcod;
|
||||
this->fTxSnr = modulator.snr_remote;
|
||||
this->fTxframeSizeNormal = modulator.snr_remote;
|
||||
this->fTx = modulator.snr_remote;
|
||||
this->fTx = modulator.snr_remote;
|
||||
this->fTx = modulator.snr_remote;
|
||||
#ifdef MODEM_IS_SCPC
|
||||
result << ",\"tx.snr\":"; writeDouble(result, modulator.snr_remote);
|
||||
|
||||
if (modulator.is_short) { result << R"(,"tx.frameSizeNormal":false)"; }
|
||||
else { result << R"(,"tx.frameSizeNormal":true)"; }
|
||||
|
||||
if (modulator.is_pilots) { result << R"(,"tx.isPilots":true)"; }
|
||||
else { result << R"(,"tx.isPilots":false)"; }
|
||||
#else
|
||||
{
|
||||
modulator_settings modSet{};
|
||||
daemon->getSettings(&modSet, nullptr, 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.speedOnIifKbit\":"; writeDouble(result, (static_cast<double>(modulator.speed_in_bytes_tx_iface) / 128.0));
|
||||
|
||||
// формируем структуру для RX
|
||||
result << ",\n\"rx.state\":" << boolAsStr(demodulator.locks.sym_sync_lock && demodulator.locks.freq_lock && demodulator.locks.afc_lock && demodulator.locks.pkt_sync);
|
||||
result << ",\"rx.sym_sync_lock\":" << boolAsStr(demodulator.locks.sym_sync_lock);
|
||||
result << ",\"rx.freq_search_lock\":" << boolAsStr(demodulator.locks.freq_lock);
|
||||
result << ",\"rx.afc_lock\":" << boolAsStr(demodulator.locks.afc_lock);
|
||||
result << ",\"rx.pkt_sync\":" << boolAsStr(demodulator.locks.pkt_sync);
|
||||
|
||||
result << ",\"rx.snr\":"; writeDouble(result, demodulator.snr);
|
||||
result << ",\"rx.rssi\":"; writeDouble(result, demodulator.rssi);
|
||||
result << ",\"rx.modcod\":" << demodulator.modcod;
|
||||
|
||||
if (demodulator.is_short) {
|
||||
result << R"(,"rx.frameSizeNormal":false)";
|
||||
} else {
|
||||
result << R"(,"rx.frameSizeNormal":true)";
|
||||
}
|
||||
|
||||
if (demodulator.is_pilots) {
|
||||
result << R"(,"rx.isPilots":true)";
|
||||
} else {
|
||||
result << R"(,"rx.isPilots":false)";
|
||||
}
|
||||
|
||||
result << ",\n\"rx.symError\":"; writeDouble(result, demodulator.sym_err);
|
||||
result << ",\"rx.freqErr\":"; writeDouble(result, demodulator.crs_freq_err);
|
||||
result << ",\"rx.freqErrAcc\":"; writeDouble(result, demodulator.fine_freq_err);
|
||||
result << ",\"rx.inputSignalLevel\":"; writeDouble(result, demodulator.if_overload);
|
||||
result << ",\"rx.pllError\":"; writeDouble(result, demodulator.afc_err);
|
||||
result << ",\"rx.speedOnRxKbit\":"; writeDouble(result, static_cast<double>(demodulator.speed_in_bytes_rx) / 128.0);
|
||||
result << ",\"rx.speedOnIifKbit\":"; writeDouble(result, static_cast<double>(demodulator.speed_in_bytes_rx_iface) / 128.0);
|
||||
result << ",\"rx.packetsOk\":" << demodulator.packet_ok_cnt;
|
||||
result << ",\"rx.packetsBad\":" << demodulator.packet_bad_cnt;
|
||||
result << ",\"rx.packetsDummy\":" << demodulator.dummy_cnt;
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
// формируем структуру для CinC
|
||||
if (isCinC) {
|
||||
if (modulator.is_tx_on) {
|
||||
if (cinc.carrier_lock) {
|
||||
result << R"(,"cinc.correlator":true)";
|
||||
} else {
|
||||
result << R"(,"cinc.correlator":false)";
|
||||
}
|
||||
} else {
|
||||
result << R"(,"cinc.correlator":null)";
|
||||
}
|
||||
|
||||
result << ",\n\"cinc.occ\":"; writeDouble(result, cinc.ratio_signal_signal, 3);
|
||||
result << ",\"cinc.correlatorFails\":" << cinc.cnt_bad_lock;
|
||||
result << ",\"cinc.freqErr\":" << cinc.freq_error_offset;
|
||||
result << ",\"cinc.freqErrAcc\":" << cinc.freq_fine_estimate;
|
||||
result << ",\"cinc.channelDelay\":" << cinc.delay_dpdi;
|
||||
} else {
|
||||
result << R"(,"cinc.correlator":null)";
|
||||
}
|
||||
#endif
|
||||
|
||||
// структура температур девайса
|
||||
result << ",\n\"device.adrv\":"; writeDouble(result, device.adrv_temp, 1);
|
||||
result << ",\"device.fpga\":"; writeDouble(result, device.pl_temp, 1);
|
||||
result << ",\"device.zynq\":"; writeDouble(result, device.zynq_temp, 1);
|
||||
#ifdef MODEM_IS_TDMA
|
||||
if (device.cur_image.empty()) {
|
||||
result << R"(,
|
||||
"device.upgradeStatus":"Нет обновлений","device.upgradePercent":0,"device.upgradeImage":"")";
|
||||
} else {
|
||||
switch (device.status) {
|
||||
case NORM_RX_OBJECT_NEW_API: result << ",\n" R"("device.upgradeStatus": "Начало загрузки")"; break;
|
||||
case NORM_RX_OBJECT_INFO_API: result << ",\n" R"("device.upgradeStatus": "Получено имя образа")"; break;
|
||||
case NORM_RX_OBJECT_UPDATED_API: result << ",\n" R"("device.upgradeStatus": "Загружается")"; break;
|
||||
case NORM_RX_OBJECT_COMPLETED_API: result << ",\n" R"("device.upgradeStatus": "Загрузка завершена")"; break;
|
||||
case NORM_RX_OBJECT_ABORTED_API: result << ",\n" R"("device.upgradeStatus": "Загрузка прервана")"; break;
|
||||
default: result << ",\n" R"("device.upgradeStatus": "?")";
|
||||
|
||||
}
|
||||
result << ",\"device.upgradePercent\":" << device.dwl_percent;
|
||||
result << ",\"device.upgradeImage\":" << buildEscapedString(device.cur_image);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
result << "}";
|
||||
*/
|
||||
this->modState = modulator;
|
||||
this->demodState = demodulator;
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
this->cincState = cinc;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
api_driver::obj::TerminalState::~TerminalState() = default;
|
||||
|
||||
|
||||
api_driver::obj::TerminalDeviceState::TerminalDeviceState() = default;
|
||||
api_driver::obj::TerminalDeviceState::TerminalDeviceState(const TerminalDeviceState &src) = default;
|
||||
api_driver::obj::TerminalDeviceState & api_driver::obj::TerminalDeviceState::operator=(const TerminalDeviceState &src) {
|
||||
fOsUptime = src.fOsUptime;
|
||||
fOsLoad1 = src.fOsLoad1;
|
||||
fOsLoad5 = src.fOsLoad5;
|
||||
fOsLoad15 = src.fOsLoad15;
|
||||
fOsTotalram = src.fOsTotalram;
|
||||
fOsFreeram = src.fOsFreeram;
|
||||
fOsProcs = src.fOsProcs;
|
||||
fTempAdrv = src.fTempAdrv;
|
||||
fTempZynq = src.fTempZynq;
|
||||
fTempFpga = src.fTempFpga;
|
||||
#ifdef MODEM_IS_TDMA
|
||||
fUpgradeStatus = src.fUpgradeStatus;
|
||||
fUpgradePercent = src.fUpgradePercent;
|
||||
fUpgradeImage = src.fUpgradeImage;
|
||||
#endif
|
||||
return *this;
|
||||
}
|
||||
|
||||
void api_driver::obj::TerminalDeviceState::updateCallback(proxy::CpProxy &cp) {
|
||||
{
|
||||
device_state ds{};
|
||||
cp.getDeviceState(ds);
|
||||
fTempAdrv = ds.adrv_temp;
|
||||
fTempZynq = ds.pl_temp;
|
||||
fTempFpga = ds.zynq_temp;
|
||||
}
|
||||
#ifdef MODEM_IS_TDMA
|
||||
{
|
||||
progress_msg ds{};
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetUpdateStatus()", CP_GetUpdateStatus(sid, ds));
|
||||
fOtaStatus = ds.status;
|
||||
fOtaPercent = ds.dwl_percent;
|
||||
fOtaImage = ds.cur_image;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct sysinfo info{};
|
||||
sysinfo(&info);
|
||||
|
||||
const double f_load = 100.0 / ((1 << SI_LOAD_SHIFT) * get_nprocs());
|
||||
fOsUptime = info.uptime;
|
||||
fOsLoad1 = f_load * static_cast<double>(info.loads[0]);
|
||||
fOsLoad5 = f_load * static_cast<double>(info.loads[1]);
|
||||
fOsLoad15 = f_load * static_cast<double>(info.loads[2]);
|
||||
fOsTotalram = (info.totalram * info.mem_unit) >> 20; // Mb
|
||||
fOsFreeram = (info.totalram * info.mem_unit) >> 20; // Mb
|
||||
fOsProcs = info.procs;
|
||||
}
|
||||
|
||||
std::string api_driver::obj::TerminalDeviceState::asJson() const {
|
||||
std::stringstream result;
|
||||
result << "{\"uptime\":" << fOsUptime
|
||||
<< ",\"load1min\":" << std::setprecision(2) << fOsLoad1
|
||||
<< ",\"load5min\":" << std::setprecision(2) << fOsLoad5
|
||||
<< ",\"load15min\":" << std::setprecision(2) << fOsLoad15
|
||||
<< ",\"totalram\":" << fOsTotalram
|
||||
<< ",\"freeram\":" << fOsFreeram
|
||||
<< ",\"procs\":" << fOsProcs
|
||||
<< ",\"adrv\":" << std::setprecision(1) << fTempAdrv
|
||||
<< ",\"fpga\":" << std::setprecision(1) << fTempFpga
|
||||
<< ",\"zynq\":" << std::setprecision(1) << fTempZynq;
|
||||
#ifdef MODEM_IS_TDMA
|
||||
if (fUpgradeImage.empty()) {
|
||||
result << R"(,
|
||||
"upgradeStatus":"Нет обновлений","upgradePercent":0,"upgradeImage":"")";
|
||||
} else {
|
||||
switch (fUpgradeStatus) {
|
||||
case NORM_RX_OBJECT_NEW_API: result << ",\n" R"("upgradeStatus": "Начало загрузки")"; break;
|
||||
case NORM_RX_OBJECT_INFO_API: result << ",\n" R"("upgradeStatus": "Получено имя образа")"; break;
|
||||
case NORM_RX_OBJECT_UPDATED_API: result << ",\n" R"("upgradeStatus": "Загружается")"; break;
|
||||
case NORM_RX_OBJECT_COMPLETED_API: result << ",\n" R"("upgradeStatus": "Загрузка завершена")"; break;
|
||||
case NORM_RX_OBJECT_ABORTED_API: result << ",\n" R"("upgradeStatus": "Загрузка прервана")"; break;
|
||||
default: result << ",\n" R"("upgradeStatus": "?")";
|
||||
|
||||
}
|
||||
result << ",\"upgradePercent\":" << fUpgradePercent;
|
||||
result << ",\"upgradeImage\":" << buildEscapedString(fUpgradeImage);
|
||||
}
|
||||
|
||||
#endif
|
||||
result << "}";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
api_driver::obj::TerminalDeviceState::~TerminalDeviceState() = default;
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,264 +0,0 @@
|
||||
#ifndef STRUCTS_H
|
||||
#define STRUCTS_H
|
||||
|
||||
#include "api-driver/stricts-enable.h"
|
||||
#include "proxy.h"
|
||||
#include <atomic>
|
||||
#include <fstream>
|
||||
#include <shared_mutex>
|
||||
#include <string>
|
||||
#include <boost/log/trivial.hpp>
|
||||
#include <boost/property_tree/ptree_fwd.hpp>
|
||||
|
||||
|
||||
|
||||
namespace api_driver::obj {
|
||||
/**
|
||||
* Обертка для объектов, доступных для обновления
|
||||
* NOTE: перед вызовом функций, требующих `TSID`, необходимо захватить мютекс API.
|
||||
*/
|
||||
class CpUpdatebleObject {
|
||||
public:
|
||||
int64_t lastUpdate = 0;
|
||||
int64_t updatePeriodMs = -1;
|
||||
|
||||
/**
|
||||
* Функция для обновления (загрузки) объекта из CP API.
|
||||
*/
|
||||
virtual void updateCallback(proxy::CpProxy& cp) = 0;
|
||||
|
||||
bool checkNeedUpdate(int64_t now) const;
|
||||
|
||||
int64_t getNextUpdate(int64_t now) const;
|
||||
|
||||
virtual ~CpUpdatebleObject();
|
||||
};
|
||||
|
||||
|
||||
#if API_OBJECT_STATISTICS_ENABLE
|
||||
class StatisticsLogger: public CpUpdatebleObject {
|
||||
public:
|
||||
StatisticsLogger();
|
||||
|
||||
static constexpr const char* LOG_FILENAME = "/tmp/weblog-statistics.csv";
|
||||
|
||||
int64_t timeStart;
|
||||
|
||||
bool logEn = false;
|
||||
std::atomic<int> logPeriodMs = 1000;
|
||||
std::atomic<int> maxAgeMs = 10000;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return {"en": bool, "logPeriodMs": int, "maxAgeMs": int}
|
||||
*/
|
||||
std::string getSettings();
|
||||
void setSettings(boost::property_tree::ptree &pt);
|
||||
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
/**
|
||||
* Записать значение в "базу данных". Метку при этом вставлять не нужно, она будет вставлена автоматически.
|
||||
* @param item
|
||||
*/
|
||||
void putItem(const debug_metrics& item);
|
||||
|
||||
// void collectExpiredItems();
|
||||
|
||||
// void resetLogs() {
|
||||
// std::lock_guard _lock(mutex);
|
||||
// logs.clear();
|
||||
// }
|
||||
|
||||
~StatisticsLogger() override;
|
||||
private:
|
||||
// std::pmr::deque<LogItem> logs;
|
||||
std::fstream logFile{};
|
||||
std::shared_mutex mutex;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(MODEM_IS_SCPC)
|
||||
static constexpr const char* DEFAULT_SERVER_NAME = "RSCM-101";
|
||||
#elif defined(MODEM_IS_TDMA)
|
||||
static constexpr const char* DEFAULT_SERVER_NAME = "TDMA Abonent";
|
||||
#elif defined(MODEM_IS_SHPC)
|
||||
static constexpr const char* DEFAULT_SERVER_NAME = "SHPS Terminal";
|
||||
#else
|
||||
#error "Selected modem type not supported!"
|
||||
#endif
|
||||
|
||||
#if API_OBJECT_NETWORK_SETTINGS_ENABLE
|
||||
class TerminalNetworkSettings: public CpUpdatebleObject {
|
||||
public:
|
||||
std::string managementIp, managementGateway, dataIp, serverName;
|
||||
bool isL2 = true;
|
||||
unsigned int dataMtu = 1500;
|
||||
|
||||
TerminalNetworkSettings();
|
||||
TerminalNetworkSettings(const TerminalNetworkSettings& src);
|
||||
TerminalNetworkSettings& operator= (const TerminalNetworkSettings& src);
|
||||
|
||||
void loadDefaults();
|
||||
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
void updateFromPt(boost::property_tree::ptree &pt);
|
||||
void store(proxy::CpProxy& cp);
|
||||
std::string asJson();
|
||||
|
||||
~TerminalNetworkSettings() override;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if API_OBJECT_QOS_SETTINGS_ENABLE
|
||||
class TerminalQosSettings: public CpUpdatebleObject {
|
||||
public:
|
||||
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
|
||||
std::string qosSettingsJson;
|
||||
bool qosEnabled = false;
|
||||
|
||||
TerminalQosSettings();
|
||||
TerminalQosSettings(const TerminalQosSettings& src);
|
||||
TerminalQosSettings& operator= (const TerminalQosSettings& src);
|
||||
|
||||
void loadDefaults();
|
||||
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
void updateFromPt(boost::property_tree::ptree &pt);
|
||||
void store(proxy::CpProxy& cp);
|
||||
std::string asJson();
|
||||
|
||||
~TerminalQosSettings() override;
|
||||
};
|
||||
#endif
|
||||
|
||||
class TerminalFirmwareVersion {
|
||||
public:
|
||||
std::string version, modemId, modemSn, macMang, macData;
|
||||
|
||||
TerminalFirmwareVersion();
|
||||
TerminalFirmwareVersion(const TerminalFirmwareVersion& src);
|
||||
~TerminalFirmwareVersion();
|
||||
|
||||
// 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));
|
||||
void load(proxy::CpProxy& cp);
|
||||
std::string asJson();
|
||||
|
||||
TerminalFirmwareVersion& operator= (const TerminalFirmwareVersion& src);
|
||||
};
|
||||
|
||||
/**
|
||||
* Обертка состояния терминала, тут состояние девайса, модулятора/демодулятора, состояние автоматического обновления.
|
||||
*/
|
||||
class TerminalState: public CpUpdatebleObject {
|
||||
public:
|
||||
std::string fInitState{};
|
||||
bool fIsTest = false; // daemon->isTest()
|
||||
bool fTxState = false;
|
||||
#ifdef MODEM_IS_SCPC
|
||||
bool fIsCinC = false;
|
||||
#endif
|
||||
|
||||
bool fStatRxState;
|
||||
bool fStatRxSymSyncLock;
|
||||
bool fStatRxFreqSearchLock;
|
||||
bool fStatRxAfcLock;
|
||||
bool fStatRxPktSync;
|
||||
|
||||
float fStatRxSnr;
|
||||
float fStatRxRssi;
|
||||
uint16_t fStatRxModcod;
|
||||
bool fStatRxFrameSizeNormal;
|
||||
bool fStatRxIsPilots;
|
||||
|
||||
double fStatRxSymError;
|
||||
double fStatRxFreqErr;
|
||||
double fStatRxFreqErrAcc;
|
||||
double fStatRxInputSignalLevel;
|
||||
double fStatRxPllError;
|
||||
double fStatRxSpeedOnRxKbit;
|
||||
double fStatRxSpeedOnIifKbit;
|
||||
uint32_t fStatRxPacketsOk;
|
||||
uint32_t fStatRxPacketsBad;
|
||||
uint32_t fStatRxPacketsDummy;
|
||||
|
||||
bool fStatTxState;
|
||||
uint16_t fStatTxModcod;
|
||||
double fStatTxSpeedOnTxKbit;
|
||||
double fStatTxSpeedOnIifKbit;
|
||||
#ifdef MODEM_IS_SCPC
|
||||
float fStatTxSnr;
|
||||
bool fStatTxFrameSizeNormal;
|
||||
bool fStatTxIsPilots;
|
||||
double fStatCincOcc;
|
||||
bool fStatCincCorrelator;
|
||||
uint32_t fStatCincCorrelatorFails;
|
||||
int32_t fStatCincFreqErr;
|
||||
int32_t fStatCincFreqErrAcc;
|
||||
float fStatCincChannelDelay;
|
||||
#endif
|
||||
#ifdef MODEM_IS_TDMA
|
||||
fStatTxCenterFreq;
|
||||
fStatTxSymSpeed;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Обновление основной части статистики, то есть RX/TX и sysinfo
|
||||
*/
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
|
||||
void updateFromPt(boost::property_tree::ptree &pt);
|
||||
void store(TSID sid, CP_Result& lastCpError);
|
||||
std::string asJson();
|
||||
|
||||
~TerminalState() override;
|
||||
};
|
||||
|
||||
class TerminalDeviceState: public CpUpdatebleObject {
|
||||
public:
|
||||
time_t fOsUptime{};
|
||||
double fOsLoad1{};
|
||||
double fOsLoad5{};
|
||||
double fOsLoad15{};
|
||||
unsigned int fOsTotalram{};
|
||||
unsigned int fOsFreeram{};
|
||||
unsigned int fOsProcs{};
|
||||
|
||||
double fTempAdrv{};
|
||||
double fTempZynq{};
|
||||
double fTempFpga{};
|
||||
#ifdef MODEM_IS_TDMA
|
||||
DOWNLOAD_STATUS fUpgradeStatus{};
|
||||
unsigned int fUpgradePercent{};
|
||||
std::string fUpgradeImage;
|
||||
#endif
|
||||
|
||||
TerminalDeviceState();
|
||||
TerminalDeviceState(const TerminalDeviceState& src);
|
||||
TerminalDeviceState& operator= (const TerminalDeviceState& src);
|
||||
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
std::string asJson() const;
|
||||
|
||||
~TerminalDeviceState() override;
|
||||
};
|
||||
|
||||
class TerminalRxTxSettings: public CpUpdatebleObject {
|
||||
public:
|
||||
|
||||
// TODO описать все параметры для всех терминалов
|
||||
|
||||
void updateCallback(proxy::CpProxy& cp) override;
|
||||
void updateFromPt(boost::property_tree::ptree &pt);
|
||||
void store(proxy::CpProxy& cp);
|
||||
std::string asJson();
|
||||
|
||||
~TerminalRxTxSettings() override;
|
||||
};
|
||||
}
|
||||
|
||||
#endif //STRUCTS_H
|
@ -14,15 +14,59 @@
|
||||
|
||||
typedef boost::property_tree::ptree::path_type json_path;
|
||||
|
||||
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
|
||||
// пороговое значение сна
|
||||
static constexpr int64_t SLEEP_THRESHOLD = 10;
|
||||
|
||||
// static int calculateSubnetMask(const std::string& subnet_mask) {
|
||||
// int mask = 0;
|
||||
// std::istringstream iss(subnet_mask);
|
||||
// std::string octet;
|
||||
// while (std::getline(iss, octet, '.')) {
|
||||
// int octet_value = std::stoi(octet);
|
||||
// for (int i = 7; i >= 0; i--) {
|
||||
// if (octet_value & (1 << i)) {
|
||||
// mask++;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return mask;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
|
||||
*/
|
||||
// std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
|
||||
// auto pos = input.find('/');
|
||||
// if (pos == std::string::npos) {
|
||||
// // Обработка ошибки: нет символа '/'
|
||||
// throw std::runtime_error("address not contains mask");
|
||||
// }
|
||||
// std::string ip = input.substr(0, pos);
|
||||
// const unsigned int mask_int = std::stoul(input.substr(pos + 1));
|
||||
//
|
||||
// if (mask_int > 32) {
|
||||
// throw std::runtime_error("invalid mask");
|
||||
// }
|
||||
//
|
||||
// std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
|
||||
// std::string mask_str;
|
||||
//
|
||||
// for (unsigned int i = 0; i < 4; ++i) {
|
||||
// std::string octet = mask_binary.substr(i * 8u, 8);
|
||||
// int octet_value = std::stoi(octet, nullptr, 2);
|
||||
// mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
|
||||
// }
|
||||
//
|
||||
// return std::make_pair(ip, mask_str);
|
||||
// }
|
||||
|
||||
static inline void rtrim(std::string &s) {
|
||||
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
|
||||
return !std::isspace(ch);
|
||||
}).base(), s.end());
|
||||
}
|
||||
static inline const char* boolAsStr(bool value) {
|
||||
static const char* boolAsStr(bool value) {
|
||||
return value ? "true" : "false";
|
||||
}
|
||||
|
||||
@ -218,6 +262,546 @@ private:
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Этот демон нужен для того, чтобы получать статистику из API, а так же корректно сохранять настройки
|
||||
*/
|
||||
class api_driver::TerminalApiDaemon {
|
||||
private:
|
||||
CP_Result lastCpError = OK;
|
||||
void logCpApiError(const char* desc, CP_Result err) {
|
||||
if (err != OK) {
|
||||
BOOST_LOG_TRIVIAL(error) << "CP API error in " << desc << ": " << err;
|
||||
this->lastCpError = err;
|
||||
}
|
||||
}
|
||||
|
||||
void updateState() {
|
||||
TerminalDeviceState s;
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetModulatorState()", CP_GetModulatorState(sid, s.mod));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDemodulatorState()", CP_GetDemodulatorState(sid, s.demod));
|
||||
#ifdef MODEM_IS_TDMA
|
||||
std::string tmpDevState;
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDmaDebug(status_init)", CP_GetDmaDebug(sid, "status_init", &tmpDevState));
|
||||
#endif
|
||||
{
|
||||
device_state ds{};
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDeviceState()", CP_GetDeviceState(sid, ds));
|
||||
s.adrv_temp = ds.adrv_temp;
|
||||
s.pl_temp = ds.pl_temp;
|
||||
s.zynq_temp = ds.zynq_temp;
|
||||
}
|
||||
#ifdef MODEM_IS_TDMA
|
||||
{
|
||||
progress_msg ds{};
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetUpdateStatus()", CP_GetUpdateStatus(sid, ds));
|
||||
s.otaStatus = ds.status;
|
||||
s.otaPercent = ds.dwl_percent;
|
||||
s.otaImage = ds.cur_image;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
bool isCinC = getIsCinC();
|
||||
if (isCinC) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetCinCState()", CP_GetCinCState(sid, s.cinc));
|
||||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->stateMutex);
|
||||
this->state = s;
|
||||
#ifdef MODEM_IS_TDMA
|
||||
this->deviceInitState = tmpDevState;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void updateSettings() {
|
||||
modulator_settings mod{};
|
||||
// uint32_t modulatorModcod;
|
||||
// CP_GetModulatorParams(sid, "modcod", &modulatorModcod);
|
||||
demodulator_settings demod{};
|
||||
#ifdef MODEM_IS_SCPC
|
||||
ACM_parameters_serv_ acm{};
|
||||
#endif
|
||||
DPDI_parmeters dpdi{};
|
||||
buc_lnb_settings bucLnb{};
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetModulatorSettings()", CP_GetModulatorSettings(sid, mod));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDemodulatorSettings()", CP_GetDemodulatorSettings(sid, demod));
|
||||
#ifdef MODEM_IS_SCPC
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetAcmParams()", CP_GetAcmParams(sid, &acm));
|
||||
#endif
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDpdiParams()", CP_GetDpdiParams(sid, &dpdi));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(sid, bucLnb));
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->settingsMutex);
|
||||
this->modSettings = mod;
|
||||
this->demodSettings = demod;
|
||||
#ifdef MODEM_IS_SCPC
|
||||
this->acmSettings = acm;
|
||||
#endif
|
||||
this->dpdiSettings = dpdi;
|
||||
this->bucLnbSettings = bucLnb;
|
||||
}
|
||||
}
|
||||
|
||||
void unsafeLoadNetworkSettings(TerminalNetworkSettings& s) {
|
||||
s.loadDefaults();
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp));
|
||||
// logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp));
|
||||
// s.managementIp += "/";
|
||||
// s.managementIp += std::to_string(calculateSubnetMask(tmp));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway));
|
||||
std::string nm; logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &nm));
|
||||
if (nm == "tun") {
|
||||
s.isL2 = false;
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp));
|
||||
} else {
|
||||
s.isL2 = true;
|
||||
}
|
||||
s.dataMtu = 1500;
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_GetNetwork(name_serv)", CP_GetNetwork(sid, "name_serv", &s.serverName));
|
||||
if (s.serverName.empty()) {
|
||||
s.serverName = TerminalNetworkSettings::DEFAULT_SERVER_NAME;
|
||||
}
|
||||
}
|
||||
void unsafStoreNetworkSettings(TerminalNetworkSettings& s) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafStoreNetworkSettings()->CP_SetNetwork(mode)", CP_SetNetwork(sid, "mode", s.isL2 ? "tap" : "tun"));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafStoreNetworkSettings()->CP_SetNetwork(addr)", CP_SetNetwork(sid, "addr", s.managementIp.c_str()));
|
||||
if (!s.isL2) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafStoreNetworkSettings()->CP_SetNetwork(addr_data)", CP_SetNetwork(sid, "addr_data", s.dataIp.c_str()));
|
||||
// TODO маска не устанавливается, потому что в API этого нет
|
||||
}
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafStoreNetworkSettings()->CP_SetNetwork(mask)", CP_SetNetwork(sid, "mask", "255.255.255.0"));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafStoreNetworkSettings()->CP_SetNetwork(gateway)", CP_SetNetwork(sid, "gateway", s.managementGateway.c_str()));
|
||||
|
||||
// TODO MTU не устанавливается, потому что в API этого нет
|
||||
|
||||
logCpApiError("api_driver::TerminalApiDaemon::unsafeLoadNetworkSettings()->CP_SetNetwork(name_serv)", CP_SetNetwork(sid, "name_serv", s.serverName.c_str()));
|
||||
}
|
||||
|
||||
void updateNetworkSettings() {
|
||||
TerminalNetworkSettings s;
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
unsafeLoadNetworkSettings(s);
|
||||
|
||||
{
|
||||
std::lock_guard lock2(this->networkSettingsMutex);
|
||||
this->networkSettings = s;
|
||||
}
|
||||
}
|
||||
|
||||
void updateQos() {
|
||||
bool tmp1; std::string tmp2;
|
||||
std::scoped_lock lock{this->cpApiMutex};
|
||||
logCpApiError("api_driver::TerminalApiDaemon::updateQos()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
|
||||
{
|
||||
std::lock_guard lock2(this->qosSettingsMutex);
|
||||
this->qosEnabled = tmp1;
|
||||
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
|
||||
}
|
||||
}
|
||||
|
||||
void connectToApi() {
|
||||
{
|
||||
std::lock_guard _lock(this->stateMutex);
|
||||
this->deviceInitState = "Not connected to API";
|
||||
this->networkSettings.loadDefaults();
|
||||
}
|
||||
|
||||
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() {
|
||||
// это демон, который в бесконечном цикле опрашивает API
|
||||
this->connectToApi();
|
||||
|
||||
struct IntervalUpdate_t {
|
||||
int64_t lastUpdate;
|
||||
int64_t periodMs;
|
||||
|
||||
std::function<void()> callback;
|
||||
|
||||
bool checkNeedUpdate(int64_t now) const {
|
||||
if (periodMs < 0) return false;
|
||||
// тут нет смысла спать меньше чем на 20мс, поэтому можно разрешить чтение на некоторое время раньше
|
||||
return now - lastUpdate >= (periodMs - SLEEP_THRESHOLD);
|
||||
}
|
||||
|
||||
int64_t getNextUpdate(int64_t now) const {
|
||||
if (checkNeedUpdate(now)) {
|
||||
return 0;
|
||||
}
|
||||
auto next = now - lastUpdate;
|
||||
return next < 0 ? 0 : next;
|
||||
}
|
||||
};
|
||||
|
||||
IntervalUpdate_t updaters[] = {
|
||||
#ifdef MODEM_IS_SCPC
|
||||
// обновление логов
|
||||
{.lastUpdate = 0, .periodMs = -1, .callback = [this]() {
|
||||
try {
|
||||
{
|
||||
std::lock_guard _alock(this->cpApiMutex);
|
||||
std::lock_guard _slock(this->stateMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon->statsLogs.putItem()->CP_GetDebugMetrics()", CP_GetDebugMetrics(sid, state.debug));
|
||||
}
|
||||
this->statsLogs.putItem(state.debug);
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon->statsLogs.putItem(): success write statistics state to log!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon->statsLogs.putItem() failed to log: " << e.what();
|
||||
}
|
||||
}},
|
||||
#endif
|
||||
// обновление статистики
|
||||
{.lastUpdate = 0, .periodMs = CACHE_STATISTICS_UPDATE_MS, .callback = [this]() {
|
||||
try {
|
||||
this->updateState();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateState(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateState(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша настроек
|
||||
{.lastUpdate = 0, .periodMs = CACHE_SETTINGS_UPDATE_MS, .callback = [this]() {
|
||||
try {
|
||||
this->updateSettings();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateSettings(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateSettings(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша настроек сети (делается отдельно)
|
||||
{.lastUpdate = 0, .periodMs = CACHE_SETTINGS_UPDATE_MS, .callback = [this]() {
|
||||
try {
|
||||
this->updateNetworkSettings();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateNetworkSettings(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateNetworkSettings(): " << e.what();
|
||||
}
|
||||
}},
|
||||
// обновление кеша QoS
|
||||
{.lastUpdate = 0, .periodMs = CACHE_QOS_UPDATE_MS, .callback = [this]() {
|
||||
try {
|
||||
this->updateQos();
|
||||
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateQos(): success update!";
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateQos(): " << e.what();
|
||||
}
|
||||
}}
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
#ifdef MODEM_IS_SCPC
|
||||
updaters[0].periodMs = this->statsLogs.logEn ? this->statsLogs.logPeriodMs.load() : -1;
|
||||
#endif
|
||||
int64_t sleepTime = 60000; // минута по-умолчанию
|
||||
auto now = TIME_NOW();
|
||||
for (auto& u: updaters) {
|
||||
if (u.checkNeedUpdate(now)) {
|
||||
auto targetTime = u.lastUpdate + u.periodMs;
|
||||
if (targetTime + SLEEP_THRESHOLD <= now && targetTime - SLEEP_THRESHOLD >= now) {
|
||||
u.lastUpdate = targetTime;
|
||||
} else {
|
||||
u.lastUpdate = now;
|
||||
}
|
||||
|
||||
u.callback();
|
||||
now = TIME_NOW();
|
||||
}
|
||||
if (u.periodMs >= 0) {
|
||||
sleepTime = std::min(sleepTime, u.getNextUpdate(now));
|
||||
}
|
||||
}
|
||||
|
||||
if (sleepTime > 0) {
|
||||
boost::this_thread::sleep_for(boost::chrono::duration(boost::chrono::milliseconds(sleepTime)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_mutex stateMutex;
|
||||
std::string deviceInitState;
|
||||
TerminalDeviceState state;
|
||||
|
||||
std::shared_mutex settingsMutex;
|
||||
modulator_settings modSettings{};
|
||||
demodulator_settings demodSettings{};
|
||||
#ifdef MODEM_IS_SCPC
|
||||
ACM_parameters_serv_ acmSettings{};
|
||||
#endif
|
||||
DPDI_parmeters dpdiSettings{};
|
||||
buc_lnb_settings bucLnbSettings{};
|
||||
|
||||
std::shared_mutex networkSettingsMutex;
|
||||
TerminalNetworkSettings networkSettings;
|
||||
|
||||
std::shared_mutex qosSettingsMutex;
|
||||
bool qosEnabled;
|
||||
std::string qosClassesJson;
|
||||
|
||||
std::shared_mutex firmwareMutex;
|
||||
TerminalFirmwareVersion firmware;
|
||||
|
||||
public:
|
||||
#ifdef MODEM_IS_SCPC
|
||||
StatisticsLogger statsLogs;
|
||||
#endif
|
||||
|
||||
std::mutex cpApiMutex;
|
||||
TSID sid;
|
||||
boost::thread daemon;
|
||||
|
||||
explicit TerminalApiDaemon(): deviceInitState("Not connected to API"), qosEnabled(false), sid(0), daemon([this]() { this->run(); }) {
|
||||
this->qosClassesJson = DEFAULT_QOS_CLASSES;
|
||||
}
|
||||
|
||||
std::string getDeviceInitState() {
|
||||
std::shared_lock lock(this->stateMutex);
|
||||
return this->deviceInitState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
*/
|
||||
TerminalDeviceState getState() {
|
||||
TerminalDeviceState s;
|
||||
{
|
||||
std::shared_lock lock(this->stateMutex);
|
||||
s = this->state;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
/**
|
||||
* Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
|
||||
*/
|
||||
void getSettings(
|
||||
modulator_settings* mod, demodulator_settings* demod,
|
||||
#ifdef MODEM_IS_SCPC
|
||||
ACM_parameters_serv_* acm,
|
||||
#endif
|
||||
DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) {
|
||||
if (mod || demod ||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
acm ||
|
||||
#endif
|
||||
dpdi || bucLnb) {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
if (mod) { *mod = this->modSettings; }
|
||||
if (demod) { *demod = this->demodSettings; }
|
||||
#ifdef MODEM_IS_SCPC
|
||||
if (acm) { *acm = this->acmSettings; }
|
||||
#endif
|
||||
if (dpdi) { *dpdi = this->dpdiSettings; }
|
||||
if (bucLnb) { *bucLnb = this->bucLnbSettings; }
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
bool getIsCinC() {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
return modSettings.is_cinc;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isTest() {
|
||||
std::shared_lock lock(this->settingsMutex);
|
||||
return modSettings.tx_is_on && (!modSettings.is_carrier
|
||||
#ifdef MODEM_IS_SCPC
|
||||
|| this->modSettings.is_test_data
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
void getNetworkSettings(TerminalNetworkSettings& dest) {
|
||||
std::shared_lock lock(this->networkSettingsMutex);
|
||||
dest = this->networkSettings;
|
||||
}
|
||||
|
||||
void getQosSettings(bool& isEnabled, std::string& json) {
|
||||
std::shared_lock lock(this->qosSettingsMutex);
|
||||
isEnabled = this->qosEnabled;
|
||||
json = this->qosClassesJson;
|
||||
}
|
||||
|
||||
#ifdef MODEM_IS_SCPC
|
||||
void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, ACM_parameters_serv_& acm, 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));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_SetAcmParams()", CP_SetAcmParams(this->sid, acm));
|
||||
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));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsRxTx()->CP_GetAcmParams()", CP_GetAcmParams(this->sid, &acm));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->modSettings = mod;
|
||||
this->demodSettings = demod;
|
||||
this->acmSettings = acm;
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
void setSettingsDpdi(DPDI_parmeters& s, bool readback = true) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDpdiParams()", CP_SetDpdiParams(sid, s));
|
||||
if (readback) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_GetDpdiParams()", CP_GetDpdiParams(this->sid, &s));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->dpdiSettings = s;
|
||||
}
|
||||
}
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsDpdi()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_SetBUC_LNB_settings()", CP_SetBUC_LNB_settings(this->sid, bucLnb));
|
||||
if (readback) {
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setSettingsBucLnb()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(this->sid, bucLnb));
|
||||
{
|
||||
std::lock_guard lock2{this->settingsMutex};
|
||||
this->bucLnbSettings = bucLnb;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetQoSSettings()", CP_SetQoSSettings(this->sid, str, enabled));
|
||||
if (readback) {
|
||||
bool tmp1; std::string tmp2;
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_GetQoSSettings()", CP_GetQoSSettings(this->sid, tmp2, tmp1));
|
||||
{
|
||||
std::lock_guard lock2(this->qosSettingsMutex);
|
||||
this->qosEnabled = tmp1;
|
||||
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
|
||||
}
|
||||
}
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setQosSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
void setNetworkSettings(TerminalNetworkSettings& s, bool readback = true) {
|
||||
// const auto mang = splitIpAndMask();
|
||||
// std::pair<std::string, std::string> data;
|
||||
// if (!s.isL2) {
|
||||
// data = splitIpAndMask(s.dataIp);
|
||||
// }
|
||||
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
unsafStoreNetworkSettings(s);
|
||||
|
||||
if (readback) {
|
||||
unsafeLoadNetworkSettings(s);
|
||||
{
|
||||
std::lock_guard lock2(this->networkSettingsMutex);
|
||||
this->networkSettings = s;
|
||||
}
|
||||
}
|
||||
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() {
|
||||
std::string tmp;
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetPacketStatistics()->CP_GetDmaDebug(reset_cnt_rx)", CP_GetDmaDebug(sid, "reset_cnt_rx", &tmp));
|
||||
}
|
||||
|
||||
void resetDefaultSettings() {
|
||||
std::lock_guard lock(this->cpApiMutex);
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(default_params)", CP_SetDmaDebug(sid, "default_params", ""));
|
||||
logCpApiError("api_driver::TerminalApiDaemon::resetDefaultSettings()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", ""));
|
||||
}
|
||||
|
||||
~TerminalApiDaemon() {
|
||||
try {
|
||||
daemon.interrupt();
|
||||
daemon.try_join_for(boost::chrono::seconds(2));
|
||||
} catch (std::exception& e) {
|
||||
BOOST_LOG_TRIVIAL(error) << "api_driver::~TerminalApiDaemon(): " << e.what();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
api_driver::ApiDriver::ApiDriver() = default;
|
||||
|
||||
@ -794,4 +1378,41 @@ void api_driver::ApiDriver::setLoggingStatisticsSettings(boost::property_tree::p
|
||||
}
|
||||
#endif
|
||||
|
||||
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 */
|
||||
// };
|
||||
|
||||
const double f_load = 100.0 / ((1 << SI_LOAD_SHIFT) * get_nprocs());
|
||||
|
||||
result << "{\n\"uptime\":" << info.uptime;
|
||||
result << ",\"load1min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[0]), 2);
|
||||
result << ",\"load5min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[1]), 2);
|
||||
result << ",\"load15min\":"; writeDouble(result, f_load * static_cast<double>(info.loads[2]), 2);
|
||||
result << ",\"totalram\":" << ((info.totalram * info.mem_unit) >> 20); // Mb
|
||||
result << ",\"freeram\":" << ((info.freeram * info.mem_unit) >> 20); // Mb
|
||||
// result << ",\"sharedram\":" << ((info.sharedram * info.mem_unit) >> 20); // Mb
|
||||
// result << ",\"bufferram\":" << ((info.bufferram * info.mem_unit) >> 20); // Mb
|
||||
// result << ",\"totalswap\":" << info.totalswap * info.mem_unit;
|
||||
// result << ",\"freeswap\":" << info.freeswap * info.mem_unit;
|
||||
result << ",\"procs\":" << static_cast<long>(info.procs);
|
||||
result << "\n}";
|
||||
return result.str();
|
||||
}
|
||||
|
||||
api_driver::ApiDriver::~ApiDriver() = default;
|
||||
|
@ -1,6 +1,7 @@
|
||||
#ifndef TERMINAL_API_DRIVER_H
|
||||
#define TERMINAL_API_DRIVER_H
|
||||
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
|
@ -1,764 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>ШПС Модем</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>
|
||||
<body>
|
||||
|
||||
<div id="app" hidden>
|
||||
<header>
|
||||
<span class="nav-bar-element">Прием: <span :class="{ indicator_bad: statRx.state === false, indicator_good: statRx.state === true, indicator: true }"></span></span>
|
||||
<span class="nav-bar-element">Передача: <span :class="{ indicator_good: statTx.state === true, indicator: true }"></span></span>
|
||||
<span class="nav-bar-element">Тест: <span :class="{ indicator_good: testState, indicator: true }"></span></span>
|
||||
<!-- Последнее обновление: {{ lastUpdateTime }}-->
|
||||
<span :class="{ value_bad: initState !== 'Успешная инициализация системы' }">{{ initState }}</span>
|
||||
<div class="tabs-header">
|
||||
<span style="font-weight:bold">ШПС Модем</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="#admin" class="tabs-btn" @click="activeTab = 'admin'" :class="{ active: activeTab === 'admin' }">Администрирование</a>
|
||||
<a href="/logout" class="tabs-btn">Выход</a>
|
||||
</div>
|
||||
</header>
|
||||
<div id="content">
|
||||
|
||||
<div class="tabs-body-item tabs-item-flex-container" v-if="activeTab === 'monitoring'">
|
||||
<div class="settings-set-container statistics-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>ОСШ/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 }} кбит/с</td></tr>
|
||||
<tr><th>Инф. скорость на интерфейсе</th><td>{{ statRx.speedOnIifKbit }} кбит/с</td></tr>
|
||||
<tr><td colspan="2" style="padding-top: 1em; text-align: center">Статистика пакетов</td></tr>
|
||||
<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 statistics-container">
|
||||
<h2>Статистика передачи</h2>
|
||||
<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 }} кбит/с</td></tr>
|
||||
<tr><th>Инф. скорость на интерфейсе</th><td>{{ statTx.speedOnIifKbit }} кбит/с</td></tr>
|
||||
<tr><th>Центральная частота</th><td>{{ statTx.centerFreq }} кГц</td></tr>
|
||||
<tr><th>Символьная скорость</th><td>{{ statTx.symSpeed }} ksymb</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="settings-set-container statistics-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>Время работы устройства</th><td>{{ statOs.uptime }}</td></tr>
|
||||
<tr><th>Средняя загрузка ЦП (1/5/15 мин.)</th><td>{{ statOs.load1 }}% {{ statOs.load5 }}% {{ statOs.load15 }}%</td></tr>
|
||||
<tr><th>ОЗУ всего/свободно</th><td>{{ statOs.totalram }}МБ/{{ statOs.freeram }}МБ</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tabs-body-item" v-if="activeTab === 'setup' && settingFetchComplete">
|
||||
<h2>Настройки приема/передачи</h2>
|
||||
<div class="tabs-item-flex-container">
|
||||
<div class="settings-set-container">
|
||||
<h3>Настройки передатчика</h3>
|
||||
<label>
|
||||
<span>Включить передатчик</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramRxtx.txEn" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Автоматический запуск передатчика</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramRxtx.txAutoStart" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Режим работы модулятора</span>
|
||||
<select v-model="paramRxtx.txModulatorIsTest">
|
||||
<option :value="false">Нормальный</option>
|
||||
<option :value="true">Тест (CW)</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>Входные данные</span>
|
||||
<select v-model="paramRxtx.txIsTestInput">
|
||||
<option :value="false">Ethernet</option>
|
||||
<option :value="true">Тест</option>
|
||||
</select>
|
||||
</label>
|
||||
<h3>Параметры передачи</h3>
|
||||
<label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.txCentralFreq" min="950000" max="6000000" step="0.01"/></label>
|
||||
<label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.txBaudrate" min="200000" max="54000000"/></label>
|
||||
<label>
|
||||
<span>Roll-off</span>
|
||||
<select v-model="paramRxtx.txRolloff">
|
||||
<option :value="2">0.02</option>
|
||||
<option :value="5">0.05</option>
|
||||
<option :value="10">0.10</option>
|
||||
<option :value="15">0.15</option>
|
||||
<option :value="20">0.20</option>
|
||||
<option :value="25">0.25</option>
|
||||
</select>
|
||||
</label>
|
||||
<label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.txSpreadCoef" min="-1000" max="1000" step="0.01"/></label>
|
||||
<label>
|
||||
<span>Номер последовательности Голда</span>
|
||||
<select v-model="paramRxtx.txGoldan">
|
||||
<option :value="0">0</option>
|
||||
<option :value="1">1</option>
|
||||
</select>
|
||||
</label>
|
||||
<label><span>Ослабление, дБ</span><input type="number" v-model="paramRxtx.txAttenuation" min="-40" step="0.25"/></label>
|
||||
</div>
|
||||
<div class="settings-set-container">
|
||||
<h3>Настройки приемника</h3>
|
||||
<label>
|
||||
<span>Режим управления усилением</span>
|
||||
<select v-model="paramRxtx.rxAgcEn">
|
||||
<option :value="false">РРУ</option>
|
||||
<option :value="true">АРУ</option>
|
||||
</select>
|
||||
</label>
|
||||
<label v-show="paramRxtx.rxAgcEn === false"><span>Усиление, дБ</span><input type="number" v-model="paramRxtx.rxManualGain" min="-40" max="40" step="0.01"/></label>
|
||||
<label v-show="paramRxtx.rxAgcEn === true">
|
||||
<span>Текущее усиление</span><span>{{ paramRxtx.rxManualGain }}</span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Инверсия спектра</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramRxtx.rxSpectrumInversion" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label><span>Центральная частота, КГц</span><input type="number" v-model="paramRxtx.rxCentralFreq" min="950000" max="6000000" step="0.01"/></label>
|
||||
<label><span>Символьная скорость, Бод</span><input type="number" v-model="paramRxtx.rxBaudrate" min="200000" max="54000000"/></label>
|
||||
<label>
|
||||
<span>Roll-off</span>
|
||||
<select v-model="paramRxtx.rxRolloff">
|
||||
<option :value="2">0.02</option>
|
||||
<option :value="5">0.05</option>
|
||||
<option :value="10">0.10</option>
|
||||
<option :value="15">0.15</option>
|
||||
<option :value="20">0.20</option>
|
||||
<option :value="25">0.25</option>
|
||||
</select>
|
||||
</label>
|
||||
<label><span>Коэф. расширения</span><input type="number" v-model="paramRxtx.rxSpreadCoef" min="-1000" max="1000" step="0.01"/></label>
|
||||
<label>
|
||||
<span>Номер последовательности Голда</span>
|
||||
<select v-model="paramRxtx.rxGoldan">
|
||||
<option :value="0">0</option>
|
||||
<option :value="1">1</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="action-button" @click="settingsSubmitRxtx()">Сохранить <span class="submit-spinner" v-show="submitStatus.rxtx"></span></button>
|
||||
<h2>Настройки питания и опорного генератора</h2>
|
||||
<div class="tabs-item-flex-container">
|
||||
<div class="settings-set-container">
|
||||
<h3>Настройки BUC</h3>
|
||||
<label>
|
||||
<span>Подача опоры 10МГц</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramBuclnb.bucRefClk10M" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Питание BUC</span>
|
||||
<select v-model="paramBuclnb.bucPowering">
|
||||
<option :value="0">Выкл</option>
|
||||
<option :value="24">24В</option>
|
||||
<option :value="48">48В</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-set-container">
|
||||
<h3>Настройки LNB</h3>
|
||||
<label>
|
||||
<span>Подача опоры 10МГц</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramBuclnb.lnbRefClk10M" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Питание LNB</span>
|
||||
<select v-model="paramBuclnb.lnbPowering">
|
||||
<option :value="0">Выкл</option>
|
||||
<option :value="13">13В</option>
|
||||
<option :value="18">18В</option>
|
||||
<option :value="24">24В</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<div class="settings-set-container">
|
||||
<h3>Сервисные настройки</h3>
|
||||
<label>
|
||||
<span>Подача опоры 10МГц на 'Выход 10МГц'</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramBuclnb.srvRefClk10M" /><span class="slider"></span></span>
|
||||
</label>
|
||||
<label>
|
||||
<span>Автозапуск BUC и LNB при включении</span>
|
||||
<span class="toggle-input"><input type="checkbox" v-model="paramBuclnb.bucLnbAutoStart" /><span class="slider"></span></span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<button class="action-button" @click="settingsSubmitBuclnb()">Сохранить <span class="submit-spinner" v-show="submitStatus.buclnb"></span></button>
|
||||
</div> <div class="tabs-body-item" v-if="activeTab === 'admin' && settingFetchComplete">
|
||||
|
||||
<h2>Система</h2>
|
||||
<div class="settings-set-container statistics-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>
|
||||
</div>
|
||||
|
||||
<h2>Обновление ПО</h2>
|
||||
<div class="settings-set-container statistics-container">
|
||||
<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>
|
||||
</div>
|
||||
<p>Последнее обновление статистики: {{ lastUpdateTime }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/vue.js?v=3.5.13"></script>
|
||||
<script>
|
||||
const availableTabs = ['monitoring', 'setup', 'admin']
|
||||
|
||||
// для обновления высоты хидера
|
||||
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 availableTabs[0]
|
||||
}
|
||||
|
||||
function toLocaleStringWithSpaces(num) {
|
||||
if (typeof num !== 'number') {
|
||||
if (typeof num === 'string') { return num }
|
||||
return String(num);
|
||||
}
|
||||
const numberString = num.toString()
|
||||
const [integerPart, fractionalPart] = numberString.split('.')
|
||||
const spacedIntegerPart = integerPart.replace(/\B(?=(\d{3})+(?!\d))/g, " ")
|
||||
if (fractionalPart) { return `${spacedIntegerPart}.${fractionalPart}` }
|
||||
else { return spacedIntegerPart }
|
||||
}
|
||||
|
||||
const app = Vue.createApp({
|
||||
data() {
|
||||
return {
|
||||
// false - означает что статистика не отправляется, true - отправляется
|
||||
submitStatus: {
|
||||
rxtx: false,
|
||||
buclnb: false,
|
||||
firmwareUpload: false,
|
||||
firmwareUpgrade: false,
|
||||
// когда модем перезагружается, тут должен быть счетчик. Направление счета - к нулю
|
||||
modemReboot: null
|
||||
},
|
||||
|
||||
// ========== include from 'common/all-params-data.js.j2'
|
||||
paramRxtx: {
|
||||
txEn: false,
|
||||
txAutoStart: false,
|
||||
txModulatorIsTest: false,
|
||||
txIsTestInput: false,
|
||||
txCentralFreq: 950000,
|
||||
txBaudrate: 200000,
|
||||
txRolloff: 2,
|
||||
txSpreadCoef: -1000,
|
||||
txGoldan: 0,
|
||||
txAttenuation: -40,
|
||||
rxAgcEn: false,
|
||||
rxManualGain: -40,
|
||||
rxSpectrumInversion: false,
|
||||
rxCentralFreq: 950000,
|
||||
rxBaudrate: 200000,
|
||||
rxRolloff: 2,
|
||||
rxSpreadCoef: -1000,
|
||||
rxGoldan: 0,
|
||||
},
|
||||
paramBuclnb: {
|
||||
bucRefClk10M: false,
|
||||
bucPowering: 0,
|
||||
lnbRefClk10M: false,
|
||||
lnbPowering: 0,
|
||||
srvRefClk10M: false,
|
||||
bucLnbAutoStart: false,
|
||||
},
|
||||
// ========== include end from 'common/all-params-data.js.j2'
|
||||
|
||||
// ========== include from 'common/monitoring-data.js.j2'
|
||||
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: '?',
|
||||
|
||||
// прочие поля
|
||||
modcod: '?', speedOnTxKbit: '?', speedOnIifKbit: '?', centerFreq: '?', symSpeed: '?'
|
||||
},
|
||||
statDevice: { // температурные датчики
|
||||
adrv: 0, zynq: 0, fpga: 0
|
||||
},
|
||||
statOs: {uptime: '?', load1: '?', load5: '?', load15: '?', totalram: '?', freeram: '?'},
|
||||
// ========== include end from 'common/monitoring-data.js.j2'
|
||||
|
||||
// ========== include from 'common/setup-data.js.j2'
|
||||
// ========== include end from 'common/setup-data.js.j2'
|
||||
|
||||
// ========== include from 'common/admin-data.js.j2'
|
||||
// ========== include end from 'common/admin-data.js.j2'
|
||||
|
||||
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: {
|
||||
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 ""
|
||||
},
|
||||
getAvailableModcods(modulation) {
|
||||
// NOTE модкоды со скоростью хода 3/5 не работают
|
||||
switch (modulation) {
|
||||
case 'qpsk':
|
||||
return ['1/4', '1/3', '2/5', '1/2', '3/5', '2/3', '3/4', '4/5', '5/6', '8/9', '9/10']
|
||||
case '8psk':
|
||||
return ['3/5', '2/3', '3/4', '5/6', '8/9', '9/10']
|
||||
case '16apsk':
|
||||
return ['2/3', '3/4', '4/5', '5/6', '8/9', '9/10']
|
||||
case '32apsk':
|
||||
return ['3/4', '4/5', '5/6', '8/9', '9/10']
|
||||
default:
|
||||
return []
|
||||
}
|
||||
},
|
||||
inputFormatNumber(src, validation) {
|
||||
if (validation === null || validation === undefined) { validation = {} }
|
||||
const rawVal = src.toString().replace(/[^0-9.,]/g, '').replace(',', '.')
|
||||
let result = rawVal === '' ? 0 : parseFloat(rawVal)
|
||||
const step = 'step' in validation ? validation['step']: 1.0
|
||||
result = Math.round(result / step) * step
|
||||
if ('min' in validation) { if (result <= validation['min']) { result = validation['min'] } }
|
||||
if ('max' in validation) { if (result >= validation['max']) { result = validation['max'] } }
|
||||
return toLocaleStringWithSpaces(result)
|
||||
},
|
||||
|
||||
// ========== include from 'common/all-params-methods.js.j2'
|
||||
settingsSubmitRxtx() {
|
||||
if (this.submitStatus.rxtx) { return }
|
||||
|
||||
let query = {
|
||||
"txEn": this.paramRxtx.txEn,
|
||||
"txAutoStart": this.paramRxtx.txAutoStart,
|
||||
"txModulatorIsTest": this.paramRxtx.txModulatorIsTest,
|
||||
"txIsTestInput": this.paramRxtx.txIsTestInput,
|
||||
"txCentralFreq": this.paramRxtx.txCentralFreq,
|
||||
"txBaudrate": this.paramRxtx.txBaudrate,
|
||||
"txRolloff": this.paramRxtx.txRolloff,
|
||||
"txSpreadCoef": this.paramRxtx.txSpreadCoef,
|
||||
"txGoldan": this.paramRxtx.txGoldan,
|
||||
"txAttenuation": this.paramRxtx.txAttenuation,
|
||||
"rxAgcEn": this.paramRxtx.rxAgcEn,
|
||||
"rxManualGain": this.paramRxtx.rxManualGain,
|
||||
"rxSpectrumInversion": this.paramRxtx.rxSpectrumInversion,
|
||||
"rxCentralFreq": this.paramRxtx.rxCentralFreq,
|
||||
"rxBaudrate": this.paramRxtx.rxBaudrate,
|
||||
"rxRolloff": this.paramRxtx.rxRolloff,
|
||||
"rxSpreadCoef": this.paramRxtx.rxSpreadCoef,
|
||||
"rxGoldan": this.paramRxtx.rxGoldan,
|
||||
}
|
||||
|
||||
this.submitStatus.rxtx = true
|
||||
fetch('/api/set/rxtx', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' })
|
||||
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.updateRxtxSettings(vals) })
|
||||
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
|
||||
.finally(() => { this.submitStatus.rxtx = false })
|
||||
},
|
||||
settingsSubmitBuclnb() {
|
||||
if (this.submitStatus.buclnb) { return }
|
||||
{ if (!confirm("Применение неправильных настроек может вывести из строя оборудование! Продолжить?")) return }
|
||||
|
||||
let query = {
|
||||
"bucRefClk10M": this.paramBuclnb.bucRefClk10M,
|
||||
"bucPowering": this.paramBuclnb.bucPowering,
|
||||
"lnbRefClk10M": this.paramBuclnb.lnbRefClk10M,
|
||||
"lnbPowering": this.paramBuclnb.lnbPowering,
|
||||
"srvRefClk10M": this.paramBuclnb.srvRefClk10M,
|
||||
"bucLnbAutoStart": this.paramBuclnb.bucLnbAutoStart,
|
||||
}
|
||||
|
||||
this.submitStatus.buclnb = true
|
||||
fetch('/api/set/buclnb', {method: 'POST', headers: {'Content-Type': 'application/json'}, body: JSON.stringify(query), credentials: 'same-origin' })
|
||||
.then(async (resp) => { let vals = await resp.json(); if (vals['status'] !== 'ok') { throw new Error(vals['error'] ? vals['error'] : "Server returns undefined error") } this.updateBuclnbSettings(vals) })
|
||||
.catch((reason) => { alert(`Ошибка при применении настроек: ${reason}`) })
|
||||
.finally(() => { this.submitStatus.buclnb = false })
|
||||
},
|
||||
|
||||
updateRxtxSettings(vals) {
|
||||
this.submitStatus.rxtx = false
|
||||
this.paramRxtx.txEn = vals["settings"]["txEn"]
|
||||
this.paramRxtx.txAutoStart = vals["settings"]["txAutoStart"]
|
||||
this.paramRxtx.txModulatorIsTest = vals["settings"]["txModulatorIsTest"]
|
||||
this.paramRxtx.txIsTestInput = vals["settings"]["txIsTestInput"]
|
||||
this.paramRxtx.txCentralFreq = vals["settings"]["txCentralFreq"]
|
||||
this.paramRxtx.txBaudrate = vals["settings"]["txBaudrate"]
|
||||
this.paramRxtx.txRolloff = vals["settings"]["txRolloff"]
|
||||
this.paramRxtx.txSpreadCoef = vals["settings"]["txSpreadCoef"]
|
||||
this.paramRxtx.txGoldan = vals["settings"]["txGoldan"]
|
||||
this.paramRxtx.txAttenuation = vals["settings"]["txAttenuation"]
|
||||
this.paramRxtx.rxAgcEn = vals["settings"]["rxAgcEn"]
|
||||
this.paramRxtx.rxManualGain = vals["settings"]["rxManualGain"]
|
||||
this.paramRxtx.rxSpectrumInversion = vals["settings"]["rxSpectrumInversion"]
|
||||
this.paramRxtx.rxCentralFreq = vals["settings"]["rxCentralFreq"]
|
||||
this.paramRxtx.rxBaudrate = vals["settings"]["rxBaudrate"]
|
||||
this.paramRxtx.rxRolloff = vals["settings"]["rxRolloff"]
|
||||
this.paramRxtx.rxSpreadCoef = vals["settings"]["rxSpreadCoef"]
|
||||
this.paramRxtx.rxGoldan = vals["settings"]["rxGoldan"]
|
||||
},
|
||||
updateBuclnbSettings(vals) {
|
||||
this.submitStatus.buclnb = false
|
||||
this.paramBuclnb.bucRefClk10M = vals["settings"]["bucRefClk10M"]
|
||||
this.paramBuclnb.bucPowering = vals["settings"]["bucPowering"]
|
||||
this.paramBuclnb.lnbRefClk10M = vals["settings"]["lnbRefClk10M"]
|
||||
this.paramBuclnb.lnbPowering = vals["settings"]["lnbPowering"]
|
||||
this.paramBuclnb.srvRefClk10M = vals["settings"]["srvRefClk10M"]
|
||||
this.paramBuclnb.bucLnbAutoStart = vals["settings"]["bucLnbAutoStart"]
|
||||
},
|
||||
// ========== include end from 'common/all-params-methods.js.j2'
|
||||
|
||||
// ========== include from 'common/monitoring-methods.js.j2'
|
||||
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") {
|
||||
return "?";
|
||||
}
|
||||
if (modcod < 0 || modcod >= modcods.length) {
|
||||
return `? (${modcod})`
|
||||
}
|
||||
return modcods[modcod]
|
||||
}
|
||||
|
||||
this.lastUpdateTime = new Date();
|
||||
this.initState = vals["mainState"]["initState"]
|
||||
|
||||
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"]
|
||||
|
||||
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"]
|
||||
|
||||
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} дней, ` + 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', credentials: 'same-origin'
|
||||
}).then(() => {
|
||||
this.statRx.packetsOk = 0
|
||||
this.statRx.packetsBad = 0
|
||||
this.statRx.packetsDummy = 0
|
||||
})
|
||||
},
|
||||
// ========== include end from 'common/monitoring-methods.js.j2'
|
||||
|
||||
// ========== include from 'common/setup-methods.js.j2'
|
||||
// ========== include end from 'common/setup-methods.js.j2'
|
||||
|
||||
// ========== include from 'common/admin-methods.js.j2'
|
||||
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) => {})
|
||||
}, // ========== include end from 'common/admin-methods.js.j2'
|
||||
|
||||
|
||||
performUpdateSettings() {
|
||||
const doFetchSettings = async () => {
|
||||
let d = await fetch("/api/get/settings")
|
||||
let vals = await d.json()
|
||||
this.settingFetchComplete = true
|
||||
this.updateRxtxSettings(vals)
|
||||
this.updateBuclnbSettings(vals)
|
||||
|
||||
if ('netServerName' in vals['settings']) {
|
||||
document.getElementsByTagName('title')[0].innerText = vals['settings']['netServerName']
|
||||
}
|
||||
}
|
||||
|
||||
doFetchSettings().then(() => {})
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
const doFetchStatistics = async () => {
|
||||
if (this.submitStatus.modemReboot !== null) {
|
||||
this.initState = `Перезагрузка модема... Осталось ${this.submitStatus.modemReboot} сек`
|
||||
this.submitStatus.modemReboot--
|
||||
if (this.submitStatus.modemReboot <= 0) {
|
||||
window.location.reload()
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
let d = await fetch("/api/get/statistics", { credentials: 'same-origin' })
|
||||
this.updateStatistics(await d.json())
|
||||
} catch (e) {
|
||||
this.initState = "Ошибка обновления статистики"
|
||||
}
|
||||
}
|
||||
setTimeout(() => {
|
||||
doFetchStatistics()
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const doFetchAbout = async () => {
|
||||
try {
|
||||
const fr = await fetch("/api/get/aboutFirmware")
|
||||
const d = await fr.json()
|
||||
this.about.firmwareVersion = d["fw.version"]
|
||||
this.about.modemUid = d["fw.modemId"]
|
||||
this.about.modemSn = d["fw.modemSn"]
|
||||
this.about.macManagement = d["fw.macMang"]
|
||||
this.about.macData = d["fw.macData"]
|
||||
} catch (e) {
|
||||
console.log('Ошибка загрузки версии ПО', e)
|
||||
}
|
||||
}
|
||||
|
||||
doFetchStatistics().then(() => {})
|
||||
doFetchAbout().then(() => {})
|
||||
|
||||
this.performUpdateSettings()
|
||||
|
||||
document.getElementById("app").removeAttribute("hidden")
|
||||
}
|
||||
});
|
||||
app.mount('#app')
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user