Skip to content

Commit

Permalink
FreeBSD adding temperature sensors (WIP) (#1350)
Browse files Browse the repository at this point in the history
FreeBSD: add temperature sensors
  • Loading branch information
amanusk authored and giampaolo committed Nov 3, 2018
1 parent 648d8ba commit bb5d032
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 2 deletions.
18 changes: 18 additions & 0 deletions psutil/_psbsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import xml.etree.ElementTree as ET
from collections import namedtuple
from socket import AF_INET
from collections import defaultdict

from . import _common
from . import _psposix
Expand Down Expand Up @@ -437,6 +438,23 @@ def sensors_battery():
secsleft = minsleft * 60
return _common.sbattery(percent, secsleft, power_plugged)

def sensors_temperatures():
"Return CPU cores temperatures if available, else an empty dict."
ret = defaultdict(list)
num_cpus = cpu_count_logical()
for cpu in range(num_cpus):
try:
current, high = cext.sensors_cpu_temperature(cpu)
if high <= 0:
high = None
name = "Core %s" % cpu
ret["coretemp"].append(
_common.shwtemp(name, current, high, high))
except NotImplementedError:
pass

return ret


# =====================================================================
# --- other system functions
Expand Down
2 changes: 2 additions & 0 deletions psutil/_psutil_bsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,8 @@ PsutilMethods[] = {
#if defined(PSUTIL_FREEBSD)
{"sensors_battery", psutil_sensors_battery, METH_VARARGS,
"Return battery information."},
{"sensors_cpu_temperature", psutil_sensors_cpu_temperature, METH_VARARGS,
"Return temperature information for a given CPU core number."},
#endif

// --- others
Expand Down
36 changes: 36 additions & 0 deletions psutil/arch/freebsd/specific.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#define PSUTIL_TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0)
#define PSUTIL_BT2MSEC(bt) (bt.sec * 1000 + (((uint64_t) 1000000000 * (uint32_t) \
(bt.frac >> 32) ) >> 32 ) / 1000000)
#define DECIKELVIN_2_CELCIUS(t) (t - 2731) / 10
#ifndef _PATH_DEVNULL
#define _PATH_DEVNULL "/dev/null"
#endif
Expand Down Expand Up @@ -1010,3 +1011,38 @@ psutil_sensors_battery(PyObject *self, PyObject *args) {
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}


/*
* Return temperature information for a given CPU core number.
*/
PyObject *
psutil_sensors_cpu_temperature(PyObject *self, PyObject *args) {
int current;
int tjmax;
int core;
char sensor[26];
size_t size = sizeof(current);

if (! PyArg_ParseTuple(args, "i", &core))
return NULL;
sprintf(sensor, "dev.cpu.%d.temperature", core);
if (sysctlbyname(sensor, &current, &size, NULL, 0))
goto error;
current = DECIKELVIN_2_CELCIUS(current);

// Return -273 in case of faliure.
sprintf(sensor, "dev.cpu.%d.coretemp.tjmax", core);
if (sysctlbyname(sensor, &tjmax, &size, NULL, 0))
tjmax = 0;
tjmax = DECIKELVIN_2_CELCIUS(tjmax);

return Py_BuildValue("ii", current, tjmax);

error:
if (errno == ENOENT)
PyErr_SetString(PyExc_NotImplementedError, "no temperature sensors");
else
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
1 change: 1 addition & 0 deletions psutil/arch/freebsd/specific.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ PyObject* psutil_virtual_mem(PyObject* self, PyObject* args);
PyObject* psutil_cpu_stats(PyObject* self, PyObject* args);
#if defined(PSUTIL_FREEBSD)
PyObject* psutil_sensors_battery(PyObject* self, PyObject* args);
PyObject* psutil_sensors_cpu_temperature(PyObject* self, PyObject* args);
#endif
17 changes: 17 additions & 0 deletions psutil/tests/test_bsd.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,23 @@ def test_sensors_battery_no_battery(self):
sysctl("hw.acpi.acline")
self.assertIsNone(psutil.sensors_battery())

# --- sensors_temperatures

def test_sensors_temperatures_against_sysctl(self):
num_cpus = psutil.cpu_count(True)
for cpu in range(num_cpus):
sensor = "dev.cpu.%s.temperature" % cpu
# sysctl returns a string in the format 46.0C
sysctl_result = int(float(sysctl(sensor)[:-1]))
self.assertAlmostEqual(
psutil.sensors_temperatures()["coretemp"][cpu].current,
sysctl_result, delta=10)

sensor = "dev.cpu.%s.coretemp.tjmax" % cpu
sysctl_result = int(float(sysctl(sensor)[:-1]))
self.assertEqual(
psutil.sensors_temperatures()["coretemp"][cpu].high,
sysctl_result)

# =====================================================================
# --- OpenBSD
Expand Down
4 changes: 2 additions & 2 deletions psutil/tests/test_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ def test_cpu_freq(self):

def test_sensors_temperatures(self):
self.assertEqual(
hasattr(psutil, "sensors_temperatures"), LINUX)
hasattr(psutil, "sensors_temperatures"), LINUX or FREEBSD)

def test_sensors_fans(self):
self.assertEqual(hasattr(psutil, "sensors_fans"), LINUX)
Expand Down Expand Up @@ -337,7 +337,7 @@ def test_fetch_all(self):
self.assertEqual(err.name, p.name())
assert str(err)
assert err.msg
except Exception as err:
except Exception:
s = '\n' + '=' * 70 + '\n'
s += "FAIL: test_%s (proc=%s" % (name, p)
if ret != default:
Expand Down

0 comments on commit bb5d032

Please sign in to comment.