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:
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.
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
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
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:
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!
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
a single script that returns both values as separate results so I can assign each to a separate variable,
or
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.
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!