PDA

View Full Version : Simple Idea, where to start?




ArtOfWarfare
Jan 9, 2012, 07:34 PM
I'd like to make an app that displays the battery status of everything connected to the computer, say, a magic trackpad, wireless mouse or keyboard... maybe even an attached iPad or iPhone.

Unfortunately, I don't know where to look. I searched through the Apple docs but it seems that everything related to batteries brings up iOS references and everything related to the trackpad has to do with handling events.

So, any pointers on how I could make an app request the current battery status of any attached magic trackpads, for example?



phantax
Jan 9, 2012, 07:57 PM
You can get the battery percentage from ioreg, I am not sure if the bluetooth devices will give further detail such as battery capacity, etc.

Apple Keyboard:
ioreg -n "AppleBluetoothHIDKeyboard" | grep -i "batterypercent"

Magic Mouse:
ioreg -n "BNBMouseDevice" | grep -i "batterypercent"

ArtOfWarfare
Jan 9, 2012, 08:08 PM
Battery percent will be fine for my purposes.

Unless I'm mistaken, the code you gave is for terminal (which I'm going to have to confess I'm borderline clueless on how to use... I'll need to remedy that someday soon I'm sure,) would it be possible for you to tell me how I might have an NSLog that outputs the battery percentage in applicationDidFinishLaunching?

KnightWRX
Jan 9, 2012, 08:15 PM
http://developer.apple.com/library/mac/#documentation/devicedrivers/conceptual/IOKitFundamentals/TheRegistry/TheRegistry.html#//apple_ref/doc/uid/TP0000014-TP9

Sounds pretty much like what you need to be using.

willieva
Jan 9, 2012, 08:33 PM
You can get the battery percentage from ioreg, I am not sure if the bluetooth devices will give further detail such as battery capacity, etc.

Apple Keyboard:
ioreg -n "AppleBluetoothHIDKeyboard" | grep -i "batterypercent"

Magic Mouse:
ioreg -n "BNBMouseDevice" | grep -i "batterypercent"

This output of this for my mouse is 65%. Yet when I click on the bluetooth logo on the menu bar and look at the device there, it says 100%. Since the batteries are fresh, I'm inclined to believe that number. Can anyone explain this discrepancy?

phantax
Jan 9, 2012, 08:41 PM
Seems there is a bug in Lion which hasn't been addressed yet, I saw some postings discussing it.

My findings are the opposite. My keyboard shows 100% in system preferences, ioreg shows 73% and the batteries are over a month old.

thundersteele
Jan 10, 2012, 12:44 AM
Battery percent will be fine for my purposes.

Unless I'm mistaken, the code you gave is for terminal (which I'm going to have to confess I'm borderline clueless on how to use... I'll need to remedy that someday soon I'm sure,) would it be possible for you to tell me how I might have an NSLog that outputs the battery percentage in applicationDidFinishLaunching?

Option 1:
Call the terminal code from within your program (NSTask), pipe it into a string (NSpipe) and parse it for the information you are looking for.

Option 2:
Look into IOkit and the IOregistry.


For option 1, I found some useful information here:
http://stackoverflow.com/questions/412562/execute-a-terminal-command-from-a-cocoa-app

For option 2... it's a mess... takes some time to learn, I still have to figure it out. One of Apples sample codes has implemented something like that, might be useful.

seepel
Jan 10, 2012, 08:48 AM
In my experience "simple ideas" are simple if Apple nticipates you doing it, and rather convoluted if they don't. I think this might fall into the latter category.

KnightWRX
Jan 10, 2012, 08:53 AM
In my experience "simple ideas" are simple if Apple nticipates you doing it, and rather convoluted if they don't. I think this might fall into the latter category.

Except as has been pointed out, the IO Registry does just this.

I myself would write this as a Dashboard widget or a menu bar icon.

seepel
Jan 10, 2012, 10:42 AM
Except as has been pointed out, the IO Registry does just this.

I myself would write this as a Dashboard widget or a menu bar icon.

Don't get me wrong I'm not saying it can't be done, but as per the bugs that were reported above, and adding in phones etc... I am just am little skeptical that the implementation can be as simple as the concept. There are often posts about simple ideas, and I'd like to caution that in my experience simple ideas often turn not so simple pretty quickly.

ArtOfWarfare
Jan 10, 2012, 03:42 PM
Except as has been pointed out, the IO Registry does just this.

I myself would write this as a Dashboard widget or a menu bar icon.

Ultimately I'd like to make a menu bar icon, but I figured I'd explore one thing I'm unfamiliar with at a time. So for the first attempt at this, I'm just going to make a single window application. Once I've gotten that figured out I'll try to do it as a menu bar icon. (Will Apple allow menu bar icons to be sold via the Mac App Store?)

Edit: I read what KnightWRX posted a link to, and... I still can't write a single line of code in the right direction for this.

Does anyone have any sample code that could help? It seems like this aught to be extremely simple, something like

[IOReg registeredDevices];

or... I suppose it would be C or C++, not Obj-C... still... I can't imagine a program for just making an NSLog with the battery percent would take more than ten lines of code.

2X Edit:

BNBTrackpadDevice inherits from BNBTrackpadDevice, BNBDevice, BluetoothMultitouchTransport, IOAppleBluetoothHIDDriver, IOBluetoothHIDDriver, IOHIDDevice, IOService, IORegistryEntry, and OSObject.

...

This almost seems like useful information, except the documentation on these classes... doesn't exist? It's not what I want. I want a function I can call to someone, get the device registry, and then a function that I can use to get the device registry to tell me which devices have BatteryPercent as a property...

3X Edit:

I'm finally making it somewhere... I've now written some C++ code that iterates through the registry and outputs the IOClass property for everything... I'll update this post once I've gotten it to give names and battery percents instead.

ArtOfWarfare
Jan 10, 2012, 09:35 PM
I get this log output:

Apple Wireless Trackpad - 100%

So... it works!

Next, I need to figure out how to move this into a window... and then after that, into the menubar. Getting this to appear in a window shouldn't be difficult, but the menubar is going to be a bit more difficult.

Does anyone know how I can
1 - Make the app run in the background, that is, without a dock icon
2 - Make an icon appear on the right side of the menubar, IE, where the battery icon on a laptop would show up
3 - Bundle it in such a way it'd be acceptable on the Mac App Store

Here's the code I'm using right now:
#import "BatTAppDelegate.h"

@implementation BatTAppDelegate

@synthesize window = _window;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
mach_port_t masterPort;
kern_return_t kr;
io_iterator_t ite;
io_object_t obj = 0;
CFMutableDictionaryRef properties;

kr = IOMasterPort(bootstrap_port, &masterPort);
if (kr != KERN_SUCCESS)
printf("IOMasterPort() failed: %x\n", kr);

kr = IORegistryCreateIterator(masterPort,
kIOServicePlane,
true, /* recursive */
&ite);

while ((obj = IOIteratorNext(ite)))
{
kr = IORegistryEntryCreateCFProperties(obj,
&properties,
kCFAllocatorDefault,
kNilOptions);

if ((kr != KERN_SUCCESS) || !properties) {
printf("IORegistryEntryCreateCFProperties error %x\n", kr);
}

else
{
CFNumberRef percent = (CFNumberRef) CFDictionaryGetValue(properties, CFSTR("BatteryPercent"));
if (percent)
{
SInt32 s;
if(!CFNumberGetValue(percent, kCFNumberSInt32Type, &s))
{
printf("***CFNumber overflow***\n");
}

else
{
CFStringRef name = (CFStringRef) CFDictionaryGetValue(properties, CFSTR("Product"));

const char * c = CFStringGetCStringPtr(name, kCFStringEncodingMacRoman);

if (c)
printf(c);
else
{
CFIndex bufferSize = CFStringGetMaximumSizeForEncoding(CFStringGetLength(name), kCFStringEncodingMacRoman) + sizeof('\0');
char * buffer = (char *) malloc(bufferSize);

if (buffer)
{
if ( CFStringGetCString(
/* string */ name,
/* buffer */ buffer,
/* bufferSize */ bufferSize,
/* encoding */ kCFStringEncodingMacRoman) )
printf(buffer);

free(buffer);
}
}

printf(" - %d%%\n", (int)s);
}

}

else
{
//There wasn't a battery.
}
}
}
}

@end

KnightWRX
Jan 11, 2012, 04:15 AM
Edit: I read what KnightWRX posted a link to, and... I still can't write a single line of code in the right direction for this.

Does anyone have any sample code that could help? It seems like this aught to be extremely simple, something like

[IOReg registeredDevices];

or... I suppose it would be C or C++, not Obj-C... still... I can't imagine a program for just making an NSLog with the battery percent would take more than ten lines of code.

I once set out to write a pretty simple Win32 apps (some 10 years ago). I wanted to check if the main volume in the sound mixer was muted. If it wasn't, I wanted to mute it, if it was, I wanted to unmute it. Basically, a quite mute toggle.

Simple uh ?

I ended up with something like 200 lines of codes and reading documentation on setting up about 3-4 big structs to pass along the various stages of the mixer API.

Low-level APIs are like that unfortunately.

ArtOfWarfare
Jan 11, 2012, 06:44 AM
I once set out to write a pretty simple Win32 apps (some 10 years ago). I wanted to check if the main volume in the sound mixer was muted. If it wasn't, I wanted to mute it, if it was, I wanted to unmute it. Basically, a quite mute toggle.

Simple uh ?

I ended up with something like 200 lines of codes and reading documentation on setting up about 3-4 big structs to pass along the various stages of the mixer API.

Low-level APIs are like that unfortunately.

I'm just going to have to use them more and get more comfortable with them, I think, given I'm going to be applying for an internship at Apple this summer (I'm not really expecting to get it, and I am applying for internships at other companies as well.)

Anyways, the code works, and it's entirely written in C (unless I'm mistaken.)

Getting it to appear in a windowed application would be a trivial step, but I'm curious if it'd be a step in the wrong direction.

I'd like to:
1 - Make the app run in the background, that is, without a dock icon
2 - Make an icon appear on the right side of the menubar, IE, where the battery icon on a laptop would show up
3 - Bundle it in such a way it'd be acceptable on the Mac App Store

Any suggestions?

KnightWRX
Jan 11, 2012, 09:00 AM
Getting it to appear in a windowed application would be a trivial step, but I'm curious if it'd be a step in the wrong direction.

I'd like to:
1 - Make the app run in the background, that is, without a dock icon
2 - Make an icon appear on the right side of the menubar, IE, where the battery icon on a laptop would show up
3 - Bundle it in such a way it'd be acceptable on the Mac App Store

Any suggestions?

I'm not versed in those areas of Mac development unfortunately. Maybe someone else can help you out on those.

seepel
Jan 11, 2012, 09:18 AM
I'm just going to have to use them more and get more comfortable with them, I think, given I'm going to be applying for an internship at Apple this summer (I'm not really expecting to get it, and I am applying for internships at other companies as well.)

Anyways, the code works, and it's entirely written in C (unless I'm mistaken.)

Getting it to appear in a windowed application would be a trivial step, but I'm curious if it'd be a step in the wrong direction.

I'd like to:
1 - Make the app run in the background, that is, without a dock icon
2 - Make an icon appear on the right side of the menubar, IE, where the battery icon on a laptop would show up
3 - Bundle it in such a way it'd be acceptable on the Mac App Store

Any suggestions?

1 - In your plist there is an element that needs the raw value LSUIElement (or something close to that) set to YES
2 - NSStatusItem
3 - nothing special needed here, just follow the normal guidelines.

ArtOfWarfare
Jan 11, 2012, 04:53 PM
1 - In your plist there is an element that needs the raw value LSUIElement (or something close to that) set to YES
2 - NSStatusItem
3 - nothing special needed here, just follow the normal guidelines.

Thanks for the keywords :)

This was too easy... I followed this tutorial a bit:
http://www.sonsothunder.com/devres/livecode/tutorials/StatusMenu.html

and I also looked at Apple's sample project entitled "ItemMenuView".