macosbluetoothapplescriptcore-bluetooth

Find bluetooth connected devices battery level through Apple Script


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


Solution

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