Merge branch 'main' of https://github.com/jeanGaston/WeatherStation
This commit is contained in:
commit
42a8c119d1
@ -49,9 +49,9 @@ def dashboard():
|
|||||||
data = fetch_all_data()[:5]
|
data = fetch_all_data()[:5]
|
||||||
|
|
||||||
# Convert figure to JSON for rendering in template
|
# Convert figure to JSON for rendering in template
|
||||||
graph_json = history_graph('Home')
|
temp_graph_json = history_graph_temp()
|
||||||
|
HR_graph_json = history_graph_HR()
|
||||||
return render_template('index.html', data=data, temperature=None, graph_json=graph_json)
|
return render_template('index.html', data=data, temperature=None, temp_graph_json=temp_graph_json, HR_graph_json=HR_graph_json)
|
||||||
|
|
||||||
#Route to display the sensor history
|
#Route to display the sensor history
|
||||||
@app.route('/history')
|
@app.route('/history')
|
||||||
@ -79,7 +79,10 @@ def admin():
|
|||||||
|
|
||||||
# Fetch email settings
|
# Fetch email settings
|
||||||
email_settings = fetch_email_settings()
|
email_settings = fetch_email_settings()
|
||||||
return render_template('admin.html', data=data, sensors=data, email_settings=email_settings)
|
|
||||||
|
#Fetch threshold settings
|
||||||
|
threshold_settings = fetch_threshold_settings()
|
||||||
|
return render_template('admin.html', data=data, sensors=data, email_settings=email_settings, threshold_settings=threshold_settings)
|
||||||
|
|
||||||
@app.route('/updateMail', methods=['POST'])
|
@app.route('/updateMail', methods=['POST'])
|
||||||
def update_mail():
|
def update_mail():
|
||||||
@ -89,9 +92,14 @@ def update_mail():
|
|||||||
smtp_server = request.form['smtp_server']
|
smtp_server = request.form['smtp_server']
|
||||||
smtp_port = request.form['smtp_port']
|
smtp_port = request.form['smtp_port']
|
||||||
recipient_email = request.form['recipient_email']
|
recipient_email = request.form['recipient_email']
|
||||||
|
max_hr = request.form['MAX_HR']
|
||||||
|
max_temp = request.form['MAX_TEMP']
|
||||||
|
|
||||||
# Update email settings in the database or perform any other actions
|
# Update email settings in the database
|
||||||
update_email_settings(smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email)
|
update_email_settings(smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email)
|
||||||
|
# Update threshold settings in the database
|
||||||
|
update_threshold_settings(max_hr, max_temp)
|
||||||
|
|
||||||
# Redirect to a success page or render a template
|
# Redirect to a success page or render a template
|
||||||
return redirect("/adm")
|
return redirect("/adm")
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@ -5,7 +5,6 @@ import plotly.graph_objs as go
|
|||||||
import pandas as pd
|
import pandas as pd
|
||||||
|
|
||||||
|
|
||||||
import time
|
|
||||||
|
|
||||||
from env import *
|
from env import *
|
||||||
|
|
||||||
@ -27,18 +26,20 @@ def create_database(db_name):
|
|||||||
Sensor TEXT,
|
Sensor TEXT,
|
||||||
Timestamp TEXT,
|
Timestamp TEXT,
|
||||||
Temp INT,
|
Temp INT,
|
||||||
HR INTEGER,
|
HR INT,
|
||||||
Bat INT,
|
Bat INT,
|
||||||
FOREIGN KEY (Sensor) REFERENCES Sensors(Name))''')
|
FOREIGN KEY (Sensor) REFERENCES Sensors(Name))''')
|
||||||
|
|
||||||
c.execute('''CREATE TABLE IF NOT EXISTS settings (
|
c.execute('''CREATE TABLE IF NOT EXISTS alert_settings (
|
||||||
id INTEGER PRIMARY KEY,
|
id INTEGER PRIMARY KEY,
|
||||||
smtp_id TEXT,
|
smtp_id TEXT,
|
||||||
smtp_pwd TEXT,
|
smtp_pwd TEXT,
|
||||||
smtp_server TEXT,
|
smtp_server TEXT,
|
||||||
smtp_port INTEGER,
|
smtp_port INTEGER,
|
||||||
recipient_email TEXT);''')
|
recipient_email TEXT,
|
||||||
c.execute("INSERT OR IGNORE INTO settings (smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email) VALUES (?, ?, ?, ?, ?)", (SMTP_ID, SMTP_PWD, SMTP, SMTP_PORT, RECIPIENT))
|
MAX_HR INT,
|
||||||
|
MAX_TEMP INT);''')
|
||||||
|
c.execute("INSERT OR IGNORE INTO alert_settings (smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email, MAX_HR, MAX_TEMP) VALUES (?, ?, ?, ?, ?, ?, ?)", (SMTP_ID, SMTP_PWD, SMTP, SMTP_PORT, RECIPIENT, MAX_HR, MAX_TEMP))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -49,11 +50,11 @@ def create_database(db_name):
|
|||||||
def check_database(db_name):
|
def check_database(db_name):
|
||||||
if not path.exists(db_name):
|
if not path.exists(db_name):
|
||||||
|
|
||||||
print(f"[{datetime.now()}] Database '{db_name}' not found. Creating...")
|
print(f"[{datetime.now()}] DB - Database '{db_name}' not found. Creating...")
|
||||||
create_database(db_name)
|
create_database(db_name)
|
||||||
print(f"[{datetime.now()}] Database and tables created successfully.")
|
print(f"[{datetime.now()}] DB - Database and tables created successfully.")
|
||||||
else:
|
else:
|
||||||
print(f"[{datetime.now()}] Database '{db_name}' found.")
|
print(f"[{datetime.now()}] DB - Database '{db_name}' found.")
|
||||||
|
|
||||||
|
|
||||||
# Function to add data to SensorData table
|
# Function to add data to SensorData table
|
||||||
@ -107,7 +108,15 @@ def update_sensor_settings(new_name, old_name):
|
|||||||
def fetch_email_settings():
|
def fetch_email_settings():
|
||||||
conn = sqlite3.connect(DBFILE)
|
conn = sqlite3.connect(DBFILE)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute("SELECT smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email FROM settings")
|
c.execute("SELECT smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email FROM alert_settings")
|
||||||
|
settings = c.fetchone()
|
||||||
|
conn.close()
|
||||||
|
return settings
|
||||||
|
# Function to fetch MAX HR and MAX temp from the database
|
||||||
|
def fetch_threshold_settings():
|
||||||
|
conn = sqlite3.connect(DBFILE)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("SELECT MAX_HR, MAX_TEMP FROM alert_settings")
|
||||||
settings = c.fetchone()
|
settings = c.fetchone()
|
||||||
conn.close()
|
conn.close()
|
||||||
return settings
|
return settings
|
||||||
@ -116,19 +125,29 @@ def fetch_email_settings():
|
|||||||
def update_email_settings(smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email):
|
def update_email_settings(smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email):
|
||||||
conn = sqlite3.connect(DBFILE)
|
conn = sqlite3.connect(DBFILE)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
c.execute("UPDATE settings SET smtp_id = ?, smtp_pwd = ?, smtp_server = ?, smtp_port = ?, recipient_email = ? ", (smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email))
|
c.execute("UPDATE alert_settings SET smtp_id = ?, smtp_pwd = ?, smtp_server = ?, smtp_port = ?, recipient_email = ? ", (smtp_id, smtp_pwd, smtp_server, smtp_port, recipient_email))
|
||||||
conn.commit()
|
conn.commit()
|
||||||
print(f"[{datetime.now()}] Mail settings updated :")
|
print(f"[{datetime.now()}] Web - Mail settings updated :")
|
||||||
print_email_settings()
|
print_email_settings()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
|
# Function to update threshold settings in the database
|
||||||
|
def update_threshold_settings(max_hr, max_temp):
|
||||||
|
conn = sqlite3.connect(DBFILE)
|
||||||
|
c = conn.cursor()
|
||||||
|
c.execute("UPDATE alert_settings SET MAX_HR = ?, MAX_TEMP = ? ", (max_hr, max_temp))
|
||||||
|
conn.commit()
|
||||||
|
print(f"[{datetime.now()}] Web - threshold settings updated :")
|
||||||
|
print_threshold_settings()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
def print_email_settings():
|
def print_email_settings():
|
||||||
# Connect to the database
|
# Connect to the database
|
||||||
conn = sqlite3.connect(DBFILE)
|
conn = sqlite3.connect(DBFILE)
|
||||||
c = conn.cursor()
|
c = conn.cursor()
|
||||||
|
|
||||||
# Fetch email settings
|
# Fetch email settings
|
||||||
c.execute("SELECT * FROM settings")
|
c.execute("SELECT * FROM alert_settings")
|
||||||
settings = c.fetchone()
|
settings = c.fetchone()
|
||||||
|
|
||||||
# Print settings
|
# Print settings
|
||||||
@ -145,21 +164,80 @@ def print_email_settings():
|
|||||||
# Close the connection
|
# Close the connection
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
def history_graph(sensor):
|
def print_threshold_settings():
|
||||||
# Fetch sensor data
|
# Connect to the database
|
||||||
data = fetch_data_by_sensor(sensor)
|
conn = sqlite3.connect(DBFILE)
|
||||||
df = pd.DataFrame(data, columns=['ID', 'Sensor', 'Timestamp', 'Temp', 'HR', 'Bat'])
|
c = conn.cursor()
|
||||||
# Create traces for temperature and HR
|
|
||||||
trace_temp = go.Scatter(x=df['Timestamp'], y=df['Temp'], mode='lines', name='Temperature')
|
|
||||||
trace_hr = go.Scatter(x=df['Timestamp'], y=df['HR'], mode='lines', name='Humidity Rate')
|
|
||||||
|
|
||||||
|
# Fetch threshold settings
|
||||||
|
c.execute("SELECT MAX_HR, MAX_TEMP FROM alert_settings")
|
||||||
|
settings = c.fetchone()
|
||||||
|
|
||||||
|
# Print settings
|
||||||
|
if settings:
|
||||||
|
print("threshold Settings:")
|
||||||
|
print(f"MAX_HR: {settings[0]}")
|
||||||
|
print(f"MAX_TEMP:{settings[1]}")
|
||||||
|
else:
|
||||||
|
print("No threshold settings found in the database.")
|
||||||
|
|
||||||
|
# Close the connection
|
||||||
|
conn.close
|
||||||
|
|
||||||
|
def history_graph_temp():
|
||||||
|
# Fetch sensor data
|
||||||
|
sensorList = fetch_all_sensor()
|
||||||
|
Trace = ['','' ,'' ]
|
||||||
|
i =0
|
||||||
|
for mac, name in sensorList:
|
||||||
|
|
||||||
|
data = fetch_data_by_sensor(name)
|
||||||
|
#print(data)
|
||||||
|
df = pd.DataFrame(data, columns=['ID', 'Sensor', 'Timestamp', 'Temp', 'HR', 'Bat'])
|
||||||
|
# Create traces for temperature
|
||||||
|
Trace[i] = go.Scatter(x=df['Timestamp'], y=df['Temp'], mode='lines', name=name)
|
||||||
|
#print(Trace[i])
|
||||||
|
i+=1
|
||||||
|
#print(trace_temp)
|
||||||
# Create layout
|
# Create layout
|
||||||
layout = go.Layout(title='Last Hour of History',
|
layout = go.Layout(title='Graph Temp history',
|
||||||
xaxis=dict(title='Time'),
|
xaxis=dict(title='Time'),
|
||||||
yaxis=dict(title='Value'))
|
yaxis=dict(title='Temperature in °C'))
|
||||||
|
|
||||||
# Create figure
|
# Create figure
|
||||||
fig = go.Figure(data=[trace_temp, trace_hr], layout=layout)
|
fig = go.Figure(data=[Trace[0], Trace[1], Trace[2] ], layout=layout )
|
||||||
|
|
||||||
# Convert figure to JSON for rendering in template
|
# Convert figure to JSON for rendering in template
|
||||||
graph_json = fig.to_json()
|
graph_json = fig.to_json()
|
||||||
|
#print(graph_json)
|
||||||
|
return graph_json
|
||||||
|
def history_graph_HR():
|
||||||
|
# Fetch sensor data
|
||||||
|
sensorList = fetch_all_sensor()
|
||||||
|
Trace = ['','','']
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
|
||||||
|
for mac, name in sensorList:
|
||||||
|
|
||||||
|
data = fetch_data_by_sensor(name)
|
||||||
|
df = pd.DataFrame(data, columns=['ID', 'Sensor', 'Timestamp', 'Temp', 'HR', 'Bat'])
|
||||||
|
# Create traces for temperature
|
||||||
|
Trace[i] = go.Scatter(x=df['Timestamp'], y=df['HR'], mode='lines', name=name)
|
||||||
|
#print(Trace[i])
|
||||||
|
i+=1
|
||||||
|
|
||||||
|
|
||||||
|
#print(trace_temp)
|
||||||
|
# Create layout
|
||||||
|
layout = go.Layout(title='Graph HR history',
|
||||||
|
xaxis=dict(title='Time'),
|
||||||
|
yaxis=dict(title='Humidity Rate in % '))
|
||||||
|
|
||||||
|
# Create figure
|
||||||
|
fig = go.Figure(data=[Trace[0], Trace[1], Trace[2] ], layout=layout )
|
||||||
|
|
||||||
|
# Convert figure to JSON for rendering in template
|
||||||
|
graph_json = fig.to_json()
|
||||||
|
#print(graph_json)
|
||||||
|
return graph_json
|
||||||
@ -32,7 +32,7 @@ def email(recipient_email, message, ReachedVal, Sensor, TimeStamp):
|
|||||||
- The sensor on wich the values are maxed out
|
- The sensor on wich the values are maxed out
|
||||||
- the time stamp
|
- the time stamp
|
||||||
"""
|
"""
|
||||||
print(fetch_email_settings())
|
#print(fetch_email_settings())
|
||||||
sender_email, password, smtp_server, port, recipient_email = fetch_email_settings()
|
sender_email, password, smtp_server, port, recipient_email = fetch_email_settings()
|
||||||
|
|
||||||
# Create a MIME message
|
# Create a MIME message
|
||||||
@ -55,11 +55,11 @@ def email(recipient_email, message, ReachedVal, Sensor, TimeStamp):
|
|||||||
|
|
||||||
# Send the email
|
# Send the email
|
||||||
server.sendmail(sender_email, recipient_email, msg.as_string())
|
server.sendmail(sender_email, recipient_email, msg.as_string())
|
||||||
print(f" [{datetime.now()}] Email sent successfully!")
|
print(f"[{datetime.now()}] Mail Alerte System - Email sent successfully!")
|
||||||
# Close the connection
|
# Close the connection
|
||||||
server.quit()
|
server.quit()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"[{datetime.now()}] Failed to send email. Error: {e}")
|
print(f"[{datetime.now()}] Mail Alerte System - Failed to send email. Error: {e}")
|
||||||
finally:
|
finally:
|
||||||
None
|
None
|
||||||
|
|
||||||
@ -72,19 +72,23 @@ def check_and_send_email():
|
|||||||
# Retrieve the last record from SensorData table
|
# Retrieve the last record from SensorData table
|
||||||
c.execute("SELECT * FROM SensorData ORDER BY Id DESC LIMIT 1")
|
c.execute("SELECT * FROM SensorData ORDER BY Id DESC LIMIT 1")
|
||||||
last_record = c.fetchone()
|
last_record = c.fetchone()
|
||||||
|
# Retrieve the threshold settings from Alert_settings table
|
||||||
|
c.execute("SELECT MAX_HR, MAX_TEMP FROM alert_settings")
|
||||||
|
threshold = c.fetchone()
|
||||||
|
print(threshold)
|
||||||
|
|
||||||
if last_record:
|
if last_record:
|
||||||
# Extract HR and Temp values from the last record
|
# Extract HR and Temp values from the last record
|
||||||
_, sensor, time, temp, hr, _ = last_record
|
_, sensor, time, temp, hr, _ = last_record
|
||||||
|
|
||||||
# Check if HR or Temp exceed set values
|
# Check if HR or Temp exceed set values
|
||||||
if temp > MAX_HR:
|
if temp > threshold[1]:
|
||||||
email(RECIPIENT, MESSAGE_TEMP, temp, sensor, time)
|
email(RECIPIENT, MESSAGE_TEMP, temp, sensor, time)
|
||||||
elif hr > MAX_TEMP:
|
if hr > threshold[0]:
|
||||||
email(RECIPIENT, MESSAGE_HR, temp, sensor, time)
|
email(RECIPIENT, MESSAGE_HR, hr, sensor, time)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print("No data found in the database.")
|
print(f"[{datetime.now()}] Mail - No data found in the database.")
|
||||||
|
|
||||||
# Close database connection
|
# Close database connection
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|||||||
@ -112,7 +112,7 @@
|
|||||||
<br><br>
|
<br><br>
|
||||||
<button type="submit">Rename Sensor</button>
|
<button type="submit">Rename Sensor</button>
|
||||||
</form>
|
</form>
|
||||||
<h1>Email Settings</h1>
|
<h1>Alert Settings</h1>
|
||||||
<form method="post" action="/updateMail">
|
<form method="post" action="/updateMail">
|
||||||
<label for="smtp_id">Sender Email:</label>
|
<label for="smtp_id">Sender Email:</label>
|
||||||
<input type="email" id="smtp_id" name="smtp_id" value="{{ email_settings[0] }}">
|
<input type="email" id="smtp_id" name="smtp_id" value="{{ email_settings[0] }}">
|
||||||
@ -129,6 +129,12 @@
|
|||||||
<label for="recipient_email">Recipient Email:</label>
|
<label for="recipient_email">Recipient Email:</label>
|
||||||
<input type="email" id="recipient_email" name="recipient_email" value="{{ email_settings[4] }}">
|
<input type="email" id="recipient_email" name="recipient_email" value="{{ email_settings[4] }}">
|
||||||
<br><br>
|
<br><br>
|
||||||
|
<label for="MAX_TEMP">Temperature max threshold:</label>
|
||||||
|
<input type="number" id="MAX_TEMP" name="MAX_TEMP" value="{{ threshold_settings[1] }}">
|
||||||
|
<br><br>
|
||||||
|
<label for="MAX_HR">HR max threshold:</label>
|
||||||
|
<input type="number" id="MAX_HR" name="MAX_HR" value="{{ threshold_settings[0] }}">
|
||||||
|
<br><br>
|
||||||
<button type="submit">Save Settings</button>
|
<button type="submit">Save Settings</button>
|
||||||
</form>
|
</form>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
|
||||||
<title>Sensor Data Dashboard</title>
|
<title>Sensor Data Dashboard</title>
|
||||||
<!-- <link rel="stylesheet" href="/css"> -->
|
<!-- <link rel="stylesheet" href="/css"> -->
|
||||||
<style>body {
|
<style>body {
|
||||||
@ -85,14 +86,16 @@
|
|||||||
<p>Unable to fetch weather data.</p>
|
<p>Unable to fetch weather data.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
<h1>Last Hour of History</h1>
|
<h1>History in graphs</h1>
|
||||||
<div id="graph"></div>
|
<div id="graph_temp"></div>
|
||||||
|
<div id="graph_hr"></div>
|
||||||
<script>
|
<script>
|
||||||
// Parse JSON data
|
// Parse JSON data
|
||||||
var graphData = {{ graph_json | safe }};
|
var temp_graphData = {{ temp_graph_json | safe }};
|
||||||
|
var HR_graphData = {{ HR_graph_json | safe }};
|
||||||
// Render graph
|
// Render graph
|
||||||
Plotly.newPlot('graph', graphData.data, graphData.layout);
|
Plotly.newPlot('graph_temp', temp_graphData.data, temp_graphData.layout);
|
||||||
|
Plotly.newPlot('graph_hr', HR_graphData.data, HR_graphData.layout);
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
// Refresh the page every 10 seconds
|
// Refresh the page every 10 seconds
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user