40 #include <linux/limits.h>
51 #define ARGP_ARGUMENTS_COUNT 1
53 #define OPT_FILE_SIZE 1
55 #define OPT_SAMPLES_COUNT 2
57 #define OPT_SET_DEFAULT 3
59 #define OPT_RESET_DEFAULT 4
61 #define OPT_CALIBRATION 5
81 "RocketLogger CLI -- manage your RocketLogger measurements.\n"
82 "Control or configure measurements using the actions specified by ACTION. "
83 "Supported values for ACTION are:\n"
85 " Measurement control:\n"
86 " start\tStart a new measurement with provided configuration\n"
87 " stop\tStop measurement running in the background\n"
89 " Measurement configuration and status management:\n"
90 " config\tDisplay configuration, not starting a new or affecting a "
91 "running measurement\n"
92 " status\tDisplay the current sampling status\n";
97 static char args_doc[] =
"ACTION";
102 static struct argp_option options[] = {
103 {0, 0, 0, OPTION_DOC,
"Basic measurement configuration options:", 1},
105 "Number of samples to record before stopping measurement (k, M, G, T "
106 "scaling suffixes can be used).",
108 {
"channel",
'c',
"SELECTION", 0,
"Channel selection to sample. A comma "
109 "separated list of the channel names (V1, "
110 "V2, V3, V4, I1L, I1H, I2L, and/or I2H) "
111 "or 'all' to enable all channels.",
113 {
"rate",
'r',
"RATE", 0,
"Sampling rate in Hz. Supported values are: 1, "
114 "10, 100, 1k, 2k, 4k, 8k, 16k, 32k, 64k.",
116 {
"update",
'u',
"RATE", 0,
117 "Measurement data update rate in Hz. Supported values: 1, 2, 5, 10.", 0},
118 {
"output",
'o',
"FILE", 0,
119 "Store data to specified file. Use zero to disable file storage.", 0},
120 {
"interactive",
'i', 0, 0,
121 "Display measurement data in the command line interface.", 0},
122 {
"background",
'b', 0, 0,
123 "Start measurement in the background and exit after start.", 0},
125 {0, 0, 0, OPTION_DOC,
126 "Measurement configuration options for storing measurement files:", 3},
127 {
"format",
'f',
"FORMAT", 0,
"Select file format: 'csv', 'rld'.", 0},
129 "Select max file size (k, M, G, T scaling suffixes can be used).", 0},
130 {
"comment",
'C',
"COMMENT", 0,
"Comment stored in file header. Comment is "
131 "ignored if file saving is disabled.",
134 {0, 0, 0, OPTION_DOC,
"Setting and resetting the stored default:", 4},
135 {
"default",
OPT_SET_DEFAULT, 0, 0,
"Set current configuration as default. "
136 "Supported for all measurement "
140 "Reset default configuration to factory defaults and ignores any other "
141 "provided configuration without notice. Only allowed in combination with "
142 "the 'config' action.",
145 {0, 0, 0, OPTION_DOC,
"Optional arguments for extended sampling features:",
147 {
"digital",
'd',
"BOOL", OPTION_ARG_OPTIONAL,
148 "Enable logging of digital inputs. Enabled by default.", 0},
149 {
"ambient",
'a',
"BOOL", OPTION_ARG_OPTIONAL,
150 "Enable logging of ambient sensors, if available. Disabled by default.",
152 {
"aggregate",
'g',
"MODE", 0,
"Data aggregation mode for low sample rates. "
153 "Existing modes: 'average', 'downsample'.",
155 {
"high-range",
'h',
"SELECTION", 0,
156 "Force high range measurements on selected channels. A comma separated "
157 "list of the channel names (I1H and/or I2H) or 'all' to force high range "
158 "measurements all channels. Inactive per default.",
161 "values. Use this option for device "
162 "calibration measurements only.",
164 {
"web",
'w',
"BOOL", OPTION_ARG_OPTIONAL,
165 "Enable web server plotting. Enabled per default.", 0},
167 {0, 0, 0, OPTION_DOC,
"Optional arguments for status and config actions:",
170 "Print configuration or status as JSON formatted string.", 0},
171 {
"cli",
OPT_CLI, 0, 0,
"Print configuration as full CLI command.", 0},
173 {0, 0, 0, OPTION_DOC,
"Generic program switches:", 7},
174 {
"verbose",
'v', 0, 0,
"Produce verbose output", 0},
175 {
"quiet",
'q', 0, 0,
"Do not produce any output", 0},
176 {
"silent",
's', 0, OPTION_ALIAS, 0, 0},
196 static error_t parse_opt(
int key,
char *arg,
struct argp_state *state);
197 static void parse_bool(
char const *arg,
struct argp_state *state,
199 static void parse_bool_named_list(
char const *arg,
struct argp_state *state,
200 char const *
const *
const names,
201 bool *
const values,
int size);
202 static void parse_uint32(
char const *arg,
struct argp_state *state,
203 uint32_t *
const value);
204 static void parse_uint64(
char const *arg,
struct argp_state *state,
205 uint64_t *
const value);
206 static void print_config(
rl_config_t const *
const config);
207 static void print_version(FILE *stream,
struct argp_state *state);
217 static struct argp argp = {
220 .args_doc = args_doc,
236 int main(
int argc,
char *argv[]) {
242 error(EXIT_FAILURE, errno,
"failed reading default configuration file");
249 .config_reset =
false,
250 .config_set_default =
false,
258 int argp_status = argp_parse(&argp, argc, argv, 0, 0, &
arguments);
259 if (argp_status != 0) {
260 error(0, argp_status,
"argument parsing failed");
276 errno, strerror(errno));
290 (strcmp(action,
"start") == 0 || strcmp(action,
"stop") == 0 ||
291 strcmp(action,
"config") == 0 || strcmp(action,
"status") == 0);
299 "string at the same time.");
305 if (valid_config < 0) {
312 if (strcmp(action,
"config") != 0) {
314 "the --reset option is only allowed for config action.");
324 printf(
"The following configuration was saved as new default:\n");
330 if (strcmp(action,
"start") == 0) {
334 "Stop with `rocketlogger stop` first.\n");
344 if (strcmp(action,
"stop") == 0) {
352 printf(
"Wait for measurement to stop...\n");
356 if (strcmp(action,
"config") == 0) {
365 if (strcmp(action,
"status") == 0) {
390 static error_t parse_opt(
int key,
char *arg,
struct argp_state *state) {
433 if (strlen(arg) == 1 && arg[0] ==
'0') {
445 if (strcmp(arg,
"csv") == 0 || strcmp(arg,
"CSV") == 0) {
447 }
else if (strcmp(arg,
"rld") == 0 || strcmp(arg,
"RLD") == 0) {
479 if (strcmp(arg,
"downsample") == 0) {
481 }
else if (strcmp(arg,
"average") == 0) {
547 return ARGP_ERR_UNKNOWN;
562 static void parse_bool(
char const *arg,
struct argp_state *state,
564 if (strlen(arg) == 1) {
568 }
else if (arg[0] ==
'1') {
573 if (strcmp(arg,
"true") == 0 || strcmp(arg,
"True") == 0 ||
574 strcmp(arg,
"TRUE") == 0) {
578 if (strcmp(arg,
"false") == 0 || strcmp(arg,
"False") == 0 ||
579 strcmp(arg,
"FALSE") == 0) {
599 static void parse_bool_named_list(
char const *arg,
struct argp_state *state,
600 char const *
const *
const names,
601 bool *
const values,
int size) {
603 if (strcmp(arg,
"all") == 0) {
604 memset(values,
true, size *
sizeof(
bool));
608 memset(values,
false, size *
sizeof(
bool));
611 char const *split_pos = arg;
612 while (*arg !=
'\0') {
614 split_pos = strchr(arg,
',');
615 char arg_name[16] = {0};
616 if (split_pos == NULL) {
617 strncpy(arg_name, arg,
sizeof(arg_name) - 1);
618 arg = arg + strlen(arg);
620 strncpy(arg_name, arg, split_pos - arg);
625 char *ptr = arg_name;
627 *ptr = toupper(*ptr);
633 if (strcmp(arg_name, names[i]) == 0) {
656 static void parse_uint32(
char const *arg,
struct argp_state *state,
657 uint32_t *
const value) {
659 parse_uint64(arg, state, &temp);
660 if ((temp >> 32) == 0) {
661 *value = (uint32_t)temp;
676 static void parse_uint64(
char const *arg,
struct argp_state *state,
677 uint64_t *
const value) {
679 *value = strtoull(arg, &suffix, 10);
682 if (suffix != NULL) {
685 *value = *value * 1000;
688 *value = *value * 1000;
691 *value = *value * 1000;
694 *value = *value * 1000;
714 static void print_version(FILE *stream,
struct argp_state *state) {
727 printf(
"\nRocketLogger Configuration:\n");
int rl_log(rl_log_level_t log_level, char const *const format,...)
int rl_log_init(char const *const log_file, rl_log_level_t verbosity)
@ RL_LOG_INFO
Information.
@ RL_LOG_IGNORE
Ignore log (only for verbosity configuration)
char const *const RL_CHANNEL_NAMES[RL_CHANNEL_COUNT]
RocketLogger channel names.
void rl_status_print_json(rl_status_t const *const status)
char const *const RL_CHANNEL_FORCE_NAMES[RL_CHANNEL_SWITCHED_COUNT]
RocketLogger force range channel names.
void rl_config_print_json(rl_config_t const *const config)
void rl_config_reset(rl_config_t *const config)
void rl_config_print(rl_config_t const *const config)
int rl_config_read_default(rl_config_t *const config)
int rl_config_write_default(rl_config_t const *const config)
int rl_config_validate(rl_config_t const *const config)
void rl_status_print(rl_status_t const *const status)
void rl_config_print_cmd(rl_config_t const *const config)
@ RL_FILE_FORMAT_RLD
CSV format.
#define RL_CHANNEL_SWITCHED_COUNT
Number of RocketLogger switched channels (allowing to force range)
#define RL_MEASUREMENT_LOG_FILE
RocketLogger measurement log file.
#define RL_CHANNEL_COUNT
Number of RocketLogger analog channels.
@ RL_AGGREGATION_MODE_AVERAGE
Aggregate using down sampling.
@ RL_AGGREGATION_MODE_DOWNSAMPLE
bool rl_is_sampling(void)
int rl_run(rl_config_t *const config)
int rl_get_status(rl_status_t *const status)
int main(int argc, char *argv[])
#define OPT_SAMPLES_COUNT
const char * argp_program_version
#define ARGP_ARGUMENTS_COUNT
#define OPT_RESET_DEFAULT
const char * argp_program_bug_address
void(* argp_program_version_hook)(FILE *, struct argp_state *)
rl_config_t * config
program arguments
bool config_set_default
whether to reset the stored default config
bool verbose
flag for silent output
bool cli
whether to save provided config as default
bool json
flag for CLI command formatted config output
bool silent
flag for JSON formatted output
char * args[ARGP_ARGUMENTS_COUNT]
bool config_reset
pointer to sampling configuration
bool channel_force_range[RL_CHANNEL_SWITCHED_COUNT]
Current channels to force to high range.
char file_name[PATH_MAX]
Data file name.
bool interactive_enable
Display measurement data interactively in CLI while sampling.
char const * file_comment
File comment.
uint64_t file_size
Maximum data file size.
rl_aggregation_mode_t aggregation_mode
Sample aggregation mode (for sampling rates below lowest native one)
bool background_enable
Put the measurement process in background after successful start.
bool ambient_enable
Enable logging of ambient sensor.
uint64_t sample_limit
Sample limit (0 for continuous)
bool web_enable
Enable web interface connection.
rl_file_format_t file_format
File format.
uint32_t sample_rate
Sampling rate.
bool channel_enable[RL_CHANNEL_COUNT]
Channels to sample.
uint32_t update_rate
Data update rate.
bool file_enable
Enable storing measurements to file.
bool digital_enable
Enable digital inputs.
bool calibration_ignore
Perform calibration measurement (ignore existing calibration)
char const *const COMPILE_DATE
Compilation date of the program.
char const *const PROJECT_VERSION
The RocketLogger software version string.
char const *const GIT_DESCRIPTION
Git code revision description of the code base.
char const *const GIT_DATE
Date of the of last git commit.