Skip to content

Commit da487fa

Browse files
committed
Added command line argument parser.
1 parent 6f8d7e1 commit da487fa

File tree

6 files changed

+45
-47
lines changed

6 files changed

+45
-47
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ find_package(Gnuradio COMPONENTS
2424
)
2525
find_package(nlohmann_json REQUIRED)
2626
find_package(PahoMqttCpp REQUIRED)
27+
find_package(CLI11 CONFIG REQUIRED)
2728

2829
file(GLOB_RECURSE SOURCES
2930
"${PROJECT_SOURCE_DIR}/sources/*.h"
@@ -50,6 +51,7 @@ target_link_libraries(auto_sdr
5051
nlohmann_json::nlohmann_json
5152
spdlog::spdlog
5253
PahoMqttCpp::paho-mqttpp3
54+
CLI11::CLI11
5355
)
5456

5557
add_executable(auto_sdr_test ${TEST_SOURCES} "tests/test_main.cpp")

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM ubuntu:24.04 AS build
22
ENV DEBIAN_FRONTEND=noninteractive
33
RUN apt-get update && \
4-
apt-get install -y --no-install-recommends ca-certificates curl git zip build-essential cmake ccache tzdata libspdlog-dev libliquid-dev nlohmann-json3-dev libgtest-dev libgmock-dev libusb-1.0-0-dev libfftw3-dev libboost-all-dev libsoapysdr-dev gnuradio gnuradio-dev libsndfile1-dev libssl-dev libpaho-mqtt-dev libpaho-mqttpp-dev
4+
apt-get install -y --no-install-recommends ca-certificates curl git zip build-essential cmake ccache tzdata libspdlog-dev libliquid-dev nlohmann-json3-dev libgtest-dev libgmock-dev libusb-1.0-0-dev libfftw3-dev libboost-all-dev libsoapysdr-dev gnuradio gnuradio-dev libsndfile1-dev libssl-dev libpaho-mqtt-dev libpaho-mqttpp-dev libcli11-dev
55

66
WORKDIR /sdrplay_api
77
COPY sdrplay/*.run .

entrypoint/entrypoint_run.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,5 @@ if [ ! -f /app/config.json ]; then
44
echo "Not found /app/config.json - copying default"
55
cp /config/config.example.json /app/config.json
66
fi
7-
87
sdrplay_apiService &
9-
/usr/bin/auto_sdr /app/config.json
8+
/usr/bin/auto_sdr --config /app/config.json --mqtt-url "$MQTT_URL" --mqtt-user "$MQTT_USER" --mqtt-password "$MQTT_PASSWORD"

sources/config.cpp

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,20 +23,6 @@ spdlog::level::level_enum parseLogLevel(const std::string& level) {
2323
return spdlog::level::level_enum::off;
2424
}
2525

26-
std::string getEnv(const std::string& key) {
27-
const auto value = std::getenv(key.c_str());
28-
if (value) {
29-
if (key.find("PASSWORD") == std::string::npos) {
30-
Logger::info(LABEL, "read env variable, key: {}, value: {}", colored(GREEN, "{}", key), colored(GREEN, "{}", value));
31-
} else {
32-
Logger::info(LABEL, "read env variable, key: {}, value: {}", colored(GREEN, "{}", key), colored(GREEN, "{}", "*****"));
33-
}
34-
return {value};
35-
} else {
36-
throw std::runtime_error(fmt::format("key not found in env: {}", key));
37-
}
38-
}
39-
4026
template <typename T>
4127
T readKey(const nlohmann::json& json, const std::vector<std::string>& keys) {
4228
std::string key;
@@ -69,8 +55,9 @@ std::vector<FrequencyRange> readIgnoredRanges(const nlohmann::json& json) {
6955
}
7056
}
7157

72-
Config::Config(const nlohmann::json& json)
58+
Config::Config(const nlohmann::json& json, const ArgConfig& argConfig)
7359
: m_json(json),
60+
m_argConfig(argConfig),
7461
m_devices(SdrDeviceReader::readDevices(json)),
7562
m_isColorLogEnabled(readKey<bool>(json, {"output", "color_log_enabled"})),
7663
m_consoleLogLevel(parseLogLevel(readKey<std::string>(json, {"output", "console_log_level"}))),
@@ -80,12 +67,9 @@ Config::Config(const nlohmann::json& json)
8067
m_recordingMinTime(std::chrono::milliseconds(readKey<int>(json, {"recording", "min_time_ms"}))),
8168
m_recordingTimeout(std::chrono::milliseconds(readKey<int>(json, {"recording", "max_noise_time_ms"}))),
8269
m_recordingTuningStep(readKey<Frequency>(json, {"recording", "step"})),
83-
m_workers(readKey<int>(json, {"workers"})),
84-
m_mqttUrl(getEnv("MQTT_URL")),
85-
m_mqttUsername(getEnv("MQTT_USER")),
86-
m_mqttPassword(getEnv("MQTT_PASSWORD")) {}
70+
m_workers(readKey<int>(json, {"workers"})) {}
8771

88-
Config Config::loadFromFile(const std::string& path) {
72+
Config Config::loadFromFile(const std::string& path, const ArgConfig& argConfig) {
8973
constexpr auto BUFFER_SIZE = 1024 * 1024;
9074
FILE* file = fopen(path.c_str(), "r");
9175

@@ -98,7 +82,7 @@ Config Config::loadFromFile(const std::string& path) {
9882
ConfigMigrator::update(json);
9983
SdrDeviceReader::scanSoapyDevices(json);
10084
ConfigMigrator::sort(json);
101-
return Config(json);
85+
return Config(json, argConfig);
10286
} catch (const nlohmann::json::parse_error& exception) {
10387
throw std::runtime_error(fmt::format("can not parse config file, invalid json format: {}", path));
10488
}
@@ -123,7 +107,7 @@ void Config::saveToFile(const std::string& path, const nlohmann::json& json) {
123107
}
124108

125109
nlohmann::json Config::json() const { return m_json; }
126-
std::string Config::mqtt() const { return fmt::format("{}@{}", m_mqttUsername, m_mqttUrl); };
110+
std::string Config::mqtt() const { return fmt::format("{}@{}", m_argConfig.mqttUser, m_argConfig.mqttUrl); };
127111

128112
std::vector<Device> Config::devices() const { return m_devices; }
129113

@@ -142,6 +126,6 @@ std::chrono::milliseconds Config::recordingMinTime() const { return m_recordingM
142126
std::chrono::milliseconds Config::recordingTimeout() const { return m_recordingTimeout; }
143127
Frequency Config::recordingTuningStep() const { return m_recordingTuningStep; }
144128

145-
std::string Config::mqttUrl() const { return m_mqttUrl; }
146-
std::string Config::mqttUsername() const { return m_mqttUsername; }
147-
std::string Config::mqttPassword() const { return m_mqttPassword; }
129+
std::string Config::mqttUrl() const { return m_argConfig.mqttUrl; }
130+
std::string Config::mqttUsername() const { return m_argConfig.mqttUser; }
131+
std::string Config::mqttPassword() const { return m_argConfig.mqttPassword; }

sources/config.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ constexpr auto DEBUG_SAVE_FULL_RAW_IQ = false; // sav
1212
constexpr auto DEBUG_SAVE_FULL_POWER = false; // save orgignal sdr data as raw iq
1313
constexpr auto DEBUG_SAVE_RECORDING_RAW_IQ = false; // save recordings as raw iq
1414
constexpr auto INITIAL_DELAY = std::chrono::milliseconds(1000); // delay after first start sdr device to start processing
15-
constexpr auto LOG_FILE_NAME = "sdr_scanner.log"; // log filename
16-
constexpr auto LOG_FILE_SIZE = 10 * 1024 * 1024; // single log file max size
17-
constexpr auto LOG_FILES_COUNT = 9; // keep last n log files
1815
constexpr auto PERFORMANCE_LOGGER_INTERVAL = 1000; // print stats every n frames
1916
constexpr auto RECORDER_FLUSH_INTERVAL = std::chrono::milliseconds(100); // flush recordings to mqtt every 2 * n bytes
2017
constexpr auto RESAMPLER_THRESHOLD = 125; // max interpolation or decimation factor of RESAMPLER
@@ -37,9 +34,19 @@ constexpr auto SPECTROGRAM_PREFERRED_MAX_STEP = 1000; //
3734
constexpr auto SPECTROGRAM_MAX_FFT = 16384; // spectrogram fft limit
3835
constexpr auto SPECTROGRAM_SEND_INTERVAL = std::chrono::milliseconds(1000); // send spectrogram data interval
3936

37+
struct ArgConfig {
38+
std::string configFile;
39+
std::string logFileName = "sdr_scanner.log"; // default log filename
40+
int logFileCount = 9; // default keep last n log files
41+
int logFileSize = 10 * 1024 * 1024; // default single log file max size
42+
std::string mqttUrl;
43+
std::string mqttUser;
44+
std::string mqttPassword;
45+
};
46+
4047
class Config {
4148
public:
42-
static Config loadFromFile(const std::string& path);
49+
static Config loadFromFile(const std::string& path, const ArgConfig& argConfig);
4350
static void saveToFile(const std::string& path, const nlohmann::json& json);
4451
nlohmann::json json() const;
4552
std::string mqtt() const;
@@ -62,9 +69,10 @@ class Config {
6269
std::string mqttPassword() const;
6370

6471
private:
65-
Config(const nlohmann::json& json);
72+
Config(const nlohmann::json& json, const ArgConfig& argConfig);
6673

6774
const nlohmann::json m_json;
75+
const ArgConfig& m_argConfig;
6876

6977
const std::vector<Device> m_devices;
7078

@@ -78,8 +86,4 @@ class Config {
7886
const std::chrono::milliseconds m_recordingTimeout;
7987
const Frequency m_recordingTuningStep;
8088
const int m_workers;
81-
82-
const std::string m_mqttUrl;
83-
const std::string m_mqttUsername;
84-
const std::string m_mqttPassword;
8589
};

sources/main.cpp

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <scanner.h>
77
#include <signal.h>
88

9+
#include <CLI/CLI.hpp>
910
#include <memory>
1011
#include <thread>
1112

@@ -19,32 +20,40 @@ void handler(int) {
1920
}
2021

2122
int main(int argc, char** argv) {
23+
CLI::App app("sdr-scanner");
24+
argv = app.ensure_utf8(argv);
25+
26+
ArgConfig argConfig;
27+
app.add_option("--config", argConfig.configFile, "config file")->required()->check(CLI::ExistingFile);
28+
app.add_option("--log-file", argConfig.logFileName, "log file");
29+
app.add_option("--log-file-count", argConfig.logFileCount, "log file count")->check(CLI::PositiveNumber);
30+
app.add_option("--log-file-size", argConfig.logFileSize, "log file size")->check(CLI::PositiveNumber);
31+
app.add_option("--mqtt-url", argConfig.mqttUrl, "mqtt url")->required();
32+
app.add_option("--mqtt-user", argConfig.mqttUser, "mqtt username")->required();
33+
app.add_option("--mqtt-password", argConfig.mqttPassword, "mqtt password")->required();
34+
CLI11_PARSE(app, argc, argv);
35+
2236
dup2(fileno(fopen("/dev/null", "w")), fileno(stderr));
2337
SoapySDR_setLogLevel(SoapySDRLogLevel::SOAPY_SDR_WARNING);
2438
signal(SIGINT, handler);
2539
signal(SIGTERM, handler);
2640

2741
try {
28-
Logger::configure(spdlog::level::info, spdlog::level::info, LOG_FILE_NAME, LOG_FILE_SIZE, LOG_FILES_COUNT, true);
42+
Logger::configure(spdlog::level::info, spdlog::level::info, argConfig.logFileName, argConfig.logFileSize, argConfig.logFileCount, true);
2943
Logger::info(LABEL, "{}", colored(GREEN, "{}", "starting"));
30-
const std::string configFile = 2 <= argc ? argv[1] : "";
31-
if (configFile.empty()) {
32-
Logger::error(LABEL, "no config file argument provided");
33-
return 1;
34-
}
3544

3645
const auto id = generateRandomHash();
3746
while (isRunning) {
3847
bool reload = false;
39-
const Config config = Config::loadFromFile(configFile);
40-
Logger::configure(config.consoleLogLevel(), config.fileLogLevel(), LOG_FILE_NAME, LOG_FILE_SIZE, LOG_FILES_COUNT, config.isColorLogEnabled());
48+
const Config config = Config::loadFromFile(argConfig.configFile, argConfig);
49+
Logger::configure(config.consoleLogLevel(), config.fileLogLevel(), argConfig.logFileName, argConfig.logFileSize, argConfig.logFileCount, config.isColorLogEnabled());
4150
Logger::info(LABEL, "config: {}", colored(GREEN, "{}", config.json().dump()));
4251
Logger::info(LABEL, "mqtt: {}", colored(GREEN, "{}", config.mqtt()));
4352

4453
Mqtt mqtt(config);
45-
RemoteController remoteController(config, id, mqtt, [&reload, &configFile](const nlohmann::json& json) {
54+
RemoteController remoteController(config, id, mqtt, [&reload, &argConfig](const nlohmann::json& json) {
4655
Logger::info(LABEL, "reload config: {}", colored(GREEN, "{}", json.dump()));
47-
Config::saveToFile(configFile, json);
56+
Config::saveToFile(argConfig.configFile, json);
4857
reload = true;
4958
});
5059
std::vector<std::unique_ptr<Scanner>> scanners;

0 commit comments

Comments
 (0)