One of the worst things about the Apple Magic mouse is the fact that the OS doesn't give you any kind of low battery alert until it hits 2% battery. Maybe mine is defective, but that's not enough to get through a full work day. This wouldn't be so bad if not for the worst thing about the magic mouse:
You can't charge it and use it at the same time....thanks Apple.
This details a very basic work around. We're going to add a cron job that runs every 15min that will check the battery level and show a notification if its below a certain threshold.
Setup your script
- Open a new terminal window
- enter the following commands, I'll explain what they all are later down
- mkdir bin
- cd bin
- touch mouseCheck.sh
- chmod a+x mouseCheck.sh
Copy all of this black text
#!/bin/bash
# Edit cron tab
# env EDITOR=nano crontab -e
# */15 * * * * ~/bin/mouseCheck.sh
#
#
BATT=`ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i mouse -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2`
KEY_BATT=`ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i "Magic Keyboard" -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2`
# defaults to warn at 12%; accepts other number as 1st argument (useful for testing)
COMPARE=${1:-12}
#COMPARE=101
if [ -z "$BATT" ]; then
echo 'No mouse found.'
exit 0
fi
if (( BATT < COMPARE )); then
osascript -e "display notification \"Mouse battery is at ${BATT}%.\" with title \"Mouse Battery Low\""
fi
if [ -z "$KEY_BATT" ]; then
echo 'No Keyboard found.'
exit 0
fi
if (( KEY_BATT < COMPARE )); then
osascript -e "display notification \"Keyboard battery is at ${KEY_BATT}%.\" with title \"Keyboard Battery Low\""
fi
- Go back to your terminal and type the following:
- cat > mouseCheck.sh
- Paste the above CMD + V
- Hit CMD + D to return to terminal prompt.
Set up the cronjob
- Type the following into the same terminal(capitals are important):
- env EDITOR=nano crontab -e
You should something that looks like this:
paste the following into it:
*/15 * * * * ~/bin/mouseCheck.sh
- Hit Ctrl + x
- Hit y
- Hit Enter
You might get a warning saying 'Terminal wants to administer' your computer, Click Ok.
Thats it! If you battery or keyboard get below 12% you should get an alert like this in the top right. I've found 12% is more than enough to get me through 2 days in case I forget after the first one.
Mine are higher because when writing this article I changed the alert level to get a screen shot.
Stick around and I'll explain what everything does if you're curious and what you can change on your own.
Commands explained:
-
mkdir bin
- create a folder called bin. This is typically where executables go. -
cd bin
- change current directory to be bin -
touch mouseCheck.sh
- create an empty file called mouseCheck.sh The .sh means this is a shell script, or will be at least. -
cat > mouseCheck.sh
write something to mouseCheck.sh - in this case we don't tell it what to write, so it will prompt us for input afterwards, until it sees the End of File character (EoF) -
ctrl + D
send the EoF character to close input.
At this point you can see whats in the file with the command: cat mouseCheck.sh
cat is the basic command to read text files.
-
env EDITOR=nano crontab -e
- Open the cron tab for editing. we need to add theenv EDITOR=nano
before hand because it lets us make a temporary change to the ENVIRONMENT VARIABLES just for this command. It's a good idea to not change things unless we specifically mean to.- If you used lower case editor, or left it out you'll end up in the default text editor VIM, which is a very powerful editor but has a very steep learning curve and is famous for not being able to be easily quit.
- If you end up here by accident you can either:
- Close your terminal and start over (remember to cd bin)
- Attempt to exit vim by:
- Hitting
esc
then type:q
and hit enter
-
Crontab syntax isn't very complicated but its unique and weird the first time you see it, if you're interested I found this was a good read on it: https://www.geeksforgeeks.org/crontab-in-linux-with-examples/
-
*/15 * * * * ~/bin/mouseCheck.sh
translates to run the script mouseCheck.sh located in the bin directory/folder in my home directory (~) every 15 minutes.
-
Script Explained
#!/bin/bash
This tells the program where to find the program to run this script. In our case we're using the shell bash
thats in the /bin
directory. This is different from the bin we put our script in.
# Edit cron tab
# env EDITOR=nano crontab -e
# */15 * * * * ~/bin/mouseCheck.sh
Honestly this isn't needed...the # at the beginning tell bash to ignore these lines, but I leave this here because I can never remember how to get to the cron editor.
BATT=`ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i mouse -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2`
KEY_BATT=`ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i "Magic Keyboard" -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2`
This sets up 2 variables, one for mouse battery and one for keyboard battery by running several commands each. Each time you see a | its taking the output from one command and using it as the input for the next one.
# defaults to warn at 12%; accepts other number as 1st argument (useful for testing)
COMPARE=${1:-12}
#COMPARE=101
if [ -z "$BATT" ]; then
echo 'No mouse found.'
exit 0
fi
if (( BATT < COMPARE )); then
osascript -e "display notification \"Mouse battery is at ${BATT}%.\" with title \"Mouse Battery Low\""
fi
if [ -z "$KEY_BATT" ]; then
echo 'No Keyboard found.'
exit 0
fi
if (( KEY_BATT < COMPARE )); then
osascript -e "display notification \"Keyboard battery is at ${KEY_BATT}%.\" with title \"Keyboard Battery Low\""
fi
I've run out of time, but if you're very interested in the rest of these commands drop a comment and I can fill the rest in.
Cheers.
Top comments (8)
I too was getting quite annoyed only getting a battery-low warning at 2%. This script is a great workaround.
The only thing I had to add was the path to ioreg as the cron job could not find it
PATH=/usr/sbin:$PATH
Where does this code go?
In the mouseCheck.sh, just before the 'BATT=..' command
Thank you for posting this! So annoying Apple hasn't built in their own warning. One typo though: Hit CMD + D to return to terminal prompt should be CTR + D (control).
This script is absolutely beautiful, thank-you so much!
Here are some recommendations:
If you have multiple mice or keyboards, consider only the one having the lowest battery level:
BATT=
ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i mouse -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2 | sort -n | head -1
KEY_BATT=
ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i "Magic Keyboard" -A 20 | grep BatteryPercent | cut -d= -f2 | cut -d' ' -f2 | sort -n | head -1
If you would like to play a sound (From /System/Library/Sounds) along with the notification:
osascript -e "display notification \"Mouse battery is at ${BATT}%.\" with title \"Mouse Battery Low\" sound name \"Bottle\""
osascript -e "display notification \"Keyboard battery is at ${KEY_BATT}%.\" with title \"Keyboard Battery Low\" sound name \"Bottle\""
You can also check if the mouse is charging with the following:
When I save the crontab file, it's tacking on this weird extension at the end of the file. See screenshot attached.
That's normal. You are not editing the crontab file directly. Once you save this tmp file and it contains no errors, it will overwrite the actual cron file (in /var/at/tabs/)