[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[STUMP] [PATCH] Add battery2.lisp - works with multiple batteries, uses
From: |
John Li |
Subject: |
[STUMP] [PATCH] Add battery2.lisp - works with multiple batteries, uses sysfs. |
Date: |
Sun, 20 Jul 2008 08:11:43 -0400 |
User-agent: |
Mutt/1.5.18 (2008-05-17) |
---
I rewrote battery.lisp. Mine:
- uses sysfs and works with 2.6.25 kernels (which have no
/proc/apci/battery/ (which I noticed when my stump started crashing
hard on reboot))
- works multiple batteries (or at least should! I have none to test)
- is designed to be easy to write your own formatter, if you don't
like my tastes.
- is (should be) very crash-resistant
- is cleaner :) (to me)
Notes:
- The formatter uses UTF characters ↑ and ↓ (U+2191 and U+2193) to
indicate charging and discharging. Do most people use a stumpwm font
with these characters? I think they look very nice.
- The formatter relies on my bar-zone-color patch from a few days ago;
I've added some commented code you can use if you don't have that
patch.
- The defun-cached macro would be useful for all formatters that you
wouldn't want to call every time you switch a frame or otherwise
cause the mode-line to update. It'd fit perfectly with cpu.lisp, for
one.
I'd really appreciate testing, particularly from people with multiple
batteries. I don't know Shawn's policy on contrib/ module code
quality, but I took care not to stomp on battery.lisp, so they could
co-exist... :)
contrib/battery2.lisp | 142 +++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 142 insertions(+), 0 deletions(-)
create mode 100644 contrib/battery2.lisp
diff --git a/contrib/battery2.lisp b/contrib/battery2.lisp
new file mode 100644
index 0000000..bcd1936
--- /dev/null
+++ b/contrib/battery2.lisp
@@ -0,0 +1,142 @@
+;;; Battery information formatters for the mode-line
+;;;
+;;; Copyright 2008 John Li
+;;;
+;;; Maintainer: John Li
+;;;
+;;; This module is free software; you can redistribute it and/or modify
+;;; it under the terms of the GNU General Public License as published by
+;;; the Free Software Foundation; either version 2, or (at your option)
+;;; any later version.
+;;;
+;;; This module is distributed in the hope that it will be useful,
+;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;;; GNU General Public License for more details.
+;;;
+;;; You should have received a copy of the GNU General Public License
+;;; along with this software; see the file COPYING. If not, write to
+;;; the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+;;; Boston, MA 02111-1307 USA
+;;;
+
+;;; USAGE:
+;;;
+;;; Place the following line in your ~/.stumpwmrc
+;;;
+;;; (load "/path/to/battery2.lisp")
+;;;
+;;; Then use "%B" in your mode-line format.
+;;;
+;;; NOTES:
+;;;
+;;; This is specific to Linux and accesses information through
+;;; sysfs. The files used may vary depending on your kernel version
+;;; and it would not be surprising for them to continue to change in
+;;; the future.
+;;;
+;;; This is designed to be easy to customize, since you might prefer a
+;;; different display. Simply define your own fmt-bat function after
+;;; loading this file in your .stumpwmrc; bat-perc and bat-time are
+;;; functions that you can use.
+
+(pushnew '(#\B fmt-bat) *screen-mode-line-formatters* :test 'equal)
+
+(defvar *bat-wait-time* 5
+ "Don't update the battery information more often than once every 10
+seconds.")
+
+(defmacro defun-cached (name interval arglist &body body)
+ "Creates a function that does simple caching. The body must be
+written in a functional style - the value returned is set as the
+prev-val."
+ (let ((prev-time (gensym "prev-time"))
+ (prev-val (gensym "prev-val"))
+ (now (gensym "now"))
+ (docstring (when (stringp (car body))
+ (pop body)))
+ (declares (loop while (and (listp (car body))
+ (eq 'declare (caar body)))
+ collect (pop body))))
+ `(progn (defvar ,prev-time 0)
+ (defvar ,prev-val nil)
+ (defun ,name ,arglist
+ ;; if no docstring, return nothing (not even nil)
+ ,@(when docstring (list docstring))
+ ,@declares
+ (let ((,now (/ (get-internal-real-time)
+ internal-time-units-per-second)))
+ (when (>= (- ,now ,prev-time) ,interval)
+ (setf ,prev-time ,now)
+ (setf ,prev-val (progn ,@body)))
+ ,prev-val)))))
+
+(defun bat-data (bat data)
+ "Gets the data for the corresponding file under the given battery's
+sysfs path. If the data is an integer, the integer is returned. If the
+file doesn't exist, nil is returned."
+ (with-open-file (s (merge-pathnames bat data)
+ :direction :input :if-does-not-exist nil)
+ (when s
+ (let* ((val (read-line s nil))
+ (int (ignore-errors (parse-integer val))))
+ (if int
+ int
+ val)))))
+
+(defun parse-time (float-hour)
+ "Takes a floating point hour and returns a string of the form hh:mm."
+ (multiple-value-bind (h m) (truncate (* 60 float-hour) 60)
+ (format nil "~D:~2,'0D" h (round m))))
+
+(defun bat-time (status charge current &optional (full t))
+ "Returns either how much battery time is left when discharging or
+how much time remains until fully charged. If any required info is
+missing, returns nil."
+ (when (and status charge current full)
+ (cond ((string= status "Full") "")
+ ;; when switching from "Full" to "Discharging" status,
+ ;; there's a chance that current is 0
+ ((string= status "Discharging")
+ (ignore-errors (parse-time (/ charge current))))
+ ((string= status "Charging")
+ (ignore-errors (parse-time (/ (- full charge) current))))
+ (t "?"))))
+
+(defun bat-perc (charge full)
+ (when (and charge full)
+ (round (* 100 (/ charge full)))))
+
+(defun bat-status (bat)
+ "Prints information about the given battery. Example output:
+3:50- 90% battery at 90%, discharging, and you have 3:50 left
+0:50+ 74% battery at 74%, charging, ~50 minutes until fully charged
+~ 100% battery is full"
+ (let* ((status (bat-data bat "status"))
+ (charge (bat-data bat "charge_now"))
+ (full (bat-data bat "charge_full"))
+ (current (bat-data bat "current_now"))
+ (time (bat-time status charge current full))
+ (status-icon (cond ((string= status "Full") "~")
+ ((string= status "Discharging") "↓")
+ ((string= status "Charging") "↑")
+ (t "?")))
+ (perc (bat-perc charge full)))
+; if you don't have my bar-zone-color patch (mailed on 20080718), use this:
+; (format nil "~A~A ~A%"
+; time status-icon perc)))
+ (format nil "~A~A ^[~A~A%^]"
+ time status-icon (bar-zone-color perc 50 30 20 t) perc)))
+
+(defun-cached fmt-bat *bat-wait-time* (ml)
+ "Prints the battery status of all batteries in *bat-list* not more
+often that *bat-wait-time* seconds using the defun-cached macro."
+ (declare (ignore ml))
+ (let ((bat-list (directory #P"/sys/class/power_supply/BAT*/")))
+ (cond ((null bat-list) "nil")
+ ((cadr bat-list) (let ((acc nil))
+ (dolist (b bat-list)
+ (push b acc)
+ (push (bat-status b) acc))
+ (format nil "~{~A: ~A~^ |~}" (nreverse acc))))
+ (t (bat-status (car bat-list))))))
--
1.5.6
Re: [STUMP] [PATCH] Add battery2.lisp - works with multiple batteries, uses sysfs., Vitaly Mayatskikh, 2008/07/24