Introducing battery crate

My latest pet project has now matured enough to be properly announced and I’m happy to do that.
For the last few years my notebook battery had degraded terribly and this fact gave me an idea about the rust crate1, with which I can learn new stuff besides usual web development activities and contribute something useful to the community.

All operating systems provide routines for battery information fetching, but those are very different by nature — Linux is creating the power_supply class in the sysfs, Windows is exposing functions via a Power Management API and FreeBSD suggests reading data from /dev/acpi device.
With Linux you will get current energy value in µWh (with few extra steps2) and Mac OS returns mAh units; there are a lot of differences can be found when you’re creating a cross-platform software.

This is not cool and as a programmer, I definitely want to have the same interface over all possible operating systems; yet there were none, so I made it by myself — that’s how battery crate was born.
Right now it has the very simple interface: you can iterate over available batteries and fetch various information about them:

fn main() {
    let manager = battery::Manager::new();
    for battery in manager.iter() {
        println!("Vendor: {}", battery.vendor().unwrap_or("unknown"));
        println!("Percentage: {} %", battery.percentage());
        println!("Capacity: {:.2} %", battery.capacity());
    }
}

You will get an output similar to this:

Vendor: DP
Percentage: 57 %
Capacity: 68.41 %

As a showcase example, here is a screencast of the assistant crate battery-cli, which helps you to see all needed information in the console similar to the top, htop and other -top utilities:

OS support

At the moment of writing this post battery is compatible with:

  • Linux 2.6.39+
  • Windows 7+3
  • Mac OS 10.103
  • FreeBSD
  • DragonFlyBSD

There definitely will be implementations for NetBSD, OpenBSD and Solaris, and it would be nice to have Android, iOS and Fuchsia integrations, but I’m not sure yet if it is even possible.

Other languages

There is one more assistant crate — battery-ffi, which is exposing FFI bindings for main crate, so it can be used with C, Python, JS or whatever you want.
GitHub repository has two examples written in C and Python, you can check them out:

manager = lib.battery_manager_new()
iterator = lib.battery_manager_iter(manager)
while True:
    battery = lib.battery_iterator_next(iterator)
    if not battery:
        break

    print('Vendor', lib.battery_get_vendor(battery))
    print('Percentage (%)', lib.battery_get_percentage(battery))
    print('Capacity (%)', lib.battery_get_capacity(battery))

    lib.battery_free(battery)

lib.battery_iterator_free(battery)
lib.battery_manager_free(manager)

It is still in the experimental phase, but I would love to hear if you’re interested in using it and have some thoughts about API provided.

What’s next?

There is still a lot of work to do 😁

First of all, I’m still not sure about library public interface — while all operating systems from above provides the same information about installed batteries, this assumption might be wrong for the not-yet-supported systems.

Few smelly code pieces and maybe even bugs exist — but this is okay for the first “alpha” milestone, further work and community contributions will solve this.
Internal implementation is terribly bad for some target systems right now: for Linux it is reading too much files each time, Mac OS part is using obsolete libraries for FFI communication and both FreeBSD and Mac OS are not capable to support more than one battery; I’m going to fix that :)

Also, I do not have so many different devices with various systems installed; lucky me that VirtualBox creates a virtual battery device for each running VM, at least I can test the prototypes.

In any way, this is funny, I’m learning a lot and hope that someone will find this library useful.

Similar projects


  1. crate” is a Rust term for “package” as in some other languages [return]
  2. I’m going to write a series of posts about found caveats later [return]
  3. Maybe it will work with previous versions, but I can’t guarantee that [return]