Jump to content

[RELEASE]: SleepOnLowBattery (“SOLB”)


BuXb
 Share

15 posts in this topic

Recommended Posts

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:

GmZS1aW.jpg

 

Between ≤8 and >5% battery charge:

IWZefgN.jpg

 

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

qEQgOYT.jpg

 

sNPAmze.jpg

 

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:
https://hints.macworld.com/article.php?story=20110219013713667

~~~~~~~~~~~~~~~~~~~~~~~~~~~~

THE CODE (of the version with sound):

install.command:

 
#!/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 #
##==============================================================================##

 

 

LaunchAgent SleepOnLowBatterySound.plist:

Spoiler
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>KeepAlive</key>
	<false/>
	<key>Label</key>
	<string>SleepOnLowBatterySound</string>
	<key>LowPriorityIO</key>
	<true/>
	<key>ProgramArguments</key>
	<array>
		<string>/usr/bin/osascript</string>
		<string>/etc/SleepOnLowBatterySound.scpt</string>
</array>
	<key>RunAtLoad</key>
	<true/>
	<key>ServiceDescription</key>
	<string>SleepOnLowBatterySound</string>
	<key>StartInterval</key>
	<integer>120</integer>
</dict>
</plist>

 

 

Script SleepOnLowBatterySound.scpt:

Spoiler
# 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.

 

 

SleepOnLowBattery (SOLB) by BugsB v.1.22 (2021-12-17).zip

Edited by BuXb
2021-12-17 v.1.22 update
  • Like 9
Link to comment
Share on other sites

  • 1 month later...

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!

Edited by BuXb
Link to comment
Share on other sites

  • 10 months later...

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).

 

 

Link to comment
Share on other sites

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)

 

SleepOnLowBattery (SOLB) by BugsB v.1.1 (2019-11-15).zip

 

@Allan @onemanOSX  @TombaFI

Edited by BuXb
Link to comment
Share on other sites

  • 1 month later...
On 11/15/2019 at 3:47 AM, BuXb said:

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)

 

SleepOnLowBattery (SOLB) by BugsB v.1.1 (2019-11-15).zip

 

@Allan @onemanOSX  @TombaFI

 

Thank you. How can I modify it to go to hibernate or sleep if it’s idle for a long time or the battery is at a higher level, for example 50%?

  • Like 1
Link to comment
Share on other sites

@boris1

modify it to go to hibernate or sleep if it’s idle for a long time:

hmm, I'm really neither a bash nor an Applescript Pro, much rather an apprentice in maybe his 2nd year, so I can't answer if or how this is possible in either of the two script languages. You would need to websearch that. I do know however that that is possible with Bernhard Baehr's sleepwatcher command-line binary which you can download on his minimalist homepage. The downside is that it's badly documented, and you'd probably encounter a rather steep learning curve.

 

or the battery is at a higher level, for example 50%?:

SleepOnLowBatterySound.scpt:

edit

if Pct  10 and Pct > 8 then

into

if Pct  50 and Pct > 8 then

save

 

PS: congrats on joining T*nyM*c today, making one vulgar but true post, and getting suspended right away. Good some mod there must obviously have read your candid and courageous assessment. The more people speak out the truth the better.

 

Edited by BuXb
Link to comment
Share on other sites

  • 1 year later...

SleepOnLowBattery (SOLB) by BugsB v.1.22 (2021-12-17).zip

 

Change log:

    •    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

 

Tested working in macOS Monterey 12.0.1 and Catalina 10.15.7.

Link to comment
Share on other sites

I am not getting the voice feature to work properly and it appears to be because my voice installations are not located in System/Library/Speech/Voice.  The only folder I have in there is NoraSiri.SpeechVoice even though I have Allison and other voices downloaded and installed.  I can't seem to find where they are located using Spotlight but I did find this entry in a plist for mobile assist voice services:  com.apple.ttsbundle.Allison.  Any thoughts about what I need to do to modify your script?

 

P.S. - When I run the demo script, I unsurprisingly get this error:  Extras/demo.scpt: execution error: The variable voicename is not defined. (-2753) I was able to work around this error by making a copy of my NoraSiri.SpeechVoice folder and renaming it to Allison.SpeechVoice.

Edited by mnfesq
Link to comment
Share on other sites

@mnfesq

 

1) which macOS as exact as possible, please, like: macOS 12.1

2) have you in any way ran some macOS tweak util like Onyx, TinkerTool etc?

 

I just checked in macOS Monterey 12.1 as well as in Catalina 10.15.7: in both, inside System/Library/Speech/Voice, these two folders:

Allison.SpeechVoice
AllisonCompact.SpeechVoice

My guess is that something went wrong with your voice download in macOS. Simply open Speech Sys Pref, e.g. via this one command in Terminal

 

osascript -e "tell application \"System Preferences\"" -e "set the current pane to pane id \"com.apple.preference.universalaccess\"" -e "reveal anchor \"TextToSpeech\" of pane id \"com.apple.preference.universalaccess\"" -e "activate"  -e "end tell"

 

-> Modify, uncheck Allison, OK -> re-download "her" -> best restart macOS -> try (and if needed look) again.

  • Like 1
Link to comment
Share on other sites

1 hour ago, BuXb said:

@mnfesq

 

1) which macOS as exact as possible, please, like: macOS 12.1

2) have you in any way ran some macOS tweak util like Onyx, TinkerTool etc?

 

I think you may have found the explanation.  My settings are so old that I cannot remember every tweak I have made over the years.  I may have changed the location of the voice downloads to save disk space on a previous, smaller system disk or partition. Re-downloading the voice files did not put them in the default location.  I may have to reinstall tinkertool to see if that was the cause.  Thanks.

  • Like 1
Link to comment
Share on other sites

20 hours ago, BuXb said:

@mnfesq maybe this thread is of help to you (or maybe not)

 

So no luck and I checked 3 other installations of I have of macOS and only one old installation of Catalina had the voices in System/Library/Speech/Voices, and those were all the compact versions only.  My workaround will be fine but now I am really curious why I get all the voices I selected in system preferences but cannot find them anywhere in my system partition.  It is puzzling.

Link to comment
Share on other sites

indeed. A few more options:

  1. Have you looked in /Library/Speech/Voices yet?
  2. If not there: you can search for Allison with a tool like FAF (FindAnyFile)
  3. Have you tried yet to create a new macOS user with admin privs, then install voices from there?
Link to comment
Share on other sites

Hey Allan - thanks, I'm hanging in there.

 

Cool, Hackintosh Tools - not sure where it was before. Funny enough the base script came from a real Mac user whose Mac suffered from insomnia :) This script should work for anyone running macOS. But even some users of old Macs use OpenCore these days, LOL

  • Like 1
Link to comment
Share on other sites

 Share

×
×
  • Create New...