summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2008-09-03 10:23:03 +0100
committerRichard Hughes <richard@hughsie.com>2008-09-03 10:23:03 +0100
commitf897e3d24c07d119b2680a3319a393e1b9ff2dd3 (patch)
treee4912552d370a9b67a61944fbd4d1fba2fe81a7c
parentd400e1ae7cf277af894f570b946cda2c6cd5973e (diff)
support getting stats from DkpSupply devices
-rw-r--r--src/Makefile.am1
-rw-r--r--src/dkp-history.c94
-rw-r--r--src/dkp-history.h4
-rw-r--r--src/dkp-supply.c22
4 files changed, 120 insertions, 1 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 6bfa13b..fef658f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,7 @@ devkit_power_daemon_CPPFLAGS = \
$(AM_CPPFLAGS)
devkit_power_daemon_LDADD = \
+ -lm \
$(USB_LIBS) \
$(GIO_LIBS) \
$(DBUS_GLIB_LIBS) \
diff --git a/src/dkp-history.c b/src/dkp-history.c
index 6df0232..838956c 100644
--- a/src/dkp-history.c
+++ b/src/dkp-history.c
@@ -23,11 +23,13 @@
#include <stdlib.h>
#include <stdio.h>
+#include <math.h>
#include <glib/gi18n.h>
#include <gio/gio.h>
#include "egg-debug.h"
#include "dkp-history.h"
+#include "dkp-stats-obj.h"
#include "dkp-history-obj.h"
static void dkp_history_class_init (DkpHistoryClass *klass);
@@ -78,6 +80,22 @@ dkp_history_new_history_list (void)
}
/**
+ * dkp_history_get_stats_list:
+ **/
+static EggObjList *
+dkp_history_new_stats_list (void)
+{
+ EggObjList *list;
+ list = egg_obj_list_new ();
+ egg_obj_list_set_new (list, (EggObjListNewFunc) dkp_stats_obj_new);
+ egg_obj_list_set_copy (list, (EggObjListCopyFunc) dkp_stats_obj_copy);
+ egg_obj_list_set_free (list, (EggObjListFreeFunc) dkp_stats_obj_free);
+ egg_obj_list_set_to_string (list, (EggObjListToStringFunc) dkp_stats_obj_to_string);
+ egg_obj_list_set_from_string (list, (EggObjListFromStringFunc) dkp_stats_obj_from_string);
+ return list;
+}
+
+/**
* dkp_history_copy_array_timespan:
**/
static EggObjList *
@@ -172,6 +190,82 @@ dkp_history_get_time_empty_data (DkpHistory *history, guint timespan)
}
/**
+ * dkp_history_get_profile_data:
+ **/
+EggObjList *
+dkp_history_get_profile_data (DkpHistory *history, gboolean charging)
+{
+ guint i;
+ const DkpHistoryObj *obj;
+ const DkpHistoryObj *obj_old = NULL;
+ DkpStatsObj *stats;
+ EggObjList *array;
+ EggObjList *data;
+ guint time;
+ gdouble value;
+ guint int_bin;
+ gdouble total_accuracy = 0.0f;
+
+ g_return_val_if_fail (DKP_IS_HISTORY (history), NULL);
+
+ /* create 100 item list and set to zero */
+ data = dkp_history_new_stats_list ();
+ for (i=0; i<101; i++) {
+ stats = dkp_stats_obj_create (0.0f, 0.0f);
+ egg_obj_list_add (data, stats);
+ dkp_stats_obj_free (stats);
+ }
+
+ /* partition the array into bins */
+ array = history->priv->data_charge;
+ egg_debug ("array->len=%i", array->len);
+ for (i=0; i<array->len; i++) {
+ obj = (const DkpHistoryObj *) egg_obj_list_index (array, i);
+ if (obj_old == NULL || obj->state != obj_old->state) {
+ obj_old = obj;
+ egg_debug ("ignoring %i as not the same as prev", obj->time);
+ continue;
+ }
+ /* center the value on a specific time difference */
+ time = obj->time - obj_old->time;
+ value = (obj->value + obj_old->value) / 2.0f;
+ if (value < 0.0001) {
+ egg_debug ("ignoring %i as zero", obj->time);
+ continue;
+ }
+
+ /* use the accuracy field as a counter for now */
+ if ((charging && obj->state == DKP_DEVICE_STATE_CHARGING) ||
+ (!charging && obj->state == DKP_DEVICE_STATE_DISCHARGING)) {
+ /* round to the nearest int */
+ int_bin = rint (value);
+ stats = (DkpStatsObj *) egg_obj_list_index (data, int_bin);
+ stats->value += time;
+ stats->accuracy++;
+ }
+ }
+
+ /* calculate average, and find total accuracy */
+ for (i=0; i<101; i++) {
+ stats = (DkpStatsObj *) egg_obj_list_index (data, i);
+ if (stats->accuracy != 0)
+ stats->value /= stats->accuracy;
+ total_accuracy += stats->accuracy;
+ }
+
+ /* set 100% as average */
+ total_accuracy = 10000.0f / total_accuracy;
+
+ /* normalise accuracy */
+ for (i=0; i<101; i++) {
+ stats = (DkpStatsObj *) egg_obj_list_index (data, i);
+ stats->accuracy *= total_accuracy;
+ }
+
+ return data;
+}
+
+/**
* dkp_history_get_filename:
**/
static gchar *
diff --git a/src/dkp-history.h b/src/dkp-history.h
index 06a37a1..594bf9e 100644
--- a/src/dkp-history.h
+++ b/src/dkp-history.h
@@ -29,7 +29,7 @@
G_BEGIN_DECLS
-#define DKP_TYPE_HISTORY (dkp_history_get_type ())
+#define DKP_TYPE_HISTORY (dkp_history_get_type ())
#define DKP_HISTORY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), DKP_TYPE_HISTORY, DkpHistory))
#define DKP_HISTORY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), DKP_TYPE_HISTORY, DkpHistoryClass))
#define DKP_IS_HISTORY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), DKP_TYPE_HISTORY))
@@ -61,6 +61,8 @@ EggObjList *dkp_history_get_time_full_data (DkpHistory *history,
guint timespan);
EggObjList *dkp_history_get_time_empty_data (DkpHistory *history,
guint timespan);
+EggObjList *dkp_history_get_profile_data (DkpHistory *history,
+ gboolean charging);
gboolean dkp_history_set_id (DkpHistory *history,
const gchar *id);
diff --git a/src/dkp-supply.c b/src/dkp-supply.c
index c0e1688..6efb9b8 100644
--- a/src/dkp-supply.c
+++ b/src/dkp-supply.c
@@ -384,6 +384,27 @@ dkp_supply_get_history (DkpDevice *device, const gchar *type, guint timespan)
}
/**
+ * dkp_supply_get_stats:
+ **/
+static EggObjList *
+dkp_supply_get_stats (DkpDevice *device, const gchar *type)
+{
+ DkpSupply *supply = DKP_SUPPLY (device);
+ EggObjList *array = NULL;
+
+ g_return_val_if_fail (DKP_IS_SUPPLY (supply), FALSE);
+ g_return_val_if_fail (type != NULL, FALSE);
+
+ /* get the correct data */
+ if (egg_strequal (type, "charging"))
+ array = dkp_history_get_profile_data (supply->priv->history, TRUE);
+ else if (egg_strequal (type, "discharging"))
+ array = dkp_history_get_profile_data (supply->priv->history, FALSE);
+
+ return array;
+}
+
+/**
* dkp_supply_coldplug:
**/
static gboolean
@@ -512,6 +533,7 @@ dkp_supply_class_init (DkpSupplyClass *klass)
device_class->coldplug = dkp_supply_coldplug;
device_class->refresh = dkp_supply_refresh;
device_class->get_history = dkp_supply_get_history;
+ device_class->get_stats = dkp_supply_get_stats;
g_type_class_add_private (klass, sizeof (DkpSupplyPrivate));
}