Перейти к содержимому

Уведомления о батарее

Когда работаешь за внешним монитором с закрытой крышкой, легко не заметить, что зарядка отвалилась — и через час ноутбук уйдёт в сон. Решается одним скриптом.

Скрипт ~/bin/notifly-battery:

#!/usr/bin/env bash
set -eu
set -a; source ~/.notifly.env; set +a
LEVEL=$(cat /sys/class/power_supply/BAT0/capacity)
STATUS=$(cat /sys/class/power_supply/BAT0/status)
STATE_FILE=/tmp/notifly-battery.state
PREV=$(cat "$STATE_FILE" 2>/dev/null || echo "Full:100")
PREV_STATUS="${PREV%%:*}"
PREV_LEVEL="${PREV##*:}"
send() {
~/bin/notifly-send "$1" "$2" "$3"
}
# Низкий заряд (только если разряжается).
if [[ "$STATUS" == "Discharging" ]]; then
if (( LEVEL <= 5 )) && (( PREV_LEVEL > 5 )); then send "🪫 Батарея 5%" "Срочно подключайте зарядку!" 9; fi
if (( LEVEL <= 15 )) && (( PREV_LEVEL > 15 )); then send "🔋 Батарея 15%" "Скоро понадобится зарядка." 6; fi
if (( LEVEL <= 30 )) && (( PREV_LEVEL > 30 )); then send "🔋 Батарея 30%" "Заряд снижается." 3; fi
fi
# Смена статуса AC (отвалился/подключили блок питания).
if [[ "$STATUS" != "$PREV_STATUS" ]]; then
case "$STATUS" in
Discharging) send "⚡ Зарядка отключена" "Текущий уровень: ${LEVEL}%" 5 ;;
Charging) send "🔌 Зарядка подключена" "Текущий уровень: ${LEVEL}%" 2 ;;
Full) send "✅ Батарея 100%" "Можно отключать." 3 ;;
esac
fi
echo "$STATUS:$LEVEL" > "$STATE_FILE"

Делаем исполняемым и заводим systemd-таймер на каждые 60 секунд:

~/.config/systemd/user/notifly-battery.service
[Unit]
Description=Notifly battery check
[Service]
Type=oneshot
ExecStart=%h/bin/notifly-battery
~/.config/systemd/user/notifly-battery.timer
[Unit]
Description=Run notifly-battery every minute
[Timer]
OnBootSec=2min
OnUnitActiveSec=60s
[Install]
WantedBy=timers.target
Окно терминала
systemctl --user daemon-reload
systemctl --user enable --now notifly-battery.timer
~/bin/notifly-battery
#!/usr/bin/env bash
set -eu; set -a; source ~/.notifly.env; set +a
LEVEL=$(pmset -g batt | grep -Eo "[0-9]+%" | head -1 | tr -d '%')
SRC=$(pmset -g batt | head -1 | grep -Eo "AC|Battery")
STATE=/tmp/notifly-battery.state
PREV=$(cat "$STATE" 2>/dev/null || echo "AC:100")
# ... та же логика, что и для Linux
echo "$SRC:$LEVEL" > "$STATE"

~/Library/LaunchAgents/com.notifly.battery.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key> <string>com.notifly.battery</string>
<key>ProgramArguments</key> <array><string>/Users/you/bin/notifly-battery</string></array>
<key>StartInterval</key> <integer>60</integer>
</dict>
</plist>

launchctl load ~/Library/LaunchAgents/com.notifly.battery.plist.

C:\scripts\Notifly-Battery.ps1
$ErrorActionPreference = "Stop"
$cfg = Get-Content "$env:USERPROFILE\.notifly.json" | ConvertFrom-Json
$bat = (Get-CimInstance Win32_Battery)
$level = $bat.EstimatedChargeRemaining
$onBattery = ($bat.BatteryStatus -eq 1)
$state = "$env:TEMP\notifly-bat.txt"
$prev = if (Test-Path $state) { Get-Content $state } else { "AC:100" }
$prevLevel = [int]($prev.Split(":")[1])
function Send($title, $msg, $pri) {
Invoke-RestMethod -Method Post -Uri "$($cfg.url)/message?token=$($cfg.token)" `
-ContentType "application/json" `
-Body (@{ title = $title; message = $msg; priority = $pri } | ConvertTo-Json)
}
if ($onBattery) {
if ($level -le 5 -and $prevLevel -gt 5) { Send "🪫 Батарея 5%" "СРОЧНО!" 9 }
if ($level -le 15 -and $prevLevel -gt 15) { Send "🔋 Батарея 15%" "Подключите зарядку." 6 }
}
"$(if($onBattery){'BAT'}else{'AC'}):$level" | Set-Content $state

В Task Scheduler — запуск каждую минуту от вашего пользователя.

  • Не «убьёте» рабочий день случайным разрядом.
  • Знаете, когда блок питания отвалился — не нужно дёргать ноутбук, чтобы посмотреть индикатор.
  • На приоритете 9 push приходит даже в DND.
  • Прикладывать в сообщение оценку оставшегося времени (pmset -g batt, upower -i).
  • Раздельные скрипты для лэптопа и для UPS компьютера.