Files
I38/scripts/battery_status.sh

199 lines
6.8 KiB
Bash
Executable File

#!/usr/bin/env bash
# This file is part of I38.
# I38 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation,
# either version 3 of the License, or (at your option) any later version.
# I38 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
# PURPOSE. See the GNU General Public License for more details.
# You should have received a copy of the GNU General Public License along with I38. If not, see <https://www.gnu.org/licenses/>.
# Battery status reporting.
# Simple mode (default, Panel Mode mod+b): speaks a concise status as a quick
# announcement. Detailed mode (-d/--detailed, Panel Mode Shift+b): shows
# the full report in a screen reader accessible yad text-info dialog so it can
# be reviewed with the arrow keys.
# Parse command line arguments
detailedMode=0
if [[ "$1" == "-d" ]] || [[ "$1" == "--detailed" ]]; then
detailedMode=1
fi
# Read a sysfs attribute safely, stripping trailing newlines. Returns empty if
# the attribute file does not exist or cannot be read.
read_attribute() {
local path="$1"
[[ -f "$path" ]] && cat "$path" 2>/dev/null | tr -d '\n'
}
get_battery_details() {
local batteryPath="$1"
local batteryName="${batteryPath##*/}"
local modelName
local manufacturer
local capacity
local status
local health
local cycleCount
local technology
local voltage
local current
local power
local deviceName
local output=""
modelName="$(read_attribute "${batteryPath}/model_name")"
manufacturer="$(read_attribute "${batteryPath}/manufacturer")"
capacity="$(read_attribute "${batteryPath}/capacity")"
status="$(read_attribute "${batteryPath}/status")"
health="$(read_attribute "${batteryPath}/capacity_level")"
cycleCount="$(read_attribute "${batteryPath}/cycle_count")"
technology="$(read_attribute "${batteryPath}/technology")"
# Voltage (microvolts -> volts)
local voltageUv
voltageUv="$(read_attribute "${batteryPath}/voltage_now")"
if [[ -n "$voltageUv" ]] && [[ "$voltageUv" =~ ^[0-9]+$ ]]; then
voltage="$(awk "BEGIN {printf \"%.2f\", $voltageUv/1000000}")"
fi
# Current (microamps -> amps)
local currentUa
currentUa="$(read_attribute "${batteryPath}/current_now")"
if [[ -n "$currentUa" ]] && [[ "$currentUa" =~ ^[0-9]+$ ]]; then
current="$(awk "BEGIN {printf \"%.2f\", $currentUa/1000000}")"
fi
# Power (microwatts -> watts)
local powerUw
powerUw="$(read_attribute "${batteryPath}/power_now")"
if [[ -n "$powerUw" ]] && [[ "$powerUw" =~ ^[0-9]+$ ]]; then
power="$(awk "BEGIN {printf \"%.2f\", $powerUw/1000000}")"
fi
# Build readable device name
if [[ -n "$manufacturer" ]] && [[ -n "$modelName" ]]; then
deviceName="$manufacturer $modelName"
elif [[ -n "$modelName" ]]; then
deviceName="$modelName"
elif [[ -n "$manufacturer" ]]; then
deviceName="$manufacturer Battery"
else
deviceName="${batteryName//BAT/Battery }"
deviceName="${deviceName//hid-/}"
deviceName="${deviceName//_/ }"
fi
output="$deviceName"
[[ -n "$capacity" ]] && output="${output}"$'\n'"Charge: ${capacity}%"
[[ -n "$status" ]] && output="${output}"$'\n'"Status: ${status,,}"
[[ -n "$health" ]] && output="${output}"$'\n'"Health: ${health,,}"
[[ -n "$technology" ]] && output="${output}"$'\n'"Type: $technology"
[[ -n "$voltage" ]] && output="${output}"$'\n'"Voltage: ${voltage} V"
[[ -n "$current" ]] && output="${output}"$'\n'"Current: ${current} A"
[[ -n "$power" ]] && output="${output}"$'\n'"Power: ${power} W"
[[ -n "$cycleCount" ]] && output="${output}"$'\n'"Cycles: $cycleCount"
echo "$output"
}
# Concise one-line report for the simple spoken announcement.
get_battery_simple() {
local batteryPath="$1"
local batteryName="${batteryPath##*/}"
local status
local capacity
local deviceName
status="$(read_attribute "${batteryPath}/status")"
capacity="$(read_attribute "${batteryPath}/capacity")"
deviceName="${batteryName//BAT/Battery }"
if [[ -n "$status" ]] && [[ -n "$capacity" ]]; then
echo "${deviceName}: ${status,,}, ${capacity}%"
elif [[ -n "$capacity" ]]; then
echo "${deviceName}: ${capacity}%"
fi
}
if [[ $detailedMode -eq 1 ]]; then
# Detailed mode: show the full report in a reviewable yad text-info dialog.
batteryInfoText=""
batteryCount=0
# Append a non-empty battery block, separating batteries with a blank line.
add_battery_block() {
local block="$1"
[[ -z "$block" ]] && return
batteryCount=$((batteryCount + 1))
if [[ -n "$batteryInfoText" ]]; then
batteryInfoText="${batteryInfoText}"$'\n\n'
fi
batteryInfoText="${batteryInfoText}${block}"
}
# Prefer acpi -V, fall back to /sys/class/power_supply.
if command -v acpi &> /dev/null; then
acpiInfo=""
while IFS= read -r line; do
[[ -z "$line" ]] && continue
if [[ -n "$acpiInfo" ]]; then
acpiInfo="${acpiInfo}"$'\n'
fi
acpiInfo="${acpiInfo}${line}"
done < <(acpi -V 2>/dev/null | grep -i battery)
add_battery_block "$acpiInfo"
fi
if [[ $batteryCount -eq 0 ]]; then
while IFS= read -r batteryPath; do
if [[ -e "${batteryPath}/capacity" ]] || [[ -e "${batteryPath}/status" ]]; then
add_battery_block "$(get_battery_details "$batteryPath")"
fi
done < <(find /sys/class/power_supply -type l 2>/dev/null)
fi
if [[ $batteryCount -eq 0 ]]; then
batteryInfoText="No battery information available."
fi
displayText="Battery Information (Detailed)
${batteryInfoText}
End of text. Press Control+Home to return to the beginning."
echo "$displayText" | yad --pname=I38Battery \
--title="I38 Battery Information" \
--text-info \
--show-cursor \
--width=450 \
--height=400 \
--center \
--button="Close:0"
exit $?
fi
# Simple mode: speak a concise status as a quick announcement.
announcement=""
if command -v acpi &> /dev/null; then
announcement="$(acpi -b 2>/dev/null)"
else
while IFS= read -r batteryPath; do
if [[ -e "${batteryPath}/capacity" ]]; then
block="$(get_battery_simple "$batteryPath")"
[[ -n "$block" ]] && announcement="${announcement:+$announcement. }$block"
fi
done < <(find /sys/class/power_supply -type l 2>/dev/null)
fi
if [[ -z "$announcement" ]]; then
announcement="No battery information available."
fi
spd-say -P important -Cw "$announcement"
exit $?