init
This commit is contained in:
commit
8f36d3ffa7
5 changed files with 386 additions and 0 deletions
114
monitor.cpp
Normal file
114
monitor.cpp
Normal file
|
@ -0,0 +1,114 @@
|
|||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <cctype>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
|
||||
const string WHITESPACE = " \n\r\t\f\v";
|
||||
string ltrim(const string& s) {
|
||||
size_t start = s.find_first_not_of(WHITESPACE);
|
||||
return (start == string::npos) ? "" : s.substr(start);
|
||||
}
|
||||
string rtrim(const string& s) {
|
||||
size_t end = s.find_last_not_of(WHITESPACE);
|
||||
return (end == string::npos) ? "" : s.substr(0, end + 1);
|
||||
}
|
||||
string trim(const string& s) { return rtrim(ltrim(s)); }
|
||||
|
||||
void split_comma(string &s, vector<string> &l);
|
||||
void sort_names(vector<string> &l, vector<int> &order, int &num);
|
||||
int max_len(vector<string> &l);
|
||||
|
||||
int main(int argc,char *argv[]) {
|
||||
string name_line, value_line;
|
||||
getline(cin, name_line);
|
||||
// cout<<name_line<<endl;
|
||||
|
||||
int num; int name_length_max;
|
||||
vector<int> orders;
|
||||
vector<string> names, values;
|
||||
vector<double> raw_values;
|
||||
|
||||
split_comma(name_line, names);
|
||||
num = names.size();
|
||||
sort_names(names, orders, num);
|
||||
name_length_max = max_len(names);
|
||||
|
||||
for(int i=0;i<num;++i) {
|
||||
int space_num = name_length_max + 2 - names[orders[i]].size();
|
||||
cout<<names[orders[i]];
|
||||
for(int j=0;j<space_num;++j) cout<<" ";
|
||||
cout<<"| "<<endl;
|
||||
}
|
||||
// cout<<num<<endl;
|
||||
// for(int i=0;i<num;++i) cout<<" "<<endl;
|
||||
cout<<"\x1b[100D"<<"\x1b["<<num<<"A"<<flush;
|
||||
// ANSI Escape sequences http://ascii-table.com/ansi-escape-sequences.php
|
||||
// https://www.lihaoyi.com/post/BuildyourownCommandLinewithANSIescapecodes.html#progress-indicator
|
||||
|
||||
while(getline(cin, value_line)) {
|
||||
// cout<<"\x1b[1000D"<<value_line<<flush;
|
||||
split_comma(value_line, values);
|
||||
assert(values.size() == num);
|
||||
|
||||
for(int i=0;i<names.size();++i) {
|
||||
cout<<"\x1b["<<name_length_max + 4<<"C"<<flush;
|
||||
cout<<values[orders[i]]<<endl;
|
||||
}
|
||||
// cout<<num<<"=="<<endl;
|
||||
cout<<"\x1b[100D"<<"\x1b["<<num<<"A"<<flush;
|
||||
usleep(500000); // sleep(1); https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/usleep.3.html
|
||||
}
|
||||
cout<<endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void split_comma(string &s, vector<string> &l) {
|
||||
l.clear();
|
||||
stringstream s_stream(s);
|
||||
while(s_stream.good()) {
|
||||
string w;
|
||||
getline(s_stream, w, ','); //get first string delimited by comma
|
||||
w=trim(w);
|
||||
if(!w.empty())
|
||||
l.push_back(w);
|
||||
}
|
||||
}
|
||||
|
||||
void sort_names(vector<string> &l, vector<int> &order, int &num) {
|
||||
vector< pair<string, int> > l_id;
|
||||
for(int i=0;i<num;++i) l_id.push_back(make_pair(l[i], i));
|
||||
sort(l_id.begin(), l_id.end());
|
||||
|
||||
order.clear();
|
||||
for(int i=0;i<num;++i) order.push_back(l_id[i].second);
|
||||
}
|
||||
|
||||
int max_len(vector<string> &l) {
|
||||
int res = 0;
|
||||
for(int i=0;i<l.size();++i)
|
||||
if(l[i].size() > res)
|
||||
res = l[i].size();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
cout << "\r%1"<<flush;
|
||||
sleep(1);
|
||||
cout << "\r%2"<<flush;
|
||||
sleep(1);
|
||||
cout << "\r%3"<<flush;
|
||||
cout << endl;
|
||||
*/
|
34
readme.md
Normal file
34
readme.md
Normal file
|
@ -0,0 +1,34 @@
|
|||
# Temperature Sensor Monitor for Apple Silicon M1
|
||||
|
||||
- temp_sensor.m: A modified version of the [code](https://github.com/freedomtan/sensors/blob/master/sensors/sensors.m) for iOS sensor by [freedomtan](https://github.com/freedomtan);
|
||||
|
||||
- monitor.cpp: A c++ wrapper of Objective-C output for monitoring temperature in the terminal.
|
||||
|
||||
## Usage
|
||||
|
||||
`./temp_sensor | ./monitor`
|
||||
|
||||
Only test with my Mac mini with M1. Please check your mac's `ioreg -lfx` output if needed.
|
||||
|
||||
## References
|
||||
|
||||
For better name for the sensors, please refer to
|
||||
|
||||
https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
|
||||
|
||||
https://github.com/acidanthera/VirtualSMC/blob/master/Docs/SMCSensorKeys.txt
|
||||
|
||||
Similar code for getting sensor values using IOKit (for intel Mac)
|
||||
|
||||
https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
|
||||
|
||||
|
||||
|
||||
## screen shot and screen record
|
||||
|
||||
![screen record](screen record.mp4)
|
||||
|
||||
![screen shot](screen shot.png)
|
||||
|
||||
|
||||
|
BIN
screen record.mp4
Normal file
BIN
screen record.mp4
Normal file
Binary file not shown.
BIN
screen shot.png
Normal file
BIN
screen shot.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 349 KiB |
238
temp_sensor.m
Normal file
238
temp_sensor.m
Normal file
|
@ -0,0 +1,238 @@
|
|||
//
|
||||
// main.m
|
||||
// sensors
|
||||
//
|
||||
// Created by Yang on 11/26/20.
|
||||
//
|
||||
|
||||
|
||||
#include <IOKit/hidsystem/IOHIDEventSystemClient.h>
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Declarations from other IOKit source code
|
||||
|
||||
typedef struct __IOHIDEvent *IOHIDEventRef;
|
||||
typedef struct __IOHIDServiceClient *IOHIDServiceClientRef;
|
||||
#ifdef __LP64__
|
||||
typedef double IOHIDFloat;
|
||||
#else
|
||||
typedef float IOHIDFloat;
|
||||
#endif
|
||||
|
||||
IOHIDEventSystemClientRef IOHIDEventSystemClientCreate(CFAllocatorRef allocator);
|
||||
int IOHIDEventSystemClientSetMatching(IOHIDEventSystemClientRef client, CFDictionaryRef match);
|
||||
int IOHIDEventSystemClientSetMatchingMultiple(IOHIDEventSystemClientRef client, CFArrayRef match);
|
||||
IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t , int32_t, int64_t);
|
||||
CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property);
|
||||
IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field);
|
||||
|
||||
CFDictionaryRef matching(int page, int usage)
|
||||
{
|
||||
CFNumberRef nums[2];
|
||||
CFStringRef keys[2];
|
||||
|
||||
keys[0] = CFStringCreateWithCString(0, "PrimaryUsagePage", 0);
|
||||
keys[1] = CFStringCreateWithCString(0, "PrimaryUsage", 0);
|
||||
nums[0] = CFNumberCreate(0, kCFNumberSInt32Type, &page);
|
||||
nums[1] = CFNumberCreate(0, kCFNumberSInt32Type, &usage);
|
||||
|
||||
CFDictionaryRef dict = CFDictionaryCreate(0, (const void**)keys, (const void**)nums, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
return dict;
|
||||
}
|
||||
|
||||
CFArrayRef getProductNames(CFDictionaryRef sensors) {
|
||||
IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault); // in CFBase.h = NULL
|
||||
// ... this is the same as using kCFAllocatorDefault or the return value from CFAllocatorGetDefault()
|
||||
IOHIDEventSystemClientSetMatching(system, sensors);
|
||||
CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system); // matchingsrvs = matching services
|
||||
|
||||
long count = CFArrayGetCount(matchingsrvs);
|
||||
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
IOHIDServiceClientRef sc = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(matchingsrvs, i);
|
||||
CFStringRef name = IOHIDServiceClientCopyProperty(sc, CFSTR("Product")); // here we use ...CopyProperty
|
||||
if (name) {
|
||||
CFArrayAppendValue(array, name);
|
||||
} else {
|
||||
CFArrayAppendValue(array, @"noname"); // @ gives a Ref like in "CFStringRef name"
|
||||
}
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
// from IOHIDFamily/IOHIDEventTypes.h
|
||||
// e.g., https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-701.60.2/IOHIDFamily/IOHIDEventTypes.h.auto.html
|
||||
|
||||
#define IOHIDEventFieldBase(type) (type << 16)
|
||||
#define kIOHIDEventTypeTemperature 15
|
||||
#define kIOHIDEventTypePower 25
|
||||
|
||||
CFArrayRef getPowerValues(CFDictionaryRef sensors) {
|
||||
IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
|
||||
IOHIDEventSystemClientSetMatching(system, sensors);
|
||||
CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system);
|
||||
|
||||
long count = CFArrayGetCount(matchingsrvs);
|
||||
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
for (int i = 0; i < count; i++) {
|
||||
IOHIDServiceClientRef sc = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(matchingsrvs, i);
|
||||
IOHIDEventRef event = IOHIDServiceClientCopyEvent(sc, kIOHIDEventTypePower, 0, 0);
|
||||
|
||||
CFNumberRef value;
|
||||
if (event != 0) {
|
||||
double temp = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(kIOHIDEventTypePower));
|
||||
value = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &temp);
|
||||
} else {
|
||||
double temp = 0;
|
||||
value = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &temp);
|
||||
}
|
||||
CFArrayAppendValue(array, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
CFArrayRef getThermalValues(CFDictionaryRef sensors) {
|
||||
IOHIDEventSystemClientRef system = IOHIDEventSystemClientCreate(kCFAllocatorDefault);
|
||||
IOHIDEventSystemClientSetMatching(system, sensors);
|
||||
CFArrayRef matchingsrvs = IOHIDEventSystemClientCopyServices(system);
|
||||
|
||||
long count = CFArrayGetCount(matchingsrvs);
|
||||
CFMutableArrayRef array = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
IOHIDServiceClientRef sc = (IOHIDServiceClientRef)CFArrayGetValueAtIndex(matchingsrvs, i);
|
||||
IOHIDEventRef event = IOHIDServiceClientCopyEvent(sc, kIOHIDEventTypeTemperature, 0, 0); // here we use ...CopyEvent
|
||||
|
||||
CFNumberRef value;
|
||||
if (event != 0) {
|
||||
double temp = IOHIDEventGetFloatValue(event, IOHIDEventFieldBase(kIOHIDEventTypeTemperature));
|
||||
value = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &temp);
|
||||
} else {
|
||||
double temp = 0;
|
||||
value = CFNumberCreate(kCFAllocatorDefault, kCFNumberDoubleType, &temp);
|
||||
}
|
||||
CFArrayAppendValue(array, value);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
void dumpValues(CFArrayRef values)
|
||||
{
|
||||
long count = CFArrayGetCount(values);
|
||||
for (int i = 0; i < count; i++) {
|
||||
CFNumberRef value = CFArrayGetValueAtIndex(values, i);
|
||||
double temp = 0.0;
|
||||
CFNumberGetValue(value, kCFNumberDoubleType, &temp);
|
||||
// NSLog(@"value = %lf\n", temp);
|
||||
printf("%0.1lf, ", temp);
|
||||
}
|
||||
}
|
||||
|
||||
void dumpNames(CFArrayRef names, char *cat)
|
||||
{
|
||||
long count = CFArrayGetCount(names);
|
||||
for (int i = 0; i < count; i++) {
|
||||
NSString *name = (NSString *)CFArrayGetValueAtIndex(names, i);
|
||||
// NSLog(@"value = %lf\n", temp);
|
||||
// printf("%s (%s), ", [name UTF8String], cat);
|
||||
printf("%s, ", [name UTF8String]);
|
||||
}
|
||||
}
|
||||
|
||||
NSArray* currentArray() {
|
||||
CFDictionaryRef currentSensors = matching(0xff08, 2);
|
||||
return CFBridgingRelease(getProductNames(currentSensors));
|
||||
}
|
||||
|
||||
NSArray* voltageArray() {
|
||||
CFDictionaryRef currentSensors = matching(0xff08, 3);
|
||||
return CFBridgingRelease(getProductNames(currentSensors));
|
||||
}
|
||||
|
||||
NSArray* thermalArray() {
|
||||
CFDictionaryRef currentSensors = matching(0xff00, 5);
|
||||
return CFBridgingRelease(getProductNames(currentSensors));
|
||||
}
|
||||
|
||||
NSArray* returnCurrentValues() {
|
||||
CFDictionaryRef currentSensors = matching(0xff08, 2);
|
||||
return CFBridgingRelease(getPowerValues(currentSensors));
|
||||
}
|
||||
|
||||
NSArray* returnVoltageValues() {
|
||||
CFDictionaryRef voltageSensors = matching(0xff08, 3);
|
||||
return CFBridgingRelease(getPowerValues(voltageSensors));
|
||||
}
|
||||
|
||||
NSArray* returnThermalValues() {
|
||||
CFDictionaryRef currentSensors = matching(0xff00, 5);
|
||||
return CFBridgingRelease(getThermalValues(currentSensors));
|
||||
}
|
||||
|
||||
|
||||
//extern uint64_t my_mhz(void);
|
||||
//extern void mybat(void);
|
||||
|
||||
#if 1
|
||||
int main () {
|
||||
// Primary Usage Page:
|
||||
// kHIDPage_AppleVendor = 0xff00,
|
||||
// kHIDPage_AppleVendorTemperatureSensor = 0xff05,
|
||||
// kHIDPage_AppleVendorPowerSensor = 0xff08,
|
||||
//
|
||||
// Primary Usage:
|
||||
// kHIDUsage_AppleVendor_TemperatureSensor = 0x0005,
|
||||
// kHIDUsage_AppleVendorPowerSensor_Current = 0x0002,
|
||||
// kHIDUsage_AppleVendorPowerSensor_Voltage = 0x0003,
|
||||
// See IOHIDFamily/AppleHIDUsageTables.h for more information
|
||||
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-701.60.2/IOHIDFamily/AppleHIDUsageTables.h.auto.html
|
||||
|
||||
CFDictionaryRef currentSensors = matching(0xff08, 2);
|
||||
CFDictionaryRef voltageSensors = matching(0xff08, 3);
|
||||
CFDictionaryRef thermalSensors = matching(0xff00, 5); // 65280_10 = FF00_16
|
||||
// I change it to 0xff00, due to ioreg -dlx
|
||||
|
||||
CFArrayRef currentNames = getProductNames(currentSensors);
|
||||
CFArrayRef voltageNames = getProductNames(voltageSensors);
|
||||
CFArrayRef thermalNames = getProductNames(thermalSensors);
|
||||
|
||||
|
||||
// printf("freq, v_bat, a_bat, temp_bat");
|
||||
// dumpNames(voltageNames, "V");
|
||||
// dumpNames(currentNames, "A");
|
||||
dumpNames(thermalNames, "C");
|
||||
printf("\n"); fflush(stdout);
|
||||
|
||||
while (1) {
|
||||
CFArrayRef currentValues = getPowerValues(currentSensors);
|
||||
CFArrayRef voltageValues = getPowerValues(voltageSensors);
|
||||
CFArrayRef thermalValues = getThermalValues(thermalSensors);
|
||||
// printf("%lld, ", my_mhz());
|
||||
// mybat();
|
||||
|
||||
// dumpValues(voltageValues);
|
||||
// dumpValues(currentValues);
|
||||
dumpValues(thermalValues);
|
||||
printf("\n"); fflush(stdout);
|
||||
usleep(1000000); // usleep - suspend execution for microsecond intervals
|
||||
CFRelease(currentValues);
|
||||
CFRelease(voltageValues);
|
||||
CFRelease(thermalValues);
|
||||
}
|
||||
|
||||
#if 0
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(currentNames, 0));
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(currentNames, 1));
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(voltageNames, 0));
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(voltageNames, 1));
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(thermalNames, 0));
|
||||
NSLog(@"%@\n", CFArrayGetValueAtIndex(thermalNames, 1));
|
||||
#endif
|
||||
|
||||
// IOHIDEventRef event = IOHIDServiceClientCopyEvent(alssc, 25, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
Loading…
Reference in a new issue