summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2017-01-26 18:29:20 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2017-01-26 18:29:20 +0100
commit109f873ea81b28c9f82142a556f75e68256dbaa5 (patch)
tree8ce8b83bdde772db984e69b823849b33e57aa8b2
parent13114eefc8da22a7b18a8e7f0b877044ac0e1897 (diff)
downloadpsutil-109f873ea81b28c9f82142a556f75e68256dbaa5.tar.gz
#955: sensors_batter() win impl
-rw-r--r--docs/index.rst28
-rw-r--r--psutil/__init__.py2
-rw-r--r--psutil/_common.py13
-rw-r--r--psutil/_pslinux.py2
-rw-r--r--psutil/_psutil_windows.c27
-rw-r--r--psutil/_pswindows.py26
-rwxr-xr-xpsutil/tests/test_system.py5
7 files changed, 101 insertions, 2 deletions
diff --git a/docs/index.rst b/docs/index.rst
index 0131b56a..8db5b111 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -617,6 +617,25 @@ Network
.. versionadded:: 3.0.0
+Sensors
+-------
+
+.. function:: sensors_battery()
+
+ Return a namedtuple with the following values:
+
+ - **percent**: battery power left as a percentage.
+ - **secsleft**: number of seconds left before battery run out of power; this
+ may also be :data:`psutil.POWER_TIME_UNKNOWN <psutil.POWER_TIME_UNKNOWN>`
+ or :data:`psutil.POWER_TIME_UNLIMITED <psutil.POWER_TIME_UNLIMITED>`.
+
+ If no battery is installed this function will return ``None``.
+
+ Availability: Linux, Windows
+
+ .. versionadded:: 5.1.0
+
+
Other system info
-----------------
@@ -1984,6 +2003,15 @@ Constants
.. versionadded:: 3.0.0
+.. _const-power:
+.. data:: POWER_TIME_UNKNOWN
+.. data:: POWER_TIME_UNLIMITED
+
+ This can be the value of *secsleft* field of
+ :func:`psutil.sensors_battery()`.
+
+ .. versionadded:: 5.1.0
+
.. _const-version-info:
.. data:: version_info
diff --git a/psutil/__init__.py b/psutil/__init__.py
index 7e3217df..745d66fd 100644
--- a/psutil/__init__.py
+++ b/psutil/__init__.py
@@ -171,6 +171,8 @@ __all__ = [
"NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN",
+ "POWER_TIME_UNKNOWN", "POWER_TIME_UNLIMITED",
+
"BSD", "FREEBSD", "LINUX", "NETBSD", "OPENBSD", "OSX", "POSIX", "SUNOS",
"WINDOWS",
diff --git a/psutil/_common.py b/psutil/_common.py
index 4342d254..b28af999 100644
--- a/psutil/_common.py
+++ b/psutil/_common.py
@@ -121,6 +121,17 @@ else:
globals().update(NicDuplex.__members__)
+# sensors_battery()
+if enum is None:
+ POWER_TIME_UNKNOWN = -1
+ POWER_TIME_UNLIMITED = -2
+else:
+ class Power(enum.IntEnum):
+ POWER_TIME_UNKNOWN = -1
+ POWER_TIME_UNLIMITED = -2
+
+ globals().update(NicDuplex.__members__)
+
# ===================================================================
# --- namedtuples
@@ -159,7 +170,7 @@ scpustats = namedtuple(
# psutil.cpu_freq()
scpufreq = namedtuple('scpufreq', ['current', 'min', 'max'])
# psutil.sensors_battery()
-sbattery = namedtuple('sbattery', ['percent'])
+sbattery = namedtuple('sbattery', ['percent', 'secsleft'])
# --- for Process methods
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py
index 1a5304a6..0fba0fa6 100644
--- a/psutil/_pslinux.py
+++ b/psutil/_pslinux.py
@@ -1075,7 +1075,7 @@ def sensors_battery():
# energy_full = int(cat(root + "energy_full"))
# secsleft = 3600 * energy_now / power_now
percent = int(cat(root + "capacity"))
- return _common.sbattery(percent)
+ return _common.sbattery(percent, 0)
# =====================================================================
diff --git a/psutil/_psutil_windows.c b/psutil/_psutil_windows.c
index 4caace7d..74edc6cd 100644
--- a/psutil/_psutil_windows.c
+++ b/psutil/_psutil_windows.c
@@ -3456,6 +3456,31 @@ error:
}
+/*
+ * Return battery usage stats.
+ */
+static PyObject *
+psutil_sensors_battery(PyObject *self, PyObject *args) {
+ SYSTEM_POWER_STATUS sps;
+
+ if (GetSystemPowerStatus(&sps) == 0) {
+ PyErr_SetFromWindowsErr(0);
+ return NULL;
+ }
+ return Py_BuildValue(
+ "iiiI",
+ sps.ACLineStatus, // whether AC is connected: 0=no, 1=yes, 255=unknown
+ // status flag:
+ // 1, 2, 4 = high, low, critical
+ // 8 = charging
+ // 128 = no battery
+ sps.BatteryFlag,
+ sps.BatteryLifePercent, // percent
+ sps.BatteryLifeTime // remaining secs
+ );
+}
+
+
// ------------------------ Python init ---------------------------
static PyMethodDef
@@ -3562,6 +3587,8 @@ PsutilMethods[] = {
"Return NICs stats."},
{"cpu_freq", psutil_cpu_freq, METH_VARARGS,
"Return CPU frequency."},
+ {"sensors_battery", psutil_sensors_battery, METH_VARARGS,
+ "Return battery metrics usage."},
// --- windows services
{"winservice_enumerate", psutil_winservice_enumerate, METH_VARARGS,
diff --git a/psutil/_pswindows.py b/psutil/_pswindows.py
index da8552e1..80faec91 100644
--- a/psutil/_pswindows.py
+++ b/psutil/_pswindows.py
@@ -362,6 +362,32 @@ def net_if_addrs():
# =====================================================================
+# --- sensors
+# =====================================================================
+
+
+def sensors_battery():
+ acline_status, flags, percent, secsleft = cext.sensors_battery()
+ power_connected = acline_status == 1
+ no_battery = bool(flags & 128)
+ charging = bool(flags & 8)
+
+ # print("acline_status=%s, flags=%s, percent=%s, secsleft=%s" % (
+ # acline_status, flags, percent, secsleft))
+ # print("power_connected=%s, no_battery=%s, charging=%s" % (
+ # power_connected, no_battery, charging))
+
+ if no_battery:
+ return None
+ if power_connected or charging:
+ secsleft = _common.POWER_TIME_UNLIMITED
+ elif secsleft == -1:
+ secsleft = _common.POWER_TIME_UNKNOWN
+
+ return _common.sbattery(percent, secsleft)
+
+
+# =====================================================================
# --- other system functions
# =====================================================================
diff --git a/psutil/tests/test_system.py b/psutil/tests/test_system.py
index 58b7c9c0..906641e4 100755
--- a/psutil/tests/test_system.py
+++ b/psutil/tests/test_system.py
@@ -758,9 +758,14 @@ class TestSystemAPIs(unittest.TestCase):
"platform not supported")
def test_sensors_battery(self):
ret = psutil.sensors_battery()
+ if ret is None:
+ return # no battery
if ret.percent is not None:
self.assertGreaterEqual(ret.percent, 0)
self.assertLessEqual(ret.percent, 100)
+ if ret.secsleft not in (psutil.POWER_TIME_UNKNOWN,
+ psutil.POWER_TIME_UNLIMITED):
+ self.assertGreaterEqual(ret.secsleft, 0)
if __name__ == '__main__':