23
23
; ;; Commentary:
24
24
25
25
; ; There is at present support for GNU/Linux, macOS and Windows. This
26
- ; ; library supports both the `/proc/apm' file format of Linux version
27
- ; ; 1.3.58 or newer and the `/proc/acpi/' directory structure of Linux
28
- ; ; 2.4.20 and 2.6. Darwin (macOS) is supported by using the `pmset'
29
- ; ; program. Windows is supported by the GetSystemPowerStatus API call.
26
+ ; ; library supports UPower (https://upower.freedesktop.org) via D-Bus
27
+ ; ; API or the `/proc/apm' file format of Linux version 1.3.58 or newer
28
+ ; ; and the `/proc/acpi/' directory structure of Linux 2.4.20 and 2.6.
29
+ ; ; Darwin (macOS) is supported by using the `pmset' program. Windows
30
+ ; ; is supported by the GetSystemPowerStatus API call.
30
31
31
32
; ;; Code:
32
33
33
34
(require 'timer )
35
+ (require 'dbus )
34
36
(eval-when-compile (require 'cl-lib ))
35
37
36
38
(defgroup battery nil
37
39
" Display battery status information."
38
40
:prefix " battery-"
39
41
:group 'hardware )
40
42
41
- (defcustom battery-upower-device " battery_BAT1"
42
- " Upower battery device name."
43
- :version " 26.1"
44
- :type 'string
43
+ (defcustom battery-upower-device nil
44
+ " UPower device of the `:battery' type.
45
+ Use `battery-upower-device-list' to list all available UPower devices.
46
+ If set to nil, then autodetect `:battery' device."
47
+ :version " 28.1"
48
+ :type '(choice string (const :tag " Autodetect" nil ))
45
49
:group 'battery )
46
50
51
+ (defcustom battery-upower-line-power-device nil
52
+ " UPower device of the `:line-power' type.
53
+ Use `battery-upower-device-list' to list all available UPower devices.
54
+ If set to nil, then autodetect `:battery' device."
55
+ :version " 28.1"
56
+ :type '(choice string (const :tag " Autodetect" nil ))
57
+ :group 'battery )
58
+
59
+ (defconst battery-upower-dbus-service " org.freedesktop.UPower"
60
+ " Well-known UPower service name for the D-Bus system." )
61
+
47
62
(defun battery--find-linux-sysfs-batteries ()
48
63
(let ((dirs nil ))
49
64
(dolist (file (directory-files " /sys/class/power_supply/" t ))
54
69
(nreverse dirs)))
55
70
56
71
(defcustom battery-status-function
57
- (cond ((and (eq system-type 'gnu/linux )
72
+ (cond ((dbus-ping :system battery-upower-dbus-service)
73
+ #'battery-upower )
74
+ ((and (eq system-type 'gnu/linux )
58
75
(file-readable-p " /proc/apm" ))
59
76
#'battery-linux-proc-apm )
60
77
((and (eq system-type 'gnu/linux )
@@ -537,17 +554,68 @@ The following %-sequences are provided:
537
554
(t " N/A" ))))))
538
555
539
556
540
- (declare-function dbus-get-property " dbus.el"
541
- (bus service path interface property))
542
-
543
557
; ;; `upowerd' interface.
544
- (defsubst battery-upower-prop (pname &optional device )
558
+ (defconst battery-upower-dbus-interface " org.freedesktop.UPower"
559
+ " The interface to UPower.
560
+ See URL `https://upower.freedesktop.org/docs/' ." )
561
+
562
+ (defconst battery-upower-dbus-path " /org/freedesktop/UPower"
563
+ " D-Bus path to talk to UPower service." )
564
+
565
+ (defconst battery-upower-dbus-device-interface
566
+ (concat battery-upower-dbus-interface " .Device" )
567
+ " The Device interface of the UPower.
568
+ See URL `https://upower.freedesktop.org/docs/Device.html' ." )
569
+
570
+ (defconst battery-upower-dbus-device-path
571
+ (concat battery-upower-dbus-path " /devices" )
572
+ " D-Bus path to talk to devices part of the UPower service." )
573
+
574
+ (defconst battery-upower-types
575
+ '((0 . :unknown ) (1 . :line-power ) (2 . :battery )
576
+ (3 . :ups ) (4 . :monitor ) (5 . :mouse )
577
+ (6 . :keyboard ) (7 . :pda ) (8 . :phone ))
578
+ " Type of the device." )
579
+
580
+ (defconst battery-upower-states
581
+ '((0 . " unknown" ) (1 . " charging" ) (2 . " discharging" )
582
+ (3 . " empty" ) (4 . " fully-charged" ) (5 . " pending-charge" )
583
+ (6 . " pending-discharge" ))
584
+ " Alist of battery power states.
585
+ Only valid for `:battery' devices." )
586
+
587
+ (defun battery-upower-device-property (device property )
588
+ " Get value of the single PROPERTY for the UPower DEVICE."
545
589
(dbus-get-property
546
- :system
547
- " org.freedesktop.UPower"
548
- (concat " /org/freedesktop/UPower/devices/" (or device battery-upower-device))
549
- " org.freedesktop.UPower"
550
- pname))
590
+ :system battery-upower-dbus-service
591
+ (expand-file-name device battery-upower-dbus-device-path)
592
+ battery-upower-dbus-device-interface
593
+ property))
594
+
595
+ (defun battery-upower-device-all-properties (device )
596
+ " Return value for all available properties for the UPower DEVICE."
597
+ (dbus-get-all-properties
598
+ :system battery-upower-dbus-service
599
+ (expand-file-name device battery-upower-dbus-device-path)
600
+ battery-upower-dbus-device-interface))
601
+
602
+ (defun battery-upower-device-list ()
603
+ " Return list of all available UPower devices.
604
+ Each element is the cons cell in form: (DEVICE . DEVICE-TYPE)."
605
+ (mapcar (lambda (device-path )
606
+ (let* ((device (file-relative-name
607
+ device-path battery-upower-dbus-device-path))
608
+ (type-num (battery-upower-device-property device " Type" )))
609
+ (cons device (or (cdr (assq type-num battery-upower-types))
610
+ :unknown ))))
611
+ (dbus-call-method :system battery-upower-dbus-service
612
+ battery-upower-dbus-path
613
+ battery-upower-dbus-interface
614
+ " EnumerateDevices" )))
615
+
616
+ (defun battery-upower-device-autodetect (device-type )
617
+ " Return first matching UPower device of DEVICE-TYPE."
618
+ (car (rassq device-type (battery-upower-device-list))))
551
619
552
620
(defun battery-upower ()
553
621
" Get battery status from dbus Upower interface.
@@ -559,45 +627,49 @@ The following %-sequences are provided:
559
627
%p Battery load percentage
560
628
%r Current rate
561
629
%B Battery status (verbose)
630
+ %b Battery status: empty means high, `-' means low,
631
+ `!' means critical, and `+' means charging
562
632
%L AC line status (verbose)
563
633
%s Remaining time (to charge or discharge) in seconds
564
634
%m Remaining time (to charge or discharge) in minutes
565
635
%h Remaining time (to charge or discharge) in hours
566
636
%t Remaining time (to charge or discharge) in the form `h:min' "
567
- (let ((percents (battery-upower-prop " Percentage" ))
568
- (time-to-empty (battery-upower-prop " TimeToEmpty" ))
569
- (time-to-full (battery-upower-prop " TimeToFull" ))
570
- (state (battery-upower-prop " State" ))
571
- (online (battery-upower-prop " Online" " line_power_ACAD" ))
572
- (energy (battery-upower-prop " Energy" ))
573
- (energy-rate (battery-upower-prop " EnergyRate" ))
574
- (battery-states '((0 . " unknown" ) (1 . " charging" )
575
- (2 . " discharging" ) (3 . " empty" )
576
- (4 . " fully-charged" ) (5 . " pending-charge" )
577
- (6 . " pending-discharge" )))
578
- seconds minutes hours remaining-time)
579
- (cond ((and online time-to-full)
580
- (setq seconds time-to-full))
581
- ((and (not online) time-to-empty)
582
- (setq seconds time-to-empty)))
583
- (when seconds
584
- (setq minutes (/ seconds 60 )
585
- hours (/ minutes 60 )
586
- remaining-time (format " %d :%0 2d" hours (mod minutes 60 ))))
587
- (list (cons ?c (or (and energy
588
- (number-to-string (round (* 1000 energy))))
589
- " N/A" ))
590
- (cons ?p (or (and percents (number-to-string (round percents)))
591
- " N/A" ))
592
- (cons ?r (or (and energy-rate
593
- (concat (number-to-string energy-rate) " W" ))
594
- " N/A" ))
595
- (cons ?B (or (and state (cdr (assoc state battery-states)))
596
- " unknown" ))
597
- (cons ?L (or (and online " on-line" ) " off-line" ))
598
- (cons ?s (or (and seconds (number-to-string seconds)) " N/A" ))
599
- (cons ?m (or (and minutes (number-to-string minutes)) " N/A" ))
600
- (cons ?h (or (and hours (number-to-string hours)) " N/A" ))
637
+ (let* ((bat-device (or battery-upower-device
638
+ (battery-upower-device-autodetect :battery )))
639
+ (bat-props (when bat-device
640
+ (battery-upower-device-all-properties bat-device)))
641
+ (percents (cdr (assoc " Percentage" bat-props)))
642
+ (time-to-empty (cdr (assoc " TimeToEmpty" bat-props)))
643
+ (time-to-full (cdr (assoc " TimeToFull" bat-props)))
644
+ (state (cdr (assoc " State" bat-props)))
645
+ (level (cdr (assoc " BatteryLevel" bat-props)))
646
+ (energy (cdr (assoc " Energy" bat-props)))
647
+ (energy-rate (cdr (assoc " EnergyRate" bat-props)))
648
+ (lp-device (or battery-upower-line-power-device
649
+ (battery-upower-device-autodetect :line-power )))
650
+ (online-p (when lp-device
651
+ (battery-upower-device-property lp-device " Online" )))
652
+ (seconds (if online-p time-to-full time-to-empty))
653
+ (minutes (when seconds (/ seconds 60 )))
654
+ (hours (when minutes (/ minutes 60 )))
655
+ (remaining-time (when hours
656
+ (format " %d :%0 2d" hours (mod minutes 60 )))))
657
+ (list (cons ?c (if energy (number-to-string (round (* 1000 energy))) " N/A" ))
658
+ (cons ?p (if percents (number-to-string (round percents)) " N/A" ))
659
+ (cons ?r (if energy-rate
660
+ (concat (number-to-string energy-rate) " W" )
661
+ " N/A" ))
662
+ (cons ?B (if state
663
+ (cdr (assq state battery-upower-states))
664
+ " unknown" ))
665
+ (cons ?b (cond ((= level 3 ) " -" )
666
+ ((= level 4 ) " !" )
667
+ (online-p " +" )
668
+ (t " " )))
669
+ (cons ?L (if online-p " on-line" (if lp-device " off-line" " unknown" )))
670
+ (cons ?s (if seconds (number-to-string seconds) " N/A" ))
671
+ (cons ?m (if minutes (number-to-string minutes) " N/A" ))
672
+ (cons ?h (if hours (number-to-string hours) " N/A" ))
601
673
(cons ?t (or remaining-time " N/A" )))))
602
674
603
675
0 commit comments