55#include < radio/sdr_device_reader.h>
66#include < utils/utils.h>
77
8+ #include < fstream>
89#include < regex>
910
1011constexpr auto LABEL = " config" ;
@@ -25,67 +26,13 @@ spdlog::level::level_enum parseLogLevel(const std::string& level) {
2526 return spdlog::level::level_enum::off;
2627}
2728
28- template <typename T>
29- T readKey (const nlohmann::json& json, const std::vector<std::string>& keys) {
30- std::string key;
31- try {
32- nlohmann::json value = json;
33- for (const auto & _key : keys) {
34- value = value.at (_key);
35- key += _key + " ." ;
36- }
37- key.pop_back ();
38- Logger::info (LABEL, " read json variable, key: {}, value: {}" , colored (GREEN, " {}" , key), colored (GREEN, " {}" , value.get <T>()));
39- return value.get <T>();
40- } catch (const std::exception& exception) {
41- throw std::runtime_error (fmt::format (" key not found in json config: {}" , key));
42- }
43- }
44-
45- std::vector<FrequencyRange> readIgnoredRanges (const nlohmann::json& json) {
46- constexpr auto KEY = " ignored_frequencies" ;
47- try {
48- std::vector<FrequencyRange> ranges;
49- for (const auto & item : json.at (KEY)) {
50- const auto frequency = item.at (" frequency" ).get <Frequency>();
51- const auto bandwidth = item.at (" bandwidth" ).get <Frequency>();
52- ranges.emplace_back (frequency - bandwidth / 2 , frequency + bandwidth / 2 );
53- }
54- return ranges;
55- } catch (const std::exception& exception) {
56- throw std::runtime_error (fmt::format (" key not found or invalid value in json: {}" , KEY));
57- }
58- }
59-
60- Config::Config (const nlohmann::json& json, const ArgConfig& argConfig)
61- : m_json(json),
62- m_argConfig(argConfig),
63- m_id(!argConfig.id.empty() ? argConfig.id : randomHex(8 )),
64- m_devices(SdrDeviceReader::readDevices(json)),
65- m_isColorLogEnabled(readKey<bool >(json, {" output" , " color_log_enabled" })),
66- m_consoleLogLevel(parseLogLevel(readKey<std::string>(json, {" output" , " console_log_level" }))),
67- m_fileLogLevel(parseLogLevel(readKey<std::string>(json, {" output" , " file_log_level" }))),
68- m_ignoredRanges(readIgnoredRanges(json)),
69- m_recordingBandwidth(readKey<Frequency>(json, {" recording" , " min_sample_rate" })),
70- m_recordingMinTime(std::chrono::milliseconds(readKey<int >(json, {" recording" , " min_time_ms" }))),
71- m_recordingTimeout(std::chrono::milliseconds(readKey<int >(json, {" recording" , " max_noise_time_ms" }))),
72- m_recordingTuningStep(readKey<Frequency>(json, {" recording" , " step" })),
73- m_workers(readKey<int >(json, {" workers" })),
74- m_apiKey(readKey<std::string>(json, {" api_key" })),
75- m_latitude(readKey<std::string>(json, {" position" , " latitude" })),
76- m_longitude(readKey<std::string>(json, {" position" , " longitude" })),
77- m_altitude(readKey<int >(json, {" position" , " altitude" })) {}
29+ Config::Config (const nlohmann::json& json, const ArgConfig& argConfig) : m_id(!argConfig.id.empty() ? argConfig.id : randomHex(8 )), m_json(json), m_argConfig(argConfig), m_fileConfig(json) {}
7830
7931Config Config::loadFromFile (const std::string& path, const ArgConfig& argConfig) {
80- constexpr auto BUFFER_SIZE = 1024 * 1024 ;
81- FILE* file = fopen (path.c_str (), " r" );
82-
83- if (file) {
84- char buffer[BUFFER_SIZE];
85- const auto size = fread (buffer, 1 , BUFFER_SIZE, file);
86- fclose (file);
32+ std::ifstream stream (path);
33+ if (stream) {
8734 try {
88- auto json = nlohmann::json::parse (std::string{buffer, size} );
35+ auto json = nlohmann::json::parse (stream );
8936 ConfigMigrator::update (json);
9037 SdrDeviceReader::scanSoapyDevices (json);
9138 ConfigMigrator::sort (json);
@@ -99,15 +46,11 @@ Config Config::loadFromFile(const std::string& path, const ArgConfig& argConfig)
9946}
10047
10148void Config::saveToFile (const std::string& path, const nlohmann::json& json) {
102- FILE* file = fopen (path. c_str (), " w " );
103- if (file ) {
49+ std::ofstream stream (path);
50+ if (stream ) {
10451 auto tmp = json;
10552 SdrDeviceReader::clearDevices (tmp);
106- const auto data = tmp.dump (4 , ' ' );
107- if (fwrite (data.c_str (), 1 , data.size (), file) != data.size ()) {
108- Logger::warn (LABEL, " save new config failed" );
109- }
110- fclose (file);
53+ stream << std::setw (4 ) << tmp << std::endl;
11154 } else {
11255 Logger::warn (LABEL, " save new config failed" );
11356 }
@@ -132,28 +75,34 @@ nlohmann::json Config::json() const { return m_json; }
13275std::string Config::mqtt () const { return fmt::format (" {}@{}" , m_argConfig.mqttUser , m_argConfig.mqttUrl ); };
13376
13477std::string Config::getId () const { return m_id; }
135- std::vector<Device> Config::devices () const { return m_devices ; }
78+ std::vector<Device> Config::devices () const { return m_fileConfig. devices ; }
13679
137- bool Config::isColorLogEnabled () const { return m_isColorLogEnabled ; }
138- spdlog::level::level_enum Config::consoleLogLevel () const { return m_consoleLogLevel ; }
139- spdlog::level::level_enum Config::fileLogLevel () const { return m_fileLogLevel ; }
80+ bool Config::isColorLogEnabled () const { return m_fileConfig. output . color_log_enabled ; }
81+ spdlog::level::level_enum Config::consoleLogLevel () const { return parseLogLevel (m_fileConfig. output . console_log_level ) ; }
82+ spdlog::level::level_enum Config::fileLogLevel () const { return parseLogLevel (m_fileConfig. output . file_log_level ) ; }
14083
141- std::vector<FrequencyRange> Config::ignoredRanges () const { return m_ignoredRanges; }
84+ std::vector<FrequencyRange> Config::ignoredRanges () const {
85+ std::vector<FrequencyRange> ranges;
86+ for (const auto & range : m_fileConfig.ignored_frequencies ) {
87+ ranges.emplace_back (range.frequency - range.bandwidth / 2 , range.frequency + range.bandwidth / 2 );
88+ }
89+ return ranges;
90+ }
14291int Config::recordersCount () const {
14392 const auto max_workers = static_cast <int >(std::thread::hardware_concurrency () / 2 );
144- const auto workers = std::max (0 , std::min (m_workers , max_workers));
93+ const auto workers = std::max (0 , std::min (m_fileConfig. workers , max_workers));
14594 return workers == 0 ? max_workers : workers;
14695}
147- Frequency Config::recordingBandwidth () const { return m_recordingBandwidth ; }
148- std::chrono::milliseconds Config::recordingMinTime () const { return m_recordingMinTime ; }
149- std::chrono::milliseconds Config::recordingTimeout () const { return m_recordingTimeout ; }
150- Frequency Config::recordingTuningStep () const { return m_recordingTuningStep ; }
96+ Frequency Config::recordingBandwidth () const { return m_fileConfig. recording . min_sample_rate ; }
97+ std::chrono::milliseconds Config::recordingMinTime () const { return m_fileConfig. recording . min_time_ms ; }
98+ std::chrono::milliseconds Config::recordingTimeout () const { return m_fileConfig. recording . max_noise_time_ms ; }
99+ Frequency Config::recordingTuningStep () const { return m_fileConfig. recording . step ; }
151100
152101std::string Config::mqttUrl () const { return m_argConfig.mqttUrl ; }
153102std::string Config::mqttUsername () const { return m_argConfig.mqttUser ; }
154103std::string Config::mqttPassword () const { return m_argConfig.mqttPassword ; }
155104
156- std::string Config::apiKey () const { return m_apiKey ; }
157- std::string Config::latitude () const { return m_latitude ; }
158- std::string Config::longitude () const { return m_longitude ; }
159- int Config::altitude () const { return m_altitude ; }
105+ std::string Config::apiKey () const { return m_fileConfig. api_key ; }
106+ std::string Config::latitude () const { return m_fileConfig. position . latitude ; }
107+ std::string Config::longitude () const { return m_fileConfig. position . longitude ; }
108+ int Config::altitude () const { return m_fileConfig. position . altitude ; }
0 commit comments