BuXb Posted November 10, 2018 Share Posted November 10, 2018 (edited) 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: Between ≤8 and >5% battery charge: On ≤ 5% battery charge you will see a 10 seconds countdown dialog box in 1 second intervals: 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: Have the sound version install script check if Allison is installed, and if not, offer to download and install it. 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 December 17, 2021 by BuXb 2021-12-17 v.1.22 update 9 Link to comment Share on other sites More sharing options...
BuXb Posted January 1, 2019 Author Share Posted January 1, 2019 (edited) 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 February 21, 2021 by BuXb Link to comment Share on other sites More sharing options...
BuXb Posted November 13, 2019 Author Share Posted November 13, 2019 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 More sharing options...
BuXb Posted November 15, 2019 Author Share Posted November 15, 2019 (edited) 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 November 15, 2019 by BuXb Link to comment Share on other sites More sharing options...
boris1 Posted December 26, 2019 Share Posted December 26, 2019 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%? 1 Link to comment Share on other sites More sharing options...
BuXb Posted December 26, 2019 Author Share Posted December 26, 2019 (edited) @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 December 26, 2019 by BuXb Link to comment Share on other sites More sharing options...
BuXb Posted December 17, 2021 Author Share Posted December 17, 2021 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 More sharing options...
mnfesq Posted December 25, 2021 Share Posted December 25, 2021 (edited) 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 December 25, 2021 by mnfesq Link to comment Share on other sites More sharing options...
BuXb Posted December 25, 2021 Author Share Posted December 25, 2021 @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. 1 Link to comment Share on other sites More sharing options...
mnfesq Posted December 25, 2021 Share Posted December 25, 2021 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. 1 Link to comment Share on other sites More sharing options...
BuXb Posted December 26, 2021 Author Share Posted December 26, 2021 @mnfesq maybe this thread is of help to you (or maybe not) Link to comment Share on other sites More sharing options...
mnfesq Posted December 26, 2021 Share Posted December 26, 2021 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 More sharing options...
BuXb Posted December 26, 2021 Author Share Posted December 26, 2021 indeed. A few more options: Have you looked in /Library/Speech/Voices yet? If not there: you can search for Allison with a tool like FAF (FindAnyFile) 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 More sharing options...
Allan Posted December 26, 2021 Share Posted December 26, 2021 @BuXb how are you? I've moved your topic to a proper place: Hackintosh Tools 😉 1 Link to comment Share on other sites More sharing options...
BuXb Posted December 27, 2021 Author Share Posted December 27, 2021 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 1 Link to comment Share on other sites More sharing options...
Recommended Posts