Skip to content

Instantly share code, notes, and snippets.

@WinkelCode
Last active March 18, 2023 22:51
Show Gist options
  • Save WinkelCode/13be9bdec07f5f77a23b6181d580e6f6 to your computer and use it in GitHub Desktop.
Save WinkelCode/13be9bdec07f5f77a23b6181d580e6f6 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
if [ "$EUID" != '0' ]; then
echo "This script must be run as root"
exit 1
fi
# Or just run the parts below in the terminal as root!
mkdir -p '/var/lib/sd-battmgr/'
echo "Downloading script"
curl -fL https://gist.githubusercontent.com/WinkelCode/13be9bdec07f5f77a23b6181d580e6f6/raw/sd-battmgr.sh >'/var/lib/sd-battmgr/sd-battmgr.sh'
chmod +x '/var/lib/sd-battmgr/sd-battmgr.sh'
echo "Downloading systemd unit"
curl -fL https://gist.githubusercontent.com/WinkelCode/13be9bdec07f5f77a23b6181d580e6f6/raw/sd-battmgr.service >'/etc/systemd/system/sd-battmgr.service'
systemctl enable --now 'sd-battmgr.service'
sleep 2
systemctl status 'sd-battmgr.service'
[Unit]
Description=Steam Deck Battery Manager
[Service]
# Path to script, minimum charge, nominal charge
ExecStart='/var/lib/sd-battmgr/sd-battmgr.sh' 45 55
User=root
Restart=always
[Install]
WantedBy=multi-user.target
#!/usr/bin/env bash
set -e
batctrl_path='/usr/share/jupiter_controller_fw_updater/RA_bootloader_updater/linux_host_tools/BatCtrl'
min_charge="$1"
[[ "$min_charge" =~ ^[0-9]+$ ]] || { echo "Error: Invalid minimum charge level: '$min_charge'"; exit 1; }
nom_charge="$2"
[[ "$nom_charge" =~ ^[0-9]+$ ]] || { echo "Error: Invalid nominal charge level: '$nom_charge'"; exit 1; }
if [ "$EUID" != '0' ]; then
echo "This script must be run as root"
exit 1
fi
log() {
echo "$(date -Is) (Batt@${bat_level}%) $1"
}
sanity_checks() {
[[ "$ac_status" =~ ^[01]$ ]] || { echo "Error: Unexpected value for ACAD/online: '$ac_status'"; exit 1; }
[[ "$bat_status" =~ ^(Unknown|Charging|Discharging|Full)$ ]] || { echo "Error: Unexpected value for BAT1/status: '$bat_status'"; exit 1; }
[[ "$bat_level" =~ ^[0-9]{1,3}$ ]] || { echo "Error: Unexpected value for BAT1/capacity: '$bat_level'"; exit 1; }
}
set_batt_mode() {
case "$1" in
'charge')
if [ "$bat_status" = 'Charging' ]; then
return
fi
log "Telling BatCtrl to charge"
$batctrl_path ChargeMode 2 &>/dev/null
;;
'idle')
if [ "$bat_status" = 'Unknown' ] || [ $bat_status = 'Full' ]; then
return
fi
log "Telling BatCtrl to idle"
$batctrl_path ChargeMode 1 &>/dev/null
;;
'discharge')
if [ "$bat_status" = 'Discharging' ]; then
return
fi
log "Telling BatCtrl to discharge"
$batctrl_path ChargeMode 0 &>/dev/null
;;
esac
}
ac_loop() {
if [ "$1" == 'init' ] && [ "$ac_status" = '1' ]; then
log "AC adapter connected, starting normal operation"
elif [ "$ac_status" = '0' ]; then
log "AC adapter not connected, waiting for AC power"
while [ "$ac_status" = "0" ]; do
sleep 5
get_pwr_state aconly
done
log "AC adapter connected, resuming normal operation"
fi
}
get_pwr_state() {
if [ "$1" != 'aconly' ]; then
bat_status="$(cat /sys/class/power_supply/BAT1/status)"
bat_level="$(cat /sys/class/power_supply/BAT1/capacity)"
fi
ac_status="$(cat /sys/class/power_supply/ACAD/online)"
sanity_checks
}
# Main loop
# ---------
echo "$(date -Is) Starting battery manager with min_charge='${min_charge}%', nom_charge='${nom_charge}%'..."
get_pwr_state
ac_loop init
while true; do
get_pwr_state
ac_loop
case "$mode" in
'charge')
if [ "$bat_level" -ge "$nom_charge" ]; then
log "Battery at or above nominal charge level (>=${nom_charge}%), switching to idle mode"
mode="idle"
set_batt_mode idle
else
set_batt_mode charge
fi
;;
'idle')
if [ "$bat_level" -lt "$min_charge" ]; then
log "Battery below minimum charge level (<${min_charge}%), switching to charge mode"
mode="charge"
set_batt_mode charge
else
set_batt_mode idle
fi
;;
*)
log "Initializing charge behavior..."
if [ "$bat_level" -ge "$nom_charge" ]; then
log "Init: Found battery at or above nominal charge level (>=${nom_charge}%), starting in idle mode"
mode="idle"
set_batt_mode idle
elif [ "$bat_level" -lt "$min_charge" ]; then
log "Init: Found battery below minimum charge level (<${min_charge}%), starting in charge mode"
mode="charge"
set_batt_mode charge
else
log "Init: Found battery in normal range (=${min_charge}%-${nom_charge}%), starting in idle mode"
mode="idle"
set_batt_mode idle
fi
esac
sleep 5
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment