Function: battery-linux-sysfs

battery-linux-sysfs is a byte-compiled function defined in battery.el.gz.

Signature

(battery-linux-sysfs)

Documentation

Get sysfs status information from Linux kernel.

This function works only with the new /sys/class/power_supply/ interface introduced in Linux version 2.4.25.

The following %-sequences are provided:
%c Current capacity (mAh or mWh)
%r Current rate of charge or discharge
%L Power source (verbose)
%B Battery status (verbose)
%b Battery status, empty means high, - means low,
   ! means critical, and + means charging
%d Temperature (in degrees Celsius)
%p Battery load percentage
%m Remaining time (to charge or discharge) in minutes
%h Remaining time (to charge or discharge) in hours
%t Remaining time (to charge or discharge) in the form h:min

Source Code

;; Defined in /usr/src/emacs/lisp/battery.el.gz
;;; `/sys/class/power_supply/BATN' interface for Linux.

(defun battery-linux-sysfs ()
  "Get sysfs status information from Linux kernel.
This function works only with the new `/sys/class/power_supply/'
interface introduced in Linux version 2.4.25.

The following %-sequences are provided:
%c Current capacity (mAh or mWh)
%r Current rate of charge or discharge
%L Power source (verbose)
%B Battery status (verbose)
%b Battery status, empty means high, `-' means low,
   `!' means critical, and `+' means charging
%d Temperature (in degrees Celsius)
%p Battery load percentage
%m Remaining time (to charge or discharge) in minutes
%h Remaining time (to charge or discharge) in hours
%t Remaining time (to charge or discharge) in the form `h:min'"
  (let (;; Some batteries report charges and current, others energy and power.
        ;; In order to reliably be able to combine those data, we convert them
        ;; all to energy/power (since we can't combine different charges if
        ;; they're not at the same voltage).
	(energy-full 0.0)
	(energy-now 0.0)
	(power-now 0.0)
        (voltage-now 10.8) ; Arbitrary default, in case the info is missing.
        charging-state temperature hours percentage-now)
    ;; SysFS provides information about each battery present in the
    ;; system in a separate subdirectory.  We are going to merge the
    ;; available information together.
    (with-temp-buffer
      (dolist (dir (battery--find-linux-sysfs-batteries))
        (ignore-errors
          (insert-file-contents (expand-file-name "uevent" dir) nil nil nil t))
	(goto-char (point-min))
	(when (re-search-forward
	       "POWER_SUPPLY_VOLTAGE_NOW=\\([0-9]*\\)$" nil t)
	  (setq voltage-now (/ (string-to-number (match-string 1)) 1000000.0)))
	(goto-char (point-min))
	(when (re-search-forward "POWER_SUPPLY_PRESENT=1$" nil t)
	  (goto-char (point-min))
	  (and (re-search-forward "POWER_SUPPLY_STATUS=\\(.*\\)$" nil t)
	       (member charging-state '("Unknown" "Full" nil))
	       (setq charging-state (match-string 1)))
	  (goto-char (point-min))
	  (when (re-search-forward
                 "POWER_SUPPLY_\\(CURRENT\\|POWER\\)_NOW=\\([0-9]*\\)$"
                 nil t)
            (incf power-now
                  (* (string-to-number (match-string 2))
                     (if (eq (char-after (match-beginning 1)) ?C)
                         voltage-now 1))))
	  (goto-char (point-min))
	  (when (re-search-forward "POWER_SUPPLY_TEMP=\\([0-9]*\\)$" nil t)
	    (setq temperature (match-string 1)))
	  (goto-char (point-min))
	  (let (full-string now-string)
	    ;; Sysfs may list either charge (mAh) or energy (mWh).
	    ;; Keep track of both, and choose which to report later.
	    (cond ((and (re-search-forward
			 "POWER_SUPPLY_CHARGE_FULL=\\([0-9]*\\)$" nil t)
			(setq full-string (match-string 1))
			(re-search-forward
			 "POWER_SUPPLY_CHARGE_NOW=\\([0-9]*\\)$" nil t)
			(setq now-string (match-string 1)))
                   (incf energy-full (* (string-to-number full-string)
                                        voltage-now))
                   (incf energy-now  (* (string-to-number now-string)
                                        voltage-now)))
                  ((and (goto-char (point-min))
			(re-search-forward
			 "POWER_SUPPLY_ENERGY_FULL=\\([0-9]*\\)$" nil t)
			(setq full-string (match-string 1))
			(re-search-forward
			 "POWER_SUPPLY_ENERGY_NOW=\\([0-9]*\\)$" nil t)
			(setq now-string (match-string 1)))
                   (incf energy-full (string-to-number full-string))
                   (incf energy-now  (string-to-number now-string)))))
	  (unless (zerop power-now)
	    (let ((remaining (if (string= charging-state "Discharging")
				 energy-now
			       (- energy-full energy-now))))
	      (setq hours (/ remaining power-now)))))))
    (when (and (> energy-full 0) (> energy-now 0))
      (setq percentage-now (/ (* 100 energy-now) energy-full)))
    (list (cons ?c (if (or (> energy-full 0) (> energy-now 0))
                       (number-to-string (/ energy-now voltage-now))
                     "N/A"))
	  (cons ?r (if (> power-now 0.0)
		       (format "%.1f" (/ power-now 1000000.0))
		     "N/A"))
	  (cons ?m (if hours (format "%d" (* hours 60)) "N/A"))
	  (cons ?h (if hours (format "%d" hours) "N/A"))
	  (cons ?t (if hours
		       (format "%d:%02d" hours (* (- hours (floor hours)) 60))
		     "N/A"))
	  (cons ?d (or temperature "N/A"))
	  (cons ?B (or charging-state "N/A"))
          (cons ?b (cond ((string= charging-state "Charging") "+")
                         ((not percentage-now) "")
                         ((< percentage-now battery-load-critical) "!")
                         ((< percentage-now battery-load-low) "-")
                         ("")))
          (cons ?p (if percentage-now (format "%.1f" percentage-now) "N/A"))
          (cons ?L (pcase (battery-search-for-one-match-in-files
                           '("/sys/class/power_supply/AC/online"
                             "/sys/class/power_supply/ACAD/online"
                             "/sys/class/power_supply/ADP1/online")
                           (rx (in "01")) 0)
                     ("0" "BAT")
                     ("1" "AC")
                     (_ "N/A"))))))