1

I'm making a swift app that shows the battery level of all connected bluetooth devices. I've got three devices connected: Mysz(name surname), Magic Keyboard (name), i12; where Mysz is just Magic Mouse.

Using this script I manage to get only the first two devices:

set batteryInfo to do shell script "ioreg -r -l -k 'BatteryPercent'" set deviceList to paragraphs of batteryInfo set currentDevice to "" set currentBatteryLevel to "" set batteryInfo to "" repeat with a in deviceList if a contains "Product" and a does not contain "ProductID" then set currentDevice to text ((offset of "=" in a) + 3) through -2 of a end if if a contains "BatteryPercent" then set currentBatteryLevel to text ((offset of "=" in a) + 2) through -1 of a set batteryInfo to batteryInfo & currentDevice & ": " & currentBatteryLevel & "%\n" end if end repeat if (length of batteryInfo) > 0 then set batteryInfo to text 1 through -2 of batteryInfo end if return batteryInfo 

This script return this:

Magic Mouse: 70% Magic Keyboard: 75% 

Using the MacOS GUI I see all three devices with listed battery levels beside them. Does anyone know how to retrieve the battery level of all connected bluetooth devices? I'm using MacOS 13.7.6

4
  • Out of curiosity: Why do you want to use AppleScript instead of Swift? Commented Jul 24 at 10:06
  • Might not be a good reason but as I found the ioreg command I was looking for a way to execute it from my Swift code. Commented Jul 24 at 10:22
  • Plus, as for now, I can't retrieve any battery info through CoreBluetooth. Commented Jul 24 at 10:29
  • The swift tag reaches more Bluetooth experts than the applescript tag. Have you tried stackoverflow.com/search?q=%5Bswift%5D+bluetooth+battery or stackoverflow.com/search?q=%5Bswift%5D+ioreg ? Commented Jul 24 at 10:54

2 Answers 2

1

When you run ioreg -r -l -k BatteryPercent you’re only seeing devices that expose a BatteryPercent property in the HID event service (i.e. mice, keyboards, trackpads). The “i12” earbuds (and most other head‑sets) don’t publish their battery level that way, so they never show up in your script’s output.

There are basically two ways to pull in all battery‑capable Bluetooth devices on macOS. The first option is to read the system's bluetooth cache plist, which is located in /Library/Preferences/com.apple.Bluetooth.plist . Next, for a more robust solution, you can try using CoreBluetooth (see here). Most headsets (and AirPods‑style earbuds) implement the standard Battery Service (UUID 0x180F) with the Battery Level characteristic (0x2A19). With CoreBluetooth, you can scan for all connected peripherals that offer that service, connect, and read their battery‑level value.

Sign up to request clarification or add additional context in comments.

2 Comments

The file /Library/Preferences/com.apple.Bluetooth.plist has been last updated over a year ago while I use bluetooth all the time. Is there another file with bluetooth caches?
Using CoreBluetooth i can't find any battery service or characteristics in my bluetooth devices.
1

This command returns the full list of connected devices wich provide a battery level information: `pmset -g accps`.

Which makes the Apple Script look like this to return a clear format like `Device: n%`:

set batteryInfo to {} set uniqueVerses to {} set pmsetOutput to do shell script "pmset -g accps" set pmsetOutput to (paragraphs of pmsetOutput) as list set pmsetOutput to (items 2 thru -1 of pmsetOutput) as list repeat with verse in pmsetOutput set cleanVerse to text 3 thru -1 of verse set semicolonPos to offset of ";" in cleanVerse if semicolonPos > 0 then set cleanVerse to text 1 thru (semicolonPos - 1) of cleanVerse end if set openParenPos to offset of "(" in cleanVerse if openParenPos > 0 then if text (openParenPos + 1) thru (openParenPos + 2) of cleanVerse is "id" then set closeParenPos to offset of ")" in cleanVerse if closeParenPos > 0 then set cleanVerse to text 1 thru (openParenPos - 1) of cleanVerse & text (closeParenPos + 1) thru -1 of cleanVerse end if end if end if set AppleScript's text item delimiters to {ASCII character 9} set textItems to text items of cleanVerse set AppleScript's text item delimiters to {""} set cleanVerse to textItems as string set percentPos to offset of "%" in cleanVerse if percentPos > 2 then set lastSpaceBeforePercent to 0 repeat with i from percentPos - 1 to 1 by -1 if character i of cleanVerse is " " then set lastSpaceBeforePercent to i exit repeat end if end repeat if lastSpaceBeforePercent > 0 then set cleanVerse to text 1 thru (lastSpaceBeforePercent - 1) of cleanVerse & ":" & text lastSpaceBeforePercent thru -1 of cleanVerse end if end if if cleanVerse is not in uniqueVerses then set end of uniqueVerses to cleanVerse set end of batteryInfo to cleanVerse & " " end if end repeat set batteryInfo to batteryInfo as string set batteryInfo to text 1 thru -2 of batteryInfo return batteryInfo 

I've tries the CoreBluetooth approach but I've not managed to find any battery service in any of my devices, while this return a pretty clear list of what I need.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.