chiark / gitweb /
energy vs power
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 5 Jun 2012 23:56:20 +0000 (00:56 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 5 Jun 2012 23:56:20 +0000 (00:56 +0100)
cprogs/xacpi-simple.c
debian/changelog

index c0810eaad93ce286a9a88097e0573c351acdf23b..6328e5b9e0efaa80200a2e8aeb4b3a979fe8ba41 100644 (file)
@@ -1,6 +1,4 @@
 /* todo
- power vs current
- Full
  old way of doing alarm
 */
 
@@ -51,6 +49,7 @@
 #include <ctype.h>
 #include <stdint.h>
 #include <limits.h>
+#include <inttypes.h>
 
 #include <sys/poll.h>
 #include <sys/types.h>
@@ -67,6 +66,7 @@
 #define TIMEOUT_ONERROR 3333 /* milliseconds */
 
 static const char program_name[]= "xacpi-simple";
+static int debug;
 
 /*---------- general utility stuff and declarations ----------*/
 
@@ -102,21 +102,23 @@ typedef struct batinfo_field {
   const char *enumarray[10];
 } batinfo_field;
 
-#define BAT_QTYS(_)                                                    \
-  _(design_capacity,              ENERGY, CHARGE,  FULL_DESIGN )       \
-  _(last_full_capacity,           ENERGY, CHARGE,  FULL        )       \
-  _(remaining_capacity,           ENERGY, CHARGE,  NOW         )       \
-  _(present_rate,                 POWER,  CURRENT, NOW         )
+#define BAT_QTYS(_, _ec, EC_, PC_)                             \
+  _(design_capacity##_ec,    BATTERY,  EC_##FULL_DESIGN )      \
+  _(last_full_capacity##_ec, BATTERY,  EC_##FULL        )      \
+  _(remaining_capacity##_ec, BATTERY,  EC_##NOW         )      \
+  _(present_rate##_ec,       BATTERY,  PC_##NOW         )
  /* ENERGY [mWh]; POWER [mW]; CHARGE [uAh]; CURRENT [uA] */
 
-#define UEVENT_QTY_CHARGE(f,lle,llc,lr)                \
-  _(f##_energy,         BATTERY,  lle##_##lr ) \
-  _(f##_charge,         BATTERY,  llc##_##lr )
+#define UEVENT_ESSENTIAL_QUANTITY_FIELDS(_)                    \
+  _(present,                 BATTERY,  PRESENT /* bool */ )    \
+  _(online,                  MAINS,    ONLINE  /* bool */ )
 
-#define UEVENT_QUANTITY_FIELDS(_)                                      \
-  BAT_QTYS(UEVENT_QTY_CHARGE)                                          \
-  _(present,            BATTERY,  PRESENT            ) /* boolean */   \
-  _(online,             MAINS,    ONLINE             ) /* boolean */
+#define UEVENT_FUNKY_QUANTITY_FIELDS(_)                \
+  BAT_QTYS(_,_energy,ENERGY_,POWER_)           \
+  BAT_QTYS(_,_charge,CHARGE_,CURRENT_)
+
+#define UEVENT_OPTIONAL_QUANTITY_FIELDS(_)                     \
+  _(voltage,                 BATTERY,  VOLTAGE_NOW /* uV */ )
 
 #define UEVENT_ENUM_FIELDS(_)                                          \
   _(state,   BATTERY,  STATUS,  "Discharging","Charging","Full","Unknown" ) \
@@ -135,18 +137,32 @@ typedef struct batinfo_field {
 #define SEPARATE_QUANTITY_FIELDS(_)            \
   _(alarm,   BATTERY,  "alarm", "0", "1")
 
-#define ALL_FIELDS(_)                          \
-  UEVENT_QUANTITY_FIELDS(_)                    \
+
+#define ALL_DIRECT_VARS(_)                     \
+  UEVENT_ESSENTIAL_QUANTITY_FIELDS(_)          \
+  UEVENT_FUNKY_QUANTITY_FIELDS(_)              \
+  UEVENT_OPTIONAL_QUANTITY_FIELDS(_)           \
   UEVENT_ENUM_FIELDS(_)                                \
   SEPARATE_QUANTITY_FIELDS(_)
 
-#define ALL_QUANTITY_FIELDS(_)                 \
-  UEVENT_QUANTITY_FIELDS(_)                    \
+#define ALL_VARS(_)                            \
+  ALL_DIRECT_VARS(_)                           \
+  BAT_QTYS(_,,,)
+
+#define ALL_NEEDED_FIELDS(_)                   \
+  UEVENT_ESSENTIAL_QUANTITY_FIELDS(_)          \
+  UEVENT_ENUM_FIELDS(_)                                \
   SEPARATE_QUANTITY_FIELDS(_)
 
-#define ALL_VARS(_)                            \
-  ALL_FIELDS(_)                                        \
-  BAT_QTYS(_)
+#define ALL_PLAIN_ACCUMULATE_FIELDS(_)         \
+  UEVENT_ESSENTIAL_QUANTITY_FIELDS(_)          \
+  UEVENT_ENUM_FIELDS(_)                                \
+  SEPARATE_QUANTITY_FIELDS(_)
+
+#define ALL_ACCUMULATE_FIELDS(_)               \
+  ALL_PLAIN_ACCUMULATE_FIELDS(_)               \
+  BAT_QTYS(_,,,)
+
 
 #define F_VAR(f,...) \
 static value this_##f;
@@ -156,7 +172,9 @@ ALL_VARS(F_VAR)
 #define E_FLD(f,t,l,vl...)  { "POWER_SUPPLY_" #l, &this_##f, { vl } },
 
 static const batinfo_field uevent_fields[]= {
-  UEVENT_QUANTITY_FIELDS(Q_FLD)
+  UEVENT_ESSENTIAL_QUANTITY_FIELDS(Q_FLD)
+  UEVENT_FUNKY_QUANTITY_FIELDS(Q_FLD)
+  UEVENT_OPTIONAL_QUANTITY_FIELDS(Q_FLD)
   UEVENT_ENUM_FIELDS(E_FLD)
   { 0 }
 };
@@ -310,6 +328,13 @@ ALL_VARS(V_NOTFOUND)
     batfile= 0;
   }
 
+  if (debug) {
+    printf("%s:\n",batdirname);
+#define V_PRINT(f,...)                                 \
+    printf(" %-30s = %20"PRId64"\n", #f, (int64_t)this_##f);
+ALL_DIRECT_VARS(V_PRINT)
+  }
+
   int needsfields_MAINS   = this_type == TYPE_MAINS;
   int needsfields_BATTERY = this_type == TYPE_BATTERY;
   int needsfields_BOTH    = 1;
@@ -322,7 +347,7 @@ ALL_VARS(V_NOTFOUND)
            batdirname, #f);                            \
     missing++;                                         \
   }
-ALL_FIELDS(V_NEEDED)
+ALL_NEEDED_FIELDS(V_NEEDED)
 
   if (missing) return -1;
 
@@ -338,7 +363,7 @@ static int alarm_level; /* 0=ok, 1=low */
 
 #define Q_VAR(f,t,...) \
 static double total_##f;
-  ALL_QUANTITY_FIELDS(Q_VAR)
+  ALL_ACCUMULATE_FIELDS(Q_VAR)
 
 static void acquiredata(void) {
   DIR *di;
@@ -349,7 +374,7 @@ static void acquiredata(void) {
 
 #define Q_ZERO(f,t,...) \
   total_##f= 0;
-ALL_QUANTITY_FIELDS(Q_ZERO)
+ALL_ACCUMULATE_FIELDS(Q_ZERO)
 
   r = chdir_base();
   if (r) goto bad;
@@ -374,32 +399,48 @@ ALL_QUANTITY_FIELDS(Q_ZERO)
 
       charging_mask |= 1u << this_state;
 
+#define QTY_SUPPLIED(f,...)   this_##f != VAL_NOTFOUND &&
+#define QTY_USE_ENERGY(f,...) this_##f = this_##f##_energy;
+#define QTY_USE_CHARGE(f,...) this_##f = this_##f##_charge;
+
+      double funky_multiplier;
+      if (BAT_QTYS(QTY_SUPPLIED,_energy,,) 1) {
+       if (debug) printf(" using energy\n");
+       BAT_QTYS(QTY_USE_ENERGY,,,);
+       funky_multiplier = 1.0;
+      } else if (BAT_QTYS(QTY_SUPPLIED,_charge,,)
+                this_voltage != VAL_NOTFOUND) {
+       if (debug) printf(" using charge\n");
+       BAT_QTYS(QTY_USE_CHARGE,,,);
+       funky_multiplier = this_voltage * 1e-6;
+      } else {
+       batfailc("neither complete set of energy nor charge");
+       continue;
+      }
       if (this_state == CHGST_DISCHARGING)
        /* negate it */
-       total_present_rate -= 2.0 * thisbat_present_rate;
-
-#define QTY_ENERGY_SUPPLIED(f,...) this_##f##_energy != V_NOTFOUND &&
-#define QTY_ENERGY_USE(f,...)      this_##f = this_##f##_energy;
-#define QTY_CHARGE_SUPPLIED(f,...) this_##f##_charge != V_NOTFOUND &&
-#define QTY_CHARGE_USE(f,...)      this_##f = this_##f##_charge;
+       total_present_rate -= 2.0 * this_present_rate * funky_multiplier;
 
-      if (BAT_QTYS(QTY_ENERGY_SUPPLIED) 1) {
-       BAT_QTYS(QTY_ENERGY_USE);
-      } else if (BAT_QTYS(QTY_CHARGE_SUPPLIED) 1) {
-       BAT_QTYS(QTY_CHARGE_USE);
-      } else {
-       return batfailc("neither complete set of energy nor charge");
-      }
+#define Q_ACCUMULATE_FUNKY(f,...)                      \
+      total_##f += this_##f * funky_multiplier;
+BAT_QTYS(Q_ACCUMULATE_FUNKY,,,)
     }
 
-#define Q_TOTALISE(f,t,...)                    \
-    if (thisbat_type == TYPE_##t)              \
-      total_##f += thisbat_##f;
-ALL_QUANTITY_FIELDS(Q_TOTALISE)
+#define Q_ACCUMULATE_PLAIN(f,t,...)                    \
+    if (this_type == TYPE_##t)                 \
+      total_##f += this_##f;
+ALL_PLAIN_ACCUMULATE_FIELDS(Q_ACCUMULATE_PLAIN)
+
       
   }
   closedir(di);
 
+  printf("TOTAL:\n");
+#define T_PRINT(f,...)                                 \
+    printf(" %-30s = %20.6f\n", #f, total_##f);
+BAT_QTYS(T_PRINT,,,)
+ALL_PLAIN_ACCUMULATE_FIELDS(T_PRINT)
+
   if (total_design_capacity < 0.5)
     total_design_capacity= 1.0;
 
@@ -452,6 +493,7 @@ static const char defaultresources[]=
 
 #define S(s) ((char*)(s))
 static const XrmOptionDescRec optiontable[]= {
+  { S("-debug"),        S("*debug"),        XrmoptionIsArg },
   { S("-display"),      S("*display"),      XrmoptionSepArg },
   { S("-geometry"),     S("*geometry"),     XrmoptionSepArg },
 #define GC(g)
@@ -500,6 +542,8 @@ static void parseargs(int argc, char **argv) {
 
   if (argc>1) badusage();
 
+  debug= !!getresource("debug");
+
   disp= XOpenDisplay(getresource("display"));
   if (!disp) fail("could not open display");
 
index 4ed6596d88cbf682a253c65fcab00a5524ebf129..35f62477991fc094a671d5b44129063339c01191 100644 (file)
@@ -2,12 +2,22 @@ chiark-utils (4.1.31~~iwj) unstable; urgency=low
 
   * chiark-backup Suggests chiark-utils-bin, not the nonexistent
     chiark-cprogs (for `summer').
+
+  * xacpi-simple updated:
+    - now works with recent kernels by reading /sys/class/power_supply
+      (so is now misnamed, since that may or may not come from acpi)
+    - copes both with batteries which report charge/current and ones which
+      report energy/power.
+    - copes with batteries which are not full, charging or discharging
+      (eg, if the system is on a/c but battery charging is suppressed)
+    - some debugging output
+
   * Fix the build-depends to refer to nettle-dev not libnettle-dev.
   * Add ${misc:Depends} to Depends: lines.  Causes no change to the .debs.
   * Switch to git.  Move .cvsignores to .gitignore, etc.
   * Update my email address.
 
- -- Ian Jackson <ijackson@chiark.greenend.org.uk>  Sun, 03 Jun 2012 14:56:36 +0100
+ --
 
 chiark-utils (4.1.30) unstable; urgency=low