added cpuTemperature also for OSX

This commit is contained in:
Sebastian Hildebrandt 2017-01-15 12:31:40 +01:00
parent d11f44564e
commit 469bdce3f3
5 changed files with 332 additions and 3 deletions

View File

@ -42,6 +42,7 @@ si.cpu()
### Latest Activity
- Version 3.15.0: added cpuTemperature also for OSX
- Version 3.14.0: added currentLoad per cpu/core, cpu cache (L1, L2, L3) and cpu flags
- Version 3.13.0: added shell (returns standard shell)
- Version 3.12.0: refactoring and extended currentLoad (better OSX coverage and added irq load).
@ -136,9 +137,9 @@ This library is splitted in several sections:
| - min | X | X | min CPU speed (all cores) |
| - max | X | X | max CPU speed (all cores) |
| si.cpuTemperature(cb) | X | | CPU temperature (if sensors is installed) |
| - main | X | | main temperature |
| - cores | X | | array of temperatures |
| - max | X | | max temperature |
| - main | X | X | main temperature |
| - cores | X | X | array of temperatures |
| - max | X | X | max temperature |
| si.mem(cb) | X | X | Memory information|
| - total | X | X | total memory |
| - free | X | X | not used |

19
binding.gyp Executable file
View File

@ -0,0 +1,19 @@
{
'targets': [
],
'conditions': [
['OS=="mac"', {
'targets': [
{
"target_name": "smc",
"sources": [ "lib/OSX/smc.h", "lib/OSX/smc.cc" ],
"link_settings": {
'libraries': [
'IOKit.framework'
]
}
}
],
}]
]
}

210
lib/OSX/smc.cc Executable file
View File

@ -0,0 +1,210 @@
/*
* Apple System Management Control (SMC) Tool
* Copyright (C) 2006 devnull
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef BUILDING_NODE_EXTENSION
#define BUILDING_NODE_EXTENSION
#endif
#include <stdio.h>
#include <string.h>
#include <IOKit/IOKitLib.h>
#include <node.h>
#include <v8.h>
#include "smc.h"
using namespace v8;
static io_connect_t conn;
UInt32 _strtoul(char *str, int size, int base) {
UInt32 total = 0;
int i;
for (i = 0; i < size; i++) {
if (base == 16)
total += str[i] << (size - 1 - i) * 8;
else
total += (unsigned char) (str[i] << (size - 1 - i) * 8);
}
return total;
}
float _strtof(char *str, int size, int e) {
float total = 0;
int i;
for (i = 0; i < size; i++) {
if (i == (size - 1))
total += (str[i] & 0xff) >> e;
else
total += str[i] << (size - 1 - i) * (8 - e);
}
return total;
}
void _ultostr(char *str, UInt32 val) {
str[0] = '\0';
sprintf(str, "%c%c%c%c",
(unsigned int) val >> 24,
(unsigned int) val >> 16,
(unsigned int) val >> 8,
(unsigned int) val);
}
kern_return_t SMCOpen(void) {
kern_return_t result;
io_iterator_t iterator;
io_object_t device;
CFMutableDictionaryRef matchingDictionary = IOServiceMatching("AppleSMC");
result = IOServiceGetMatchingServices(kIOMasterPortDefault, matchingDictionary, &iterator);
if (result != kIOReturnSuccess) {
printf("Error: IOServiceGetMatchingServices() = %08x\n", result);
return 1;
}
device = IOIteratorNext(iterator);
IOObjectRelease(iterator);
if (device == 0) {
printf("Error: no SMC found\n");
return 1;
}
result = IOServiceOpen(device, mach_task_self(), 0, &conn);
IOObjectRelease(device);
if (result != kIOReturnSuccess) {
printf("Error: IOServiceOpen() = %08x\n", result);
return 1;
}
return kIOReturnSuccess;
}
kern_return_t SMCClose() {
return IOServiceClose(conn);
}
kern_return_t SMCCall(int index, SMCKeyData_t *inputStructure, SMCKeyData_t *outputStructure) {
size_t structureInputSize;
size_t structureOutputSize;
structureInputSize = sizeof(SMCKeyData_t);
structureOutputSize = sizeof(SMCKeyData_t);
#if MAC_OS_X_VERSION_10_5
return IOConnectCallStructMethod( conn, index,
// inputStructure
inputStructure, structureInputSize,
// ouputStructure
outputStructure, &structureOutputSize );
#else
return IOConnectMethodStructureIStructureO( conn, index,
structureInputSize, /* structureInputSize */
&structureOutputSize, /* structureOutputSize */
inputStructure, /* inputStructure */
outputStructure); /* ouputStructure */
#endif
}
kern_return_t SMCReadKey(UInt32Char_t key, SMCVal_t *val) {
kern_return_t result;
SMCKeyData_t inputStructure;
SMCKeyData_t outputStructure;
memset(&inputStructure, 0, sizeof(SMCKeyData_t));
memset(&outputStructure, 0, sizeof(SMCKeyData_t));
memset(val, 0, sizeof(SMCVal_t));
inputStructure.key = _strtoul(key, 4, 16);
inputStructure.data8 = SMC_CMD_READ_KEYINFO;
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
if (result != kIOReturnSuccess)
return result;
val->dataSize = outputStructure.keyInfo.dataSize;
_ultostr(val->dataType, outputStructure.keyInfo.dataType);
inputStructure.keyInfo.dataSize = val->dataSize;
inputStructure.data8 = SMC_CMD_READ_BYTES;
result = SMCCall(KERNEL_INDEX_SMC, &inputStructure, &outputStructure);
if (result != kIOReturnSuccess)
return result;
memcpy(val->bytes, outputStructure.bytes, sizeof(outputStructure.bytes));
return kIOReturnSuccess;
}
double SMCGet(UInt32Char_t key) {
SMCVal_t val;
kern_return_t result;
result = SMCReadKey((char*) key, &val);
if (result == kIOReturnSuccess) {
// read succeeded - check returned value
if (val.dataSize > 0) {
if (strcmp(val.dataType, DATATYPE_SP78) == 0) {
// convert sp78 value to temperature
int intValue = val.bytes[0] * 256 + (unsigned char)val.bytes[1];
return intValue / 256.0;
}
if (strcmp(val.dataType, DATATYPE_UINT8) == 0) {
int intValue = _strtoul((char *)val.bytes, val.dataSize, 10);
return intValue;
}
if (strcmp(val.dataType, DATATYPE_FPE2) == 0) {
int intValue = _strtof(val.bytes, val.dataSize, 2);
return intValue;
}
}
}
// read failed
return 0.0;
}
void Get(const FunctionCallbackInfo<Value>& args) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
SMCOpen();
if (args.Length() < 1) {
args.GetReturnValue().Set(Undefined(isolate));
return;
}
if (!args[0]->IsString()) {
isolate->ThrowException(Exception::TypeError(
String::NewFromUtf8(isolate, "Expected string")));
return;
}
v8::String::Utf8Value k(args[0]->ToString());
char *key = *k;
double value = SMCGet(key);
SMCClose();
args.GetReturnValue().Set(Number::New(isolate, value));
}
void Init(v8::Handle<Object> exports) {
NODE_SET_METHOD(exports, "get", Get);
}
NODE_MODULE(smc, Init)

84
lib/OSX/smc.h Executable file
View File

@ -0,0 +1,84 @@
/*
* Apple System Management Control (SMC) Tool
* Copyright (C) 2006 devnull
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef __SMC_H__
#define __SMC_H__
#endif
#define VERSION "0.02"
#define KERNEL_INDEX_SMC 2
#define SMC_CMD_READ_BYTES 5
#define SMC_CMD_WRITE_BYTES 6
#define SMC_CMD_READ_INDEX 8
#define SMC_CMD_READ_KEYINFO 9
#define SMC_CMD_READ_PLIMIT 11
#define SMC_CMD_READ_VERS 12
#define DATATYPE_FPE2 "fpe2"
#define DATATYPE_UINT8 "ui8 "
#define DATATYPE_UINT16 "ui16"
#define DATATYPE_UINT32 "ui32"
#define DATATYPE_SP78 "sp78"
typedef struct {
char major;
char minor;
char build;
char reserved[1];
UInt16 release;
} SMCKeyData_vers_t;
typedef struct {
UInt16 version;
UInt16 length;
UInt32 cpuPLimit;
UInt32 gpuPLimit;
UInt32 memPLimit;
} SMCKeyData_pLimitData_t;
typedef struct {
UInt32 dataSize;
UInt32 dataType;
char dataAttributes;
} SMCKeyData_keyInfo_t;
typedef char SMCBytes_t[32];
typedef struct {
UInt32 key;
SMCKeyData_vers_t vers;
SMCKeyData_pLimitData_t pLimitData;
SMCKeyData_keyInfo_t keyInfo;
char result;
char status;
char data8;
UInt32 data32;
SMCBytes_t bytes;
} SMCKeyData_t;
typedef char UInt32Char_t[5];
typedef struct {
UInt32Char_t key;
UInt32 dataSize;
UInt32Char_t dataType;
SMCBytes_t bytes;
} SMCVal_t;

View File

@ -252,6 +252,21 @@ function cpuTemperature(callback) {
});
}
if (_darwin) {
let smc = require('./build/Release/smc');
let cores = ['TC1C', 'TC2C', 'TC3C', 'TC4C', 'TC5C', 'TC6C', 'TC7C', 'TC8C'];
let sum = 0;
cores.forEach(function(key) {
let value = smc.get(key);
if (value > 0) {
result.cores.push(value);
sum = sum + value;
if (value > result.max) result.max = value;
}
});
if (result.cores.length) {
result.main = sum / result.cores.length;
}
if (callback) { callback(result) }
resolve(result);
}