Compare commits

...

10 commits

Author SHA1 Message Date
Federico Rossi
565742c1be initial 2023-11-19 21:35:01 +01:00
fermion-star
c6c160ba87
Merge pull request #4 from mikemadden42/feature/add-makefile
Add Makefile for easy compile & run.
2023-02-04 13:35:22 -08:00
Michael Madden
f9da4031ca Add Makefile for easy compile & run. 2021-09-24 19:27:28 -05:00
Ethan Wang
81230c6f6b screen shot/record update 2021-03-01 18:14:17 -05:00
Ethan Wang
4cfeb22e06 exit with Ctrl+C and vline 2021-03-01 17:55:30 -05:00
Ethan Wang
55a83ff9cb record max temp and update every 1s->0.5s 2021-02-28 18:44:18 -05:00
Ethan Wang
01e6fe0bc3 python curses wrapper 2021-02-27 17:46:31 -05:00
yifan wang
f7d6a13f4f readme 2020-11-29 19:00:23 -05:00
yifan wang
9b25cbf035 readme 2020-11-28 12:04:58 -05:00
yifan wang
0986157910 add licence for temp_sensor.m 2020-11-28 10:47:12 -05:00
7 changed files with 103 additions and 189 deletions

6
.gitignore vendored Normal file
View file

@ -0,0 +1,6 @@
.DS_Store
/sensors/
/bin/
/curses/
/info/
temp_sensor

20
Makefile Normal file
View file

@ -0,0 +1,20 @@
CC=clang
FRAMEWORKS:= -framework Foundation -framework IOKit
LIBRARIES:= -lobjc
SOURCE=temp_sensor.m
CFLAGS=-Wall -v $(SOURCE)
LDFLAGS=$(LIBRARIES) $(FRAMEWORKS)
OUT=-o temp_sensor
build:
$(CC) $(CFLAGS) $(LDFLAGS) $(OUT)
all: build
run:
./temp_sensor | ./monitor.py
.phony: build run

View file

@ -1,114 +0,0 @@
#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;
*/

View file

@ -1,44 +0,0 @@
# 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 names (e.g. what is `PMU TP3w` ?) 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
Here is a similar code in swift for getting sensor values using IOKit (for intel Mac)
https://github.com/exelban/stats/blob/master/Modules/Sensors/values.swift
For intel Mac, an easier way to get sensor infomation:
`sudo powermetrics`
## screen shot and screen record
- screen record ->screen_record.mp4[1.4MB]
![screen record](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/screen_record.mp4)
- screen shot
![screen shot](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/screen_shot.png)
<!---
![screen record](screen_record.mp4)
![screen shot](screen_shot.png)
--->

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 KiB

View file

@ -1,9 +1,35 @@
// // This code is originally from https://github.com/freedomtan/sensors/blob/master/sensors/sensors.m
// main.m // Here is the original code's license
// sensors
// // BSD 3-Clause License
// Created by Yang on 11/26/20.
// // Copyright (c) 2016-2018, "freedom" Koan-Sin Tan
// All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// * Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <IOKit/hidsystem/IOHIDEventSystemClient.h> #include <IOKit/hidsystem/IOHIDEventSystemClient.h>
@ -27,6 +53,7 @@ IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t , int32
CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property); CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property);
IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field); IOHIDFloat IOHIDEventGetFloatValue(IOHIDEventRef event, int32_t field);
// create a dict ref, like for temperature sensor {"PrimaryUsagePage":0xff00, "PrimaryUsage":0x5}
CFDictionaryRef matching(int page, int usage) CFDictionaryRef matching(int page, int usage)
{ {
CFNumberRef nums[2]; CFNumberRef nums[2];
@ -118,16 +145,34 @@ CFArrayRef getThermalValues(CFDictionaryRef sensors) {
return array; return array;
} }
double getTempValue(CFArrayRef values, int index) {
CFNumberRef value = CFArrayGetValueAtIndex(values, index);
double temp = 0.0;
CFNumberGetValue(value, kCFNumberDoubleType, &temp);
return temp;
}
void printCPUGPUTemps(CFArrayRef values) {
printf("CPU %0.1lf GPU %0.1lf, ", getTempValue(values,0), getTempValue(values,2));
}
void dumpValues(CFArrayRef values) void dumpValues(CFArrayRef values)
{ {
long count = CFArrayGetCount(values); long count = CFArrayGetCount(values);
double accumTemp = 0.0;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
CFNumberRef value = CFArrayGetValueAtIndex(values, i); CFNumberRef value = CFArrayGetValueAtIndex(values, i);
double temp = 0.0; double temp = 0.0;
CFNumberGetValue(value, kCFNumberDoubleType, &temp); CFNumberGetValue(value, kCFNumberDoubleType, &temp);
// NSLog(@"value = %lf\n", temp); // NSLog(@"value = %lf\n", temp);
printf("%0.1lf, ", temp); //printf("%0.1lf, ", temp);
if(temp > 0)
accumTemp+=temp;
} }
printf("%0.0lf", accumTemp/count);
} }
void dumpNames(CFArrayRef names, char *cat) void dumpNames(CFArrayRef names, char *cat)
@ -192,7 +237,8 @@ int main () {
CFDictionaryRef currentSensors = matching(0xff08, 2); CFDictionaryRef currentSensors = matching(0xff08, 2);
CFDictionaryRef voltageSensors = matching(0xff08, 3); CFDictionaryRef voltageSensors = matching(0xff08, 3);
CFDictionaryRef thermalSensors = matching(0xff00, 5); // 65280_10 = FF00_16 CFDictionaryRef thermalSensors = matching(0xff00, 5); // 65280_10 = FF00_16
// I change it to 0xff00, due to ioreg -dlx // thermalSensors's PrimaryUsagePage should be 0xff00 for M1 chip, instead of 0xff05
// can be checked by ioreg -lfx
CFArrayRef currentNames = getProductNames(currentSensors); CFArrayRef currentNames = getProductNames(currentSensors);
CFArrayRef voltageNames = getProductNames(voltageSensors); CFArrayRef voltageNames = getProductNames(voltageSensors);
@ -202,10 +248,10 @@ int main () {
// printf("freq, v_bat, a_bat, temp_bat"); // printf("freq, v_bat, a_bat, temp_bat");
// dumpNames(voltageNames, "V"); // dumpNames(voltageNames, "V");
// dumpNames(currentNames, "A"); // dumpNames(currentNames, "A");
dumpNames(thermalNames, "C"); //dumpNames(thermalNames, "C");
printf("\n"); fflush(stdout); //printf("\n"); fflush(stdout);
while (1) { //while (1) {
CFArrayRef currentValues = getPowerValues(currentSensors); CFArrayRef currentValues = getPowerValues(currentSensors);
CFArrayRef voltageValues = getPowerValues(voltageSensors); CFArrayRef voltageValues = getPowerValues(voltageSensors);
CFArrayRef thermalValues = getThermalValues(thermalSensors); CFArrayRef thermalValues = getThermalValues(thermalSensors);
@ -216,11 +262,11 @@ int main () {
// dumpValues(currentValues); // dumpValues(currentValues);
dumpValues(thermalValues); dumpValues(thermalValues);
printf("\n"); fflush(stdout); printf("\n"); fflush(stdout);
usleep(1000000); // usleep - suspend execution for microsecond intervals usleep(500000); // usleep - suspend execution for microsecond intervals
CFRelease(currentValues); CFRelease(currentValues);
CFRelease(voltageValues); CFRelease(voltageValues);
CFRelease(thermalValues); CFRelease(thermalValues);
} //}
#if 0 #if 0
NSLog(@"%@\n", CFArrayGetValueAtIndex(currentNames, 0)); NSLog(@"%@\n", CFArrayGetValueAtIndex(currentNames, 0));