A lightweight, modular Telegram bot for monitoring Raspberry Pi system health metrics. Designed for Raspberry Pi OS, it collects temperature, CPU, RAM, disk, uptime, and network statistics and serves them on demand via a private Telegram bot — plus proactive alerts when something goes wrong.
pidiag/
├── src/
│ └── pidiag/
│ ├── __init__.py # Package marker
│ ├── __main__.py # Entry point for `python -m pidiag`
│ ├── config.py # Reads secrets from env vars, metric display labels
│ ├── collector.py # System metrics collection (psutil + sysfs)
│ ├── thresholds.py # Threshold definitions, persistence (JSON), alert logic
│ ├── bot.py # Telegram bot with inline keyboard + periodic alert job
│ └── main.py # Startup / shutdown logic
├── .env.example # Template for secrets (copy to .env)
├── .env # Your secrets (gitignored)
├── .gitignore
├── LICENSE
├── pidiag.service # systemd unit file
├── pyproject.toml # Package metadata & editable install
├── requirements.txt # Dependencies (sync with pyproject.toml)
└── README.md
Runtime data (`thresholds.json`, `.alerts_enabled`) is stored **outside**
the package — in `~/.config/pidiag/` (or `$PIDIAG_DATA_DIR`).
This keeps them safe across reinstalls and updates.
| Module | Role |
|---|---|
config.py |
Reads PIDIAG_BOT_TOKEN and PIDIAG_USER_ID from environment variables (.env). Defines metric display labels. |
collector.py |
Stateless metric functions returning (value, unit). collect_all() returns formatted strings for display; collect_raw() returns raw float values for threshold checking. |
thresholds.py |
Threshold definitions with metadata (unit, direction, defaults), JSON persistence, deduplication logic for repeated alerts (30 min cooldown). |
bot.py |
Telegram interface via python-telegram-bot v21+ with inline keyboard navigation. All handlers check authorization. Runs a periodic job every 5 minutes that checks all metrics against thresholds and sends proactive notifications. |
main.py |
Sets up logging, builds the app, and starts polling. |
The bot is fully operated via inline buttons — no typing required for common actions.
Just send /start (or any message) to get the main menu:
👋 PiDiag Bot — Raspberry Pi diagnostic
Choose a voice from the menu below:
🔔 Proactive notifications: ✅ active
[🌡️ Temperature] [⚙️ CPU]
[🧠 RAM] [💾 Disk]
[⏱️ Uptime] [🌐 Network]
[📊 All] [📏 Thresholds]
[🔔 Alerts: ON]
[❓ Help]
Tap a button to see live data. Each metric view has an [⬅️ Back to menu] button
to go back. The Alerts button toggles proactive notifications on/off.
Press [📏 Thresholds] to enter the interactive thresholds view:
📏 Alert Thresholds
Use ➖ and ➕ to adjust each threshold. Changes are saved immediately.
CPU Temperature: 75.0 °C
[➖] [➕]
GPU Temperature: 80.0 °C
[➖] [➕]
…
[⬅️ Back to menu]
Each threshold has a ➖ and ➕ button. One tap adjusts by a preset step
(5°C for temperatures, 5% for RAM/disk, 50 MHz for frequency, 0.5 for load average).
Changes are saved instantly to thresholds.json — no /set_threshold needed.
All commands still work by typing — useful for power users or automation:
| Command | Output |
|---|---|
/start |
Shows the main menu |
/temp |
CPU and GPU temperature in °C |
/cpu |
CPU load %, frequency (MHz), load average 1/5/15m |
/ram |
RAM used / total / percentage |
/disk |
Disk used / total / percentage |
/uptime |
System uptime (days/hours/minutes) |
/net |
IP address, current upload/download speed (B/s) |
/all |
Full diagnostics in a single message |
/thresholds |
Interactive threshold adjustment via inline buttons |
/set_threshold <key> <value> |
Change a threshold at runtime (persisted to thresholds.json) |
/alerts |
Enable proactive threshold notifications |
/noalerts |
Disable proactive threshold notifications |
/help |
Shows the main menu |
/set_threshold temp 75
The bot replies with a confirmation and saves the change immediately to thresholds.json.
The next alert cycle (within 5 minutes) will use the new value.
Every 5 minutes the bot runs a background check against all metrics. Notifications are state‑based, not timer‑based: you get a message only when something changes.
You can toggle proactive notifications at any time via the 🔔 Alerts button in the menu,
or with /alerts (enable) and /noalerts (disable).
The setting persists across bot restarts.
| Transition | What you receive |
|---|---|
| Normal → Threshold crossed | 🚨 CPU Temperature — Current: 82.0°C (above 75.0) |
| Threshold crossed → Normal | ✅ CPU Temperature — Current: 60.0°C (back to normal) |
If the value stays above the threshold across subsequent checks, no message is sent — zero spam. As soon as it returns to normal, you get a ✅ resolved notification. If it goes critical again later, you get a new 🚨 alert.
Example combined message:
🚨 Active alerts
🚨 CPU Temperature
Current: 82.0 °C (above 75.0)
✅ Resolved issues
✅ RAM Usage
Current: 40.0 % (back to normal)
Default values are calibrated for a Raspberry Pi 4:
| Key | Label | Direction | Default | What it detects |
|---|---|---|---|---|
temp |
CPU Temperature | > 75 °C | 75.0 | Overheating (throttling starts at 80°C) |
gpu |
GPU Temperature | > 80 °C | 80.0 | GPU overheating |
load |
CPU Load | > 80 % | 80.0 | High CPU usage (quad‑core) |
ram |
RAM Usage | > 85 % | 85.0 | Memory nearly full |
disk |
Root Disk | > 85 % | 85.0 | SD card nearly full |
freq |
CPU Frequency | < 600 MHz | 600.0 | Throttling / under‑voltage |
load15 |
Load Average 15m | > 3.5 | 3.5 | System overloaded (max 4.0 on 4‑core Pi) |
# 1. Clone / copy the project, then enter the directory
cd pidiag
# 2. Create and activate a dedicated virtual environment
python3 -m venv .venv
source .venv/bin/activate
# 3. Install the package in editable mode (includes all dependencies)
pip install -e .
# 4. Configure your secrets
cp .env.example .env
nano .env # ← paste your bot token and Telegram user ID
# 5. Run the bot (long-polling mode)
python -m pidiagStop it with Ctrl+C.
A service file is included at pidiag.service:
sudo cp pidiag.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable pidiag.service
sudo systemctl start pidiag.serviceThe bot runs from the virtual environment at .venv/. Make sure .env exists
in the project root — the service reads it at startup.
⚠️ Editpidiag.servicebefore copying to match your local paths (User,WorkingDirectory,ExecStart).
The .env file (which contains your bot token and user ID) is excluded from Git
via .gitignore. When cloning or forking this repository, remember to create your
own .env from .env.example — never commit real secrets.
All secrets are read from environment variables — never hardcoded. Copy .env.example
to .env and fill in your values:
cp .env.example .env| Variable | Source | Description |
|---|---|---|
PIDIAG_BOT_TOKEN |
@BotFather | Your bot's API token |
PIDIAG_USER_ID |
@userinfobot | Your Telegram numeric ID (only this ID can interact) |
PIDIAG_DATA_DIR |
(optional) | Override for runtime data directory (default: ~/.config/pidiag/) |
The .env file is excluded from Git via .gitignore — your secrets stay local.
Labels shown in the bot are defined in config.py → METRIC_NAMES dict. Feel free to
customise them (emoji, language, etc.).
Thresholds are managed through Telegram at runtime (use the 📏 Thresholds menu button
or /set_threshold) and persisted in thresholds.json. You can also edit the JSON file
directly — the bot reloads it on every check cycle.
python-telegram-bot[job-queue] >= 21.0— Telegram Bot API wrapper with scheduler supportpsutil >= 5.9.0— Cross-platform system metricspython-dotenv >= 1.0.0— Load.envfiles into environment variables
All are lightweight and available via pip. Install them all at once with pip install -e ..
- Network traffic speed is computed as a delta between consecutive
collect_all()calls. The first call returns—(no baseline yet). - Logging is in English and goes to stdout; redirect to a file if needed (e.g.
StandardOutput=append:/var/log/pidiag.login the service file). - The bot processes both text messages and callback queries from inline buttons.
- All replies use MarkdownV2 formatting.
- The alert job starts 60 seconds after the bot boots, giving time for the first conversation to establish the authorized chat ID.
- The
.envfile is loaded bymain.pybefore anypidiag.*imports, so secrets are available from the momentconfig.pyis first imported.