Scripting Batteries and UPS on Mac OS X

Power Manager provides scripting access to the power sources of the Mac, including Uninterruptible Power Supplies (UPS). You can access the power source information using AppleScript or through the command line.

Developers can use Power Manager’s Software Development Kit (SDK) to integrate this information into your tools.

Power Manager provides a range of triggers and conditions that deal with power supplies and their states. When we created these triggers and conditions, we discovered there was no scriptable way to access to this information as a user. To rectify this, we added the Power API.

The Power API provides a list of all the power sources available to your Mac; these include batteries and uninterruptible power supplies.

Shell Scripts and Tools

Listing the power sources in Terminal.app

Listing the power sources in Terminal.app

Using the tool pmctl, you can list your Mac’s power supplies with the following command:

cd /Library/Application\ Support/Power\ Manager/Tools/
./pmctl power.sources

On a MacBook Pro with its internal battery, this pmctl command might respond with:

[{"charging"=>0,"health"=>"good","present"=>1,"current capacity"=>98,"seconds remaining"=>17040,"Name"=>"InternalBattery-0","type"=>"internal","state"=>"battery","name"=>"InternalBattery-0"}]

Inserting the additional command line flag of -f xml asks pmctl to provide the output in XML format:

./pmctl -f xml power.sources

This time the response is as an XML Property List formatted file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
	<dict>
		<key>Name</key>
		<string>InternalBattery-0</string>
		<key>charging</key>
		<false/>
		<key>current capacity</key>
		<integer>98</integer>
		<key>health</key>
		<string>good</string>
		<key>name</key>
		<string>InternalBattery-0</string>
		<key>present</key>
		<true/>
		<key>seconds remaining</key>
		<integer>18240</integer>
		<key>state</key>
		<string>battery</string>
		<key>type</key>
		<string>internal</string>
	</dict>
</array>
</plist>

AppleScript

Power API documentation in AppleScript Editor.app

Power API documentation in AppleScript Editor.app

The equivalent in AppleScript is to ask for the properties of every source of power:

tell application "/Library/Application Support/Power Manager/Agents/Power Manager Scripting.app"
    set mySources to properties of every power source in Power
end tell

The response mirrors pmctl’s output:

{{health:good, charging:false, confidence:missing value, present:true, seconds remaining:22140, class:power source internal, current capacity:97, name:"InternalBattery-0", state:battery}}

Interpreting the properties returned from power sources requires a little understanding of what is possible. There are numerous states a battery might be in, for example the battery may be charging and plugged in, it may be unplugged but not in use, or it may be discharging. This is not a complete list and it does not deal with combinations involving the battery’s health.

So how do you work with this new scripting access to the power source? You probably want to know one or two main pieces of information.

  • Is the battery being used? Look for state = battery.
  • Is mains power connected? Look for state = ac power.
  • How much power is left in the battery? Use the current capacity property.

The developer documentation for all the properties is in the Power Manager Developer Guide.

As an aside, note that power sources is plural. There can be more than one power source; a laptop could be connected to an external UPS. Apple has shipped laptops with support for two internal batteries.

Power Manager can be used to trigger events based on changes to your power sources. There is no compelling reason to write scripts that regularly poll for power changes; better to create an event in Power Manager and have it run your scripts or actions.

The Power API lets you discover the power state of your Mac from within scripts and AppleScripts. We expect this insight will be useful when deciding if tasks should be performed or not - such as avoiding software updates while the battery is low or not plugged into the mains.