Magic Mouse Low Battery Alert
Published: 2021-09-14 00:45:55

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:
![Nano Window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nc5re6ggh461tcxw28ez.png)

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

* Hit Ctrl + x
* Hit y
* Hit Enter

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hhdsvfysw7uyizgpcqca.png)

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

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hhdsvfysw7uyizgpcqca.png)

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ytcvjsprwcyqs7ww563x.png)

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