First, I should admit that I’ve lost all control with ChatGPT. Second, programming a Raspberry Pi with Python to read the output of an inexpensive Hall Effect Flow Meter so I know when to change my water filter is a really cool project. Third, I could just replace my water filter every six months and not worry about it, but that’s not me. So I’ll probably exceed my WordPress and ChatGPT limits, but here goes. First, a list of the sections:
Basic Water Flow Monitor
Water Flow Monitor with Web Access
Water Flow Monitor with Alerts
Water Flow Monitor with Email Notifications
Water Flow Monitor with Logging
Water Flow Monitor with Graphing
Water Flow Monitor with Email Alerts
Water Flow Monitor with Reports
How to Power Water Flow Sensor
Gredia Sensor Changes from Digiten Sensor
Implement Virtual Environment for Flask
Set Program as Systemd Service
Set Up Reverse Proxy
Set Up SSL Certificate and Authentication
Set Up Login Page in Flask
Restrict Access to Logged-in Users
Deployment with Gunicorn & Nginx
How to backup an image of the Raspberry Pi SD (from Gemini)
I say:
Write a python program for a raspberry pi that uses a Digiten water hall effect flow sensor meter that records water flow.
Basic Water Flow Monitor
ChatGPT says:
Here’s a Python program for a Raspberry Pi that reads data from a DIGITEN water flow sensor (Hall effect sensor) and records the water flow in real-time.
🔹 How It Works:
- Uses GPIO interrupts to count pulses from the Hall effect sensor.
- Calculates the flow rate (L/min) and total water used (Liters).
- Records data to a CSV file for logging.
🔹 Hardware Setup:
- Connect the flow sensor’s wires to the Raspberry Pi:
- Red → 3.3V or 5V
- Black → Ground (GND)
- Yellow → GPIO pin (e.g., GPIO 17)
🔹 Python Code for Raspberry Pi
import RPi.GPIO as GPIO
import time
import csv
# GPIO pin connected to the yellow signal wire of the flow sensor
FLOW_SENSOR_PIN = 17
# Flow sensor calibration factor (from manufacturer, usually ~7.5 pulses per liter)
CALIBRATION_FACTOR = 7.5
# Variables
pulse_count = 0
total_liters = 0.0
# Setup GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def pulse_callback(channel):
""" Interrupt function to count pulses from flow sensor """
global pulse_count
pulse_count += 1
# Attach interrupt to count pulses
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
# CSV logging setup
csv_filename = "water_flow_log.csv"
with open(csv_filename, "a", newline="") as file:
writer = csv.writer(file)
writer.writerow(["Timestamp", "Flow Rate (L/min)", "Total Liters"])
try:
print("Monitoring water flow... Press Ctrl+C to stop.")
while True:
start_time = time.time()
pulse_count = 0 # Reset pulse count
time.sleep(1) # Measure over 1-second intervals
# Calculate flow rate (L/min)
flow_rate = (pulse_count / CALIBRATION_FACTOR) * 60
# Update total liters used
total_liters += (pulse_count / CALIBRATION_FACTOR)
# Log data
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
with open(csv_filename, "a", newline="") as file:
writer = csv.writer(file)
writer.writerow([timestamp, round(flow_rate, 2), round(total_liters, 2)])
# Display in terminal
print(f"[{timestamp}] Flow Rate: {flow_rate:.2f} L/min | Total: {total_liters:.2f} L")
except KeyboardInterrupt:
print("\nStopping water flow monitoring.")
finally:
GPIO.cleanup()
🔹 How to Use the Program
- Connect the flow sensor to your Raspberry Pi.
- Install required libraries (old Raspberry Pi):
sudo apt update sudo apt install python3-rpi.gpio - Install required libraries (new Raspberry Pi):
sudo apt update sudo apt install python3-rpi.lgpio - Run the script:
python3 flow_sensor.py - View data log in
water_flow_log.csv. - Add pip3:
sudo apt-get install python3-pip
🔹 Features
✅ Uses GPIO interrupts for accurate counting.
✅ Calculates flow rate (L/min) and total water usage (Liters).
✅ Logs data in a CSV file with timestamps.
✅ Efficient & real-time monitoring with minimal CPU usage.
Would you like to extend this with visual graphs or a web dashboard? 🚀
Water Flow Monitor with Web Access
Because of a conflict between apt and pip3, Flask should be installed in a virtual environment. Jump forward for how to setup the virtual environment.
To extend the Raspberry Pi water flow monitoring system with real-time graphs and a web dashboard, we can use Flask (for a web interface) and Plotly/Dash for dynamic graphs.
🔹 Plan for the Web Dashboard
- Backend (Flask): Reads data from the flow sensor and stores it in a CSV file.
- Frontend (Dash/Plotly): Displays real-time graphs of flow rate and total water usage.
- Web Access: You can view live data from any device on the same network.
🔹 Install Required Libraries
Before running the new version, install the necessary Python packages:
sudo apt update
pip3 install flask dash pandas plotly RPi.GPIO #for older RPi's
pip3 install flask dash pandas plotly rpi-lgpio # for newer RPi's
🔹 Updated Python Code (with Flask & Dash for Graphs)
This script runs both the water flow sensor and a web dashboard for real-time monitoring.
import RPi.GPIO as GPIO
import time
import csv
import pandas as pd
from flask import Flask
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
# GPIO Setup
FLOW_SENSOR_PIN = 17
CALIBRATION_FACTOR = 7.5
pulse_count = 0
total_liters = 0.0
csv_filename = "water_flow_log.csv"
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def pulse_callback(channel):
""" Interrupt function to count pulses from flow sensor """
global pulse_count
pulse_count += 1
# Attach interrupt to count pulses
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
# Initialize Flask and Dash
server = Flask(__name__)
app = dash.Dash(__name__, server=server)
# Dash Layout
app.layout = html.Div(children=[
html.H1("Water Flow Monitoring Dashboard"),
dcc.Graph(id="live-graph"),
dcc.Interval(id="interval-component", interval=3000, n_intervals=0) # Updates every 3 sec
])
# Background function to log data
def log_data():
global pulse_count, total_liters
with open(csv_filename, "a", newline="") as file:
writer = csv.writer(file)
writer.writerow(["Timestamp", "Flow Rate (L/min)", "Total Liters"])
try:
while True:
start_time = time.time()
pulse_count = 0
time.sleep(1)
flow_rate = (pulse_count / CALIBRATION_FACTOR) * 60
total_liters += (pulse_count / CALIBRATION_FACTOR)
timestamp = time.strftime("%Y-%m-%d %H:%M:%S")
with open(csv_filename, "a", newline="") as file:
writer = csv.writer(file)
writer.writerow([timestamp, round(flow_rate, 2), round(total_liters, 2)])
print(f"[{timestamp}] Flow Rate: {flow_rate:.2f} L/min | Total: {total_liters:.2f} L")
except KeyboardInterrupt:
GPIO.cleanup()
# Dash Callback for Graph Update
@app.callback(
Output("live-graph", "figure"),
Input("interval-component", "n_intervals")
)
def update_graph(n):
df = pd.read_csv(csv_filename)
fig = {
"data": [
{"x": df["Timestamp"], "y": df["Flow Rate (L/min)"], "type": "line", "name": "Flow Rate"},
{"x": df["Timestamp"], "y": df["Total Liters"], "type": "line", "name": "Total Usage"}
],
"layout": {"title": "Water Flow Data"}
}
return fig
if __name__ == "__main__":
from threading import Thread
Thread(target=log_data, daemon=True).start()
app.run_server(debug=True, host="0.0.0.0", port=8050)
🔹 How to Use
- Run the script on your Raspberry Pi:
python3 flow_monitor_dashboard.py - Access the dashboard from any device on the same network:
http://<Raspberry_Pi_IP>:8050(Replace<Raspberry_Pi_IP>with your Pi’s local IP address, e.g.,192.168.1.10:8050)
🔹 Features of This System
✅ Live Water Flow Graphs
✅ Historical Data Logging in CSV
✅ Access Dashboard from Any Device
✅ Efficient & Real-Time Updates
Would you like any additional features, such as alerts or mobile notifications? 🚀
Water Flow Monitor with Alerts
You can add alerts and mobile notifications to your Raspberry Pi water flow monitoring system using different methods. Here are some simple approaches:
🔹 Option 1: Send Notifications via Telegram (Recommended)
Why Telegram?
✅ Free & easy to set up
✅ Works on Android, iOS, PC, and Web
✅ Supports messages and images
✅ No need for extra apps if you already use Telegram
🔹 Steps to Set Up Telegram Alerts
1️⃣ Create a Telegram Bot
- Open Telegram and search for
@BotFather. - Start the chat and send:
/newbot - Follow the prompts and name your bot.
- Copy the bot token provided (e.g.,
123456789:ABCdefGhIjklMNO).
2️⃣ Get Your Chat ID
- Open
https://api.telegram.org/bot<TOKEN>/getUpdates
(Replace<TOKEN>with your bot token.) - Send a message to your bot.
- Reload the URL above; your chat ID will be in the response (
"chat": {"id": XXXXXXX}).
3️⃣ Add Telegram Notifications to Your Python Code
Modify your script to send an alert if the water flow exceeds a threshold:
import requests
# Replace with your Telegram bot token and chat ID
TELEGRAM_BOT_TOKEN = "123456789:ABCdefGhIjklMNO"
CHAT_ID = "XXXXXXXXX"
def send_telegram_alert(message):
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message}
requests.post(url, json=payload)
# Example: Send alert if flow rate exceeds 10 L/min
if flow_rate > 10:
send_telegram_alert(f"🚨 High Water Flow Alert! 🚰 Rate: {flow_rate:.2f} L/min")
🔹 Option 2: Email Alerts via Gmail
Steps:
- Enable “Less Secure Apps” on your Gmail account.
- Install
smtplib(already included in Python). - Modify your script to send emails:
import smtplib
EMAIL = "your-email@gmail.com"
PASSWORD = "your-email-password"
TO_EMAIL = "recipient-email@gmail.com"
def send_email_alert(message):
subject = "🚨 Water Flow Alert!"
body = f"Alert: {message}"
email_message = f"Subject: {subject}\n\n{body}"
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(EMAIL, PASSWORD)
server.sendmail(EMAIL, TO_EMAIL, email_message)
# Example usage
if flow_rate > 10:
send_email_alert(f"High water flow detected: {flow_rate:.2f} L/min")
🔹 Option 3: Push Notifications via Pushover
Why Pushover?
✅ Simple setup
✅ Works on all devices
✅ Free for basic use
Steps:
- Create a Pushover account at pushover.net.
- Get an API Key and User Key.
- Install
requests:pip3 install requests - Add this function to send notifications:
import requests
PUSHOVER_USER_KEY = "your-user-key"
PUSHOVER_API_KEY = "your-api-key"
def send_pushover_alert(message):
url = "https://api.pushover.net/1/messages.json"
payload = {
"token": PUSHOVER_API_KEY,
"user": PUSHOVER_USER_KEY,
"message": message
}
requests.post(url, data=payload)
# Example usage
if flow_rate > 10:
send_pushover_alert(f"High Water Flow: {flow_rate:.2f} L/min 🚰")
🔹 Which One Should You Use?
- ✅ Telegram: Easiest and most flexible
- ✅ Email: Good if you prefer inbox notifications
- ✅ Pushover: Great for mobile push notifications
Water Flow Monitor with Email Notifications
Would you like me to integrate one of these directly into your water monitoring script? 🚀
I’ll integrate Telegram notifications into your Raspberry Pi water flow monitoring script since it’s the easiest and most reliable method. Here’s the full script:
🔹 Features
✅ Reads flow rate from the DIGITEN water flow sensor
✅ Sends Telegram alerts when water flow exceeds a threshold
✅ Runs on a Raspberry Pi using GPIO & interrupts
✅ Customizable threshold for alerts
🔹 Steps to Use
1️⃣ Get a Telegram Bot Token
- Open Telegram and search for
@BotFather. - Send
/newbotand follow the instructions. - Copy the bot token (e.g.,
123456789:ABCdefGhIjklMNO).
2️⃣ Get Your Chat ID
- Visit:
https://api.telegram.org/bot<TOKEN>/getUpdates(Replace<TOKEN>with your bot token.) - Send a message to your bot.
- Reload the URL above and find your
"chat": {"id": XXXXXXX}.
3️⃣ Install Required Libraries
Run this command on your Raspberry Pi:
pip3 install RPi.GPIO requests
4️⃣ Full Python Script
import RPi.GPIO as GPIO
import time
import requests
# Telegram Bot Credentials
TELEGRAM_BOT_TOKEN = "123456789:ABCdefGhIjklMNO" # Replace with your bot token
CHAT_ID = "XXXXXXXXX" # Replace with your Telegram chat ID
# Flow Sensor Setup
FLOW_SENSOR_PIN = 17 # GPIO pin where the sensor signal is connected
FLOW_CALIBRATION = 7.5 # Adjust based on your sensor (L/pulse)
flow_rate = 0
pulse_count = 0
def send_telegram_alert(message):
""" Sends an alert message via Telegram """
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message}
requests.post(url, json=payload)
def pulse_callback(channel):
""" Interrupt function that counts pulses """
global pulse_count
pulse_count += 1
# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
try:
print("🔹 Water Flow Monitoring Started...")
while True:
pulse_count = 0 # Reset count
time.sleep(1) # Wait 1 second
flow_rate = (pulse_count / FLOW_CALIBRATION) * 60 # Convert pulses to L/min
# Print flow rate to console
print(f"💧 Flow Rate: {flow_rate:.2f} L/min")
# Send alert if flow rate is too high
if flow_rate > 10: # Change threshold as needed
send_telegram_alert(f"🚨 High Water Flow Alert! 🚰 {flow_rate:.2f} L/min")
except KeyboardInterrupt:
print("\n🔻 Stopping Monitoring...")
GPIO.cleanup()
🔹 How It Works
- Reads pulses from the DIGITEN water flow sensor.
- Converts pulses into liters per minute (L/min).
- If flow exceeds 10 L/min, sends a Telegram alert.
- Runs continuously until stopped (
Ctrl + C).
🔹 Customization
- Change the flow threshold in this line:
if flow_rate > 10:(Example: Set it to15if you want alerts at 15 L/min.) - Change GPIO pin (
FLOW_SENSOR_PIN = 17) if using a different pin.
🔹 Running the Script
Save the script as flow_monitor.py and run it with:
python3 flow_monitor.py
Your Raspberry Pi will now monitor water flow and send alerts to Telegram! 🚀
Would you like me to add logging to a file or historical tracking?
Water Flow Monitor with Logging
I’ll modify the script to log water flow data to a CSV file and track historical records. This will allow you to analyze trends over time.
🔹 New Features
✅ Saves flow data to flow_log.csv
✅ Includes timestamp, flow rate, and alert status
✅ Keeps track of max flow rate
✅ Telegram alerts still work
🔹 Full Python Script with Logging
import RPi.GPIO as GPIO
import time
import requests
import csv
import os
from datetime import datetime
# Telegram Bot Credentials
TELEGRAM_BOT_TOKEN = "123456789:ABCdefGhIjklMNO" # Replace with your bot token
CHAT_ID = "XXXXXXXXX" # Replace with your Telegram chat ID
# Flow Sensor Setup
FLOW_SENSOR_PIN = 17 # GPIO pin where the sensor signal is connected
FLOW_CALIBRATION = 7.5 # Adjust based on your sensor (L/pulse)
flow_rate = 0
pulse_count = 0
MAX_FLOW_RATE = 0 # Track highest recorded flow rate
# CSV Log File
LOG_FILE = "flow_log.csv"
def send_telegram_alert(message):
""" Sends an alert message via Telegram """
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message}
requests.post(url, json=payload)
def pulse_callback(channel):
""" Interrupt function that counts pulses """
global pulse_count
pulse_count += 1
def log_data(timestamp, flow_rate, alert_sent):
""" Logs water flow data to CSV file """
file_exists = os.path.isfile(LOG_FILE)
with open(LOG_FILE, mode="a", newline="") as file:
writer = csv.writer(file)
# Write header if file is new
if not file_exists:
writer.writerow(["Timestamp", "Flow Rate (L/min)", "Alert Sent"])
# Write data row
writer.writerow([timestamp, flow_rate, alert_sent])
# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
try:
print("🔹 Water Flow Monitoring Started...")
while True:
pulse_count = 0 # Reset count
time.sleep(1) # Wait 1 second
flow_rate = (pulse_count / FLOW_CALIBRATION) * 60 # Convert pulses to L/min
# Track max flow rate
global MAX_FLOW_RATE
if flow_rate > MAX_FLOW_RATE:
MAX_FLOW_RATE = flow_rate
# Print to console
print(f"{datetime.now()} 💧 Flow Rate: {flow_rate:.2f} L/min (Max: {MAX_FLOW_RATE:.2f} L/min)")
# Check for high flow rate and send alert
alert_sent = "No"
if flow_rate > 10: # Adjust threshold as needed
alert_sent = "Yes"
send_telegram_alert(f"🚨 High Water Flow Alert! 🚰 {flow_rate:.2f} L/min")
# Log data
log_data(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), flow_rate, alert_sent)
except KeyboardInterrupt:
print("\n🔻 Stopping Monitoring...")
GPIO.cleanup()
🔹 How It Works
- Reads water flow rate every second.
- Saves data to
flow_log.csvwith a timestamp. - Tracks the highest recorded flow rate.
- Sends a Telegram alert if the flow rate exceeds 10 L/min.
🔹 Example CSV Output (flow_log.csv)
Timestamp,Flow Rate (L/min),Alert Sent
2025-03-03 12:00:01,3.50,No
2025-03-03 12:00:02,4.20,No
2025-03-03 12:00:03,12.10,Yes
2025-03-03 12:00:04,11.75,Yes
🔹 Running the Script
Run this command on your Raspberry Pi:
python3 flow_monitor.py
Your Raspberry Pi will now log all water flow data and track the highest flow rate.
Would you like me to add graphing capabilities so you can visualize the data? 📊
Water Flow Monitor with Graphing
I’ll add graphing capabilities using Matplotlib so you can visualize your water flow data. The script will:
✅ Generate real-time graphs of water flow
✅ Plot historical data from flow_log.csv
✅ Automatically update the graph every few seconds
🔹 Install Matplotlib
Run this on your Raspberry Pi:
pip3 install matplotlib pandas
🔹 Updated Script with Graphing
import RPi.GPIO as GPIO
import time
import requests
import csv
import os
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from datetime import datetime
# Telegram Bot Credentials
TELEGRAM_BOT_TOKEN = "123456789:ABCdefGhIjklMNO" # Replace with your bot token
CHAT_ID = "XXXXXXXXX" # Replace with your Telegram chat ID
# Flow Sensor Setup
FLOW_SENSOR_PIN = 17 # GPIO pin where the sensor signal is connected
FLOW_CALIBRATION = 7.5 # Adjust based on your sensor (L/pulse)
flow_rate = 0
pulse_count = 0
MAX_FLOW_RATE = 0 # Track highest recorded flow rate
# CSV Log File
LOG_FILE = "flow_log.csv"
def send_telegram_alert(message):
""" Sends an alert message via Telegram """
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message}
requests.post(url, json=payload)
def pulse_callback(channel):
""" Interrupt function that counts pulses """
global pulse_count
pulse_count += 1
def log_data(timestamp, flow_rate, alert_sent):
""" Logs water flow data to CSV file """
file_exists = os.path.isfile(LOG_FILE)
with open(LOG_FILE, mode="a", newline="") as file:
writer = csv.writer(file)
# Write header if file is new
if not file_exists:
writer.writerow(["Timestamp", "Flow Rate (L/min)", "Alert Sent"])
# Write data row
writer.writerow([timestamp, flow_rate, alert_sent])
def read_csv_data():
""" Reads CSV file and returns data as a DataFrame """
if os.path.exists(LOG_FILE):
df = pd.read_csv(LOG_FILE)
return df
return None
# Graphing Function
def update_graph(frame):
""" Updates the real-time graph from CSV data """
plt.clf()
df = read_csv_data()
if df is not None and not df.empty:
df["Timestamp"] = pd.to_datetime(df["Timestamp"])
df["Flow Rate (L/min)"] = df["Flow Rate (L/min)"].astype(float)
plt.plot(df["Timestamp"], df["Flow Rate (L/min)"], label="Flow Rate (L/min)", color="b")
plt.axhline(y=10, color='r', linestyle='--', label="Alert Threshold (10 L/min)")
plt.xlabel("Time")
plt.ylabel("Flow Rate (L/min)")
plt.title("Water Flow Monitoring")
plt.xticks(rotation=45)
plt.legend()
plt.grid()
# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
try:
print("🔹 Water Flow Monitoring Started...")
fig = plt.figure()
ani = animation.FuncAnimation(fig, update_graph, interval=5000) # Update every 5 seconds
plt.show(block=False)
while True:
pulse_count = 0 # Reset count
time.sleep(1) # Wait 1 second
flow_rate = (pulse_count / FLOW_CALIBRATION) * 60 # Convert pulses to L/min
# Track max flow rate
global MAX_FLOW_RATE
if flow_rate > MAX_FLOW_RATE:
MAX_FLOW_RATE = flow_rate
# Print to console
print(f"{datetime.now()} 💧 Flow Rate: {flow_rate:.2f} L/min (Max: {MAX_FLOW_RATE:.2f} L/min)")
# Check for high flow rate and send alert
alert_sent = "No"
if flow_rate > 10: # Adjust threshold as needed
alert_sent = "Yes"
send_telegram_alert(f"🚨 High Water Flow Alert! 🚰 {flow_rate:.2f} L/min")
# Log data
log_data(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), flow_rate, alert_sent)
except KeyboardInterrupt:
print("\n🔻 Stopping Monitoring...")
GPIO.cleanup()
🔹 How It Works
- Monitors water flow and logs it to
flow_log.csv - Plots real-time water flow data in a graph
- Red dashed line at 10 L/min shows the alert threshold
- Graph updates every 5 seconds
- Runs in the background while monitoring
🔹 Running the Script
Run this command on your Raspberry Pi:
python3 flow_monitor.py
You’ll see a real-time graph pop up tracking the water flow over time. 📈
Would you like an email alert option too? 📩
Water Flow Monitor with Email Alerts
I’ll add email alerts using SMTP with Gmail so you can receive notifications when water flow exceeds a set threshold.
🔹 What’s New?
✅ Email alerts when water flow is high 🚨
✅ Works alongside Telegram alerts 📲
✅ Uses SMTP for Gmail or any other provider
🔹 Setup Email Alerts
Before running the script, enable “Less Secure Apps” or create an App Password in your email settings.
For Gmail, go to: Google App Passwords
Generate a password and use it instead of your regular password in the script.
🔹 Install Required Package
Run this on your Raspberry Pi:
pip3 install smtplib
🔹 Updated Python Script with Email Alerts
import RPi.GPIO as GPIO
import time
import requests
import csv
import os
import smtplib
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from datetime import datetime
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
# Telegram Bot Credentials
TELEGRAM_BOT_TOKEN = "123456789:ABCdefGhIjklMNO" # Replace with your bot token
CHAT_ID = "XXXXXXXXX" # Replace with your Telegram chat ID
# Email Credentials
SMTP_SERVER = "smtp.gmail.com" # Change if using Outlook, Yahoo, etc.
SMTP_PORT = 587
EMAIL_ADDRESS = "your_email@gmail.com" # Replace with your email
EMAIL_PASSWORD = "your_app_password" # Replace with App Password
# Flow Sensor Setup
FLOW_SENSOR_PIN = 17 # GPIO pin where the sensor signal is connected
FLOW_CALIBRATION = 7.5 # Adjust based on your sensor (L/pulse)
flow_rate = 0
pulse_count = 0
MAX_FLOW_RATE = 0 # Track highest recorded flow rate
# CSV Log File
LOG_FILE = "flow_log.csv"
def send_telegram_alert(message):
""" Sends an alert message via Telegram """
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {"chat_id": CHAT_ID, "text": message}
requests.post(url, json=payload)
def send_email_alert(subject, body):
""" Sends an email alert """
try:
msg = MIMEMultipart()
msg["From"] = EMAIL_ADDRESS
msg["To"] = EMAIL_ADDRESS # Send email to yourself (or modify to send to others)
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls()
server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
server.sendmail(EMAIL_ADDRESS, EMAIL_ADDRESS, msg.as_string())
server.quit()
print("📧 Email Alert Sent!")
except Exception as e:
print(f"❌ Email Alert Failed: {e}")
def pulse_callback(channel):
""" Interrupt function that counts pulses """
global pulse_count
pulse_count += 1
def log_data(timestamp, flow_rate, alert_sent):
""" Logs water flow data to CSV file """
file_exists = os.path.isfile(LOG_FILE)
with open(LOG_FILE, mode="a", newline="") as file:
writer = csv.writer(file)
# Write header if file is new
if not file_exists:
writer.writerow(["Timestamp", "Flow Rate (L/min)", "Alert Sent"])
# Write data row
writer.writerow([timestamp, flow_rate, alert_sent])
def read_csv_data():
""" Reads CSV file and returns data as a DataFrame """
if os.path.exists(LOG_FILE):
df = pd.read_csv(LOG_FILE)
return df
return None
# Graphing Function
def update_graph(frame):
""" Updates the real-time graph from CSV data """
plt.clf()
df = read_csv_data()
if df is not None and not df.empty:
df["Timestamp"] = pd.to_datetime(df["Timestamp"])
df["Flow Rate (L/min)"] = df["Flow Rate (L/min)"].astype(float)
plt.plot(df["Timestamp"], df["Flow Rate (L/min)"], label="Flow Rate (L/min)", color="b")
plt.axhline(y=10, color='r', linestyle='--', label="Alert Threshold (10 L/min)")
plt.xlabel("Time")
plt.ylabel("Flow Rate (L/min)")
plt.title("Water Flow Monitoring")
plt.xticks(rotation=45)
plt.legend()
plt.grid()
# GPIO Setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(FLOW_SENSOR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(FLOW_SENSOR_PIN, GPIO.FALLING, callback=pulse_callback)
try:
print("🔹 Water Flow Monitoring Started...")
fig = plt.figure()
ani = animation.FuncAnimation(fig, update_graph, interval=5000) # Update every 5 seconds
plt.show(block=False)
while True:
pulse_count = 0 # Reset count
time.sleep(1) # Wait 1 second
flow_rate = (pulse_count / FLOW_CALIBRATION) * 60 # Convert pulses to L/min
# Track max flow rate
global MAX_FLOW_RATE
if flow_rate > MAX_FLOW_RATE:
MAX_FLOW_RATE = flow_rate
# Print to console
print(f"{datetime.now()} 💧 Flow Rate: {flow_rate:.2f} L/min (Max: {MAX_FLOW_RATE:.2f} L/min)")
# Check for high flow rate and send alerts
alert_sent = "No"
if flow_rate > 10: # Adjust threshold as needed
alert_sent = "Yes"
message = f"🚨 High Water Flow Alert! 🚰 {flow_rate:.2f} L/min"
send_telegram_alert(message)
send_email_alert("🚨 Water Flow Alert!", message)
# Log data
log_data(datetime.now().strftime("%Y-%m-%d %H:%M:%S"), flow_rate, alert_sent)
except KeyboardInterrupt:
print("\n🔻 Stopping Monitoring...")
GPIO.cleanup()
🔹 How It Works
- Monitors water flow and logs it to
flow_log.csv - Plots real-time water flow data 📈
- Sends alerts via Telegram and Email if water flow exceeds 10 L/min
- Automatically updates the graph every 5 seconds
🔹 Running the Script
Run this command on your Raspberry Pi:
python3 flow_monitor.py
Your Raspberry Pi will now log all water flow data, track alerts, and notify you via Telegram & Email.
🔹 Example Email Alert
Subject: 🚨 Water Flow Alert!
Body:
🚨 High Water Flow Alert! 🚰 12.5 L/min
Now, you’ve got a fully automated monitoring system! Want weekly reports emailed with summary stats? 📊📧
Water Flow Monitor with Reports
I’ll add weekly email reports that summarize water usage and include a graph. The report will:
✅ Show total water usage for the week
✅ Include highest & average flow rates
✅ Attach a graph of water flow trends
🔹 Install Required Packages
Before running the script, install the required dependencies:
pip3 install pandas matplotlib smtplib
🔹 Updated Script with Weekly Email Reports
import os
import csv
import pandas as pd
import matplotlib.pyplot as plt
import smtplib
from datetime import datetime, timedelta
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders
# Email Credentials
SMTP_SERVER = "smtp.gmail.com"
SMTP_PORT = 587
EMAIL_ADDRESS = "your_email@gmail.com" # Replace with your email
EMAIL_PASSWORD = "your_app_password" # Use App Password
# CSV Log File
LOG_FILE = "flow_log.csv"
REPORT_IMAGE = "weekly_report.png"
def generate_weekly_report():
""" Reads CSV data, calculates stats, and generates a weekly graph. """
if not os.path.exists(LOG_FILE):
print("❌ No log data found!")
return None
# Load data
df = pd.read_csv(LOG_FILE)
df["Timestamp"] = pd.to_datetime(df["Timestamp"])
# Filter for the last 7 days
last_week = datetime.now() - timedelta(days=7)
df = df[df["Timestamp"] >= last_week]
if df.empty:
print("❌ No data available for the past week!")
return None
# Calculate statistics
total_usage = df["Flow Rate (L/min)"].sum()
avg_flow = df["Flow Rate (L/min)"].mean()
max_flow = df["Flow Rate (L/min)"].max()
# Generate graph
plt.figure(figsize=(10, 5))
plt.plot(df["Timestamp"], df["Flow Rate (L/min)"], label="Flow Rate", color="b")
plt.axhline(y=10, color='r', linestyle='--', label="Alert Threshold (10 L/min)")
plt.xlabel("Date")
plt.ylabel("Flow Rate (L/min)")
plt.title("Weekly Water Flow Report")
plt.xticks(rotation=45)
plt.legend()
plt.grid()
plt.savefig(REPORT_IMAGE)
plt.close()
return total_usage, avg_flow, max_flow
def send_weekly_email():
""" Sends a weekly email with stats and an attached graph. """
stats = generate_weekly_report()
if not stats:
return
total_usage, avg_flow, max_flow = stats
# Email Content
subject = "💧 Weekly Water Flow Report"
body = (
f"Here is your water usage summary for the past week:\n\n"
f"📊 Total Water Usage: {total_usage:.2f} L\n"
f"📉 Average Flow Rate: {avg_flow:.2f} L/min\n"
f"🚀 Highest Flow Rate: {max_flow:.2f} L/min\n\n"
f"See the attached graph for trends. 📈"
)
msg = MIMEMultipart()
msg["From"] = EMAIL_ADDRESS
msg["To"] = EMAIL_ADDRESS # Send to yourself
msg["Subject"] = subject
msg.attach(MIMEText(body, "plain"))
# Attach the graph
with open(REPORT_IMAGE, "rb") as attachment:
part = MIMEBase("application", "octet-stream")
part.set_payload(attachment.read())
encoders.encode_base64(part)
part.add_header("Content-Disposition", f"attachment; filename={REPORT_IMAGE}")
msg.attach(part)
# Send Email
try:
server = smtplib.SMTP(SMTP_SERVER, SMTP_PORT)
server.starttls()
server.login(EMAIL_ADDRESS, EMAIL_PASSWORD)
server.sendmail(EMAIL_ADDRESS, EMAIL_ADDRESS, msg.as_string())
server.quit()
print("📧 Weekly Report Sent!")
except Exception as e:
print(f"❌ Email Failed: {e}")
# Schedule to run once a week
if __name__ == "__main__":
send_weekly_email()
🔹 How It Works
- Runs once a week (you can automate this with a cron job)
- Reads the past 7 days of water flow data
- Calculates total, average, and max flow rate
- Generates a graph 📈
- Sends an email with stats + graph attachment
🔹 Automate with Cron Job
To send the report every Monday at 8 AM, edit your crontab:
crontab -e
Add this line:
0 8 * * 1 python3 /home/pi/send_weekly_email.py
🔹 Example Email Report
Subject: 💧 Weekly Water Flow Report
Here is your water usage summary for the past week:
📊 Total Water Usage: 320.5 L
📉 Average Flow Rate: 4.8 L/min
🚀 Highest Flow Rate: 12.3 L/min
See the attached graph for trends. 📈
📎 Attachment: weekly_report.png (Graph of water flow trends)
Now you’ll get automatic weekly reports summarizing your water usage! Let me know if you want custom thresholds or other features. 🚀
How should i provide power to the sensor?
How to Power Water Flow Sensor
The DIGITEN water flow sensor is typically powered by 5V DC, which is compatible with the Raspberry Pi’s 5V pin. Here’s how you can provide power safely:
🔹 Recommended Wiring for Raspberry Pi
| Flow Sensor Wire | Connect To |
|---|---|
| Red (Power) | 5V pin on Raspberry Pi |
| Black (Ground) | GND pin on Raspberry Pi |
| Yellow (Signal) | GPIO 17 (or your chosen GPIO pin) |
🔹 Powering the Sensor Directly from Raspberry Pi
- Use the Raspberry Pi’s 5V Pin
- The 5V pin on the Raspberry Pi can provide enough power for the sensor.
- Connect the Red wire of the sensor to the 5V pin.
- Connect Ground (GND)
- The Black wire should go to a GND pin on the Raspberry Pi.
- Signal to GPIO
- The Yellow wire carries the pulses from the Hall effect sensor.
- Connect it to GPIO 17 (or another available GPIO pin).
🔹 Alternative: External 5V Power Supply (If Needed)
If you’re using multiple sensors or don’t want to draw power from the Raspberry Pi, you can:
- Use a separate 5V power supply (USB adapter or battery pack).
- Common ground is required: Connect the GND of the external power supply to the GND of the Raspberry Pi.
Would you like a wiring diagram for better clarity? 🚀
Here’s a simple wiring diagram to help you connect your DIGITEN water flow sensor to a Raspberry Pi properly.
🔹 Wiring Guide
Option 1: Powering the Sensor from Raspberry Pi (Recommended)
- Red wire (Power) → Raspberry Pi 5V (Pin 2 or 4)
- Black wire (Ground) → Raspberry Pi GND (Pin 6, 9, 14, 20, etc.)
- Yellow wire (Signal) → Raspberry Pi GPIO 17 (Pin 11)
+------------------------+
| Raspberry Pi (GPIO) |
+------------------------+
| 5V (Pin 2) ──── Red │ → Power to sensor
| GND (Pin 6) ──── Black│ → Ground
| GPIO17 (Pin 11) ── Yellow │ → Signal from sensor
+------------------------+
Option 2: Powering the Sensor with an External 5V Power Supply
- Red wire → External 5V Power Supply (+)
- Black wire → External Power Supply GND & Raspberry Pi GND
- Yellow wire → Raspberry Pi GPIO 17
+------------------------+ +--------------------+
| Raspberry Pi (GPIO) | | External 5V PSU |
+------------------------+ +--------------------+
| GND (Pin 6) ───────────┐ | GND (Black) |
| GPIO17 (Pin 11) ─── Yellow │ | 5V (Red) |
| │────────| |
+------------------------+ +--------------------+
⚠ Important: Make sure the Raspberry Pi GND and external GND are connected together.
🔹 Wiring Diagram (Visual Representation)
I’ll generate an image of the wiring diagram for better clarity. Give me a moment.
Here is a wiring diagram showing how to connect a DIGITEN water flow sensor to a Raspberry Pi. Let me know if you need any modifications or further explanations! 🚀

How do i start this program when the rpi boots?
Start Program at Boot
You can set up your Raspberry Pi to run the script at boot using one of these methods:
Method 1: Use systemd (Recommended)
Systemd is the most reliable way to start a script at boot and restart it if it crashes.
1️⃣ Create a systemd Service File
Run the following command to create a new service file:
sudo nano /etc/systemd/system/flow_monitor.service
Paste this into the file (update the paths if needed):
[Unit]
Description=Water Flow Monitor
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/send_weekly_email.py
WorkingDirectory=/home/pi
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Save the file (CTRL + X, then Y, then Enter).
2️⃣ Enable the Service
Run these commands to start the service at boot:
sudo systemctl daemon-reload
sudo systemctl enable flow_monitor.service
sudo systemctl start flow_monitor.service
Check if it’s running:
sudo systemctl status flow_monitor.service
To restart manually:
sudo systemctl restart flow_monitor.service
To stop it:
sudo systemctl stop flow_monitor.service
Method 2: Use Cron (Simple but Less Reliable)
- Open the crontab editor:
crontab -e - Add this line at the bottom to run the script at boot:
@reboot python3 /home/pi/send_weekly_email.py & - Save and exit.
Which Method to Use?
- ✅ Use systemd if you want automatic restarts and better reliability.
- ✅ Use cron if you need a quick and simple setup.
Let me know if you need help with any step! 🚀
The Digiten sensor wasn’t available so I got a Gredia GR-402B sensor. Will there be any changes?
Changes for Gredia Sensor Instead of Digiten Sensor
Yes, the program should work almost the same with a GREDIA water flow sensor, as it also uses a Hall-effect sensor to measure water flow. However, you may need to adjust the calibration factor (pulse-per-liter value) depending on the specific model of your GREDIA sensor.
🔹 What to Check?
- Pinout: Ensure you connect the GREDIA sensor’s VCC, GND, and Signal (Yellow/Green) wire correctly to your Raspberry Pi.
- Operating Voltage: Most GREDIA sensors work with 5V, while some also support 3.3V.
- Pulse-per-Liter Factor: Different flow sensors have different pulse-per-liter ratios.
- DIGITEN sensors often use 450 pulses per liter.
- GREDIA sensors could have 450, 500, or 550 pulses per liter, depending on the model.
To find the correct pulse-per-liter for your sensor, check its datasheet or do a manual calibration.
🔹 Adjusting the Code for a GREDIA Sensor
Find this line in your script:
pulse_per_liter = 450 # Adjust based on sensor model
✅ Change this value based on your GREDIA sensor’s specifications.
🔹 How to Manually Calibrate?
- Run the script and measure how much water you actually use.
- Compare it to what the program records.
- Adjust the
pulse_per_litervalue until the recorded water usage matches real-world usage.
🔹 Will Alerts & Email Reports Still Work?
Yes! The rest of the program (data logging, alerts, and email reports) will work the same. The only thing that needs adjusting is the pulse-per-liter value.
Would you like help finding the correct value for your specific GREDIA sensor? 🚀
the flask install had the error: externally-managed-environment
The externally-managed-environment error occurs because you’re trying to install Flask (or another package) in a system-managed Python environment, like the one on Raspberry Pi OS (Debian-based Linux). This happens because newer versions of pip prevent modifying system-wide Python packages.
🔹 How to Fix It
You have a few options to install Flask properly:
✅ Option 1: Use a Virtual Environment (Recommended)
This is the best method because it keeps your Python packages separate and avoids system conflicts.
1️⃣ Create a Virtual Environment
Run these commands:
cd /home/pi # Go to your working directory
python3 -m venv venv # Create a virtual environment named 'venv'
2️⃣ Activate the Virtual Environment
source venv/bin/activate
You should see (venv) appear in your terminal.
3️⃣ Install Flask
pip install flask
4️⃣ Run Your Flask App
Now, when running your Flask script, make sure the virtual environment is activated:
python your_flask_script.py
💡 To exit the virtual environment, type:
deactivate
✅ Option 2: Use pip install --break-system-packages
If you really want to install Flask system-wide (not recommended), use:
pip install flask --break-system-packages
⚠️ Warning: This could break system dependencies.
✅ Option 3: Use --user Flag (Less Recommended)
pip install --user flask
This installs Flask in the user’s home directory, avoiding system conflicts.
🔹 Which Method to Use?
- ✅ Use a Virtual Environment if you’re working on a project.
- ✅ Use
--break-system-packagesonly if you fully control your Raspberry Pi and don’t mind breaking things. - ✅ Use
--userfor a quick fix, but it’s not as clean as a virtual environment.
Would you like me to update your Python script to run inside a virtual environment automatically? 🚀
I’ll update your Python script to automatically activate a virtual environment and install dependencies if needed. Here’s how to do it:
🔹 Updated Python Script
Replace your existing script with this version:
import os
import sys
import subprocess
# Define the virtual environment path
VENV_PATH = os.path.expanduser("~/venv")
# Function to check if Flask is installed
def check_flask():
try:
import flask
except ImportError:
return False
return True
# Function to set up the virtual environment
def setup_virtualenv():
if not os.path.exists(VENV_PATH):
print("Creating virtual environment...")
subprocess.run([sys.executable, "-m", "venv", VENV_PATH], check=True)
# Install Flask if not present
activate_script = os.path.join(VENV_PATH, "bin", "activate")
pip_path = os.path.join(VENV_PATH, "bin", "pip")
if not check_flask():
print("Installing Flask in virtual environment...")
subprocess.run([pip_path, "install", "flask"], check=True)
# Setup virtual environment
setup_virtualenv()
# Activate the virtual environment
activate_script = os.path.join(VENV_PATH, "bin", "activate_this.py")
exec(open(activate_script).read(), dict(__file__=activate_script))
# Now you can safely import Flask and run your app
from flask import Flask
app = Flask(__name__)
@app.route("/")
def home():
return "Flask is running in a virtual environment!"
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
🔹 How This Works
- Automatically creates a virtual environment in
~/venvif it doesn’t exist. - Installs Flask inside the virtual environment if it’s not already installed.
- Activates the virtual environment before running the Flask app.
- Starts a simple Flask web server on
http://0.0.0.0:5000.
🔹 How to Run It
Save the script as app.py and run:
python3 app.py
Flask will now run inside the virtual environment automatically!
Would you like help setting this up as a systemd service so it starts at boot? 🚀
Would you like help setting this up as a systemd service so it starts at boot? 🚀
Set Program as Systemd Service
Set Up Flask as a Systemd Service on Raspberry Pi
This will ensure your Flask app starts automatically at boot and keeps running in the background.
🔹 Step 1: Create a systemd Service File
Run this command to open a new service file:
sudo nano /etc/systemd/system/flask_app.service
Paste the following inside (update the User, WorkingDirectory, and ExecStart paths if needed):
[Unit]
Description=Flask Web Application
After=network.target
[Service]
User=pi
WorkingDirectory=/home/pi
ExecStart=/home/pi/venv/bin/python3 /home/pi/app.py
Restart=always
[Install]
WantedBy=multi-user.target
✅ Save the file: Press CTRL + X, then Y, then Enter.
🔹 Step 2: Enable and Start the Service
Run these commands:
sudo systemctl daemon-reload
sudo systemctl enable flask_app.service
sudo systemctl start flask_app.service
🔹 Step 3: Check If Flask is Running
To check the status:
sudo systemctl status flask_app.service
You should see output indicating that Flask is active (running).
If there’s an error, check the logs:
journalctl -u flask_app.service --no-pager --lines=50
🔹 Step 4: Restarting or Stopping Flask
To restart manually:
sudo systemctl restart flask_app.service
To stop it:
sudo systemctl stop flask_app.service
🔹 Step 5: Test Flask in a Web Browser
Open a browser and go to:
http://<Your-Raspberry-Pi-IP>:5000
If running locally, use:
http://localhost:5000
🚀 Your Flask App Now Starts at Boot!
Would you like help setting up nginx as a reverse proxy for better performance and HTTPS support?
Set Up Reverse Proxy
Set Up Nginx as a Reverse Proxy for Flask on Raspberry Pi
This will allow your Flask app to be accessible using port 80 (HTTP) instead of port 5000 and make it more efficient. It also allows for SSL encryption if you add a certificate later.
🔹 Step 1: Install Nginx
Run:
sudo apt update
sudo apt install nginx -y
🔹 Step 2: Create an Nginx Configuration File
- Open a new configuration file:
sudo nano /etc/nginx/sites-available/flask_app - Paste this configuration (adjust server_name if needed):
server { listen 80; server_name _; # Change this to your domain if using one location / { proxy_pass http://127.0.0.1:5000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } error_page 404 /404.html; location = /404.html { internal; } } - Save and exit: Press
CTRL + X, thenY, thenEnter.
🔹 Step 3: Enable the Configuration
- Create a symbolic link to enable the configuration:
sudo ln -s /etc/nginx/sites-available/flask_app /etc/nginx/sites-enabled/ - Remove the default configuration (optional but recommended):
sudo rm /etc/nginx/sites-enabled/default - Test Nginx for errors:
sudo nginx -t✅ If you seesyntax is OK, you’re good to go! - Restart Nginx:
sudo systemctl restart nginx
🔹 Step 4: Test the Setup
- Open your browser and visit:
http://<Your-Raspberry-Pi-IP>/or if you set up a domain:http://yourdomain.com/ - Your Flask app should now be accessible without
:5000.
🔹 Step 5: Optional – Enable HTTPS with Let’s Encrypt (Recommended)
If you have a domain, you can secure your site with Let’s Encrypt SSL:
sudo apt install certbot python3-certbot-nginx -y
sudo certbot --nginx -d yourdomain.com
This automatically configures Nginx to use HTTPS.
🚀 Flask is Now Running Behind Nginx!
Would you like me to help with auto-renewing SSL certificates or adding authentication to your Flask app?
Set Up SSL Certificate and Authentication
🔹 Auto-Renew SSL Certificates & Add Authentication to Your Flask App
Now that your Flask app runs behind Nginx with HTTPS, let’s ensure:
✅ SSL certificates auto-renew
✅ Your Flask app is protected with authentication (optional)
1️⃣ Auto-Renew SSL Certificates
Let’s Encrypt SSL certificates expire every 90 days, but we can automate renewal.
🔹 Step 1: Test Manual Renewal
Run this command to test renewing your SSL certificate:
sudo certbot renew --dry-run
✅ If no errors appear, the renewal process is working.
🔹 Step 2: Set Up Automatic Renewal
Certbot already installs a systemd timer for renewal. But to be sure:
- Edit the crontab to check renewal daily:
sudo crontab -e - Add this line at the bottom to renew certificates automatically and reload Nginx:
0 2 * * * certbot renew --quiet && systemctl reload nginx🔹 This runs every day at 2 AM (0 2 * * *). - Save and exit (
CTRL + X, thenY, thenEnter).
✅ Now, SSL auto-renews when needed!
2️⃣ Add Authentication to Your Flask App
If you only want authorized users to access the Flask app, you can require a login using Basic Authentication in Nginx.
🔹 Step 1: Install apache2-utils
This provides the htpasswd command to create a username/password file:
sudo apt install apache2-utils -y
🔹 Step 2: Create a User for Authentication
Replace yourusername with your preferred login name:
sudo htpasswd -c /etc/nginx/.htpasswd yourusername
🔹 Enter a secure password when prompted.
✅ This stores the credentials securely in /etc/nginx/.htpasswd.
🔹 Step 3: Update the Nginx Config
Edit your Flask app’s Nginx configuration:
sudo nano /etc/nginx/sites-available/flask_app
Find this section:
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
🔹 Modify it to require authentication:
location / {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
✅ This forces users to enter a username and password before accessing the Flask app.
🔹 Step 4: Restart Nginx
Apply the changes:
sudo systemctl restart nginx
3️⃣ Testing Your Secure Setup
🛠 Test Auto-Renewal
Run:
sudo certbot renew --dry-run
If no errors appear, it’s set to auto-renew!
🔑 Test Authentication
- Open your browser and go to:
http://yourdomain.com/orhttp://<Your-Raspberry-Pi-IP>/ - You should see a username/password prompt.
✅ Enter your htpasswd credentials to access your Flask app.
🎯 Your Flask App is Now:
✔ Running behind Nginx
✔ Secured with SSL
✔ Auto-renewing certificates
✔ Password-protected (if enabled)
Would you like me to help with OAuth (Google Login) or adding a custom login page in Flask? 🚀
Set Up Login Page in Flask
🔹 Add OAuth (Google Login) to Your Flask App
Instead of using basic authentication, let’s allow users to log in with Google! This method is more secure, user-friendly, and scalable.
1️⃣ Set Up Google OAuth Credentials
Google provides OAuth authentication via Google Cloud Console.
🔹 Step 1: Create a Google OAuth App
- Go to Google Cloud Console and sign in.
- Click “Select a Project” → “New Project”.
- Give it a name (e.g.,
FlaskOAuthApp) and click “Create”. - In the left sidebar, go to APIs & Services > Credentials.
- Click “Create Credentials” → “OAuth 2.0 Client ID”.
- Select “Web Application” as the application type.
- Under “Authorized Redirect URIs”, add:
http://yourdomain.com/login/callbackor, if testing locally:http://localhost:5000/login/callback - Click “Create”, then copy your:
- Client ID
- Client Secret
2️⃣ Install Required Python Packages
Your Flask app needs the Flask-OAuthlib package:
pip install flask flask-oauthlib
3️⃣ Modify Your Flask App to Use Google Login
Update your app.py to include Google OAuth authentication:
from flask import Flask, redirect, url_for, session
from flask_oauthlib.client import OAuth
import os
app = Flask(__name__)
app.secret_key = os.urandom(24) # Change this to a fixed secret key in production
oauth = OAuth(app)
google = oauth.remote_app(
'google',
consumer_key='YOUR_GOOGLE_CLIENT_ID',
consumer_secret='YOUR_GOOGLE_CLIENT_SECRET',
request_token_params={
'scope': 'email profile'
},
base_url='https://www.googleapis.com/oauth2/v1/',
request_token_url=None,
access_token_method='POST',
access_token_url='https://accounts.google.com/o/oauth2/token',
authorize_url='https://accounts.google.com/o/oauth2/auth'
)
@app.route('/')
def home():
return 'Welcome! <a href="/login">Login with Google</a>'
@app.route('/login')
def login():
return google.authorize(callback=url_for('authorized', _external=True))
@app.route('/login/callback')
def authorized():
response = google.authorized_response()
if response is None or response.get('access_token') is None:
return 'Access Denied'
session['google_token'] = (response['access_token'], '')
user_info = google.get('userinfo') # Get user details
return f"Hello, {user_info.data['name']}! You are logged in."
@google.tokengetter
def get_google_oauth_token():
return session.get('google_token')
@app.route('/logout')
def logout():
session.pop('google_token', None)
return redirect(url_for('home'))
if __name__ == '__main__':
app.run(debug=True)
🔹 Replace:
YOUR_GOOGLE_CLIENT_IDYOUR_GOOGLE_CLIENT_SECRET
with your credentials.
4️⃣ Restart Flask & Test Login
- Run the Flask app:
python3 app.py - Open your browser and visit:
http://localhost:5000/ - Click “Login with Google”.
- Sign in with Google.
- You should see a welcome message with your name!
5️⃣ Secure OAuth in Production
- Use a fixed secret key in
app.secret_key. - Deploy behind Nginx & use HTTPS.
- Restrict Google OAuth to trusted domains (in Google Cloud settings).
🚀 Google Login is Now Enabled!
Would you like to: ✅ Store user data in a database
✅ Restrict access to logged-in users
✅ Add logout redirection?
Restrict Access to Logged-in Users
🔹 Store User Data & Restrict Access in Your Flask App
Now that Google OAuth is working, let’s:
✅ Store user data in a database
✅ Restrict access to logged-in users
✅ Add logout redirection
1️⃣ Install & Set Up SQLite (or Use MySQL/PostgreSQL)
We’ll use SQLite for simplicity, but this can be replaced with MySQL/PostgreSQL.
🔹 Install SQLite & Flask-SQLAlchemy
Run:
pip install flask-sqlalchemy
🔹 Modify app.py to Use a Database
Update your Flask app to store user details:
from flask import Flask, redirect, url_for, session, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_oauthlib.client import OAuth
import os
app = Flask(__name__)
app.secret_key = os.urandom(24) # Change this for production
# Configure SQLite Database
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///users.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
# Define User Model
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
google_id = db.Column(db.String(100), unique=True, nullable=False)
name = db.Column(db.String(100), nullable=False)
email = db.Column(db.String(100), unique=True, nullable=False)
# OAuth Setup
oauth = OAuth(app)
google = oauth.remote_app(
'google',
consumer_key='YOUR_GOOGLE_CLIENT_ID',
consumer_secret='YOUR_GOOGLE_CLIENT_SECRET',
request_token_params={'scope': 'email profile'},
base_url='https://www.googleapis.com/oauth2/v1/',
request_token_url=None,
access_token_method='POST',
access_token_url='https://accounts.google.com/o/oauth2/token',
authorize_url='https://accounts.google.com/o/oauth2/auth'
)
@app.route('/')
def home():
if 'google_token' in session:
user = User.query.filter_by(google_id=session['google_id']).first()
return f"Hello, {user.name}! <a href='/logout'>Logout</a>"
return '<a href="/login">Login with Google</a>'
@app.route('/login')
def login():
return google.authorize(callback=url_for('authorized', _external=True))
@app.route('/login/callback')
def authorized():
response = google.authorized_response()
if response is None or response.get('access_token') is None:
return 'Access Denied'
session['google_token'] = (response['access_token'], '')
user_info = google.get('userinfo').data
# Store User Info in Database
user = User.query.filter_by(google_id=user_info['id']).first()
if not user:
user = User(google_id=user_info['id'], name=user_info['name'], email=user_info['email'])
db.session.add(user)
db.session.commit()
# Store user details in session
session['google_id'] = user_info['id']
session['name'] = user_info['name']
return redirect(url_for('home'))
@google.tokengetter
def get_google_oauth_token():
return session.get('google_token')
@app.route('/logout')
def logout():
session.pop('google_token', None)
session.pop('google_id', None)
session.pop('name', None)
return redirect(url_for('home'))
# Initialize Database
with app.app_context():
db.create_all()
if __name__ == '__main__':
app.run(debug=True)
2️⃣ Run Your Flask App & Test
- Initialize the database (Run this once):
python3 app.pyThis createsusers.dbto store logged-in users. - Start Flask again:
python3 app.py - Open your browser and visit:
http://localhost:5000/ - Login with Google.
- Your name should appear, and your details will be stored in the database.
- Logout and try logging in again—your data is now persistent!
3️⃣ Restrict Access to Logged-In Users
If you want to protect certain routes (e.g., a dashboard), modify your Flask app:
from functools import wraps
def login_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
if 'google_id' not in session:
return redirect(url_for('login'))
return f(*args, **kwargs)
return decorated_function
@app.route('/dashboard')
@login_required
def dashboard():
return f"Welcome to your dashboard, {session['name']}!"
Now, if users visit /dashboard, they must log in first.
🚀 Your Flask App Now Has:
✔ Google OAuth login
✔ User database storage
✔ Restricted access for logged-in users
✔ Logout functionality
Would you like help deploying this on your Raspberry Pi server with Gunicorn & Nginx?
Deployment with Gunicorn & Nginx
🚀 Deploy Your Flask App on a Raspberry Pi with Gunicorn & Nginx
Now that your Flask app is working, let’s deploy it properly on your Raspberry Pi. This setup ensures that your app:
✅ Runs in the background without needing to manually start it
✅ Is accessible over the network
✅ Uses Nginx as a reverse proxy for better performance
1️⃣ Install Required Packages
Run the following on your Raspberry Pi:
sudo apt update && sudo apt upgrade -y
sudo apt install python3-pip python3-venv nginx -y
2️⃣ Set Up a Virtual Environment
Navigate to your Flask project directory and create a virtual environment:
cd /home/pi/my_flask_app
python3 -m venv venv
source venv/bin/activate
🔹 Install Dependencies
Reinstall Flask and other required packages inside the virtual environment:
pip install flask flask-oauthlib flask-sqlalchemy gunicorn
3️⃣ Test Gunicorn
Gunicorn is a production-ready WSGI server that will serve your Flask app.
Run:
gunicorn -w 3 -b 0.0.0.0:8000 app:app
This:
- Runs 3 worker processes (
-w 3) for handling requests - Binds to port 8000 (
-b 0.0.0.0:8000)
Test by opening:
http://<YOUR_RPI_IP>:8000
If it’s working, press Ctrl+C to stop it.
4️⃣ Create a Systemd Service
To automatically start the app at boot, create a systemd service:
sudo nano /etc/systemd/system/flask_app.service
Paste this inside:
[Unit]
Description=Gunicorn instance to serve Flask app
After=network.target
[Service]
User=pi
Group=pi
WorkingDirectory=/home/pi/my_flask_app
Environment="PATH=/home/pi/my_flask_app/venv/bin"
ExecStart=/home/pi/my_flask_app/venv/bin/gunicorn -w 3 -b 0.0.0.0:8000 app:app
[Install]
WantedBy=multi-user.target
Save & exit (Ctrl+X, Y, Enter).
🔹 Enable & Start the Service
sudo systemctl daemon-reload
sudo systemctl enable flask_app
sudo systemctl start flask_app
Check if it’s running:
sudo systemctl status flask_app
If you see “active (running)”, the app is working!
5️⃣ Set Up Nginx as a Reverse Proxy
Now, we’ll configure Nginx to serve the Flask app.
🔹 Create an Nginx Config File
sudo nano /etc/nginx/sites-available/flask_app
Paste this inside:
server {
listen 80;
server_name _;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
Save & exit (Ctrl+X, Y, Enter).
🔹 Enable the Nginx Config
sudo ln -s /etc/nginx/sites-available/flask_app /etc/nginx/sites-enabled
sudo systemctl restart nginx
6️⃣ Test Your Deployment
Now, open your browser and visit:
http://<YOUR_RPI_IP>
If everything is set up correctly, you should see your Flask app!
7️⃣ Optional: Use a Custom Domain
If you have a domain, update server_name in the Nginx config:
server_name yourdomain.com;
Then restart Nginx:
sudo systemctl restart nginx
🚀 Your Flask App Is Now Deployed!
✔ Runs automatically on boot
✔ Uses Gunicorn for performance
✔ Uses Nginx as a reverse proxy
Would you like to secure it with HTTPS using Let’s Encrypt? 🔐
🔐 Secure Your Flask App with HTTPS (Let’s Encrypt & Certbot)
Now that your Flask app is running with Nginx, let’s secure it with free SSL certificates from Let’s Encrypt using Certbot.
1️⃣ Install Certbot
Run the following on your Raspberry Pi:
sudo apt update
sudo apt install certbot python3-certbot-nginx -y
2️⃣ Obtain an SSL Certificate
Replace yourdomain.com with your actual domain and run:
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
🔹 What Happens Here?
- Certbot will automatically configure Nginx for HTTPS.
- It will redirect HTTP traffic to HTTPS.
- It will ask for your email for renewal reminders.
If the setup is successful, you’ll see a message like:
Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/yourdomain.com/fullchain.pem
3️⃣ Test Your HTTPS Setup
Open a browser and visit:
https://yourdomain.com
Your site should now be secure with a padlock icon! 🔒
4️⃣ Auto-Renew SSL Certificates
Let’s Encrypt certificates expire every 90 days, but Certbot can automatically renew them.
Run:
sudo certbot renew --dry-run
If everything looks good, Certbot will renew your certificates automatically in the background.
🚀 Your Flask App Is Now Fully Secured with HTTPS!
✔ Runs on boot
✔ Uses Gunicorn & Nginx for performance
✔ Automatically renews SSL certificates
Would you like to set up a custom firewall (UFW) to further secure your Raspberry Pi? 🔥
🔥 Secure Your Raspberry Pi with a Firewall (UFW)
Now that your Flask app is running securely with HTTPS, let’s set up a firewall using UFW (Uncomplicated Firewall) to protect your Raspberry Pi from unwanted access.
1️⃣ Install UFW
First, make sure UFW is installed:
sudo apt update
sudo apt install ufw -y
2️⃣ Allow Essential Services
We’ll allow only the necessary ports for your Flask app and system management:
- SSH (22) – If you connect remotely via SSH
- HTTP (80) – Needed for the initial Certbot challenge
- HTTPS (443) – Secured access to your Flask app
Run these commands:
sudo ufw allow OpenSSH # Allow SSH access
sudo ufw allow 80/tcp # Allow HTTP (needed for Let's Encrypt renewal)
sudo ufw allow 443/tcp # Allow HTTPS for secure access
3️⃣ Enable the Firewall
Once you’ve added the rules, enable UFW:
sudo ufw enable
⚠ Important: If you’re connected via SSH, make sure you’ve allowed SSH (sudo ufw allow OpenSSH) before enabling the firewall. Otherwise, you might get locked out!
To check the firewall status:
sudo ufw status
You should see something like:
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
4️⃣ (Optional) Allow Local Network Access
If you want to allow access from devices on your home network (but not the internet), find your local subnet (e.g., 192.168.1.0/24) and allow it:
sudo ufw allow from 192.168.1.0/24
🚀 Your Raspberry Pi is Now Secure!
✔ Firewall is enabled
✔ Only necessary ports are open
✔ Protects against unauthorized access
Would you like to set up logging & alerts for potential threats? 📊🔔
📊 Set Up Logging & Alerts for Security on Raspberry Pi
Now that your firewall is active, let’s enable logging and set up email alerts for potential threats. This will help you track any unauthorized access attempts.
1️⃣ Enable UFW Logging
By default, UFW logs blocked connections, but we’ll make sure logging is enabled.
Run:
sudo ufw logging on
To check logs, use:
sudo journalctl -u ufw --no-pager | tail -20
Or, check the log file directly:
sudo cat /var/log/ufw.log | tail -20
2️⃣ Install & Configure Fail2Ban
Fail2Ban blocks repeated failed login attempts (e.g., SSH brute force attacks).
🔹 Install Fail2Ban
sudo apt install fail2ban -y
🔹 Configure Fail2Ban
Create a custom config file:
sudo nano /etc/fail2ban/jail.local
Paste this inside:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
destemail = your-email@example.com
sender = fail2ban@yourdomain.com
mta = sendmail
action = %(action_mwl)s
[sshd]
enabled = true
bantime = 1h→ Bans IPs for 1 hour after multiple failed attemptsmaxretry = 5→ Blocks an IP after 5 failed attemptsdestemail→ Change to your email for notifications
Save & exit (Ctrl+X, Y, Enter).
🔹 Restart Fail2Ban
sudo systemctl restart fail2ban
sudo systemctl enable fail2ban
🔹 Check If It’s Running
sudo fail2ban-client status sshd
If working, you’ll see:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 10
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 0
|- Total banned: 3
3️⃣ Get Email Alerts for SSH Login Attempts
If you want email alerts when someone logs into your Raspberry Pi via SSH:
🔹 Install Mail Client
sudo apt install mailutils -y
🔹 Edit SSH Login Notification Script
sudo nano /etc/profile.d/ssh-notify.sh
Paste this inside:
#!/bin/bash
echo "SSH Login Alert: User $USER from $(who | awk '{print $5}')" | mail -s "SSH Login Alert" your-email@example.com
Replace your-email@example.com with your actual email.
🔹 Make It Executable
sudo chmod +x /etc/profile.d/ssh-notify.sh
Now, whenever someone logs into your Raspberry Pi via SSH, you’ll get an email notification. 📩
🚀 Your Raspberry Pi Is Now Extra Secure!
✔ UFW logging is enabled
✔ Fail2Ban prevents brute-force attacks
✔ SSH login alerts notify you of logins
Would you like to monitor system performance & logs remotely using a tool like Grafana? 📊🔍
📊 Monitor Raspberry Pi Performance & Logs Remotely with Grafana
Now that we’ve secured your Raspberry Pi, let’s set up Grafana with Prometheus to monitor:
✅ CPU & memory usage
✅ Disk & network activity
✅ Uptime & system logs
✅ Firewall & security events
1️⃣ Install Prometheus for System Metrics
Prometheus is a powerful monitoring system that collects system performance data.
🔹 Install Prometheus & Node Exporter
Run:
sudo apt update
sudo apt install prometheus prometheus-node-exporter -y
🔹 Enable and Start Services
sudo systemctl enable prometheus prometheus-node-exporter
sudo systemctl start prometheus prometheus-node-exporter
To check if they are running:
sudo systemctl status prometheus
sudo systemctl status prometheus-node-exporter
Your Raspberry Pi is now collecting system metrics! 🚀
2️⃣ Install Grafana for Data Visualization
Grafana provides a beautiful web-based dashboard to visualize Prometheus data.
🔹 Install Grafana
sudo apt install -y grafana
🔹 Enable and Start Grafana
sudo systemctl enable grafana-server
sudo systemctl start grafana-server
To check if it’s running:
sudo systemctl status grafana-server
🔹 Access Grafana Dashboard
Open a browser and go to:
http://your_raspberry_pi_ip:3000
- Default username:
admin - Default password:
admin(You’ll be asked to change it after first login)
3️⃣ Connect Prometheus to Grafana
- In Grafana, go to Configuration → Data Sources
- Click “Add data source”
- Select Prometheus
- Set the URL to:
http://localhost:9090 - Click Save & Test (It should confirm the connection)
4️⃣ Import a Raspberry Pi Dashboard
- Go to Dashboards → Import
- Enter 1860 (Official Raspberry Pi dashboard ID)
- Click Load, then Import
🎉 Now you have a live monitoring dashboard for your Raspberry Pi!
5️⃣ (Optional) Monitor Security Logs in Grafana
If you want to monitor firewall (UFW) & Fail2Ban logs in Grafana:
- Install Loki (Grafana’s log system)
sudo apt install -y loki - Configure UFW logs in Loki
- Add Loki as a data source in Grafana
- Visualize firewall blocks & SSH login attempts
🚀 Your Raspberry Pi Now Has:
✔ Live performance monitoring
✔ Security event tracking
✔ Beautiful, remote dashboards
Would you like to set up alerts in Grafana for CPU spikes, low disk space, or security threats? 🔔
🔔 Set Up Alerts in Grafana for CPU, Disk, and Security Events
Now that your Raspberry Pi is being monitored in Grafana, let’s set up real-time alerts for:
✅ High CPU usage 🚀
✅ Low disk space 💾
✅ Network overload 📶
✅ Security threats (SSH attempts, firewall blocks) 🔐
1️⃣ Enable Grafana Alerting
By default, Grafana alerting is disabled on Raspberry Pi. Enable it with:
sudo nano /etc/grafana/grafana.ini
Find the section [alerting] and set:
enabled = true
Save & exit (Ctrl+X, Y, Enter), then restart Grafana:
sudo systemctl restart grafana-server
2️⃣ Configure Notification Channels
Grafana supports Email, Telegram, Slack, Discord, Webhooks, etc.
🔹 Set Up Email Alerts
- In Grafana, go to Alerting → Notification Channels
- Click “Add Channel”
- Set:
- Name: System Alerts
- Type: Email
- Addresses: your-email@example.com
- Click Save
If you prefer Telegram, Slack, or Discord, let me know! 🤖
3️⃣ Create an Alert for High CPU Usage
- Open your Raspberry Pi System Dashboard
- Find the CPU Usage graph
- Click the panel title → Edit
- Go to the Alert tab
- Click “Create Alert”, then set:
- Condition: If CPU > 85% for 5 minutes
- Evaluate every: 1m
- Notification Channel: System Alerts
- Click Save
4️⃣ Add Alerts for Disk Space & Security Logs
🔹 Low Disk Space Alert
- Open the Disk Usage panel
- Set an alert: If disk space < 2GB for 5 minutes
- Save
🔹 Security Alerts (SSH & Firewall Logs)
If you set up Loki for logs, you can create alerts for:
✅ Multiple failed SSH logins
✅ IP bans by Fail2Ban
✅ Blocked IPs by UFW
5️⃣ Test Your Alerts!
- Go to Alerting → Alert Rules
- Click “Test Rule” on your alerts
- If set up correctly, you should receive an email alert 📩
🚀 Your Raspberry Pi Now Has:
✔ Live monitoring in Grafana
✔ Real-time alerts for system health & security
✔ Notifications via Email (or Telegram/Slack)
Would you like to automate actions (e.g., restart a service if CPU is too high)? 🔄
🔄 Automate Actions Based on Alerts on Your Raspberry Pi
Now that Grafana can send alerts, let’s automate responses!
✅ Restart a service if CPU is too high 🚀
✅ Block an IP after repeated SSH login failures 🔐
✅ Send a custom notification (e.g., text message)
1️⃣ Auto-Restart a Service if CPU is Too High
We’ll create a script that restarts a service when Grafana detects high CPU usage.
🔹 Step 1: Create the Auto-Restart Script
Run:
sudo nano /usr/local/bin/restart_service.sh
Paste this inside:
#!/bin/bash
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
THRESHOLD=85.0
if (( $(echo "$CPU_USAGE > $THRESHOLD" | bc -l) )); then
echo "$(date) - High CPU detected: $CPU_USAGE%" >> /var/log/cpu_alert.log
sudo systemctl restart your-service-name
echo "Restarted your-service-name" >> /var/log/cpu_alert.log
fi
Replace your-service-name with the actual service (e.g., nginx, grafana-server).
Save & exit (Ctrl+X, Y, Enter).
🔹 Step 2: Make the Script Executable
sudo chmod +x /usr/local/bin/restart_service.sh
🔹 Step 3: Set Up a Cron Job
Run:
crontab -e
Add this line at the bottom:
*/5 * * * * /usr/local/bin/restart_service.sh
✅ This checks CPU usage every 5 minutes and restarts the service if needed.
2️⃣ Auto-Ban an IP After Multiple SSH Failures
Let’s automate IP banning when Grafana detects multiple failed SSH attempts.
🔹 Step 1: Create a Fail2Ban Rule for Auto-Banning
Run:
sudo nano /etc/fail2ban/jail.local
Add:
[sshd]
enabled = true
filter = sshd
logpath = /var/log/auth.log
maxretry = 5
bantime = 1h
Save & restart Fail2Ban:
sudo systemctl restart fail2ban
🔹 Step 2: Check Banned IPs
sudo fail2ban-client status sshd
🚀 Now, after 5 failed login attempts, the attacker’s IP will be automatically blocked.
3️⃣ Send a Custom Notification (Telegram or SMS)
If you want to receive a Telegram or SMS alert, we can do that too!
Would you like Telegram notifications, Twilio SMS, or both? 📲
📲 Automate Telegram & SMS Notifications for Alerts
Now, let’s set up both Telegram and SMS (via Twilio) notifications when an alert is triggered.
1️⃣ Send a Telegram Message When an Alert is Triggered
🔹 Step 1: Create a Telegram Bot
- Open Telegram and search for BotFather
- Send the command:
/newbot - Follow the instructions and get your bot token (It looks like
123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11). - Get your chat ID:
- Go to
https://api.telegram.org/bot<your-bot-token>/getUpdates - Send a message to your bot and refresh the link above.
- Find your chat ID (a number like
-123456789).
- Go to
🔹 Step 2: Create a Telegram Alert Script
Run:
sudo nano /usr/local/bin/telegram_alert.sh
Paste this:
#!/bin/bash
BOT_TOKEN="your-telegram-bot-token"
CHAT_ID="your-chat-id"
MESSAGE="🚨 Alert! High CPU usage detected on your Raspberry Pi!"
curl -s -X POST "https://api.telegram.org/bot$BOT_TOKEN/sendMessage" -d chat_id=$CHAT_ID -d text="$MESSAGE"
Replace your-telegram-bot-token and your-chat-id with your actual values.
Save & exit (Ctrl+X, Y, Enter).
Make it executable:
sudo chmod +x /usr/local/bin/telegram_alert.sh
2️⃣ Send an SMS Alert Using Twilio
🔹 Step 1: Create a Twilio Account
- Sign up at Twilio
- Get your Twilio Account SID, Auth Token, and Twilio Phone Number
🔹 Step 2: Install Twilio Python Library
Run:
pip install twilio
🔹 Step 3: Create an SMS Alert Script
Run:
sudo nano /usr/local/bin/sms_alert.py
Paste this:
from twilio.rest import Client
# Twilio credentials
ACCOUNT_SID = "your-account-sid"
AUTH_TOKEN = "your-auth-token"
TWILIO_NUMBER = "+your-twilio-number"
TO_NUMBER = "+your-phone-number"
# Alert message
message_body = "🚨 Alert! High CPU usage detected on your Raspberry Pi!"
# Send SMS
client = Client(ACCOUNT_SID, AUTH_TOKEN)
message = client.messages.create(
body=message_body,
from_=TWILIO_NUMBER,
to=TO_NUMBER
)
print(f"SMS sent: {message.sid}")
Replace your-account-sid, your-auth-token, your-twilio-number, and your-phone-number.
Save & exit (Ctrl+X, Y, Enter).
Make it executable:
sudo chmod +x /usr/local/bin/sms_alert.py
3️⃣ Link Alerts to Grafana
Now, configure Grafana to trigger these scripts when alerts occur.
🔹 Step 1: Modify the Auto-Restart Script
Edit:
sudo nano /usr/local/bin/restart_service.sh
Update it:
#!/bin/bash
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
THRESHOLD=85.0
if (( $(echo "$CPU_USAGE > $THRESHOLD" | bc -l) )); then
echo "$(date) - High CPU detected: $CPU_USAGE%" >> /var/log/cpu_alert.log
sudo systemctl restart your-service-name
echo "Restarted your-service-name" >> /var/log/cpu_alert.log
# Send Telegram Alert
/usr/local/bin/telegram_alert.sh
# Send SMS Alert
python3 /usr/local/bin/sms_alert.py
fi
Save & exit (Ctrl+X, Y, Enter).
4️⃣ Test Your Alerts
- Manually run the script:
/usr/local/bin/restart_service.sh - You should receive both a Telegram message and an SMS alert! 📲
🚀 Your Raspberry Pi Now Has:
✔ Real-time alerts in Telegram & SMS
✔ Automated service restarts
✔ IP banning for security threats
Would you like to log all alerts into a file for tracking? 📜
📜 Log All Alerts for Tracking
Now, let’s make sure every alert (CPU spikes, service restarts, IP bans, etc.) is logged into a file so you can review past alerts.
1️⃣ Create a Log File for Alerts
We’ll use /var/log/alert_log.log to store alerts.
Run:
sudo touch /var/log/alert_log.log
sudo chmod 666 /var/log/alert_log.log
✅ This creates the log file and allows any script to write to it.
2️⃣ Modify the Restart Script to Log Alerts
Run:
sudo nano /usr/local/bin/restart_service.sh
Update it:
#!/bin/bash
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
THRESHOLD=85.0
LOG_FILE="/var/log/alert_log.log"
if (( $(echo "$CPU_USAGE > $THRESHOLD" | bc -l) )); then
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP - 🚨 High CPU detected: $CPU_USAGE%" | tee -a $LOG_FILE
sudo systemctl restart your-service-name
echo "$TIMESTAMP - 🔄 Restarted your-service-name" | tee -a $LOG_FILE
# Send Telegram Alert
/usr/local/bin/telegram_alert.sh
echo "$TIMESTAMP - 📩 Telegram alert sent" | tee -a $LOG_FILE
# Send SMS Alert
python3 /usr/local/bin/sms_alert.py
echo "$TIMESTAMP - 📲 SMS alert sent" | tee -a $LOG_FILE
fi
✅ This logs every action taken (CPU spike, service restart, alerts sent).
Save & exit (Ctrl+X, Y, Enter).
3️⃣ Modify IP Ban Script to Log Banned IPs
If you want to track banned IPs, update Fail2Ban logging.
Run:
sudo nano /etc/fail2ban/action.d/log_ban.conf
Paste this:
[Definition]
actionstart =
actionstop =
actioncheck =
actionban = echo "$(date "+%Y-%m-%d %H:%M:%S") - 🚫 IP Banned: <ip>" >> /var/log/alert_log.log
actionunban = echo "$(date "+%Y-%m-%d %H:%M:%S") - ✅ IP Unbanned: <ip>" >> /var/log/alert_log.log
Save & restart Fail2Ban:
sudo systemctl restart fail2ban
✅ Now, banned/unbanned IPs will be logged.
4️⃣ View & Monitor Logs
To see logs in real time, run:
tail -f /var/log/alert_log.log
This will show updates as they happen.
🚀 Now every alert is logged! Would you like logs to be emailed to you daily? 📧
📧 Daily Email Reports for Alerts
Now, let’s set up automatic daily email reports so you get a summary of all alerts, service restarts, and banned IPs every day.
1️⃣ Install Mail Utilities on Raspberry Pi
Run:
sudo apt update && sudo apt install postfix mailutils -y
During setup, select “Internet Site” and set your system mail name (usually your Pi’s hostname).
2️⃣ Create a Script to Send the Email
Run:
sudo nano /usr/local/bin/send_alert_email.sh
Paste this:
#!/bin/bash
LOG_FILE="/var/log/alert_log.log"
EMAIL="your-email@example.com"
SUBJECT="🚨 Daily Alert Report from Raspberry Pi"
# Get log summary
LOG_SUMMARY=$(tail -n 50 $LOG_FILE)
# Send email
echo -e "Hello,\n\nHere is your daily alert report:\n\n$LOG_SUMMARY\n\n- Raspberry Pi Alert System" | mail -s "$SUBJECT" $EMAIL
Replace your-email@example.com with your actual email.
Save & exit (Ctrl+X, Y, Enter).
Make it executable:
sudo chmod +x /usr/local/bin/send_alert_email.sh
3️⃣ Automate Daily Email Using Cron
Run:
crontab -e
At the bottom, add:
0 8 * * * /usr/local/bin/send_alert_email.sh
✅ This will send the email every day at 8 AM. Change the time as needed.
4️⃣ Test the Email Setup
Run manually:
/usr/local/bin/send_alert_email.sh
Check your email! 📩
🚀 Now, you’ll receive a daily report of all alerts, restarts, and security events!
Would you like the report to include system stats like CPU, RAM, and disk usage? 📊
📊 Add System Stats to Daily Email Reports
Now, we’ll enhance your daily email to include CPU, RAM, and disk usage, so you get a complete system health report.
1️⃣ Update the Email Script to Include System Stats
Run:
sudo nano /usr/local/bin/send_alert_email.sh
Replace the previous script with this:
#!/bin/bash
LOG_FILE="/var/log/alert_log.log"
EMAIL="your-email@example.com"
SUBJECT="🚨 Daily Alert & System Report from Raspberry Pi"
# Get system stats
HOSTNAME=$(hostname)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
UPTIME=$(uptime -p)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
MEMORY_USAGE=$(free -m | awk 'NR==2{printf "%.2f%% (Used: %sMB / Total: %sMB)", $3*100/$2, $3, $2}')
DISK_USAGE=$(df -h / | awk 'NR==2{print $5 " (Used: " $3 " / Total: " $2 ")"}')
LOG_SUMMARY=$(tail -n 50 $LOG_FILE)
# Email body
EMAIL_BODY="Hello,\n\nHere is your daily alert & system report:\n
📅 Date: $TIMESTAMP
🖥️ Hostname: $HOSTNAME
⏳ Uptime: $UPTIME
🔹 **System Stats:**
🔥 CPU Usage: $CPU_USAGE%
💾 Memory Usage: $MEMORY_USAGE
📀 Disk Usage: $DISK_USAGE
🔹 **Recent Alerts & Events:**
$LOG_SUMMARY
- Raspberry Pi Alert System"
# Send email
echo -e "$EMAIL_BODY" | mail -s "$SUBJECT" $EMAIL
✅ This adds CPU, RAM, and disk usage to the email.
Save & exit (Ctrl+X, Y, Enter).
2️⃣ Test the New Report
Run:
/usr/local/bin/send_alert_email.sh
Check your email! 📩 It should now include system stats along with alerts.
3️⃣ Ensure the Daily Email is Scheduled
If you haven’t already set up a cron job, run:
crontab -e
Add this line at the bottom:
0 8 * * * /usr/local/bin/send_alert_email.sh
✅ This automates the report every day at 8 AM.
🚀 Now, you’ll get a daily system health and alert report!
Would you like me to include network status (IP, speed test, etc.) in the report too? 🌐📡
🌐 Add Network Status to Daily Email Reports
Now, we’ll enhance your daily email to include:
✅ Current IP Address (Public & Local)
✅ Wi-Fi or Ethernet Connection Status
✅ Internet Speed Test (Download & Upload speeds)
1️⃣ Install Speedtest Tool
Run:
sudo apt update && sudo apt install speedtest-cli -y
✅ This installs a command-line tool to check your internet speed.
2️⃣ Update the Email Script to Include Network Info
Run:
sudo nano /usr/local/bin/send_alert_email.sh
Replace the script with this:
#!/bin/bash
LOG_FILE="/var/log/alert_log.log"
EMAIL="your-email@example.com"
SUBJECT="🚨 Daily Alert & System Report from Raspberry Pi"
# Get system stats
HOSTNAME=$(hostname)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
UPTIME=$(uptime -p)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
MEMORY_USAGE=$(free -m | awk 'NR==2{printf "%.2f%% (Used: %sMB / Total: %sMB)", $3*100/$2, $3, $2}')
DISK_USAGE=$(df -h / | awk 'NR==2{print $5 " (Used: " $3 " / Total: " $2 ")"}')
# Get network info
LOCAL_IP=$(hostname -I | awk '{print $1}')
PUBLIC_IP=$(curl -s https://api64.ipify.org)
CONNECTION_TYPE=$(ip route get 8.8.8.8 | grep -o "dev .*" | awk '{print $2}')
SPEEDTEST_RESULT=$(speedtest-cli --simple)
# Get latest log summary
LOG_SUMMARY=$(tail -n 50 $LOG_FILE)
# Email body
EMAIL_BODY="Hello,\n\nHere is your daily alert & system report:\n
📅 Date: $TIMESTAMP
🖥️ Hostname: $HOSTNAME
⏳ Uptime: $UPTIME
🔹 **System Stats:**
🔥 CPU Usage: $CPU_USAGE%
💾 Memory Usage: $MEMORY_USAGE
📀 Disk Usage: $DISK_USAGE
🔹 **Network Status:**
🌐 Local IP: $LOCAL_IP
🌍 Public IP: $PUBLIC_IP
🔗 Connection Type: $CONNECTION_TYPE
📶 **Internet Speed Test:**
$SPEEDTEST_RESULT
🔹 **Recent Alerts & Events:**
$LOG_SUMMARY
- Raspberry Pi Alert System"
# Send email
echo -e "$EMAIL_BODY" | mail -s "$SUBJECT" $EMAIL
Replace your-email@example.com with your actual email.
Save & exit (Ctrl+X, Y, Enter).
3️⃣ Test the New Report
Run:
/usr/local/bin/send_alert_email.sh
✅ Check your email—it should now include network details & speed test results.
4️⃣ Ensure the Daily Email is Scheduled
If you haven’t already set up a cron job, run:
crontab -e
Add this line at the bottom:
0 8 * * * /usr/local/bin/send_alert_email.sh
✅ This automates the report every day at 8 AM.
🚀 Now, you’ll get a full system health + network report daily!
Would you like to include disk space alerts if storage gets low? 📀🔴
📀 Add Disk Space Alerts to Daily Email Reports
Now, we’ll add disk space alerts to your daily report. If your storage drops below 10% free space, the email will include a ⚠️ warning.
1️⃣ Update the Email Script to Check Disk Space
Run:
sudo nano /usr/local/bin/send_alert_email.sh
Replace the script with this:
#!/bin/bash
LOG_FILE="/var/log/alert_log.log"
EMAIL="your-email@example.com"
SUBJECT="🚨 Daily Alert & System Report from Raspberry Pi"
# Get system stats
HOSTNAME=$(hostname)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
UPTIME=$(uptime -p)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
MEMORY_USAGE=$(free -m | awk 'NR==2{printf "%.2f%% (Used: %sMB / Total: %sMB)", $3*100/$2, $3, $2}')
DISK_USAGE=$(df -h / | awk 'NR==2{print $5 " (Used: " $3 " / Total: " $2 ")"}')
# Check disk space percentage
DISK_PERCENT=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
DISK_ALERT=""
if [ "$DISK_PERCENT" -gt 90 ]; then
DISK_ALERT="⚠️ Warning: Low Disk Space! Only $((100 - DISK_PERCENT))% free."
fi
# Get network info
LOCAL_IP=$(hostname -I | awk '{print $1}')
PUBLIC_IP=$(curl -s https://api64.ipify.org)
CONNECTION_TYPE=$(ip route get 8.8.8.8 | grep -o "dev .*" | awk '{print $2}')
SPEEDTEST_RESULT=$(speedtest-cli --simple)
# Get latest log summary
LOG_SUMMARY=$(tail -n 50 $LOG_FILE)
# Email body
EMAIL_BODY="Hello,\n\nHere is your daily alert & system report:\n
📅 Date: $TIMESTAMP
🖥️ Hostname: $HOSTNAME
⏳ Uptime: $UPTIME
🔹 **System Stats:**
🔥 CPU Usage: $CPU_USAGE%
💾 Memory Usage: $MEMORY_USAGE
📀 Disk Usage: $DISK_USAGE
$DISK_ALERT
🔹 **Network Status:**
🌐 Local IP: $LOCAL_IP
🌍 Public IP: $PUBLIC_IP
🔗 Connection Type: $CONNECTION_TYPE
📶 **Internet Speed Test:**
$SPEEDTEST_RESULT
🔹 **Recent Alerts & Events:**
$LOG_SUMMARY
- Raspberry Pi Alert System"
# Send email
echo -e "$EMAIL_BODY" | mail -s "$SUBJECT" $EMAIL
Replace your-email@example.com with your actual email.
Save & exit (Ctrl+X, Y, Enter).
2️⃣ Test the New Report
Run:
/usr/local/bin/send_alert_email.sh
✅ Check your email—you should now see a disk space warning if your storage is low.
3️⃣ Ensure the Daily Email is Scheduled
If you haven’t already set up a cron job, run:
crontab -e
Add this line at the bottom:
0 8 * * * /usr/local/bin/send_alert_email.sh
✅ This automates the report every day at 8 AM.
🚀 Now, your daily email includes disk space alerts!
Would you like to add temperature monitoring for your Raspberry Pi’s CPU? 🌡️🔥
🌡️ Add Raspberry Pi CPU Temperature Monitoring
Now, we’ll add CPU temperature monitoring to your daily report. If the temperature goes above 70°C, the email will include a ⚠️ high-temperature warning.
1️⃣ Update the Email Script to Include CPU Temperature
Run:
sudo nano /usr/local/bin/send_alert_email.sh
Replace the script with this:
#!/bin/bash
LOG_FILE="/var/log/alert_log.log"
EMAIL="your-email@example.com"
SUBJECT="🚨 Daily Alert & System Report from Raspberry Pi"
# Get system stats
HOSTNAME=$(hostname)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
UPTIME=$(uptime -p)
CPU_USAGE=$(top -bn1 | grep "Cpu(s)" | awk '{print $2 + $4}')
MEMORY_USAGE=$(free -m | awk 'NR==2{printf "%.2f%% (Used: %sMB / Total: %sMB)", $3*100/$2, $3, $2}')
DISK_USAGE=$(df -h / | awk 'NR==2{print $5 " (Used: " $3 " / Total: " $2 ")"}')
# Check disk space percentage
DISK_PERCENT=$(df -h / | awk 'NR==2 {print $5}' | sed 's/%//')
DISK_ALERT=""
if [ "$DISK_PERCENT" -gt 90 ]; then
DISK_ALERT="⚠️ Warning: Low Disk Space! Only $((100 - DISK_PERCENT))% free."
fi
# Get CPU temperature
CPU_TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)
CPU_TEMP_C=$((CPU_TEMP_RAW / 1000))
CPU_TEMP_ALERT=""
if [ "$CPU_TEMP_C" -gt 70 ]; then
CPU_TEMP_ALERT="🔥 Warning: High CPU Temperature! $CPU_TEMP_C°C"
fi
# Get network info
LOCAL_IP=$(hostname -I | awk '{print $1}')
PUBLIC_IP=$(curl -s https://api64.ipify.org)
CONNECTION_TYPE=$(ip route get 8.8.8.8 | grep -o "dev .*" | awk '{print $2}')
SPEEDTEST_RESULT=$(speedtest-cli --simple)
# Get latest log summary
LOG_SUMMARY=$(tail -n 50 $LOG_FILE)
# Email body
EMAIL_BODY="Hello,\n\nHere is your daily alert & system report:\n
📅 Date: $TIMESTAMP
🖥️ Hostname: $HOSTNAME
⏳ Uptime: $UPTIME
🔹 **System Stats:**
🔥 CPU Usage: $CPU_USAGE%
🌡️ CPU Temperature: $CPU_TEMP_C°C
$CPU_TEMP_ALERT
💾 Memory Usage: $MEMORY_USAGE
📀 Disk Usage: $DISK_USAGE
$DISK_ALERT
🔹 **Network Status:**
🌐 Local IP: $LOCAL_IP
🌍 Public IP: $PUBLIC_IP
🔗 Connection Type: $CONNECTION_TYPE
📶 **Internet Speed Test:**
$SPEEDTEST_RESULT
🔹 **Recent Alerts & Events:**
$LOG_SUMMARY
- Raspberry Pi Alert System"
# Send email
echo -e "$EMAIL_BODY" | mail -s "$SUBJECT" $EMAIL
Replace your-email@example.com with your actual email.
Save & exit (Ctrl+X, Y, Enter).
2️⃣ Test the New Report
Run:
/usr/local/bin/send_alert_email.sh
✅ Check your email—you should now see a CPU temperature reading, and if it’s high, a warning message.
3️⃣ Ensure the Daily Email is Scheduled
If you haven’t already set up a cron job, run:
crontab -e
Add this line at the bottom:
0 8 * * * /usr/local/bin/send_alert_email.sh
✅ This automates the report every day at 8 AM.
🚀 Now, your daily report includes CPU temperature alerts!
Would you like to add automatic shutdown or throttling if the CPU temperature gets dangerously high? 🔥🛑
🛑 Automatically Throttle or Shutdown Raspberry Pi If CPU Overheats
If your Raspberry Pi’s CPU temperature goes above 80°C, it will automatically throttle performance.
If it reaches 85°C, the system will shut down to prevent damage.
1️⃣ Create a Temperature Monitoring Script
Run:
sudo nano /usr/local/bin/temp_monitor.sh
Paste this code:
#!/bin/bash
LOG_FILE="/var/log/temperature_log.log"
MAX_TEMP=85 # Shutdown threshold
THROTTLE_TEMP=80 # Throttle warning threshold
while true; do
# Get CPU temperature
CPU_TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)
CPU_TEMP=$((CPU_TEMP_RAW / 1000))
# Log temperature
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP - CPU Temp: $CPU_TEMP°C" >> $LOG_FILE
# Check for throttling
if [ "$CPU_TEMP" -ge "$THROTTLE_TEMP" ] && [ "$CPU_TEMP" -lt "$MAX_TEMP" ]; then
echo "$TIMESTAMP - ⚠️ Warning: CPU is overheating ($CPU_TEMP°C). Consider reducing load!" | mail -s "⚠️ Raspberry Pi High Temperature Alert" your-email@example.com
fi
# Check for shutdown condition
if [ "$CPU_TEMP" -ge "$MAX_TEMP" ]; then
echo "$TIMESTAMP - 🚨 Critical: CPU temperature reached $CPU_TEMP°C! Shutting down..." | mail -s "🚨 Raspberry Pi Overheat Shutdown" your-email@example.com
sudo shutdown -h now
fi
sleep 60 # Check every minute
done
Replace your-email@example.com with your actual email.
Save & exit (Ctrl+X, Y, Enter).
2️⃣ Make the Script Executable
Run:
sudo chmod +x /usr/local/bin/temp_monitor.sh
3️⃣ Run the Script at Startup
Run:
sudo nano /etc/systemd/system/temp_monitor.service
Paste this:
[Unit]
Description=Raspberry Pi Temperature Monitor
After=network.target
[Service]
ExecStart=/usr/local/bin/temp_monitor.sh
Restart=always
User=root
[Install]
WantedBy=multi-user.target
Save & exit (Ctrl+X, Y, Enter).
4️⃣ Enable and Start the Service
Run:
sudo systemctl daemon-reload
sudo systemctl enable temp_monitor.service
sudo systemctl start temp_monitor.service
✅ The script will now run automatically at startup and check the temperature every minute.
🚀 Now, Your Raspberry Pi is Protected from Overheating!
If the CPU temperature exceeds 80°C, you’ll get a warning email.
If it reaches 85°C, the Pi will shut down automatically.
Would you like to also log all temperature data for later analysis? 📊
📊 Log All Raspberry Pi CPU Temperature Data for Analysis
Now, we’ll store all temperature data in a CSV file so you can analyze trends over time.
1️⃣ Modify the Temperature Monitoring Script
Run:
sudo nano /usr/local/bin/temp_monitor.sh
Replace the script with this updated version:
#!/bin/bash
LOG_FILE="/var/log/temperature_log.log"
CSV_FILE="/var/log/cpu_temp_data.csv"
MAX_TEMP=85 # Shutdown threshold
THROTTLE_TEMP=80 # Throttle warning threshold
# Create CSV file with headers if it doesn't exist
if [ ! -f "$CSV_FILE" ]; then
echo "Timestamp,CPU_Temperature_C" > "$CSV_FILE"
fi
while true; do
# Get CPU temperature
CPU_TEMP_RAW=$(cat /sys/class/thermal/thermal_zone0/temp)
CPU_TEMP=$((CPU_TEMP_RAW / 1000))
# Get current timestamp
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
# Log to CSV
echo "$TIMESTAMP,$CPU_TEMP" >> "$CSV_FILE"
# Log to text file
echo "$TIMESTAMP - CPU Temp: $CPU_TEMP°C" >> "$LOG_FILE"
# Check for overheating
if [ "$CPU_TEMP" -ge "$THROTTLE_TEMP" ] && [ "$CPU_TEMP" -lt "$MAX_TEMP" ]; then
echo "$TIMESTAMP - ⚠️ Warning: CPU is overheating ($CPU_TEMP°C). Consider reducing load!" | mail -s "⚠️ Raspberry Pi High Temperature Alert" your-email@example.com
fi
# Check for shutdown condition
if [ "$CPU_TEMP" -ge "$MAX_TEMP" ]; then
echo "$TIMESTAMP - 🚨 Critical: CPU temperature reached $CPU_TEMP°C! Shutting down..." | mail -s "🚨 Raspberry Pi Overheat Shutdown" your-email@example.com
sudo shutdown -h now
fi
sleep 60 # Check every minute
done
✅ This logs CPU temperature to:
- CSV file (
/var/log/cpu_temp_data.csv) – For analysis in Excel or Python - Log file (
/var/log/temperature_log.log) – For quick checking - Email Alerts if the temperature exceeds 80°C or 85°C
2️⃣ Make the Script Executable
Run:
sudo chmod +x /usr/local/bin/temp_monitor.sh
3️⃣ Restart the Service
Run:
sudo systemctl restart temp_monitor.service
✅ The script will now log temperature every minute and keep a history.
4️⃣ View Your Logged Temperature Data
To see the last 10 entries:
tail -n 10 /var/log/cpu_temp_data.csv
To open the CSV file in Excel, Google Sheets, or Python, copy it to your computer:
scp pi@your-pi-ip:/var/log/cpu_temp_data.csv .
🚀 Your Raspberry Pi Now Logs and Alerts for Overheating!
Would you like a graph to visualize the temperature history? 📈
📈 Graph Raspberry Pi CPU Temperature History
Now, let’s create a Python script to generate a temperature graph from the logged data.
1️⃣ Install Required Libraries
Run:
pip install pandas matplotlib
2️⃣ Create the Python Script
Run:
nano ~/plot_temp.py
Paste this code:
import pandas as pd
import matplotlib.pyplot as plt
# File path of the temperature log
CSV_FILE = "/var/log/cpu_temp_data.csv"
# Read the CSV file
df = pd.read_csv(CSV_FILE, parse_dates=["Timestamp"])
# Plot the data
plt.figure(figsize=(10, 5))
plt.plot(df["Timestamp"], df["CPU_Temperature_C"], label="CPU Temp (°C)", color="red", linewidth=2)
plt.axhline(y=80, color="orange", linestyle="--", label="Throttle Temp (80°C)")
plt.axhline(y=85, color="red", linestyle="--", label="Shutdown Temp (85°C)")
# Formatting
plt.xlabel("Time")
plt.ylabel("CPU Temperature (°C)")
plt.title("Raspberry Pi CPU Temperature Over Time")
plt.legend()
plt.xticks(rotation=45)
plt.grid(True)
# Show the plot
plt.show()
Save & exit (Ctrl+X, Y, Enter).
3️⃣ Run the Graph Script
Run:
python3 ~/plot_temp.py
✅ You’ll see a graph of your CPU temperature over time!
🚀 Your Raspberry Pi Now Logs, Alerts & Graphs Temperature Trends!
Would you like to automate this graph generation and save it as an image for easy access? 🖼️
📊 Automate CPU Temperature Graph Generation & Save as Image
Now, we’ll modify the script to automatically generate and save the graph every hour.
1️⃣ Update the Python Script
Run:
nano ~/plot_temp.py
Replace with:
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime
# File path of the temperature log
CSV_FILE = "/var/log/cpu_temp_data.csv"
OUTPUT_IMAGE = f"/var/log/cpu_temp_graph_{datetime.now().strftime('%Y-%m-%d_%H-%M-%S')}.png"
# Read the CSV file
df = pd.read_csv(CSV_FILE, parse_dates=["Timestamp"])
# Plot the data
plt.figure(figsize=(10, 5))
plt.plot(df["Timestamp"], df["CPU_Temperature_C"], label="CPU Temp (°C)", color="red", linewidth=2)
plt.axhline(y=80, color="orange", linestyle="--", label="Throttle Temp (80°C)")
plt.axhline(y=85, color="red", linestyle="--", label="Shutdown Temp (85°C)")
# Formatting
plt.xlabel("Time")
plt.ylabel("CPU Temperature (°C)")
plt.title("Raspberry Pi CPU Temperature Over Time")
plt.legend()
plt.xticks(rotation=45)
plt.grid(True)
# Save the graph as an image
plt.savefig(OUTPUT_IMAGE, bbox_inches="tight")
plt.close()
print(f"✅ Graph saved as {OUTPUT_IMAGE}")
Save & exit (Ctrl+X, Y, Enter).
2️⃣ Automate Graph Generation with Cron Job
Run:
crontab -e
At the bottom, add this line:
0 * * * * /usr/bin/python3 /home/pi/plot_temp.py
✅ This will generate and save the graph every hour.
3️⃣ View the Latest Graph
To check the latest saved graph:
ls -lt /var/log/cpu_temp_graph_*.png | head -n 1
To open it on your Raspberry Pi:
xdg-open $(ls -t /var/log/cpu_temp_graph_*.png | head -n 1)
🚀 Now, Your Raspberry Pi Automatically Logs, Alerts & Saves Temperature Graphs!
Would you like to send the graph via email or access it from a web interface? 📧🌍
📧 Send the Temperature Graph via Email & Access via Web Interface
Now, we’ll automate email notifications with the latest graph and serve it via a simple web page.
1️⃣ Install Required Packages
Run:
pip install yagmail flask
yagmail→ For sending emailsFlask→ For hosting the web interface
2️⃣ Set Up Email Alerts
Run:
nano ~/send_graph_email.py
Paste this code:
import yagmail
import glob
import os
# Email Configuration
EMAIL_USER = "your-email@gmail.com" # Use your Gmail
EMAIL_PASS = "your-app-password" # Generate an app password in Gmail settings
EMAIL_TO = "recipient-email@example.com"
# Find the latest graph image
latest_graph = max(glob.glob("/var/log/cpu_temp_graph_*.png"), key=os.path.getctime)
# Email setup
yag = yagmail.SMTP(EMAIL_USER, EMAIL_PASS)
# Send email with the latest graph
yag.send(
to=EMAIL_TO,
subject="📊 Raspberry Pi CPU Temperature Report",
contents="Here is the latest CPU temperature graph.",
attachments=latest_graph,
)
print(f"✅ Email sent with attachment: {latest_graph}")
Save & exit (Ctrl+X, Y, Enter).
3️⃣ Automate Email Sending
Run:
crontab -e
Add this line to send an email every morning at 8 AM:
0 8 * * * /usr/bin/python3 /home/pi/send_graph_email.py
✅ Your Pi will now email the latest temperature graph daily!
4️⃣ Create a Simple Web Interface
Run:
nano ~/web_server.py
Paste this code:
from flask import Flask, send_file
import glob
import os
app = Flask(__name__)
@app.route("/")
def serve_latest_graph():
# Find the latest graph image
latest_graph = max(glob.glob("/var/log/cpu_temp_graph_*.png"), key=os.path.getctime)
return send_file(latest_graph, mimetype="image/png")
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5000)
Save & exit (Ctrl+X, Y, Enter).
5️⃣ Start the Web Server on Boot
Run:
sudo nano /etc/systemd/system/web_server.service
Paste this:
[Unit]
Description=Raspberry Pi CPU Temp Web Server
After=network.target
[Service]
ExecStart=/usr/bin/python3 /home/pi/web_server.py
Restart=always
User=pi
[Install]
WantedBy=multi-user.target
Save & exit.
Then run:
sudo systemctl daemon-reload
sudo systemctl enable web_server
sudo systemctl start web_server
✅ Your Raspberry Pi is now hosting the latest CPU temperature graph at:
📌 http://your-pi-ip:5000
🚀 Now You Can Receive & View Your Pi’s Temperature Graphs Anytime!
Would you like to add mobile notifications (Telegram or Pushbullet) for real-time alerts? 📲
📲 Get Real-Time Mobile Notifications for High CPU Temperature
Now, let’s set up Telegram or Pushbullet to receive instant alerts when your Raspberry Pi CPU temperature gets too high.
1️⃣ Choose Your Notification Method
You can use Telegram (recommended) or Pushbullet:
- Telegram → Free, secure, and works on all devices.
- Pushbullet → Easier setup but limits free messages.
I’ll walk you through Telegram first—let me know if you prefer Pushbullet instead.
2️⃣ Set Up a Telegram Bot
🔹 Create a Telegram Bot
- Open Telegram and search for BotFather.
- Type
/newbotand follow the prompts:- Choose a name (e.g., “RaspberryPiMonitor”).
- Choose a username (must end in
bot, e.g., “RPiTempBot”).
- Copy the API token that BotFather gives you.
🔹 Get Your Chat ID
- Open Telegram and search for @userinfobot.
- Type
/startand note your Chat ID (a number like123456789).
3️⃣ Install Telegram Library on Raspberry Pi
Run:
pip install python-telegram-bot
4️⃣ Add Telegram Alerts to Your Script
Run:
nano ~/cpu_temp_alert.py
Paste this code:
import os
import requests
# Telegram Bot API Token (from BotFather)
TELEGRAM_BOT_TOKEN = "your_bot_token_here"
# Your Telegram Chat ID
TELEGRAM_CHAT_ID = "your_chat_id_here"
# Read CPU temperature
def get_cpu_temperature():
temp_output = os.popen("vcgencmd measure_temp").readline()
return float(temp_output.replace("temp=", "").replace("'C\n", ""))
# Send Telegram Alert
def send_telegram_alert(temp):
message = f"⚠️ *Raspberry Pi Overheating!*\n\nCPU Temperature: {temp}°C"
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
data = {"chat_id": TELEGRAM_CHAT_ID, "text": message, "parse_mode": "Markdown"}
requests.post(url, data=data)
# Check CPU Temp and Alert if Over 80°C
cpu_temp = get_cpu_temperature()
if cpu_temp > 80:
send_telegram_alert(cpu_temp)
Save & exit (Ctrl+X, Y, Enter).
5️⃣ Automate Alerts with Cron
Run:
crontab -e
Add this line to check the temperature every 5 minutes:
*/5 * * * * /usr/bin/python3 /home/pi/cpu_temp_alert.py
✅ Now, you’ll get a Telegram alert if your Raspberry Pi overheats!
🚀 Your Raspberry Pi Now Logs, Graphs, and Sends Alerts!
Would you also like Pushbullet alerts as an alternative? 📱
📲 Set Up Pushbullet for CPU Temperature Alerts
Pushbullet is another great way to receive real-time notifications when your Raspberry Pi overheats.
1️⃣ Set Up Pushbullet
🔹 Get a Pushbullet API Key
- Go to Pushbullet.com and sign in.
- Click on your profile picture → Settings.
- Go to Access Tokens and click Create Access Token.
- Copy the token (you’ll need it in the next step).
2️⃣ Install Pushbullet Python Library
Run:
pip install pushbullet.py
3️⃣ Create the Pushbullet Alert Script
Run:
nano ~/cpu_temp_alert_pushbullet.py
Paste this code:
import os
from pushbullet import Pushbullet
# Pushbullet API Token (replace with your actual token)
PUSHBULLET_API_KEY = "your_pushbullet_token_here"
# Read CPU temperature
def get_cpu_temperature():
temp_output = os.popen("vcgencmd measure_temp").readline()
return float(temp_output.replace("temp=", "").replace("'C\n", ""))
# Send Pushbullet Alert
def send_pushbullet_alert(temp):
pb = Pushbullet(PUSHBULLET_API_KEY)
title = "⚠️ Raspberry Pi Overheating!"
message = f"CPU Temperature: {temp}°C - Check your system!"
pb.push_note(title, message)
# Check CPU Temp and Alert if Over 80°C
cpu_temp = get_cpu_temperature()
if cpu_temp > 80:
send_pushbullet_alert(cpu_temp)
Save & exit (Ctrl+X, Y, Enter).
4️⃣ Automate Alerts with Cron
Run:
crontab -e
Add this line to check the temperature every 5 minutes:
*/5 * * * * /usr/bin/python3 /home/pi/cpu_temp_alert_pushbullet.py
✅ Now, you’ll get Pushbullet notifications when your Raspberry Pi overheats!
🚀 Your Pi Now Supports Telegram & Pushbullet Alerts!
Would you like to customize alert thresholds or send alerts to multiple devices? 📱🔥
How to backup an image of the Raspberry Pi SD (from Gemini)
Creating an image of your Raspberry Pi’s SD card is essential for backups, cloning, or restoring your system. Here’s how you can do it, depending on your operating system:
1. On Linux:
- Using
dd(Disk Dump):- This is a powerful command-line tool for copying disk images.
- Identify the SD card:
- Use
lsblkorsudo fdisk -lto list your connected drives. Identify the SD card’s device name (e.g.,/dev/sdb,/dev/mmcblk0). Be very careful to select the correct device, asddcan overwrite data.
- Use
- Create the image:
sudo dd bs=4M if=/dev/sdX of=rpi-image.img status=progress- Replace
/dev/sdXwith your SD card’s device name. rpi-image.imgis the name of the image file.bs=4Msets the block size to 4MB for faster copying.status=progressshows the copy progress.
- Replace
- Compress the image (optional):
gzip rpi-image.img- This will create a compressed image file (
rpi-image.img.gz), which is smaller and easier to store.
- This will create a compressed image file (
2. On macOS:
- Using
dd(similar to Linux):- Identify the SD card:
- Use
diskutil listin the Terminal to find the SD card’s device identifier (e.g.,/dev/disk2).
- Use
- Unmount the SD card:
diskutil unmountDisk /dev/disk2(replace/dev/disk2with your SD card’s identifier).
- Create the image:
sudo dd bs=4m if=/dev/rdisk2 of=rpi-image.img- Note the use of
/dev/rdisk2(raw disk) for faster copying.
- Note the use of
- Compress the image (optional):
gzip rpi-image.img
- Identify the SD card:
3. On Windows:
- Using Raspberry Pi Imager:
- The Raspberry Pi Imager is a user-friendly tool that can create images and restore them.1
- Download and install the Raspberry Pi Imager from the official Raspberry Pi website.2
- Insert your SD card into your computer.
- Open the Raspberry Pi Imager.
- Click “Choose Storage” and select your SD card.
- Click the gear icon in the lower right corner, and select “Save image to file”.
- Choose a location and filename for the image.
- Click “Write” to create the image.
- Using Win32 Disk Imager:
- Win32 Disk Imager is another popular tool for creating and restoring disk images.3
- Download and install Win32 Disk Imager.
- Insert your SD card into your computer.
- Open Win32 Disk Imager.
- Select your SD card’s drive letter.
- Choose a location and filename for the image.
- Click “Read” to create the image.
Important Notes:
- SD Card Size: The image file will be the same size as your SD card, regardless of the amount of data it contains.
- Backup Data: Before creating an image, ensure you have backed up any important data on the SD card.
- Verification: After creating the image, you can verify it by comparing its checksum with the original SD card.
- Restoring the Image: You can use the same tools (Raspberry Pi Imager, Win32 Disk Imager, or
dd) to restore the image to another SD card. - Power Down: Always properly power down your raspberry pi before removing the SD card.
- Unmount: Always unmount the SD card before removing it from a computer.