バッテリーの状況

Windows でバッテリーの状況は Win32API の関数を使うと取れる。しかし pywin32 *1 には肝心の GetSystemPowerStatus 関数 *2 がないじゃないか。

しょうがないので伝家の宝刀 ctypes *3 を使うべ。GetSystemPowerStatus 関数自体はそう難しくない。所定の構造体へのポインターを渡すと、バッテリーの情報を入れてくれる、というよくあるパターンだ。これならC初心者の自分にもできるはずだ。

まずは import

import ctypes
from ctypes import wintypes

wintypes には BYTE や DWORD などの型が定義されている。どのように typedef されているのかわざわざ調べなくても済む。

次に、SYSTEM_POWER_STATUS 構造体を作ろう。http://msdn.microsoft.com/en-us/library/aa373232%28VS.85%29.aspx を見てどのようなメンバーがあるかのか調べて並べる。

class SYSTEM_POWER_STATUS(ctypes.Structure):
    _fields_ = [("ACLineStatus", wintypes.BYTE),
                ("BatteryFlag", wintypes.BYTE),
                ("BatteryLifePercent", wintypes.BYTE),
                ("Reserved1", wintypes.BYTE),
                ("BatteryLifeTime", wintypes.DWORD),
                ("BatteryFullLifeTime", wintypes.DWORD),
                ]

stat = SYSTEM_POWER_STATUS()  # さっそく1個作る

O.K.

次に GetSystemPowerStatus 関数の詳細を調べる。http://msdn.microsoft.com/en-us/library/aa372693%28VS.85%29.aspx

ページの終わりにある requirements を見よう。場所は Kernel32.dll だから ctypes.windll.kernel32.GetSystemPowerStatus で関数が呼び出せる。

戻り値が BOOL であることを知せるために、

ctypes.windll.kernel32.GetSystemPowerStatus.restype = wintypes.BOOL

とやる。

最後に、引数はポインタ渡しだから、

nerr = ctypes.windll.kernel32.GetSystemPowerStatus(ctypes.byref(stat))

のように呼べばいい。

完成図はこうだ。

#! c:\Python25\python.exe 
# -*- coding: cp932 -*-

import ctypes
from ctypes import wintypes

class SYSTEM_POWER_STATUS(ctypes.Structure):
    _fields_ = [("ACLineStatus", wintypes.BYTE),
                ("BatteryFlag", wintypes.BYTE),
                ("BatteryLifePercent", wintypes.BYTE),
                ("Reserved1", wintypes.BYTE),
                ("BatteryLifeTime", wintypes.DWORD),
                ("BatteryFullLifeTime", wintypes.DWORD),
                ]

stat = SYSTEM_POWER_STATUS()
ctypes.windll.kernel32.GetSystemPowerStatus.restype = wintypes.BOOL
nerr = ctypes.windll.kernel32.GetSystemPowerStatus(ctypes.byref(stat))

if not nerr:
    import sys
    sys.exit('情報が取得できません。')

if stat.ACLineStatus == 0:
    print '電源に接続していません。'
elif stat.ACLineStatus == 1:
    print '電源に接続しています。'
elif stat.ACLineStatus == 255:
    print '電源の状態が不明です。'

if stat.BatteryLifePercent == 255:
    print '残量不明'
else:
    print "残量 %d%%" % stat.BatteryLifePercent

*1:Python for Windows extnsions とも言う。いまだに正確な名前がわからん…。

*2:なぜか Windows CE 用の GetSystemPowerStatusEx 関数だけはある。CeGetSystemPowerStatusEx という名前だ。普通のコンピュータは別の方法があるよ♪と暗に言っているように見えなくもないが、方法が見つからない。

*3:伝家とか言いながら、標準ライブラリに入ったのは Python 2.5 からだ。