какая-то куча изменений (2). тут уже вырисовывается новая архитектура бекенда для cp api

This commit is contained in:
2025-05-29 18:56:19 +03:00
parent 3745f98a82
commit 3e38e77069
9 changed files with 1059 additions and 769 deletions

View File

@@ -1,8 +1,68 @@
#include "api-driver/structs.h"
#include "api-driver/proxy.h"
#include <iomanip>
#include <sys/sysinfo.h>
#include <boost/property_tree/ptree.hpp>
#include "api-driver/proxy.h"
#define TIME_NOW() std::chrono::time_point_cast<std::chrono::milliseconds>(std::chrono::system_clock::now()).time_since_epoch().count()
typedef boost::property_tree::ptree::path_type json_path;
static constexpr const char* DEFAULT_QOS_CLASSES = R"({"rt1":[],"rt2":[],"rt3":[],"cd":[]})";
// пороговое значение сна
// static int calculateSubnetMask(const std::string& subnet_mask) {
// int mask = 0;
// std::istringstream iss(subnet_mask);
// std::string octet;
// while (std::getline(iss, octet, '.')) {
// int octet_value = std::stoi(octet);
// for (int i = 7; i >= 0; i--) {
// if (octet_value & (1 << i)) {
// mask++;
// }
// }
// }
// return mask;
// }
/**
* Преобразует строку вида `1.2.3.4/24` в пару строк вида `1.2.3.4` `255.255.255.0`
*/
// std::pair<std::string, std::string> splitIpAndMask(const std::string& input) {
// auto pos = input.find('/');
// if (pos == std::string::npos) {
// // Обработка ошибки: нет символа '/'
// throw std::runtime_error("address not contains mask");
// }
// std::string ip = input.substr(0, pos);
// const unsigned int mask_int = std::stoul(input.substr(pos + 1));
//
// if (mask_int > 32) {
// throw std::runtime_error("invalid mask");
// }
//
// std::string mask_binary = std::string(mask_int, '1') + std::string(32 - mask_int, '0');
// std::string mask_str;
//
// for (unsigned int i = 0; i < 4; ++i) {
// std::string octet = mask_binary.substr(i * 8u, 8);
// int octet_value = std::stoi(octet, nullptr, 2);
// mask_str += std::to_string(octet_value) + (i < 3 ? "." : "");
// }
//
// return std::make_pair(ip, mask_str);
// }
static inline void rtrim(std::string &s) {
s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}
static inline const char* boolAsStr(bool value) {
return value ? "true" : "false";
}
std::ostream& operator<<(std::ostream& out, CP_Result result) {
switch (result) {
@@ -47,23 +107,227 @@ int64_t api_driver::obj::CpUpdatebleObject::getNextUpdate(int64_t now) const {
}
api_driver::obj::CpUpdatebleObject::~CpUpdatebleObject() = default;
#if API_OBJECT_STATISTICS_ENABLE
api_driver::obj::StatisticsLogger::StatisticsLogger(): timeStart(TIME_NOW()) {}
void api_driver::obj::TerminalState::updateCallback(TSID sid, CP_Result &lastCpError) {
constexpr const char* thisFunc = "api_driver::obj::TerminalState::load()";
std::string api_driver::obj::StatisticsLogger::getSettings() {
std::lock_guard _lock(mutex);
std::stringstream res;
res << "{\"en\":" << boolAsStr(this->logEn);
res << ",\"logPeriodMs\":" << logPeriodMs;
res << ",\"maxAgeMs\":" << maxAgeMs;
res << '}';
return res.str();
}
modulator_state modulator{};
demodulator_state demodulator{};
void api_driver::obj::StatisticsLogger::setSettings(boost::property_tree::ptree &pt) {
const bool newEn = pt.get<bool>("en");
const int newInterval = pt.get<int>("logPeriodMs");
const int newMaxAgeMs = pt.get<int>("maxAgeMs");
std::lock_guard _lock(this->mutex);
this->logPeriodMs = newInterval;
this->maxAgeMs = newMaxAgeMs;
if (newEn != this->logEn) {
if (newEn) {
this->logFile.open(LOG_FILENAME, std::ios::out);
if (this->logFile.is_open()) {
const auto* header = "timestamp\tcnt ok\tcnt bad\tfine freq dem\tcrs freq dem\tcrs freq compensator\tcrs time est\tfine time est\tmax level corr\tcurrent delay\tSNR\tcurrent modcod\tfine freq compensator\tind freq grb\tind freq tochn\tind filt adapt\tfilter corr cinc\tcorr cnt\tRSS\tcor erl\tcor lat\tgc gain\tpower pl rx\n";
this->logFile.write(header, static_cast<std::streamsize>(strlen(header)));
this->logEn = true;
this->timeStart = TIME_NOW();
}
} else {
if (this->logFile.is_open()) {
this->logFile.close();
}
this->logEn = false;
}
}
}
void api_driver::obj::StatisticsLogger::updateCallback(proxy::CpProxy &cp) {
}
void api_driver::obj::StatisticsLogger::putItem(const debug_metrics &item) {
std::lock_guard _lock(this->mutex);
if (!logEn) return;
if (this->logFile.is_open()) {
std::stringstream res;
res << makeTimepointFromMillis(TIME_NOW()) << '\t';
res << item.cnt_ok << '\t';
res << item.cnt_bad << '\t';
res << item.fine_freq_dem << '\t';
res << item.crs_freq_dem << '\t';
res << item.crs_freq_compensator << '\t';
res << item.crs_time_est << '\t';
res << item.fine_time_est << '\t';
res << item.max_level_corr << '\t';
res << item.current_delay << '\t';
res << item.SNR << '\t';
res << item.current_modcod << '\t';
res << item.fine_freq_compensator << '\t';
res << item.ind_freq_grb << '\t';
res << item.ind_freq_tochn << '\t';
res << item.ind_filt_adapt << '\t';
res << item.filter_corr_cinc << '\t';
res << item.corr_cnt << '\t';
res << item.RSS << '\t';
res << item.cor_erl << '\t';
res << item.cor_lat << '\t';
res << item.gc_gain << '\t';
res << item.power_pl_rx << '\n';
const auto out = res.str();
this->logFile.write(out.c_str(), static_cast<std::streamsize>(out.length()));
this->logFile.flush();
}
}
api_driver::obj::StatisticsLogger::~StatisticsLogger() = default;
#endif
#if API_OBJECT_NETWORK_SETTINGS_ENABLE
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings() { loadDefaults(); }
api_driver::obj::TerminalNetworkSettings::TerminalNetworkSettings(const TerminalNetworkSettings &src) = default;
api_driver::obj::TerminalNetworkSettings & api_driver::obj::TerminalNetworkSettings::operator=(const TerminalNetworkSettings &src) {
managementIp = src.managementIp;
managementGateway = src.managementGateway;
dataIp = src.dataIp;
serverName = src.serverName;
isL2 = src.isL2;
dataMtu = src.dataMtu;
return *this;
}
void api_driver::obj::TerminalNetworkSettings::loadDefaults() {
managementIp = "0.0.0.0";
managementGateway = "";
isL2 = true;
dataIp = "0.0.0.0";
dataMtu = 1500;
serverName = DEFAULT_SERVER_NAME;
}
void api_driver::obj::TerminalNetworkSettings::updateCallback(proxy::CpProxy &cp) {
loadDefaults();
try {
managementIp = cp.getNetwork("addr");
// s.managementIp += "/";
// s.managementIp += std::to_string(calculateSubnetMask(cp.getNetwork("mask")));
managementGateway = cp.getNetwork("gateway");
if (cp.getNetwork("mode") == "tun") {
isL2 = false;
dataIp = cp.getNetwork("addr_data");
} else {
isL2 = true;
}
dataMtu = 1500;
serverName = cp.getNetwork("name_serv");
if (serverName.empty()) {
serverName = DEFAULT_SERVER_NAME;
}
} catch (std::exception& e) {
throw std::runtime_error(std::string("api_driver::obj::TerminalNetworkSettings::updateCallback() error: ") + e.what());
}
}
void api_driver::obj::TerminalNetworkSettings::updateFromPt(boost::property_tree::ptree &pt) {
}
void api_driver::obj::TerminalNetworkSettings::store(proxy::CpProxy& cp) {
try {
cp.setNetwork("mode", isL2 ? "tap" : "tun");
cp.setNetwork("addr", managementIp);
if (!isL2) {
cp.setNetwork("addr_data", dataIp);
}
cp.setNetwork("mask", "255.255.255.0");
cp.setNetwork("gateway", managementGateway);
// cp.setNetwork("data_mtu", std::to_string(dataMtu));
cp.setNetwork("name_serv", serverName);
} catch (std::exception& e) {
throw std::runtime_error(std::string("api_driver::obj::TerminalNetworkSettings::store() error: ") + e.what());
}
}
std::string api_driver::obj::TerminalNetworkSettings::asJson() {
std::stringstream out;
return out.str();
}
api_driver::obj::TerminalNetworkSettings::~TerminalNetworkSettings() = default;
#endif
#if API_OBJECT_QOS_SETTINGS_ENABLE
api_driver::obj::TerminalQosSettings::TerminalQosSettings() {
}
api_driver::obj::TerminalQosSettings::TerminalQosSettings(const TerminalQosSettings &src) {
}
api_driver::obj::TerminalQosSettings & api_driver::obj::TerminalQosSettings::operator=(const TerminalQosSettings &src) {
}
void api_driver::obj::TerminalQosSettings::loadDefaults() {
}
void api_driver::obj::TerminalQosSettings::updateCallback(proxy::CpProxy &cp) {
}
void api_driver::obj::TerminalQosSettings::updateFromPt(boost::property_tree::ptree &pt) {
}
void api_driver::obj::TerminalQosSettings::store(proxy::CpProxy &cp) {
}
std::string api_driver::obj::TerminalQosSettings::asJson() {
}
api_driver::obj::TerminalQosSettings::~TerminalQosSettings() {
}
#endif
void api_driver::obj::TerminalState::updateCallback(proxy::CpProxy& cp) {
modulator_state mod{};
demodulator_state demod{};
#ifdef MODEM_IS_SCPC
CinC_state cinc{};
#endif
try {
cp.getModState(mod);
cp.getDemodState(demod);
#ifdef MODEM_IS_SCPC
// CinC state прописывается в настройках
{
proxy::getModState(sid, modulator, thisFunc);
proxy::getDemodState(sid, demodulator, thisFunc);
#ifdef MODEM_IS_TDMA
const auto tmpDevState = proxy::getDmaDebug(sid, "status_init", thisFunc);
}
cp.getCincState(cinc);
#endif
#ifdef MODEM_IS_TDMA
fInitState = cp.getDmaDebug("status_init");
#endif
} catch (std::exception& e) {
throw std::runtime_error(std::string("api_driver::obj::TerminalState::updateCallback() error: ") + e.what());
}
#ifdef MODEM_IS_SCPC
bool isCinC = getIsCinC();
if (isCinC) {
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetCinCState()", CP_GetCinCState(sid, cinc));
@@ -71,7 +335,6 @@ void api_driver::obj::TerminalState::updateCallback(TSID sid, CP_Result &lastCpE
#endif
{
std::lock_guard lock2(this->mutex);
#ifdef MODEM_IS_TDMA
this->fInitState = tmpDevState;
#endif
@@ -201,6 +464,96 @@ void api_driver::obj::TerminalState::updateCallback(TSID sid, CP_Result &lastCpE
api_driver::obj::TerminalState::~TerminalState() = default;
api_driver::obj::TerminalDeviceState::TerminalDeviceState() = default;
api_driver::obj::TerminalDeviceState::TerminalDeviceState(const TerminalDeviceState &src) = default;
api_driver::obj::TerminalDeviceState & api_driver::obj::TerminalDeviceState::operator=(const TerminalDeviceState &src) {
fOsUptime = src.fOsUptime;
fOsLoad1 = src.fOsLoad1;
fOsLoad5 = src.fOsLoad5;
fOsLoad15 = src.fOsLoad15;
fOsTotalram = src.fOsTotalram;
fOsFreeram = src.fOsFreeram;
fOsProcs = src.fOsProcs;
fTempAdrv = src.fTempAdrv;
fTempZynq = src.fTempZynq;
fTempFpga = src.fTempFpga;
#ifdef MODEM_IS_TDMA
fUpgradeStatus = src.fUpgradeStatus;
fUpgradePercent = src.fUpgradePercent;
fUpgradeImage = src.fUpgradeImage;
#endif
return *this;
}
void api_driver::obj::TerminalDeviceState::updateCallback(proxy::CpProxy &cp) {
{
device_state ds{};
cp.getDeviceState(ds);
fTempAdrv = ds.adrv_temp;
fTempZynq = ds.pl_temp;
fTempFpga = ds.zynq_temp;
}
#ifdef MODEM_IS_TDMA
{
progress_msg ds{};
logCpApiError("api_driver::TerminalApiDaemon::updateState()->CP_GetUpdateStatus()", CP_GetUpdateStatus(sid, ds));
fOtaStatus = ds.status;
fOtaPercent = ds.dwl_percent;
fOtaImage = ds.cur_image;
}
#endif
struct sysinfo info{};
sysinfo(&info);
const double f_load = 100.0 / ((1 << SI_LOAD_SHIFT) * get_nprocs());
fOsUptime = info.uptime;
fOsLoad1 = f_load * static_cast<double>(info.loads[0]);
fOsLoad5 = f_load * static_cast<double>(info.loads[1]);
fOsLoad15 = f_load * static_cast<double>(info.loads[2]);
fOsTotalram = (info.totalram * info.mem_unit) >> 20; // Mb
fOsFreeram = (info.totalram * info.mem_unit) >> 20; // Mb
fOsProcs = info.procs;
}
std::string api_driver::obj::TerminalDeviceState::asJson() const {
std::stringstream result;
result << "{\"uptime\":" << fOsUptime
<< ",\"load1min\":" << std::setprecision(2) << fOsLoad1
<< ",\"load5min\":" << std::setprecision(2) << fOsLoad5
<< ",\"load15min\":" << std::setprecision(2) << fOsLoad15
<< ",\"totalram\":" << fOsTotalram
<< ",\"freeram\":" << fOsFreeram
<< ",\"procs\":" << fOsProcs
<< ",\"adrv\":" << std::setprecision(1) << fTempAdrv
<< ",\"fpga\":" << std::setprecision(1) << fTempFpga
<< ",\"zynq\":" << std::setprecision(1) << fTempZynq;
#ifdef MODEM_IS_TDMA
if (fUpgradeImage.empty()) {
result << R"(,
"upgradeStatus":"Нет обновлений","upgradePercent":0,"upgradeImage":"")";
} else {
switch (fUpgradeStatus) {
case NORM_RX_OBJECT_NEW_API: result << ",\n" R"("upgradeStatus": "Начало загрузки")"; break;
case NORM_RX_OBJECT_INFO_API: result << ",\n" R"("upgradeStatus": "Получено имя образа")"; break;
case NORM_RX_OBJECT_UPDATED_API: result << ",\n" R"("upgradeStatus": "Загружается")"; break;
case NORM_RX_OBJECT_COMPLETED_API: result << ",\n" R"("upgradeStatus": "Загрузка завершена")"; break;
case NORM_RX_OBJECT_ABORTED_API: result << ",\n" R"("upgradeStatus": "Загрузка прервана")"; break;
default: result << ",\n" R"("upgradeStatus": "?")";
}
result << ",\"upgradePercent\":" << fUpgradePercent;
result << ",\"upgradeImage\":" << buildEscapedString(fUpgradeImage);
}
#endif
result << "}";
return result.str();
}
api_driver::obj::TerminalDeviceState::~TerminalDeviceState() = default;