Skip to content

Commit 497d25e

Browse files
committed
Detect if not run as admin, minor fixes
1 parent 6d3f4e5 commit 497d25e

File tree

6 files changed

+47
-26
lines changed

6 files changed

+47
-26
lines changed

.github/workflows/system-monitor-windows.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ jobs:
3434
echo "Using theme ${{ matrix.theme }}"
3535
(Get-Content config.yaml) -replace "^ THEME.*$"," THEME: ${{ matrix.theme }}" | Set-Content config.yaml
3636
37+
# For tests do not use LibreHardwareMonitor as it needs admin rights
38+
(Get-Content config.yaml) -replace "^ HW_SENSORS.*$"," HW_SENSORS: PYTHON" | Set-Content config.yaml
39+
3740
- name: Run system monitor for 20 seconds
3841
run: |
3942
Start-Process -NoNewWindow python3 main.py -RedirectStandardOutput output.log -RedirectStandardError error.log

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,5 @@ dmypy.json
137137
# Simulated display capture
138138
screencap.png
139139
tmp
140+
141+
external/LibreHardwareMonitor/LibreHardwareMonitorLib.sys

config.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ config:
1515

1616
# Hardware sensors reading
1717
# Choose the appropriate method for reading your hardware sensors:
18-
# - PYTHON use Python libraries (psutils, GPUtil...) to read hardware sensors (supports all OS but not all HW)
19-
# - LHM use LibreHardwareMonitor library to read hardware sensors (Windows only)
20-
# - STUB use fake random data instead of real hardware sensors
21-
# - AUTO use the best method based on your OS: Windows OS will use LHM, other OS will use Python libraries
18+
# - PYTHON use Python libraries (psutils, GPUtil...) to read hardware sensors (supports all OS but not all HW)
19+
# - LHM use LibreHardwareMonitor library to read hardware sensors (Windows only - NEEDS ADMIN RIGHTS)
20+
# - STUB use fake random data instead of real hardware sensors
21+
# - AUTO use the best method based on your OS: Windows OS will use LHM, other OS will use Python libraries
2222
HW_SENSORS: AUTO
2323

2424
# Network interfaces

library/sensors/sensors_librehardwaremonitor.py

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import clr # from pythonnet package, not clr package !
2+
import ctypes
23
import math
34
import os
5+
import sys
46
from typing import Tuple
57
from statistics import mean
68
from win32api import *
@@ -26,6 +28,15 @@
2628
str(HIWORD(ls_file_version)),
2729
str(LOWORD(ls_file_version))]))
2830

31+
if ctypes.windll.shell32.IsUserAnAdmin() == 0:
32+
logger.error(
33+
"Program is not running as administrator. Please run with admin rights or choose another HW_SENSORS option in "
34+
"config.yaml")
35+
try:
36+
sys.exit(0)
37+
except:
38+
os._exit(0)
39+
2940
handle = Hardware.Computer()
3041
handle.IsCpuEnabled = True
3142
handle.IsGpuEnabled = True
@@ -66,7 +77,7 @@ def get_net_interface_and_update(if_name: str) -> Hardware.Hardware:
6677
hardware.Update()
6778
return hardware
6879

69-
logger.error("Network interface '%s' not found. Check names in config.yaml." % if_name)
80+
logger.warning("Network interface '%s' not found. Check names in config.yaml." % if_name)
7081
return None
7182

7283

@@ -86,7 +97,7 @@ def frequency() -> float:
8697
frequencies = []
8798
cpu = get_hw_and_update(Hardware.HardwareType.Cpu)
8899
for sensor in cpu.Sensors:
89-
if sensor.SensorType == Hardware.SensorType.Clock and str(sensor.Name).startswith("CPU Core #"):
100+
if sensor.SensorType == Hardware.SensorType.Clock and "Core #" in str(sensor.Name):
90101
frequencies.append(float(sensor.Value))
91102
return mean(frequencies)
92103

@@ -100,11 +111,9 @@ def is_temperature_available() -> bool:
100111
cpu = get_hw_and_update(Hardware.HardwareType.Cpu)
101112
for sensor in cpu.Sensors:
102113
if sensor.SensorType == Hardware.SensorType.Temperature:
103-
if str(sensor.Name).startswith("Core Average") or str(sensor.Name).startswith("Core Max") or str(
104-
sensor.Name).startswith("CPU Package"):
114+
if str(sensor.Name).startswith("Core") or str(sensor.Name).startswith("CPU Package"):
105115
return True
106116

107-
logger.error("CPU temperature cannot be read")
108117
return False
109118

110119
@staticmethod
@@ -118,10 +127,14 @@ def temperature() -> float:
118127
for sensor in cpu.Sensors:
119128
if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("Core Max"):
120129
return float(sensor.Value)
121-
# Otherwise the CPU Package temperature (usually same as max core temperature) will be used
130+
# If not available, the CPU Package temperature (usually same as max core temperature) will be used
122131
for sensor in cpu.Sensors:
123132
if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("CPU Package"):
124133
return float(sensor.Value)
134+
# Otherwise any sensor named "Core..." will be used
135+
for sensor in cpu.Sensors:
136+
if sensor.SensorType == Hardware.SensorType.Temperature and str(sensor.Name).startswith("Core"):
137+
return float(sensor.Value)
125138

126139
return math.nan
127140

@@ -233,7 +246,8 @@ def disk_usage_percent() -> float:
233246
if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("Used Space"):
234247
return float(sensor.Value)
235248

236-
return math.nan
249+
# Get this data from psutil if it is not available from LibreHardwareMonitor
250+
return psutil.disk_usage("/").percent
237251

238252
@staticmethod
239253
def disk_used() -> int: # In bytes
@@ -251,25 +265,25 @@ class Net(sensors.Net):
251265
def stats(if_name, interval) -> Tuple[
252266
int, int, int, int]: # up rate (B/s), uploaded (B), dl rate (B/s), downloaded (B)
253267

254-
dl_speed = 0
255-
dl = 0
256-
up_speed = 0
257-
up = 0
268+
upload_rate = 0
269+
uploaded = 0
270+
download_rate = 0
271+
downloaded = 0
258272

259273
if if_name != "":
260274
net_if = get_net_interface_and_update(if_name)
261275
if net_if is not None:
262276
for sensor in net_if.Sensors:
263277
if sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith("Data Uploaded"):
264-
up = int(sensor.Value * 1000000000.0)
278+
uploaded = int(sensor.Value * 1000000000.0)
265279
elif sensor.SensorType == Hardware.SensorType.Data and str(sensor.Name).startswith(
266280
"Data Downloaded"):
267-
dl = int(sensor.Value * 1000000000.0)
281+
downloaded = int(sensor.Value * 1000000000.0)
268282
elif sensor.SensorType == Hardware.SensorType.Throughput and str(sensor.Name).startswith(
269283
"Upload Speed"):
270-
up_speed = int(sensor.Value)
284+
upload_rate = int(sensor.Value)
271285
elif sensor.SensorType == Hardware.SensorType.Throughput and str(sensor.Name).startswith(
272286
"Download Speed"):
273-
dl_speed = int(sensor.Value)
287+
download_rate = int(sensor.Value)
274288

275-
return up_speed, up, dl_speed, dl
289+
return upload_rate, uploaded, download_rate, downloaded

library/sensors/sensors_python.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,10 @@ def stats(if_name, interval) -> Tuple[
254254
# Get current counters
255255
pnic_after = psutil.net_io_counters(pernic=True)
256256

257-
upload_rate = math.nan
258-
uploaded = math.nan
259-
download_rate = math.nan
260-
downloaded = math.nan
257+
upload_rate = 0
258+
uploaded = 0
259+
download_rate = 0
260+
downloaded = 0
261261

262262
if if_name in pnic_after:
263263
try:
@@ -270,5 +270,7 @@ def stats(if_name, interval) -> Tuple[
270270
pass
271271

272272
PNIC_BEFORE.update({if_name: pnic_after[if_name]})
273+
else:
274+
logger.warning("Network interface '%s' not found. Check names in config.yaml." % if_name)
273275

274276
return upload_rate, uploaded, download_rate, downloaded

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# Python packages requirements
2-
Pillow~=9.2.0 # Image generation
2+
Pillow~=9.3.0 # Image generation
33
pyserial~=3.5 # Serial linl to communicate with the display
44
PyYAML~=6.0 # For themes files
5-
psutil~=5.9.2 # CPU / disk / network metrics
5+
psutil~=5.9.4 # CPU / disk / network metrics
66
GPUtil~=1.4.0 # Nvidia GPU
77

88
# Following packages are for AMD GPU on Linux

0 commit comments

Comments
 (0)