PDA

View Full Version : Accessing battery information




thundersteele
Jan 6, 2012, 05:27 PM
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
Jan 6, 2012, 06:36 PM
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
Jan 8, 2012, 06:12 PM
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
Jan 15, 2012, 04:55 AM
Ok, after another day of trial and error, I got it sorted out :)
The relevant code ended up being very short!


#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
Feb 21, 2014, 09:50 AM
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
Feb 23, 2014, 12:48 PM
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.

chown33
Feb 23, 2014, 02:05 PM
Fun fact: you can cast most Core Foundation objects into Objective C classes.

This capability is called "toll-free bridging". The reference doc is here:
https://developer.apple.com/library/mac/documentation/General/Conceptual/CocoaEncyclopedia/Toll-FreeBridgin/Toll-FreeBridgin.html#//apple_ref/doc/uid/TP40010810-CH2