mirror of
https://github.com/ChrisSewell/PiTemp.git
synced 2025-04-18 22:28:01 -04:00
Initial commit: Add Raspberry Pi Live Temperature Monitor script and documentation
This commit is contained in:
commit
c8a9d99328
155
PiTemp.py
Executable file
155
PiTemp.py
Executable file
@ -0,0 +1,155 @@
|
||||
import curses
|
||||
import subprocess
|
||||
import time
|
||||
import asciichartpy
|
||||
import psutil
|
||||
from collections import deque
|
||||
import argparse
|
||||
import statistics
|
||||
|
||||
# Parse command-line arguments
|
||||
parser = argparse.ArgumentParser(description="Live Raspberry Pi Temperature Monitor")
|
||||
parser.add_argument("--threshold", type=float, default=70.0, help="Temperature threshold for alerts (default: 70.0°C)")
|
||||
parser.add_argument("--log", type=str, help="Path to log file (optional)")
|
||||
parser.add_argument("--points", type=int, default=100, help="Number of points to display on the graph (default: 100)")
|
||||
args = parser.parse_args()
|
||||
THRESHOLD = args.threshold
|
||||
LOG_FILE = args.log
|
||||
MAX_POINTS = args.points
|
||||
|
||||
# Initialize data storage
|
||||
temps = deque(maxlen=MAX_POINTS) # Store temperature readings
|
||||
start_time = time.time() # Track script start time
|
||||
|
||||
# Function to get the temperature
|
||||
def get_temp():
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['vcgencmd', 'measure_temp'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=2
|
||||
)
|
||||
temp_str = result.stdout.strip().split('=')[1].replace("'C", "")
|
||||
return float(temp_str)
|
||||
except Exception as e:
|
||||
return None
|
||||
|
||||
# Function to get the CPU load
|
||||
def get_cpu_load():
|
||||
return psutil.cpu_percent(interval=0.1)
|
||||
|
||||
# Function to log temperature to file if logging is enabled
|
||||
def log_temperature(temp):
|
||||
if LOG_FILE:
|
||||
with open(LOG_FILE, "a") as log_file:
|
||||
log_file.write(f"{time.strftime('%Y-%m-%d %H:%M:%S')} - {temp} °C\n")
|
||||
|
||||
# Function to draw the graph using asciichartpy
|
||||
def draw_graph(stdscr, temps, cpu_load, paused):
|
||||
stdscr.clear()
|
||||
height, width = stdscr.getmaxyx()
|
||||
|
||||
# Initialize colors
|
||||
curses.start_color()
|
||||
curses.use_default_colors()
|
||||
curses.init_pair(1, curses.COLOR_GREEN, -1) # Green for safe temps
|
||||
curses.init_pair(2, curses.COLOR_YELLOW, -1) # Yellow for warning temps
|
||||
curses.init_pair(3, curses.COLOR_RED, -1) # Red for high temps
|
||||
curses.init_pair(4, curses.COLOR_CYAN, -1) # Cyan for CPU load
|
||||
curses.init_pair(5, curses.COLOR_WHITE, -1) # White for normal text
|
||||
|
||||
# Display current temp and CPU load info
|
||||
if temps:
|
||||
current_temp = temps[-1]
|
||||
elapsed_time = time.strftime("%H:%M:%S", time.gmtime(time.time() - start_time))
|
||||
|
||||
# Choose color based on temperature
|
||||
if current_temp < THRESHOLD - 5:
|
||||
temp_color = curses.color_pair(1) # Green
|
||||
elif current_temp < THRESHOLD:
|
||||
temp_color = curses.color_pair(2) # Yellow
|
||||
else:
|
||||
temp_color = curses.color_pair(3) # Red
|
||||
|
||||
stdscr.addstr(0, 0, f"Current Temp: ", curses.color_pair(5))
|
||||
stdscr.addstr(f"{current_temp:.1f} °C", temp_color)
|
||||
|
||||
stdscr.addstr(1, 0, f"CPU Load: ", curses.color_pair(5))
|
||||
stdscr.addstr(f"{cpu_load:.1f}%", curses.color_pair(4))
|
||||
|
||||
stdscr.addstr(2, 0, f"Threshold: {THRESHOLD} °C", curses.color_pair(5))
|
||||
stdscr.addstr(3, 0, f"Elapsed Time: {elapsed_time}", curses.color_pair(5))
|
||||
stdscr.addstr(4, 0, f"{'PAUSED' if paused else 'RUNNING'}", curses.color_pair(5))
|
||||
|
||||
# Display alert if the latest temperature exceeds the threshold
|
||||
if current_temp > THRESHOLD:
|
||||
stdscr.addstr(5, 0, "ALERT: High Temperature!", curses.color_pair(3) | curses.A_BOLD | curses.A_REVERSE)
|
||||
|
||||
# Calculate dynamic min and max for the graph with buffers
|
||||
min_temp = min(temps)
|
||||
max_temp = max(temps)
|
||||
|
||||
# Add buffers to min and max temperatures
|
||||
buffer = 5
|
||||
min_temp_bound = max(min_temp - buffer, 0)
|
||||
max_temp_bound = max_temp + buffer
|
||||
|
||||
# Ensure a reasonable range if temps are very close
|
||||
if max_temp_bound - min_temp_bound < 10:
|
||||
max_temp_bound = min_temp_bound + 10
|
||||
|
||||
# Determine the number of points to display based on terminal width
|
||||
graph_width = width - 10
|
||||
temp_slice = list(temps)[-graph_width:]
|
||||
|
||||
# Plot temperatures using asciichartpy
|
||||
chart = asciichartpy.plot(temp_slice, {'height': height - 10, 'min': min_temp_bound, 'max': max_temp_bound})
|
||||
for i, line in enumerate(chart.split("\n")):
|
||||
if i + 7 < height:
|
||||
stdscr.addstr(i + 7, 0, line)
|
||||
|
||||
else:
|
||||
stdscr.addstr(0, 0, "No temperature data available.", curses.color_pair(3))
|
||||
|
||||
# Display command options at the bottom
|
||||
commands = "Commands: [q] Quit | [p] Pause | [r] Resume"
|
||||
stdscr.addstr(height - 2, 0, commands, curses.color_pair(4))
|
||||
|
||||
stdscr.refresh()
|
||||
|
||||
# Main function for curses
|
||||
def main(stdscr):
|
||||
curses.curs_set(0) # Hide cursor
|
||||
stdscr.nodelay(True) # Make getch non-blocking
|
||||
stdscr.timeout(1000) # Refresh every 1 second
|
||||
|
||||
paused = False
|
||||
|
||||
while True:
|
||||
key = stdscr.getch()
|
||||
if key == ord('q'):
|
||||
break
|
||||
elif key == ord('p'):
|
||||
paused = True
|
||||
elif key == ord('r'):
|
||||
paused = False
|
||||
|
||||
if not paused:
|
||||
temp = get_temp()
|
||||
if temp is not None:
|
||||
temps.append(temp)
|
||||
log_temperature(temp)
|
||||
|
||||
cpu_load = get_cpu_load()
|
||||
else:
|
||||
cpu_load = get_cpu_load() # Keep updating CPU load even when paused
|
||||
|
||||
draw_graph(stdscr, temps, cpu_load, paused)
|
||||
|
||||
# Run the curses application and display summary on exit
|
||||
try:
|
||||
curses.wrapper(main)
|
||||
finally:
|
||||
print("\nMonitoring stopped.")
|
||||
|
102
README.md
Normal file
102
README.md
Normal file
@ -0,0 +1,102 @@
|
||||
# Raspberry Pi Live Temperature Monitor
|
||||
|
||||
This script provides a **live, real-time graph** of your Raspberry Pi's CPU temperature and CPU load directly in the terminal. The graph scrolls dynamically as new data is collected and includes color-coded alerts for temperature thresholds.
|
||||
|
||||
I built this for use on my [Hackberry Pi](https://github.com/ZitaoTech/Hackberry-Pi_Zero), but others may find it useful as well. Check out their project for a great hand-held cyberdeck!
|
||||
|
||||
## Features
|
||||
|
||||
- **Real-Time Temperature Monitoring**: Continuously updates the CPU temperature in real-time.
|
||||
- **Dynamic Scrolling Graph**: Displays a scrolling graph of the most recent temperature readings.
|
||||
- **CPU Load Display**: Shows current CPU load percentage.
|
||||
- **Color-Coded Alerts**:
|
||||
- **Green**: Safe temperature.
|
||||
- **Yellow**: Warning temperature (close to threshold).
|
||||
- **Red**: Temperature exceeds the specified threshold.
|
||||
- **Pause/Resume Functionality**: Pause and resume the monitoring process.
|
||||
- **Logging (Optional)**: Logs temperature readings to a file with timestamps if the `--log` argument is provided.
|
||||
- **Elapsed Time**: Displays the total runtime of the script.
|
||||
- **Command-Line Arguments**: Customize threshold, log file path, and number of points displayed.
|
||||
|
||||
## Requirements
|
||||
|
||||
- **Python 3**
|
||||
- **Dependencies**:
|
||||
- `asciichartpy`: For plotting the graph.
|
||||
- `psutil`: For fetching CPU load data.
|
||||
|
||||
### Installing Dependencies
|
||||
|
||||
You can install the required dependencies using the `requirements.txt` file.
|
||||
|
||||
1. **Install via `pip`**:
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
2. **Alternatively, Install Manually**:
|
||||
|
||||
```bash
|
||||
pip install asciichartpy psutil
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Running the Script
|
||||
|
||||
```bash
|
||||
python PiTemp.py [OPTIONS]
|
||||
```
|
||||
|
||||
### Command-Line Options
|
||||
|
||||
| Option | Description | Default Value |
|
||||
|----------------------|---------------------------------------------------|------------------------|
|
||||
| `--threshold` | Temperature threshold for alerts (°C). | `70.0` |
|
||||
| `--log` | Path to the log file (optional). | None |
|
||||
| `--points` | Number of points to display on the graph. | `100` |
|
||||
|
||||
#### Example Command
|
||||
|
||||
```bash
|
||||
python PiTemp.py --threshold 65.0 --log my_temp_log.txt --points 200
|
||||
```
|
||||
|
||||
### Controls
|
||||
|
||||
| Key | Action |
|
||||
|-----|---------------|
|
||||
| `q` | Quit the script. |
|
||||
| `p` | Pause updates. |
|
||||
| `r` | Resume updates. |
|
||||
|
||||
## Output Example
|
||||
|
||||
```
|
||||
Current Temp: 55.2 °C
|
||||
CPU Load: 32.1%
|
||||
Threshold: 70.0 °C
|
||||
Elapsed Time: 00:05:23
|
||||
RUNNING
|
||||
|
||||
60.0 ┤ ╭─╮
|
||||
57.5 ┤ ╭────╯ ╰─╮
|
||||
55.0 ┤ ╭────╯ ╰╮
|
||||
52.5 ┤ ╭───────╯ ╰╮
|
||||
50.0 ┤ ╭───╯ ╰
|
||||
47.5 ┤ ╭───╯
|
||||
|
||||
Commands: [q] Quit | [p] Pause | [r] Resume
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
Temperature readings will **only be logged** if the `--log` argument is provided. Example log entries:
|
||||
|
||||
```
|
||||
2024-06-15 12:01:23 - 55.2 °C
|
||||
2024-06-15 12:01:24 - 55.6 °C
|
||||
2024-06-15 12:01:25 - 56.0 °C
|
||||
```
|
||||
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
asciichartpy==1.5.23
|
||||
psutil==5.9.8
|
Loading…
x
Reference in New Issue
Block a user