From 0ae11ae6c9e805da7daae09d40e67c3fd5546612 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Tue, 22 Aug 2023 16:04:25 +0200 Subject: [PATCH 01/12] Battery calibration --- battery.sh | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/battery.sh b/battery.sh index cd09d1c..4bc61a0 100755 --- a/battery.sh +++ b/battery.sh @@ -65,6 +65,9 @@ Usage: manually set the adapter to (not) charge even when plugged in eg: battery adapter off + battery calibrate + battery calibration + battery charge LEVEL[1-100] charge the battery to a certain percentage, and disable charging when that percentage is reached eg: battery charge 90 @@ -568,3 +571,36 @@ if [[ "$action" == "logs" ]]; then exit 0 fi + +# Battery calibration +if [[ "$action" == "calibrate" ]]; then + log "Starting calibration" + + # Stop the maintaining + battery maintain stop + + # Discharge battery to 15% + battery discharge 15 + + while true; do + log "checking if at 100%" + # Check if battery level has reached 100% + if battery status | head -n 1 | grep -q "Battery at 100%"; then + break + else + sleep 300 + continue + fi + done + + # Wait before discharging to target level + log "reached 100%, maintaining for 1 hour" + sleep 3600 + + # Discharge battery to 80% + battery discharge 80 + + # Maintain battery to 80% + battery maintain 80 + exit 0 +fi \ No newline at end of file From 62e783ad9f126bbd237a0dc595e8545cb34a29bb Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Thu, 24 Aug 2023 18:17:15 +0200 Subject: [PATCH 02/12] Addedd comment --- battery.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/battery.sh b/battery.sh index 4bc61a0..f44225f 100755 --- a/battery.sh +++ b/battery.sh @@ -66,7 +66,7 @@ Usage: eg: battery adapter off battery calibrate - battery calibration + calibrate the battery by discharding it to 15%, then recharging it to 100%, and keeping it there for 1 hour battery charge LEVEL[1-100] charge the battery to a certain percentage, and disable charging when that percentage is reached From 58ab5aaf77780b857c9fc32f82b2c0af7cd85296 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sat, 26 Aug 2023 17:01:24 +0200 Subject: [PATCH 03/12] Calibration process checking with pid --- .DS_Store | Bin 0 -> 6148 bytes battery.sh | 97 +++++++++++++++++++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 33 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..8444e48e3a60bdd22617ec589c6cc7a5c15ad92b GIT binary patch literal 6148 zcmeHK%WB&|6ulF>u^gx1MGM&!1l=0fNlhVi8d?D|GNUbc1tv-2~CD^Vf`M#)BK}MO~OR^^K@cX`A>fm zM`_k-{SsTH@}2F9Q*mm}2k%VIy=Yi|KX#j z$D{N3B9ULU=mOs)Wp@o;!Z$R`Y(9I_B$ml1jBxZelt^)flu^2-#}D}PdhC#o=nPj# zQ~E+p@Xm@H@nDU!OFeo;FX@DiX-Hjqjn)wTXKOru!u-9;6i|fx*;?H1wYUmBN4_2n zkkg|c`t$V?%Cj6qvZ6D* zWt&vW$5&NkpwtboWw1VZ2D;X6tbkb`PVL4_ORx%91#Y_n{C#jy7&``68r7!*l{x|d z%NSOMw)*)8x;y~v7+h(@2ux@yP*a6DVhD3~5Sk8u$HcERYB~vZXXG(=7UqN^%+W)* zDx5?|qpht1R)L}dCEcy_{y*4!{x6bj&njRQxK#>>a^LHBF(tFNUYQ*4wJyp>6gG}q nX;c(cW;<35-ir57l)>k61K2UR(ufh5{Si/dev/null fi + if test -f "$calibrate_pidfile"; then + pid=$(cat "$calibrate_pidfile" 2>/dev/null) + log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + fi + if [[ "$setting" == "stop" ]]; then log "Killing running maintain daemons & enabling charging as default state" rm $pidfile 2>/dev/null @@ -523,6 +529,64 @@ if [[ "$action" == "maintain" ]]; then fi +# Battery calibration +if [[ "$action" == "calibrate_synchronous" ]]; then + log "Starting calibration" + + # Stop the maintaining + battery maintain stop + + # Discharge battery to 15% + battery discharge 15 + + while true; do + log "checking if at 100%" + # Check if battery level has reached 100% + if battery status | head -n 1 | grep -q "Battery at 100%"; then + break + else + sleep 300 + continue + fi + done + + # Wait before discharging to target level + log "reached 100%, maintaining for 1 hour" + sleep 3600 + + # Discharge battery to 80% + battery discharge 80 + + # Maintain battery to 80% + battery maintain 80 + exit 0 +fi + +# Asynchronous battery level maintenance +if [[ "$action" == "calibrate" ]]; then + # Kill old process silently + if test -f "$calibrate_pidfile"; then + pid=$(cat "$calibrate_pidfile" 2>/dev/null) + kill $pid &>/dev/null + fi + + if [[ "$setting" == "stop" ]]; then + log "Killing running calibration daemon" + kill $calibrate_pidfile &>/dev/null + rm $calibrate_pidfile 2>/dev/null + + exit 0 + fi + + # Start calibration script + log "Starting calibration script" + nohup ./battery.sh calibrate_synchronous >>$logfile & + + # Store pid of calibration process and setting + echo $! >$calibrate_pidfile + pid=$(cat "$calibrate_pidfile" 2>/dev/null) +fi + # Status logger if [[ "$action" == "status" ]]; then @@ -635,37 +699,4 @@ if [[ "$action" == "logs" ]]; then exit 0 -fi - -# Battery calibration -if [[ "$action" == "calibrate" ]]; then - log "Starting calibration" - - # Stop the maintaining - battery maintain stop - - # Discharge battery to 15% - battery discharge 15 - - while true; do - log "checking if at 100%" - # Check if battery level has reached 100% - if battery status | head -n 1 | grep -q "Battery at 100%"; then - break - else - sleep 300 - continue - fi - done - - # Wait before discharging to target level - log "reached 100%, maintaining for 1 hour" - sleep 3600 - - # Discharge battery to 80% - battery discharge 80 - - # Maintain battery to 80% - battery maintain 80 - exit 0 fi \ No newline at end of file From e723d7945e54cdbe936c636eec6e3821955f815f Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sat, 26 Aug 2023 17:05:00 +0200 Subject: [PATCH 04/12] Checking also in synch process --- battery.sh | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/battery.sh b/battery.sh index 2a5f99f..c648834 100755 --- a/battery.sh +++ b/battery.sh @@ -410,6 +410,12 @@ fi # Maintain at level if [[ "$action" == "maintain_synchronous" ]]; then + + # Checking if the calibration process is running + if test -f "$calibrate_pidfile"; then + pid=$(cat "$calibrate_pidfile" 2>/dev/null) + log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + fi # Recover old maintain status if old setting is found if [[ "$setting" == "recover" ]]; then @@ -580,7 +586,7 @@ if [[ "$action" == "calibrate" ]]; then # Start calibration script log "Starting calibration script" - nohup ./battery.sh calibrate_synchronous >>$logfile & + nohup battery calibrate_synchronous >>$logfile & # Store pid of calibration process and setting echo $! >$calibrate_pidfile From f257b9d9dc5d223efffe3a2c01dbf0c5cca5baf4 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 27 Aug 2023 14:32:24 +0200 Subject: [PATCH 05/12] Maintain recover at the and of calibration --- battery.sh | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/battery.sh b/battery.sh index c648834..832ace9 100755 --- a/battery.sh +++ b/battery.sh @@ -560,11 +560,8 @@ if [[ "$action" == "calibrate_synchronous" ]]; then log "reached 100%, maintaining for 1 hour" sleep 3600 - # Discharge battery to 80% - battery discharge 80 - - # Maintain battery to 80% - battery maintain 80 + # Recover old maintain status + battery maintain recover exit 0 fi From 4777260f9acad2f18e4d47dc150e096bb73063e6 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 27 Aug 2023 16:54:10 +0200 Subject: [PATCH 06/12] The battery need to be discharged before maint. --- battery.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/battery.sh b/battery.sh index 832ace9..7929977 100755 --- a/battery.sh +++ b/battery.sh @@ -560,7 +560,10 @@ if [[ "$action" == "calibrate_synchronous" ]]; then log "reached 100%, maintaining for 1 hour" sleep 3600 - # Recover old maintain status + # Discharge battery to 80% + battery discharge 80 + + # Maintain battery to 80% battery maintain recover exit 0 fi From 3c6ae140d4c3d0684da5e5e44ee1f60936039728 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 27 Aug 2023 16:55:50 +0200 Subject: [PATCH 07/12] changed comment --- battery.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/battery.sh b/battery.sh index 7929977..a1696c5 100755 --- a/battery.sh +++ b/battery.sh @@ -563,7 +563,7 @@ if [[ "$action" == "calibrate_synchronous" ]]; then # Discharge battery to 80% battery discharge 80 - # Maintain battery to 80% + # Recover old maintain status battery maintain recover exit 0 fi From 5883bbe70c4dbdd070734a06cec6f11a44a1d8fd Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Wed, 17 Jan 2024 12:55:57 +0100 Subject: [PATCH 08/12] Style Fix --- .DS_Store | Bin 6148 -> 6148 bytes .vscode/settings.json | 2 +- app/.DS_Store | Bin 0 -> 6148 bytes battery.sh | 170 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 164 insertions(+), 8 deletions(-) create mode 100644 app/.DS_Store diff --git a/.DS_Store b/.DS_Store index 8444e48e3a60bdd22617ec589c6cc7a5c15ad92b..74a78db103bc6f056aec745b79a5a7660681a3ba 100644 GIT binary patch delta 175 zcmZoMXfc@J&&aniU^g=(-((&ZYsPJpJy;4=#j2|fbQFwDjB0fhsx6IxY!fq++FDKy zQDuGWp!n>Z+`Rmb$q!iM89OJj-V|kFNMXoiC}t>0DlaZb%E?b+U|=B8AjwXk9=JJW Z!9{sF`FZI;F~-f;SbZ5cvvd6A2LR5PFz5gP delta 64 zcmV-G0Kfl)FoZCWPXP?EP`d*G43i85I{~

;-WO7<+p$IW#OFGcc3E1RMd1lima$ W0gIFV1lhB_21)^ufaJ3W2>lP1Fcu>K diff --git a/.vscode/settings.json b/.vscode/settings.json index 2296389..febebe8 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -10,7 +10,7 @@ "typescriptreact" ], "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" }, "editor.renderWhitespace": "all", "editor.formatOnSave": true, diff --git a/app/.DS_Store b/app/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..563238f6823579c4bf57edf8e2132df4f400eabe GIT binary patch literal 6148 zcmeHK&2G~`5S~rb#vvdD2@n?~OI%9`C8~tDn2;VgaH$a-00p~_T2t2>#SS?{k$eR4 z4t<5*c$B_NPw>s|R@hB)r4`z-X203pnO*Pa{qYi!=ue|(L~SB+pp5lfNLC2fvo1-^ zlyIC-ZRC`_N#sG8$Z*Nq7FY%>12>HUUb|ZqP=;qj)%DAp!YgR!w-WX0n-tQNVoE3~ zt#tN0Tkjdpva#6{eud*C&hl>eT+}w|n_CU1;k2C3{*j#dd5}-DelYpSxpz_~;iVmf z@8i*I*uM8#rg;#jqlpTLqY+#_eTdUY&iZniMwyEBb%oP(n#1;k`MkUBKJV=;w%z%Q z9oW6y-eS>o?mvF|a({T7oTT!*8XF1hVoL59yo4VxN+bW~PtruDhbZNU)?ZF&NJk{` z99MQi@FO0|JPQZIiDRt=UlK0OQ-jX74pWr){cUf-x;)?fO8l&w4yhT8V@PC3R zsq(5X*lG3a)p#uBx4V6%g*9<%ew>!(N0atx52XWo3+!NwtL8~L0v%hq76#00cUsrd zyY196U>Uf{4DkNoLK!`Sg+{e?AW>HUU>(IuVDrxa$G8SPgM~)aK!gqj>QG^>7($1m z+% 13.0 have a native charge threshold that +# does not required any userspace daemon running. +# This native limit works even when the laptop is sleeping or powered off therefore +# it is preferable to the userspace daemon. +# Nonetheless, it only works with fixed thresholds (80% as upper limit and 70% as +# lower limit). +# +# Thanks to @marcan for the implementation details in the Asahi Linux kernel: +# https://github.com/AsahiLinux/linux/commit/107ed86e21d1522d5d5d9d629f1d9c371e37df7f#diff-6b2c1b57b60e2829a9973ea707f596a3ff85fa787eca5d6d3b8ac79ebdd0381cR453 +# https://oftc.irclog.whitequark.org/asahi-dev/2023-04-18#32076880 + +# CHWA key is the one used to enable/disable the native limit. 01 = 80% limit, 00 = no limit +chwa_key="$( sudo smc -r -k CHWA | grep -q "no data" && echo "unavailable" || echo "available" )" + +function enable_native_limit() { + log " Enabling native limit at 80%" + sudo smc -k CHWA -w 01 +} + +function disable_native_limit() { + log " Disabling native limit" + sudo smc -k CHWA -w 00 +} +function get_native_limit_status() { + if [[ "$chwa_key" == "unavailable" ]]; then + echo "disabled" + else + hex_status=$( smc -k CHWA -r | awk '{print $4}' | sed s:\):: ) + if [[ "$hex_status" == "00" ]]; then + echo "disabled" + else + echo "enabled" + fi + fi +} + +function get_native_limit() { + if [[ "$(get_native_limit_status)" == "enabled" ]]; then + echo "80" + else + echo "" + fi +} + +# both the daemon and the native limit can be set at the same time so this function +# returns the lowest of the two. +# When both are set, the daemonic limit is the one that is used while the mac is awake +# and the native limit is the one that is used when the mac is sleeping or powered off. +function get_actual_limit() { + native=$( get_native_limit ) + daemon=$( get_maintain_percentage ) + + # if both are set, return the lowest + if [[ ! -z "$native" ]] && [[ ! -z "$daemon" ]]; then + if [[ "$native" -lt "$daemon" ]]; then + echo "$native" + else + echo "$daemon" + fi + # if only one is set, return that one + elif [[ ! -z "$native" ]]; then + echo "$native" + elif [[ ! -z "$daemon" ]]; then + echo "$daemon" + else + # if neither is set, return nothing + echo "" + fi +} + + function get_smc_charging_status() { hex_status=$(smc -k CH0B -r | awk '{print $4}' | sed s:\)::) if [[ "$hex_status" == "00" ]]; then @@ -433,6 +510,41 @@ if [[ "$action" == "maintain_synchronous" ]]; then fi fi + # if maintain percentage is 80 and CHWA is available, exit. This daemon is not needed. + # This condition could happen in some rare cases, for example when the daemon is started before + # updating the tool or before CHWA is available. + if [[ "$chwa_key" == "available" ]]; then + if [[ "$setting" == "80" ]]; then + log "Skipping daemon start as CHWA is available and maintain percentage is $setting" + # Disable daemon + battery maintain stop + battery disable_daemon + # Activate the native limit in case this is the first restart after the update of MacOs + # or of this tool + if [[ "$( get_native_limit_status )" == "disabled" ]]; then + enable_native_limit + fi + exit 0 + else + # If $setting is below 80 activate the native charging limiter as a mixed strategy. At + # least during sleep it will get as high as 80%, closer to the desired $setting than 100%. + if [[ "$setting" -lt "80" ]]; then + log "Using mixed limiter (daemon: $setting% / native: 80%)" + if [[ "$( get_native_limit_status )" == "disabled" ]]; then + enable_native_limit + fi + else + # Disabling native charging limiter if the limit > 80% as it would interfere with + # the daemon. + if [[ "$( get_native_limit_status )" == "enabled" ]]; then + disable_native_limit + fi + fi + + + fi + fi + # Check if the user requested that the battery maintenance first discharge to the desired level if [[ "$subsetting" == "--force-discharge" ]]; then # Before we start maintaining the battery level, first discharge to the target level @@ -514,6 +626,23 @@ if [[ "$action" == "maintain" ]]; then fi + # Use CHWA method if available an 80% is used (it's the only level supported by CHWA) + if [[ "$chwa_key" == "available" ]]; then + if [[ "$setting" == "80" ]]; then + if test -f "$pidfile"; then + kill_daemon + battery disable_daemon + log "Killing and disabling daemon as native limiter is available" + fi + enable_native_limit + exit 0 + else + log "Native charging limiter is available but only supports 80% limit. Consider using 80% because it works even during sleep." + fi + fi + + kill_daemon + # Start maintenance script log "Starting battery maintenance at $setting% $subsetting" nohup battery maintain_synchronous $setting $subsetting >>$logfile & @@ -548,9 +677,10 @@ if [[ "$action" == "calibrate_synchronous" ]]; then while true; do log "checking if at 100%" # Check if battery level has reached 100% - if battery status | head -n 1 | grep -q "Battery at 100%"; then + if battery status | head -n 1 | grep -q "Battery at 100%"; + then break - else + else sleep 300 continue fi @@ -595,11 +725,37 @@ fi # Status logger if [[ "$action" == "status" ]]; then + daemon_limit=$( get_maintain_percentage ) + native_limit=$( get_native_limit ) + actual_limit=$( get_actual_limit ) - log "Battery at $(get_battery_percentage)% ($(get_remaining_time) remaining), smc charging $(get_smc_charging_status)" - if test -f $pidfile; then - maintain_percentage=$(cat $maintain_percentage_tracker_file 2>/dev/null) - log "Your battery is currently being maintained at $maintain_percentage%" + log "Battery at $( get_battery_percentage )% ($( get_remaining_time ) remaining), smc charging $( get_smc_charging_status )" + + if [[ ! -z "$actual_limit" ]]; then + limit_status="Battery maintenance is set to $actual_limit%" + # if both daemon and native limiters are enabled, show both as: " using mixed daemon/native limiter. While your mac is awake the limit will be $setting% and during sleep it will be $native_limit%." + if [[ ! -z "$daemon_limit" ]] && [[ ! -z "$native_limit" ]]; then + limit_status="$limit_status using mixed daemon/native limiter ($daemon_limit% while your mac is awake / $native_limit% during sleep)." + elif [[ ! -z "$native_limit" ]]; then + limit_status="$limit_status using native limiter." + elif [[ ! -z "$daemon_limit" ]]; then + limit_status="$limit_status using daemon limiter (only works while your mac is awake)." + else + limit_status="$limit_status." + fi + + + if [[ "$chwa_key" == "available" ]] && [[ ! -z "$daemon_limit" ]]; then + limit_status="$limit_status Consider using native limit of 80% instead of $daemon_limit% to improve battery health." + fi + fi + + if [[ "$chwa_key" != "available" ]]; then + limit_status="$limit_status Consider upgrading to macOS to enable native battery limiter. It works even during sleep." + fi + + if [[ ! -z "$limit_status" ]]; then + log "$limit_status" fi exit 0 From 6021aa9d497fa5118a0ef61baca8fd42e1e02a04 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Wed, 17 Jan 2024 16:23:44 +0100 Subject: [PATCH 09/12] Calibration Stop --- battery.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/battery.sh b/battery.sh index 4c2a50f..74c26e6 100755 --- a/battery.sh +++ b/battery.sh @@ -491,7 +491,8 @@ if [[ "$action" == "maintain_synchronous" ]]; then # Checking if the calibration process is running if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + battery calibrate stop + log "🚨 Calibration was running, now the calibration process have been Stopped" fi # Recover old maintain status if old setting is found @@ -601,7 +602,8 @@ if [[ "$action" == "maintain" ]]; then if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + battery calibrate stop + log "🚨 Calibration was running, now the calibration process have been Stopped" fi if [[ "$setting" == "stop" ]]; then From 13159c75f72da8a3f8c9687d6c9d61a60e289c5c Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 21 Jan 2024 00:50:22 +0100 Subject: [PATCH 10/12] Recovered Right files --- battery.sh | 184 ++++------------------------------------------------- 1 file changed, 13 insertions(+), 171 deletions(-) diff --git a/battery.sh b/battery.sh index 74c26e6..a1696c5 100755 --- a/battery.sh +++ b/battery.sh @@ -4,10 +4,10 @@ ## Update management ## variables are used by this binary as well at the update script ## ############### -BATTERY_CLI_VERSION="v1.1.6" +BATTERY_CLI_VERSION="v1.1.5" # Path fixes for unexpected environments -PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew/bin:/opt/homebrew/sbin:/opt/homebrew +PATH=/bin:/usr/bin:/usr/local/bin:/usr/sbin:/opt/homebrew ## ############### ## Variables @@ -67,7 +67,7 @@ Usage: eg: battery adapter off battery calibrate - calibrate the battery by discharging it to 15%, then recharging it to 100%, and keeping it there for 1 hour + calibrate the battery by discharding it to 15%, then recharging it to 100%, and keeping it there for 1 hour battery charge LEVEL[1-100] charge the battery to a certain percentage, and disable charging when that percentage is reached @@ -101,17 +101,11 @@ Cmnd_Alias BATTERYON = $binfolder/smc -k CH0B -w 00, $binfolder/smc -k CH0C Cmnd_Alias DISCHARGEOFF = $binfolder/smc -k CH0I -w 00, $binfolder/smc -k CH0I -r Cmnd_Alias DISCHARGEON = $binfolder/smc -k CH0I -w 01 Cmnd_Alias LEDCONTROL = $binfolder/smc -k ACLC -w 04, $binfolder/smc -k ACLC -w 03, $binfolder/smc -k ACLC -w 00, $binfolder/smc -k ACLC -r -Cmnd_Alias NATIVELIMITOFF = $binfolder/smc -k CHWA -w 00 -Cmnd_Alias NATIVELIMITON = $binfolder/smc -k CHWA -w 01 -Cmnd_Alias NATIVELIMITREAD = $binfolder/smc -k CHWA -r ALL ALL = NOPASSWD: BATTERYOFF ALL ALL = NOPASSWD: BATTERYON ALL ALL = NOPASSWD: DISCHARGEOFF ALL ALL = NOPASSWD: DISCHARGEON ALL ALL = NOPASSWD: LEDCONTROL -ALL ALL = NOPASSWD: NATIVELIMITOFF -ALL ALL = NOPASSWD: NATIVELIMITON -ALL ALL = NOPASSWD: NATIVELIMITREAD " # Get parameters @@ -182,77 +176,6 @@ function disable_charging() { sudo smc -k CH0C -w 02 } -# Apple Silicon laptops with firmware > 13.0 have a native charge threshold that -# does not required any userspace daemon running. -# This native limit works even when the laptop is sleeping or powered off therefore -# it is preferable to the userspace daemon. -# Nonetheless, it only works with fixed thresholds (80% as upper limit and 70% as -# lower limit). -# -# Thanks to @marcan for the implementation details in the Asahi Linux kernel: -# https://github.com/AsahiLinux/linux/commit/107ed86e21d1522d5d5d9d629f1d9c371e37df7f#diff-6b2c1b57b60e2829a9973ea707f596a3ff85fa787eca5d6d3b8ac79ebdd0381cR453 -# https://oftc.irclog.whitequark.org/asahi-dev/2023-04-18#32076880 - -# CHWA key is the one used to enable/disable the native limit. 01 = 80% limit, 00 = no limit -chwa_key="$( sudo smc -r -k CHWA | grep -q "no data" && echo "unavailable" || echo "available" )" - -function enable_native_limit() { - log " Enabling native limit at 80%" - sudo smc -k CHWA -w 01 -} - -function disable_native_limit() { - log " Disabling native limit" - sudo smc -k CHWA -w 00 -} -function get_native_limit_status() { - if [[ "$chwa_key" == "unavailable" ]]; then - echo "disabled" - else - hex_status=$( smc -k CHWA -r | awk '{print $4}' | sed s:\):: ) - if [[ "$hex_status" == "00" ]]; then - echo "disabled" - else - echo "enabled" - fi - fi -} - -function get_native_limit() { - if [[ "$(get_native_limit_status)" == "enabled" ]]; then - echo "80" - else - echo "" - fi -} - -# both the daemon and the native limit can be set at the same time so this function -# returns the lowest of the two. -# When both are set, the daemonic limit is the one that is used while the mac is awake -# and the native limit is the one that is used when the mac is sleeping or powered off. -function get_actual_limit() { - native=$( get_native_limit ) - daemon=$( get_maintain_percentage ) - - # if both are set, return the lowest - if [[ ! -z "$native" ]] && [[ ! -z "$daemon" ]]; then - if [[ "$native" -lt "$daemon" ]]; then - echo "$native" - else - echo "$daemon" - fi - # if only one is set, return that one - elif [[ ! -z "$native" ]]; then - echo "$native" - elif [[ ! -z "$daemon" ]]; then - echo "$daemon" - else - # if neither is set, return nothing - echo "" - fi -} - - function get_smc_charging_status() { hex_status=$(smc -k CH0B -r | awk '{print $4}' | sed s:\)::) if [[ "$hex_status" == "00" ]]; then @@ -424,9 +347,9 @@ if [[ "$action" == "adapter" ]]; then # Set charging to on and off if [[ "$setting" == "on" ]]; then - disable_discharging - elif [[ "$setting" == "off" ]]; then enable_discharging + elif [[ "$setting" == "off" ]]; then + disable_discharging fi exit 0 @@ -491,8 +414,7 @@ if [[ "$action" == "maintain_synchronous" ]]; then # Checking if the calibration process is running if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - battery calibrate stop - log "🚨 Calibration was running, now the calibration process have been Stopped" + log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" fi # Recover old maintain status if old setting is found @@ -511,41 +433,6 @@ if [[ "$action" == "maintain_synchronous" ]]; then fi fi - # if maintain percentage is 80 and CHWA is available, exit. This daemon is not needed. - # This condition could happen in some rare cases, for example when the daemon is started before - # updating the tool or before CHWA is available. - if [[ "$chwa_key" == "available" ]]; then - if [[ "$setting" == "80" ]]; then - log "Skipping daemon start as CHWA is available and maintain percentage is $setting" - # Disable daemon - battery maintain stop - battery disable_daemon - # Activate the native limit in case this is the first restart after the update of MacOs - # or of this tool - if [[ "$( get_native_limit_status )" == "disabled" ]]; then - enable_native_limit - fi - exit 0 - else - # If $setting is below 80 activate the native charging limiter as a mixed strategy. At - # least during sleep it will get as high as 80%, closer to the desired $setting than 100%. - if [[ "$setting" -lt "80" ]]; then - log "Using mixed limiter (daemon: $setting% / native: 80%)" - if [[ "$( get_native_limit_status )" == "disabled" ]]; then - enable_native_limit - fi - else - # Disabling native charging limiter if the limit > 80% as it would interfere with - # the daemon. - if [[ "$( get_native_limit_status )" == "enabled" ]]; then - disable_native_limit - fi - fi - - - fi - fi - # Check if the user requested that the battery maintenance first discharge to the desired level if [[ "$subsetting" == "--force-discharge" ]]; then # Before we start maintaining the battery level, first discharge to the target level @@ -602,8 +489,7 @@ if [[ "$action" == "maintain" ]]; then if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - battery calibrate stop - log "🚨 Calibration was running, now the calibration process have been Stopped" + log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" fi if [[ "$setting" == "stop" ]]; then @@ -628,23 +514,6 @@ if [[ "$action" == "maintain" ]]; then fi - # Use CHWA method if available an 80% is used (it's the only level supported by CHWA) - if [[ "$chwa_key" == "available" ]]; then - if [[ "$setting" == "80" ]]; then - if test -f "$pidfile"; then - kill_daemon - battery disable_daemon - log "Killing and disabling daemon as native limiter is available" - fi - enable_native_limit - exit 0 - else - log "Native charging limiter is available but only supports 80% limit. Consider using 80% because it works even during sleep." - fi - fi - - kill_daemon - # Start maintenance script log "Starting battery maintenance at $setting% $subsetting" nohup battery maintain_synchronous $setting $subsetting >>$logfile & @@ -679,10 +548,9 @@ if [[ "$action" == "calibrate_synchronous" ]]; then while true; do log "checking if at 100%" # Check if battery level has reached 100% - if battery status | head -n 1 | grep -q "Battery at 100%"; - then + if battery status | head -n 1 | grep -q "Battery at 100%"; then break - else + else sleep 300 continue fi @@ -727,37 +595,11 @@ fi # Status logger if [[ "$action" == "status" ]]; then - daemon_limit=$( get_maintain_percentage ) - native_limit=$( get_native_limit ) - actual_limit=$( get_actual_limit ) - log "Battery at $( get_battery_percentage )% ($( get_remaining_time ) remaining), smc charging $( get_smc_charging_status )" - - if [[ ! -z "$actual_limit" ]]; then - limit_status="Battery maintenance is set to $actual_limit%" - # if both daemon and native limiters are enabled, show both as: " using mixed daemon/native limiter. While your mac is awake the limit will be $setting% and during sleep it will be $native_limit%." - if [[ ! -z "$daemon_limit" ]] && [[ ! -z "$native_limit" ]]; then - limit_status="$limit_status using mixed daemon/native limiter ($daemon_limit% while your mac is awake / $native_limit% during sleep)." - elif [[ ! -z "$native_limit" ]]; then - limit_status="$limit_status using native limiter." - elif [[ ! -z "$daemon_limit" ]]; then - limit_status="$limit_status using daemon limiter (only works while your mac is awake)." - else - limit_status="$limit_status." - fi - - - if [[ "$chwa_key" == "available" ]] && [[ ! -z "$daemon_limit" ]]; then - limit_status="$limit_status Consider using native limit of 80% instead of $daemon_limit% to improve battery health." - fi - fi - - if [[ "$chwa_key" != "available" ]]; then - limit_status="$limit_status Consider upgrading to macOS to enable native battery limiter. It works even during sleep." - fi - - if [[ ! -z "$limit_status" ]]; then - log "$limit_status" + log "Battery at $(get_battery_percentage)% ($(get_remaining_time) remaining), smc charging $(get_smc_charging_status)" + if test -f $pidfile; then + maintain_percentage=$(cat $maintain_percentage_tracker_file 2>/dev/null) + log "Your battery is currently being maintained at $maintain_percentage%" fi exit 0 From 26346918797461c8e8324f3641fe992498f7c728 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 21 Jan 2024 00:52:08 +0100 Subject: [PATCH 11/12] Indentation fix --- battery.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/battery.sh b/battery.sh index a1696c5..6ed54cb 100755 --- a/battery.sh +++ b/battery.sh @@ -550,7 +550,7 @@ if [[ "$action" == "calibrate_synchronous" ]]; then # Check if battery level has reached 100% if battery status | head -n 1 | grep -q "Battery at 100%"; then break - else + else sleep 300 continue fi From acc0322d6dc373eb28b9e7407e863c4754777594 Mon Sep 17 00:00:00 2001 From: Nicola De Rosa Date: Sun, 21 Jan 2024 00:58:45 +0100 Subject: [PATCH 12/12] Fix --- battery.sh | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/battery.sh b/battery.sh index 6ed54cb..7f9df6a 100755 --- a/battery.sh +++ b/battery.sh @@ -67,7 +67,7 @@ Usage: eg: battery adapter off battery calibrate - calibrate the battery by discharding it to 15%, then recharging it to 100%, and keeping it there for 1 hour + calibrate the battery by discharging it to 15%, then recharging it to 100%, and keeping it there for 1 hour battery charge LEVEL[1-100] charge the battery to a certain percentage, and disable charging when that percentage is reached @@ -414,7 +414,8 @@ if [[ "$action" == "maintain_synchronous" ]]; then # Checking if the calibration process is running if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + kill $calibrate_pidfile &>/dev/null + log "🚨 Calibration process have been stopped" fi # Recover old maintain status if old setting is found @@ -489,7 +490,8 @@ if [[ "$action" == "maintain" ]]; then if test -f "$calibrate_pidfile"; then pid=$(cat "$calibrate_pidfile" 2>/dev/null) - log "🚨 Calibration is running, please run 'battery calibrate stop' or wait for it to finish" + kill $calibrate_pidfile &>/dev/null + log "🚨 Calibration process have been stopped" fi if [[ "$setting" == "stop" ]]; then