terminal-web-server/src/terminal_api_driver.cpp

660 lines
27 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "terminal_api_driver.h"
#include <cmath>
#include "terminal_api/ControlProtoCInterface.h"
#include <sstream>
#include <iomanip>
#include <shared_mutex>
#include <boost/thread.hpp>
#include <boost/log/trivial.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "../dependencies/control_system/common/protocol_commands.h"
typedef boost::property_tree::ptree::path_type json_path;
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
/**
* Этот демон нужен для того, чтобы получать статистику из API, а так же корректно сохранять настройки
*/
class api_driver::TerminalApiDaemon {
private:
TSID sid;
boost::thread daemon;
void updateStatistics() {
modulator_state modulator{};
demodulator_state demodulator{};
device_state device{};
std::lock_guard lock(this->cpApiMutex);
CP_GetModulatorState(sid, modulator);
CP_GetDemodulatorState(sid, demodulator);
CP_GetDeviceState(sid, device);
{
std::lock_guard lock2(this->stateMutex);
this->modState = modulator;
this->demodState = demodulator;
this->devState = device;
}
}
void updateSettings() {
modulator_settings mod{};
// uint32_t modulatorModcod;
// CP_GetModulatorParams(sid, "modcod", &modulatorModcod);
demodulator_settings demod{};
ACM_parameters_serv_ acm{};
DPDI_parmeters dpdi{};
buc_lnb_settings bucLnb{};
std::lock_guard lock(this->cpApiMutex);
CP_GetModulatorSettings(sid, mod);
CP_GetDemodulatorSettings(sid, demod);
CP_GetAcmParams(sid, &acm);
CP_GetDpdiParams(sid, &dpdi);
CP_GetBUC_LNB_settings(sid, bucLnb);
{
std::lock_guard lock2(this->settingsMutex);
this->modSettings = mod;
this->demodSettings = demod;
this->acmSettings = acm;
this->dpdiSettings = dpdi;
this->bucLnbSettings = bucLnb;
}
}
void updateQos() {
bool tmp1; std::string tmp2;
std::scoped_lock lock{this->cpApiMutex};
CP_GetQoSSettings(this->sid, tmp2, tmp1);
{
std::lock_guard lock2(this->qosSettingsMutex);
this->qosEnabled = tmp1;
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
}
}
void run() {
// это демон, который в бесконечном цикле опрашивает API
struct IntervalUpdate_t {
int64_t lastUpdate;
int64_t periodMs;
std::function<void()> callback;
bool checkNeedUpdate(int64_t now) const {
// тут нет смысла спать меньше чем на 20мс, поэтому можно разрешить чтение на некоторое время раньше
return now - lastUpdate >= (periodMs - 20);
}
int64_t getNextUpdate(int64_t now) const {
if (checkNeedUpdate(now)) {
return 0;
}
auto next = now - lastUpdate;
return next < 0 ? 0 : next;
}
};
IntervalUpdate_t updaters[] = {
// обновление статистики
{.lastUpdate = 0, .periodMs = CACHE_STATISTICS_UPDATE_MS, .callback = [this]() {
try {
this->updateStatistics();
BOOST_LOG_TRIVIAL(debug) << "api_driver::TerminalApiDaemon::updateStatistics(): success update!";
} catch (std::exception& e) {
BOOST_LOG_TRIVIAL(error) << "api_driver::TerminalApiDaemon::updateStatistics(): " << 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();
}
}},
// обновление кеша 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) {
int64_t sleepTime = 60000; // минута по-умолчанию
auto now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
for (auto& u: updaters) {
if (u.checkNeedUpdate(now)) {
u.lastUpdate = now;
u.callback();
now = std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
}
sleepTime = std::min(sleepTime, u.getNextUpdate(now));
}
if (sleepTime > 0) {
boost::this_thread::sleep_for(boost::chrono::duration(boost::chrono::milliseconds(sleepTime)));
}
}
}
std::mutex cpApiMutex;
std::shared_mutex stateMutex;
modulator_state modState{};
demodulator_state demodState{};
device_state devState{};
std::shared_mutex settingsMutex;
modulator_settings modSettings{};
demodulator_settings demodSettings{};
ACM_parameters_serv_ acmSettings{};
DPDI_parmeters dpdiSettings{};
buc_lnb_settings bucLnbSettings{};
std::shared_mutex qosSettingsMutex;
bool qosEnabled;
std::string qosClassesJson;
public:
explicit TerminalApiDaemon(TSID sid): sid(sid), daemon([this]() { this->run(); }), qosEnabled(false) {
this->qosClassesJson = DEFAULT_QOS_CLASSES;
}
/**
* Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
* @param mod статистика модулятра
* @param demod статистика демодулятора
* @param dev статистика устройства (температуры)
*/
void getStatistics(modulator_state* mod, demodulator_state* demod, device_state* dev) {
if (mod != nullptr || demod != nullptr || dev != nullptr) {
std::shared_lock lock(this->stateMutex);
if (mod) { *mod = this->modState; }
if (demod) { *demod = this->demodState; }
if (dev) { *dev = this->devState; }
}
}
/**
* Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет.
*/
void getSettings(modulator_settings* mod, demodulator_settings* demod, ACM_parameters_serv_* acm, DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) {
if (mod || demod || acm || dpdi || bucLnb) {
std::shared_lock lock(this->settingsMutex);
if (mod) { *mod = this->modSettings; }
if (demod) { *demod = this->demodSettings; }
if (acm) { *acm = this->acmSettings; }
if (dpdi) { *dpdi = this->dpdiSettings; }
if (bucLnb) { *bucLnb = this->bucLnbSettings; }
}
}
void getQosSettings(bool& isEnabled, std::string& json) {
std::shared_lock lock(this->settingsMutex);
isEnabled = this->qosEnabled;
json = this->qosClassesJson;
}
void setSettingsRxTx(modulator_settings& mod, demodulator_settings& demod, ACM_parameters_serv_& acm, bool readback = true) {
std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", "");
CP_SetModulatorSettings(this->sid, mod);
CP_SetDemodulatorSettings(this->sid, demod);
CP_SetAcmParams(this->sid, acm);
if (readback) {
CP_GetModulatorSettings(this->sid, mod);
CP_GetDemodulatorSettings(this->sid, demod);
CP_GetAcmParams(this->sid, &acm);
{
std::lock_guard lock2{this->settingsMutex};
this->modSettings = mod;
this->demodSettings = demod;
this->acmSettings = acm;
}
}
CP_SetDmaDebug(sid, "save_config", "");
}
void setSettingsCinc(DPDI_parmeters& s, bool readback = true) {
std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", "");
CP_SetDpdiParams(sid, s);
if (readback) {
CP_GetDpdiParams(this->sid, &s);
{
std::lock_guard lock2{this->settingsMutex};
this->dpdiSettings = s;
}
}
CP_SetDmaDebug(sid, "save_config", "");
}
void setSettingsBucLnb(buc_lnb_settings& bucLnb, bool readback = true) {
std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", "");
CP_SetBUC_LNB_settings(this->sid, bucLnb);
if (readback) {
CP_GetBUC_LNB_settings(this->sid, bucLnb);
{
std::lock_guard lock2{this->settingsMutex};
this->bucLnbSettings = bucLnb;
}
}
CP_SetDmaDebug(sid, "save_config", "");
}
void setQosSettings(bool enabled, const std::string& str, bool readback = true) {
std::lock_guard lock(this->cpApiMutex);
CP_SetDmaDebug(sid, "begin_save_config", "");
CP_SetQoSSettings(this->sid, str, enabled);
if (readback) {
bool tmp1; std::string tmp2;
CP_GetQoSSettings(this->sid, tmp2, tmp1);
{
std::lock_guard lock2(this->qosSettingsMutex);
this->qosEnabled = tmp1;
this->qosClassesJson = tmp2.empty() ? DEFAULT_QOS_CLASSES : tmp2;
}
}
CP_SetDmaDebug(sid, "save_config", "");
}
void resetPacketStatistics() {
std::string tmp;
std::lock_guard lock(this->cpApiMutex);
CP_GetDmaDebug(sid, "reset_cnt_rx", &tmp);
}
~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() {
CP_Login("admin", "pass", &sid, &access);
CP_GetDmaDebug(sid, "status_init", &deviceInitState);
}
void api_driver::ApiDriver::startDaemon() {
if (daemon == nullptr) {
daemon = std::make_unique<TerminalApiDaemon>(this->sid);
BOOST_LOG_TRIVIAL(info) << "api_driver::ApiDriver::startDaemon(): API daemon succes started!";
}
}
static const char* boolAsStr(bool value) {
return value ? "true" : "false";
}
static std::string buildEscapedString(const std::string& source) {
std::string str(source);
size_t start_pos = 0;
while((start_pos = str.find('\"', start_pos)) != std::string::npos) {
str.replace(start_pos, 1, "\\\"");
start_pos += 2;
}
return "\"" + str + "\"";
}
void writeDouble(std::ostream& out, double value, int prec = 2) {
if (std::isnan(value) || std::isinf(value)) {
out << "\"nan\"";
} else {
out << std::fixed << std::setprecision(prec) << value;
}
}
double translateCoordinates(uint8_t deg, uint8_t min) {
return static_cast<double>(deg) + static_cast<double>(min) / 60;
}
std::tuple<uint8_t, uint8_t> translateCoordinates(double abs) {
auto deg = static_cast<uint8_t>(abs);
double min_double = (abs - deg) * 60;
auto min = static_cast<uint8_t>(min_double);
return std::make_tuple(deg, min);
}
std::string api_driver::ApiDriver::loadTerminalState() const {
if (daemon == nullptr) {
return R"({"error": "api daemon not started!"})";
}
std::stringstream result;
result << "{\n\"initState\":" << buildEscapedString(this->deviceInitState);
modulator_state modulator{};
demodulator_state demodulator{};
device_state device{};
daemon->getStatistics(&modulator, &demodulator, &device);
const bool isCinC = this->getIsCinC();
result << ",\"isCinC\":" << boolAsStr(isCinC);
// формируем структуру для TX
result << ",\n\"tx.state\":" << boolAsStr(modulator.is_tx_on);
result << ",\"tx.modcod\":" << modulator.modcod;
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)";
}
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;
// формируем структуру для CinC
if (isCinC) {
CinC_state state_cinc{};
CP_GetCinCState(sid,state_cinc);
if (modulator.is_tx_on) {
if (state_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, state_cinc.ratio_signal_signal, 3);
result << ",\"cinc.correlatorFails\":" << state_cinc.cnt_bad_lock;
result << ",\"cinc.freqErr\":" << state_cinc.freq_error_offset;
result << ",\"cinc.freqErrAcc\":" << state_cinc.freq_fine_estimate;
result << ",\"cinc.channelDelay\":" << state_cinc.delay_dpdi;
} else {
result << R"(,"cinc.correlator":null)";
}
// структура температур девайса
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);
result << "}";
return result.str();
}
void api_driver::ApiDriver::resetPacketStatistics() const {
this->daemon->resetPacketStatistics();
}
std::string api_driver::ApiDriver::loadSettings() const {
if (daemon == nullptr) {
return R"({"error": "api daemon not started!"})";
}
modulator_settings modSettings{};
demodulator_settings demodSettings{};
ACM_parameters_serv_ acmSettings{};
DPDI_parmeters dpdiSettings{};
buc_lnb_settings bucLnb{};
daemon->getSettings(&modSettings, &demodSettings, &acmSettings, &dpdiSettings, &bucLnb);
// uint32_t modulatorModcod;
// {
// modulator_state ms{};
// daemon->getStatistics(&ms, nullptr, nullptr);
// modulatorModcod = ms.modcod;
// }
std::stringstream result;
result << "{\n\"general.isCinC\":" << boolAsStr(modSettings.is_cinc);
result << ",\"general.txEn\":" << boolAsStr(modSettings.tx_is_on);
result << ",\"general.modulatorMode\":" << (modSettings.is_carrier ? "\"normal\"" : "\"test\"");
result << ",\"general.autoStartTx\":" << boolAsStr(modSettings.is_save_current_state);
result << ",\"general.isTestInputData\":" << boolAsStr(modSettings.is_test_data);
result << ",\n\"tx.attenuation\":"; writeDouble(result, modSettings.attenuation);
result << ",\"tx.rolloff\":" << static_cast<int>(modSettings.rollof * 100);
result << ",\"tx.cymRate\":" << modSettings.baudrate;
result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3);
result << ",\"dvbs2.frameSizeNormal\":" << boolAsStr(!(modSettings.modcod_tx & 2));
result << ",\"dvbs2.ccm_modcod\":" << (modSettings.modcod_tx >> 4);
// result << ",\"dvbs2.isPilots\":" << "null";
result << ",\n\"dvbs2.isAcm\":" << boolAsStr(acmSettings.enable);
result << ",\"dvbs2.acm_maxModcod\":" << (acmSettings.max_modcod >> 2);
result << ",\"dvbs2.acm_minModcod\":" << (acmSettings.min_modcod >> 2);
result << ",\"dvbs2.snrReserve\":"; writeDouble(result, acmSettings.snr_treashold_acm);
result << ",\"dvbs2.servicePacketPeriod\":" << acmSettings.period_pack;
result << ",\n\"acm.en\":" << boolAsStr(acmSettings.enable_auto_atten);
result << ",\"acm.maxAttenuation\":"; writeDouble(result, acmSettings.max_attenuation);
result << ",\"acm.minAttenuation\":"; writeDouble(result, acmSettings.min_attenuation);
result << ",\"acm.requiredSnr\":"; writeDouble(result, acmSettings.snr_treashold);
result << ",\n\"rx.gainMode\":" << (demodSettings.is_aru_on ? "\"auto\"" : "\"manual\"");
result << ",\"rx.manualGain\":"; writeDouble(result, demodSettings.gain);
result << ",\"rx.spectrumInversion\":" << boolAsStr(demodSettings.is_rvt_iq);
result << ",\"rx.rolloff\":" << static_cast<int>(demodSettings.rollof * 100);
result << ",\"rx.cymRate\":" << demodSettings.baudrate;
result << ",\"rx.centerFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz);
result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\"");
result << ",\"cinc.searchBandwidth\":" << dpdiSettings.freq_offset; // полоса поиска в кГц
result << ",\"cinc.position.station.latitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.latitude_station_grad, dpdiSettings.latitude_station_minute), 6);
result << ",\"cinc.position.station.longitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_station_grad, dpdiSettings.longitude_station_minute), 6);
result << ",\"cinc.position.satelliteLongitude\":"; writeDouble(result, translateCoordinates(dpdiSettings.longitude_sattelite_grad, dpdiSettings.longitude_sattelite_minute), 6);
result << ",\"cinc.delayMin\":" << dpdiSettings.min_delay;
result << ",\"cinc.delayMax\":" << dpdiSettings.max_delay;
result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc);
switch (bucLnb.buc) {
case voltage_buc::_24V: result << ",\"buc.powering\":24"; break;
case voltage_buc::_48V: result << ",\"buc.powering\":48"; break;
case voltage_buc::DISABLE:
default: result << ",\"buc.powering\":0";
}
result << ",\n\"lnb.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_lnb);
switch (bucLnb.lnb) {
case voltage_lnb::_13V: result << ",\"lnb.powering\":13"; break;
case voltage_lnb::_18V: result << ",\"lnb.powering\":18"; break;
case voltage_lnb::_24V: result << ",\"lnb.powering\":24"; break;
case voltage_lnb::DISABLE:
default: result << ",\"lnb.powering\":0";
}
result << ",\n\"serviceSettings.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_output);
result << ",\"serviceSettings.autoStart\":" << boolAsStr(bucLnb.is_save_current_state);
bool qosEnabled = false; std::string qosClasses;
daemon->getQosSettings(qosEnabled, qosClasses);
result << ",\n\"qos.enabled\":" << boolAsStr(qosEnabled);
result << ",\"qos.profile\":" << qosClasses;
result << "}";
return result.str();
}
void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) {
modulator_settings mod{};
demodulator_settings demod{};
ACM_parameters_serv_ acm{};
// для модулятора
mod.is_cinc = pt.get<bool>(json_path("general.isCinC", '/'));
mod.tx_is_on = pt.get<bool>(json_path("general.txEn", '/'));
auto tmp = pt.get<std::string>(json_path("general.modulatorMode", '/'));
if (tmp == "normal") { mod.is_carrier = true; }
else if (tmp == "test") { mod.is_carrier = false; }
else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong carrier mode: " + tmp); }
mod.is_save_current_state = pt.get<bool>(json_path("general.autoStartTx", '/'));
mod.is_test_data = pt.get<bool>(json_path("general.isTestInputData", '/'));
mod.attenuation = pt.get<double>(json_path("tx.attenuation", '/'));
mod.rollof = pt.get<double>(json_path("tx.rolloff", '/')) / 100.0;
mod.baudrate = pt.get<uint32_t>(json_path("tx.cymRate", '/'));
mod.central_freq_in_kGz = pt.get<double>(json_path("tx.centerFreq", '/'));
const bool acmIsShortFrame = pt.get<bool>(json_path("dvbs2.frameSizeNormal", '/'));
mod.modcod_tx = (pt.get<uint32_t>(json_path("dvbs2.ccm_modcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
// демодулятор
tmp = pt.get<std::string>(json_path("rx.gainMode", '/'));
if (tmp == "auto") { demod.is_aru_on = true; }
else if (tmp == "manual") { demod.is_aru_on = false; }
else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong gain mode: " + tmp); }
demod.gain = pt.get<double>(json_path("rx.manualGain", '/'));
demod.baudrate = pt.get<uint32_t>(json_path("rx.cymRate", '/'));
demod.is_rvt_iq = pt.get<bool>(json_path("rx.spectrumInversion", '/'));
demod.rollof = pt.get<double>(json_path("rx.rolloff", '/')) / 100.0;
demod.central_freq_in_kGz = pt.get<double>(json_path("rx.centerFreq", '/'));
// ACM
acm.enable = pt.get<bool>(json_path("dvbs2.isAcm", '/'));
acm.max_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_maxModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
acm.min_modcod = (pt.get<uint32_t>(json_path("dvbs2.acm_minModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0);
acm.snr_treashold_acm = pt.get<double>(json_path("dvbs2.snrReserve", '/')); // запас ОСШ
acm.period_pack = pt.get<uint32_t>(json_path("dvbs2.servicePacketPeriod", '/'));
acm.enable_auto_atten = pt.get<bool>(json_path("acm.en", '/'));
acm.max_attenuation = pt.get<double>(json_path("acm.maxAttenuation", '/'));
acm.min_attenuation = pt.get<double>(json_path("acm.minAttenuation", '/'));
acm.snr_treashold = pt.get<double>(json_path("acm.requiredSnr", '/')); // требуемый ОСШ
daemon->setSettingsRxTx(mod, demod, acm);
}
void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) {
DPDI_parmeters s{};
//result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\"");
auto tmp = pt.get<std::string>(json_path("cinc.mode", '/'));
if (tmp == "delay") { s.is_delay_window = true; }
else if (tmp == "positional") { s.is_delay_window = false; }
else {
throw std::runtime_error("Wrong CinC mode: " + tmp);
}
auto ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.station.latitude", '/')));
s.latitude_station_grad = std::get<0>(ctmp);
s.latitude_station_minute = std::get<1>(ctmp);
ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.station.longitude", '/')));
s.longitude_station_grad = std::get<0>(ctmp);
s.longitude_station_minute = std::get<1>(ctmp);
ctmp = translateCoordinates(pt.get<double>(json_path("cinc.position.satelliteLongitude", '/')));
s.longitude_sattelite_grad = std::get<0>(ctmp);
s.longitude_sattelite_minute = std::get<1>(ctmp);
s.max_delay = pt.get<uint32_t>(json_path("cinc.delayMax", '/'));
s.min_delay = pt.get<uint32_t>(json_path("cinc.delayMin", '/'));
this->daemon->setSettingsCinc(s);
}
void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) {
buc_lnb_settings s{};
auto tmp = pt.get<int>(json_path("lnb.powering", '/'));
switch (tmp) {
case 13: s.lnb = voltage_lnb::_13V; break;
case 18: s.lnb = voltage_lnb::_18V; break;
case 24: s.lnb = voltage_lnb::_24V; break;
case 0:
default:
s.lnb = voltage_lnb::DISABLE;
}
s.is_ref_10MHz_lnb = pt.get<bool>(json_path("lnb.refClk10M", '/'));
tmp = pt.get<int>(json_path("buc.powering", '/'));
switch (tmp) {
case 24: s.buc = voltage_buc::_24V; break;
case 48: s.buc = voltage_buc::_48V; break;
case 0:
default:
s.lnb = voltage_lnb::DISABLE;
}
// { "lnb": {"powering": 0} }
s.is_ref_10MHz_buc = pt.get<bool>(json_path("buc.refClk10M", '/'));
s.is_ref_10MHz_output = pt.get<bool>(json_path("serviceSettings.refClk10M", '/'));
s.is_save_current_state = pt.get<bool>(json_path("serviceSettings.autoStart", '/'));
this->daemon->setSettingsBucLnb(s);
}
void api_driver::ApiDriver::setQosSettings(boost::property_tree::ptree &pt) {
bool enabled = pt.get<bool>("en");
pt.erase("en");
std::ostringstream oss;
write_json(oss, pt);
this->daemon->setQosSettings(enabled, oss.str());
}
bool api_driver::ApiDriver::getIsCinC() const {
modulator_settings s{};
daemon->getSettings(&s, nullptr, nullptr, nullptr, nullptr);
return s.is_cinc;
}
api_driver::ApiDriver::~ApiDriver() = default;