966 lines
34 KiB
C++
966 lines
34 KiB
C++
#include "api-driver/structs.h"
|
|
#include "api-driver/proxy.h"
|
|
#include "common/nlohmann/json.hpp"
|
|
#include <iomanip>
|
|
#include <sys/sysinfo.h>
|
|
#include <boost/property_tree/ptree.hpp>
|
|
#include "terminal_api_driver.h"
|
|
|
|
|
|
#define TIME_NOW() std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count()
|
|
|
|
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();
|
|
}
|
|
|
|
|
|
#ifdef API_OBJECT_DEBUG_METRICS_ENABLE
|
|
api_driver::obj::StatisticsLogger::StatisticsLogger(): timeStart(TIME_NOW()) {}
|
|
|
|
nlohmann::json api_driver::obj::StatisticsLogger::getSettings() {
|
|
std::lock_guard _lock(mutex);
|
|
nlohmann::json res;
|
|
res["en"] = this->logEn;
|
|
res["logPeriodMs"] = logPeriodMs.load();
|
|
res["maxAgeMs"] = maxAgeMs.load();
|
|
return res;
|
|
}
|
|
|
|
void api_driver::obj::StatisticsLogger::setSettings(const nlohmann::json& data) {
|
|
const bool newEn = data.value("en", logEn);
|
|
const int newInterval = data.value("logPeriodMs", logPeriodMs.load());
|
|
const int newMaxAgeMs = data.value("maxAgeMs", maxAgeMs.load());
|
|
|
|
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) {
|
|
if (!logEn) return;
|
|
|
|
debug_metrics dm{};
|
|
cp.getDebugMetrics(dm);
|
|
putItem(dm);
|
|
}
|
|
|
|
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
|
|
|
|
#ifdef API_OBJECT_NETWORK_SETTINGS_ENABLE
|
|
static int calculateSubnetMask(const std::string& subnet_mask) {
|
|
int mask = 0;
|
|
std::istringstream iss(subnet_mask);
|
|
std::string octet;
|
|
while (std::getline(iss, octet, '.')) {
|
|
int octet_value = std::stoi(octet);
|
|
for (int i = 7; i >= 0; i--) {
|
|
if (octet_value & (1 << i)) {
|
|
mask++;
|
|
}
|
|
}
|
|
}
|
|
return mask;
|
|
}
|
|
|
|
/**
|
|
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
|
|
*/
|
|
std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
|
|
auto pos = input.find('/');
|
|
if (pos == std::string::npos) {
|
|
// Обработка ошибки: нет символа '/'
|
|
throw std::runtime_error("address not contains mask");
|
|
}
|
|
std::string ip = input.substr(0, pos);
|
|
const unsigned int mask_int = std::stoul(input.substr(pos + 1));
|
|
|
|
if (mask_int > 32) {
|
|
throw std::runtime_error("invalid mask");
|
|
}
|
|
|
|
std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
|
|
std::string mask_str;
|
|
|
|
for (unsigned int i = 0; i < 4; ++i) {
|
|
std::string octet = mask_binary.substr(i * 8u, 8);
|
|
int octet_value = std::stoi(octet, nullptr, 2);
|
|
mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
|
|
}
|
|
|
|
return std::make_pair(ip, mask_str);
|
|
}
|
|
|
|
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings() { loadDefaults(); }
|
|
|
|
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const TerminalNetworkSettings &src) = default;
|
|
|
|
api_driver::obj::TerminalNetworkSettings & api_driver::obj::TerminalNetworkSettings::operator=(const TerminalNetworkSettings &src) = default;
|
|
|
|
void api_driver::obj::TerminalNetworkSettings::loadDefaults() {
|
|
managementIp = "0.0.0.0/24";
|
|
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");
|
|
managementIp += "/";
|
|
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::updateFromJson(const nlohmann::json &data) {
|
|
managementIp = data.value("managementIp", managementIp);
|
|
isL2 = data.value("isL2", isL2);
|
|
dataIp = data.value("dataIp", dataIp);
|
|
dataMtu = data.value("dataMtu", dataMtu);
|
|
serverName = data.value("serverName", serverName);
|
|
}
|
|
|
|
void api_driver::obj::TerminalNetworkSettings::store(proxy::CpProxy& cp) {
|
|
try {
|
|
cp.setNetwork("mode", isL2 ? "tap" : "tun");
|
|
auto [mAddr, mMask] = splitIpAndMask(managementIp);
|
|
cp.setNetwork("addr", mAddr);
|
|
cp.setNetwork("mask", mMask);
|
|
|
|
if (!isL2) {
|
|
cp.setNetwork("addr_data", dataIp);
|
|
}
|
|
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());
|
|
}
|
|
}
|
|
|
|
nlohmann::json api_driver::obj::TerminalNetworkSettings::asJson() {
|
|
nlohmann::json res;
|
|
res["isL2"] = isL2;
|
|
res["managementIp"] = managementIp;
|
|
res["managementGateway"] = managementGateway;
|
|
res["dataIp"] = dataIp;
|
|
res["dataMtu"] = dataMtu;
|
|
res["serverName"] = serverName;
|
|
return res;
|
|
}
|
|
|
|
api_driver::obj::TerminalNetworkSettings::~TerminalNetworkSettings() = default;
|
|
#endif
|
|
|
|
#ifdef API_OBJECT_QOS_SETTINGS_ENABLE
|
|
api_driver::obj::TerminalQosSettings::TerminalQosSettings(): qosSettingsJson(DEFAULT_QOS_CLASSES) {};
|
|
api_driver::obj::TerminalQosSettings::TerminalQosSettings(const TerminalQosSettings &src) = default;
|
|
api_driver::obj::TerminalQosSettings & api_driver::obj::TerminalQosSettings::operator=(const TerminalQosSettings &src) = default;
|
|
|
|
void api_driver::obj::TerminalQosSettings::loadDefaults() {
|
|
qosEnabled = false;
|
|
qosSettingsJson = DEFAULT_QOS_CLASSES;
|
|
}
|
|
|
|
void api_driver::obj::TerminalQosSettings::updateCallback(proxy::CpProxy &cp) {
|
|
auto [profile, en] = cp.getQosSettings();
|
|
qosEnabled = en;
|
|
try {
|
|
qosSettingsJson = nlohmann::json::parse(profile);
|
|
} catch (std::exception& e) {
|
|
BOOST_LOG_TRIVIAL(warning) << "api_driver::obj::TerminalQosSettings::updateCallback(): Failed to parse QoS settings json: " << e.what();
|
|
qosSettingsJson = DEFAULT_QOS_CLASSES;
|
|
}
|
|
}
|
|
|
|
void api_driver::obj::TerminalQosSettings::updateFromJson(const nlohmann::json &data) {
|
|
qosEnabled = data.value("en", qosEnabled);
|
|
qosSettingsJson = data.value("profile", qosSettingsJson);
|
|
}
|
|
|
|
void api_driver::obj::TerminalQosSettings::store(proxy::CpProxy &cp) {
|
|
cp.setQosSettings(qosSettingsJson.dump(), qosEnabled);
|
|
}
|
|
|
|
nlohmann::json api_driver::obj::TerminalQosSettings::asJson() {
|
|
nlohmann::json res;
|
|
res["en"] = qosEnabled;
|
|
res["profile"] = qosSettingsJson;
|
|
return res;
|
|
}
|
|
|
|
api_driver::obj::TerminalQosSettings::~TerminalQosSettings() = default;
|
|
#endif
|
|
|
|
api_driver::obj::TerminalFirmwareVersion::TerminalFirmwareVersion() = default;
|
|
api_driver::obj::TerminalFirmwareVersion::TerminalFirmwareVersion(const TerminalFirmwareVersion &src) = default;
|
|
api_driver::obj::TerminalFirmwareVersion & api_driver::obj::TerminalFirmwareVersion::operator=(const TerminalFirmwareVersion &src) = default;
|
|
|
|
void api_driver::obj::TerminalFirmwareVersion::load(proxy::CpProxy &cp) {
|
|
version = cp.getNetwork("version");
|
|
modemId = cp.getNetwork("chip_id");
|
|
rtrim(modemId);
|
|
modemSn = cp.getNetwork("serial");
|
|
macMang = cp.getNetwork("mac_eth0");
|
|
macData = cp.getNetwork("mac_eth1");
|
|
}
|
|
|
|
nlohmann::json api_driver::obj::TerminalFirmwareVersion::asJson() {
|
|
nlohmann::json res;
|
|
res["version"] = version;
|
|
res["modemId"] = modemId;
|
|
res["modemSn"] = modemSn;
|
|
res["macMang"] = macMang;
|
|
res["macData"] = macData;
|
|
return res;
|
|
}
|
|
|
|
api_driver::obj::TerminalFirmwareVersion::~TerminalFirmwareVersion() = default;
|
|
|
|
|
|
api_driver::obj::TerminalState::TerminalState() = default;
|
|
|
|
void api_driver::obj::TerminalState::updateCallback(proxy::CpProxy& cp) {
|
|
modulator_state mod{};
|
|
modulator_settings modSet{};
|
|
demodulator_state demod{};
|
|
#ifdef MODEM_IS_SCPC
|
|
CinC_state cinc{};
|
|
#endif
|
|
try {
|
|
cp.getModState(mod);
|
|
cp.getDemodState(demod);
|
|
cp.getModSettings(modSet);
|
|
|
|
fTxState = modSet.tx_is_on;
|
|
fIsTest = modSet.tx_is_on && (!modSet.is_carrier || modSet.is_test_data);
|
|
#ifdef MODEM_IS_SCPC
|
|
fIsCinC = modSet.is_cinc;
|
|
if (fIsCinC) {
|
|
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());
|
|
}
|
|
|
|
fRxState = demod.locks.sym_sync_lock && demod.locks.freq_lock && demod.locks.afc_lock && demod.locks.pkt_sync;
|
|
#ifndef MODEM_IS_SHPS
|
|
fRxSymSyncLock = demod.locks.sym_sync_lock;
|
|
fRxFreqSearchLock = demod.locks.freq_lock;
|
|
fRxAfcLock = demod.locks.afc_lock;
|
|
fRxPktSync = demod.locks.pkt_sync;
|
|
#endif
|
|
|
|
fRxSnr = demod.snr;
|
|
fRxRssi = demod.rssi;
|
|
#ifndef MODEM_IS_SHPS
|
|
fRxModcod = demod.modcod;
|
|
fRxFrameSizeNormal = !demod.is_short;
|
|
fRxIsPilots = demod.is_pilots;
|
|
|
|
fRxSymError = demod.sym_err;
|
|
fRxFreqErr = demod.crs_freq_err;
|
|
#endif
|
|
fRxFreqErrAcc = demod.fine_freq_err;
|
|
fRxInputSignalLevel = demod.if_overload;
|
|
fRxPllError = demod.afc_err;
|
|
fRxSpeedOnRxKbit = static_cast<double>(demod.speed_in_bytes_rx) / 128.0;
|
|
fRxSpeedOnIifKbit = static_cast<double>(demod.speed_in_bytes_rx_iface) / 128.0;
|
|
fRxPacketsOk = demod.packet_ok_cnt;
|
|
fRxPacketsBad = demod.packet_bad_cnt;
|
|
#ifndef MODEM_IS_SHPS
|
|
fRxPacketsDummy = demod.dummy_cnt;
|
|
fTxModcod = mod.modcod;
|
|
#endif
|
|
fTxSpeedOnTxKbit = static_cast<double>(mod.speed_in_bytes_tx) / 128.0;
|
|
fTxSpeedOnIifKbit = static_cast<double>(mod.speed_in_bytes_tx_iface) / 128.0;
|
|
#ifdef MODEM_IS_SCPC
|
|
fTxSnr = mod.snr_remote;
|
|
fTxFrameSizeNormal = !mod.is_short;
|
|
fTxIsPilots = mod.is_pilots;
|
|
fCincOcc = cinc.ratio_signal_signal;
|
|
fCincCorrelator = cinc.carrier_lock;
|
|
fCincCorrelatorFails = cinc.cnt_bad_lock;
|
|
fCincFreqErr = cinc.freq_error_offset;
|
|
fCincFreqErrAcc = cinc.freq_fine_estimate;
|
|
fCincChannelDelay = cinc.delay_dpdi;
|
|
#endif
|
|
fTxCenterFreq = modSet.central_freq_in_kGz;
|
|
fTxSymSpeed = static_cast<double>(modSet.baudrate) / 1000.0;
|
|
}
|
|
|
|
nlohmann::json api_driver::obj::TerminalState::asJson() {
|
|
nlohmann::json res{};
|
|
|
|
res["initState"] = fInitState;
|
|
res["testState"] = fIsTest;
|
|
#ifdef MODEM_IS_SCPC
|
|
res["isCinC"] = fIsCinC;
|
|
#endif
|
|
|
|
res["rx"]["state"] = fRxState;
|
|
#ifndef MODEM_IS_SHPS
|
|
res["rx"]["sym_sync_lock"] = fRxSymSyncLock;
|
|
res["rx"]["freq_search_lock"] = fRxFreqSearchLock;
|
|
res["rx"]["afc_lock"] = fRxAfcLock;
|
|
res["rx"]["pkt_sync"] = fRxPktSync;
|
|
#endif
|
|
|
|
res["rx"]["snr"] = fRxSnr;
|
|
res["rx"]["rssi"] = fRxRssi;
|
|
#ifndef MODEM_IS_SHPS
|
|
res["rx"]["modcod"] = fRxModcod;
|
|
res["rx"]["frameSizeNormal"] = fRxFrameSizeNormal;
|
|
res["rx"]["isPilots"] = fRxIsPilots;
|
|
|
|
res["rx"]["symError"] = fRxSymError;
|
|
res["rx"]["freqErr"] = fRxFreqErr;
|
|
#endif
|
|
res["rx"]["freqErrAcc"] = fRxFreqErrAcc;
|
|
res["rx"]["inputSignalLevel"] = fRxInputSignalLevel;
|
|
res["rx"]["pllError"] = fRxPllError;
|
|
res["rx"]["speedOnRxKbit"] = fRxSpeedOnRxKbit;
|
|
res["rx"]["speedOnIifKbit"] = fRxSpeedOnIifKbit;
|
|
res["rx"]["packetsOk"] = fRxPacketsOk;
|
|
res["rx"]["packetsBad"] = fRxPacketsBad;
|
|
#ifndef MODEM_IS_SHPS
|
|
res["rx"]["packetsDummy"] = fRxPacketsDummy;
|
|
res["tx"]["modcod"] = fTxModcod;
|
|
#endif
|
|
res["tx"]["state"] = fTxState;
|
|
res["tx"]["speedOnTxKbit"] = fTxSpeedOnTxKbit;
|
|
res["tx"]["speedOnIifKbit"] = fTxSpeedOnIifKbit;
|
|
#ifdef MODEM_IS_SCPC
|
|
res["tx"]["snr"] = fTxSnr;
|
|
res["tx"]["frameSizeNormal"] = fTxFrameSizeNormal;
|
|
res["tx"]["isPilots"] = fTxIsPilots;
|
|
|
|
if (fIsCinC) {
|
|
if (fTxState) {
|
|
res["cinc"]["correlator"] = fCincCorrelator;
|
|
} else {
|
|
res["cinc"]["correlator"] = nullptr;
|
|
}
|
|
|
|
res["cinc"]["occ"] = fCincOcc;
|
|
res["cinc"]["correlatorFails"] = fCincCorrelatorFails;
|
|
res["cinc"]["freqErr"] = fCincFreqErr;
|
|
res["cinc"]["freqErrAcc"] = fCincFreqErrAcc;
|
|
res["cinc"]["channelDelay"] = fCincChannelDelay;
|
|
} else {
|
|
res["cinc"]["correlator"] = nullptr;
|
|
}
|
|
#endif
|
|
res["tx"]["centerFreq"] = fTxCenterFreq;
|
|
res["tx"]["symSpeed"] = fTxSymSpeed;
|
|
|
|
return res;
|
|
}
|
|
|
|
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) = default;
|
|
|
|
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{};
|
|
cp.getUpdateStatus(ds);
|
|
fUpgradeStatus = ds.status;
|
|
fUpgradePercent = ds.dwl_percent;
|
|
fUpgradeImage = 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;
|
|
}
|
|
|
|
nlohmann::json api_driver::obj::TerminalDeviceState::asJson() const {
|
|
nlohmann::json res;
|
|
res["uptime"] = fOsUptime;
|
|
res["load1min"] = fOsLoad1;
|
|
res["load5min"] = fOsLoad5;
|
|
res["load15min"] = fOsLoad15;
|
|
res["totalram"] = fOsTotalram;
|
|
res["freeram"] = fOsFreeram;
|
|
res["procs"] = fOsProcs;
|
|
res["adrv"] = fTempAdrv;
|
|
res["fpga"] = fTempFpga;
|
|
res["zynq"] = fTempZynq;
|
|
#ifdef MODEM_IS_TDMA
|
|
if (fUpgradeImage.empty()) {
|
|
res["upgradeStatus"] = "Нет обновлений";
|
|
res["upgradePercent"] = 0;
|
|
res["upgradeImage"] = "";
|
|
} else {
|
|
switch (fUpgradeStatus) {
|
|
case NORM_RX_OBJECT_NEW_API: res["upgradeStatus"] = "Начало загрузки"; break;
|
|
case NORM_RX_OBJECT_INFO_API: res["upgradeStatus"] = "Получено имя образа"; break;
|
|
case NORM_RX_OBJECT_UPDATED_API: res["upgradeStatus"] = "Загружается"; break;
|
|
case NORM_RX_OBJECT_COMPLETED_API: res["upgradeStatus"] = "Загрузка завершена"; break;
|
|
case NORM_RX_OBJECT_ABORTED_API: res["upgradeStatus"] = "Загрузка прервана"; break;
|
|
default: res["upgradeStatus"] = "?";
|
|
}
|
|
res["upgradePercent"] = fUpgradePercent;
|
|
res["upgradeImage"] = fUpgradeImage;
|
|
}
|
|
|
|
#endif
|
|
return res;
|
|
}
|
|
|
|
api_driver::obj::TerminalDeviceState::~TerminalDeviceState() = default;
|
|
|
|
|
|
api_driver::obj::TerminalRxTxSettings::TerminalRxTxSettings() = default;
|
|
api_driver::obj::TerminalRxTxSettings::TerminalRxTxSettings(const TerminalRxTxSettings &src) = default;
|
|
api_driver::obj::TerminalRxTxSettings & api_driver::obj::TerminalRxTxSettings::operator=(const TerminalRxTxSettings &src) = default;
|
|
|
|
void api_driver::obj::TerminalRxTxSettings::updateCallback(proxy::CpProxy &cp) {
|
|
cp.getModSettings(mod);
|
|
cp.getDemodSettings(dem);
|
|
#ifdef API_STRUCT_ACM_ENABLE
|
|
cp.getAcmSettings(acm);
|
|
#endif
|
|
#ifdef API_OBJECT_DPDI_SETTINGS_ENABLE
|
|
cp.getDpdiSettings(dpdi);
|
|
#endif
|
|
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
|
|
cp.getBuclnbSettings(buclnb);
|
|
#endif
|
|
}
|
|
|
|
void api_driver::obj::TerminalRxTxSettings::storeMainSettings(proxy::CpProxy &cp) {
|
|
cp.setModSettings(mod);
|
|
cp.setDemodSettings(dem);
|
|
#ifdef API_STRUCT_ACM_ENABLE
|
|
cp.setAcmSettings(acm);
|
|
#endif
|
|
}
|
|
|
|
|
|
struct ModcodDef_t {const char* modulation; const char* speed;};
|
|
const static ModcodDef_t ModcodDefs[] = {
|
|
{.modulation = "dummy", .speed = "0"},
|
|
{.modulation = "qpsk", .speed = "1/4"},
|
|
{.modulation = "qpsk", .speed = "1/3"},
|
|
{.modulation = "qpsk", .speed = "2/5"},
|
|
{.modulation = "qpsk", .speed = "1/2"},
|
|
{.modulation = "qpsk", .speed = "3/5"},
|
|
{.modulation = "qpsk", .speed = "2/3"},
|
|
{.modulation = "qpsk", .speed = "3/4"},
|
|
{.modulation = "qpsk", .speed = "4/5"},
|
|
{.modulation = "qpsk", .speed = "5/6"},
|
|
{.modulation = "qpsk", .speed = "8/9"},
|
|
{.modulation = "qpsk", .speed = "9/10"},
|
|
{.modulation = "8psk", .speed = "3/5"},
|
|
{.modulation = "8psk", .speed = "2/3"},
|
|
{.modulation = "8psk", .speed = "3/4"},
|
|
{.modulation = "8psk", .speed = "5/6"},
|
|
{.modulation = "8psk", .speed = "8/9"},
|
|
{.modulation = "8psk", .speed = "9/10"},
|
|
{.modulation = "16apsk", .speed = "2/3"},
|
|
{.modulation = "16apsk", .speed = "3/4"},
|
|
{.modulation = "16apsk", .speed = "4/5"},
|
|
{.modulation = "16apsk", .speed = "5/6"},
|
|
{.modulation = "16apsk", .speed = "8/9"},
|
|
{.modulation = "16apsk", .speed = "9/10"},
|
|
{.modulation = "32apsk", .speed = "3/4"},
|
|
{.modulation = "32apsk", .speed = "4/5"},
|
|
{.modulation = "32apsk", .speed = "5/6"},
|
|
{.modulation = "32apsk", .speed = "8/9"},
|
|
{.modulation = "32apsk", .speed = "9/10"},
|
|
};
|
|
|
|
static const char* extractModcodModulation(uint32_t modcod, bool defaultQpsk1_4 = true) {
|
|
modcod >>= 2;
|
|
const auto* d = defaultQpsk1_4 ? ModcodDefs : ModcodDefs + 1;
|
|
if (modcod < (sizeof(ModcodDefs) / sizeof(ModcodDef_t))) {
|
|
d = ModcodDefs + modcod;
|
|
}
|
|
return d->modulation;
|
|
}
|
|
static const char* extractModcodSpeed(uint32_t modcod, bool defaultQpsk1_4 = true) {
|
|
modcod >>= 2;
|
|
const auto* d = defaultQpsk1_4 ? ModcodDefs : ModcodDefs + 1;
|
|
if (modcod < (sizeof(ModcodDefs) / sizeof(ModcodDef_t))) {
|
|
d = ModcodDefs + modcod;
|
|
}
|
|
return d->speed;
|
|
}
|
|
static bool extractModcodFrameSizeNormal(uint32_t modcod) { return (modcod & 2) == 0; }
|
|
static bool extractModcodIsPilots(uint32_t modcod) { return (modcod & 1) != 0; }
|
|
static uint32_t buildModcodFromJson(const nlohmann::json& data, uint32_t modcod, const std::string& name, bool isNormalFrame, bool isPilots = false) {
|
|
const std::string mod = data.value(name + "Modulation", extractModcodModulation(modcod));
|
|
const std::string speed = data.value(name + "Speed", extractModcodSpeed(modcod));
|
|
uint32_t _index = 0;
|
|
for (const auto& m: ModcodDefs) {
|
|
if (mod == m.modulation) {
|
|
if (modcod == 0) modcod = _index;
|
|
if (speed == m.speed) {
|
|
modcod = _index;
|
|
break;
|
|
}
|
|
}
|
|
_index++;
|
|
}
|
|
return (modcod << 2)| (isNormalFrame ? 0 : 2) | (isPilots ? 1 : 0);
|
|
}
|
|
|
|
|
|
void api_driver::obj::TerminalRxTxSettings::updateMainSettings(const nlohmann::json &data) {
|
|
// для модулятора
|
|
#ifdef MODEM_IS_SCPC
|
|
mod.is_cinc = data.value("isCinC", mod.is_cinc);
|
|
#endif
|
|
mod.tx_is_on = data.value("txEn", mod.tx_is_on);
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
mod.is_save_current_state = data.value("txAutoStart", mod.is_save_current_state);
|
|
mod.is_test_data = data.value("txIsTestInput", mod.is_test_data);
|
|
#endif
|
|
mod.is_carrier = !data.value("txModulatorIsTest", !mod.is_carrier);
|
|
mod.central_freq_in_kGz = data.value("txCentralFreq", mod.central_freq_in_kGz);
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
mod.baudrate = data.value("txBaudrate", mod.baudrate);
|
|
mod.rollof = data.value("txRolloff", mod.rollof);
|
|
mod.gold_seq_is_active = data.value("txGoldan", mod.gold_seq_is_active ? 1 : 0);
|
|
#endif
|
|
mod.attenuation = data.value("txAttenuation", mod.attenuation);
|
|
|
|
#if defined(MODEM_IS_SCPC) || defined(MODEM_IS_SHPS)
|
|
bool acmIsFrameSizeNormal = extractModcodFrameSizeNormal(mod.modcod_tx);
|
|
bool acmIsPilots = extractModcodIsPilots(mod.modcod_tx);
|
|
|
|
acmIsFrameSizeNormal = data.value("txFrameSizeNormal", acmIsFrameSizeNormal);
|
|
acmIsPilots = data.value("txIsPilots", acmIsPilots);
|
|
mod.modcod_tx = buildModcodFromJson(data, mod.modcod_tx, "dvbCcm", acmIsFrameSizeNormal, acmIsPilots);
|
|
#endif
|
|
#ifdef MODEM_IS_SHPS
|
|
mod.koef_spread = data.value("txSpreadCoef", mod.koef_spread);
|
|
mod.txFieldsDataPreamble = data.value("txFieldsDataPreamble", mod.txFieldsDataPreamble);
|
|
#endif
|
|
|
|
// демодулятор
|
|
dem.is_aru_on = data.value("rxAgcEn", dem.is_aru_on);
|
|
dem.gain = data.value("rxManualGain", dem.gain);
|
|
dem.is_rvt_iq = data.value("rxSpectrumInversion", dem.is_rvt_iq);
|
|
dem.central_freq_in_kGz = data.value("rxCentralFreq", dem.central_freq_in_kGz);
|
|
dem.baudrate = data.value("rxBaudrate", dem.baudrate);
|
|
dem.rollof = data.value("rxRolloff", dem.rollof);
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
dem.gold_seq_is_active = data.value("rxGoldan", dem.gold_seq_is_active ? 1 : 0);
|
|
#endif
|
|
#ifdef MODEM_IS_SHPS
|
|
dem.koef_spread = data.value("rxSpreadCoef", dem.koef_spread);
|
|
dem.rxFftShift = data.value("rxFftShift", dem.rxFftShift);
|
|
#endif
|
|
|
|
#ifdef API_STRUCT_ACM_ENABLE
|
|
// ACM
|
|
#ifdef MODEM_IS_SCPC
|
|
// эти настройки только в SCPC
|
|
acm.period_pack_acm = data.value("dvbServicePacketPeriod", acm.period_pack_acm);
|
|
acm.enable_acm = data.value("dvbIsAcm", acm.enable_acm);
|
|
acm.min_modcod_acm = buildModcodFromJson(data, acm.min_modcod_acm, "dvbAcmMin", acmIsFrameSizeNormal, acmIsPilots);
|
|
acm.max_modcod_acm = buildModcodFromJson(data, acm.max_modcod_acm, "dvbAcmMax", acmIsFrameSizeNormal, acmIsPilots);
|
|
acm.snr_threashold_acm = data.value("dvbSnrReserve", acm.snr_threashold_acm); // запас ОСШ
|
|
#endif
|
|
|
|
acm.enable_aupc = data.value("aupcEn", acm.enable_aupc);
|
|
acm.min_attenuation_aupc = data.value("aupcMinAttenuation", acm.min_attenuation_aupc);
|
|
acm.max_attenuation_aupc = data.value("aupcMaxAttenuation", acm.max_attenuation_aupc);
|
|
acm.snr_threashold_aupc = data.value("aupcRequiredSnr", acm.snr_threashold_aupc);
|
|
#endif
|
|
}
|
|
|
|
#ifdef API_OBJECT_DPDI_SETTINGS_ENABLE
|
|
static double translateCoordinates(uint8_t deg, uint8_t min) {
|
|
return static_cast<double>(deg) + static_cast<double>(min) / 60;
|
|
}
|
|
|
|
static 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);
|
|
}
|
|
|
|
void api_driver::obj::TerminalRxTxSettings::updateDpdiSettings(const nlohmann::json &data) {
|
|
dpdi.is_delay_window = !data.value("isPositional", !dpdi.is_delay_window);
|
|
#ifdef MODEM_IS_SCPC
|
|
dpdi.freq_offset = data.value("searchBandwidth", dpdi.freq_offset);
|
|
#endif
|
|
|
|
if (data.contains("positionStationLatitude")) {
|
|
const double pos = data["positionStationLatitude"];
|
|
const auto [g, m] = translateCoordinates(pos);
|
|
dpdi.latitude_station_grad = g;
|
|
dpdi.latitude_station_minute = m;
|
|
}
|
|
|
|
if (data.contains("positionStationLongitude")) {
|
|
const double pos = data["positionStationLongitude"];
|
|
const auto [g, m] = translateCoordinates(pos);
|
|
dpdi.longitude_station_grad = g;
|
|
dpdi.longitude_station_minute = m;
|
|
}
|
|
|
|
if (data.contains("positionSatelliteLongitude")) {
|
|
const double pos = data["positionSatelliteLongitude"];
|
|
const auto [g, m] = translateCoordinates(pos);
|
|
dpdi.longitude_sattelite_grad = g;
|
|
dpdi.longitude_sattelite_minute = m;
|
|
}
|
|
|
|
#ifdef MODEM_IS_SCPC
|
|
dpdi.min_delay = data.value("delayMin", dpdi.min_delay);
|
|
dpdi.max_delay = data.value("delayMax", dpdi.max_delay);
|
|
#else
|
|
dpdi.min_delay = 0;
|
|
dpdi.max_delay = data.value("delay", dpdi.max_delay);
|
|
#endif
|
|
}
|
|
void api_driver::obj::TerminalRxTxSettings::storeDpdiSettings(proxy::CpProxy &cp) {
|
|
cp.setDpdiSettings(dpdi);
|
|
}
|
|
#endif
|
|
|
|
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
|
|
void api_driver::obj::TerminalRxTxSettings::updateBuclnbSettings(const nlohmann::json &data) {
|
|
{
|
|
// напряжение buc
|
|
int oldVoltage = 0;
|
|
if (buclnb.buc == voltage_buc::_24V) { oldVoltage = 24; }
|
|
#ifdef MODEM_IS_SCPC
|
|
if (buclnb.buc == voltage_buc::_24V) { oldVoltage = 24; }
|
|
#endif
|
|
|
|
auto result = data.value("bucPowering", oldVoltage);
|
|
switch (result) {
|
|
case 24: buclnb.buc = voltage_buc::_24V; break;
|
|
#ifdef MODEM_IS_SCPC
|
|
case 48: buclnb.buc = voltage_buc::_48V; break;
|
|
#endif
|
|
case 0:
|
|
default:
|
|
buclnb.buc = voltage_buc::DISABLE;
|
|
}
|
|
}
|
|
buclnb.is_ref_10MHz_buc = data.value("bucRefClk10M", buclnb.is_ref_10MHz_buc);
|
|
#ifdef MODEM_IS_TDMA
|
|
buclnb.lo_buc_inkHz = data.value("bucLoKhz", buclnb.lo_buc_inkHz);
|
|
#endif
|
|
|
|
{
|
|
// напряжение lnb
|
|
int oldVoltage;
|
|
switch (buclnb.lnb) {
|
|
case voltage_lnb::_13V: oldVoltage = 13; break;
|
|
case voltage_lnb::_18V: oldVoltage = 18; break;
|
|
case voltage_lnb::_24V: oldVoltage = 24; break;
|
|
default: oldVoltage = 0;
|
|
}
|
|
|
|
auto result = data.value("lnbPowering", oldVoltage);
|
|
switch (result) {
|
|
case 13: buclnb.lnb = voltage_lnb::_13V; break;
|
|
case 18: buclnb.lnb = voltage_lnb::_18V; break;
|
|
case 24: buclnb.lnb = voltage_lnb::_24V; break;
|
|
default: buclnb.lnb = voltage_lnb::DISABLE;
|
|
}
|
|
}
|
|
buclnb.is_ref_10MHz_lnb = data.value("lnbRefClk10M", buclnb.is_ref_10MHz_lnb);
|
|
#ifdef MODEM_IS_TDMA
|
|
buclnb.lo_lnb_inkHz = data.value("lnbLoKhz", buclnb.lo_lnb_inkHz);
|
|
#endif
|
|
|
|
buclnb.is_ref_10MHz_output = data.value("srvRefClk10M", buclnb.is_ref_10MHz_output);
|
|
buclnb.is_save_current_state = data.value("bucLnbAutoStart", buclnb.is_save_current_state);
|
|
}
|
|
void api_driver::obj::TerminalRxTxSettings::storeBuclnbSettings(proxy::CpProxy &cp) {
|
|
cp.setBuclnbSettings(buclnb);
|
|
}
|
|
#endif
|
|
|
|
|
|
void api_driver::obj::TerminalRxTxSettings::storeAll(proxy::CpProxy &cp) {
|
|
storeMainSettings(cp);
|
|
#ifdef API_OBJECT_DPDI_SETTINGS_ENABLE
|
|
storeDpdiSettings(cp);
|
|
#endif
|
|
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
|
|
storeBuclnbSettings(cp);
|
|
#endif
|
|
}
|
|
|
|
|
|
nlohmann::json api_driver::obj::TerminalRxTxSettings::asJson() const {
|
|
nlohmann::json res;
|
|
|
|
// RX TX
|
|
{
|
|
auto& rxtx = res["rxtx"];
|
|
// для модулятора
|
|
#ifdef MODEM_IS_SCPC
|
|
rxtx["isCinC"] = mod.is_cinc;
|
|
#endif
|
|
rxtx["txEn"] = mod.tx_is_on;
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
rxtx["txAutoStart"] = mod.is_save_current_state;
|
|
rxtx["txIsTestInput"] = mod.is_test_data;
|
|
#endif
|
|
rxtx["txModulatorIsTest"] = !mod.is_carrier;
|
|
rxtx["txCentralFreq"] = mod.central_freq_in_kGz;
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
rxtx["txBaudrate"] = mod.baudrate;
|
|
rxtx["txRolloff"] = mod.rollof;
|
|
rxtx["txGoldan"] = mod.gold_seq_is_active ? 1 : 0;
|
|
#endif
|
|
rxtx["txAttenuation"] = mod.attenuation;
|
|
#ifdef MODEM_IS_SHPS
|
|
rxtx["txSpreadCoef"] = mod.koef_spread;
|
|
rxtx["txFieldsDataPreamble"] = mod.txFieldsDataPreamble;
|
|
#endif
|
|
|
|
#if defined(MODEM_IS_SCPC) || defined(MODEM_IS_SHPS)
|
|
const bool acmIsFrameSizeNormal = extractModcodFrameSizeNormal(mod.modcod_tx);
|
|
const bool acmIsPilots = extractModcodIsPilots(mod.modcod_tx);
|
|
|
|
rxtx["txFrameSizeNormal"] = acmIsFrameSizeNormal;
|
|
rxtx["txIsPilots"] = acmIsPilots;
|
|
|
|
rxtx["dvbCcmModulation"] = extractModcodModulation(mod.modcod_tx);
|
|
rxtx["dvbCcmSpeed"] = extractModcodSpeed(mod.modcod_tx);
|
|
#endif
|
|
|
|
// демодулятор
|
|
rxtx["rxAgcEn"] = dem.is_aru_on;
|
|
rxtx["rxManualGain"] = dem.gain;
|
|
rxtx["rxSpectrumInversion"] = dem.is_rvt_iq;
|
|
rxtx["rxCentralFreq"] = dem.central_freq_in_kGz;
|
|
rxtx["rxBaudrate"] = dem.baudrate;
|
|
rxtx["rxRolloff"] = dem.rollof;
|
|
#if defined(MODEM_IS_SCPC) || defined (MODEM_IS_SHPS)
|
|
rxtx["rxGoldan"] = dem.gold_seq_is_active ? 1 : 0;
|
|
#endif
|
|
#ifdef MODEM_IS_SHPS
|
|
rxtx["rxSpreadCoef"] = dem.koef_spread;
|
|
rxtx["rxFftShift"] = dem.rxFftShift;
|
|
#endif
|
|
|
|
#ifdef API_STRUCT_ACM_ENABLE
|
|
// ACM
|
|
#ifdef MODEM_IS_SCPC
|
|
// эти настройки только в SCPC
|
|
rxtx["dvbServicePacketPeriod"] = acm.period_pack_acm;
|
|
rxtx["dvbIsAcm"] = acm.enable_acm;
|
|
|
|
rxtx["dvbAcmMinModulation"] = extractModcodModulation(acm.min_modcod_acm);
|
|
rxtx["dvbAcmMinSpeed"] = extractModcodSpeed(acm.min_modcod_acm);
|
|
|
|
rxtx["dvbAcmMaxModulation"] = extractModcodModulation(acm.max_modcod_acm);
|
|
rxtx["dvbAcmMaxSpeed"] = extractModcodSpeed(acm.max_modcod_acm);
|
|
|
|
rxtx["dvbSnrReserve"] = acm.snr_threashold_acm; // запас ОСШ
|
|
#endif
|
|
|
|
rxtx["aupcEn"] = acm.enable_aupc;
|
|
rxtx["aupcMinAttenuation"] = acm.min_attenuation_aupc;
|
|
rxtx["aupcMaxAttenuation"] = acm.max_attenuation_aupc;
|
|
rxtx["aupcRequiredSnr"] = acm.snr_threashold_aupc;
|
|
#endif
|
|
}
|
|
|
|
#ifdef API_OBJECT_DPDI_SETTINGS_ENABLE
|
|
{
|
|
auto& dp = res["dpdi"];
|
|
|
|
dp["isPositional"] = !dpdi.is_delay_window;
|
|
#ifdef MODEM_IS_SCPC
|
|
dp["searchBandwidth"] = dpdi.freq_offset;
|
|
#endif
|
|
|
|
dp["positionStationLatitude"] = translateCoordinates(dpdi.latitude_station_grad, dpdi.latitude_station_minute);
|
|
dp["positionStationLongitude"] = translateCoordinates(dpdi.longitude_station_grad, dpdi.longitude_station_minute);
|
|
dp["positionSatelliteLongitude"] = translateCoordinates(dpdi.longitude_sattelite_grad, dpdi.longitude_sattelite_minute);
|
|
|
|
#ifdef MODEM_IS_SCPC
|
|
dp["delayMin"] = dpdi.min_delay;
|
|
dp["delayMax"] = dpdi.max_delay;
|
|
#else
|
|
dp["delay"] = dpdi.max_delay;
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
// BucLnb
|
|
#ifdef API_OBJECT_BUCLNB_SETTINGS_ENABLE
|
|
{
|
|
auto& bl = res["buclnb"];
|
|
switch (buclnb.buc) {
|
|
case voltage_buc::_24V: bl["bucPowering"] = 24; break;
|
|
#ifdef MODEM_IS_SCPC
|
|
case voltage_buc::_48V: bl["bucPowering"] = 48; break;
|
|
#endif
|
|
default: bl["bucPowering"] = 0;
|
|
}
|
|
#ifdef MODEM_IS_TDMA
|
|
bl["bucLoKhz"] = buclnb.lo_buc_inkHz;
|
|
#endif
|
|
|
|
bl["bucRefClk10M"] = buclnb.is_ref_10MHz_buc;
|
|
switch (buclnb.lnb) {
|
|
case voltage_lnb::_13V: bl["lnbPowering"] = 13; break;
|
|
case voltage_lnb::_18V: bl["lnbPowering"] = 18; break;
|
|
case voltage_lnb::_24V: bl["lnbPowering"] = 24; break;
|
|
default: bl["lnbPowering"] = 0;
|
|
}
|
|
bl["lnbRefClk10M"] = buclnb.is_ref_10MHz_lnb;
|
|
#ifdef MODEM_IS_TDMA
|
|
bl["lnbLoKhz"] = buclnb.lo_lnb_inkHz;
|
|
#endif
|
|
|
|
bl["srvRefClk10M"] = buclnb.is_ref_10MHz_output;
|
|
bl["bucLnbAutoStart"] = buclnb.is_save_current_state;
|
|
}
|
|
#endif
|
|
return res;
|
|
}
|
|
|
|
api_driver::obj::TerminalRxTxSettings::~TerminalRxTxSettings() = default;
|
|
|
|
|
|
|
|
|
|
|