Detailed battery status is now presented in a dialogue. Quick battery status should actually work now.

This commit is contained in:
Storm Dragon
2026-06-21 23:28:49 -04:00
parent 65a03eb441
commit d3fb549fd1
4 changed files with 160 additions and 159 deletions
+138 -157
View File
@@ -10,91 +10,71 @@
# 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 modelName
local manufacturer
local capacity
local status
local health
local cycleCount
local technology
local voltage
local current
local power
local deviceName
local output=""
# Get model name if available
if [[ -f "${batteryPath}/model_name" ]]; then
modelName="$(cat "${batteryPath}/model_name" 2>/dev/null | tr -d '\n')"
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
# Get manufacturer if available
if [[ -f "${batteryPath}/manufacturer" ]]; then
manufacturer="$(cat "${batteryPath}/manufacturer" 2>/dev/null | tr -d '\n')"
# 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
# Get capacity (charge percentage)
if [[ -f "${batteryPath}/capacity" ]]; then
capacity="$(cat "${batteryPath}/capacity" 2>/dev/null | tr -d '\n')"
fi
# Get status (Charging, Discharging, Full, etc.)
if [[ -f "${batteryPath}/status" ]]; then
status="$(cat "${batteryPath}/status" 2>/dev/null | tr -d '\n')"
fi
# Get health/capacity level if available
if [[ -f "${batteryPath}/capacity_level" ]]; then
health="$(cat "${batteryPath}/capacity_level" 2>/dev/null | tr -d '\n')"
fi
# Get cycle count if available
if [[ -f "${batteryPath}/cycle_count" ]]; then
cycleCount="$(cat "${batteryPath}/cycle_count" 2>/dev/null | tr -d '\n')"
fi
# Get technology (Li-ion, Li-poly, etc.)
if [[ -f "${batteryPath}/technology" ]]; then
technology="$(cat "${batteryPath}/technology" 2>/dev/null | tr -d '\n')"
fi
# Get voltage (in microvolts, convert to volts)
if [[ -f "${batteryPath}/voltage_now" ]]; then
local voltageUv
voltageUv="$(cat "${batteryPath}/voltage_now" 2>/dev/null | tr -d '\n')"
if [[ -n "$voltageUv" ]] && [[ "$voltageUv" =~ ^[0-9]+$ ]]; then
voltage="$(awk "BEGIN {printf \"%.2f\", $voltageUv/1000000}")"
fi
fi
# Get current (in microamps, convert to amps)
if [[ -f "${batteryPath}/current_now" ]]; then
local currentUa
currentUa="$(cat "${batteryPath}/current_now" 2>/dev/null | tr -d '\n')"
if [[ -n "$currentUa" ]] && [[ "$currentUa" =~ ^[0-9]+$ ]]; then
current="$(awk "BEGIN {printf \"%.2f\", $currentUa/1000000}")"
fi
fi
# Get power (in microwatts, convert to watts)
if [[ -f "${batteryPath}/power_now" ]]; then
local powerUw
powerUw="$(cat "${batteryPath}/power_now" 2>/dev/null | tr -d '\n')"
if [[ -n "$powerUw" ]] && [[ "$powerUw" =~ ^[0-9]+$ ]]; then
power="$(awk "BEGIN {printf \"%.2f\", $powerUw/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
local deviceName="$batteryName"
if [[ -n "$manufacturer" ]] && [[ -n "$modelName" ]]; then
deviceName="$manufacturer $modelName"
elif [[ -n "$modelName" ]]; then
@@ -102,116 +82,117 @@ get_battery_details() {
elif [[ -n "$manufacturer" ]]; then
deviceName="$manufacturer Battery"
else
# Try to make the battery name more readable
deviceName="${batteryName//BAT/Battery }"
deviceName="${deviceName//hid-/}"
deviceName="${deviceName//_/ }"
fi
# Build the output string
output="$deviceName"
if [[ -n "$capacity" ]]; then
output="$output, ${capacity}%"
fi
if [[ -n "$status" ]]; then
output="$output, ${status,,}"
fi
if [[ -n "$health" ]]; then
output="$output, health: ${health,,}"
fi
if [[ -n "$technology" ]]; then
output="$output, type: $technology"
fi
if [[ -n "$voltage" ]]; then
output="$output, voltage: ${voltage}V"
fi
if [[ -n "$current" ]]; then
output="$output, current: ${current}A"
fi
if [[ -n "$power" ]]; then
output="$output, power: ${power}W"
fi
if [[ -n "$cycleCount" ]]; then
output="$output, cycles: $cycleCount"
fi
[[ -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"
}
# Simple battery status (default mode)
# Concise one-line report for the simple spoken announcement.
get_battery_simple() {
local batteryPath="$1"
local bat="${batteryPath##*/}"
bat="${bat//BAT/Battery }"
bat="${bat}: $( { cat "${batteryPath}/status";echo -n ", "; cat "${batteryPath}/capacity"; } | tr -d \\n) percent."
echo "$bat"
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
}
# Main script
if [[ $detailedMode -eq 1 ]]; then
# Detailed mode
if command -v acpi &> /dev/null; then
# Try acpi first for more detailed info
batteryInfo=""
while IFS= read -r line; do
if [[ -n "$batteryInfo" ]]; then
batteryInfo="${batteryInfo}. "
fi
batteryInfo="${batteryInfo}${line}"
done < <(acpi -V 2>/dev/null | grep -i battery)
if [[ -n "$batteryInfo" ]]; then
spd-say -P important -Cw "$batteryInfo"
exit 0
fi
fi
# Fallback to /sys/class/power_supply for detailed info
# Detailed mode: show the full report in a reviewable yad text-info dialog.
batteryInfoText=""
batteryCount=0
batteryOutput=""
while IFS= read -r batteryPath; do
if [[ -e "${batteryPath}/capacity" ]] || [[ -e "${batteryPath}/status" ]]; then
batteryDetails="$(get_battery_details "$batteryPath")"
if [[ -n "$batteryDetails" ]]; then
((batteryCount++))
if [[ -n "$batteryOutput" ]]; then
batteryOutput="${batteryOutput}. "
fi
batteryOutput="${batteryOutput}${batteryDetails}"
fi
# 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
done < <(find /sys/class/power_supply -type l 2>/dev/null)
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
spd-say -P important -Cw "No battery information available"
else
spd-say -P important -Cw "$batteryOutput"
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
else
# Simple mode (default)
if command -v acpi &> /dev/null; then
bat="$(acpi -b)"
spd-say -P important -Cw "$bat"
else
find /sys/class/power_supply -type l -exec bash -c '
for i ; do
if [[ -e "$i/capacity" ]]; then
bat="${i##*/}"
bat="${bat//BAT/Battery }"
bat="${bat}: $( { cat "${i}/status";echo -n ", "; cat "${i}/capacity"; } | tr -d \\n) percent."
spd-say -P important -Cw "$bat"
fi
done
' _ {} \;
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 $?