Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Battery Capacity in Windows with Python

I am looking to figure out both the current Battery Capacity and the Design Capacity.

So far what I could get to work is using the Win32_Battery() class which doesn't give all the information I need (at least not on my system). I used the pure-python wmi library for that.

On the other hand I found this which works In Python, how can I detect whether the computer is on battery power?, but unfortunately it doesn't provide any information on Capacity neither.

The Battery Information structure and the Battery Status structure seem perfect for this. Now I know that I have to use the DeviceIoControl function to do so and I found this C++ code that explains it a little.

I would prefer something that simply uses ctypes and not the python win32api provided by pywin32. If you have an idea how to do this in python please let me know!

Thanks in advance.

like image 584
cwoebker Avatar asked May 05 '13 01:05

cwoebker


2 Answers

Tim Golden's excellent wmi module will, I believe, give you everything you want. You'll just have to do several queries to get everything:

import wmi

c = wmi.WMI()
t = wmi.WMI(moniker = "//./root/wmi")

batts1 = c.CIM_Battery(Caption = 'Portable Battery')
for i, b in enumerate(batts1):
    print 'Battery %d Design Capacity: %d mWh' % (i, b.DesignCapacity or 0)


batts = t.ExecQuery('Select * from BatteryFullChargedCapacity')
for i, b in enumerate(batts):
    print ('Battery %d Fully Charged Capacity: %d mWh' % 
          (i, b.FullChargedCapacity))

batts = t.ExecQuery('Select * from BatteryStatus where Voltage > 0')
for i, b in enumerate(batts):
    print '\nBattery %d ***************' % i
    print 'Tag:               ' + str(b.Tag)
    print 'Name:              ' + b.InstanceName

    print 'PowerOnline:       ' + str(b.PowerOnline)
    print 'Discharging:       ' + str(b.Discharging)
    print 'Charging:          ' + str(b.Charging)
    print 'Voltage:           ' + str(b.Voltage)
    print 'DischargeRate:     ' + str(b.DischargeRate)
    print 'ChargeRate:        ' + str(b.ChargeRate)
    print 'RemainingCapacity: ' + str(b.RemainingCapacity)
    print 'Active:            ' + str(b.Active)
    print 'Critical:          ' + str(b.Critical)

This is certainly not cross-platform, and it requires a 3rd party resource, but it does work very well.

like image 162
MikeHunter Avatar answered Oct 13 '22 11:10

MikeHunter


The most reliable way to retrieve this information is by using GetSystemPowerStatus instead of WMI. psutil exposes this information under Linux, Windows and FreeBSD:

>>> import psutil
>>>
>>> def secs2hours(secs):
...     mm, ss = divmod(secs, 60)
...     hh, mm = divmod(mm, 60)
...     return "%d:%02d:%02d" % (hh, mm, ss)
...
>>> battery = psutil.sensors_battery()
>>> battery
sbattery(percent=93, secsleft=16628, power_plugged=False)
>>> print("charge = %s%%, time left = %s" % (battery.percent, secs2hours(battery.secsleft)))
charge = 93%, time left = 4:37:08

The relevant commit is here.

like image 29
Giampaolo Rodolà Avatar answered Oct 13 '22 11:10

Giampaolo Rodolà