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
83 "RocketLogger CLI -- manage your RocketLogger measurements.\n"
84 "Control or configure measurements using the actions specified by ACTION. "
85 "Supported values for ACTION are:\n"
87 " Measurement control:\n"
88 " start\tStart a new measurement with provided configuration\n"
89 " stop\tStop measurement running in the background\n"
91 " Measurement configuration and status management:\n"
92 " config\tDisplay configuration, not starting a new or affecting a "
93 "running measurement\n"
94 " status\tDisplay the current sampling status\n";
99static char args_doc[] =
"ACTION";
104static struct argp_option options[] = {
105 {0, 0, 0, OPTION_DOC,
"Basic measurement configuration options:", 1},
107 "Number of samples to record before stopping measurement (k, M, G, T "
108 "scaling suffixes can be used).",
110 {
"channel",
'c',
"SELECTION", 0,
"Channel selection to sample. A comma "
111 "separated list of the channel names (V1, "
112 "V2, V3, V4, I1L, I1H, I2L, and/or I2H) "
113 "or 'all' to enable all channels.",
115 {
"rate",
'r',
"RATE", 0,
"Sampling rate in Hz. Supported values are: 1, "
116 "10, 100, 1k, 2k, 4k, 8k, 16k, 32k, 64k.",
118 {
"update",
'u',
"RATE", 0,
119 "Measurement data update rate in Hz. Supported values: 1, 2, 5, 10.", 0},
120 {
"output",
'o',
"FILE", 0,
121 "Store data to specified file. Use zero to disable file storage.", 0},
122 {
"interactive",
'i', 0, 0,
123 "Display measurement data in the command line interface.", 0},
124 {
"background",
'b', 0, 0,
125 "Start measurement in the background and exit after start.", 0},
127 {0, 0, 0, OPTION_DOC,
128 "Measurement configuration options for storing measurement files:", 3},
129 {
"format",
'f',
"FORMAT", 0,
"Select file format: 'csv', 'rld'.", 0},
131 "Select max file size (k, M, G, T scaling suffixes can be used).", 0},
132 {
"comment",
'C',
"COMMENT", 0,
"Comment stored in file header. Comment is "
133 "ignored if file saving is disabled.",
136 {0, 0, 0, OPTION_DOC,
"Setting and resetting the stored default:", 4},
137 {
"default",
OPT_SET_DEFAULT, 0, 0,
"Set current configuration as default. "
138 "Supported for all measurement "
142 "Reset default configuration to factory defaults and ignores any other "
143 "provided configuration without notice. Only allowed in combination with "
144 "the 'config' action.",
147 {0, 0, 0, OPTION_DOC,
"Optional arguments for extended sampling features:",
149 {
"digital",
'd',
"BOOL", OPTION_ARG_OPTIONAL,
150 "Enable logging of digital inputs. Enabled by default.", 0},
151 {
"ambient",
'a',
"BOOL", OPTION_ARG_OPTIONAL,
152 "Enable logging of ambient sensors, if available. Disabled by default.",
154 {
"aggregate",
'g',
"MODE", 0,
"Data aggregation mode for low sample rates. "
155 "Existing modes: 'average', 'downsample'.",
157 {
"high-range",
'h',
"SELECTION", 0,
158 "Force high range measurements on selected channels. A comma separated "
159 "list of the channel names (I1H and/or I2H) or 'all' to force high range "
160 "measurements all channels. Inactive per default.",
163 "values. Use this option for device "
164 "calibration measurements only.",
166 {
"web",
'w',
"BOOL", OPTION_ARG_OPTIONAL,
167 "Enable data stream interface (required for web interface plotting). "
168 "Enabled per default.",
170 {
"stream",
OPT_STREAM, 0, OPTION_ALIAS, 0, 0},
172 {0, 0, 0, OPTION_DOC,
"Optional arguments for status and config actions:",
175 "Print configuration or status as JSON formatted string.", 0},
176 {
"cli",
OPT_CLI, 0, 0,
"Print configuration as full CLI command.", 0},
178 {0, 0, 0, OPTION_DOC,
"Generic program switches:", 7},
179 {
"verbose",
'v', 0, 0,
"Produce verbose output", 0},
180 {
"quiet",
'q', 0, 0,
"Do not produce any output", 0},
181 {
"silent",
's', 0, OPTION_ALIAS, 0, 0},
201static error_t parse_opt(
int key,
char *arg,
struct argp_state *state);
202static void parse_bool(
char const *arg,
struct argp_state *state,
204static void parse_bool_named_list(
char const *arg,
struct argp_state *state,
205 char const *
const *
const names,
206 bool *
const values,
int size);
207static void parse_uint32(
char const *arg,
struct argp_state *state,
208 uint32_t *
const value);
209static void parse_uint64(
char const *arg,
struct argp_state *state,
210 uint64_t *
const value);
211static void print_config(
rl_config_t const *
const config);
212static void print_version(FILE *stream,
struct argp_state *state);
222static struct argp argp = {
225 .args_doc = args_doc,
241int main(
int argc,
char *argv[]) {
247 error(EXIT_FAILURE, errno,
"failed reading default configuration file");
254 .config_reset =
false,
255 .config_set_default =
false,
263 int argp_status = argp_parse(&argp, argc, argv, 0, 0, &
arguments);
264 if (argp_status != 0) {
265 error(0, argp_status,
"argument parsing failed");
281 errno, strerror(errno));
295 (strcmp(action,
"start") == 0 || strcmp(action,
"stop") == 0 ||
296 strcmp(action,
"config") == 0 || strcmp(action,
"status") == 0);
304 "string at the same time.");
310 if (valid_config < 0) {
317 if (strcmp(action,
"config") != 0) {
319 "the --reset option is only allowed for config action.");
329 printf(
"The following configuration was saved as new default:\n");
335 if (strcmp(action,
"start") == 0) {
339 "Stop with `rocketlogger stop` first.\n");
349 if (strcmp(action,
"stop") == 0) {
357 printf(
"Wait for measurement to stop...\n");
361 if (strcmp(action,
"config") == 0) {
370 if (strcmp(action,
"status") == 0) {
395static error_t parse_opt(
int key,
char *arg,
struct argp_state *state) {
438 if (strlen(arg) == 1 && arg[0] ==
'0') {
450 if (strcmp(arg,
"csv") == 0 || strcmp(arg,
"CSV") == 0) {
452 }
else if (strcmp(arg,
"rld") == 0 || strcmp(arg,
"RLD") == 0) {
484 if (strcmp(arg,
"downsample") == 0) {
486 }
else if (strcmp(arg,
"average") == 0) {
553 return ARGP_ERR_UNKNOWN;
568static void parse_bool(
char const *arg,
struct argp_state *state,
570 if (strlen(arg) == 1) {
574 }
else if (arg[0] ==
'1') {
579 if (strcmp(arg,
"true") == 0 || strcmp(arg,
"True") == 0 ||
580 strcmp(arg,
"TRUE") == 0) {
584 if (strcmp(arg,
"false") == 0 || strcmp(arg,
"False") == 0 ||
585 strcmp(arg,
"FALSE") == 0) {
605static void parse_bool_named_list(
char const *arg,
struct argp_state *state,
606 char const *
const *
const names,
607 bool *
const values,
int size) {
609 if (strcmp(arg,
"all") == 0) {
610 memset(values,
true, size *
sizeof(
bool));
614 memset(values,
false, size *
sizeof(
bool));
617 char const *split_pos = arg;
618 while (*arg !=
'\0') {
620 split_pos = strchr(arg,
',');
621 char arg_name[16] = {0};
622 if (split_pos == NULL) {
623 strncpy(arg_name, arg,
sizeof(arg_name) - 1);
624 arg = arg + strlen(arg);
626 strncpy(arg_name, arg, split_pos - arg);
631 char *ptr = arg_name;
633 *ptr = toupper(*ptr);
639 if (strcmp(arg_name, names[i]) == 0) {
662static void parse_uint32(
char const *arg,
struct argp_state *state,
663 uint32_t *
const value) {
665 parse_uint64(arg, state, &temp);
666 if ((temp >> 32) == 0) {
667 *value = (uint32_t)temp;
682static void parse_uint64(
char const *arg,
struct argp_state *state,
683 uint64_t *
const value) {
685 *value = strtoull(arg, &suffix, 10);
688 if (suffix != NULL) {
691 *value = *value * 1000;
694 *value = *value * 1000;
697 *value = *value * 1000;
700 *value = *value * 1000;
720static void print_version(FILE *stream,
struct argp_state *state) {
733 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)
#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.