Check Magic Mouse battery level and notify at certain threshold?

Howdy all, is there a way to have AS check the Magic Mouse battery level and give a notification if below a certain level?

I’ve googled and searched this forum quite a bit but haven’t found anything unfortunately. I thought this would be a simple on but perhaps not?

Thanks for any help!

This gets the battery level, but it’s UI scripting and will steal your mouse, so it may be annoying to have this polling in the background:

set mouseName to "Jerry" --Put your mouse name here

tell application "System Events"
	tell process "SystemUIServer"
		set bluetoothMenu to (first menu bar item whose description is "bluetooth") of menu bar 1
		click bluetoothMenu
		set magicMouseItem to item 1 of (the first menu item whose title is mouseName) of menu of bluetoothMenu
		tell magicMouseItem
			click
			tell menu 1 to set batteryInfo to the title of the first menu item whose title contains "Battery Level"
			cancel
		end tell
		set batteryLevel to text -3 through -2 of batteryInfo
	end tell
end tell

I’ll see what else I can find.

I don’t know if you also need help with the the application that loops it and notifies you. That’s a stay-open Application with an “on idle” handler. You can see information on those here:

https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/conceptual/ASLR_about_handlers.html#//apple_ref/doc/uid/TP40000983-CH206-SW7

Or searching.

This is much better:


set bluetoothInfo to do shell script "system_profiler SPBluetoothDataType"
set {delimitHolder, AppleScript's text item delimiters} to {AppleScript's text item delimiters, "Battery Level: "}
set batteryLevel to text 1 through 2 of text item 2 of bluetoothInfo as number
set AppleScript's text item delimiters to delimitHolder

Although if you have multiple connected bluetooth items that have battery levels, you may need to parse the “bluetoothInfo” text differently.

That first one does indeed work quite well. But like you said since it steals my mouse it could potentially interfere with my workflow. The good thing is I wouldn’t need this to run but a few times throughout the day so it’s probably not a big deal.

Another great thing is it opened my eyes to using AS to control the icons on the system menu bar; something I didn’t know was possible (I have VERY limited AS knowledge as you can probably tell haha).

Now about this one… I do indeed have multiple bluetooth items connected. Primarily my mouse and keyboard, but from time to time I also connect my trackpad.

How would I distinguish between those three devices?

Please run the script and post the contents of “bluetoothInfo,” and tell us the name of your mouse, and we’ll find a better way to extract the mouse battery level from the data.

It’s easier to figure out how to parse relevant data when the data is known.

This is the result of the script:
{“”}

Mouse name is simply “Magic Mouse 2”

I’m sorry, I assumed you knew how to find the value of a variable in Applescript.

return do shell script "system_profiler SPBluetoothDataType"

system_profiler can return the output in property list format and System Events can parse property list.

The script extracts the battery percent of all connected Bluetooth devices and returns a list of records deviceStatus containing the name and battery percent of each device

set xmlData to do shell script "system_profiler SPBluetoothDataType -xml"
tell application "System Events"
	set propertyList to make new property list item with data xmlData
	set allItems to property list item "_items" of property list item 1 of propertyList
	set devices to property list item "device_title" of property list item 1 of allItems
	set deviceStatus to {}
	repeat with deviceRecord in property list items of devices
		set currentDevice to property list item 1 of deviceRecord
		if exists property list item "device_batteryPercent" of currentDevice then
			set batteryLevel to property list item "device_batteryPercent" of currentDevice
			set end of deviceStatus to {|name|:name of currentDevice, batteryPercent:value of batteryLevel}
		end if
	end repeat
end tell
deviceStatus


Thanks, Stefan. That’s much better than using Applescript directly to parse the System Profiler output.

No worries, I’m a total noob with AS and most of this stuff goes way over my head haha. Here’s the results.

"Bluetooth:

  Apple Bluetooth Software Version: 6.0.7f11
  Hardware, Features, and Settings:
      Name: Chris’s Mac mini
      Address: 6C-40-08-99-11-C7
      Bluetooth Low Energy Supported: Yes
      Handoff Supported: Yes
      Instant Hot Spot Supported: Yes
      Manufacturer: Broadcom
      Transport: USB
      Chipset: 20702B0
      Firmware Version: v144 c9293
      Bluetooth Power: On
      Discoverable: Off
      Connectable: Yes
      Auto Seek Pointing: On
      Remote wake: On
      Vendor ID: 0x05AC
      Product ID: 0x8289
      HCI Version: 4.0 (0x6)
      HCI Revision: 0x244D
      LMP Version: 4.0 (0x6)
      LMP Subversion: 0x4190
      Device Type (Major): Computer
      Device Type (Complete): Mac Desktop
      Composite Class Of Device: 0x380104
      Device Class (Major): 0x01
      Device Class (Minor): 0x01
      Service Class: 0x1C0
      Auto Seek Keyboard: On
  Devices (Paired, Configured, etc.):
      Chris Thomerson’s Keyboard:
          Address: 40-30-04-12-E0-82
          Major Type: Peripheral
          Minor Type: Keyboard
          Services: Apple Wireless Keyboard
          Paired: Yes
          Configured: Yes
          Connected: Yes
          Manufacturer: Apple (0x3, 0x31C)
          Battery Level: 100%
          Firmware Version: 0x0050
          Vendor ID: 0x05AC
          Product ID: 0x0255
          Class of Device: 0x05 0x10 0x2540
          AFH: On
          AFH Map: 0080FFFFFFFF9FA37F
          RSSI: -54
          Role: Master
          Connection Mode: Sniff Mode
          Interval: 11.25 ms
          Host Connectable: Yes
          EDR Supported: No
          eSCO Supported: No
          SSP Supported: No
      Magic Mouse 2:
          Address: 04-4B-ED-C9-8B-2D
          Major Type: Peripheral
          Minor Type: Mouse
          Services: Magic Mouse 2
          Paired: Yes
          Configured: Yes
          Connected: Yes
          Manufacturer: Broadcom (0x5, 0x240C)
          Battery Level: 39%
          Firmware Version: 0x0064
          Vendor ID: 0x004C
          Product ID: 0x0269
          Class of Device: 0x05 0x20 0x0580
          AFH: On
          AFH Map: 0080FFFFFFFF9FA37F
          RSSI: -59
          Role: Master
          Connection Mode: Sniff Mode
          Interval: 11.25 ms
          Host Connectable: Yes
          EDR Supported: Yes
          eSCO Supported: No
          SSP Supported: Yes
      Chris Thomerson’s Trackpad:
          Address: 88-63-DF-F2-13-96
          Major Type: Peripheral
          Minor Type: Trackpad
          Services: Apple Wireless Trackpad
          Paired: Yes
          Configured: Yes
          Connected: No
          Manufacturer: Apple (0x3, 0x31C)
          Firmware Version: 0x0160
          Vendor ID: 0x05AC
          Product ID: 0x030E
          Class of Device: 0x05 0x25 0x2594
          Host Connectable: Yes
          EDR Supported: No
          eSCO Supported: No
          SSP Supported: No
  Services:
      Bluetooth File Transfer:
          Folder other devices can browse: ~/Public
          When receiving items: Accept all without warning
          State: Disabled
      Bluetooth File Exchange:
          Folder for accepted items: ~/Downloads
          When other items are accepted: Save to location
          When receiving items: Accept all without warning
          State: Disabled
      Bluetooth Internet Sharing:
          State: Disabled
  Incoming Serial Ports:
      Bluetooth-Incoming-Port:
          RFCOMM Channel: 3
          Requires Authentication: No

"

Thanks for getting that.

So, I could write Applescript to parse the Mouse’s battery percentage out of that, buy I think the best bet is to just go with Stefan’s script.

You’re welcome. Now how would I go about either setting each device’s battery level as a variable for use with Keyboard Maestro or having AS notify me if a device is below a certain threshold?

The results from that script are as follows:
{{|name|:“Chris Thomerson’s Keyboard”, batteryPercent:“100%”}, {|name|:“Magic Mouse 2”, batteryPercent:“39%”}}

Which doesn’t really lend itself to using as a variable haha.

An Applescript record does lend itself to being used as a variable.

But if you just want the mouse percentage, I modified Stefan’s script to just return the battery mouse percentage.

set mouseName to "Jerry"

set xmlData to do shell script "system_profiler SPBluetoothDataType -xml"
tell application "System Events"
	set propertyList to make new property list item with data xmlData
	set allItems to property list item "_items" of property list item 1 of propertyList
	set devices to property list item "device_title" of property list item 1 of allItems
	set batteryLevel to ""
	repeat with deviceRecord in property list items of devices
		set currentDevice to property list item 1 of deviceRecord
		if the name of currentDevice is mouseName then
			set batteryLevel to the value of property list item "device_batteryPercent" of currentDevice
			exit repeat
		end if
	end repeat
end tell

set batteryLevel to text 1 through -2 of batteryLevel as number

To make it run on a loop, you use an “on idle” handler and save as a “stay open” application. I included a link to documentation on this before. Or here’s a good example:

http://scriptingosx.com/tag/stay-open/

That works great for the mouse but I would also like to check the keyboard battery level. Unfortunately when I change the “mouseName” to the name of my keyboard it gives me the following error:

error “Can’t make text 1 thru -2 of "" into type number.” number -1700 from text 1 thru -2 of “” to number

I tried changing the line set batteryLevel to different values but I keep getting the same error. Any ideas?

I do like the ability to check mouse and keyboard separately as this allows me greater flexibility in Keyboard Maestro so please don’t give up on me haha!

Which string are you passing as mouseName ?
According to what you posted before it’s supposed to be “Chris Thomerson’s Keyboard”

Yvan KOENIG running High Sierra 10.13.6 in French (VALLAURIS, France) mardi 13 novembre 2018 20:42:05

The only thing I am changing is the first line where I set the “mouseName” to the name of the device; in this case my keyboard since I am using the same script for both devices. Below is a copy/paste:

set mouseName to "Chris Thomerson's Keyboard"

set xmlData to do shell script "system_profiler SPBluetoothDataType -xml"
tell application "System Events"
	set propertyList to make new property list item with data xmlData
	set allItems to property list item "_items" of property list item 1 of propertyList
	set devices to property list item "device_title" of property list item 1 of allItems
	set batteryLevel to ""
	repeat with deviceRecord in property list items of devices
		set currentDevice to property list item 1 of deviceRecord
		if the name of currentDevice is mouseName then
			set batteryLevel to the value of property list item "device_batteryPercent" of currentDevice
			exit repeat
		end if
	end repeat
end tell

set batteryLevel to text 1 through -2 of batteryLevel as number

What are we trying to achieve here? Stefan already had it returning the battery percentages of both the mouse and the keyboard, but I thought we were trying to get just the mouse battery percentage as a number.

Maybe just post your full script so we can see how you’re trying to use these values and figure out what the problems are?

Sorry for the confusion. His script did indeed return both values but in such a way that I was unable to integrate them into Keyboard Maestro. I would like to have either

  1. a single script that returns both values as separate results so I can assign each to a separate variable,

or

  1. two separate scripts that return the value of a specific device.

Either way I would like both values returned to be in a simple number format that way I can make Keyboard Maestro look at that value and determine if it is more or less than my threshhold and alert me accordingly.

Again, sorry for the confusion!

set mouseName to "Magic Mouse 2"
set keyboardName to "Chris Thomerson’s Keyboard"

set xmlData to do shell script "system_profiler SPBluetoothDataType -xml"
tell application "System Events"
	set propertyList to make new property list item with data xmlData
	set allItems to property list item "_items" of property list item 1 of propertyList
	set devices to property list item "device_title" of property list item 1 of allItems
	set mouseBattery to ""
	set keyboardBattery to ""
	repeat with deviceRecord in property list items of devices
		set currentDevice to property list item 1 of deviceRecord
		if the name of currentDevice is mouseName then
			set mouseBattery to the value of property list item "device_batteryPercent" of currentDevice
		else if the name of currentDevice is keyboardName then
			set keyboardBattery to the value of property list item "device_batteryPercent" of currentDevice
		end if
	end repeat
end tell

if mouseBattery is not "" then set mouseBattery to text 1 through -2 of mouseBattery as number
if keyboardBattery is not "" then set keyboardBattery to text 1 through -2 of keyboardBattery as number

That works great! I just added keyboardBattery to the end to give me the result of the keyboard and mouseBattery for the mouse. This way I can run essentially the same script for both devices and have Keyboard Maestro notify me when they drop below my defined threshold. Thanks so much for eveyrbody’s patience and help!