Mac Accessing battery information

thundersteele

macrumors 68030
Original poster
Oct 19, 2011
2,984
7
Switzerland
Ok, so I've been teaching myself some Objective C/Cocoa, using Xcode 4.2 on Lion. The goal is to get something like Coconut Battery with some added functionality. I've got it running and it works fine, but right now I'm unhappy with the way I get the battery information.

What I do is call "ioreg -c AppleSmartBattery" from within the class that provides the battery information, and then I read out the information I want from the output. This is not very elegant, and I think there should be a better way to get this information, without calling a shell program.

I found three places that give access to detailed battery information:
1) ioreg in the console
2) system report -> Power
3) IOregistryExplorer in /Developer/Tools

Now, there is the IOKit class in the OSX Dev package. In particular, IOPowerSources.h and IOPSKeys.h provide methods to get battery information, so tried to use those. To my surprise, the information is much less detailed, I only got the current and maximal charge in %, and the battery health, also in %. This was somewhat disappointing.

There must be a better way to get this information, after all the IOregistryExplorer must do it somehow. It seems I will have to find a way to access the IOservices tree. If anyone has any ideas or hints, I would be thankful.
 

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
My understanding is that ioreg outputs the io registry available to IOKit. You should be able to iterate this tree from IOKit and the IOService api to get what you currently get from the ioreg program.
 

thundersteele

macrumors 68030
Original poster
Oct 19, 2011
2,984
7
Switzerland
Thanks for your reply. I found a few examples how to get system information (MAC addresses etc) using the IOKit, and will probably go from there.
 

thundersteele

macrumors 68030
Original poster
Oct 19, 2011
2,984
7
Switzerland
Ok, after another day of trial and error, I got it sorted out :)
The relevant code ended up being very short!

Code:
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>

    CFMutableDictionaryRef properties;
    kern_return_t tester;
    
    // go to battery entry!    
    io_registry_entry_t ioRegistryRoot = 
        IORegistryEntryFromPath(kIOMasterPortDefault, "IOService:/AppleACPIPlatformExpert/SMB0/AppleECSMBusController/AppleSmartBatteryManager/AppleSmartBattery");
    
    // read out properties
    tester=IORegistryEntryCreateCFProperties(ioRegistryRoot, &properties, kCFAllocatorDefault,0);
    
    // set variables to the values from the IOregistry
    CFNumberGetValue((CFNumberRef) CFDictionaryGetValue(properties, CFSTR("CycleCount")), 9, &CycleCount);
    [... and so on...];
The hardest part was getting into non-object oriented programming. And of course finding all the small bits and pieces on how to get a number out of the CFDictionary.
Another useful code sniplet can be found here: http://wranglingmacs.blogspot.com/2009/04/getting-byhost-string.html
This helped me to see how and where to start.
 

DennisBlah

macrumors 6502
Dec 5, 2013
485
2
The Netherlands
I know this is an old topic. But I'm very interested in this charge cycle part.

I want to know more about these stored charge cycles.
When are these increasing ? When an device is fully dead, and fully charged back? Or what, because for my iphone, the charge cycle amount stays 10.
 

Madd the Sane

macrumors 6502a
Nov 8, 2010
508
40
Utah
Fun fact: you can cast most Core Foundation objects into Objective C classes.

Also, in the code snippet you gave, the use of "9" is ambiguous: it took me awhile to remember it's an enum value for the data type of the number you are getting. As it is, it's a "magic number," the use of which is discouraged: if the constant that a magic number (or magic string) is supposed to represent changes, it can result I unexpected behaviors which can lead to bugs.