RocketLogger  1.0
rl_util.c
Go to the documentation of this file.
1 
5 #include "rl_version.h"
6 
7 #include "rl_util.h"
8 
13 void rl_print_config(struct rl_conf* conf) {
14 
15  char file_format_names[3][10] = {"no file", "csv", "binary"};
16 
17  if(conf->sample_rate >= KSPS) { printf(" Sampling rate: %dkSps\n", conf->sample_rate/KSPS);
18  } else { printf(" Sampling rate: %dSps\n", conf->sample_rate);}
19  printf(" Update rate: %dHz\n", conf->update_rate);
20  if(conf->enable_web_server == 1) printf(" Webserver: enabled\n");
21  else printf(" Webserver: disabled\n");
22  if(conf->digital_inputs == 1) printf(" Digital inputs: enabled\n");
23  else printf(" Digital inputs: disabled\n");
24  printf(" File format: %s\n", file_format_names[conf->file_format]);
25  if(conf->file_format != NO_FILE) printf(" File name: %s\n", conf->file_name);
26  if(conf->max_file_size != 0) { printf(" Max file size: %lluMB\n", conf->max_file_size/1000000);}
27  if(conf->calibration == CAL_IGNORE){printf(" Calibration: ignored\n");}
28  printf(" Channels: ");
29  int i;
30  for(i=0; i<NUM_CHANNELS; i++) {
31  if (conf->channels[i] == CHANNEL_ENABLED) {
32  printf("%d,", i);
33  }
34  }
35  printf("\n");
37  printf(" Forced channels: ");
38  for(i=0; i<NUM_I_CHANNELS; i++) {
39  if (conf->force_high_channels[i] == CHANNEL_ENABLED) {
40  printf("%d,", i+1);
41  }
42  }
43  printf("\n");
44  }
45  if (conf->sample_limit == 0) { printf(" Sample limit: no limit\n");
46  } else { printf(" Sample limit: %d\n", conf->sample_limit);}
47 }
48 
54 
55  if(status->state == RL_OFF) {
56  printf("\nRocketLogger IDLE\n\n");
57  } else {
58  printf("\nRocketLogger Status: RUNNING\n");
59  rl_print_config(&(status->conf));
60  printf(" Samples taken: %llu\n", status->samples_taken);
61  time_t time = (time_t) status->calibration_time;
62  if(time > 0) {
63  printf(" Calibration time: %s\n", ctime(&time));
64  } else {
65  printf(" Calibration time: No calibration file found\n");
66  }
67  printf("\n");
68  }
69 }
70 
74 void rl_print_version(void) {
75  printf("RocketLogger Software Stack version " RL_VERSION "\n");
76 }
77 
78 
83 char* rl_get_version(void) {
84  return RL_VERSION;
85 }
86 
87 // argument parsing
94  if (strcmp(mode, "sample") == 0) {
95  return LIMIT;
96  } else if(strcmp(mode, "cont") == 0) {
97  return CONTINUOUS;
98  } else if(strcmp(mode, "meter") == 0) {
99  return METER;
100  } else if(strcmp(mode, "status") == 0) {
101  return STATUS;
102  } else if(strcmp(mode, "stop") == 0) {
103  return STOPPED;
104  } else if(strcmp(mode, "set") == 0) {
105  return SET_DEFAULT;
106  } else if(strcmp(mode, "conf") == 0) {
107  return PRINT_DEFAULT;
108  } else if(strcmp(mode, "version") == 0 || strcmp(mode, "--version") == 0) {
109  return PRINT_VERSION;
110  } else if(strcmp(mode, "help") == 0 || strcmp(mode, "h") == 0 || strcmp(mode, "-h") == 0 || strcmp(mode, "--help") == 0) {
111  return HELP;
112  }
113 
114  return NO_MODE;
115 }
116 
123  if (strcmp(option, "f") == 0) {
124  return FILE_NAME;
125  } else if(strcmp(option, "r") == 0) {
126  return SAMPLE_RATE;
127  } else if(strcmp(option, "u") == 0) {
128  return UPDATE_RATE;
129  } else if(strcmp(option, "ch") == 0) {
130  return CHANNEL;
131  } else if(strcmp(option, "fhr") == 0) {
132  return FHR;
133  } else if(strcmp(option, "w") == 0) {
134  return WEB;
135  } else if(strcmp(option, "d") == 0) {
136  return DIGITAL_INPUTS;
137  } else if(strcmp(option, "s") == 0) {
138  return DEF_CONF;
139  } else if(strcmp(option, "c") == 0) {
140  return CALIBRATION;
141  } else if(strcmp(option, "format") == 0) {
142  return FILE_FORMAT;
143  } else if(strcmp(option, "size") == 0) {
144  return FILE_SIZE;
145  }
146 
147  return NO_OPTION;
148 }
149 
156 int parse_channels(int channels[], char* value) {
157 
158  // check first channel number
159  if(isdigit(value[0]) && atoi(value) >= 0 && atoi(value) <= 9) {
160 
161  // reset default channel selection
162  memset(channels, 0, sizeof(int) * NUM_CHANNELS);
163  channels[atoi(value)] = 1;
164 
165  } else if(strcmp(value, "all") == 0) {
166  // all channels
167  int i;
168  for(i=0; i<NUM_CHANNELS; i++) {
169  channels[i] = CHANNEL_ENABLED;
170  }
171  }else {
172  rl_log(ERROR, "wrong channel number");
173  return FAILURE;
174  }
175 
176  // loop
177  int j;
178  for (j=1; j < 2*(NUM_CHANNELS-1) && value[j] == ','; j=j+2){
179 
180  //check channel number
181  char* c = &value[j+1];
182  if (isdigit(c[0]) && atoi(c) >= 0 && atoi(c) < NUM_CHANNELS) {
183  channels[atoi(c)] = 1;
184  } else {
185  rl_log(ERROR, "wrong channel number");
186  return FAILURE;
187  }
188  }
189 
190  return SUCCESS;
191 }
192 
201 int parse_args(int argc, char* argv[], struct rl_conf* conf, int* set_as_default) {
202 
203  int i; // argument count variable
204  int no_file = 0;
205  *set_as_default = 0;
206 
207  // need at least 2 arguments
208  if (argc < 2) {
209  rl_log(ERROR, "no mode");
210  return FAILURE;
211  }
212 
213  // MODE
214  conf->mode = get_mode(argv[1]);
215  if(conf->mode == NO_MODE) {
216  rl_log(ERROR, "wrong mode");
217  return FAILURE;
218  }
219 
220  if(conf->mode == LIMIT) {
221  // parse sample limit
222  if (argc > 2 && isdigit(argv[2][0]) && atoi(argv[2]) > 0) {
223  conf->sample_limit = atoi(argv[2]);
224  i = 3;
225  } else {
226  rl_log(ERROR, "no possible sample limit");
227  return FAILURE;
228  }
229  } else {
230  i = 2;
231  }
232 
233  // disable webserver as default for non-continuous mode
234  if(conf->mode == STATUS || conf->mode == LIMIT) {
235  conf->enable_web_server = 0;
236  }
237 
238  // stop parsing for some modes
239  if (conf->mode == STOPPED || conf->mode == PRINT_DEFAULT || conf->mode == HELP) {
240  return SUCCESS;
241  }
242 
243  // reset default configuration
244  if (conf->mode == SET_DEFAULT && isdigit(argv[i][0]) && atoi(argv[i]) == 0) {
245  reset_config(conf);
246  conf->mode = SET_DEFAULT;
247  return SUCCESS;
248  }
249 
250 
251  // OPTIONS
252  for (; i<argc; i++) {
253  if (argv[i][0] == '-') {
254  switch(get_option(&argv[i][1])) {
255 
256  case FILE_NAME:
257  if (argc > ++i) {
258  if (isdigit(argv[i][0]) && atoi(argv[i]) == 0) { // no file write
259  no_file = 1;
260  conf->file_format = NO_FILE;
261  } else {
262  strcpy(conf->file_name, argv[i]);
263  }
264  } else {
265  rl_log(ERROR, "no file nam");
266  return FAILURE;
267  }
268  break;
269 
270  case SAMPLE_RATE:
271  if (argc > ++i && isdigit(argv[i][0])) {
272  if(argv[i][strlen(argv[i])-1] == 'k') {
273  conf->sample_rate = atoi(argv[i]) * KSPS;
274  } else {
275  conf->sample_rate = atoi(argv[i]);
276  }
277  if(check_sample_rate(conf->sample_rate) == FAILURE) { // check if rate allowed
278  rl_log(ERROR, "wrong sampling rate");
279  return FAILURE;
280  }
281  } else {
282  rl_log(ERROR, "no sampling rate");
283  return FAILURE;
284  }
285  break;
286 
287  case UPDATE_RATE:
288  if (argc > ++i && isdigit(argv[i][0])) {
289  conf->update_rate = atoi(argv[i]);
290  if(check_update_rate(conf->update_rate) == FAILURE) { // check if rate allowed
291  rl_log(ERROR, "wrong update rate");
292  return FAILURE;
293  }
294  } else {
295  rl_log(ERROR, "no update rate");
296  return FAILURE;
297  }
298  break;
299 
300  case CHANNEL:
301  if (argc > ++i) {
302  if(parse_channels(conf->channels, argv[i]) == FAILURE) {
303  return FAILURE;
304  }
305  } else {
306  rl_log(ERROR, "no channel number");
307  return FAILURE;
308  }
309  break;
310 
311  case FHR:
312  if (argc > ++i) {
313 
314  // check first number
315  char* c = argv[i];
316  if(isdigit(c[0]) && atoi(c) < 3 && atoi(c) >= 0) {
317 
318  // reset default forced channel selection
319  memset(conf->force_high_channels, 0, sizeof(conf->force_high_channels));
320  if(atoi(c) > 0) {
321  conf->force_high_channels[atoi(c) - 1] = CHANNEL_ENABLED;
322  }
323  } else {
324  rl_log(ERROR, "wrong force-channel number");
325  return FAILURE;
326  }
327  // check second number
328  if (argv[i][1] == ',') {
329 
330  char* c = &argv[i][2];
331  if (atoi(c) < 3 && atoi(c) > 0) {
332  conf->force_high_channels[atoi(c) - 1] = CHANNEL_ENABLED;
333  } else {
334  rl_log(ERROR, "wrong force-channel number");
335  return FAILURE;
336  }
337  }
338  } else {
339  rl_log(ERROR, "no force channel number");
340  return FAILURE;
341  }
342  break;
343 
344  case WEB:
345  if(argc > i+1 && isdigit(argv[i+1][0]) && atoi(argv[i+1]) == 0) {
346  i++;
347  conf->enable_web_server = 0;
348  } else {
349  conf->enable_web_server = 1;
350  }
351  break;
352 
353  case DIGITAL_INPUTS:
354  if(argc > i+1 && isdigit(argv[i+1][0]) && atoi(argv[i+1]) == 0) {
355  i++;
357  } else {
359  }
360  break;
361 
362  case DEF_CONF:
363  *set_as_default = 1;
364  break;
365 
366  case CALIBRATION:
367  if(argc > i+1 && isdigit(argv[i+1][0]) && atoi(argv[i+1]) == 0) {
368  i++;
369  conf->calibration = CAL_IGNORE;
370  } else {
371  conf->calibration = CAL_USE;
372  }
373  break;
374 
375  case FILE_FORMAT:
376  if(argc > ++i) {
377  if(no_file == 0) { // ignore format, when no file is written
378  if(strcmp(argv[i],"csv") == 0) {
379  conf->file_format = CSV;
380  } else if(strcmp(argv[i],"bin") == 0) {
381  conf->file_format = BIN;
382  } else {
383  rl_log(ERROR, "wrong file format");
384  return FAILURE;
385  }
386  } else {
387  rl_log(INFO, "file format ignored");
388  }
389  } else {
390  rl_log(ERROR, "no file format");
391  return FAILURE;
392  }
393  break;
394 
395  case FILE_SIZE:
396  if (argc > ++i && isdigit(argv[i][0])) {
397  conf->max_file_size = atoll(argv[i]);
398  switch(argv[i][strlen(argv[i])-1]) {
399  case 'k':
400  case 'K':
401  conf->max_file_size *= 1000;
402  break;
403  case 'm':
404  case 'M':
405  conf->max_file_size *= 1000000;
406  break;
407  case 'g':
408  case 'G':
409  conf->max_file_size *= 1000000000;
410  break;
411  default:
412  break;
413  }
414  // check file size
415  if(conf->max_file_size != 0 && conf->max_file_size < 5000000) {
416  rl_log(ERROR, "too small file size (min: 5m)");
417  return FAILURE;
418  }
419  } else {
420  rl_log(ERROR, "no file size");
421  return FAILURE;
422  }
423  break;
424 
425  case NO_OPTION:
426  rl_log(ERROR, "wrong option");
427  return FAILURE;
428 
429  default:
430  rl_log(ERROR, "wrong option");
431  return FAILURE;
432  }
433  } else {
434  rl_log(ERROR, "use -[option] [value]");
435  return FAILURE;
436  }
437  }
438 
439  return SUCCESS;
440 }
441 
442 
443 // help
447 void print_usage(void) {
448  printf("\n");
449  printf("Usage:\n");
450  printf(" rocketlogger mode -[option value]\n");
451  printf("\n");
452  printf(" Modes:\n");
453  printf(" sample number Acquires number of samples.\n");
454  printf(" cont Continuously acquires samples.\n");
455  printf(" meter Starts RocketLogger Meter.\n");
456  printf(" status Get status of RocketLogger.\n");
457  printf(" stop Stops RocketLogger.\n");
458  printf(" set Set default configuration of RocketLogger (use normal options).\n");
459  printf(" Use 'set 0' to reset the default configuration.\n");
460  printf(" conf Print default configuration of RocketLogger.\n");
461  printf("\n");
462  printf(" Options:\n");
463  printf(" -r rate Acquisition rate selection.\n");
464  printf(" Possible rates: 1, 10, 100, 1k, 2k, 4k, 8k, 16k, 32k, 64k\n");
465  printf(" -u update_rate Data update rate selection.\n");
466  printf(" Possible update rates: 1, 2, 5, 10 (in Hz)\n");
467  printf(" -ch ch1,ch2,... Channel selection.\n");
468  printf(" Possible channels ('-ch all' to enable all):\n");
469  printf(" 0: I1H\t\t4: I2H\n");
470  printf(" 1: I1L\t\t5: I2L\n");
471  printf(" 2: V1 \t\t6: V3\n");
472  printf(" 3: V2 \t\t7: V4\n");
473  printf(" -fhr ch1,ch2 Force high-range.\n");
474  printf(" 0: no channel, 1: I1, 2: I2\n");
475  printf(" -c Use calibration, if existing.\n");
476  printf(" '-c 0' to ignore calibration.\n");
477  printf(" -f file Stores data to specified file.\n");
478  printf(" '-f 0' will disable file storing.\n");
479  printf(" -d Log digital inputs.\n");
480  printf(" Use '-d 0' to disable digital input logging.\n");
481  printf(" -format format Select file format: csv, bin.\n");
482  printf(" -size file_size Select max file size (k, m, g can be used).\n");
483  printf(" -w Enable webserver plotting.\n");
484  printf(" Use '-w 0' to disable webserver plotting.\n");
485  printf(" -s Set configuration as default.\n");
486  printf("\n");
487  printf(" Help/Info:\n");
488  printf(" help, --help Display this help message.\n");
489  printf(" version, --version Display the RocketLogger software version.\n");
490  printf("\n");
491 }
492 
493 
494 // configuration handling
499 void print_config(struct rl_conf* conf) {
500  printf("\nRocketLogger Configuration:\n");
501  rl_print_config(conf);
502  printf("\n");
503 
504 }
505 
510 void reset_config(struct rl_conf* conf) {
511  conf->mode = CONTINUOUS;
512  conf->sample_rate = 1000;
513  conf->update_rate = 1;
514  conf->sample_limit = 0;
516  conf->enable_web_server = 1;
517  conf->calibration = CAL_USE;
518  conf->file_format = BIN;
519  conf->max_file_size = 0;
520 
521  strcpy(conf->file_name, "/var/www/data/data.rld");
522 
523  int i;
524  for(i=0; i<NUM_CHANNELS; i++) {
525  conf->channels[i] = CHANNEL_ENABLED;
526  }
527  memset(conf->force_high_channels, 0, sizeof(conf->force_high_channels));
528 
529 }
530 
536 int read_default_config(struct rl_conf* conf) {
537 
538  // check if config file existing
539  if(open(DEFAULT_CONFIG, O_RDWR) <= 0) {
540  reset_config(conf);
541  return UNDEFINED;
542  }
543 
544  // open config file
545  FILE* file = fopen(DEFAULT_CONFIG, "r");
546  if(file == NULL) {
547  rl_log(ERROR, "failed to open configuration file");
548  return FAILURE;
549  }
550  // read values
551  fread(conf, sizeof(struct rl_conf), 1, file);
552 
553  // reset mode
554  conf->mode = CONTINUOUS;
555 
556  //close file
557  fclose(file);
558  return SUCCESS;
559 }
560 
566 int write_default_config(struct rl_conf* conf) {
567 
568  // open config file
569  FILE* file = fopen(DEFAULT_CONFIG, "w");
570  if(file == NULL) {
571  rl_log(ERROR, "failed to create configuration file");
572  return FAILURE;
573  }
574  // write values
575  fwrite(conf, sizeof(struct rl_conf), 1, file);
576 
577  //close file
578  fclose(file);
579  return SUCCESS;
580 }
int force_high_channels[NUM_I_CHANNELS]
Current channels to force to high range.
Definition: types.h:214
void rl_print_status(struct rl_status *status)
Definition: rl_util.c:53
Limited sampling mode (limited by number of samples to take)
Definition: types.h:134
Print default configuration.
Definition: types.h:140
Get current status of RocketLogger.
Definition: types.h:137
rl_mode mode
Sampling mode.
Definition: types.h:204
Stop continuous sampling.
Definition: types.h:138
Continuous sampling mode (in background)
Definition: types.h:135
void rl_print_version(void)
Definition: rl_util.c:74
enum option rl_option
Sample digital inputs.
Definition: rl_util.h:33
#define RL_VERSION
The RocketLogger software version string.
Definition: rl_version.h:9
#define UNDEFINED
Definition: types.h:51
#define FAILURE
Definition: types.h:53
#define SUCCESS
Definition: types.h:50
int check_sample_rate(int sample_rate)
Definition: lib_util.c:22
rl_mode get_mode(char *mode)
Definition: rl_util.c:93
CSV format.
Definition: types.h:151
void rl_print_config(struct rl_conf *conf)
Definition: rl_util.c:13
struct rl_status status
Current status of RocketLogger.
Definition: rl_server.c:42
Set configuration as default.
Definition: rl_util.h:34
int write_default_config(struct rl_conf *conf)
Definition: rl_util.c:566
mode
Definition: types.h:133
enum mode rl_mode
En-/disable data averaging for web server.
Definition: rl_util.h:32
void rl_log(rl_log_type type, const char *format,...)
Definition: log.c:12
void reset_config(struct rl_conf *conf)
Definition: rl_util.c:510
int parse_args(int argc, char *argv[], struct rl_conf *conf, int *set_as_default)
Definition: rl_util.c:201
int digital_inputs
En-/disable digital inputs.
Definition: types.h:216
int enable_web_server
En-/disable plots on web interface.
Definition: types.h:218
File format.
Definition: rl_util.h:36
rl_use_cal calibration
Use/ignore existing calibration.
Definition: types.h:220
#define DEFAULT_CONFIG
Default configuration file.
Definition: rl_util.h:21
Binary format.
Definition: types.h:152
Show help.
Definition: types.h:142
rl_state state
State.
Definition: types.h:234
uint64_t samples_taken
Number of samples taken.
Definition: types.h:238
int read_default_config(struct rl_conf *conf)
Definition: rl_util.c:536
#define NUM_I_CHANNELS
Maximum number of RocketLogger current channels.
Definition: types.h:80
int check_update_rate(int update_rate)
Definition: lib_util.c:37
int sample_limit
Sample limit (0 for continuous)
Definition: types.h:210
Definition: types.h:202
#define NUM_CHANNELS
Maximum number of RocketLogger channels.
Definition: types.h:78
#define CHANNEL_ENABLED
Channel sampling enabled.
Definition: types.h:178
#define KSPS
KSPS <-> SPS conversion factor.
Definition: types.h:93
char file_name[MAX_PATH_LENGTH]
Data file name.
Definition: types.h:226
void print_usage(void)
Definition: rl_util.c:447
Maximum data file size.
Definition: rl_util.h:37
Set default configuration.
Definition: types.h:139
int channels[NUM_CHANNELS]
Channels to sample.
Definition: types.h:212
uint64_t time
Time stamp of calibration run.
Definition: types.h:252
Print the RocketLogger Software Stack version.
Definition: types.h:141
#define DIGITAL_INPUTS_DISABLED
Digital input sampling disabled.
Definition: types.h:195
uint64_t calibration_time
Time stamp of last calibration run.
Definition: types.h:244
rl_file_format file_format
File format.
Definition: types.h:222
int update_rate
Data update rate.
Definition: types.h:208
rl_option get_option(char *option)
Definition: rl_util.c:122
No option.
Definition: rl_util.h:38
Name of data file to write.
Definition: rl_util.h:27
Error.
Definition: types.h:167
Data file update rate.
Definition: rl_util.h:29
struct rl_conf conf
Current configuration.
Definition: types.h:242
int sample_rate
Sampling rate.
Definition: types.h:206
No file.
Definition: types.h:150
int parse_channels(int channels[], char *value)
Definition: rl_util.c:156
Sampling rate.
Definition: rl_util.h:28
Channels to force to high range.
Definition: rl_util.h:31
Use calibration (if existing)
Definition: types.h:160
uint64_t max_file_size
Maximum data file size.
Definition: types.h:224
option
Definition: rl_util.h:26
void print_config(struct rl_conf *conf)
Definition: rl_util.c:499
char * rl_get_version(void)
Definition: rl_util.c:83
Ignore calibration.
Definition: types.h:159
Information.
Definition: types.h:169
Use/ignore existing calibration values.
Definition: rl_util.h:35
Meter mode (display current values in terminal)
Definition: types.h:136
Channels to sample.
Definition: rl_util.h:30
#define DIGITAL_INPUTS_ENABLED
Digital input sampling ensabled.
Definition: types.h:197
No mode.
Definition: types.h:143
Idle.
Definition: types.h:117