This commit is contained in:
jeanGaston 2024-05-01 22:29:23 +02:00
parent eaee2e77c9
commit ead358ab1c
8 changed files with 270 additions and 45 deletions

View File

@ -1,44 +1,90 @@
import csv
from datetime import datetime, timedelta
import threading import threading
from env import *
from flask import Flask, render_template
import sqlite3
import requests
from env import *
from flask import Flask, render_template, request
import sqlite3
from database import *
app = Flask(__name__) app = Flask(__name__)
# Function to fetch data from the database
def fetch_all_data(): # Function to fetch outdoor temperature from Météo-France
conn = sqlite3.connect(DBFILE) def fetch_outdoor_temperature():
c = conn.cursor() # Format the date in the required format (YYYYMMDD)
c.execute("SELECT * FROM SensorData ") formatted_csv_date = datetime.now().strftime("%Y%m%d%H")
data = c.fetchall() print(formatted_csv_date)
conn.close() # Construct the URL
data.reverse() url = f"https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Synop/synop.{formatted_csv_date}.csv"
return data
# Function to fetch data from the database with the sensor name as a parameter # Make the HTTP GET request
def fetch_data_by_sensor(sensor): response = requests.get(url)
conn = sqlite3.connect(DBFILE) print(response)
c = conn.cursor() # Check if request was successful
c.execute("SELECT * FROM SensorData WHERE Sensor LIKE ? ", ('%' + sensor + '%',)) try:
data = c.fetchall() # Decode the content as UTF-8 and split into lines
conn.close() lines = response.content.decode('utf-8').splitlines()
data.reverse() # Read the CSV data using csv.DictReader
return data reader = csv.DictReader(lines, delimiter=";")
# Extract outdoor temperature from the CSV data
for row in reader:
if row['numer_sta'] == '07149': #
outdoor_temp = float(row['t'])
return round(outdoor_temp - 273.15, 1) #convert °K to °c
except:
print("Failed to fetch data from Météo-France.")
# Appel de la fonction pour obtenir la température
temperature = fetch_outdoor_temperature()
print(temperature)
# Route to display the database contents # Route to display the database contents
@app.route('/') @app.route('/')
def dashboard(): def dashboard():
data = fetch_all_data()[:5] data = fetch_all_data()[:5]
return render_template('index.html', data=data) return render_template('index.html', data=data, temperature=temperature)
#Route to display the sensor history #Route to display the sensor history
@app.route('/history') @app.route('/history')
def history(): def history():
S1 = fetch_data_by_sensor("DEMO1") data = fetch_all_sensor()
S2 = fetch_data_by_sensor("DEMO2") disp_data = []
S3 = fetch_data_by_sensor("DEMO3")
for mac, name in data:
return render_template('history.html', S1=S1, S2=S2, S3=S3) disp_data += [fetch_data_by_sensor(name)]
""" S1 = fetch_data_by_sensor("DEMO1")
S2 = fetch_data_by_sensor("DEMO2")
S3 = fetch_data_by_sensor("DEMO3") """
return render_template('history.html', S1=disp_data[0], S2=disp_data[1], S3=disp_data[2])
@app.route('/adm', methods=['GET', 'POST'])
def admin():
if request.method == 'POST':
# Get form data
old_name = request.form['old_name']
new_name = request.form['new_name']
# Update sensor name in the database
conn = sqlite3.connect(DBFILE)
c = conn.cursor()
print(old_name, new_name)
c.execute("UPDATE Sensors SET Name = ? WHERE mac = ?", (new_name, old_name))
print()
conn.commit()
conn.close()
data = fetch_all_sensor()
print(data)
return render_template('admin.html', data=data, sensors=data)
def run_flask(): def run_flask():
app.run() app.run()

View File

@ -1,24 +1,32 @@
import sqlite3 import sqlite3
from os import path from os import path
from env import SENSORS, DBFILE
# Function to create the database and tables if they don't exist # Function to create the database and tables if they don't exist
def create_database(db_name): def create_database(db_name):
conn = sqlite3.connect(db_name) conn = sqlite3.connect(db_name)
c = conn.cursor() c = conn.cursor()
# Create SensorData table # Create SensorData table
c.execute('''CREATE TABLE IF NOT EXISTS SensorData
(Id INTEGER PRIMARY KEY AUTOINCREMENT,
FOREIGN KEY (Sensor) REFERENCES Sensors(Name),
Timestamp TEXT,
Temp INT,
HR INTEGER,
Bat INT)''')
# Create Sensors table
c.execute('''CREATE TABLE IF NOT EXISTS Sensors c.execute('''CREATE TABLE IF NOT EXISTS Sensors
(Mac TEXT RIMARY KEY, (Mac TEXT PRIMARY KEY,
Name TEXT )''') Name TEXT)''')
# Create SensorData table
c.execute('''CREATE TABLE IF NOT EXISTS SensorData
(Id INTEGER PRIMARY KEY AUTOINCREMENT,
Sensor TEXT,
Timestamp TEXT,
Temp INT,
HR INTEGER,
Bat INT,
FOREIGN KEY (Sensor) REFERENCES Sensors(Name))''')
for mac, name in SENSORS.items():
# Use INSERT OR IGNORE to prevent duplicates based on primary key
c.execute("INSERT OR IGNORE INTO Sensors (Mac, Name) VALUES (?, ?)", (mac, name))
conn.commit() conn.commit()
conn.close() conn.close()
@ -42,4 +50,32 @@ def add_sensor_data(db_name, sensor, timestamp, temp, hr, bat):
VALUES (?, ?, ?, ?, ?)''', (sensor, timestamp, temp, hr, bat)) VALUES (?, ?, ?, ?, ?)''', (sensor, timestamp, temp, hr, bat))
conn.commit() conn.commit()
conn.close() conn.close()
# Function to fetch data from the database
def fetch_all_data():
conn = sqlite3.connect(DBFILE)
c = conn.cursor()
c.execute("SELECT * FROM SensorData ")
data = c.fetchall()
conn.close()
data.reverse()
return data
# Function to fetch data from the database
def fetch_data_by_sensor(sensor):
conn = sqlite3.connect(DBFILE)
c = conn.cursor()
c.execute("SELECT * FROM SensorData WHERE Sensor LIKE ? ", ('%' + sensor + '%',))
data = c.fetchall()
conn.close()
data.reverse()
return data
# Function to fetch data from the database
def fetch_all_sensor():
conn = sqlite3.connect(DBFILE)
c = conn.cursor()
c.execute("SELECT * FROM Sensors ")
data = c.fetchall()
conn.close()
data.reverse()
return data

View File

@ -2,10 +2,11 @@ import schedule
import threading import threading
import time import time
from env import * from env import *
from database import add_sensor_data from database import add_sensor_data, fetch_all_sensor
from bluepy.btle import Scanner from bluepy.btle import Scanner
def BltDataScrap(): def BltDataScrap():
sensor_dict = {mac: name for mac, name in fetch_all_sensor()}
scanner = Scanner() scanner = Scanner()
#print("Begin device scan") #print("Begin device scan")
devices = scanner.scan(timeout=3.0) devices = scanner.scan(timeout=3.0)
@ -21,7 +22,16 @@ def BltDataScrap():
HR = int(value[28:32], 16) / 100 HR = int(value[28:32], 16) / 100
Bat = int(value[20:22], 16) Bat = int(value[20:22], 16)
#print(f"Temp : {temp} °c \n HR : {HR} % , \n Batterie : {Bat} %") #print(f"Temp : {temp} °c \n HR : {HR} % , \n Batterie : {Bat} %")
add_sensor_data(DBFILE, SENSORS[device.addr], time.strftime("%Y-%m-%d %H:%M:%S"), temp, HR, Bat) add_sensor_data(DBFILE, sensor_dict[device.addr], time.strftime("%Y-%m-%d %H:%M:%S"), temp, HR, Bat)
if temp > MAX_TEMP :
email(RECIPIENT, MESSAGE_Temp, temp, sensor_dict[device.addr], time.strftime("%Y-%m-%d %H:%M:%S") )
print("mail sent for temp max")
elif temp > MAX_HR :
email(RECIPIENT, MESSAGE_HR, HR, sensor_dict[device.addr], time.strftime("%Y-%m-%d %H:%M:%S") )
print("mail sent for HR max")
return 0 return 0
def RunInThread_DataScrap(): def RunInThread_DataScrap():
print("######################################################################\nOpen Thread datascrap") print("######################################################################\nOpen Thread datascrap")

View File

@ -1,3 +1,5 @@
import smtplib
import ssl
from database import * from database import *
from datascraper import * from datascraper import *
from Webserver import RunInThread_WebServer from Webserver import RunInThread_WebServer

View File

@ -0,0 +1,121 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sensor Data Dashboard</title>
<link rel="stylesheet" href="/css">
<style>body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
max-width: 800px;
margin: 20px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 5px;
}
h1 {
text-align: center;
}
table {
width: 100%;
border-collapse: collapse;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #ddd;
}
tr:hover {
background-color: #f2f2f2;
}
.btn-container {
text-align: center;
margin-top: 20px;
}
.btn {
padding: 10px 20px;
font-size: 16px;
text-decoration: none;
color: #fff;
background-color: #007bff;
border: none;
border-radius: 5px;
cursor: pointer;
}
.btn:hover {
background-color: #0056b3;
}
form {
max-width: 400px;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
label {
display: block;
margin-bottom: 10px;
}
select, input[type="text"], button {
width: 100%;
padding: 10px;
margin-bottom: 20px;
border: 1px solid #ccc;
border-radius: 4px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="btn-container">
<a href="/history" class="btn">View History</a>
<a href="/" class="btn">Dashboard</a>
</div>
<div class="container">
<h1>Sensors</h1>
<table>
<tr>
<th>mac</th>
<th>Name</th>
</tr>
{% for row in data %}
<tr>
<td>{{ row[0] }}</td>
<td>{{ row[1] }}</td>
<td>{{ row[2] }}</td>
<td>{{ row[3] }}</td>
<td>{{ row[4] }}</td>
<td>{{ row[5] }}</td>
</tr>
{% endfor %}
</table>
</div>
<h1>Rename Sensor</h1>
<form method="post">
<label for="old_name">Select sensor to rename:</label>
<select name="old_name" id="old_name">
{% for sensor in sensors %}
<option value="{{ sensor[0] }}">{{ sensor[1] }}</option>
{% endfor %}
</select>
<br><br>
<label for="new_name">Enter new name:</label>
<input type="text" name="new_name" id="new_name" required>
<br><br>
<button type="submit">Rename Sensor</button>
</form>
<script>
// Refresh the page every 10 seconds
setTimeout(function(){
location.reload();
}, 20000);
</script>
</body>
</html>

View File

@ -54,6 +54,10 @@ tr:hover {
</style> </style>
</head> </head>
<body> <body>
<div class="btn-container">
<a href="/adm" class="btn">Admin</a>
<a href="/" class="btn">Dashboard</a>
</div>
<h1>Database Contents</h1> <h1>Database Contents</h1>
<h2>Sensor 1</h2> <h2>Sensor 1</h2>
<table border="1"> <table border="1">

View File

@ -51,6 +51,10 @@
}</style> }</style>
</head> </head>
<body> <body>
<div class="btn-container">
<a href="/history" class="btn">View History</a>
<a href="/adm" class="btn">Admin</a>
</div>
<div class="container"> <div class="container">
<h1>Sensor Data Dashboard</h1> <h1>Sensor Data Dashboard</h1>
<table> <table>
@ -73,10 +77,12 @@
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<div class="btn-container"> <h1>Current Weather</h1>
<a href="/history" class="btn">View History</a> {% if temperature %}
<a href="/Admin" class="btn">Admin</a> <p>The current temperature is {{ temperature }}°C</p>
</div> {% else %}
<p>Unable to fetch weather data.</p>
{% endif %}
</div> </div>
<script> <script>
// Refresh the page every 10 seconds // Refresh the page every 10 seconds