Initialisation depuis le code en production

This commit is contained in:
Debian
2025-07-26 08:37:13 +02:00
parent 7de3e0fb50
commit 4c68a514ac
22 changed files with 228 additions and 28118 deletions

View File

@@ -1,74 +0,0 @@
import paho.mqtt.client as mqttClient
import mysql.connector
import sys
import os
import logging
from dotenv import load_dotenv
from datetime import datetime
# Charger les variables d'environnement
load_dotenv()
# 📁 Création du dossier de logs s'il n'existe pas
dossier_logs = "/var/log/Chaufferie_Saclay"
os.makedirs(dossier_logs, exist_ok=True)
# 📝 Configuration du logger
logfile = os.path.join(dossier_logs, "Chaufferie_Saclay.log")
logging.basicConfig(
filename=logfile,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
# Ajoute aussi l'affichage console
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
# 🔌 Connexion MySQL
try:
sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages")
mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME")
)
logging.info("Connexion MySQL réussie.")
except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1)
# 📥 Callback MQTT
def on_message(_client, _userdata, msg):
try:
logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
cursor = mydb.cursor()
topic_mqtt = msg.topic.split('/')[1] # ex: 'ECS'
frigo_name = msg.topic.split('/')[-1] # ex: 'Dietrich_1'
temperature = float(msg.payload.decode())
sql = "INSERT INTO Chaufferie (Sonde, Temperature, Date, Topic) VALUES (%s, %s, %s, %s)"
val = (frigo_name, temperature, datetime.now(), topic_mqtt)
cursor.execute(sql, val)
mydb.commit()
logging.info(f"Insertion réussie : {val}")
except Exception as e:
logging.error(f"Erreur lors de l'insertion du message : {e}")
# 📡 Connexion MQTT
try:
client = mqttClient.Client()
client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
client.on_message = on_message
client.connect("54.36.188.119", 1883, 60)
client.subscribe("Chaufferie/#")
logging.info("Connexion MQTT réussie et abonnement au topic 'Chaufferie/#'.")
client.loop_forever()
except Exception as err:
logging.error(f"Erreur MQTT : {err}")

View File

@@ -1,68 +0,0 @@
import paho.mqtt.client as mqttClient
import mysql.connector
import sys
import os
import logging
from dotenv import load_dotenv
# Charger les variables d'environnement
load_dotenv()
# 📁 Création du dossier de logs s'il n'existe pas
dossier_logs = "/var/log/Cuisine_Meudon"
os.makedirs(dossier_logs, exist_ok=True)
# 📝 Configuration du logger
logfile = os.path.join(dossier_logs, "Cuisine_Meudon.log")
logging.basicConfig(
filename=logfile,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
# Ajoute aussi un affichage console si utile :
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
# 🔌 Connexion MySQL
try:
sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages")
mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME")
)
logging.info("Connexion MySQL réussie.")
except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1)
# 📥 Callback MQTT
def on_message(_client, _userdata, msg):
try:
logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
cursor = mydb.cursor()
frigo_name = msg.topic.split('/')[-1]
sql = "INSERT INTO Meudon (Sonde, Temperature) VALUES (%s, %s)"
val = (frigo_name, msg.payload.decode())
cursor.execute(sql, val)
mydb.commit()
logging.info(f"Insertion réussie : {val}")
except Exception as e:
logging.error(f"Erreur lors de l'insertion du message : {e}")
# 📡 Connexion MQTT
try:
client = mqttClient.Client()
client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
client.on_message = on_message
client.connect("54.36.188.119", 1883, 60)
client.subscribe("Meudon/#")
logging.info("Connexion MQTT réussie et abonnement au topic 'Meudon/#'.")
client.loop_forever()
except Exception as err:
logging.error(f"Erreur MQTT : {err}")

View File

@@ -1,68 +0,0 @@
import paho.mqtt.client as mqttClient
import mysql.connector
import sys
import os
import logging
from dotenv import load_dotenv
# Charger les variables d'environnement
load_dotenv()
# 📁 Création du dossier de logs s'il n'existe pas
dossier_logs = "/var/log/Cuisine_Saclay"
os.makedirs(dossier_logs, exist_ok=True)
# 📝 Configuration du logger
logfile = os.path.join(dossier_logs, "Cuisine_Saclay.log")
logging.basicConfig(
filename=logfile,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
# Ajoute aussi l'affichage console
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console.setFormatter(formatter)
logging.getLogger('').addHandler(console)
# 🔌 Connexion MySQL
try:
sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages")
mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME")
)
logging.info("Connexion MySQL réussie.")
except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1)
# 📥 Callback MQTT
def on_message(_client, _userdata, msg):
try:
logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
cursor = mydb.cursor()
frigo_name = msg.topic.split('/')[-1]
sql = "INSERT INTO Saclay (Sonde, Temperature) VALUES (%s, %s)"
val = (frigo_name, msg.payload.decode())
cursor.execute(sql, val)
mydb.commit()
logging.info(f"Insertion réussie : {val}")
except Exception as e:
logging.error(f"Erreur lors de l'insertion du message : {e}")
# 📡 Connexion MQTT
try:
client = mqttClient.Client()
client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
client.on_message = on_message
client.connect("54.36.188.119", 1883, 60)
client.subscribe("Saclay/#")
logging.info("Connexion MQTT réussie et abonnement au topic 'Saclay/#'.")
client.loop_forever()
except Exception as err:
logging.error(f"Erreur MQTT : {err}")

View File

@@ -1,49 +1,49 @@
Date;Lieu;Sonde;Température;Seuil;État Date;Lieu;Sonde;Température;Seuil;État
2025-07-23 10:15:19;Saclay;Congelateur;-17.50;-15.0;Normal 2025-07-26 08:32:09;Saclay;Congelateur;-15.75;-15.0;Normal
2025-07-23 10:10:16;Saclay;Congelateur;-16.50;-15.0;Normal 2025-07-26 08:27:06;Saclay;Congelateur;-16.00;-15.0;Normal
2025-07-23 10:05:14;Saclay;Congelateur;-17.00;-15.0;Normal 2025-07-26 08:22:04;Saclay;Congelateur;-14.50;-15.0;Dépassement
2025-07-23 10:00:11;Saclay;Congelateur;-17.50;-15.0;Normal 2025-07-26 08:17:01;Saclay;Congelateur;-14.25;-15.0;Dépassement
2025-07-23 09:55:09;Saclay;Congelateur;-17.00;-15.0;Normal 2025-07-26 08:11:59;Saclay;Congelateur;-13.75;-15.0;Dépassement
2025-07-23 09:50:06;Saclay;Congelateur;-16.75;-15.0;Normal 2025-07-26 08:06:56;Saclay;Congelateur;-12.50;-15.0;Dépassement
2025-07-23 10:15:19;Saclay;BOF;1.00;8.0;Normal 2025-07-26 08:32:09;Saclay;BOF;1.50;8.0;Normal
2025-07-23 10:10:17;Saclay;BOF;2.25;8.0;Normal 2025-07-26 08:27:07;Saclay;BOF;1.00;8.0;Normal
2025-07-23 10:05:14;Saclay;BOF;1.00;8.0;Normal 2025-07-26 08:22:04;Saclay;BOF;3.25;8.0;Normal
2025-07-23 10:00:12;Saclay;BOF;2.00;8.0;Normal 2025-07-26 08:17:02;Saclay;BOF;3.00;8.0;Normal
2025-07-23 09:55:09;Saclay;BOF;1.00;8.0;Normal 2025-07-26 08:11:59;Saclay;BOF;2.00;8.0;Normal
2025-07-23 09:50:07;Saclay;BOF;1.25;8.0;Normal 2025-07-26 08:06:56;Saclay;BOF;1.50;8.0;Normal
2025-07-23 10:15:20;Saclay;Viandes;2.50;6.0;Normal 2025-07-26 08:32:10;Saclay;Viandes;20.75;6.0;Dépassement
2025-07-23 10:10:17;Saclay;Viandes;4.75;6.0;Normal 2025-07-26 08:27:07;Saclay;Viandes;20.50;6.0;Dépassement
2025-07-23 10:05:15;Saclay;Viandes;4.50;6.0;Normal 2025-07-26 08:22:05;Saclay;Viandes;21.00;6.0;Dépassement
2025-07-23 10:00:12;Saclay;Viandes;3.75;6.0;Normal 2025-07-26 08:17:02;Saclay;Viandes;20.50;6.0;Dépassement
2025-07-23 09:55:10;Saclay;Viandes;2.50;6.0;Normal 2025-07-26 08:12:00;Saclay;Viandes;20.75;6.0;Dépassement
2025-07-23 09:50:07;Saclay;Viandes;3.00;6.0;Normal 2025-07-26 08:06:57;Saclay;Viandes;20.50;6.0;Dépassement
2025-07-23 10:15:20;Saclay;Legumes;2.75;10.0;Normal 2025-07-26 08:32:10;Saclay;Legumes;4.00;10.0;Normal
2025-07-23 10:10:18;Saclay;Legumes;6.00;10.0;Normal 2025-07-26 08:27:08;Saclay;Legumes;3.50;10.0;Normal
2025-07-23 10:05:15;Saclay;Legumes;5.25;10.0;Normal 2025-07-26 08:22:05;Saclay;Legumes;5.50;10.0;Normal
2025-07-23 10:00:13;Saclay;Legumes;4.50;10.0;Normal 2025-07-26 08:17:03;Saclay;Legumes;5.50;10.0;Normal
2025-07-23 09:55:10;Saclay;Legumes;3.00;10.0;Normal 2025-07-26 08:12:00;Saclay;Legumes;5.00;10.0;Normal
2025-07-23 09:50:08;Saclay;Legumes;6.00;10.0;Normal 2025-07-26 08:06:57;Saclay;Legumes;3.75;10.0;Normal
2025-07-23 10:15:21;Saclay;MeP;4.00;8.0;Normal 2025-07-26 08:32:11;Saclay;MeP;5.25;8.0;Normal
2025-07-23 10:10:18;Saclay;MeP;5.50;8.0;Normal 2025-07-26 08:27:08;Saclay;MeP;4.00;8.0;Normal
2025-07-23 10:05:16;Saclay;MeP;4.00;8.0;Normal 2025-07-26 08:22:06;Saclay;MeP;7.00;8.0;Normal
2025-07-23 10:00:13;Saclay;MeP;6.00;8.0;Normal 2025-07-26 08:17:03;Saclay;MeP;7.75;8.0;Normal
2025-07-23 09:55:11;Saclay;MeP;3.00;8.0;Normal 2025-07-26 08:12:01;Saclay;MeP;7.00;8.0;Normal
2025-07-23 09:50:08;Saclay;MeP;6.00;8.0;Normal 2025-07-26 08:06:58;Saclay;MeP;5.50;8.0;Normal
2025-07-22 10:33:13;Meudon;Viandes;3.94;6.0;Normal 2025-07-26 07:09:45;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 09:14:54;Meudon;Viandes;3.94;6.0;Normal 2025-07-25 14:37:50;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 08:31:47;Meudon;Viandes;5.25;6.0;Normal 2025-07-25 14:32:11;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 08:26:46;Meudon;Viandes;5.06;6.0;Normal 2025-07-25 14:30:20;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 08:21:45;Meudon;Viandes;4.88;6.0;Normal 2025-07-24 11:00:36;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 08:16:44;Meudon;Viandes;4.75;6.0;Normal 2025-07-24 10:41:08;Meudon;Viandes;3.94;6.0;Normal
2025-07-22 10:33:13;Meudon;Poissons;3.94;6.0;Normal 2025-07-26 07:09:45;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 09:14:54;Meudon;Poissons;3.94;6.0;Normal 2025-07-25 14:37:50;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 08:31:47;Meudon;Poissons;5.75;6.0;Normal 2025-07-25 14:32:11;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 08:26:46;Meudon;Poissons;5.25;6.0;Normal 2025-07-25 14:30:20;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 08:21:45;Meudon;Poissons;4.56;6.0;Normal 2025-07-24 11:00:36;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 08:16:44;Meudon;Poissons;4.63;6.0;Normal 2025-07-24 10:41:08;Meudon;Poissons;3.94;6.0;Normal
2025-07-22 10:33:13;Meudon;BOF;3.00;8.0;Normal 2025-07-26 07:09:45;Meudon;BOF;3.00;8.0;Normal
2025-07-22 09:14:54;Meudon;BOF;3.00;8.0;Normal 2025-07-25 14:37:50;Meudon;BOF;3.00;8.0;Normal
2025-07-22 08:31:47;Meudon;BOF;2.25;8.0;Normal 2025-07-25 14:32:11;Meudon;BOF;3.00;8.0;Normal
2025-07-22 08:26:46;Meudon;BOF;1.75;8.0;Normal 2025-07-25 14:30:20;Meudon;BOF;3.00;8.0;Normal
2025-07-22 08:21:45;Meudon;BOF;1.25;8.0;Normal 2025-07-24 11:00:36;Meudon;BOF;3.00;8.0;Normal
2025-07-22 08:16:44;Meudon;BOF;1.00;8.0;Normal 2025-07-24 10:41:08;Meudon;BOF;3.00;8.0;Normal
1 Date Lieu Sonde Température Seuil État
2 2025-07-23 10:15:19 2025-07-26 08:32:09 Saclay Congelateur -17.50 -15.75 -15.0 Normal
3 2025-07-23 10:10:16 2025-07-26 08:27:06 Saclay Congelateur -16.50 -16.00 -15.0 Normal
4 2025-07-23 10:05:14 2025-07-26 08:22:04 Saclay Congelateur -17.00 -14.50 -15.0 Normal Dépassement
5 2025-07-23 10:00:11 2025-07-26 08:17:01 Saclay Congelateur -17.50 -14.25 -15.0 Normal Dépassement
6 2025-07-23 09:55:09 2025-07-26 08:11:59 Saclay Congelateur -17.00 -13.75 -15.0 Normal Dépassement
7 2025-07-23 09:50:06 2025-07-26 08:06:56 Saclay Congelateur -16.75 -12.50 -15.0 Normal Dépassement
8 2025-07-23 10:15:19 2025-07-26 08:32:09 Saclay BOF 1.00 1.50 8.0 Normal
9 2025-07-23 10:10:17 2025-07-26 08:27:07 Saclay BOF 2.25 1.00 8.0 Normal
10 2025-07-23 10:05:14 2025-07-26 08:22:04 Saclay BOF 1.00 3.25 8.0 Normal
11 2025-07-23 10:00:12 2025-07-26 08:17:02 Saclay BOF 2.00 3.00 8.0 Normal
12 2025-07-23 09:55:09 2025-07-26 08:11:59 Saclay BOF 1.00 2.00 8.0 Normal
13 2025-07-23 09:50:07 2025-07-26 08:06:56 Saclay BOF 1.25 1.50 8.0 Normal
14 2025-07-23 10:15:20 2025-07-26 08:32:10 Saclay Viandes 2.50 20.75 6.0 Normal Dépassement
15 2025-07-23 10:10:17 2025-07-26 08:27:07 Saclay Viandes 4.75 20.50 6.0 Normal Dépassement
16 2025-07-23 10:05:15 2025-07-26 08:22:05 Saclay Viandes 4.50 21.00 6.0 Normal Dépassement
17 2025-07-23 10:00:12 2025-07-26 08:17:02 Saclay Viandes 3.75 20.50 6.0 Normal Dépassement
18 2025-07-23 09:55:10 2025-07-26 08:12:00 Saclay Viandes 2.50 20.75 6.0 Normal Dépassement
19 2025-07-23 09:50:07 2025-07-26 08:06:57 Saclay Viandes 3.00 20.50 6.0 Normal Dépassement
20 2025-07-23 10:15:20 2025-07-26 08:32:10 Saclay Legumes 2.75 4.00 10.0 Normal
21 2025-07-23 10:10:18 2025-07-26 08:27:08 Saclay Legumes 6.00 3.50 10.0 Normal
22 2025-07-23 10:05:15 2025-07-26 08:22:05 Saclay Legumes 5.25 5.50 10.0 Normal
23 2025-07-23 10:00:13 2025-07-26 08:17:03 Saclay Legumes 4.50 5.50 10.0 Normal
24 2025-07-23 09:55:10 2025-07-26 08:12:00 Saclay Legumes 3.00 5.00 10.0 Normal
25 2025-07-23 09:50:08 2025-07-26 08:06:57 Saclay Legumes 6.00 3.75 10.0 Normal
26 2025-07-23 10:15:21 2025-07-26 08:32:11 Saclay MeP 4.00 5.25 8.0 Normal
27 2025-07-23 10:10:18 2025-07-26 08:27:08 Saclay MeP 5.50 4.00 8.0 Normal
28 2025-07-23 10:05:16 2025-07-26 08:22:06 Saclay MeP 4.00 7.00 8.0 Normal
29 2025-07-23 10:00:13 2025-07-26 08:17:03 Saclay MeP 6.00 7.75 8.0 Normal
30 2025-07-23 09:55:11 2025-07-26 08:12:01 Saclay MeP 3.00 7.00 8.0 Normal
31 2025-07-23 09:50:08 2025-07-26 08:06:58 Saclay MeP 6.00 5.50 8.0 Normal
32 2025-07-22 10:33:13 2025-07-26 07:09:45 Meudon Viandes 3.94 6.0 Normal
33 2025-07-22 09:14:54 2025-07-25 14:37:50 Meudon Viandes 3.94 6.0 Normal
34 2025-07-22 08:31:47 2025-07-25 14:32:11 Meudon Viandes 5.25 3.94 6.0 Normal
35 2025-07-22 08:26:46 2025-07-25 14:30:20 Meudon Viandes 5.06 3.94 6.0 Normal
36 2025-07-22 08:21:45 2025-07-24 11:00:36 Meudon Viandes 4.88 3.94 6.0 Normal
37 2025-07-22 08:16:44 2025-07-24 10:41:08 Meudon Viandes 4.75 3.94 6.0 Normal
38 2025-07-22 10:33:13 2025-07-26 07:09:45 Meudon Poissons 3.94 6.0 Normal
39 2025-07-22 09:14:54 2025-07-25 14:37:50 Meudon Poissons 3.94 6.0 Normal
40 2025-07-22 08:31:47 2025-07-25 14:32:11 Meudon Poissons 5.75 3.94 6.0 Normal
41 2025-07-22 08:26:46 2025-07-25 14:30:20 Meudon Poissons 5.25 3.94 6.0 Normal
42 2025-07-22 08:21:45 2025-07-24 11:00:36 Meudon Poissons 4.56 3.94 6.0 Normal
43 2025-07-22 08:16:44 2025-07-24 10:41:08 Meudon Poissons 4.63 3.94 6.0 Normal
44 2025-07-22 10:33:13 2025-07-26 07:09:45 Meudon BOF 3.00 8.0 Normal
45 2025-07-22 09:14:54 2025-07-25 14:37:50 Meudon BOF 3.00 8.0 Normal
46 2025-07-22 08:31:47 2025-07-25 14:32:11 Meudon BOF 2.25 3.00 8.0 Normal
47 2025-07-22 08:26:46 2025-07-25 14:30:20 Meudon BOF 1.75 3.00 8.0 Normal
48 2025-07-22 08:21:45 2025-07-24 11:00:36 Meudon BOF 1.25 3.00 8.0 Normal
49 2025-07-22 08:16:44 2025-07-24 10:41:08 Meudon BOF 1.00 3.00 8.0 Normal

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +0,0 @@
from alerte_sms import envoyer_sms_ovh
site = "Meudon" # ou "Meudon", selon ce que tu veux tester
message = "✅ Test SMS depuis le script Monitor - tout fonctionne bien"
envoyer_sms_ovh(message, site)

View File

@@ -1,22 +0,0 @@
import ovh
import os
from dotenv import load_dotenv
load_dotenv()
client = ovh.Client(
endpoint=os.getenv("OVH_ENDPOINT"),
application_key=os.getenv("OVH_APP_KEY"),
application_secret=os.getenv("OVH_APP_SECRET"),
)
# Demande d'une clé avec accès lecture/écriture sur les SMS
ck_request = client.new_consumer_key_request()
ck_request.add_rules(ovh.API_READ_WRITE, "/sms/*")
validation = ck_request.request()
print("✅ LIEN DE VALIDATION OVH :")
print(validation['validationUrl'])
print("\n👉 Une fois autorisé, colle cette valeur dans ton fichier .env :")
print(f"OVH_CONSUMER_KEY={validation['consumerKey']}")

View File

@@ -1,176 +0,0 @@
import mysql.connector
from datetime import datetime, timedelta
import time
from dotenv import load_dotenv
import os
from pathlib import Path
if os.name != 'nt':
log_dir = Path('/home/debian/Gestion_sondes/Logs')
else:
log_dir = Path.cwd() / 'Logs'
log_dir.mkdir(parents=True, exist_ok=True)
load_dotenv()
ENVOI_SMS = os.getenv("ENVOI_SMS") == "1"
# --- Config MySQL ---
config = {
"host": os.getenv("DB_HOST"),
"user": os.getenv("DB_USER"),
"password": os.getenv("DB_PASSWORD"),
"database": os.getenv("DB_NAME")
}
# --- Suivi des alertes actives pour rappels ---
alertes_actives = {}
# --- Fonction d'envoi de mail ---
def envoyer_sms_ovh(message, lieu):
try:
import requests
sms_data = {
"account": os.getenv("OVH_ACCOUNT"),
"login": os.getenv("OVH_LOGIN"),
"password": os.getenv("OVH_PASSWORD"),
"message": f"{lieu}: {message}",
"receivers": os.getenv("SMS_DESTINATAIRES", "").split(","),
"sender": os.getenv("SMS_SENDER", "ALERTE")
}
# Exemple d'envoi avec l'API OVH (à adapter selon ton endpoint exact)
response = requests.post("https://www.ovh.com/cgi-bin/sms/http2sms.cgi", data=sms_data)
print(f"📱 SMS envoyé : {response.text}", flush=True)
except Exception as e:
print(f"Erreur envoi SMS : {e}", flush=True)
# --- Fonction de surveillance ---
def surveiller():
global alertes_actives
log_entries = []
try:
conn = mysql.connector.connect(**config)
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT DISTINCT Lieu FROM Chambres_froides")
lieux = [row['Lieu'] for row in cursor.fetchall()]
for lieu in lieux:
table_temp = lieu
table_alertes = f"Alertes_{lieu}"
cursor.execute("SELECT Sonde, Temp_Max FROM Chambres_froides WHERE Lieu=%s AND Etat='ON'", (lieu,))
sondes = cursor.fetchall()
for sonde in sondes:
nom_sonde = sonde['Sonde']
seuil = sonde['Temp_Max']
cursor.execute(f"""
SELECT Date, Temperature FROM {table_temp}
WHERE Sonde = %s
ORDER BY Date DESC LIMIT 6
""", (nom_sonde,))
releves = cursor.fetchall()
for r in releves:
log_entries.append({
"Date": r['Date'],
"Lieu": lieu,
"Sonde": nom_sonde,
"Température": r['Temperature'],
"Seuil": seuil,
"État": "Dépassement" if r['Temperature'] > seuil else "Normal"
})
if len(releves) == 6:
toutes_hors_seuil = all(r['Temperature'] > seuil for r in releves)
plus_ancien = releves[-1]['Date']
maintenant = datetime.now()
if toutes_hors_seuil and (maintenant - plus_ancien >= timedelta(minutes=30)):
cursor.execute(f"""
SELECT COUNT(*) as total FROM {table_alertes}
WHERE Sonde=%s AND Status='En cours'
""", (nom_sonde,))
en_cours = cursor.fetchone()
if en_cours['total'] == 0:
cursor.execute(
f"INSERT INTO {table_alertes} (Sonde, Debut_defaut, Status) VALUES (%s, NOW(), 'En cours')",
(nom_sonde,)
)
print(f"🚨 Alerte déclenchée pour {nom_sonde} ({lieu})", flush=True)
sujet = f"🚨 ALERTE TEMPÉRATURE - {nom_sonde} ({lieu})"
message = (
f"La sonde '{nom_sonde}' du site '{lieu}' a dépassé le seuil de {seuil}°C "
f"depuis plus de 30 minutes.\nHeure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}"
)
destinataires_list = os.getenv("EMAIL_DESTINATAIRES", "").split(",")
envoyer_mail(sujet, message, destinataires_list)
if ENVOI_SMS:
envoyer_sms_ovh(message, lieu)
# Suivi pour rappels
alertes_actives[nom_sonde] = maintenant
else:
# Alerte déjà en cours : vérifier s'il faut faire un rappel
dernier_envoi = alertes_actives.get(nom_sonde)
if dernier_envoi and (maintenant - dernier_envoi >= timedelta(hours=1)):
sujet = f"🔔 RAPPEL ALERTE TEMPÉRATURE - {nom_sonde} ({lieu})"
message = (
f"La sonde '{nom_sonde}' du site '{lieu}' est TOUJOURS en dépassement de seuil (>{seuil}°C).\n"
f"Heure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}"
)
destinataires_list = os.getenv("EMAIL_DESTINATAIRES").split(",")
envoyer_mail(sujet, message, destinataires_list)
if ENVOI_SMS:
envoyer_sms_ovh(message, lieu)
alertes_actives[nom_sonde] = maintenant
# Vérifier retour à la normale (Acquittement)
cursor.execute(f"""
SELECT Temperature FROM {table_temp}
WHERE Sonde = %s
ORDER BY Date DESC LIMIT 1
""", (nom_sonde,))
derniere = cursor.fetchone()
if derniere and derniere['Temperature'] <= seuil:
cursor.execute(f"""
UPDATE {table_alertes}
SET Status = 'Acquitté'
WHERE Sonde = %s AND Status IN ('En cours', 'Test')
""", (nom_sonde,))
# Nettoyage du suivi si normalisé
if nom_sonde in alertes_actives:
del alertes_actives[nom_sonde]
conn.commit()
cursor.close()
conn.close()
if log_entries:
import pandas as pd
df_logs = pd.DataFrame(log_entries)
# Sauvegarde principale
df_logs.to_csv(log_dir / "monitor.csv", sep=";", index=False)
# Sauvegarde secondaire (Linux uniquement)
if os.name != 'nt':
df_logs.to_csv("/var/log/monitor.csv", sep=";", index=False)
except Exception as e:
print(f"Erreur : {e}", flush=True)
# --- Boucle principale ---
while True:
print(f"📡 Vérification à {datetime.now()}", flush=True)
surveiller()
time.sleep(300) # 5 minutes

View File

@@ -9,3 +9,4 @@ schedule~=1.2.2
paramiko~=3.5.1 paramiko~=3.5.1
python-dotenv python-dotenv
bcrypt bcrypt
ovh

View File

@@ -1,10 +1,10 @@
import mysql.connector
from datetime import datetime, timedelta
import time
from dotenv import load_dotenv
import os import os
import time
from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
import ovh from db_utils import connect_to_mysql
from dotenv import load_dotenv
from utils_sms import envoyer_sms
if os.name != 'nt': if os.name != 'nt':
log_dir = Path('/home/debian/Gestion_sondes/Logs') log_dir = Path('/home/debian/Gestion_sondes/Logs')
@@ -16,45 +16,9 @@ log_dir.mkdir(parents=True, exist_ok=True)
load_dotenv() load_dotenv()
ENVOI_SMS = os.getenv("ENVOI_SMS") == "1" ENVOI_SMS = os.getenv("ENVOI_SMS") == "1"
# --- Config MySQL ---
config = {
"host": os.getenv("DB_HOST"),
"user": os.getenv("DB_USER"),
"password": os.getenv("DB_PASSWORD"),
"database": os.getenv("DB_NAME")
}
print("▶️ Lancement Monitor.py") print("▶️ Lancement Monitor.py")
# --- Fonction denvoi de SMS ---
def envoyer_sms_ovh(message, lieu):
client = ovh.Client(
endpoint=os.getenv("OVH_ENDPOINT"), # ex : 'ovh-eu'
application_key=os.getenv("OVH_APP_KEY"),
application_secret=os.getenv("OVH_APP_SECRET"),
consumer_key=os.getenv("OVH_CONSUMER_KEY"),
)
try:
services = client.get('/sms/')
if not services:
print("❌ Aucun service SMS OVH trouvé", flush=True)
return
service_name = services[0]
numero_dest = os.getenv("NUMERO_DESTINATAIRE")
result = client.post(f'/sms/{service_name}/jobs',
sender='Monitor',
message=message,
receivers=[numero_dest],
noStopClause=True
)
print(f"📱 SMS envoyé à {numero_dest} pour {lieu}. Job ID : {result['ids']}", flush=True)
except Exception as e:
print(f"Erreur envoi SMS : {e}", flush=True)
# --- Suivi des alertes actives pour rappels --- # --- Suivi des alertes actives pour rappels ---
alertes_actives = {} alertes_actives = {}
@@ -63,17 +27,17 @@ def surveiller():
global alertes_actives global alertes_actives
log_entries = [] log_entries = []
try: try:
conn = mysql.connector.connect(**config) conn = connect_to_mysql()
cursor = conn.cursor(dictionary=True) cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT DISTINCT Lieu FROM 'Chambres_froides'") cursor.execute("SELECT DISTINCT Lieu FROM `Chambres_froides`")
lieux = [row['Lieu'] for row in cursor.fetchall()] lieux = [row['Lieu'] for row in cursor.fetchall()]
for lieu in lieux: for lieu in lieux:
table_temp = lieu table_temp = lieu
table_alertes = f"Alertes_{lieu}" table_alertes = f"Alertes_{lieu}"
cursor.execute("SELECT Sonde, Temp_Max FROM 'Chambres_froides' WHERE Lieu=%s AND Etat='ON'", (lieu,)) cursor.execute("SELECT Sonde, Temp_Max FROM `Chambres_froides` WHERE Lieu=%s AND Etat='ON'", (lieu,))
sondes = cursor.fetchall() sondes = cursor.fetchall()
for sonde in sondes: for sonde in sondes:
@@ -120,7 +84,7 @@ def surveiller():
f"depuis plus de 30 minutes.\nHeure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}" f"depuis plus de 30 minutes.\nHeure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}"
) )
if ENVOI_SMS: if ENVOI_SMS:
envoyer_sms_ovh(message, lieu) envoyer_sms(message, lieu)
alertes_actives[nom_sonde] = maintenant alertes_actives[nom_sonde] = maintenant
@@ -132,7 +96,7 @@ def surveiller():
f"Heure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}" f"Heure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}"
) )
if ENVOI_SMS: if ENVOI_SMS:
envoyer_sms_ovh(message, lieu) envoyer_sms(message, lieu)
alertes_actives[nom_sonde] = maintenant alertes_actives[nom_sonde] = maintenant
# Vérifier retour à la normale (Acquittement) # Vérifier retour à la normale (Acquittement)

23
scripts/db_utils.py Normal file
View File

@@ -0,0 +1,23 @@
import mysql.connector
import os
import sys
import logging
def connect_to_mysql(db_name: str = None):
"""
Se connecte à MySQL. Par défaut, utilise la base spécifiée dans DB_NAME,
mais peut être redirigé vers une autre base en passant db_name.
"""
try:
sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages") # à ajuster si inutile
mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=db_name if db_name else os.getenv("DB_NAME")
)
logging.info(f"Connexion MySQL à la base {mydb.database} réussie.")
return mydb
except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1)

35
scripts/logger_config.py Normal file
View File

@@ -0,0 +1,35 @@
import os
import logging
def setup_logger(log_filename: str, dossier_logs: str = "/var/log/Cuisine_Saclay") -> None:
"""
Configure le logger pour écrire à la fois dans un fichier et sur la console.
:param log_filename: Nom du fichier de log (exemple : 'Cuisine_Saclay.log')
:param dossier_logs: Dossier où enregistrer les logs (par défaut : /var/log/Cuisine_Saclay)
"""
# 📁 Créer le dossier s'il n'existe pas
os.makedirs(dossier_logs, exist_ok=True)
# 📄 Chemin complet du fichier de log
logfile = os.path.join(dossier_logs, log_filename)
# 📝 Configuration de base du logger (fichier)
logging.basicConfig(
filename=logfile,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s",
filemode="a" # ajouter au fichier existant
)
# 🔔 Ajout de la sortie console
console = logging.StreamHandler()
console.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console.setFormatter(formatter)
# 👇 Ajouter le handler console au logger racine
logging.getLogger('').addHandler(console)
logging.info(f"Logger initialisé. Fichier de log : {logfile}")

49
scripts/mqtt_logger.py Normal file
View File

@@ -0,0 +1,49 @@
import argparse
import paho.mqtt.client as mqtt_client
from dotenv import load_dotenv
import logging
from logger_config import setup_logger
from db_utils import connect_to_mysql
from functools import partial
def on_message(table_sql, _client, _userdata, msg):
try:
logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
cursor = mydb.cursor()
sonde_name = '/'.join(msg.topic.split('/')[1:])
sql = f"INSERT INTO {table_sql} (Sonde, Temperature) VALUES (%s, %s)"
val = (sonde_name, msg.payload.decode())
cursor.execute(sql, val)
mydb.commit()
logging.info(f"Insertion réussie : {val}")
except Exception as e:
logging.error(f"Erreur lors de l'insertion du message : {e}")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--log", required=True, help="Nom du fichier de log")
parser.add_argument("--table", required=True, help="Nom complet de la table SQL")
parser.add_argument("--topic", required=True, help="Topic MQTT à écouter")
args = parser.parse_args()
# 📋 Initialiser le logger
setup_logger(args.log)
# 🔑 Charger les variables d'environnement
load_dotenv()
# 🔌 Connexion MySQL
mydb = connect_to_mysql()
# 📡 Connexion MQTT
try:
client = mqtt_client.Client()
client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
client.on_message = partial(on_message, args.table)
client.connect("54.36.188.119", 1883, 60)
client.subscribe(args.topic)
logging.info(f"Connexion MQTT réussie et abonnement au topic '{args.topic}'.")
client.loop_forever()
except Exception as err:
logging.error(f"Erreur MQTT : {err}")

View File

@@ -1,37 +0,0 @@
#!/bin/bash
LOG="/home/debian/Gestion_sondes/Logs/restart_services.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE] 🔄 Redémarrage des services Supervisor" >> $LOG
echo ""
echo "===== 🔄 DÉMARRAGE REDÉMARRAGE DES SERVICES ====="
echo ""
SERVICES=("Cuisine_Saclay" "Monitor" "cuisine_meudon" "Interface")
ALL_OK=true
for service in "${SERVICES[@]}"
do
echo "🔁 Redémarrage de $service..."
supervisorctl restart $service >> $LOG 2>&1
if [ $? -eq 0 ]; then
echo "$service redémarré avec succès."
else
echo "❌ Échec du redémarrage de $service."
ALL_OK=false
fi
done
DATE_END=$(date '+%Y-%m-%d %H:%M:%S')
echo "[$DATE_END] ✅ Tous les services ont été traités." >> $LOG
echo ""
if $ALL_OK; then
echo "🎉 Tous les services ont été redémarrés avec succès !"
else
echo "⚠️ Certains services n'ont pas pu être redémarrés. Vérifiez le log :"
echo "$LOG"
fi
echo ""
echo "===== ✅ FIN DU SCRIPT ====="

View File

@@ -1,12 +0,0 @@
#!/bin/bash
echo "===== STATUS DES APPS SUPERVISÉES ====="
supervisorctl status
echo ""
echo "===== UTILISATION MÉMOIRE DES PROCESS STREAMLIT ====="
ps aux | grep streamlit | grep -v grep | awk '{printf "%-8s %-6s %-6s %-6s %s\n", $1, $2, $4, $3, $11" "$12" "$13" "$14" "$15" "$16" "$17" "$18}' | awk 'BEGIN { print "USER PID %MEM %CPU CMD" } { print }'
echo ""
echo "===== PORTS UTILISÉS PAR STREAMLIT ====="
ss -tlnp | grep streamlit | awk '{print $4 " <- " $7}' | sed 's/.*://;s/,.*//'

View File

@@ -36,7 +36,7 @@ if envoyer_mail:
try: try:
with smtplib.SMTP_SSL("smtp.mail.ovh.net", 465) as server: with smtplib.SMTP_SSL("smtp.mail.ovh.net", 465) as server:
server.login("supervisor@domo91.fr", "4j%6A63$F##x7h") server.login("services@domo91.fr", "6ZiCsVtSf9@nEHv@$^0")
server.sendmail(msg["From"], [msg["To"]], msg.as_string()) server.sendmail(msg["From"], [msg["To"]], msg.as_string())
print("📧 Mail envoyé.") print("📧 Mail envoyé.")
except Exception as e: except Exception as e:

View File

@@ -1,19 +1,31 @@
#!/home/debian/Gestion_sondes/myenv/bin/python3 #!/home/debian/Gestion_sondes/myenv/bin/python3
import mysql.connector
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
import ovh import db_utils
import logging
from utils_sms import envoyer_sms
# Dossier Logs
LOG_DIR = '/home/debian/Gestion_sondes/Logs'
os.makedirs(LOG_DIR, exist_ok=True)
# Fichier de log (nommé par date)
log_filename = os.path.join(LOG_DIR, datetime.now().strftime("surveillance_%Y-%m-%d.log"))
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler(log_filename),
logging.StreamHandler() # Affiche aussi les logs dans la console
]
)
# Charger .env # Charger .env
load_dotenv('/home/debian/Gestion_sondes/.env') load_dotenv('/home/debian/Gestion_sondes/.env')
# MySQL
MYSQL_HOST = os.getenv('DB_HOST')
MYSQL_USER = os.getenv('DB_USER')
MYSQL_PASSWORD = os.getenv('DB_PASSWORD')
MYSQL_DB = os.getenv('DB_NAME')
# OVH SMS # OVH SMS
APP_KEY = os.getenv('OVH_APP_KEY') APP_KEY = os.getenv('OVH_APP_KEY')
APP_SECRET = os.getenv('OVH_APP_SECRET') APP_SECRET = os.getenv('OVH_APP_SECRET')
@@ -22,34 +34,26 @@ SERVICE_NAME = os.getenv('OVH_SERVICE_NAME')
SMS_RECEIVER = os.getenv('SMS_RECEIVER') SMS_RECEIVER = os.getenv('SMS_RECEIVER')
SMS_SENDER = os.getenv('OVH_SMS_SENDER') SMS_SENDER = os.getenv('OVH_SMS_SENDER')
# Tables à surveiller tables = ['Saclay', 'Meudon', 'Chaufferie']
tables = ['Saclay', 'Meudon'] # ajoute tes sites ici
# seuils
DELAI_MINUTES = 15 DELAI_MINUTES = 15
RAPPEL_HEURES = 6 RAPPEL_HEURES = 6
# Dossier pour mémoriser les états
STATE_DIR = '/tmp/surveillance_states' STATE_DIR = '/tmp/surveillance_states'
os.makedirs(STATE_DIR, exist_ok=True) os.makedirs(STATE_DIR, exist_ok=True)
def should_send_alert(site): def should_send_alert(site):
state_file = os.path.join(STATE_DIR, f'{site}.state') state_file = os.path.join(STATE_DIR, f'{site}.state')
now = datetime.now() now = datetime.now()
if not os.path.exists(state_file): if not os.path.exists(state_file):
with open(state_file, 'w') as f: with open(state_file, 'w') as f:
f.write(now.isoformat()) f.write(now.isoformat())
return True return True
with open(state_file, 'r') as f: with open(state_file, 'r') as f:
last_alert = datetime.fromisoformat(f.read().strip()) last_alert = datetime.fromisoformat(f.read().strip())
if now - last_alert >= timedelta(hours=RAPPEL_HEURES): if now - last_alert >= timedelta(hours=RAPPEL_HEURES):
with open(state_file, 'w') as f: with open(state_file, 'w') as f:
f.write(now.isoformat()) f.write(now.isoformat())
return True return True
return False return False
def clear_state(site): def clear_state(site):
@@ -57,29 +61,8 @@ def clear_state(site):
if os.path.exists(state_file): if os.path.exists(state_file):
os.remove(state_file) os.remove(state_file)
def envoyer_sms(message):
client = ovh.Client(
endpoint='ovh-eu',
application_key=APP_KEY,
application_secret=APP_SECRET,
consumer_key=CONSUMER_KEY,
)
result = client.post(f'/sms/{SERVICE_NAME}/jobs',
receivers=[SMS_RECEIVER],
message=message,
priority='high',
sender=SMS_SENDER
)
print("🚨 SMS envoyé :", result)
def main(): def main():
cnx = mysql.connector.connect( cnx = db_utils.connect_to_mysql() # ← appel via db_utils
host=MYSQL_HOST,
user=MYSQL_USER,
password=MYSQL_PASSWORD,
database=MYSQL_DB
)
cursor = cnx.cursor() cursor = cnx.cursor()
now = datetime.now() now = datetime.now()
@@ -95,15 +78,16 @@ def main():
if should_send_alert(table): if should_send_alert(table):
problemes.append(f"{table} (dernier relevé : {last_update})") problemes.append(f"{table} (dernier relevé : {last_update})")
else: else:
print(f"⏳ Problème déjà signalé pour {table}, attente du délai de rappel.") logging.info(f"⏳ Problème déjà signalé pour {table}, attente du délai de rappel.")
else: else:
if os.path.exists(os.path.join(STATE_DIR, f'{table}.state')): if os.path.exists(os.path.join(STATE_DIR, f'{table}.state')):
message = f"{table} : relevés à nouveau reçus. Situation normale." message = f"{table} : relevés à nouveau reçus. Situation normale."
envoyer_sms(message) envoyer_sms(message)
clear_state(table) clear_state(table)
print(f"📩 SMS de retour à la normale envoyé pour {table}.") logging.info(f"📩 SMS de retour à la normale envoyé pour {table}.")
else: else:
print(f"{table} OK (dernier relevé : {last_update})") logging.info(f"{table} OK (dernier relevé : {last_update})")
cursor.close() cursor.close()
cnx.close() cnx.close()
@@ -111,7 +95,7 @@ def main():
message = "⚠️ ALERTE : pas de relevés depuis >15min :\n" + "\n".join(problemes) message = "⚠️ ALERTE : pas de relevés depuis >15min :\n" + "\n".join(problemes)
envoyer_sms(message) envoyer_sms(message)
else: else:
print("👍 Tout est OK, aucun SMS envoyé.") logging.info("👍 Tout est OK, aucun SMS envoyé.")
if __name__ == "__main__": if __name__ == "__main__":
main() main()

34
scripts/utils_sms.py Normal file
View File

@@ -0,0 +1,34 @@
import os
import ovh
from dotenv import load_dotenv
load_dotenv()
def envoyer_sms(message: str, lieu: str = ""):
try:
client = ovh.Client(
endpoint=os.getenv("OVH_ENDPOINT"),
application_key=os.getenv("OVH_APP_KEY"),
application_secret=os.getenv("OVH_APP_SECRET"),
consumer_key=os.getenv("OVH_CONSUMER_KEY"),
)
services = client.get('/sms/')
if not services:
print("❌ Aucun service SMS OVH trouvé", flush=True)
return
service_name = services[0]
numero_dest = os.getenv("NUMERO_DESTINATAIRE")
result = client.post(f'/sms/{service_name}/jobs',
sender='Monitor',
message=message,
receivers=[numero_dest],
noStopClause=True
)
print(f"📱 SMS envoyé à {numero_dest} pour {lieu}. Job ID : {result['ids']}", flush=True)
except Exception as e:
print(f"Erreur envoi SMS : {e}", flush=True)

View File

@@ -1,100 +0,0 @@
import mysql.connector
import os
from dotenv import load_dotenv
load_dotenv()
def lire_alertes_sondes():
conn = None
cursor = None
try:
conn = get_connection()
cursor = conn.cursor(dictionary=True)
cursor.execute("SELECT * FROM Alertes_Chaufferie ORDER BY Debut_defaut DESC")
return cursor.fetchall()
except Exception as e:
import streamlit as st
st.warning(f"Erreur lecture alertes : {e}")
return []
finally:
if cursor:
cursor.close()
if conn and conn.is_connected():
conn.close()
def acquitter_alerte(id_alerte):
conn = None
cursor = None
try:
conn = get_connection()
cursor = conn.cursor()
cursor.execute("UPDATE Alertes_Chaufferie SET Etat = 'Acquitté' WHERE Id = %s", (id_alerte,))
conn.commit()
except Exception as e:
import streamlit as st
st.warning(f"Erreur lors de l'acquittement : {e}")
finally:
if cursor:
cursor.close()
if conn and conn.is_connected():
conn.close()
def verifier_utilisateur_commun(login, password):
conn = get_connection()
cursor = conn.cursor(dictionary=True)
query = """
SELECT NomUtilisateur FROM Commun.AccesUtilisateurs
WHERE NomUtilisateur = %s
AND MotDePasse = %s
AND (DateExpiration IS NULL OR DateExpiration >= CURDATE())
"""
cursor.execute(query, (login, password))
user = cursor.fetchone()
cursor.close()
conn.close()
return user # None si non trouvée
def get_connection():
return mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=os.getenv("DB_NAME")
)
def get_latest_chaufferie():
conn = get_connection()
cursor = conn.cursor(dictionary=True)
query = """
SELECT c1.Sonde, c1.Temperature, c1.Date, c1.Topic
FROM Chaufferie c1
INNER JOIN (
SELECT Sonde, MAX(Date) AS MaxDate
FROM Chaufferie
GROUP BY Sonde
) c2 ON c1.Sonde = c2.Sonde AND c1.Date = c2.MaxDate
ORDER BY c1.Topic, c1.Sonde
"""
cursor.execute(query)
data = cursor.fetchall()
cursor.close()
conn.close()
return data
def get_history_by_sonde(sonde_name):
conn = get_connection()
cursor = conn.cursor(dictionary=True)
query = """
SELECT Date, Temperature
FROM Chaufferie
WHERE Sonde = %s AND Date >= NOW() - INTERVAL 1 DAY
ORDER BY Date ASC
"""
cursor.execute(query, (sonde_name,))
data = cursor.fetchall()
cursor.close()
conn.close()
return data