44 template <
typename... Args>
47 const std::string message = std::format(fmt, std::forward<Args>(args)...);
54 explicit ContextHandle(
fers_context_t* context) noexcept : _context(context) {}
55 ContextHandle(
const ContextHandle&) =
delete;
56 ContextHandle& operator=(
const ContextHandle&) =
delete;
57 ContextHandle(ContextHandle&&) =
delete;
58 ContextHandle& operator=(ContextHandle&&) =
delete;
61 if (_context !=
nullptr)
67 [[nodiscard]]
fers_context_t* get() const noexcept {
return _context; }
73 bool isParseExit(
const std::string& error)
75 return error ==
"Help requested." || error ==
"Version requested." || error ==
"No arguments provided.";
78 int logApiFailure(
const fers_log_level_t level,
const char* message,
const int result)
81 log(level,
"{}: {}", message, (err !=
nullptr) ? err :
"Unknown error");
88 const char* log_file_ptr = config.
log_file ? config.
log_file->c_str() :
nullptr;
95 std::cerr <<
"[ERROR] Failed to configure logging: " << ((err !=
nullptr) ? err :
"Unknown error") <<
'\n';
107 return logApiFailure(
FERS_LOG_FATAL,
"Failed to load scenario", 1);
118 log(
FERS_LOG_FATAL,
"Failed to configure VITA49 fullscale: missing required fullscale.");
123 return logApiFailure(
FERS_LOG_FATAL,
"Failed to configure VITA49 endpoint", 1);
127 return logApiFailure(
FERS_LOG_FATAL,
"Failed to configure VITA49 fullscale", 1);
132 return logApiFailure(
FERS_LOG_FATAL,
"Failed to configure VITA49 epoch", 1);
137 return logApiFailure(
FERS_LOG_FATAL,
"Failed to configure VITA49 max UDP payload", 1);
142 return logApiFailure(
FERS_LOG_FATAL,
"Failed to configure VITA49 queue depth", 1);
147 int setOutputDirectory(
fers_context_t* context,
const std::filesystem::path& final_out_dir)
153 return logApiFailure(
FERS_LOG_FATAL,
"Failed to set output directory", 1);
158 const std::filesystem::path kml_output_path =
160 const std::string kml_output_file = kml_output_path.string();
162 log(
FERS_LOG_INFO,
"Generating KML file for scenario: {}", kml_output_file);
168 return logApiFailure(
FERS_LOG_FATAL,
"Failed to generate KML file", 1);
178 log(
FERS_LOG_ERROR,
"Failed to set number of threads: {}", (err !=
nullptr) ? err :
"Unknown error");
196 int runCli(
const int argc,
char* argv[])
201 if (!isParseExit(config_result.error()))
203 std::cerr <<
"[ERROR] Argument parsing error: " << config_result.error() <<
'\n';
209 const auto& config = config_result.value();
211 if (configureLogging(config) != 0)
219 "Running FERS with arguments: script_file={}, log_level={}, num_threads={}, validate={}, log_file={}",
226 if (context.get() ==
nullptr)
232 if (loadScenario(context.get(), config) != 0)
237 if (configureVita49Output(context.get(), config) != 0)
242 if (setOutputDirectory(context.get(), final_out_dir) != 0)
249 return generateKml(context.get(), config, final_out_dir);
252 configureThreadCount(config);
254 return runSimulation(context.get());
int fers_set_vita49_queue_depth(fers_context_t *context, uint32_t queue_depth)
Sets the bounded FERS VITA 49.2 sender queue depth in packets.
void fers_log(fers_log_level_t level, const char *message)
Submits a log message to the library's unified logging system.
int fers_load_scenario_from_xml_file(fers_context_t *context, const char *xml_filepath, int validate)
Loads a scenario into the context from a FERS XML file.
char * fers_get_last_error_message()
Retrieves the last error message that occurred on the current thread.
int fers_enable_vita49_udp_output(fers_context_t *context, const char *host, uint16_t port)
Enables the FERS VITA 49.2 UDP streaming profile for a context.
int fers_generate_kml(const fers_context_t *context, const char *output_kml_filepath)
Generates a KML file for visualizing the scenario in the context.
fers_log_level_t
Log levels for the FERS library.
@ FERS_LOG_FATAL
Fatal logging for unrecoverable failures.
@ FERS_LOG_DEBUG
Debug-level diagnostic logging.
@ FERS_LOG_ERROR
Error logging for failed operations.
@ FERS_LOG_INFO
Informational logging.
@ FERS_LOG_TRACE
Trace-level diagnostic logging.
@ FERS_LOG_WARNING
Warning logging for recoverable issues.
int fers_set_output_directory(fers_context_t *context, const char *out_dir)
Sets the output directory for simulation results.
int fers_set_vita49_epoch_unix_nanoseconds(fers_context_t *context, uint64_t epoch_unix_nanoseconds)
Sets a deterministic FERS VITA 49.2 stream epoch as Unix nanoseconds.
void fers_context_destroy(fers_context_t *context)
Destroys a FERS simulation context and releases all associated memory.
fers_context_t * fers_context_create()
Creates a new FERS simulation context.
int fers_run_simulation(fers_context_t *context, fers_progress_callback_t callback, void *user_data)
Runs the simulation defined in the provided context.
void fers_free_string(char *str)
Frees a string that was allocated and returned by the libfers API.
int fers_configure_logging(fers_log_level_t level, const char *log_file_path)
Configures the internal logger.
int fers_set_vita49_fullscale(fers_context_t *context, double fullscale)
Sets the fixed ADC full-scale value used by the FERS VITA 49.2 int16 IQ profile.
int fers_set_vita49_max_udp_payload(fers_context_t *context, uint16_t max_udp_payload)
Sets the FERS VITA 49.2 UDP profile maximum payload size in bytes.
int fers_set_thread_count(unsigned num_threads)
Sets the number of worker threads for the simulation.
Command-line argument parsing utilities for the application.
std::filesystem::path resolveKmlOutputPath(const std::string &script_file, const std::filesystem::path &final_output_dir, const std::optional< std::string > &kml_file) noexcept
Resolves the KML output file path from CLI arguments and output directory.
std::filesystem::path resolveOutputDir(const std::string &script_file, const std::optional< std::string > &output_dir) noexcept
Resolves the final simulation output directory from CLI arguments.
std::expected< Config, std::string > parseArguments(const int argc, char *argv[]) noexcept
Parses command-line arguments.
void log(Level level, const std::source_location &location, const std::string &formatStr, Args &&... args) noexcept
Logs a formatted message with a specific log level and source location.
std::string getLevelString(const Level level) noexcept
Converts a log level enum value to its string representation.
Configuration structure for the application.
std::string script_file
Path to the script file.
fers_log_level_t log_level
Logging level.
std::optional< std::string > output_dir
Optional output directory for simulation results.
bool validate
Validate the input .fersxml file by default.
std::optional< uint64_t > vita49_epoch_unix_nanoseconds
Optional deterministic VITA epoch.
std::optional< double > vita49_fullscale
Fixed ADC full-scale for VITA int16 IQ output.
std::optional< uint32_t > vita49_queue_depth
Optional VITA sender queue depth in packets.
std::optional< std::string > kml_file
Optional specific file path for KML output.
bool generate_kml
Optional flag to generate KML visualization output.
std::string vita49_host
VITA 49.2 UDP destination host.
bool vita49_enabled
True when VITA 49.2 UDP output is selected.
unsigned num_threads
Number of threads to use.
std::optional< uint16_t > vita49_max_udp_payload
Optional VITA UDP payload cap in bytes.
uint16_t vita49_port
VITA 49.2 UDP destination port.
std::optional< std::string > log_file
Optional log file path for logging output.