Уведомления о батарее
Когда работаешь за внешним монитором с закрытой крышкой, легко не заметить, что зарядка отвалилась — и через час ноутбук уйдёт в сон. Решается одним скриптом.
Linux: системный таймер
Заголовок раздела «Linux: системный таймер»Скрипт ~/bin/notifly-battery:
#!/usr/bin/env bashset -euset -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.statePREV=$(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; fifi
# Смена статуса AC (отвалился/подключили блок питания).if [[ "$STATUS" != "$PREV_STATUS" ]]; then case "$STATUS" in Discharging) send "⚡ Зарядка отключена" "Текущий уровень: ${LEVEL}%" 5 ;; Charging) send "🔌 Зарядка подключена" "Текущий уровень: ${LEVEL}%" 2 ;; Full) send "✅ Батарея 100%" "Можно отключать." 3 ;; esacfi
echo "$STATUS:$LEVEL" > "$STATE_FILE"Делаем исполняемым и заводим systemd-таймер на каждые 60 секунд:
[Unit]Description=Notifly battery check
[Service]Type=oneshotExecStart=%h/bin/notifly-battery[Unit]Description=Run notifly-battery every minute
[Timer]OnBootSec=2minOnUnitActiveSec=60s
[Install]WantedBy=timers.targetsystemctl --user daemon-reloadsystemctl --user enable --now notifly-battery.timermacOS: launchd + pmset
Заголовок раздела «macOS: launchd + pmset»#!/usr/bin/env bashset -eu; set -a; source ~/.notifly.env; set +aLEVEL=$(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.statePREV=$(cat "$STATE" 2>/dev/null || echo "AC:100")# ... та же логика, что и для Linuxecho "$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.
Windows: PowerShell + Task Scheduler
Заголовок раздела «Windows: PowerShell + Task Scheduler»$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 компьютера.