diff options
| author | Basil L. Contovounesios | 2020-06-11 13:49:31 +0100 |
|---|---|---|
| committer | Basil L. Contovounesios | 2020-06-18 13:11:17 +0100 |
| commit | 453d30d92cbf940567869d4705c1fcfe57725825 (patch) | |
| tree | d79b43fdae2af987c36f018635e0c74bd1f67b53 | |
| parent | 23a148c9506f2a5bce71bd5c8822bb7cde6697e8 (diff) | |
| download | emacs-453d30d92cbf940567869d4705c1fcfe57725825.tar.gz emacs-453d30d92cbf940567869d4705c1fcfe57725825.zip | |
Improve battery.el UPower support
For discussion, see the following threads:
https://lists.gnu.org/archive/html/emacs-devel/2020-01/msg00843.html
https://lists.gnu.org/archive/html/emacs-devel/2020-02/msg00042.html
https://lists.gnu.org/archive/html/emacs-devel/2020-02/msg00282.html
* etc/NEWS: Announce that battery-upower is enabled by default.
* lisp/battery.el (battery-upower-device): Accept both battery and
line power device names, or a list thereof (bug#39491).
(battery-upower-line-power-device): Remove user option; superseded
by battery-upower-device.
(battery-upower-subscribe): New user option.
(battery-status-function): Check whether a UPower service is
provided without activating it.
(display-battery-mode): Subscribe to UPower signals when using
battery-upower.
(battery-upower): Merge data from multiple power sources. Calculate
terse battery status %b based on average battery load percentage
rather than coarse and often missing BatteryLevel (bug#39491). Add
support for average temperature %d.
(battery-upower-dbus-service)
(battery-upower-dbus-interface)
(battery-upower-dbus-path)
(battery-upower-dbus-device-interface)
(battery-upower-dbus-device-path)
(battery-upower-device-all-properties): Rename to...
(battery-upower-service)
(battery-upower-interface)
(battery-upower-path)
(battery-upower-device-interface)
(battery-upower-device-path)
(battery--upower-device-properties): ...these, respectively.
(battery-upower-device-list): Rename to...
(battery--upower-devices) ...this. Return a flat list of device
names determined by battery-upower-device.
(battery-upower-types, battery-upower-states)
(battery-upower-device-property, battery-upower-device-autodetect):
Remove.
(battery--upower-signals): New variable.
(battery--upower-signal-handler, battery--upower-props-changed)
(battery--upower-unsubscribe, battery--upower-subsribe)
(battery--upower-state): New functions.
* test/lisp/battery-tests.el (battery-upower-state)
(battery-upower-state-unknown): New tests.
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/battery.el | 294 | ||||
| -rw-r--r-- | test/lisp/battery-tests.el | 63 |
3 files changed, 256 insertions, 111 deletions
| @@ -464,6 +464,16 @@ have now been removed. | |||
| 464 | ** Battery | 464 | ** Battery |
| 465 | 465 | ||
| 466 | --- | 466 | --- |
| 467 | *** UPower is now the default battery status backend when available. | ||
| 468 | UPower support via the function 'battery-upower' was added in Emacs | ||
| 469 | 26.1, but was disabled by default. It is now the default value of | ||
| 470 | 'battery-status-function' when the system provides a UPower D-Bus | ||
| 471 | service. The user options 'battery-upower-device' and | ||
| 472 | 'battery-upower-subscribe' control which power sources to query and | ||
| 473 | whether to respond to status change notifications in addition to | ||
| 474 | polling, respectively. | ||
| 475 | |||
| 476 | --- | ||
| 467 | *** A richer syntax can be used to format battery status information. | 477 | *** A richer syntax can be used to format battery status information. |
| 468 | The user options 'battery-mode-line-format' and | 478 | The user options 'battery-mode-line-format' and |
| 469 | 'battery-echo-area-format' now support the full formatting syntax of | 479 | 'battery-echo-area-format' now support the full formatting syntax of |
diff --git a/lisp/battery.el b/lisp/battery.el index f6f70b2f16d..e568ab52460 100644 --- a/lisp/battery.el +++ b/lisp/battery.el | |||
| @@ -44,21 +44,40 @@ | |||
| 44 | :group 'hardware) | 44 | :group 'hardware) |
| 45 | 45 | ||
| 46 | (defcustom battery-upower-device nil | 46 | (defcustom battery-upower-device nil |
| 47 | "UPower device of the `:battery' type. | 47 | "Preferred UPower device name(s). |
| 48 | Use `battery-upower-device-list' to list all available UPower devices. | 48 | When `battery-status-function' is set to `battery-upower', this |
| 49 | If set to nil, then autodetect `:battery' device." | 49 | user option specifies which power sources to query for status |
| 50 | information and merge into a single report. | ||
| 51 | |||
| 52 | When nil (the default), `battery-upower' queries all present | ||
| 53 | battery and line power devices as determined by the UPower | ||
| 54 | EnumerateDevices method. A string or a nonempty list of strings | ||
| 55 | names particular devices to query instead. UPower battery and | ||
| 56 | line power device names typically follow the patterns | ||
| 57 | \"battery_BATN\" and \"line_power_ACN\", respectively, with N | ||
| 58 | starting at 0 when present. Device names should not include the | ||
| 59 | leading D-Bus path \"/org/freedesktop/UPower/devices/\"." | ||
| 50 | :version "28.1" | 60 | :version "28.1" |
| 51 | :type '(choice string (const :tag "Autodetect" nil))) | 61 | :type '(choice (const :tag "Autodetect all devices" nil) |
| 52 | 62 | (string :tag "Device") | |
| 53 | (defcustom battery-upower-line-power-device nil | 63 | (repeat :tag "Devices" string))) |
| 54 | "UPower device of the `:line-power' type. | 64 | |
| 55 | Use `battery-upower-device-list' to list all available UPower devices. | 65 | (defcustom battery-upower-subscribe t |
| 56 | If set to nil, then autodetect `:battery' device." | 66 | "Whether to subscribe to UPower device change signals. |
| 67 | When nil, battery status information is polled every | ||
| 68 | `battery-update-interval' seconds. When non-nil (the default), | ||
| 69 | the battery status is also updated whenever a power source is | ||
| 70 | added or removed, or when the system starts or stops running on | ||
| 71 | battery power. | ||
| 72 | |||
| 73 | This only takes effect when `battery-status-function' is set to | ||
| 74 | `battery-upower' before enabling `display-battery-mode'." | ||
| 57 | :version "28.1" | 75 | :version "28.1" |
| 58 | :type '(choice string (const :tag "Autodetect" nil))) | 76 | :type 'boolean) |
| 59 | 77 | ||
| 60 | (defconst battery-upower-dbus-service "org.freedesktop.UPower" | 78 | (defconst battery-upower-service "org.freedesktop.UPower" |
| 61 | "Well-known UPower service name for the D-Bus system.") | 79 | "Well-known name of the UPower D-Bus service. |
| 80 | See URL `https://upower.freedesktop.org/docs/ref-dbus.html'.") | ||
| 62 | 81 | ||
| 63 | (defun battery--files (dir) | 82 | (defun battery--files (dir) |
| 64 | "Return a list of absolute file names in DIR or nil on error. | 83 | "Return a list of absolute file names in DIR or nil on error. |
| @@ -74,7 +93,7 @@ Value does not include \".\" or \"..\"." | |||
| 74 | (nreverse dirs))) | 93 | (nreverse dirs))) |
| 75 | 94 | ||
| 76 | (defcustom battery-status-function | 95 | (defcustom battery-status-function |
| 77 | (cond ((dbus-ping :system battery-upower-dbus-service) | 96 | (cond ((member battery-upower-service (dbus-list-activatable-names)) |
| 78 | #'battery-upower) | 97 | #'battery-upower) |
| 79 | ((and (eq system-type 'gnu/linux) | 98 | ((and (eq system-type 'gnu/linux) |
| 80 | (battery--find-linux-sysfs-batteries)) | 99 | (battery--find-linux-sysfs-batteries)) |
| @@ -219,11 +238,15 @@ seconds." | |||
| 219 | (setq battery-mode-line-string "") | 238 | (setq battery-mode-line-string "") |
| 220 | (or global-mode-string (setq global-mode-string '(""))) | 239 | (or global-mode-string (setq global-mode-string '(""))) |
| 221 | (and battery-update-timer (cancel-timer battery-update-timer)) | 240 | (and battery-update-timer (cancel-timer battery-update-timer)) |
| 241 | (battery--upower-unsubscribe) | ||
| 222 | (if (and battery-status-function battery-mode-line-format) | 242 | (if (and battery-status-function battery-mode-line-format) |
| 223 | (if (not display-battery-mode) | 243 | (if (not display-battery-mode) |
| 224 | (setq global-mode-string | 244 | (setq global-mode-string |
| 225 | (delq 'battery-mode-line-string global-mode-string)) | 245 | (delq 'battery-mode-line-string global-mode-string)) |
| 226 | (add-to-list 'global-mode-string 'battery-mode-line-string t) | 246 | (add-to-list 'global-mode-string 'battery-mode-line-string t) |
| 247 | (and (eq battery-status-function #'battery-upower) | ||
| 248 | battery-upower-subscribe | ||
| 249 | (battery--upower-subsribe)) | ||
| 227 | (setq battery-update-timer (run-at-time nil battery-update-interval | 250 | (setq battery-update-timer (run-at-time nil battery-update-interval |
| 228 | #'battery-update-handler)) | 251 | #'battery-update-handler)) |
| 229 | (battery-update)) | 252 | (battery-update)) |
| @@ -577,123 +600,172 @@ The following %-sequences are provided: | |||
| 577 | (_ "N/A")))))) | 600 | (_ "N/A")))))) |
| 578 | 601 | ||
| 579 | 602 | ||
| 580 | ;;; `upowerd' interface. | 603 | ;;; UPower interface. |
| 581 | (defconst battery-upower-dbus-interface "org.freedesktop.UPower" | 604 | |
| 582 | "The interface to UPower. | 605 | (defconst battery-upower-interface "org.freedesktop.UPower" |
| 583 | See URL `https://upower.freedesktop.org/docs/'.") | 606 | "Name of the UPower D-Bus interface. |
| 607 | See URL `https://upower.freedesktop.org/docs/UPower.html'.") | ||
| 584 | 608 | ||
| 585 | (defconst battery-upower-dbus-path "/org/freedesktop/UPower" | 609 | (defconst battery-upower-path "/org/freedesktop/UPower" |
| 586 | "D-Bus path to talk to UPower service.") | 610 | "D-Bus object providing `battery-upower-interface'.") |
| 587 | 611 | ||
| 588 | (defconst battery-upower-dbus-device-interface | 612 | (defconst battery-upower-device-interface "org.freedesktop.UPower.Device" |
| 589 | (concat battery-upower-dbus-interface ".Device") | 613 | "Name of the UPower Device D-Bus interface. |
| 590 | "The Device interface of the UPower. | ||
| 591 | See URL `https://upower.freedesktop.org/docs/Device.html'.") | 614 | See URL `https://upower.freedesktop.org/docs/Device.html'.") |
| 592 | 615 | ||
| 593 | (defconst battery-upower-dbus-device-path | 616 | (defconst battery-upower-device-path "/org/freedesktop/UPower/devices" |
| 594 | (concat battery-upower-dbus-path "/devices") | 617 | "D-Bus object providing `battery-upower-device-interface'.") |
| 595 | "D-Bus path to talk to devices part of the UPower service.") | 618 | |
| 596 | 619 | (defvar battery--upower-signals nil | |
| 597 | (defconst battery-upower-types | 620 | "Handles for UPower signal subscriptions.") |
| 598 | '((0 . :unknown) (1 . :line-power) (2 . :battery) | 621 | |
| 599 | (3 . :ups) (4 . :monitor) (5 . :mouse) | 622 | (defun battery--upower-signal-handler (&rest _) |
| 600 | (6 . :keyboard) (7 . :pda) (8 . :phone)) | 623 | "Update battery status on receiving a UPower D-Bus signal." |
| 601 | "Type of the device.") | 624 | (timer-event-handler battery-update-timer)) |
| 602 | 625 | ||
| 603 | (defconst battery-upower-states | 626 | (defun battery--upower-props-changed (_interface changed _invalidated) |
| 604 | '((0 . "unknown") (1 . "charging") (2 . "discharging") | 627 | "Update status when system starts/stops running on battery. |
| 605 | (3 . "empty") (4 . "fully-charged") (5 . "pending-charge") | 628 | Intended as a UPower PropertiesChanged signal handler." |
| 606 | (6 . "pending-discharge")) | 629 | (when (assoc "OnBattery" changed) |
| 607 | "Alist of battery power states. | 630 | (battery--upower-signal-handler))) |
| 608 | Only valid for `:battery' devices.") | 631 | |
| 609 | 632 | (defun battery--upower-unsubscribe () | |
| 610 | (defun battery-upower-device-property (device property) | 633 | "Unsubscribe from UPower device change signals." |
| 611 | "Get value of the single PROPERTY for the UPower DEVICE." | 634 | (mapc #'dbus-unregister-object battery--upower-signals) |
| 612 | (dbus-get-property | 635 | (setq battery--upower-signals ())) |
| 613 | :system battery-upower-dbus-service | 636 | |
| 614 | (expand-file-name device battery-upower-dbus-device-path) | 637 | (defun battery--upower-subsribe () |
| 615 | battery-upower-dbus-device-interface | 638 | "Subscribe to UPower device change signals." |
| 616 | property)) | 639 | (push (dbus-register-signal :system battery-upower-service |
| 617 | 640 | battery-upower-path | |
| 618 | (defun battery-upower-device-all-properties (device) | 641 | dbus-interface-properties |
| 642 | "PropertiesChanged" | ||
| 643 | #'battery--upower-props-changed) | ||
| 644 | battery--upower-signals) | ||
| 645 | (dolist (method '("DeviceAdded" "DeviceRemoved")) | ||
| 646 | (push (dbus-register-signal :system battery-upower-service | ||
| 647 | battery-upower-path | ||
| 648 | battery-upower-interface | ||
| 649 | method #'battery--upower-signal-handler) | ||
| 650 | battery--upower-signals))) | ||
| 651 | |||
| 652 | (defun battery--upower-device-properties (device) | ||
| 619 | "Return value for all available properties for the UPower DEVICE." | 653 | "Return value for all available properties for the UPower DEVICE." |
| 620 | (dbus-get-all-properties | 654 | (dbus-get-all-properties |
| 621 | :system battery-upower-dbus-service | 655 | :system battery-upower-service |
| 622 | (expand-file-name device battery-upower-dbus-device-path) | 656 | (expand-file-name device battery-upower-device-path) |
| 623 | battery-upower-dbus-device-interface)) | 657 | battery-upower-device-interface)) |
| 624 | 658 | ||
| 625 | (defun battery-upower-device-list () | 659 | (defun battery--upower-devices () |
| 626 | "Return list of all available UPower devices. | 660 | "List all UPower devices according to `battery-upower-device'." |
| 627 | Each element is the cons cell in form: (DEVICE . DEVICE-TYPE)." | 661 | (cond ((stringp battery-upower-device) |
| 628 | (mapcar (lambda (device-path) | 662 | (list battery-upower-device)) |
| 629 | (let* ((device (file-relative-name | 663 | (battery-upower-device) |
| 630 | device-path battery-upower-dbus-device-path)) | 664 | ((dbus-call-method :system battery-upower-service |
| 631 | (type-num (battery-upower-device-property device "Type"))) | 665 | battery-upower-path |
| 632 | (cons device (or (cdr (assq type-num battery-upower-types)) | 666 | battery-upower-interface |
| 633 | :unknown)))) | 667 | "EnumerateDevices")))) |
| 634 | (dbus-call-method :system battery-upower-dbus-service | 668 | |
| 635 | battery-upower-dbus-path | 669 | (defun battery--upower-state (props state) |
| 636 | battery-upower-dbus-interface | 670 | "Merge the UPower battery state in PROPS with STATE. |
| 637 | "EnumerateDevices"))) | 671 | This is an extension of the UPower DisplayDevice algorithm for |
| 638 | 672 | merging multiple battery states into one. PROPS is an alist of | |
| 639 | (defun battery-upower-device-autodetect (device-type) | 673 | battery properties from `battery-upower-device-interface', and |
| 640 | "Return first matching UPower device of DEVICE-TYPE." | 674 | STATE is a symbol representing the state to merge with." |
| 641 | (car (rassq device-type (battery-upower-device-list)))) | 675 | ;; Map UPower enum into our printable symbols. |
| 676 | (let* ((new (pcase (cdr (assoc "State" props)) | ||
| 677 | (1 'charging) | ||
| 678 | (2 'discharging) | ||
| 679 | (3 'empty) | ||
| 680 | (4 'fully-charged) | ||
| 681 | (5 'pending-charge) | ||
| 682 | (6 'pending-discharge))) | ||
| 683 | ;; Unknown state represented by nil. | ||
| 684 | (either (delq nil (list new state)))) | ||
| 685 | ;; Earlier states override later ones. | ||
| 686 | (car (cond ((memq 'charging either)) | ||
| 687 | ((memq 'discharging either)) | ||
| 688 | ((memq 'pending-charge either)) | ||
| 689 | ((memq 'pending-discharge either)) | ||
| 690 | ;; Only options left are full or empty, | ||
| 691 | ;; but if they conflict return nil. | ||
| 692 | ((null (cdr either)) either) | ||
| 693 | ((apply #'eq either) either))))) | ||
| 642 | 694 | ||
| 643 | (defun battery-upower () | 695 | (defun battery-upower () |
| 644 | "Get battery status from dbus Upower interface. | 696 | "Get battery status from UPower D-Bus interface. |
| 645 | This function works only in systems with `upowerd' daemon | 697 | This function works only in systems that provide a UPower D-Bus |
| 646 | running. | 698 | service. |
| 647 | 699 | ||
| 648 | The following %-sequences are provided: | 700 | The following %-sequences are provided: |
| 649 | %c Current capacity (mWh) | 701 | %c Current capacity (mWh) |
| 650 | %p Battery load percentage | 702 | %r Current rate of charge or discharge |
| 651 | %r Current rate | 703 | %L AC line status (verbose) |
| 652 | %B Battery status (verbose) | 704 | %B Battery status (verbose) |
| 653 | %b Battery status: empty means high, `-' means low, | 705 | %b Battery status: empty means high, `-' means low, |
| 654 | `!' means critical, and `+' means charging | 706 | `!' means critical, and `+' means charging |
| 655 | %L AC line status (verbose) | 707 | %d Temperature (in degrees Celsius) |
| 708 | %p Battery load percentage | ||
| 656 | %s Remaining time (to charge or discharge) in seconds | 709 | %s Remaining time (to charge or discharge) in seconds |
| 657 | %m Remaining time (to charge or discharge) in minutes | 710 | %m Remaining time (to charge or discharge) in minutes |
| 658 | %h Remaining time (to charge or discharge) in hours | 711 | %h Remaining time (to charge or discharge) in hours |
| 659 | %t Remaining time (to charge or discharge) in the form `h:min'" | 712 | %t Remaining time (to charge or discharge) in the form `h:min'" |
| 660 | (let* ((bat-device (or battery-upower-device | 713 | (let ((count 0) props type line-status state load temperature |
| 661 | (battery-upower-device-autodetect :battery))) | 714 | secs mins hrs total-energy total-rate total-tte total-ttf) |
| 662 | (bat-props (when bat-device | 715 | ;; Merge information from all available or specified UPower |
| 663 | (battery-upower-device-all-properties bat-device))) | 716 | ;; devices like other `battery-status-function's. |
| 664 | (percents (cdr (assoc "Percentage" bat-props))) | 717 | (dolist (device (battery--upower-devices)) |
| 665 | (time-to-empty (cdr (assoc "TimeToEmpty" bat-props))) | 718 | (setq props (battery--upower-device-properties device)) |
| 666 | (time-to-full (cdr (assoc "TimeToFull" bat-props))) | 719 | (setq type (cdr (assoc "Type" props))) |
| 667 | (state (cdr (assoc "State" bat-props))) | 720 | (cond |
| 668 | (level (cdr (assoc "BatteryLevel" bat-props))) | 721 | ((and (eq type 1) (not (eq line-status 'online))) |
| 669 | (energy (cdr (assoc "Energy" bat-props))) | 722 | ;; It's a line power device: `online' if currently providing |
| 670 | (energy-rate (cdr (assoc "EnergyRate" bat-props))) | 723 | ;; power, any other non-nil value if simply present. |
| 671 | (lp-device (or battery-upower-line-power-device | 724 | (setq line-status (if (cdr (assoc "Online" props)) 'online t))) |
| 672 | (battery-upower-device-autodetect :line-power))) | 725 | ((and (eq type 2) (cdr (assoc "IsPresent" props))) |
| 673 | (online-p (when lp-device | 726 | ;; It's a battery. |
| 674 | (battery-upower-device-property lp-device "Online"))) | 727 | (setq count (1+ count)) |
| 675 | (seconds (if online-p time-to-full time-to-empty)) | 728 | (setq state (battery--upower-state props state)) |
| 676 | (minutes (when seconds (/ seconds 60))) | 729 | (let ((energy (cdr (assoc "Energy" props))) |
| 677 | (hours (when minutes (/ minutes 60))) | 730 | (rate (cdr (assoc "EnergyRate" props))) |
| 678 | (remaining-time (when hours | 731 | (percent (cdr (assoc "Percentage" props))) |
| 679 | (format "%d:%02d" hours (mod minutes 60))))) | 732 | (temp (cdr (assoc "Temperature" props))) |
| 680 | (list (cons ?c (if energy (number-to-string (round (* 1000 energy))) "N/A")) | 733 | (tte (cdr (assoc "TimeToEmpty" props))) |
| 681 | (cons ?p (if percents (number-to-string (round percents)) "N/A")) | 734 | (ttf (cdr (assoc "TimeToFull" props)))) |
| 682 | (cons ?r (if energy-rate | 735 | (when energy (setq total-energy (+ (or total-energy 0) energy))) |
| 683 | (concat (number-to-string energy-rate) " W") | 736 | (when rate (setq total-rate (+ (or total-rate 0) rate))) |
| 737 | (when percent (setq load (+ (or load 0) percent))) | ||
| 738 | (when temp (setq temperature (+ (or temperature 0) temp))) | ||
| 739 | (when tte (setq total-tte (+ (or total-tte 0) tte))) | ||
| 740 | (when ttf (setq total-ttf (+ (or total-ttf 0) ttf))))))) | ||
| 741 | (when (> count 1) | ||
| 742 | ;; Averages over multiple batteries. | ||
| 743 | (when load (setq load (/ load count))) | ||
| 744 | (when temperature (setq temperature (/ temperature count)))) | ||
| 745 | (when (setq secs (if (eq line-status 'online) total-ttf total-tte)) | ||
| 746 | (setq mins (/ secs 60)) | ||
| 747 | (setq hrs (/ secs 3600))) | ||
| 748 | (list (cons ?c (if total-energy | ||
| 749 | (format "%.0f" (* total-energy 1000)) | ||
| 684 | "N/A")) | 750 | "N/A")) |
| 685 | (cons ?B (if state | 751 | (cons ?r (if total-rate (format "%.1f W" total-rate) "N/A")) |
| 686 | (cdr (assq state battery-upower-states)) | 752 | (cons ?L (cond ((eq line-status 'online) "on-line") |
| 687 | "unknown")) | 753 | (line-status "off-line") |
| 688 | (cons ?b (cond ((= level 3) "-") | 754 | ("N/A"))) |
| 689 | ((= level 4) "!") | 755 | (cons ?B (format "%s" (or state 'unknown))) |
| 690 | (online-p "+") | 756 | (cons ?b (cond ((eq state 'charging) "+") |
| 691 | (t ""))) | 757 | ((and load (< load battery-load-critical)) "!") |
| 692 | (cons ?L (if online-p "on-line" (if lp-device "off-line" "unknown"))) | 758 | ((and load (< load battery-load-low)) "-") |
| 693 | (cons ?s (if seconds (number-to-string seconds) "N/A")) | 759 | (""))) |
| 694 | (cons ?m (if minutes (number-to-string minutes) "N/A")) | 760 | ;; Zero usually means unknown. |
| 695 | (cons ?h (if hours (number-to-string hours) "N/A")) | 761 | (cons ?d (if (and temperature (/= temperature 0)) |
| 696 | (cons ?t (or remaining-time "N/A"))))) | 762 | (format "%.0f" temperature) |
| 763 | "N/A")) | ||
| 764 | (cons ?p (if load (format "%.0f" load) "N/A")) | ||
| 765 | (cons ?s (if secs (number-to-string secs) "N/A")) | ||
| 766 | (cons ?m (if mins (number-to-string mins) "N/A")) | ||
| 767 | (cons ?h (if hrs (number-to-string hrs) "N/A")) | ||
| 768 | (cons ?t (if hrs (format "%d:%02d" hrs (% mins 60)) "N/A"))))) | ||
| 697 | 769 | ||
| 698 | 770 | ||
| 699 | ;;; `apm' interface for BSD. | 771 | ;;; `apm' interface for BSD. |
diff --git a/test/lisp/battery-tests.el b/test/lisp/battery-tests.el index 92ab013f040..8d7cc7fccf3 100644 --- a/test/lisp/battery-tests.el +++ b/test/lisp/battery-tests.el | |||
| @@ -81,6 +81,69 @@ | |||
| 81 | (should (equal (match-string 2 str) "mWh"))) | 81 | (should (equal (match-string 2 str) "mWh"))) |
| 82 | (should-not (string-match (rx battery--acpi-capacity eos) "45 mW"))) | 82 | (should-not (string-match (rx battery--acpi-capacity eos) "45 mW"))) |
| 83 | 83 | ||
| 84 | (ert-deftest battery-upower-state () | ||
| 85 | "Test `battery--upower-state'." | ||
| 86 | ;; Charging. | ||
| 87 | (dolist (total '(nil charging discharging empty fully-charged | ||
| 88 | pending-charge pending-discharge)) | ||
| 89 | (should (eq (battery--upower-state '(("State" . 1)) total) 'charging))) | ||
| 90 | (dolist (state '(nil 0 1 2 3 4 5 6)) | ||
| 91 | (should (eq (battery--upower-state `(("State" . ,state)) 'charging) | ||
| 92 | 'charging))) | ||
| 93 | ;; Discharging. | ||
| 94 | (dolist (total '(nil discharging empty fully-charged | ||
| 95 | pending-charge pending-discharge)) | ||
| 96 | (should (eq (battery--upower-state '(("State" . 2)) total) 'discharging))) | ||
| 97 | (dolist (state '(nil 0 2 3 4 5 6)) | ||
| 98 | (should (eq (battery--upower-state `(("State" . ,state)) 'discharging) | ||
| 99 | 'discharging))) | ||
| 100 | ;; Pending charge. | ||
| 101 | (dolist (total '(nil empty fully-charged pending-charge pending-discharge)) | ||
| 102 | (should (eq (battery--upower-state '(("State" . 5)) total) | ||
| 103 | 'pending-charge))) | ||
| 104 | (dolist (state '(nil 0 3 4 5 6)) | ||
| 105 | (should (eq (battery--upower-state `(("State" . ,state)) 'pending-charge) | ||
| 106 | 'pending-charge))) | ||
| 107 | ;; Pending discharge. | ||
| 108 | (dolist (total '(nil empty fully-charged pending-discharge)) | ||
| 109 | (should (eq (battery--upower-state '(("State" . 6)) total) | ||
| 110 | 'pending-discharge))) | ||
| 111 | (dolist (state '(nil 0 3 4 6)) | ||
| 112 | (should (eq (battery--upower-state `(("State" . ,state)) 'pending-discharge) | ||
| 113 | 'pending-discharge))) | ||
| 114 | ;; Empty. | ||
| 115 | (dolist (total '(nil empty)) | ||
| 116 | (should (eq (battery--upower-state '(("State" . 3)) total) 'empty))) | ||
| 117 | (dolist (state '(nil 0 3)) | ||
| 118 | (should (eq (battery--upower-state `(("State" . ,state)) 'empty) 'empty))) | ||
| 119 | ;; Fully charged. | ||
| 120 | (dolist (total '(nil fully-charged)) | ||
| 121 | (should (eq (battery--upower-state '(("State" . 4)) total) 'fully-charged))) | ||
| 122 | (dolist (state '(nil 0 4)) | ||
| 123 | (should (eq (battery--upower-state `(("State" . ,state)) 'fully-charged) | ||
| 124 | 'fully-charged)))) | ||
| 125 | |||
| 126 | (ert-deftest battery-upower-state-unknown () | ||
| 127 | "Test `battery--upower-state' with unknown states." | ||
| 128 | ;; Unknown running total retains new state. | ||
| 129 | (should-not (battery--upower-state () nil)) | ||
| 130 | (should-not (battery--upower-state '(("State" . state)) nil)) | ||
| 131 | (should-not (battery--upower-state '(("State" . 0)) nil)) | ||
| 132 | (should (eq (battery--upower-state '(("State" . 1)) nil) 'charging)) | ||
| 133 | (should (eq (battery--upower-state '(("State" . 2)) nil) 'discharging)) | ||
| 134 | (should (eq (battery--upower-state '(("State" . 3)) nil) 'empty)) | ||
| 135 | (should (eq (battery--upower-state '(("State" . 4)) nil) 'fully-charged)) | ||
| 136 | (should (eq (battery--upower-state '(("State" . 5)) nil) 'pending-charge)) | ||
| 137 | (should (eq (battery--upower-state '(("State" . 6)) nil) 'pending-discharge)) | ||
| 138 | ;; Unknown new state retains running total. | ||
| 139 | (dolist (props '(() (("State" . state)) (("State" . 0)))) | ||
| 140 | (dolist (total '(nil charging discharging empty fully-charged | ||
| 141 | pending-charge pending-discharge)) | ||
| 142 | (should (eq (battery--upower-state props total) total)))) | ||
| 143 | ;; Conflicting empty and fully-charged. | ||
| 144 | (should-not (battery--upower-state '(("State" . 3)) 'fully-charged)) | ||
| 145 | (should-not (battery--upower-state '(("State" . 4)) 'empty))) | ||
| 146 | |||
| 84 | (ert-deftest battery-format () | 147 | (ert-deftest battery-format () |
| 85 | "Test `battery-format'." | 148 | "Test `battery-format'." |
| 86 | (should (equal (battery-format "" ()) "")) | 149 | (should (equal (battery-format "" ()) "")) |