How to Set Custom Mouse/Keyboard Battery Level Alert?

    | |   +-o AppleSmartBatteryManager  <class AppleSmartBatteryManager, id 0x1000003c2, registered, matched, active, busy 0 (0 ms), retain 7>
    | |     +-o AppleSmartBattery  <class AppleSmartBattery, id 0x1000003c4, registered, matched, active, busy 0 (0 ms), retain 6>

Looks like Logitech/Apple have changed the device class (again). I think you're back to @mrpasini's plan of "get all the things, then search". (Again, last time you tried that the lines were clipped.)

You could try

ioreg -w 0 | grep -i battery

...on the assumption that the line you want will have battery in it. Or

ioreg -w 0 | grep -i nn

...where nn is the battery percentage in the UI -- expect a lot of false positives from device ids etc.

  | |   +-o AppleSmartBatteryManager  <class AppleSmartBatteryManager, id 0x1000003c2, registered, matched, active, busy 0 (0 ms), retain 7>
    | |     +-o AppleSmartBattery  <class AppleSmartBattery, id 0x1000003c4, registered, matched, active, busy 0 (0 ms), retain 6>


    | |   |           | | | +-o display0  <class IODisplayConnect, id 0x100031a2d, registered, matched, active, busy 0 (1 ms), retain 6>
    | |   |   |   | |   +-o UA Connect  <class AppleUSBHostDeviceUserClient, id 0x10001431c, !registered, !matched, active, busy 0, retain 6>
    | | |   | +-o UA Connect  <class AppleUSBLegacyDeviceUserClient, id 0x100014323, !registered, !matched, active, busy 0, retain 5>
    | +-o AppleRSMChannelController  <class AppleRSMChannelController, id 0x100000930, registered, matched, active, busy 0 (9 ms), retain 5>
    | +-o IOUserDockChannelSerial  <class IOUserService, id 0x100000905, registered, matched, active, busy 0 (0 ms), retain 8>
    +-o IOUserServer(com.apple.IOUserDockChannelSerial-0x100000905)  <class IOUserServer, id 0x100000a1a, registered, matched, active, busy 0 (0 ms), retain 11>

Then that's me out of ideas. Unless...

Does the MX show up in System Information? Apple's wireless trackpad and keyboard do, in the "Bluetooth" section of "Hardware", and include the battery %.

It's looking like "no" :frowning: It might be that the percentage is only got by the Logitech software polling the mouse for current status, so unless you can tap into that somehow...

You could UI script it to get the value from the Bluetooth menu, but that's populated on the fly so would require a click on the icon. If that's not a problem then

tell application "System Events"
	tell process "SystemUIServer"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXDescription" is "bluetooth")
		click btMenu
		properties of menu item 4 of menu 1 of btMenu
	end tell
end tell

...might give you a clue as to how to pull the % value as a text item (complete guess as to the numbers, but that looks about right).

An alternative would be to run a periodic reminder every n days, where n is less than the number of days it takes to go from full to 20% charge. Yes, you'll have some "unnecessary" re-charging in there, but better that than the battery running out in the middle of something important!

Thanks for all your efforts. The AS "can't get item 1...", and UI browser won't grab anything for me so I'm unsure whether it could work with a bit of tweakery.

That's about as good a solution as is available, although I might see how this ugly and error-prone macro works out*:

(Edit: *Not very well, as it turns out. :rofl:)

So sometime after High Sierra the Bluetooth menu bar item moved from the "SystemUIServer" process to "Control Centre" and the attribute name changed. So

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		UI elements of window 1
	end tell
end tell

...should open the menu and return the UI elements (for me that's just just a single group).

You should be able to work down from there, either by trial and error or with UI Browser, to target the MX Master element. Whether you can get the text value from that is another thing -- that seems to be broken on Ventura at the moment (or I totally misunderstand how to do it!).

I managed to get the group:

group 1 of window Control Centre of application process ControlCenter

Then I ran:

tell application "System Events"
	tell process "Control Centre"
		set uiElems to entire contents
	end tell
end tell

...and got:

Output

window Control Centre of application process ControlCenter, group 1 of window Control Centre of application process ControlCenter, static text Bluetooth of group 1 of window Control Centre of application process ControlCenter, checkbox 1 of group 1 of window Control Centre of application process ControlCenter, scroll area 1 of group 1 of window Control Centre of application process ControlCenter, UI element 1 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter, checkbox 1 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter, checkbox 2 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter, button 1 of group 1 of window Control Centre of application process ControlCenter, menu bar 1 of application process ControlCenter, menu bar item 1 of menu bar 1 of application process ControlCenter, menu bar item 2 of menu bar 1 of application process ControlCenter, menu bar item 3 of menu bar 1 of application process ControlCenter, menu bar item 4 of menu bar 1 of application process ControlCenter, menu bar item 5 of menu bar 1 of application process ControlCenter

...and then I tapped out.

For your own sake, limit it to the object of interest! So if the first script got you

group 1 of window Control Centre of application process ControlCenter

...then the next iteration of the script would be

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		UI elements of group 1 of window 1
	end tell
end tell

...and so on.

Sorry, I'm a bit crapple at appScript.

I'm using a Bartender shortcut to make the bluetooth menu visible, which might complicate things. Triggering it actually shows the menu, not just the icon, so I figured out I have to double-trigger it so that your script clicks the icon, like this:

Screenshot

Anyway, here's what I get:

AS Output

static text Bluetooth of group 1 of window Control Centre of application process ControlCenter, checkbox 1 of group 1 of window Control Centre of application process ControlCenter, scroll area 1 of group 1 of window Control Centre of application process ControlCenter, button 1 of group 1 of window Control Centre of application process ControlCenter

Excellent, and thank you! ioreg solves my problem. Though I could swear I tried it before. Perhaps Ventura fixed something.

1 Like

These things generally go left to right, top to bottom. So:

  • static text Bluetooth of group 1 of window Control Centre of application process ControlCenter
    • the "Bluetooth" label at the top
  • checkbox 1 of group 1 of window Control Centre of application process ControlCenter
    • the off/on slider
  • scroll area 1 of group 1 of window Control Centre of application process ControlCenter
    • ?
  • button 1 of group 1 of window Control Centre of application process ControlCenter
    • the "Bluetooth Settings..." button

By process of elimination, scroll area 1 is the "Devices" section, which is what you want. So the next step is something like:

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		UI elements of scroll area 1 of group 1 of window 1
	end tell
end tell

...and I'd expect the % number to be the third or fourth item, depending on whether the icon and "MX Master" text are one thing or two.

Doesn't UI Browser show you similar? (Not a user...)

When I mouse over the battery %, UI Browser shows me this:

Screenshot

The output of your latest script is:

Output

UI element 1 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter, checkbox 1 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter, checkbox 2 of scroll area 1 of group 1 of window Control Centre of application process ControlCenter

So you can work down our chain to match up with what UI Browser is showing -- we're in window 1 of Control Centre, matching the last 2 lines highlighted in your screenie. And we're looking at group 1, which contains scroll area 1 -- check! So it looks like we're after checkbox 1 (weird, but best not to ask) from which we should be able to get the description then parse out the numbers.

So cross your fingers and try

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		description of checkbox 1 of scroll area 1 of group 1 of window 1
	end tell
end tell

I feel bad because you're really putting in a shift here, but this is all it outputs:

toggle button

That looks like it's pulled role description instead. Perhaps grab all the properties and see of you can spot the right one?

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		properties of checkbox 1 of scroll area 1 of group 1 of window 1
	end tell
end tell

The battery level is currently still 90%. Can't see it here:

minimum value:missing value, orientation:missing value, position:1496, 95, class:checkbox, accessibility description:missing value, role description:toggle button, focused:missing value, title:missing value, size:288, 32, help:missing value, entire contents:, enabled:true, maximum value:missing value, role:AXCheckBox, value:1, subrole:AXToggle, selected:missing value, name:missing value, description:toggle button

Then it may be getting it from AXAttributedDescription. Those attribute values are the ones we're failing to get in Ventura, but you might be OK:

tell application "System Events"
	tell process "Control Centre"
		set btMenu to item 1 of (every menu bar item of menu bar 1 whose value of attribute "AXAttributedDescription" is "Bluetooth")
		click btMenu
		value of attribute "AXAttributedDescription" of checkbox 1 of scroll area 1 of group 1 of window 1
	end tell
end tell

I'm on Ventura and the script fails I'm afraid.

CleanShot 2022-11-08 at 19.44.30@2x