Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hardware temperatures (sensors_temperatures()) #371

Closed
giampaolo opened this issue May 23, 2014 · 45 comments
Closed

Hardware temperatures (sensors_temperatures()) #371

giampaolo opened this issue May 23, 2014 · 45 comments

Comments

@giampaolo
Copy link
Owner

giampaolo commented May 23, 2014

From g.rodola on April 24, 2013 14:59:32

Proposal

I borrowed this idea from glances: https://github.com/nicolargo/glances
...which internally uses pysensors: https://pypi.python.org/pypi/PySensors/
API may look like this:

>>> psutil.cpu_temperature()
[cputemp(name='cpu1', temp=35, high=70, critical=90), 
 cputemp(name='cpu2', temp=30, high=70, critical=90,
 ...]

psutil.cpu_temperature(celsius=False) could be used to express temperature in
fahrenheit. The order in which CPUs are returned should be the same as other cpu_*
functions and be consistent across calls so that:

>>> psutil.cpu_temperature()[0]

...and:

>>> psutil.cpu_times(percpu=True)[0]

...will refer to the same CPU.

FreeBSD: http://superuser.com/questions/344498/get-temperature-of-cpu-intel-core-i5-in-freebsd

Original issue: http://code.google.com/p/psutil/issues/detail?id=371

@giampaolo
Copy link
Owner Author

giampaolo commented May 23, 2014

From g.rodola on April 27, 2013 09:36:58

Committed in revision 22a650567ba7 in a separate branch by parsing files in /sys/class/hwmon/hwmon_/temp1__.
It is probably incomplete compared to what we can get via lm-sensors though so care should be taken on whether adding this or not.

Status: Started

@giampaolo
Copy link
Owner Author

From g.rodola on June 17, 2013 03:53:59

OSX: https://jira.hyperic.com/browse/SIGAR-12

@giampaolo
Copy link
Owner Author

giampaolo commented May 23, 2014

From jlo...@gmail.com on June 17, 2013 11:49:37

Neither of these works on my macbook running 10.8.4:

[root@macbook ]# sysctl kern.cpu_temp_is_valid
second level name cpu_temp_is_valid in kern.cpu_temp_is_valid is invalid

[root@macbook ]$ sysctl kern.cpu_temp
second level name cpu_temp in kern.cpu_temp is invalid

I also don't see any reference to temp sensors in sysctlbyname docs:
https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/sysctlbyname.3.html

@thijstriemstra
Copy link
Contributor

Would also like to see this feature. For RaspberryPi I'm now using:

def get_cpu_temperature():
    """
    Get CPU temperature.
    """
    with open('/sys/class/thermal/thermal_zone0/temp', 'r') as f:
        temp = float(f.read()) / 1000.0

    return temp

But this doesn't work on OSX for example.

@thijstriemstra
Copy link
Contributor

Here's some C-code that gets the OSX temperature: https://github.com/lavoiesl/osx-cpu-temp

@giampaolo giampaolo changed the title CPUs temperature (Linux only) Hardware temperatures Nov 24, 2016
giampaolo added a commit that referenced this issue Jan 24, 2017
giampaolo added a commit that referenced this issue Jan 24, 2017
giampaolo added a commit that referenced this issue Jan 24, 2017
@giampaolo giampaolo changed the title Hardware temperatures Hardware temperatures (sensors_temperatures()) Jan 24, 2017
@giampaolo
Copy link
Owner Author

@giampaolo
Copy link
Owner Author

Attaching a modified version of osx-cpu-temp C source code which I managed to compile (by modifying the Makefile). I get temperature == 0.0 but I suppose that's because I'm virtualizing OSX hence there are no sensors.
osx-cpu-temp.zip

@giampaolo
Copy link
Owner Author

I'm not gonna have a chance to implement this on OSX as I don't have the hardware.

@thijstriemstra
Copy link
Contributor

@giampaolo if you can slap it in a branch, i can test it on osx

@giampaolo
Copy link
Owner Author

OK, I've just merged the Linux implementation into master. For now this functionality is Linux only as:

  • I don't have a physical OSX box to test against and VirtualBox does not emulated temperature sensors. @thijstriemstra I'm no sure what to put into a branch as I don't have anything working
  • FreeBSD: sensors exist in different approaches (see: https://forums.freebsd.org/threads/882/) but none of them work on my virtualized FreeBSD box
  • Windows: I spotted at least 3 different methods to obtain temperatures by using WMI but none of them worked (I also tried no a "real" physical Windows laptop). It seems this is strictly dependent on the hardware installed so it's not portable.

@thijstriemstra
Copy link
Contributor

thijstriemstra commented Feb 6, 2017

@giampaolo coincidentally I decided to test your osx-cpu-temp on my osx when it's been on an ice-cold floor in its' case but your smb scripts works:

$ ./smc 
22.1°C

Tested on macOS 10.11.6;

uname -a
Darwin MacBook-Pro 15.6.0 Darwin Kernel Version 15.6.0: Mon Jan  9 23:07:29 PST 2017; root:xnu-3248.60.11.2.1~1/RELEASE_X86_64 x86_64

Now I need to find a place/app on this mac where I can verify this nr.

The iStats ruby package also provides CPU stats (sudo gem install iStats):

$ istats cpu
CPU temp: 22.13°C ▁▂▃▅▆▇

$ ./smc
22.1°C

If you can also provide more decimals, that would be great but this seems to work fine.

iStats also provides battery temperature:

$ istats battery temp
Battery temp: 13.19°C

@thijstriemstra
Copy link
Contributor

thijstriemstra commented Feb 6, 2017

Also tested it on the latest Raspbian (on raspberrypi)

Linux raspberrypi 4.4.38-v7+ #938 SMP Thu Dec 15 15:22:21 GMT 2016 armv7l GNU/Linux

and both master and 5.1.2 return not much:

$ python
Python 3.5.3 (default, Jan 24 2017, 00:58:06) 
[GCC 4.9.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import psutil
>>> psutil.sensors_temperatures()
{}

@sethmlarson
Copy link

sethmlarson commented Feb 6, 2017

@thijstriemstra Can you show what $ ls -Al /sys/class/hwmon/hwmon0 returns?

@thijstriemstra
Copy link
Contributor

thijstriemstra commented Feb 6, 2017

$ ls -Al /sys/class/hwmon/hwmon0
ls: cannot access /sys/class/hwmon/hwmon0: No such file or directory
$ ls -Al /sys/class/hwmon/
ls: cannot access /sys/class/hwmon/: No such file or directory

Like I mentioned, on an RPi it seems to be /sys/class/thermal/thermal_zone0/temp we're after:

$ ls -l /sys/class/thermal/thermal_zone0/
total 0
-r--r--r-- 1 root root 4096 Feb  6 23:14 available_policies
-rw-r--r-- 1 root root 4096 Feb  6 23:14 integral_cutoff
-rw-r--r-- 1 root root 4096 Feb  6 23:14 k_d
-rw-r--r-- 1 root root 4096 Feb  6 23:14 k_i
-rw-r--r-- 1 root root 4096 Feb  6 23:14 k_po
-rw-r--r-- 1 root root 4096 Feb  6 23:14 k_pu
-rw-r--r-- 1 root root 4096 Feb  6 23:14 offset
-rw-r--r-- 1 root root 4096 Feb  6 23:14 passive
-rw-r--r-- 1 root root 4096 Feb  6 23:14 policy
drwxr-xr-x 2 root root    0 Feb  6 23:14 power
-rw-r--r-- 1 root root 4096 Feb  6 23:14 slope
lrwxrwxrwx 1 root root    0 Feb  6 23:14 subsystem -> ../../../../class/thermal
-rw-r--r-- 1 root root 4096 Feb  6 23:14 sustainable_power
-r--r--r-- 1 root root 4096 Feb  6 23:14 temp
-r--r--r-- 1 root root 4096 Feb  6 23:14 type
-rw-r--r-- 1 root root 4096 Feb  1 04:17 uevent
$ cat /sys/class/thermal/thermal_zone0/temp 
41698
$ ls -l /sys/class/thermal/
total 0
lrwxrwxrwx 1 root root 0 Feb  1 04:17 thermal_zone0 -> ../../devices/virtual/thermal/thermal_zone0

@sethmlarson
Copy link

That would be the problem then. ;) There's a comment about this for Ubuntu as well in the code.

@thijstriemstra
Copy link
Contributor

thijstriemstra commented Feb 6, 2017

Should I open a new ticket? You mean it's also not working in regular Debian and Ubuntu? I haven't checked the code but I also dont remember it being in the changelog (other than 'linux support'). Seems to work fine on Ubuntu 16.04 here.

@sethmlarson
Copy link

sethmlarson commented Feb 6, 2017

I believe it's working in those OSes but they provide more than one interface for CPU temperature (thermal_zone and hwmon) whereas Raspbian appears to only provide thermal_zone.

And opening a ticket would probably be helpful. :)

@thijstriemstra
Copy link
Contributor

I see!

@giampaolo
Copy link
Owner Author

giampaolo commented Feb 6, 2017

Right now psutil reads temperatures from /sys/class/hwmon/hwmon*/temp*_*. It would be nice to add /sys/class/thermal/ as it appears it would improve Linux support.

@giampaolo
Copy link
Owner Author

/sys/class/thermal/ does not provide the same names as /sys/class/hwmon/hwmon*/temp*_* plus it does not include max temperatures so it seems it's incompatible.

@giampaolo
Copy link
Owner Author

Closing out as fixed.

@JMY1000
Copy link

JMY1000 commented Oct 29, 2017

I see that the issue is closed as fixed, but there doesn't seem to be any support for any sensors on macOS. I'm curious: why didn't this get implemented for macOS? There seem to be two pretty good libraries (SMCKit and iStats) that provide the necessary functionality (temps, fans, and battery.) I understand bloat might be a concern, but this seems like a reasonable use.

@giampaolo
Copy link
Owner Author

I didn't implement this on OSX because I don't have the hardware. I virtualize OSX via VirtualBox but with that method it shows no temperatures (or battery). As such somebody else has to do it.

@JMY1000
Copy link

JMY1000 commented Oct 29, 2017

dqk6sjs42i8z

@giampaolo
Copy link
Owner Author

Go for it! ;)
You can take a look at https://github.com/lavoiesl/osx-cpu-temp for an inspiration.

@JMY1000
Copy link

JMY1000 commented Oct 29, 2017

On that note though, since as of now everything is self contained, what's the policy on using other libraries?

@giampaolo
Copy link
Owner Author

I am against that as I don't want to introduce any installation requirement other than the C compiler.
Actually I want to move away from that too (see #824). For this specific issue you should rely on native OSX syscalls.

@wiggin15
Copy link
Collaborator

I started working on this in branch: https://github.com/Infinidat/psutil/tree/osx_sensors.
I implemented sensors_temperatures, sensors_battery and sensors_fans functions. This is mostly working except for some error handling which I need to fix before submitting this as a pull request. The interface is a little different than Linux's because we don't have "label", "high" and "critical" for the temperatures and fans... I don't know if this looks good.

In [1]: import psutil

In [2]: psutil.sensors_fans()
Out[2]: {'Fan 0': sfan(current=1292.0)}

In [3]: psutil.sensors_temperatures()
Out[3]: {'Battery': shwtemp(current=29.59765625), 'CPU': shwtemp(current=53.625)}

In [4]: psutil.sensors_battery()
Out[4]: sbattery(percent=100, secsleft=-2, power_plugged=True)

@giampaolo
Copy link
Owner Author

giampaolo commented Nov 14, 2017

Great work! Some considerations:

  • I marked sensors_ APIs as "experimental" so we have the flexibility to change them.
  • first thing I'd change (on Linux) is to move current field in position 0 because it's always supposed to be there. This should happen in a major release (I'll do that).
  • There's the question whether to return a a different namedtuple on OSX or the same one with null values. Hard to tell at this point. Adding support for Windows and seeing how things are down there would help clear things up. FWIW this shows there are min and max values on Windows, which is cool, but maybe min is different than high provided by psutil on Linux. Since we're not sure yet I think keeping the same nametuple and set None values is safer at this point.
  • We can drop "experimental" status for sensors_temperatures and sensors_fans once we have the Windows implementation. That will tell us how the final APIs should look like. Any chance you could do this on Windows as well? ;-)

@giampaolo giampaolo reopened this Nov 14, 2017
@wiggin15
Copy link
Collaborator

I created a separate namedtuple for OSX for now, however the interface still doesn't look good. On Linux, every key in the returned dict returns a list of temperatures, while on OSX we only have one temperature per component.
Current return value, I think doesn't look very good: {'Battery': [shwtemp(current=34.09765625)], 'CPU': [shwtemp(current=61.75)]}
Maybe this will make more sense? [shwtemp(name='Battery', current=34.09765625), shwtemp(name='CPU', current=61.75)]
There is a similar issue with sensors_fans. This makes the temperatures.py/fans.py/sensors.py scripts return confusing outputs:

$ scripts/sensors.py
Battery
    Temperatures:
        Battery              34.19921875 °C
Fan 0
    Fans:
        Fan 0                1309.0 RPM
CPU
    Temperatures:
        CPU                  56.875 °C
Battery:
    charge:     100.0%
    status:     fully charged
    plugged in: yes

@wiggin15
Copy link
Collaborator

Any chance you could do this on Windows as well? ;-)

I used to really like Windows API, but I don't think I'll have time to get into that 😉

@giampaolo
Copy link
Owner Author

Maybe this will make more sense? [shwtemp(name='Battery', current=34.09765625), shwtemp(name='CPU', current=61.75)]

No because sensors_temperatures on Linux returns a dict, not a list. We should keep returning a dict. The same structure will make sense on Windows (see the screenshots here: http://openhardwaremonitor.org/).

@wiggin15
Copy link
Collaborator

wiggin15 commented Nov 16, 2017

Information about sensors on OSX in general:
Apparently there are A LOT of sensors that Apple's SMC reports. This tool can list them:
https://github.com/theopolis/smc-fuzzer
Here is an output from a MacBook Pro:
https://gist.github.com/wiggin15/5b86bf1bfd1c175329c33c2da87049c7
Unfortunately the meanings are not publicly documented. There is a partial list of meanings here: https://stackoverflow.com/a/31033665/1739101 .
There is also a tool called iStat Menus that lists many of the sensor values. It looks like this: https://images.techhive.com/images/article/2013/05/istatmenus4_06-100039349-orig.png

The code in my branch decodes only a few of the values (battery temperature, cpu temperature, fan current speed) but maybe it can read more values (e.g. there are "min/max fan speed" values and more temperatures). There is also still the question about the interface(s). It doesn't look like the Linux interface matches here exactly.

@giampaolo the "sensors_battery" information uses a separate API that is documented and doesn't need the SMC. Would you be open to accepting a separate PR with this function implemented only?

@JMY1000
Copy link

JMY1000 commented Nov 16, 2017

@wiggin15 I'd recommend looking at SMCKit and iStats. They're both open source and pull from the SMC.

@wiggin15
Copy link
Collaborator

Thanks @JMY1000 . iStats only pulls a small subset of the codes (I already look at these codes in my branch - cpu temperature, battery temperature, fan speed). SMCKit pulls some more, but still far from all of the available list.
I'm wondering what temperatures are relevant to return from sensors_temperatures.

@JMY1000
Copy link

JMY1000 commented Nov 16, 2017

@wiggin15 The iStats that I linked is not the same as iStat Menus or iStat Pro–it's a Ruby gem that actually goes through every sensor AFAIK. Run istats scan to go through all the sensors.

@giampaolo
Copy link
Owner Author

@giampaolo the "sensors_battery" information uses a separate API that is documented and doesn't need the SMC. Would you be open to accepting a separate PR with this function implemented only?

Of course.

@giampaolo
Copy link
Owner Author

I'm wondering what temperatures are relevant to return from sensors_temperatures.

Most important ones are CPUs. I wouldn't mind other sensors for now. E.g. voltages don't exist at all in psutil. It would be nice to have CPU min / max limits though, because they are useful to implement apps which emit alarms. It sucks these APIs are so poorly documented.

@amanusk
Copy link
Collaborator

amanusk commented May 18, 2018

@giampaolo, I have been looking for a solution to this issue. Is there any way to know the critical or high values of the CPU temperature? I have not seen any way to probe this information in any of the sources mentioned above. If not, should it be just left blank, or set to 105 C, which is usually the critical temperature for Intel CPUs

@giampaolo
Copy link
Owner Author

sensors_temperatures() currently is not implemented on OSX. I didn't implement it because my virtualized OSX box does not have any temperature. Pull requests are welcome though. =)

@JMY1000
Copy link

JMY1000 commented May 18, 2018

@amanusk Not sure how you'd define what high is, but it seems like critical should be when it starts throttling.

For Intel processors at least, you could pull the TJMAX from ARK, but there's got to be a better way of getting that info. I don't think it's baked into the CPUID info unfortunately.

@amanusk
Copy link
Collaborator

amanusk commented May 18, 2018

sensors_temperatures() currently is not implemented on OSX. I didn't implement it because my
virtualized OSX box does not have any temperature. Pull requests are welcome though. =)

@giampaolo I have noticed it is not implemented ;), I might be able to work on it if I get access to hardware. My question is, whether you know of a method to get high and critical metrics in macOS (similar to lmsensors), and how would you want this handled if there is no way to obtain these.

@JMY1000

Not sure how you'd define what high is, but it seems like critical should be when it starts throttling.

In lmsensors, high is the temperature when throttling starts, and cirtical is when the system shuts down. I was hoping there is a way to obtain these metrics from software, similar to Linux, and not by cross referencing with ARK for each CPU model.

@JMY1000
Copy link

JMY1000 commented May 18, 2018

@amanusk Gotcha. If you'd be interested, I think I could set up access to hardware over ssh or something. Seems like @wiggin15 hasn't touched his stuff in a while. I'd also be happy to help.

Not sure how to obtain that info. The official Intel Power Gadget seems to rely on a kext, but I'm not sure how it's grabbing the info below that. sysctl hw.cpufrequency seems to be entirely static, just reporting whatever your CPU is manufactured to run at.

@amanusk amanusk mentioned this issue May 26, 2018
@JMY1000
Copy link

JMY1000 commented May 27, 2018

I compiled a list of all the temperature sensors accessible via the SMC

SMC Code Name
TA0P Ambient
TA0S PCI Slot 1 Pos 1
TA1P Ambient temperature
TA1S PCI Slot 1 Pos 2
TA2S PCI Slot 2 Pos 1
TA3S PCI Slot 2 Pos 2
TB0P BLC Proximity
TB0T Battery TS_MAX
TB1T Battery 1
TB2T Battery 2
TB3T Battery 3
TC_C CPU Core _
TC_D CPU _ Die
TC_E CPU _ ??
TC_F CPU _ ??
TC_G CPU _ ??
TC_H CPU _ Heatsink
TC_J CPU _ ??
TC_P CPU _ Proximity
TCGC PECI GPU
TCSA PECI SA
TCSC PECI SA
TCXC PECI CPU
TG_D GPU _ Die
TG_H GPU _ Heatsink
TG_P GPU _ Proximity
TH_H Heatsink _ Proximity
TH_P HDD _ Proximity
TI_P Thunderbolt _
TL_P LCD _ Proximity
TL_P LCD _
TM_P Memory _ Proximity
TM_S Memory Slot _
TMA_ DIMM A ?
TMB_ DIMM B ?
TN_D Northbridge _ Die
TN_H Northbridge _ Heatsink
TN_P Northbridge _ Proximity
TO_P Optical Drive _ Proximity
TP_C Power Supply _
TP_P Power Supply _ Proximity
TS_C Expansion Slot _
TS_P Palm Rest _
TS0C Expansion slots
TS0S Memory Bank Proximity
TW0P AirPort Proximity

Note the underscores indicating the possibility of multiple sensors. These values will need to be scanned in a smart manner.

@JMY1000
Copy link

JMY1000 commented Oct 19, 2018

Hoping to work on that PR some time in the next few months :/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants