Magic Mouse Low Battery Alert
samselfridge

samselfridge @samselfridge

Joined:
Oct 2, 2020

Magic Mouse Low Battery Alert

Publish Date: Sep 14 '21
11 8

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
Enter fullscreen mode Exit fullscreen mode
  • 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:
Nano Window

paste the following into it:
*/15 * * * * ~/bin/mouseCheck.sh

  • Hit Ctrl + x
  • Hit y
  • Hit Enter

Alt Text

You might get a warning saying 'Terminal wants to administer' your computer, Click Ok.

Alt Text

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 the env 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. Alt Text
    • 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 
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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`
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Comments 8 total

  • Sander
    SanderJul 16, 2023

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

  • Simon
    SimonAug 28, 2023

    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

    • David Tepper
      David TepperOct 12, 2023

      Where does this code go?

      • Simon
        SimonOct 13, 2023

        In the mouseCheck.sh, just before the 'BATT=..' command

  • David Tepper
    David TepperOct 12, 2023

    When I save the crontab file, it's tacking on this weird extension at the end of the file. See screenshot attached.

    Image description

    • Simon
      SimonOct 13, 2023

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

  • Richard Weinstock
    Richard WeinstockDec 12, 2024

    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\""

  • Matt
    MattDec 16, 2024

    You can also check if the mouse is charging with the following:

    CHARGING=`ioreg -c AppleDeviceManagementHIDEventService -r -l | grep -i mouse -A 20 | grep Transport | cut -d= -f2 | cut -d' ' -f2 | cut -d'"' -f2`
    
    if [ "$CHARGING" = "USB" ]; then
      exit 0
    fi
    
    Enter fullscreen mode Exit fullscreen mode
Add comment