Contribute
Register

[RELEASE]: SleepOnLowBattery (“SOLB”)

Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
SleepOnLowBattery (“SOLB”)
by BugsB, based on a script by Toggi3 * + more code snippets from the www

For those of us whose HackBook (or even real MacBook) doesn't automatically and properly go into power saving mode on very low battery but just powers down coldly, crashing macOS: “SOLB”, a small and RAM/ CPU wise very low footprint AppleScript based utility that checks the battery level every 2 minutes, running via daemon in the background.

You can choose between two versions, either with or without sound. Both display a notification in the top right of your screen.

Between ≤10 and >8% battery charge:
1611003107953.png

Between ≤8 and >5% battery charge:
1611003137402.png


On ≤ 5% battery charge you will see a 10 seconds countdown dialog box in 1 second intervals:
1611003170691.png


1611003181402.png


which you can cancel, or have your your *ac*Book be sent to sleep when down to 0.

The version with sound uses the pleasant macOS US female voice Allison. If the lady is not installed, you can download "her" via System Preferences, Accessibility, Speech (pane tab should get opened by the install script), click onto the two arrows to the right of System Voice, Customize, English (Unites States) -- Female, activate Allison, OK (macOS downloads voices to /System/Library/Speech/Voices - Allison consumes 120 MB).

If you want to see/ see and listen first, disconnect your Mac from its power supply and double click the “run Demo” file in either folder, with or without sound.

The launcher is installed per user, so one user can use the script with and another user the script without sound.

Run your desired install.command, with or without sound. The script should be active right away without restart.

Regarding the sound version, you can also:
- download any other English voice of your liking and edit the name inside the script at the very top
- download any language voice and translate the text inside the script

Edit with Apple Script Editor, save, install, reboot.

Tested working in macOS Monterey 12.0.1 and Catalina 10.15.7.
Please feedback if this utility also works for you
.

If you have ideas, experience bugs, etc., please contribute as precise, succinct, productive and friendly as possible. In case of a bug, always include your version of macOS for me or others to try and help. Thank you.

ENJOY

VERSION HISTORY:

2021-12-17 v. 1.22
BUG FIX: {Cancel} button (to prevent sleep) had stopped working in macOS 10.15+
IMPROVEMENT: in ‘with sound/Install SOLB’ script, switched launchctl action from load to enable and from start to kickstart as per Apple’s recommendations for current versions of macOS

2021-02-21 v. 1.21
IMPROVEMENT: added macOS 10.14+ compatibility for download new voice(s).scpt

2019-12-29 v. 1.2
IMPROVEMENT: Script is now compatible with both, ACPIBatteryManager.kext and SMCBatteryManager.kext

2019-11-15 v. 1.1
BUG FIX: changed all occurrences of ExternalChargeCapable to ExternalConnected in all Apple Script .scpt files (SleepOnLowBattery.scpt, SleepOnLowBatterySound.scpt, demo.scpt) to restore functionality
IMPROVEMENT: made queries of MaxCapacity and CurrentCapacity more compatible to work with hopefully any system
NEW: added Catalina compatibility to install scripts; verified Mojave compatibility
NEW: Sound script uses voice Allison if installed, otherwise automatically defaults back to another English standard voice (Daniel, Alex or Fred)

2018-11-10 v.1.0
• initial version

IDEAS TO IMPLEMENT IN FUTURE RELEASES:
  1. Have the sound version install script check if Allison is installed, and if not, offer to download and install it.
  2. Purely cosmetic: find a way to have the display notification in the top right of the screen not display the Script Editor icon but the one of the utility without turning the utility into an app but by maintaining a script to keep the load footprint low. This is currently neither possible with an Apple Script nor with an Apple Script Bundle file, only with the script compiled into an app. One possibility might be a Perl approach, if someone volunteers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Thanks to Toggi3 for the base script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
THE CODE (of the version with sound):
Code:
#!/bin/bash
clear
Plist="Library/LaunchAgents/SleepOnLowBattery.plist"
SoundPlist="Library/LaunchAgents/SleepOnLowBatterySound.plist"
Script="/etc/SleepOnLowBattery.scpt"
SoundScript="/etc/SleepOnLowBatterySound.scpt"

#===============================================================================##
## USER ABORTS SCRIPT #
##==============================================================================##
function _clean_up() {
  printf "User aborted!"
  clear
}

#===============================================================================##
## START #
##==============================================================================##
function main()
{
if test -e $Plist; then launchctl stop SleepOnLowBattery && launchctl unload $Plist && rm -R $Plist; fi
if test -e $SoundPlist; then launchctl stop SleepOnLowBatterySound && launchctl unload $SoundPlist && rm -R $SoundPlist; fi
cd "$(dirname "$0")"
echo "Installing.."
sudo cp -R InstallerData/SleepOnLowBatterySound.scpt /etc
if test ! -d ~/Library/LaunchAgents; then mkdir ~/Library/LaunchAgents; fi
cp -R InstallerData/SleepOnLowBatterySound.plist ~/Library/LaunchAgents
sudo chmod +rx /etc/SleepOnLowBatterySound.scpt
chown -R $(whoami) ~/Library/LaunchAgents/
chmod 755 ~/Library/LaunchAgents/SleepOnLowBatterySound.plist
#chmod 604 ~/Library/LaunchAgents/SleepOnLowBatterySound.plist
#according to Apple, 'launchctl load [..].plist' is considered leagcy. Use command below instead
#launchctl load ~/Library/LaunchAgents/SleepOnLowBatterySound.plist
launchctl enable gui/501/SleepOnLowBatterySound
#according to Apple, 'launchctl start [..].plist' is considered leagcy. Use command below instead
#launchctl start SleepOnLowBatterySound
# If you pass -kp to the kickstart action, it will kill any running instance and restart it, then print out the PID of the new instance
echo
launchctl kickstart -kp gui/501/SleepOnLowBatterySound
echo
echo "..done!"
echo
echo "Now I recommend you download the pleasant Allision onto your Mac :)"
echo
read -r -p "Continuing in 3 seconds..." -t 3 -n 1 -s
echo
echo
osascript "Extras/download new voice(s).scpt"
echo
}

trap '{ _clean_up; exit 1; }' INT

if [[ `id -u` -ne 0 ]];
  then
    echo "This script must be run as ROOT!"
    sudo "$0"
  else
    main
fi

#===============================================================================##
## EOF #
##==============================================================================##
Code:
# find and set good English voice from installed voices
tell application "Finder"
    
    set targetFolder to POSIX file "/System/Library/Speech/Voices/Allison.SpeechVoice"
    if exists targetFolder then
        set voicename to "allison"
    else
        set targetFolder to POSIX file "/System/Library/Speech/Voices/Alex.SpeechVoice"
        if exists targetFolder then
            set voicename to "alex"
        else
            set targetFolder to POSIX file "/System/Library/Speech/Voices/AlexCompact.SpeechVoice"
            if exists targetFolder then
                set voicename to "alex"
            else
                set targetFolder to POSIX file "/System/Library/Speech/Voices/Daniel.SpeechVoice"
                if exists targetFolder then
                    set voicename to "daniel"
                else
                    set targetFolder to POSIX file "/System/Library/Speech/Voices/DanielCompact.SpeechVoice"
                    if exists targetFolder then
                        set voicename to "daniel"
                    else
                        set targetFolder to POSIX file "/System/Library/Speech/Voices/AllisonCompact.SpeechVoice"
                        if exists targetFolder then
                            set voicename to "allison"
                        else
                            set targetFolder to POSIX file "/System/Library/Speech/Voices/AlexCompact.SpeechVoice"
                            if exists targetFolder then
                                set voicename to "alex"
                            else
                                set targetFolder to POSIX file "/System/Library/Speech/Voices/FredCompact.SpeechVoice"
                                if exists targetFolder then
                                    set voicename to "fred"
                                end if
                            end if
                        end if
                    end if
                end if
            end if
        end if
    end if
    
end tell

set currentOutputVolume to output volume of (get volume settings)

set Cap to (do shell script "ioreg -w0 -l | grep ExternalConnected")
tell Cap to set {wallPower} to {last word}
if wallPower = "Yes" then
    -- display dialog "Connected to Power Supply!" buttons {"OK"} default button 1 giving up after 10
    return 0
else
    -- display dialog "Running on Battery!" buttons {"OK"} default button 1 giving up after 10
    set Cap to (do shell script "ioreg -wO -l | grep MaxCapacity")
    tell Cap to set {Max} to {last word}
    
    set Cap to (do shell script "ioreg -wO -l | grep CurrentCapacity")
    tell Cap to set {Current} to {last word}
    
    set Pct to round (100 * Current / Max)
    
    if Pct ≤ 10 and Pct > 8 then
        display notification "Your Mac will sleep soon unless plugged into a power outlet!" with title "LOW BATTERY!"
        set volume alert volume 80
        set volume 4
        beep 1
        say "Low battery" using voicename
        #do shell script "say -v " & voicename & " \"Low battery\" "
        set volume output volume currentOutputVolume
        
    else if Pct ≤ 8 and Pct > 5 then
        display notification "Your Mac will sleep very soon unless plugged into a power outlet!" with title "VERY LOW BATTERY!"
        set volume alert volume 80
        set volume 4
        beep 2
        say "VERY low battery" using voicename
        #do shell script "say -v " & voicename & " \"VERY low battery\" "
        set volume output volume currentOutputVolume
        
    else if Pct ≤ 5 then
        set volume alert volume 80
        set volume 5
        beep 4
        say "Battery level too low - going to sleep in 10 seconds" using voicename
        #do shell script "say -v " & voicename & " \"Battery level too low - going to sleep in 10 seconds\""
        set volume output volume currentOutputVolume
        
        set theCounter to 10
        set theInterval to 1
        repeat until theCounter is 0
            display dialog "Sending computer to sleep in " & theCounter & " seconds" as text buttons {"Cancel"} cancel button 1 giving up after theInterval
            set theCounter to theCounter - theInterval
        end repeat
        do shell script "pmset sleepnow"
    end if
end if

You encounter a problem? Please follow the Troubleshooting procedure step-by-step and report back.
 

Attachments

  • SleepOnLowBattery (SOLB) by BugsB v.1.22 (2021-12-17).zip
    256.8 KB · Views: 109
Last edited:
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
So then - do you like it? Does it work for you ;) ?
 
Joined
Jan 27, 2019
Messages
9
Motherboard
N/A
CPU
Intel Core i7 4700HQ
Graphics
Intel Graphics 4600 HD
I tested it on Mojave. It attempts to sleep at 4% then wakes up again after few seconds :/
 
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
I tested it on Mojave. It attempts to sleep at 4% then wakes up again after few seconds :/
requirement is that sleep does work when invoked manually, e.g. via Apple icon in the menu bar top left, Sleep. Does it?
 
Joined
Jan 27, 2019
Messages
9
Motherboard
N/A
CPU
Intel Core i7 4700HQ
Graphics
Intel Graphics 4600 HD
Yes it does indeed.
 
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
Troubleshooting:

It's proven that different macOS versions have differing outputs for ioreg -wO -l | grep Capacity

Open Terminal, paste

pmset sleepnow

and press ENTER

Does your hack sleep normally?

If so, disconnect from power, open Script Editor, paste the SleepOnLowBatterySound.scpt code from above into it;

edit

else if Pct ≤ 5 then

into

else if Pct ≤ 100 then

then run the script (grey triangle in the title bar).

Does your hack sleep normally, or not?

If not, provide your terminal output from ALL below separately:

ioreg -wO -l | grep Capacity

ioreg -wO -l | grep MaxCapacity

ioreg -wO -l | grep CurrentCapacity

IMPORTANT: also provide the battery charge in % displayed in the menu bar!
 
Last edited:
Joined
Jun 12, 2019
Messages
4
Motherboard
HP 1993
CPU
i7-4702MQ
Graphics
HD 4600, 1366x768
Mobile Phone
  1. Android
ioreg -wO -l | grep Capacity
I have the same issue too. When I run the script in Terminal it works. But when installed the laptop attempts to sleep then turns on again. in Mojave running the code ioreg -wO -l | grep Capacity gives;


RACKAs-MacBook-Pro:~ racka$ ioreg -wO -l | grep Capacity

| | | "Configuration" = {"Correct16bitSignedCurrentRate"=Yes,"CurrentDischargeRateMax"=20000,"EstimateCycleCountDivisor"=6,"UseDesignVoltageForCurrentCapacity"=Yes,"UseDesignVoltageForMaxCapacity"=Yes,"UseExtendedBatteryInformationMethod"=Yes,"UseDesignVoltageForDesignCapacity"=Yes,"CorrectCorruptCapacities"=Yes,"StartupDelay"=0,"FirstPollDelay"=4000,"UseExtraBatteryInformationMethod"=Yes}

| | "MaxCapacity" = 4142

| | "CurrentCapacity" = 1555

| | "LegacyBatteryInfo" = {"Amperage"=3987,"Flags"=7,"Capacity"=4142,"Current"=1555,"Voltage"=12321,"Cycle Count"=39}

| | "DesignCapacity" = 4142
 
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
OK thanks for the feedback. Not sure right now when I might have time to look into it priority list wise, though .. :(
 
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
oh, something changed: in all Apple Script .scpt files (SleepOnLowBattery.scpt, SleepOnLowBatterySound.scpt, demo.scpt), ExternalChargeCapable needs to be changed to ExternalConnected

That makes more sense anyway. I took that over from the original script. Maybe in OS X back then there wasn't even a parameter or property ExternalConnected

I'll post an updated release as soon as possible (too late & tired now already).
 
Last edited:
Joined
Feb 13, 2011
Messages
410
Motherboard
Asus Vivobook S15 / x510UAR
CPU
i5-8250U
Graphics
UHD 620
Mobile Phone
  1. Android
MAJOR update:

2019-11-15 v. 1.1

  • BUG FIX: changed all occurrences of ExternalChargeCapable to ExternalConnected in all Apple Script .scpt files (SleepOnLowBattery.scpt, SleepOnLowBatterySound.scpt, demo.scpt) to restore functionality

  • IMPROVEMENT: made queries of MaxCapacity and CurrentCapacity more compatible to work with hopefully any system

  • NEW: added Catalina compatibility to install scripts; verified Mojave compatibility

  • NEW: Sound script uses voice Allison if installed, otherwise automatically defaults back to another English standard voice (Daniel, Alex or Fred)
I'm very positive this much improved version will work fine for everyone :) @Newsonic @Racka98
 
Last edited:
Top