lavoiesl / osx-cpu-temp

Outputs current CPU temperature for OSX
GNU General Public License v2.0
923 stars 156 forks source link

Invalid fan speed on Catalina #28

Open Vxider opened 4 years ago

Vxider commented 4 years ago

Get fan speed but returns fan number

osx-cpu-temp -f
Num fans: 2
roastchicken commented 4 years ago

I'm interested in working on this, if nobody else is! (I'm experiencing this issue on macOS 10.15.4 with my new MacBook Pro)

powermetrics still returns an RPM for "Fan" (sudo powermetrics --samplers smc -i1 -n1 to get a single SMC sample).

Just guessing here, I know nothing about macOS or SMC, but maybe the library this uses to get SMC information is finally incompatible with a macOS update? If so, maybe another library I ran into today trying to get my computer's temperature may help: DanielStormApps/SMC. It's written in Swift not C, but perhaps it would be useful.

Again, just riffing. If nobody has come back to this before I do again (which may be a long while) I'll look at it closer. With any luck it'll be a small change, but 🤷

Vxider commented 4 years ago

I found a useful tool istats which allows grabbing the CPU temperature, fan speeds and battery information on OS X.

roastchicken commented 4 years ago

iStats is cool, but I'm a minimalist ;)

I'd use powermetrics if the single-sample command wasn't so hard to remember.

Vxider commented 4 years ago

This is a command-line tool, not the famous iStat Menu.

roastchicken commented 4 years ago

Yeah, I know :)

Regardless, I'm experiencing this issue and would like to try to fix it. Issues #19 and #21 report similar problems with strange reports of fans. @lavoiesl mentioned in #21 that taking some fan-printing code from smcFanControl would be wise. Both of these projects are GPLv2 licensed, so although I'm not well versed in how one usually goes about crediting such it seems very doable. Again, I haven't looked at the code so maybe it's more difficult that it seems.

TwentyFourD commented 4 years ago

The datatype in SMCGetFanRPM doesn't match. This fixes getting the data:

#define IS_FLT(A) *(UInt32*)(A.dataType) == *(UInt32*)("flt ") float SMCGetFanRPM(char* key) { SMCVal_t val; kern_return_t result;

result = SMCReadKey(key, &val); if (result == kIOReturnSuccess) { // read succeeded - check returned value if (val.dataSize > 0) { if (IS_FLT(val)) return *((float*)val.bytes); else if (strcmp(val.dataType, DATATYPE_FPE2) == 0) { // convert fpe2 value to RPM return ntohs(*(UInt16*)val.bytes) / 4.0; } } } // read failed return -1.f; }

Also I'm not sure what values are supposed to be printed. I changed it to:

printf("Fan %d - %s at %.0f RPM (%.0f%%)\n", i, name, actual_speed, 100*actual_speed/maximum_speed);

The code formatting doesn't work very well. The important lines are the two with IS_FLT in.