#include "terminal_api_driver.h" #include #include "terminal_api/ControlProtoCInterface.h" #include #include #include #include #include #include #include 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 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()); } class TerminalNetworkSettings { public: std::string managementIp, managementGateway, mode, dataIp; unsigned int dataMtu = 1500; TerminalNetworkSettings() = default; TerminalNetworkSettings(const TerminalNetworkSettings& src) = default; ~TerminalNetworkSettings() = default; TerminalNetworkSettings& operator= (const TerminalNetworkSettings& src) = default; void loadDefaults() { managementIp = "0.0.0.0/0"; managementGateway = ""; mode = "l2"; dataIp = "0.0.0.0/0"; dataMtu = 1500; } }; class TerminalFirmwareVersion { public: std::string version, modemId, modemSn, macMang, macData; TerminalFirmwareVersion() = default; TerminalFirmwareVersion(const TerminalFirmwareVersion& src) = default; ~TerminalFirmwareVersion() = default; TerminalFirmwareVersion& operator= (const TerminalFirmwareVersion& src) = default; }; static std::ostream& operator<<(std::ostream& out, CP_Result result) { switch (result) { case OK: out << "OK"; break; case TIMEOUT: out << "TIMEOUT"; break; case ERROR: out << "ERROR"; break; case ABORT: out << "ABORT"; break; case BUSY: out << "BUSY"; break; default: out << static_cast(result); } return out; } /** * Этот демон нужен для того, чтобы получать статистику из 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() { modulator_state modulator{}; demodulator_state demodulator{}; device_state device{}; #ifdef MODEM_IS_SCPC CinC_state cinc{}; #endif std::lock_guard lock(this->cpApiMutex); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetModulatorState()", CP_GetModulatorState(sid, modulator)); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDemodulatorState()", CP_GetDemodulatorState(sid, demodulator)); logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDeviceState()", CP_GetDeviceState(sid, device)); #ifdef MODEM_IS_TDMA std::string tmpDevState; logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetDmaDebug(status_init)", CP_GetDmaDebug(sid, "status_init", &tmpDevState)); #endif #ifdef MODEM_IS_SCPC bool isCinC = getIsCinC(); if (isCinC) { logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetCinCState()", CP_GetCinCState(sid, cinc)); } #endif { std::lock_guard lock2(this->stateMutex); this->modState = modulator; this->demodState = demodulator; this->devState = device; #ifdef MODEM_IS_TDMA this->deviceInitState = tmpDevState; #endif #ifdef MODEM_IS_SCPC this->cincState = cinc; #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{}; DPDI_parmeters dpdi{}; #endif 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)); logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetDpdiParams()", CP_GetDpdiParams(sid, &dpdi)); #endif logCpApiError("api_driver::TerminalApiDaemon::updateSettings()->CP_GetBUC_LNB_settings()", CP_GetBUC_LNB_settings(sid, bucLnb)); { std::lock_guard lock2(this->settingsMutex); this->modSettings = mod; this->demodSettings = demod; #ifdef MODEM_IS_SCPC this->acmSettings = acm; this->dpdiSettings = dpdi; #endif this->bucLnbSettings = bucLnb; } } void updateNetworkSettings() { TerminalNetworkSettings s; std::string tmp; std::lock_guard lock(this->cpApiMutex); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &tmp)); s.managementIp = tmp + "/"; tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp)); s.managementIp += std::to_string(calculateSubnetMask(tmp)); tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway)); s.managementGateway = tmp; tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp)); if (tmp == "tun") { s.mode = "l3"; logCpApiError("api_driver::TerminalApiDaemon::updateNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp)); s.dataIp += "/24"; } else { s.mode = "l2"; s.dataIp = "0.0.0.0/24"; } s.dataMtu = 1500; { 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"; } 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 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->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(); } int64_t sleepTime = 60000; // минута по-умолчанию auto now = std::chrono::time_point_cast(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::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::shared_mutex stateMutex; modulator_state modState{}; demodulator_state demodState{}; device_state devState{}; std::string deviceInitState; #ifdef MODEM_IS_SCPC CinC_state cincState{}; #endif std::shared_mutex settingsMutex; modulator_settings modSettings{}; demodulator_settings demodSettings{}; #ifdef MODEM_IS_SCPC ACM_parameters_serv_ acmSettings{}; DPDI_parmeters dpdiSettings{}; #endif 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: 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; } #ifdef MODEM_IS_SCPC /** * Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. * @param mod статистика модулятра * @param demod статистика демодулятора * @param dev статистика устройства (температуры) * @param cinc статистика CinC (актуальна только для режима CinC, но в любом случае будет перезаписана) */ void getState(modulator_state* mod, demodulator_state* demod, device_state* dev, CinC_state* cinc) { 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; } if (cinc) { *cinc = this->cincState; } } } #else /** * Получение статистики, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. * @param mod статистика модулятра * @param demod статистика демодулятора * @param dev статистика устройства (температуры) */ void getState(modulator_state* mod, demodulator_state* demod, device_state* dev) { if (mod != nullptr || demod != nullptr || dev != nullptr) { std::shared_lock lock(this->stateMutex); if (mod) { *mod = this->modState; } if (demod) { *demod = this->demodState; } if (dev) { *dev = this->devState; } } } #endif /** * Получение настроек, копирует текущие значения в структуры, переданные по указателю. Если передан пустой указатель, копирования не произойдет. */ #ifdef MODEM_IS_SCPC void getSettings(modulator_settings* mod, demodulator_settings* demod, ACM_parameters_serv_* acm, DPDI_parmeters* dpdi, buc_lnb_settings* bucLnb) { 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; } } } #else void getSettings(modulator_settings* mod, demodulator_settings* demod, buc_lnb_settings* bucLnb) { if (mod || demod || bucLnb) { std::shared_lock lock(this->settingsMutex); if (mod) { *mod = this->modSettings; } if (demod) { *demod = this->demodSettings; } if (bucLnb) { *bucLnb = this->bucLnbSettings; } } } #endif #ifdef MODEM_IS_SCPC bool getIsCinC() { std::shared_lock lock(this->settingsMutex); return modSettings.is_cinc; } #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 #ifdef MODEM_IS_SCPC void setSettingsCinc(DPDI_parmeters& s, bool readback = true) { std::lock_guard lock(this->cpApiMutex); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", "")); logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDpdiParams()", CP_SetDpdiParams(sid, s)); if (readback) { logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_GetDpdiParams()", CP_GetDpdiParams(this->sid, &s)); { std::lock_guard lock2{this->settingsMutex}; this->dpdiSettings = s; } } logCpApiError("api_driver::TerminalApiDaemon::setSettingsCinc()->CP_SetDmaDebug(save_config)", CP_SetDmaDebug(sid, "save_config", "")); } #endif 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(s.managementIp); std::pair data; bool isL2; if (s.mode == "l2") { isL2 = true; } else if (s.mode == "l3") { isL2 = false; data = splitIpAndMask(s.dataIp); } else { throw std::runtime_error("invalid mode"); } std::lock_guard lock(this->cpApiMutex); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetDmaDebug(begin_save_config)", CP_SetDmaDebug(sid, "begin_save_config", "")); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mode)", CP_SetNetwork(sid, "mode", isL2 ? "tap" : "tun")); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(addr)", CP_SetNetwork(sid, "addr", mang.first.c_str())); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(mask)", CP_SetNetwork(sid, "mask", mang.second.c_str())); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(gateway)", CP_SetNetwork(sid, "gateway", s.managementGateway.c_str())); if (!isL2) { logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_SetNetwork(data_addr)", CP_SetNetwork(sid, "data_addr", data.first.c_str())); // TODO маска не устанавливается, потому что в API этого нет } // TODO MTU не устанавливается, потому что в API этого нет if (readback) { std::string tmp; s.loadDefaults(); s.managementIp.clear(); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr)", CP_GetNetwork(sid, "addr", &s.managementIp)); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mask)", CP_GetNetwork(sid, "mask", &tmp)); s.managementIp += "/"; s.managementIp += std::to_string(calculateSubnetMask(tmp)); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(gateway)", CP_GetNetwork(sid, "gateway", &s.managementGateway)); tmp.clear(); logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(mode)", CP_GetNetwork(sid, "mode", &tmp)); if (tmp == "tun") { s.mode = "l3"; logCpApiError("api_driver::TerminalApiDaemon::setNetworkSettings()->CP_GetNetwork(addr_data)", CP_GetNetwork(sid, "addr_data", &s.dataIp)); } else { s.mode = "l2"; s.dataIp = "0.0.0.0/24"; } s.dataMtu = 1500; { 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; void api_driver::ApiDriver::startDaemon() { if (daemon == nullptr) { daemon = std::make_unique(); 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; } } #ifdef MODEM_IS_SCPC double translateCoordinates(uint8_t deg, uint8_t min) { return static_cast(deg) + static_cast(min) / 60; } std::tuple translateCoordinates(double abs) { auto deg = static_cast(abs); double min_double = (abs - deg) * 60; auto min = static_cast(min_double); return std::make_tuple(deg, min); } #endif std::string api_driver::ApiDriver::loadTerminalState() const { if (daemon == nullptr) { return R"({"error": "api daemon not started!"})"; } std::stringstream result; result << "{\n\"initState\":" << buildEscapedString(daemon->getDeviceInitState()); modulator_state modulator{}; demodulator_state demodulator{}; device_state device{}; #ifdef MODEM_IS_SCPC CinC_state cinc{}; daemon->getState(&modulator, &demodulator, &device, &cinc); const bool isCinC = this->daemon->getIsCinC(); #else daemon->getState(&modulator, &demodulator, &device); #endif #ifdef MODEM_IS_SCPC result << ",\"isCinC\":" << boolAsStr(isCinC); #endif // формируем структуру для TX result << ",\n\"tx.state\":" << boolAsStr(modulator.is_tx_on); result << ",\"tx.modcod\":" << modulator.modcod; #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); result << ",\"tx.centerFreq\":"; writeDouble(result, modSet.central_freq_in_kGz); result << ",\"tx.symSpeed\":"; writeDouble(result, (static_cast(modSet.baudrate) / 1000.0)); } #endif result << ",\"tx.speedOnTxKbit\":"; writeDouble(result, static_cast(modulator.speed_in_bytes_tx) / 128.0); result << ",\"tx.speedOnIifKbit\":"; writeDouble(result, (static_cast(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(demodulator.speed_in_bytes_rx) / 128.0); result << ",\"rx.speedOnIifKbit\":"; writeDouble(result, static_cast(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); 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{}; buc_lnb_settings bucLnb{}; TerminalNetworkSettings network; #ifdef MODEM_IS_SCPC ACM_parameters_serv_ acmSettings{}; DPDI_parmeters dpdiSettings{}; daemon->getSettings(&modSettings, &demodSettings, &acmSettings, &dpdiSettings, &bucLnb); #else daemon->getSettings(&modSettings, &demodSettings, &bucLnb); #endif daemon->getNetworkSettings(network); std::stringstream result; #ifdef MODEM_IS_SCPC 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(modSettings.rollof * 100); result << ",\"tx.goldan\":" << static_cast(modSettings.qold_seq_is_active); 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 >> 2); // 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(demodSettings.rollof * 100); result << ",\"rx.goldan\":" << static_cast(demodSettings.qold_seq_is_active); result << ",\"rx.cymRate\":" << demodSettings.baudrate; result << ",\"rx.centerFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz); result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\""); result << ",\"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; #else result << "{\n\"tx.txEn\":" << boolAsStr(modSettings.tx_is_on); result << ",\"tx.isTestInputData\":" << boolAsStr(modSettings.is_test_data); result << ",\"tx.cymRate\":" << modSettings.baudrate; result << ",\"tx.centerFreq\":"; writeDouble(result, modSettings.central_freq_in_kGz, 3); result << ",\"tx.attenuation\":"; writeDouble(result, modSettings.attenuation); result << ",\n\"rx.gainMode\":" << (demodSettings.is_aru_on ? "\"auto\"" : "\"manual\""); result << ",\"rx.manualGain\":"; writeDouble(result, demodSettings.gain); result << ",\"rx.spectrumInversion\":" << boolAsStr(demodSettings.is_rvt_iq); result << ",\"rx.rolloff\":" << static_cast(demodSettings.rollof * 100); result << ",\"rx.cymRate\":" << demodSettings.baudrate; result << ",\"rx.centerFreq\":"; writeDouble(result, demodSettings.central_freq_in_kGz); #endif result << ",\n\"buc.refClk10M\":" << boolAsStr(bucLnb.is_ref_10MHz_buc); 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 << ",\"network.managementIp\":\n" << buildEscapedString(network.managementIp); result << ",\"network.managementGateway\":\n" << buildEscapedString(network.managementGateway); result << ",\"network.mode\":\n" << buildEscapedString(network.mode); result << ",\"network.dataIp\":\n" << buildEscapedString(network.dataIp); result << ",\"network.dataMtu\":\n" << network.dataMtu; result << "}"; return result.str(); } std::string api_driver::ApiDriver::loadFirmwareVersion() const { if (daemon == nullptr) { return R"({"error": "api daemon not started!"})"; } std::stringstream result; auto firmware = daemon->getFirmware(); result << "{\n\"fw.version\":" << buildEscapedString(firmware.version); result << ",\"fw.modemId\":" << buildEscapedString(firmware.modemId); result << ",\"fw.modemSn\":" << buildEscapedString(firmware.modemSn); result << ",\"fw.macMang\":" << buildEscapedString(firmware.macMang); result << ",\"fw.macData\":" << buildEscapedString(firmware.macData); result << "\n}"; return result.str(); } void api_driver::ApiDriver::setRxTxSettings(boost::property_tree::ptree &pt) { modulator_settings mod{}; demodulator_settings demod{}; #ifdef MODEM_IS_SCPC ACM_parameters_serv_ acm{}; #endif // для модулятора #ifdef MODEM_IS_SCPC mod.is_cinc = pt.get(json_path("general.isCinC", '/')); mod.tx_is_on = pt.get(json_path("general.txEn", '/')); auto tmp = pt.get(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(json_path("general.autoStartTx", '/')); mod.is_test_data = pt.get(json_path("general.isTestInputData", '/')); mod.attenuation = pt.get(json_path("tx.attenuation", '/')); mod.rollof = pt.get(json_path("tx.rolloff", '/')) / 100.0; mod.qold_seq_is_active = pt.get(json_path("tx.goldan", '/')); mod.baudrate = pt.get(json_path("tx.cymRate", '/')); mod.central_freq_in_kGz = pt.get(json_path("tx.centerFreq", '/')); const bool acmIsShortFrame = !pt.get(json_path("dvbs2.frameSizeNormal", '/')); mod.modcod_tx = (pt.get(json_path("dvbs2.ccm_modcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0); #else mod.tx_is_on = pt.get(json_path("tx.txEn", '/')); mod.is_test_data = pt.get(json_path("tx.isTestInputData", '/')); mod.central_freq_in_kGz = pt.get(json_path("tx.centerFreq", '/')); mod.baudrate = pt.get(json_path("tx.cymRate", '/')); mod.attenuation = pt.get(json_path("tx.attenuation", '/')); #endif // демодулятор #ifdef MODEM_IS_SCPC tmp = pt.get(json_path("rx.gainMode", '/')); demod.qold_seq_is_active = pt.get(json_path("rx.goldan", '/')); #else auto tmp = pt.get(json_path("rx.gainMode", '/')); #endif if (tmp == "auto") { demod.is_aru_on = true; } else if (tmp == "manual") { demod.is_aru_on = false; } else { throw std::runtime_error("api_driver::ApiDriver::setRxTxSettings(): Wrong gain mode: " + tmp); } demod.gain = pt.get(json_path("rx.manualGain", '/')); demod.baudrate = pt.get(json_path("rx.cymRate", '/')); demod.is_rvt_iq = pt.get(json_path("rx.spectrumInversion", '/')); demod.rollof = pt.get(json_path("rx.rolloff", '/')) / 100.0; demod.central_freq_in_kGz = pt.get(json_path("rx.centerFreq", '/')); #ifdef MODEM_IS_SCPC // ACM acm.enable = pt.get(json_path("dvbs2.isAcm", '/')); acm.max_modcod = (pt.get(json_path("dvbs2.acm_maxModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0); acm.min_modcod = (pt.get(json_path("dvbs2.acm_minModcod", '/')) << 2) | (acmIsShortFrame ? 2 : 0); acm.snr_treashold_acm = pt.get(json_path("dvbs2.snrReserve", '/')); // запас ОСШ acm.period_pack = pt.get(json_path("dvbs2.servicePacketPeriod", '/')); acm.enable_auto_atten = pt.get(json_path("acm.en", '/')); acm.max_attenuation = pt.get(json_path("acm.maxAttenuation", '/')); acm.min_attenuation = pt.get(json_path("acm.minAttenuation", '/')); acm.snr_treashold = pt.get(json_path("acm.requiredSnr", '/')); // требуемый ОСШ daemon->setSettingsRxTx(mod, demod, acm); #else daemon->setSettingsRxTx(mod, demod); #endif } #ifdef MODEM_IS_SCPC void api_driver::ApiDriver::setCincSettings(boost::property_tree::ptree &pt) { DPDI_parmeters s{}; //result << ",\n\"cinc.mode\":" << (dpdiSettings.is_delay_window ? "\"delay\"" : "\"positional\""); auto tmp = pt.get(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(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(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(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(json_path("cinc.delayMax", '/')); s.min_delay = pt.get(json_path("cinc.delayMin", '/')); s.freq_offset = pt.get(json_path("cinc.searchBandwidth", '/')); this->daemon->setSettingsCinc(s); } #endif void api_driver::ApiDriver::setBucLnbSettings(boost::property_tree::ptree &pt) { buc_lnb_settings s{}; auto tmp = pt.get(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(json_path("lnb.refClk10M", '/')); tmp = pt.get(json_path("buc.powering", '/')); switch (tmp) { case 24: s.buc = voltage_buc::_24V; break; #ifdef MODEM_IS_SCPC case 48: s.buc = voltage_buc::_48V; break; #endif case 0: default: s.lnb = voltage_lnb::DISABLE; } s.is_ref_10MHz_buc = pt.get(json_path("buc.refClk10M", '/')); s.is_ref_10MHz_output = pt.get(json_path("serviceSettings.refClk10M", '/')); s.is_save_current_state = pt.get(json_path("serviceSettings.autoStart", '/')); this->daemon->setSettingsBucLnb(s); } void api_driver::ApiDriver::setQosSettings(boost::property_tree::ptree &pt) { bool enabled = pt.get("en"); pt.erase("en"); std::ostringstream oss; write_json(oss, pt); this->daemon->setQosSettings(enabled, oss.str()); } void api_driver::ApiDriver::setNetworkSettings(boost::property_tree::ptree &pt) { TerminalNetworkSettings s; s.managementIp = pt.get(json_path("network.managementIp", '/')); s.managementGateway = pt.get(json_path("network.managementGateway", '/')); s.mode = pt.get(json_path("network.mode", '/')); s.dataIp = pt.get(json_path("network.dataIp", '/')); s.dataMtu = pt.get(json_path("network.dataMtu", '/')); daemon->setNetworkSettings(s); } void api_driver::ApiDriver::setDebugSendSettings(boost::property_tree::ptree &pt) { boost::ignore_unused(pt); } void api_driver::ApiDriver::resetDefaultSettings() { daemon->resetDefaultSettings(); } void api_driver::ApiDriver::executeInApi(const std::function& callback) { try { std::lock_guard lock(this->daemon->cpApiMutex); callback(this->daemon->sid); } catch (std::exception& e) { BOOST_LOG_TRIVIAL(error) << "ApiDriver::executeInApi(): failed to exec with error: " << e.what(); } } std::string api_driver::ApiDriver::loadSysInfo() { std::stringstream result; struct sysinfo info{}; sysinfo(&info); struct sysinfo { long uptime; /* Seconds since boot */ unsigned long loads[3]; /* 1, 5, and 15 minute load averages */ unsigned long totalram; /* Total usable main memory size */ unsigned long freeram; /* Available memory size */ unsigned long sharedram; /* Amount of shared memory */ unsigned long bufferram; /* Memory used by buffers */ unsigned long totalswap; /* Total swap space size */ unsigned long freeswap; /* Swap space still available */ unsigned short procs; /* Number of current processes */ unsigned long totalhigh; /* Total high memory size */ unsigned long freehigh; /* Available high memory size */ unsigned int mem_unit; /* Memory unit size in bytes */ }; result << "{\n\"uptime\":" << info.uptime; result << ",\"load1min\":" << info.loads[0]; result << ",\"load5min\":" << info.loads[1]; result << ",\"load15min\":" << info.loads[2]; result << ",\"totalram\":" << info.totalram; result << ",\"freeram\":" << info.freeram; result << ",\"sharedram\":" << info.sharedram; result << ",\"bufferram\":" << info.bufferram; result << ",\"totalswap\":" << info.totalswap; result << ",\"freeswap\":" << info.freeswap; result << ",\"procs\":" << static_cast(info.procs); result << ",\"totalhigh\":" << info.totalhigh; result << ",\"freehigh\":" << info.freehigh; result << ",\"mem_unit\":" << info.mem_unit; result << "\n}"; return result.str(); } api_driver::ApiDriver::~ApiDriver() = default;