あんパン

こしあん派

dunstとsystemdのtimerで端末のバッテリが減ったら通知を出す

昨晩夕飯食べずに寝落ちしてしまい、PCの電源も刺さずにつけっぱなしにしてしまった。それを忘れて朝PCを触っていたところ電源が落ちた。以前からバッテリが減っていることに気づけず困っていたので、バッテリが減っていて充電もしていなかった場合に通知を出すことにした。

f:id:masawada:20200418171950p:plain

通知にはdunstを利用しているのでこれを使う。dunstifyを利用すると任意のテキストで簡単に通知を出すことができる。

まず以下のスクリプトを適当に $PATH に含まれてるディレクトリの中に放り込む。 /sys/class/power_supply/BAT0 とか BAT1 とかでバッテリ情報が入ってるのでこれを使う。 自分の端末はThinkPad T480でフロントバッテリとリアバッテリがあるので BAT0BAT1 があった。これを実行すると、全てのバッテリの残量が10%未満かつ充電していない場合にdunstでアラートを表示できる。

#!/bin/bash

set -eu

urgency=1

for battery in $(ls /sys/class/power_supply/ | grep BAT); do
  battery_path="/sys/class/power_supply/${battery}"
  battery_capacity=$(cat ${battery_path}/capacity);
  battery_status=$(cat ${battery_path}/status);

  if [ ${battery_capacity} -ge 10 ] || [ ${battery_status} = "Charging" ]; then
    urgency=0
  fi
done

[ "${urgency}" = 1 ] && dunstify -u critical 'Low Battery!'

exit 0;

あとはこれを1分おきに実行する。いま使っているディストリビューションはArch Linuxで、デフォルトでcronは入らないしsystemdのタイマー機能を利用する。

まずはsystemdのUnitファイルを $HOME/.config/systemd/user/low-battery-notifier.service みたいな名前で保存する。/path/to/low-battery-notifier は実行ファイルを置いた場所を指定する。これで、 systemd --user start low-battery-notifier.service で通知が動いていれば問題ない。

[Unit]
Description=Notify low battery alert

[Service]
Type=oneshot
ExecStart=/path/to/low-battery-notifier

次にこれを1分おきに実行するよう設定する。以下のtimerファイルを $HOME/.config/systemd/user/low-battery-notifier.timer みたいな名前で保存する。 serviceファイルと名前を対応づけて拡張子を.timerにする必要がある。

[Unit]
Description=Notify low battery alert timer

[Timer]
OnCalendar=*-*-* *:*:00

[Install]
WantedBy=timers.target

これで systemctl --user enable low-battery-notifier.timer && systemctl --user start low-battery-notifier.timer すると1分おきに最初のスクリプトが実行されるようになる。タイマーが正常に動いているかどうかは systemctl list-timers --users --all で確認することができる。

$ systemctl list-timers --user --all
NEXT                        LEFT     LAST                        PASSED  UNIT                       ACTIVATES
Sat 2020-04-18 17:37:00 JST 20s left Sat 2020-04-18 17:36:05 JST 34s ago low-battery-notifier.timer low-battery-notifier.service

という具合。これでバッテリが減ったら1分おきに通知が出る。