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 |
|
| `s` | Show system information |
|
||||||
| `r` | Open reminder panel |
|
| `r` | Open reminder panel |
|
||||||
| `n` | Launch notes application |
|
| `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 |
|
| `Shift` + `b` | Show detailed battery information |
|
||||||
| `m` | Launch password manager |
|
| `m` | Launch password manager |
|
||||||
| `p` | Show power options |
|
| `p` | Show power options |
|
||||||
@@ -150,7 +151,10 @@ The system information panel (`s` key in Panel Mode) displays vital system stati
|
|||||||
- Memory usage
|
- Memory usage
|
||||||
- Disk space
|
- Disk space
|
||||||
- Network status
|
- 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
|
### 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 ~/.xinitrc and ~/.xprofile.
|
||||||
- -X: Generate ~/.xprofile only.
|
- -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
|
## Development
|
||||||
|
|
||||||
Enable the tracked pre-commit hooks once after cloning:
|
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\""
|
echo "bindsym b exec --no-startup-id blueman-manager, mode \"default\""
|
||||||
fi)
|
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
|
# Detailed battery information bound to Shift+b
|
||||||
bindsym Shift+b exec --no-startup-id ${i3Path}/scripts/battery_status.sh --detailed, mode "default"
|
bindsym Shift+b exec --no-startup-id ${i3Path}/scripts/battery_status.sh --detailed, mode "default"
|
||||||
|
|
||||||
|
|||||||
+123
-142
@@ -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/>.
|
# 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
|
# Parse command line arguments
|
||||||
detailedMode=0
|
detailedMode=0
|
||||||
if [[ "$1" == "-d" ]] || [[ "$1" == "--detailed" ]]; then
|
if [[ "$1" == "-d" ]] || [[ "$1" == "--detailed" ]]; then
|
||||||
detailedMode=1
|
detailedMode=1
|
||||||
fi
|
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() {
|
get_battery_details() {
|
||||||
local batteryPath="$1"
|
local batteryPath="$1"
|
||||||
local batteryName="${batteryPath##*/}"
|
local batteryName="${batteryPath##*/}"
|
||||||
local modelName=""
|
local modelName
|
||||||
local manufacturer=""
|
local manufacturer
|
||||||
local capacity=""
|
local capacity
|
||||||
local status=""
|
local status
|
||||||
local health=""
|
local health
|
||||||
local cycleCount=""
|
local cycleCount
|
||||||
local technology=""
|
local technology
|
||||||
local voltage=""
|
local voltage
|
||||||
local current=""
|
local current
|
||||||
local power=""
|
local power
|
||||||
|
local deviceName
|
||||||
local output=""
|
local output=""
|
||||||
|
|
||||||
# Get model name if available
|
modelName="$(read_attribute "${batteryPath}/model_name")"
|
||||||
if [[ -f "${batteryPath}/model_name" ]]; then
|
manufacturer="$(read_attribute "${batteryPath}/manufacturer")"
|
||||||
modelName="$(cat "${batteryPath}/model_name" 2>/dev/null | tr -d '\n')"
|
capacity="$(read_attribute "${batteryPath}/capacity")"
|
||||||
fi
|
status="$(read_attribute "${batteryPath}/status")"
|
||||||
|
health="$(read_attribute "${batteryPath}/capacity_level")"
|
||||||
|
cycleCount="$(read_attribute "${batteryPath}/cycle_count")"
|
||||||
|
technology="$(read_attribute "${batteryPath}/technology")"
|
||||||
|
|
||||||
# Get manufacturer if available
|
# Voltage (microvolts -> volts)
|
||||||
if [[ -f "${batteryPath}/manufacturer" ]]; then
|
|
||||||
manufacturer="$(cat "${batteryPath}/manufacturer" 2>/dev/null | tr -d '\n')"
|
|
||||||
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
|
local voltageUv
|
||||||
voltageUv="$(cat "${batteryPath}/voltage_now" 2>/dev/null | tr -d '\n')"
|
voltageUv="$(read_attribute "${batteryPath}/voltage_now")"
|
||||||
if [[ -n "$voltageUv" ]] && [[ "$voltageUv" =~ ^[0-9]+$ ]]; then
|
if [[ -n "$voltageUv" ]] && [[ "$voltageUv" =~ ^[0-9]+$ ]]; then
|
||||||
voltage="$(awk "BEGIN {printf \"%.2f\", $voltageUv/1000000}")"
|
voltage="$(awk "BEGIN {printf \"%.2f\", $voltageUv/1000000}")"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Get current (in microamps, convert to amps)
|
# Current (microamps -> amps)
|
||||||
if [[ -f "${batteryPath}/current_now" ]]; then
|
|
||||||
local currentUa
|
local currentUa
|
||||||
currentUa="$(cat "${batteryPath}/current_now" 2>/dev/null | tr -d '\n')"
|
currentUa="$(read_attribute "${batteryPath}/current_now")"
|
||||||
if [[ -n "$currentUa" ]] && [[ "$currentUa" =~ ^[0-9]+$ ]]; then
|
if [[ -n "$currentUa" ]] && [[ "$currentUa" =~ ^[0-9]+$ ]]; then
|
||||||
current="$(awk "BEGIN {printf \"%.2f\", $currentUa/1000000}")"
|
current="$(awk "BEGIN {printf \"%.2f\", $currentUa/1000000}")"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Get power (in microwatts, convert to watts)
|
# Power (microwatts -> watts)
|
||||||
if [[ -f "${batteryPath}/power_now" ]]; then
|
|
||||||
local powerUw
|
local powerUw
|
||||||
powerUw="$(cat "${batteryPath}/power_now" 2>/dev/null | tr -d '\n')"
|
powerUw="$(read_attribute "${batteryPath}/power_now")"
|
||||||
if [[ -n "$powerUw" ]] && [[ "$powerUw" =~ ^[0-9]+$ ]]; then
|
if [[ -n "$powerUw" ]] && [[ "$powerUw" =~ ^[0-9]+$ ]]; then
|
||||||
power="$(awk "BEGIN {printf \"%.2f\", $powerUw/1000000}")"
|
power="$(awk "BEGIN {printf \"%.2f\", $powerUw/1000000}")"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
|
|
||||||
# Build readable device name
|
# Build readable device name
|
||||||
local deviceName="$batteryName"
|
|
||||||
if [[ -n "$manufacturer" ]] && [[ -n "$modelName" ]]; then
|
if [[ -n "$manufacturer" ]] && [[ -n "$modelName" ]]; then
|
||||||
deviceName="$manufacturer $modelName"
|
deviceName="$manufacturer $modelName"
|
||||||
elif [[ -n "$modelName" ]]; then
|
elif [[ -n "$modelName" ]]; then
|
||||||
@@ -102,116 +82,117 @@ get_battery_details() {
|
|||||||
elif [[ -n "$manufacturer" ]]; then
|
elif [[ -n "$manufacturer" ]]; then
|
||||||
deviceName="$manufacturer Battery"
|
deviceName="$manufacturer Battery"
|
||||||
else
|
else
|
||||||
# Try to make the battery name more readable
|
|
||||||
deviceName="${batteryName//BAT/Battery }"
|
deviceName="${batteryName//BAT/Battery }"
|
||||||
deviceName="${deviceName//hid-/}"
|
deviceName="${deviceName//hid-/}"
|
||||||
deviceName="${deviceName//_/ }"
|
deviceName="${deviceName//_/ }"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Build the output string
|
|
||||||
output="$deviceName"
|
output="$deviceName"
|
||||||
|
[[ -n "$capacity" ]] && output="${output}"$'\n'"Charge: ${capacity}%"
|
||||||
if [[ -n "$capacity" ]]; then
|
[[ -n "$status" ]] && output="${output}"$'\n'"Status: ${status,,}"
|
||||||
output="$output, ${capacity}%"
|
[[ -n "$health" ]] && output="${output}"$'\n'"Health: ${health,,}"
|
||||||
fi
|
[[ -n "$technology" ]] && output="${output}"$'\n'"Type: $technology"
|
||||||
|
[[ -n "$voltage" ]] && output="${output}"$'\n'"Voltage: ${voltage} V"
|
||||||
if [[ -n "$status" ]]; then
|
[[ -n "$current" ]] && output="${output}"$'\n'"Current: ${current} A"
|
||||||
output="$output, ${status,,}"
|
[[ -n "$power" ]] && output="${output}"$'\n'"Power: ${power} W"
|
||||||
fi
|
[[ -n "$cycleCount" ]] && output="${output}"$'\n'"Cycles: $cycleCount"
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
echo "$output"
|
echo "$output"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Simple battery status (default mode)
|
# Concise one-line report for the simple spoken announcement.
|
||||||
get_battery_simple() {
|
get_battery_simple() {
|
||||||
local batteryPath="$1"
|
local batteryPath="$1"
|
||||||
local bat="${batteryPath##*/}"
|
local batteryName="${batteryPath##*/}"
|
||||||
bat="${bat//BAT/Battery }"
|
local status
|
||||||
bat="${bat}: $( { cat "${batteryPath}/status";echo -n ", "; cat "${batteryPath}/capacity"; } | tr -d \\n) percent."
|
local capacity
|
||||||
echo "$bat"
|
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
|
if [[ $detailedMode -eq 1 ]]; then
|
||||||
# Detailed mode
|
# Detailed mode: show the full report in a reviewable yad text-info dialog.
|
||||||
if command -v acpi &> /dev/null; then
|
batteryInfoText=""
|
||||||
# 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
|
|
||||||
batteryCount=0
|
batteryCount=0
|
||||||
batteryOutput=""
|
|
||||||
|
|
||||||
while IFS= read -r batteryPath; do
|
# Append a non-empty battery block, separating batteries with a blank line.
|
||||||
if [[ -e "${batteryPath}/capacity" ]] || [[ -e "${batteryPath}/status" ]]; then
|
add_battery_block() {
|
||||||
batteryDetails="$(get_battery_details "$batteryPath")"
|
local block="$1"
|
||||||
|
[[ -z "$block" ]] && return
|
||||||
|
batteryCount=$((batteryCount + 1))
|
||||||
|
if [[ -n "$batteryInfoText" ]]; then
|
||||||
|
batteryInfoText="${batteryInfoText}"$'\n\n'
|
||||||
|
fi
|
||||||
|
batteryInfoText="${batteryInfoText}${block}"
|
||||||
|
}
|
||||||
|
|
||||||
if [[ -n "$batteryDetails" ]]; then
|
# Prefer acpi -V, fall back to /sys/class/power_supply.
|
||||||
((batteryCount++))
|
if command -v acpi &> /dev/null; then
|
||||||
if [[ -n "$batteryOutput" ]]; then
|
acpiInfo=""
|
||||||
batteryOutput="${batteryOutput}. "
|
while IFS= read -r line; do
|
||||||
|
[[ -z "$line" ]] && continue
|
||||||
|
if [[ -n "$acpiInfo" ]]; then
|
||||||
|
acpiInfo="${acpiInfo}"$'\n'
|
||||||
fi
|
fi
|
||||||
batteryOutput="${batteryOutput}${batteryDetails}"
|
acpiInfo="${acpiInfo}${line}"
|
||||||
|
done < <(acpi -V 2>/dev/null | grep -i battery)
|
||||||
|
add_battery_block "$acpiInfo"
|
||||||
fi
|
fi
|
||||||
fi
|
|
||||||
done < <(find /sys/class/power_supply -type l 2>/dev/null)
|
|
||||||
|
|
||||||
if [[ $batteryCount -eq 0 ]]; then
|
if [[ $batteryCount -eq 0 ]]; then
|
||||||
spd-say -P important -Cw "No battery information available"
|
while IFS= read -r batteryPath; do
|
||||||
else
|
if [[ -e "${batteryPath}/capacity" ]] || [[ -e "${batteryPath}/status" ]]; then
|
||||||
spd-say -P important -Cw "$batteryOutput"
|
add_battery_block "$(get_battery_details "$batteryPath")"
|
||||||
fi
|
fi
|
||||||
else
|
done < <(find /sys/class/power_supply -type l 2>/dev/null)
|
||||||
# Simple mode (default)
|
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
|
if command -v acpi &> /dev/null; then
|
||||||
bat="$(acpi -b)"
|
announcement="$(acpi -b 2>/dev/null)"
|
||||||
spd-say -P important -Cw "$bat"
|
|
||||||
else
|
else
|
||||||
find /sys/class/power_supply -type l -exec bash -c '
|
while IFS= read -r batteryPath; do
|
||||||
for i ; do
|
if [[ -e "${batteryPath}/capacity" ]]; then
|
||||||
if [[ -e "$i/capacity" ]]; then
|
block="$(get_battery_simple "$batteryPath")"
|
||||||
bat="${i##*/}"
|
[[ -n "$block" ]] && announcement="${announcement:+$announcement. }$block"
|
||||||
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
|
fi
|
||||||
done
|
done < <(find /sys/class/power_supply -type l 2>/dev/null)
|
||||||
' _ {} \;
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -z "$announcement" ]]; then
|
||||||
|
announcement="No battery information available."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
spd-say -P important -Cw "$announcement"
|
||||||
|
exit $?
|
||||||
|
|||||||
Reference in New Issue
Block a user