X-Git-Url: http://git.itanic.dy.fi/?p=log-plotter;a=blobdiff_plain;f=data.c;h=56a6b72faeca6cd445135421bbc5910851c32dd3;hp=fa370729b0c8a242b4efa053cc569a9dcfa4f632;hb=HEAD;hpb=4daad2abbacb183bc39d7ef1220e86afe6068b5d diff --git a/data.c b/data.c index fa37072..56a6b72 100644 --- a/data.c +++ b/data.c @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include #include #include @@ -11,8 +13,22 @@ #include "data.h" #include "trace.h" +#include "event.h" #include "utils.h" - +#include "event.h" +#include "plotter_status.h" + +#define MAX_CHANNELS 4 + +struct dataparser_struct { + struct eventhandler_entry evhandler; + struct plotter_config *cfg; + int infd; + int outfd[MAX_CHANNELS]; + int offset; + time_t start_time; + char buf[256]; +}; static int separate_entries(char *buf, char *entries[], int max_entries) { @@ -70,8 +86,6 @@ static int parse_logline(const char *buf, struct charger_data *data) entry_count = separate_entries(str, entries, ARRAY_SIZE(entries)); - pr_debug("Entry count: %d\n", entry_count); - init_data(data); if (entries[0][0] != '$') { @@ -79,12 +93,11 @@ static int parse_logline(const char *buf, struct charger_data *data) 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++]); + if (data->channel > MAX_CHANNELS) + data->channel = 0; data->state = atoi(entries[i++]); @@ -110,6 +123,9 @@ static int parse_logline(const char *buf, struct charger_data *data) for (j = 0; j < max_cells; j++, i++) { d = atoi(entries[i]); ASSIGN_OR_NAN(data->cell_voltage[j], d / 1000.0); + + if (d) + data->cell_count++; } d = atoi(entries[i++]); @@ -175,9 +191,11 @@ static void print_status_line(struct charger_data *data) } cell_avg /= (double)active_cells; - pr_info("\r\033[K%8s Ubat: %.3fV Ucell avg: %.3fV " + pr_info("\r\033[K%s [%s] Ubat: %.3fV Ucell avg: %.3fV " "Current: %.2fA Charge %.0fmAh ", - time_str, data->charging_voltage, cell_avg, + time_str, + state_to_str(data->state), + data->charging_voltage, cell_avg, data->charging_current, data->total_charge); fflush(stdout); @@ -207,6 +225,8 @@ static int read_log_line(int infd, char *buf, size_t bufsize, int *offset) if (ret == 0) { pr_err("Read EOF, stopping\n"); + + set_plotter_system_status(SYSTEM_STATUS_NO_USB); return -1; } buf[*offset + ret] = 0; @@ -238,107 +258,145 @@ static int read_log_line(int infd, char *buf, size_t bufsize, int *offset) return 0; } -int read_data(int infd, int outfd) +static int open_new_logfile(struct dataparser_struct *dt, int channel) { - struct epoll_event ev; - time_t start_time = 0, cur_time; - int epoll_fd; - int ret; - char buf[256]; - int offset = 0; + char path[2048]; + struct tm *tm; + time_t cur_time = time(NULL); + + tm = localtime(&cur_time); + strftime(path, sizeof(path), dt->cfg->log_path, tm); + + store_int_variable_value_to_array("channel", channel, dt->cfg); + replace_variables_with_values(path, sizeof(path), dt->cfg); - epoll_fd = epoll_create(1); - if (epoll_fd < 0) { - pr_err("Failed to create epoll socket: %m\n"); + pr_debug("Opening %s for writing the log file\n", path); + + dt->outfd[channel] = open(path, O_CREAT | O_APPEND | O_WRONLY, 0664); + if (dt->outfd[channel] < 0) { + pr_err("Failed to open file %s for writing: %m\n", + path); return -1; } - ev.events = EPOLLIN; - ev.data.fd = infd; - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, infd, &ev) == -1) { - pr_err("epoll_ctl: %m\n"); - return 1; - } + return 0; +} - while (1) { - struct charger_data data; - char str[320]; - int len; +static int read_data(struct eventhandler_entry *h) +{ + struct dataparser_struct *dt; + time_t cur_time; + int ret; + struct charger_data data; + char str[320]; + int len; - ret = epoll_wait(epoll_fd, &ev, 1, -1); - if (ret == 0) - continue; + dt = container_of(h, struct dataparser_struct, evhandler); - if (ret < 0) { - pr_err("epoll: %m\n"); - return -1; - } + ret = read_log_line(dt->infd, dt->buf, sizeof(dt->buf), &dt->offset); + if (ret <= 0) + return ret; - ret = read_log_line(infd, buf, sizeof(buf), &offset); - if (ret < 0) - return ret; + if (ret == 0) + pr_err("%s %s: EOF\n", __FILE__, __func__); - if (ret == 0) - continue; + if (strlen(dt->buf) < 5) { + pr_debug("discarding truncated log entry\n"); + dt->offset = 0; + return 0; + } - if (strlen(buf) < 5) { - pr_debug("discarding truncated log entry\n"); - offset = 0; - continue; - } + if (!dt->start_time) + dt->start_time = time(NULL); - if (!start_time) - start_time = time(NULL); + cur_time = time(NULL); - cur_time = time(NULL); + parse_logline(dt->buf, &data); - parse_logline(buf, &data); + set_plotter_system_status(data.state); - /* Fill in possibly missing timestamp */ - if (isnan(data.timestamp) || data.timestamp == 0); - data.timestamp = cur_time - start_time; + /* Fill in possibly missing timestamp */ + if (isnan(data.timestamp) || data.timestamp == 0) + data.timestamp = cur_time - dt->start_time; - print_status_line(&data); + print_status_line(&data); + if (0) dump_data(&data); - if (!outfd) - continue; + if (!dt->cfg->log_path) + return 0; - len = snprintf(str, sizeof(str), - "%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.int_temp, - data.ext_temp, - data.total_charge); - - ret = write(outfd, str, len); - if (ret < 0) { - pr_err("write: %m\n"); - break; - } + if (state_has_changed()) { + dt->start_time = time(NULL); + data.timestamp = 0; + store_str_variable_value_to_array("status", + state_to_str(plotter_state.system_status), dt->cfg); + + store_int_variable_value_to_array("cell_count", + data.cell_count, dt->cfg); + + ret = open_new_logfile(dt, data.channel); + if (ret < 0) + return ret; + } + + len = snprintf(str, sizeof(str), + "%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.int_temp, + data.ext_temp, + data.total_charge); + + if (dt->outfd[data.channel] <= 0) + open_new_logfile(dt, data.channel); + + ret = write(dt->outfd[data.channel], str, len); + if (ret < 0) { + pr_err("write: %m\n"); + return -1;; } return 0; } +static struct dataparser_struct dataparser = { + .evhandler.name = "OpenLog Parser", + .evhandler.events = EPOLLIN, + .evhandler.handle_event = read_data, +}; + +int init_data_parser(int infd, struct plotter_config *cfg) +{ + int ret; + + dataparser.evhandler.fd = infd; + dataparser.infd = infd; + dataparser.cfg = cfg; + + ret = register_event_handler(&dataparser.evhandler); + if (ret < 0) + return 1; + + return 0; +}