python curses wrapper

This commit is contained in:
Ethan Wang 2021-02-27 17:46:31 -05:00
parent f7d6a13f4f
commit 01e6fe0bc3
9 changed files with 125 additions and 14 deletions

6
.gitignore vendored
View file

@ -1 +1,5 @@
.DS_Store
.DS_Store
/sensors/
/bin/
/curses/
/info/

View file

Before

Width:  |  Height:  |  Size: 4.7 MiB

After

Width:  |  Height:  |  Size: 4.7 MiB

BIN
demo/screen_shot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,022 KiB

106
monitor.py Executable file
View file

@ -0,0 +1,106 @@
#!/usr/bin/env python3
from curses import wrapper
import sys
import time
import platform
# import os, platform, subprocess
def get_processor_name():
return "Apple M1"
if platform.system() == "Darwin":
# os.environ['PATH'] = os.environ['PATH'] + os.pathsep + '/usr/sbin'
command ="/usr/sbin/sysctl -n machdep.cpu.brand_string"
return subprocess.check_output(command).strip()
return ""
def get_OS_ver():
ver = platform.mac_ver();
return f'macOS {ver[0]} ({ver[2]})'
log_flag = False;
if log_flag:
log_file = open("message.log","w")
def get_sorted_names():
# get `name1, name2, name3,` as names_str
names_str = sys.stdin.readline().strip()
names = names_str.split(',')[:-1] # ignore last '' item
names = [name.strip() for name in names]
name_i = [(name, i) for i, name in enumerate(names)]
# alphabetical order
sorted_name_i = sorted(name_i, key=lambda x: x[0].lower())
sorted_names = [name for name, i in sorted_name_i]
ordered_list = [i for name, i in sorted_name_i]
# i-th place holds nums[ordered_list[i]]
if log_flag:
print(names_str, '\n', sep='\n', file=log_file, flush=True) # sorted_name_i
return sorted_names, ordered_list
def get_sorted_nums(ordered_list):
nums_str = sys.stdin.readline().strip()
nums = nums_str.split(',')[:-1]
nums = [num.strip() for num in nums]
assert len(nums) == len(ordered_list)
sorted_nums = [float(nums[ordered_list[i]]) for i in range(len(nums))]
if log_flag:
print(nums_str, '\n', sep='\n', file=log_file, flush=True) # sorted_nums
return sorted_nums
def main(stdscr):
# 57 items, max name len = 25
# sorted_names = ['ANE MTR Temp Sensor1', 'GPU MTR Temp Sensor1', 'GPU MTR Temp Sensor4', 'ISP MTR Temp Sensor5', 'NAND CH0 temp', 'PMGR SOC Die Temp Sensor0', 'PMGR SOC Die Temp Sensor1', 'PMGR SOC Die Temp Sensor2', 'PMU TP3w', 'PMU tcal', 'PMU tdev1', 'PMU tdev2', 'PMU tdev3', 'PMU tdev4', 'PMU tdev5', 'PMU tdev6', 'PMU tdev7', 'PMU tdev8', 'PMU tdie1', 'PMU tdie2', 'PMU tdie4', 'PMU tdie5', 'PMU tdie6', 'PMU tdie7', 'PMU tdie8', 'PMU2 TR0Z', 'PMU2 TR1d', 'PMU2 TR1l', 'PMU2 TR2d', 'PMU2 TR2l', 'PMU2 TR3b', 'PMU2 TR3d', 'PMU2 TR4b', 'PMU2 TR4d', 'PMU2 TR5b', 'PMU2 TR5d', 'PMU2 TR6b', 'PMU2 TR7b', 'PMU2 TR8b', 'SOC MTR Temp Sensor0', 'SOC MTR Temp Sensor1', 'SOC MTR Temp Sensor2', 'eACC MTR Temp Sensor0', 'eACC MTR Temp Sensor3', 'gas gauge battery', 'gas gauge battery', 'gas gauge battery', 'gas gauge battery', 'gas gauge battery', 'gas gauge battery', 'pACC MTR Temp Sensor2', 'pACC MTR Temp Sensor3', 'pACC MTR Temp Sensor4', 'pACC MTR Temp Sensor5', 'pACC MTR Temp Sensor7', 'pACC MTR Temp Sensor8', 'pACC MTR Temp Sensor9'];
sorted_names, ordered_list = get_sorted_names()
n = len(sorted_names)
max_name_length = max(map(len, sorted_names));
ncol = 2
nrow0 = 3
nrow1 = n//2 + 1
sys_info = f'{get_processor_name()}, {get_OS_ver()}' # Processor: , OS:
while True:
# Clear screen
stdscr.clear()
ny,nx = stdscr.getmaxyx()
# Coordinates are always passed in the order y,x
# the top-left corner of a window is coordinate (0,0).
# assert nx>=80 and ny>=32
if not (nx>=80 and ny>=32):
stdscr.addnstr(0,0, 'enlarge the size of this terminal...', 50)
stdscr.addnstr(1,0, f'requires min 32x80, now {ny}x{nx} (row x col)', 50)
stdscr.refresh()
time.sleep(0.2)
continue
stdscr.addnstr(0,0, f'{sys_info}, {n} sensors (max_name_length={max_name_length})', 80)
xmid = nx//2 # //ncol
# __|__
# xmid
# xmid+3
sorted_nums = get_sorted_nums(ordered_list)
for y in range(0, nrow1):
stdscr.addnstr(nrow0+y,xmid, '|', 1)
i = 0;
for y in range(0, nrow1):
if i<n:
stdscr.addnstr(nrow0+y, 0, f'{sorted_names[i]:{max_name_length+3}} {sorted_nums[i]:5.1f}', 37)
i += 1
for y in range(0, nrow1):
if i<n:
stdscr.addnstr(nrow0+y,xmid+3, f'{sorted_names[i]:{max_name_length+3}} {sorted_nums[i]:5.1f}', 37)
i += 1
stdscr.refresh()
# stdscr.getkey()
time.sleep(0.9)
wrapper(main)

View file

@ -1,20 +1,20 @@
# Temperature Sensor Monitor for Apple Silicon M1
# Temperature Sensor Monitor for Apple Silicon M1
- `temp_sensor.m`: A modified version of the Objective-C [code](https://github.com/freedomtan/sensors/blob/master/sensors/sensors.m) for iOS sensor by [freedomtan](https://github.com/freedomtan);
- `temp_sensor.m`: modified on the Objective-C [code](https://github.com/freedomtan/sensors/blob/master/sensors/sensors.m) for iOS sensor by [freedomtan](https://github.com/freedomtan);
- `monitor.cpp`: A naive C++ wrapper for `temp_sensor.m` output for monitoring temperature in the terminal.
- `monitor.py`: a wrapper for `temp_sensor.m` output for monitoring temperature in the terminal.
## Usage
Compile `temp_sensor.m` and `monitor.cpp` individually. Then
Compile `temp_sensor.m` (by `clang -Wall -v temp_sensor.m -framework IOKit -framework Foundation -o temp_sensor`, Xcode on M1 mac needed). Then
`./temp_sensor | ./monitor` or `./temp_sensor`
`./temp_sensor | ./monitor.py` or `./temp_sensor`
Only test with my Mac mini with M1. Please check your mac's `ioreg -lfx` output to make changes in `temp_sensor.m` if needed.
Only test with my Macbook air with M1. Please check your mac's `ioreg -lfx` output to make changes in `temp_sensor.m` if needed.
## References
For **better names** (e.g. what is `PMU TP3w` ?) for the sensors, please refer to
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
@ -29,17 +29,16 @@ For intel Mac, an easier way to get sensor infomation:
`sudo powermetrics`
## Demo: screen shot and screen record
- screen record : screen_record.mp4[1.4MB] or
![screen record](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/screen_record.low.gif)
![screen record](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/demo/screen_record.low.gif)
- screen shot
![screen shot](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/screen_shot.png)
- screen shot
![screen shot](https://raw.githubusercontent.com/fermion-star/apple_sensors/master/demo/screen_shot.png)
<!---
![screen record](screen_record.mp4)
![screen shot](screen_shot.png)
![screen shot](screen_shot.png)
--->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 KiB

View file

@ -53,6 +53,7 @@ IOHIDEventRef IOHIDServiceClientCopyEvent(IOHIDServiceClientRef, int64_t , int32
CFStringRef IOHIDServiceClientCopyProperty(IOHIDServiceClientRef service, CFStringRef property);
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)
{
CFNumberRef nums[2];
@ -218,7 +219,8 @@ int main () {
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
// thermalSensors's PrimaryUsagePage should be 0xff00 for M1 chip, instead of 0xff05
// can be checked by ioreg -lfx
CFArrayRef currentNames = getProductNames(currentSensors);
CFArrayRef voltageNames = getProductNames(voltageSensors);