[gnome-battery-bench] Power supply: basic voltage & energy setup code
- From: Christian Kellner <gicmo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-battery-bench] Power supply: basic voltage & energy setup code
- Date: Mon, 3 Apr 2017 15:37:31 +0000 (UTC)
commit f7da26f059cc2f9ddddb42575689e080194de6e9
Author: Christian Kellner <gicmo gnome org>
Date: Fri Mar 17 16:14:32 2017 +0100
Power supply: basic voltage & energy setup code
src/power-supply.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 files changed, 178 insertions(+), 5 deletions(-)
---
diff --git a/src/power-supply.c b/src/power-supply.c
index 018c57d..5ded60a 100644
--- a/src/power-supply.c
+++ b/src/power-supply.c
@@ -3,6 +3,10 @@
#include <glib.h>
#include <gudev/gudev.h>
+#define _ISOC99_SOURCE //for NAN
+#include <math.h>
+#include <limits.h>
+
#include "power-supply.h"
struct _GbbBattery {
@@ -11,6 +15,13 @@ struct _GbbBattery {
GUdevDevice *udevice;
char *vendor;
char *model;
+
+ double voltage_desgin;
+
+ double energy;
+ double energy_full;
+ double energy_full_design;
+ gboolean use_charge;
};
enum {
@@ -20,6 +31,12 @@ enum {
PROP_VENDOR,
PROP_MODEL,
+ PROP_VOLTAGE_DESIGN,
+
+ PROP_ENERGY,
+ PROP_ENERGY_FULL,
+ PROP_ENERGY_FULL_DESIGN,
+
PROP_BAT_LAST
};
@@ -27,6 +44,15 @@ static GParamSpec *battery_props[PROP_BAT_LAST] = { NULL, };
G_DEFINE_TYPE(GbbBattery, gbb_battery, G_TYPE_OBJECT);
+
+static char * sysfs_read_string_cached (GUdevDevice *device,
+ const char *name);
+static double sysfs_read_double_scaled (GUdevDevice *device,
+ const char *name);
+
+static void voltage_design_initialize (GbbBattery *battery);
+static void energy_design_initialize (GbbBattery *battery);
+
static void
gbb_battery_finalize(GObject *obj)
{
@@ -60,6 +86,22 @@ gbb_battery_get_property(GObject *object,
case PROP_MODEL:
g_value_set_string(value, bat->model);
break;
+
+ case PROP_VOLTAGE_DESIGN:
+ g_value_set_double(value, bat->voltage_desgin);
+ break;
+
+ case PROP_ENERGY:
+ g_value_set_double(value, bat->energy);
+ break;
+
+ case PROP_ENERGY_FULL:
+ g_value_set_double(value, bat->energy_full);
+ break;
+
+ case PROP_ENERGY_FULL_DESIGN:
+ g_value_set_double(value, bat->energy_full_design);
+ break;
}
}
@@ -86,13 +128,12 @@ gbb_battery_constructed(GObject *obj)
{
GbbBattery *bat = GBB_BATTERY(obj);
GUdevDevice *device = bat->udevice;
- const gchar *value;
- value = g_udev_device_get_sysfs_attr(device, "manufacturer");
- bat->vendor = g_strdup(value);
+ bat->vendor = sysfs_read_string_cached(device, "manufacturer");
+ bat->model = sysfs_read_string_cached(device, "model_name");
- value = g_udev_device_get_sysfs_attr(device, "model_name");
- bat->model = g_strdup(value);
+ voltage_design_initialize(bat);
+ energy_design_initialize(bat);
G_OBJECT_CLASS(gbb_battery_parent_class)->constructed(obj);
}
@@ -134,12 +175,144 @@ gbb_battery_class_init(GbbBatteryClass *klass)
G_PARAM_READABLE |
G_PARAM_STATIC_NAME);
+ battery_props[PROP_VOLTAGE_DESIGN] =
+ g_param_spec_double("voltage-design",
+ NULL, NULL,
+ 0, G_MAXDOUBLE, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ battery_props[PROP_ENERGY] =
+ g_param_spec_double("energy",
+ NULL, NULL,
+ 0, G_MAXDOUBLE, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ battery_props[PROP_ENERGY_FULL] =
+ g_param_spec_double("energy-full",
+ NULL, NULL,
+ 0, G_MAXDOUBLE, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
+ battery_props[PROP_ENERGY_FULL_DESIGN] =
+ g_param_spec_double("energy-full-design",
+ NULL, NULL,
+ 0, G_MAXDOUBLE, 0,
+ G_PARAM_READABLE |
+ G_PARAM_STATIC_NAME);
+
g_object_class_install_properties(gobject_class,
PROP_BAT_LAST,
battery_props);
}
+static char *
+sysfs_read_string_cached(GUdevDevice *device, const char *name)
+{
+ const char *value;
+
+ value = g_udev_device_get_sysfs_attr(device, name);
+ if (value == NULL) {
+ value = "Unknown";
+ }
+
+ return g_strdup(value);
+}
+
+static double
+sysfs_read_double_scaled(GUdevDevice *device, const char *name)
+{
+ g_autofree char *buffer = NULL;
+ char filename[PATH_MAX];
+ const char *path;
+ guint64 value;
+ double dv;
+ gboolean ok;
+ char *end;
+
+ path = g_udev_device_get_sysfs_path(device);
+
+ g_snprintf(filename, sizeof(filename), "%s/%s", path, name);
+ ok = g_file_get_contents(filename, &buffer, NULL, NULL);
+ if (!ok) {
+ return NAN;
+ }
+
+ value = g_ascii_strtoull(buffer, &end, 10);
+ if (end != buffer) {
+ dv = value / 1000000.;
+ } else {
+ dv = NAN;
+ }
+
+ return dv;
+}
+
+static const char *voltage_sources[] = {
+ "voltage_min_design",
+ "voltage_max_design",
+ "voltage_present",
+ "voltage_now",
+ NULL
+};
+
+static void
+voltage_design_initialize (GbbBattery *bat)
+{
+ const char **source;
+
+ for (source = voltage_sources; *source != NULL; source++) {
+ const char *name = *source;
+ double val = sysfs_read_double_scaled(bat->udevice, name);
+
+ if (val > 1.0) {
+ g_debug("Using '%s' as design voltage", name);
+ bat->voltage_desgin = val;
+ return;
+ }
+ }
+
+ g_warning("Could not get design voltage, estimating 12V.");
+ bat->voltage_desgin = 12;
+}
+
+static void
+energy_design_initialize(GbbBattery *bat)
+{
+ GUdevDevice *dev = bat->udevice;
+ double val;
+
+ val = sysfs_read_double_scaled(dev, "energy_now");
+ if (val > 1.0f) {
+ val = sysfs_read_double_scaled(dev, "energy_full");
+ bat->energy_full = val;
+
+ val = sysfs_read_double_scaled(dev, "energy_full_design");
+ bat->energy_full_design = val;
+ return;
+ }
+
+ val = sysfs_read_double_scaled(dev, "charge_now");
+ if (val > 1.0f) {
+ const double voltage_design = bat->voltage_desgin;
+ val = sysfs_read_double_scaled(dev, "charge_full");
+ bat->energy_full = val * voltage_design;
+
+ val = sysfs_read_double_scaled(dev, "charge_full_design");
+ bat->energy_full_design = val * voltage_design;
+
+ bat->use_charge = TRUE;
+ }
+
+ if (bat->energy_full < 1.0f ||
+ bat->energy_full_design < 1.0f) {
+ /* We actually should report that and give up working at all */
+ g_warning("Could not get energy full (design) for battery");
+ }
+}
GList *
gbb_battery_discover()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]