Draw idle as one timeline, and let the power button answer to its owner
Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
@@ -69,6 +69,53 @@ read_int() {
|
||||
printf '%s\n' "$value"
|
||||
}
|
||||
|
||||
# How much of the pack's design capacity is left, as a whole percent.
|
||||
#
|
||||
# Energy (µWh) and charge (µAh) are the two spellings of the same pair and a
|
||||
# pack has one or the other, never both worth trusting, so each is tried in the
|
||||
# order the kernel prefers. Summed across every system pack for the same reason
|
||||
# the percentage is: on a two-battery machine, one pack's wear is not the
|
||||
# machine's.
|
||||
#
|
||||
# Fails rather than guessing when the firmware exposes no design capacity,
|
||||
# which plenty does not. A health figure computed from a design capacity that
|
||||
# was itself invented is a confident number that is wrong, and this page has
|
||||
# already decided once (no time-to-empty) that it would rather say nothing.
|
||||
battery_health() {
|
||||
local dir full design total_full=0 total_design=0
|
||||
while IFS= read -r dir; do
|
||||
full="$(read_int "$dir/energy_full" || read_int "$dir/charge_full")" || continue
|
||||
design="$(read_int "$dir/energy_full_design" || read_int "$dir/charge_full_design")" || continue
|
||||
(( design > 0 )) || continue
|
||||
total_full=$(( total_full + full ))
|
||||
total_design=$(( total_design + design ))
|
||||
done < <(all_battery_dirs)
|
||||
(( total_design > 0 )) || return 1
|
||||
printf '%s\n' "$(( (total_full * 100 + total_design / 2) / total_design ))"
|
||||
}
|
||||
|
||||
# Full charge cycles, from the primary pack and then from whichever pack
|
||||
# answers.
|
||||
#
|
||||
# A reported zero is treated as "the firmware does not count", not as a battery
|
||||
# that has never been charged: a great many laptops export cycle_count as a
|
||||
# permanent 0, and "0 cycles" beside a four-year-old pack reads as a fact
|
||||
# rather than the absence of one.
|
||||
battery_cycles() {
|
||||
local primary="$1" dir value
|
||||
if [[ -n "$primary" ]] && value="$(read_int "$primary/cycle_count")" && (( value > 0 )); then
|
||||
printf '%s\n' "$value"
|
||||
return 0
|
||||
fi
|
||||
while IFS= read -r dir; do
|
||||
if value="$(read_int "$dir/cycle_count")" && (( value > 0 )); then
|
||||
printf '%s\n' "$value"
|
||||
return 0
|
||||
fi
|
||||
done < <(all_battery_dirs)
|
||||
return 1
|
||||
}
|
||||
|
||||
cmd_paths() {
|
||||
local battery mains threshold=""
|
||||
battery="$(battery_dir)" || battery=""
|
||||
@@ -87,6 +134,7 @@ cmd_paths() {
|
||||
|
||||
cmd_status() {
|
||||
local battery mains capacity="" state="Unknown" online=1 threshold=0
|
||||
local health="" cycles=""
|
||||
battery="$(battery_dir)" || battery=""
|
||||
mains="$(mains_dir)" || mains=""
|
||||
|
||||
@@ -109,16 +157,23 @@ cmd_status() {
|
||||
done
|
||||
(( total_full > 0 )) && capacity=$(( (total_now * 100 + total_full / 2) / total_full ))
|
||||
fi
|
||||
|
||||
health="$(battery_health)" || health=""
|
||||
cycles="$(battery_cycles "$battery")" || cycles=""
|
||||
fi
|
||||
if [[ -n "$mains" ]]; then
|
||||
online="$(read_int "$mains/online")" || online=0
|
||||
fi
|
||||
|
||||
printf '{"available":%s,"percent":%s,"status":"%s","acOnline":%s,"chargeLimit":%s}\n' \
|
||||
# health and cycles are JSON null when sysfs does not report them, which is
|
||||
# most desktops and a fair number of laptops. Null rather than 0: a zero
|
||||
# would render as a dead battery that has never been charged.
|
||||
printf '{"available":%s,"percent":%s,"status":"%s","acOnline":%s,"chargeLimit":%s,"healthPercent":%s,"cycleCount":%s}\n' \
|
||||
"$([[ -n "$capacity" ]] && echo true || echo false)" \
|
||||
"${capacity:-0}" "$state" \
|
||||
"$([[ "$online" == "1" ]] && echo true || echo false)" \
|
||||
"$threshold"
|
||||
"$threshold" \
|
||||
"${health:-null}" "${cycles:-null}"
|
||||
}
|
||||
|
||||
cmd_set_threshold() {
|
||||
@@ -156,7 +211,9 @@ case "${1:-status}" in
|
||||
usage: panama-battery [paths|status|set-threshold <50-100>]
|
||||
|
||||
paths JSON: which sysfs files hold the battery, mains and threshold
|
||||
status JSON: one reading of charge, state, power source and limit
|
||||
status JSON: one reading of charge, state, power source, limit,
|
||||
health against design capacity and charge cycles (the last
|
||||
two null where the firmware does not report them)
|
||||
set-threshold cap charging at N percent (asks for a password)
|
||||
USAGE
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user