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
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__)
# 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 with the sensor name as a parameter
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 outdoor temperature from Météo-France
def fetch_outdoor_temperature():
# Format the date in the required format (YYYYMMDD)
formatted_csv_date = datetime.now().strftime("%Y%m%d%H")
print(formatted_csv_date)
# Construct the URL
url = f"https://donneespubliques.meteofrance.fr/donnees_libres/Txt/Synop/synop.{formatted_csv_date}.csv"
# Make the HTTP GET request
response = requests.get(url)
print(response)
# Check if request was successful
try:
# Decode the content as UTF-8 and split into lines
lines = response.content.decode('utf-8').splitlines()
# Read the CSV data using csv.DictReader
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
@app.route('/')
def dashboard():
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
@app.route('/history')
def history():
S1 = fetch_data_by_sensor("DEMO1")
S2 = fetch_data_by_sensor("DEMO2")
S3 = fetch_data_by_sensor("DEMO3")
return render_template('history.html', S1=S1, S2=S2, S3=S3)
data = fetch_all_sensor()
disp_data = []
for mac, name in data:
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():
app.run()

View File

@ -1,24 +1,32 @@
import sqlite3
from os import path
from env import SENSORS, DBFILE
# Function to create the database and tables if they don't exist
def create_database(db_name):
conn = sqlite3.connect(db_name)
c = conn.cursor()
# 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
(Mac TEXT RIMARY KEY,
Name TEXT )''')
(Mac TEXT PRIMARY KEY,
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.close()
@ -42,4 +50,32 @@ def add_sensor_data(db_name, sensor, timestamp, temp, hr, bat):
VALUES (?, ?, ?, ?, ?)''', (sensor, timestamp, temp, hr, bat))
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 time
from env import *
from database import add_sensor_data
from database import add_sensor_data, fetch_all_sensor
from bluepy.btle import Scanner
def BltDataScrap():
sensor_dict = {mac: name for mac, name in fetch_all_sensor()}
scanner = Scanner()
#print("Begin device scan")
devices = scanner.scan(timeout=3.0)
@ -21,7 +22,16 @@ def BltDataScrap():
HR = int(value[28:32], 16) / 100
Bat = int(value[20:22], 16)
#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
def RunInThread_DataScrap():
print("######################################################################\nOpen Thread datascrap")

View File

@ -1,3 +1,5 @@
import smtplib
import ssl
from database import *
from datascraper import *
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>
</head>
<body>
<div class="btn-container">
<a href="/adm" class="btn">Admin</a>
<a href="/" class="btn">Dashboard</a>
</div>
<h1>Database Contents</h1>
<h2>Sensor 1</h2>
<table border="1">

View File

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