summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Nocera <hadess@hadess.net>2013-10-15 14:54:03 +0200
committerBastien Nocera <hadess@hadess.net>2013-10-15 15:01:37 +0200
commit689ae112de257c49403722efcb5ab2c82335a860 (patch)
treef83733ced73aa590271681e2bb7673c268bd657e
parent7e61b094097a198e9d9b2fe409b3b16b1d171a14 (diff)
downloadupower-689ae112de257c49403722efcb5ab2c82335a860.tar.gz
daemon: Calculate global WarningLevel correctly
By using the state of all the combined batteries, rather than each one (eg. 2 batteries of the same type at 15% shouldn't trigger the "low" warning level). This introduces code to calculate the state of a "display" device, which is either a UPS, or a combination of all batteries.
-rw-r--r--src/up-daemon.c154
1 files changed, 137 insertions, 17 deletions
diff --git a/src/up-daemon.c b/src/up-daemon.c
index ce5da3a..77e701c 100644
--- a/src/up-daemon.c
+++ b/src/up-daemon.c
@@ -84,6 +84,16 @@ struct UpDaemonPrivate
gboolean lid_is_present;
gboolean is_docked;
+ /* Display battery properties */
+ UpDeviceKind kind;
+ UpDeviceState state;
+ gdouble percentage;
+ gdouble energy;
+ gdouble energy_full;
+ gdouble energy_rate;
+ gint64 time_to_empty;
+ gint64 time_to_full;
+
/* WarningLevel configuration */
gboolean use_percentage_for_policy;
guint low_percentage;
@@ -165,41 +175,151 @@ up_daemon_get_number_devices_of_type (UpDaemon *daemon, UpDeviceKind type)
}
/**
- * up_daemon_get_warning_level_local:
+ * up_daemon_update_display_battery:
*
- * As soon as _all_ batteries are low, this is true
+ * Update our internal state.
+ *
+ * Returns: %TRUE if the state changed.
**/
static gboolean
-up_daemon_get_warning_level_local (UpDaemon *daemon)
+up_daemon_update_display_battery (UpDaemon *daemon)
{
guint i;
GPtrArray *array;
- UpDeviceLevel level = UP_DEVICE_LEVEL_LAST;
- /* ask each device */
+ UpDeviceKind kind_total = UP_DEVICE_KIND_UNKNOWN;
+ UpDeviceState state_total = UP_DEVICE_STATE_UNKNOWN;
+ gdouble percentage_total = 0.0;
+ gdouble energy_total = 0.0;
+ gdouble energy_full_total = 0.0;
+ gdouble energy_rate_total = 0.0;
+ gint64 time_to_empty_total = 0;
+ gint64 time_to_full_total = 0;
+ guint num_batteries = 0;
+
+ /* Gather state from each device */
array = up_device_list_get_array (daemon->priv->power_devices);
for (i = 0; i < array->len; i++) {
UpDevice *device;
- UpDeviceLevel device_level;
- UpDeviceKind kind;
+
+ UpDeviceState state = UP_DEVICE_STATE_UNKNOWN;
+ UpDeviceKind kind = UP_DEVICE_KIND_UNKNOWN;
+ gdouble percentage = 0.0;
+ gdouble energy = 0.0;
+ gdouble energy_full = 0.0;
+ gdouble energy_rate = 0.0;
+ gint64 time_to_empty = 0;
+ gint64 time_to_full = 0;
device = g_ptr_array_index (array, i);
- g_object_get (G_OBJECT (device),
+ g_object_get (device,
"type", &kind,
- "warning-level", &device_level,
+ "state", &state,
+ "percentage", &percentage,
+ "energy", &energy,
+ "energy-full", &energy_full,
+ "energy-rate", &energy_rate,
+ "time-to-empty", &time_to_empty,
+ "time-to-full", &time_to_full,
NULL);
- if (kind != UP_DEVICE_KIND_BATTERY &&
- kind != UP_DEVICE_KIND_UPS)
+
+ /* When we have a UPS, it's either a desktop, and
+ * has no batteries, or a laptop, in which case we
+ * ignore the batteries */
+ if (kind == UP_DEVICE_KIND_UPS) {
+ kind_total = kind;
+ state_total = state;
+ energy_total = energy;
+ energy_full_total = energy_full;
+ energy_rate_total = energy_rate;
+ time_to_empty_total = time_to_empty;
+ time_to_full_total = time_to_full;
+ percentage_total = percentage;
+ break;
+ }
+ if (kind != UP_DEVICE_KIND_BATTERY)
continue;
- if (device_level < level)
- level = device_level;
+
+ /* If one battery is charging, then the composite is charging
+ * If all batteries are discharging, then the composite is discharging
+ * If all batteries are fully charged, then they're all fully charged
+ * Everything else is unknown */
+ if (state == UP_DEVICE_STATE_CHARGING)
+ state_total = UP_DEVICE_STATE_CHARGING;
+ else if (state == UP_DEVICE_STATE_DISCHARGING &&
+ state_total != UP_DEVICE_STATE_CHARGING)
+ state_total = UP_DEVICE_STATE_DISCHARGING;
+ else if (state == UP_DEVICE_STATE_FULLY_CHARGED &&
+ state_total == UP_DEVICE_STATE_UNKNOWN)
+ state_total = UP_DEVICE_STATE_FULLY_CHARGED;
+
+ /* sum up composite */
+ energy_total += energy;
+ energy_full_total += energy_full;
+ energy_rate_total += energy_rate;
+ time_to_empty_total += time_to_empty;
+ time_to_full_total += time_to_full;
+ /* Will be recalculated for multiple batteries, no worries */
+ percentage_total += percentage;
+ num_batteries++;
}
- g_ptr_array_unref (array);
- if (level == UP_DEVICE_LEVEL_LAST)
- level = UP_DEVICE_LEVEL_NONE;
+ /* Handle multiple batteries */
+ if (num_batteries <= 1)
+ goto out;
+
+ g_debug ("Calculating percentage and time to full/to empty for %i batteries", num_batteries);
+
+ /* use percentage weighted for each battery capacity */
+ if (energy_full_total > 0.0)
+ percentage_total = 100.0 * energy_total / energy_full_total;
+
+ /* calculate a quick and dirty time remaining value */
+ if (energy_rate_total > 0) {
+ if (state_total == UP_DEVICE_STATE_DISCHARGING && time_to_empty_total == 0)
+ time_to_empty_total = 3600 * (energy_total / energy_rate_total);
+ else if (state_total == UP_DEVICE_STATE_CHARGING && time_to_full_total == 0)
+ time_to_full_total = 3600 * ((energy_full_total - energy_total) / energy_rate_total);
+ }
+
+out:
+ daemon->priv->kind = kind_total;
+ daemon->priv->state = state_total;
+ daemon->priv->energy = energy_total;
+ daemon->priv->energy_full = energy_full_total;
+ daemon->priv->energy_rate = energy_rate_total;
+ daemon->priv->time_to_empty = time_to_empty_total;
+ daemon->priv->time_to_full = time_to_full_total;
+
+ daemon->priv->percentage = percentage_total;
+
+ /* FIXME: Return whether the above actually changed significantly */
+ return TRUE;
+}
+
+/**
+ * up_daemon_get_warning_level_local:
+ *
+ * As soon as _all_ batteries are low, this is true
+ **/
+static gboolean
+up_daemon_get_warning_level_local (UpDaemon *daemon)
+{
+ up_daemon_update_display_battery (daemon);
+ if (daemon->priv->kind != UP_DEVICE_KIND_UPS &&
+ daemon->priv->kind != UP_DEVICE_KIND_BATTERY)
+ return UP_DEVICE_LEVEL_NONE;
+
+ if (daemon->priv->kind == UP_DEVICE_KIND_UPS &&
+ daemon->priv->state != UP_DEVICE_STATE_DISCHARGING)
+ return UP_DEVICE_LEVEL_NONE;
- return level;
+ return up_daemon_compute_warning_level (daemon,
+ daemon->priv->state,
+ daemon->priv->kind,
+ TRUE, /* power_supply */
+ daemon->priv->percentage,
+ daemon->priv->time_to_empty);
}
/**