From 89f26595b6215eab389cb2cfff68f9a70392e862 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sat, 12 Sep 2015 04:34:32 +0200 Subject: [PATCH] support missing power usage data Some notebooks do not provide power usage data. This code tries to estimate the current power usage by measuring the battery level difference in a specific time interval. --- src/battery/linux.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/battery/linux.c b/src/battery/linux.c index 89989d5..47a0942 100644 --- a/src/battery/linux.c +++ b/src/battery/linux.c @@ -34,6 +34,7 @@ enum psy_type { struct psy_battery { /* generic properties */ gchar* name; + gint64 timestamp; /* sysfs files */ gchar* path_present; gchar* path_energy_now; @@ -280,17 +281,31 @@ gboolean battery_os_init() { return batteries != NULL; } +static gint estimate_power_usage(struct psy_battery *bat, gint old_energy_now, gint64 old_timestamp) { + gint64 diff_power = ABS(bat->energy_now - old_energy_now); + gint64 diff_time = bat->timestamp - old_timestamp; + + /* µW = (µWh * 3600) / (µs * 1000000) */ + gint power = diff_power * 3600 * 1000000 / diff_time; + + return power; +} + static gboolean update_linux_battery(struct psy_battery *bat) { GError *error = NULL; gchar *data; gsize datalen; + gint64 old_timestamp = bat->timestamp; + int old_energy_now = bat->energy_now; + /* reset values */ bat->present = 0; bat->status = BATTERY_UNKNOWN; bat->energy_now = 0; bat->energy_full = 0; bat->power_now = 0; + bat->timestamp = g_get_monotonic_time(); /* present */ g_file_get_contents(bat->path_present, &data, &datalen, &error); @@ -329,9 +344,17 @@ static gboolean update_linux_battery(struct psy_battery *bat) { /* power now */ g_file_get_contents(bat->path_power_now, &data, &datalen, &error); - RETURN_ON_ERROR(error); - bat->power_now = atoi(data); - g_free(data); + if (g_error_matches(error, G_FILE_ERROR, G_FILE_ERROR_NODEV)) { + /* some hardware does not support reading current power consumption */ + g_error_free(error); + bat->power_now = estimate_power_usage(bat, old_energy_now, old_timestamp); + } else if(error) { + g_error_free(error); + return FALSE; + } else { + bat->power_now = atoi(data); + g_free(data); + } return TRUE; }