Detailed battery status is now presented in a dialogue. Quick battery status should actually work now.
This commit is contained in:
@@ -132,7 +132,8 @@ In Panel Mode, single keypresses launch different information panels:
|
||||
| `s` | Show system information |
|
||||
| `r` | Open reminder panel |
|
||||
| `n` | Launch notes application |
|
||||
| `b` | Open bluetooth. *requires blueman be installed at the time of your i3 config generation* |
|
||||
| `b` | Open Bluetooth *(requires blueman during i3 config generation)* |
|
||||
| `@MODKEY@` + `b` | Speak a quick battery status |
|
||||
| `Shift` + `b` | Show detailed battery information |
|
||||
| `m` | Launch password manager |
|
||||
| `p` | Show power options |
|
||||
@@ -150,7 +151,10 @@ The system information panel (`s` key in Panel Mode) displays vital system stati
|
||||
- Memory usage
|
||||
- Disk space
|
||||
- Network status
|
||||
- Battery level (if applicable)
|
||||
|
||||
### Battery Information
|
||||
|
||||
The battery report has two modes. Press `@MODKEY@` + `b` in Panel Mode for a concise spoken announcement of charge level and charging state. Press `Shift` + `b` in Panel Mode for the detailed report, shown in a reviewable text dialog instead of spoken aloud, so the full details can be navigated with the arrow keys: charge, status, health, chemistry, voltage, current, power draw, and cycle count when the hardware exposes them. The quick report is also available with `Alt` + `b` in Ratpoison Mode. If `acpi` is installed it is used for the report, otherwise I38 reads `/sys/class/power_supply` directly. In the detailed dialog, press `Control` + `Home` to jump back to the top of the text.
|
||||
|
||||
### Weather Panel
|
||||
|
||||
|
||||
@@ -116,6 +116,19 @@ You can apply the same configuration to GTK2 apps. Create or edit ~/.gtkrc-2.0
|
||||
- -x: Generate ~/.xinitrc and ~/.xprofile.
|
||||
- -X: Generate ~/.xprofile only.
|
||||
|
||||
## Dependency Helpers
|
||||
|
||||
Distro-specific dependency helpers live in `extra/`. On Arch Linux, run:
|
||||
|
||||
```bash
|
||||
extra/arch-linux.sh
|
||||
```
|
||||
|
||||
The helper checks I38's required packages, asks which missing provider
|
||||
applications to install, adds lightweight optional feature packages, then
|
||||
installs the selected package list at the end. Optional packages that need
|
||||
manual choice, such as Tesseract language data, are skipped.
|
||||
|
||||
## Development
|
||||
|
||||
Enable the tracked pre-commit hooks once after cloning:
|
||||
|
||||
@@ -1360,6 +1360,9 @@ $(if command -v blueman-manager &> /dev/null ; then
|
||||
echo "bindsym b exec --no-startup-id blueman-manager, mode \"default\""
|
||||
fi)
|
||||
|
||||
# Quick battery status bound to the configured mod key+b
|
||||
bindsym \$mod+b exec --no-startup-id ${i3Path}/scripts/battery_status.sh, mode "default"
|
||||
|
||||
# Detailed battery information bound to Shift+b
|
||||
bindsym Shift+b exec --no-startup-id ${i3Path}/scripts/battery_status.sh --detailed, mode "default"
|
||||
|
||||
|
||||
+138
-157
@@ -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 $?
|
||||
|
||||
Reference in New Issue
Block a user