From: Timo Kokkonen Date: Wed, 9 Oct 2013 19:49:27 +0000 (+0300) Subject: data.c: Add data parsing and output processing X-Git-Url: http://git.itanic.dy.fi/?p=log-plotter;a=commitdiff_plain;h=12ee6e0cd4ead444856b50c2823c5c1f07178819 data.c: Add data parsing and output processing Parse all input data into C structure. This allows proper processing of the data. Print out the data into the log file in proper format after the processing. Signed-off-by: Timo Kokkonen --- diff --git a/data.c b/data.c index ef11dfa..0e334d8 100644 --- a/data.c +++ b/data.c @@ -2,12 +2,154 @@ #include #include #include +#include #include #include #include +#include +#include +#include "data.h" #include "debug.h" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +static int separate_entries(char *buf, char *entries[], int max_entries) +{ + int i = 0; + + entries[i] = buf; + i++; + + while (*buf && i< max_entries) { + if (*buf != ';') { + buf++; + continue; + } + + *buf = 0; + buf++; + entries[i] = buf; + i++; + } + + return i; +} + +static void init_data(struct charger_data *data) +{ + int i; + + bzero(data, sizeof(*data)); + for (i = 0; i < MAX_CELLS; i++) + data->cell_voltage[i] = NAN; + + data->timestamp = NAN; + data->input_voltage = NAN; + data->charging_voltage = NAN; + data->charging_current = NAN; + data->total_charge = NAN; + data->int_temp = NAN; + data->ext_temp = NAN; +} + +/* + * Convert one log line into charger_data structure. Supports at least + * iCharger 6 and 10 cell chargers. Others are not tested. + * + * Returns negative on incorrect data, zero on success + */ +static int parse_logline(const char *buf, struct charger_data *data) +{ + int i, j, entry_count; + int ret = -1; + int max_cells; + int d; + char *str = strdup(buf); + char *entries[64]; + + entry_count = separate_entries(str, entries, ARRAY_SIZE(entries)); + + pr_debug("Entry count: %d\n", entry_count); + + init_data(data); + + if (entries[0][0] != '$') { + pr_debug("Discarding malformed data entry\n"); + goto out; + } + + for (i = 0; i < entry_count; i++) + pr_debug("Entry %d: data: %s\n", i, entries[i]); + + i = 0; + entries[i]++; /* discard the dollar sign */ + data->channel = atoi(entries[i++]); + + data->state = atoi(entries[i++]); + + /* Timestamp is optional */ + if (strlen(entries[1]) > 0) + data->timestamp = atof(entries[i++]); + + data->input_voltage = atof(entries[i++]) / 1000.0; + data->charging_voltage = atof(entries[i++]) / 1000.0; + data->charging_current = atof(entries[i++]) / 100.0; + +#define ASSIGN_OR_NAN(data, val) \ + do { \ + if ((val) == 0) \ + (data) = NAN; \ + else \ + (data) = val; \ + } while(0); + + max_cells = entry_count - 10; + pr_debug("max_cells: %d\n", max_cells); + + for (j = 0; j < max_cells; j++, i++) { + d = atoi(entries[i]); + ASSIGN_OR_NAN(data->cell_voltage[j], d / 1000.0); + } + + d = atoi(entries[i++]); + ASSIGN_OR_NAN(data->int_temp, d / 10.0); + + d = atoi(entries[i++]); + ASSIGN_OR_NAN(data->ext_temp, d / 10.0); + + data->total_charge = atof(entries[i++]); + + ret = 0; +out: + free(str); + return ret; +} + +static void dump_data(struct charger_data *data) +{ + int i; + + pr_debug("channel %d\n", data->channel); + pr_debug("state %d\n", data->state); + pr_debug("timestamp %.1f\n", data->timestamp); + pr_debug("input_voltage %.3f\n", data->input_voltage); + pr_debug("charging_voltage %.3f\n", data->charging_voltage); + pr_debug("charging_current %.3f\n", data->charging_current); + + for (i = 0; i < MAX_CELLS; i++) { + if (isnan(data->cell_voltage[i])) + continue; + + pr_debug("cell_voltage[%d] %f\n", i, + data->cell_voltage[i]); + } + + pr_debug("total_charge %.0f\n", data->total_charge); + pr_debug("int_temp %.1f\n", data->int_temp); + pr_debug("ext_temp %.1f\n", data->ext_temp); +} + /** * Read data from a slow device * @@ -85,6 +227,7 @@ int read_data(int infd, int outfd) } while (1) { + struct charger_data data; char str[320]; int len; @@ -117,12 +260,42 @@ int read_data(int infd, int outfd) pr_info("%s\n", buf); + parse_logline(buf, &data); + + dump_data(&data); + + if (isnan(data.timestamp)) + data.timestamp = cur_time - start_time; + if (!outfd) continue; len = snprintf(str, sizeof(str), - "%ld;%s\n", cur_time - start_time, buf); + "%d;%d;%.1f;" + "%.3f;%.3f;%.3f;" + "%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;%.3f;" + "%.f;%.1f;%.1f\n", /* mAh, and temp */ + data.channel, + data.state, + data.timestamp, + + data.input_voltage, + data.charging_voltage, + data.charging_current, + data.cell_voltage[0], + data.cell_voltage[1], + data.cell_voltage[2], + data.cell_voltage[3], + data.cell_voltage[4], + data.cell_voltage[5], + data.cell_voltage[6], + data.cell_voltage[7], + data.cell_voltage[8], + data.cell_voltage[9], + data.total_charge, + data.int_temp, + data.ext_temp); ret = write(outfd, str, len); if (ret < 0) { pr_err("write: %m\n"); diff --git a/data.h b/data.h index fa3b055..3034e0c 100644 --- a/data.h +++ b/data.h @@ -1,6 +1,22 @@ #ifndef _DATA_H_ #define _DATA_H_ +#define MAX_CELLS 10 + +struct charger_data { + int channel; + int state; + double timestamp; /* seconds since beginning of the charging */ + double input_voltage; + double charging_voltage; + double charging_current; + double cell_voltage[MAX_CELLS]; + + double total_charge; /* mAh */ + double int_temp; /* milli celsius */ + double ext_temp; +}; + int read_data(int infd, int outfd); #endif