问题
I'm using this BetterTouchToll for make my touch bar more interesting, what is very cool.
He accept some Apple Scripts for more dynamic, so I start to study this scripts.
Now I wanna to display my Magic Mouse Battery on my touch bar, for this I was trying this code, but is not working.
if application "Mouse" is running then
tell application "Mouse"
return (get Battery)
end tell
end if
return "no mouse"
My guess is that Mouse is not a application, but don't know what to put in the place
回答1:
The traditional means of getting the battery level is to use ioreg
on the command line. However, the traditional means of doing this no longer seem to work as of at least macOS High Sierra/10.13.4; that is, they no longer allow choosing to display just the battery percentage of a single bluetooth device.
So this is a hack that assumes that the Magic Mouse is always the last device displayed by ioreg. This is likely to fail, if not across different installations of macOS, then across different versions.
ioreg -c AppleDeviceManagementHIDEventService | grep BatteryPercent | tail -1 | sed 's/[^[:digit:]]//g'
In an AppleScript, this would be:
do shell script "ioreg -c AppleDeviceManagementHIDEventService | grep BatteryPercent | tail -1 | sed 's/[^[:digit:]]//g'"
You have your code setup to also detect when the Magic Mouse is not connected. The product name is in the property “Product” in ioreg. For example:
ioreg -c AppleDeviceManagementHIDEventService | grep '"Product" ='
So to make sure that this final device is the Mouse, you could do:
set finalDevice to do shell script "ioreg -c AppleDeviceManagementHIDEventService | grep '\"Product\" =' | tail -1"
if finalDevice contains "Magic Mouse" then
set remaining to do shell script "ioreg -c AppleDeviceManagementHIDEventService | grep BatteryPercent | tail -1 | sed 's/[^[:digit:]]//g'"
remaining & "%"
else
"no mouse"
end if
The basic logic:
- Grab the list of all products using
ioreg
. - Use
tail
to get only the final product in the list. - If the final product is a Magic Mouse, then:
- Grab the list of all battery percentages using
ioreg
. - Use
tail
to get only the final battery percentage in the list. - Use
sed
to get only the actual number from that line. - Append a percentage symbol to the number.
- Grab the list of all battery percentages using
- Otherwise, there is no mouse. (Or the mouse is not the final item in the list.)
For the older means of using ioreg
, see, for example:
- Reporting on Bluetooth Mouse/Keyboard battery status
- Read Magic Mouse and Apple Wireless Keyboard Battery percentage
回答2:
Thanks so much for the solution. Very inspiring. As I have multiple devices I made my own script based on your solutions. I want to share it here in case it could be useful to others.
As I have more than one bluetooth device, the order of them in ioreg is based on the order they were connected. Which means I cannot assume that the mouse is the last device.
I made most of it in shell, not in applescript, since I am more experienced in shell and therefore it was quicker that way. Using Applescript for filtering the output from ioreg would properly have been a 'cleaner' solution :p
WARNING: I know this code is pretty crappy, but it was quick to write and it does the job, don't assume this to be a way of doing things properly.
My solution
From BTT the following script calls the shell script
set devicename to "Magic Mouse 2" -- The name of the device in ioreg
set displayname to "Mouse" -- The name to display on the touchbar
set remaining to do shell script "~/.dotfiles/shell/device_battery_level.sh" & " " & quoted form of devicename
if remaining is "" then
"" --No device present = no output to touchbar
else
displayname & " " & remaining & "%" -- Show output on touchbar
end if
As seen the code pretty much just calls the shell script. The name provided in the variable "devicename" is used as a argument to the script and is the name that the script will look for in ioreg. If the shell script outputs an empty script no widget will be displayed. For me this was preferred over displaying "No device".
The script in "~/.dotfiles/shell/device_battery_level.sh" then looks like this:
#!/bin/sh
DEVICES=$(ioreg -r -l -n AppleHSBluetoothDevice | egrep '"BatteryPercent" = |^ \| "Bluetooth Product Name" = ') #Lets get a list of all bluetooth devices
DEVICELINE=$(grep -n "$1" <<< "$DEVICES") #$1 is the device that this script was called with. Lets extract only the line with that device
if [$DEVICELINE = ""] #If DEVICELINE is empty the name of the device was not in the output and it is properly not connected.
then
echo "" #Device not present, lets give BTT an empty string
else
LINENR="${DEVICELINE:0:1}" #Then we find out where the line of the device is located
NEXTLINE=$(expr $LINENR + "1") #The battery level is at the next line therefore we increment the line number
SEDCOMMAND="p"
BATTERYLINE=$(echo "$DEVICES" | sed -n $NEXTLINE$SEDCOMMAND) # Now we can extract the line with the battery percent
echo $BATTERYLINE | sed 's/[^[:digit:]]//g' #Finally we just need to get the digit and echo that to BTT
fi
The basic logic is the same as the above answer. Except instead of grabbing the last line from ioreg with tail egrep is used to only output relevant lines. The egrep code is based on another post here: https://apple.stackexchange.com/questions/293502/how-can-i-determine-the-battery-level-of-my-magic-mouse-from-the-command-line/293505#293505 Based on this the line which mentions the devicename is found. The logic is that since the battery level information is always below the devicename in ioreg the next line in the extracted list must be the battery level.
来源:https://stackoverflow.com/questions/50190787/display-magic-mouse-battery-in-touch-bar-using-bettertouchtool