199 lines
6.8 KiB
Bash
Executable File
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 $?
|