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 = {
218 .options = options, .parser = parse_opt, .args_doc = args_doc, .doc = doc,
233 int main(
int argc,
char *argv[]) {
239 error(EXIT_FAILURE, errno,
"failed reading default configuration file");
246 .config_reset =
false,
247 .config_set_default =
false,
255 int argp_status = argp_parse(&argp, argc, argv, 0, 0, &
arguments);
256 if (argp_status != 0) {
257 error(0, argp_status,
"argument parsing failed");
273 errno, strerror(errno));
287 (strcmp(action,
"start") == 0 || strcmp(action,
"stop") == 0 ||
288 strcmp(action,
"config") == 0 || strcmp(action,
"status") == 0);
296 "string at the same time.");
302 if (valid_config < 0) {
309 if (strcmp(action,
"config") != 0) {
311 "the --reset option is only allowed for config action.");
321 printf(
"The following configuration was saved as new default:\n");
327 if (strcmp(action,
"start") == 0) {
331 "Stop with `rocketlogger stop` first.\n");
341 if (strcmp(action,
"stop") == 0) {
349 printf(
"Wait for measurement to stop...\n");
353 if (strcmp(action,
"config") == 0) {
362 if (strcmp(action,
"status") == 0) {
387 static error_t parse_opt(
int key,
char *arg,
struct argp_state *state) {
430 if (strlen(arg) == 1 && arg[0] ==
'0') {
442 if (strcmp(arg,
"csv") == 0 || strcmp(arg,
"CSV") == 0) {
444 }
else if (strcmp(arg,
"rld") == 0 || strcmp(arg,
"RLD") == 0) {
476 if (strcmp(arg,
"downsample") == 0) {
478 }
else if (strcmp(arg,
"average") == 0) {
544 return ARGP_ERR_UNKNOWN;
559 static void parse_bool(
char const *arg,
struct argp_state *state,
561 if (strlen(arg) == 1) {
565 }
else if (arg[0] ==
'1') {
570 if (strcmp(arg,
"true") == 0 || strcmp(arg,
"True") == 0 ||
571 strcmp(arg,
"TRUE") == 0) {
575 if (strcmp(arg,
"false") == 0 || strcmp(arg,
"False") == 0 ||
576 strcmp(arg,
"FALSE") == 0) {
596 static void parse_bool_named_list(
char const *arg,
struct argp_state *state,
597 char const *
const *
const names,
598 bool *
const values,
int size) {
600 if (strcmp(arg,
"all") == 0) {
601 memset(values,
true, size *
sizeof(
bool));
605 memset(values,
false, size *
sizeof(
bool));
608 char const *split_pos = arg;
609 while (*arg !=
'\0') {
611 split_pos = strchr(arg,
',');
612 char arg_name[16] = {0};
613 if (split_pos == NULL) {
614 strncpy(arg_name, arg,
sizeof(arg_name) - 1);
615 arg = arg + strlen(arg);
617 strncpy(arg_name, arg, split_pos - arg);
622 char *ptr = arg_name;
624 *ptr = toupper(*ptr);
630 if (strcmp(arg_name, names[i]) == 0) {
653 static void parse_uint32(
char const *arg,
struct argp_state *state,
654 uint32_t *
const value) {
656 parse_uint64(arg, state, &temp);
657 if ((temp >> 32) == 0) {
658 *value = (uint32_t)temp;
673 static void parse_uint64(
char const *arg,
struct argp_state *state,
674 uint64_t *
const value) {
676 *value = strtoull(arg, &suffix, 10);
679 if (suffix != NULL) {
682 *value = *value * 1000;
685 *value = *value * 1000;
688 *value = *value * 1000;
691 *value = *value * 1000;
711 static void print_version(FILE *stream,
struct argp_state *state) {
724 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.