diff --git a/app/Monitor_Meudon.py b/app/Monitor_Meudon.py index 510109b..04268c6 100644 --- a/app/Monitor_Meudon.py +++ b/app/Monitor_Meudon.py @@ -24,7 +24,6 @@ import time from datetime import datetime from email.message import EmailMessage from zoneinfo import ZoneInfo - from dotenv import load_dotenv, find_dotenv # ========= .env (une seule fois) ========= diff --git a/app/domo91.py b/app/domo91.py index e21612d..51476c0 100644 --- a/app/domo91.py +++ b/app/domo91.py @@ -9,7 +9,7 @@ import matplotlib.dates as mdates import matplotlib.pyplot as plt import mysql.connector import pandas as pd - +import numpy as np pd.set_option("future.no_silent_downcasting", True) import streamlit as st from PIL import Image @@ -820,7 +820,7 @@ if st.session_state.get("authenticated"): pass # ========================================================= -# Navigation + Pages (CORRIGÉ : pour superviseur ET utilisateur) +# Navigation + Pages # ========================================================= if st.session_state.get("authenticated"): @@ -972,6 +972,7 @@ if st.session_state.get("authenticated"): st.text(traceback.format_exc()) # ------------------ Statistiques ------------------ + elif onglet_selectionne == "Statistiques": st.markdown("## 📈 Statistiques de température") @@ -1000,14 +1001,48 @@ if st.session_state.get("authenticated"): sondes = sorted(df["Sonde"].unique()) sonde = st.selectbox("Choisir une sonde :", sondes, key="selectbox_stats") df_sonde = df[df["Sonde"] == sonde] - + # Récupérer Temp_Max pour cette sonde (si définie) + seuil = None + try: + with closing(get_connection()) as conn_thr, closing(conn_thr.cursor(dictionary=True)) as cur_thr: + cur_thr.execute( + "SELECT Temp_Max FROM Sondes.Chambres_froides WHERE Lieu = %s AND Sonde = %s", + (site, sonde), + ) + row_thr = cur_thr.fetchone() + if row_thr: + seuil = float(row_thr["Temp_Max"]) + except Exception as e: + st.warning(f"Impossible de récupérer le seuil pour {sonde} : {e}") st.subheader("Évolution journalière") fig, ax = plt.subplots(figsize=(10, 4)) - ax.plot(df_sonde["Date"], df_sonde["Temperature"], marker="o") + + dates = df_sonde["Date"] + temp = df_sonde["Temperature"] + + if seuil is None: + # Pas de seuil trouvé : tracé classique + ax.plot(dates, temp, marker="o") + else: + # On sépare les valeurs normales et excessives + temp_ok = temp.where(temp <= seuil, np.nan) + temp_high = temp.where(temp > seuil, np.nan) + + # Courbe normale + ax.plot(dates, temp_ok, marker="o") + + # Partie excessive en rouge + ax.plot(dates, temp_high, marker="o", color="red") + + # Ligne horizontale du seuil (optionnel mais très parlant) + ax.axhline(seuil, linestyle="--", linewidth=1) + ax.text(dates.iloc[0], seuil, f" Seuil {seuil}°C", va="bottom") + ax.set_title(f"{sonde} - {date_val.strftime('%d/%m/%Y')}") ax.set_xlabel("Heure") ax.set_ylabel("Température (°C)") ax.xaxis.set_major_formatter(mdates.DateFormatter("%H:%M")) + st.pyplot(fig) except Exception as e: @@ -1022,13 +1057,18 @@ if st.session_state.get("authenticated"): try: with closing(get_connection()) as conn_admin, closing( - conn_admin.cursor(dictionary=True)) as cursor_admin: - cursor_admin.execute("SELECT * FROM Sondes.Chambres_froides WHERE Lieu = %s", (site,)) + conn_admin.cursor(dictionary=True) + ) as cursor_admin: + cursor_admin.execute( + "SELECT * FROM Sondes.Chambres_froides WHERE Lieu = %s", (site,) + ) chambres = cursor_admin.fetchall() if not chambres: st.warning("Aucune chambre froide pour ce site.") else: + table_alertes = f"Alertes_{site}" + for chambre in chambres: col1, col2, col3 = st.columns([3, 1, 2]) with col1: @@ -1057,14 +1097,35 @@ if st.session_state.get("authenticated"): if st.button("▲", key=f"plus_{chambre['Id']}"): temp_max += 1 + # Si quelque chose a changé (état ou Temp_Max) if new_etat != chambre["Etat"] or temp_max != chambre["Temp_Max"]: + # 1) Mise à jour de la chambre froide cursor_admin.execute( - "UPDATE Sondes.Chambres_froides SET Etat = %s, Temp_Max = %s WHERE Id = %s", + "UPDATE Sondes.Chambres_froides " + "SET Etat = %s, Temp_Max = %s WHERE Id = %s", (new_etat, temp_max, chambre["Id"]), ) conn_admin.commit() st.success(f"{chambre['Sonde']} mise à jour") + # 2) Si on vient de passer la chambre à OFF → acquitter les alertes + if new_etat == "OFF": + try: + cursor_admin.execute( + f"UPDATE Sondes.`{table_alertes}` " + "SET Etat = 'Acquitté' " + "WHERE Sonde = %s AND Etat <> 'Acquitté'", + (chambre["Sonde"],), + ) + conn_admin.commit() + st.info( + f"Toutes les alertes en cours pour {chambre['Sonde']} ont été acquittées." + ) + except Exception as e_alert: + st.error( + f"Erreur lors de l'acquittement des alertes pour {chambre['Sonde']} : {e_alert}" + ) + except Exception as e: st.error(f"Erreur SQL (admin) : {e}") st.text(traceback.format_exc()) diff --git a/app/utils_db.py b/app/utils_db.py deleted file mode 100644 index d355df8..0000000 --- a/app/utils_db.py +++ /dev/null @@ -1,73 +0,0 @@ -import mysql.connector -from dotenv import load_dotenv -import os - -load_dotenv() - - -def connect_to_mysql(): - return mysql.connector.connect( - host=os.getenv("DB_HOST"), - user=os.getenv("DB_USER"), - password=os.getenv("DB_PASS"), - database=os.getenv("DB_NAME") - ) - - -def get_latest_chaufferie(): - conn = connect_to_mysql() - cursor = conn.cursor(dictionary=True) - query = """ - SELECT Sonde, Temperature, Date, Topic - FROM Sondes.Chaufferie - WHERE Date >= NOW() - INTERVAL 5 MINUTE - ORDER BY Date DESC \ - """ - cursor.execute(query) - result = cursor.fetchall() - cursor.close() - conn.close() - return result - - -def get_history_by_sonde(sonde): - conn = connect_to_mysql() - cursor = conn.cursor(dictionary=True) - query = """ - SELECT Sonde, Temperature, Date - FROM Sondes.Chaufferie - WHERE Sonde = %s - AND Date >= NOW() - INTERVAL 1 DAY \ - - """ - cursor.execute(query, (sonde,)) - result = cursor.fetchall() - cursor.close() - conn.close() - return result - - -def lire_alertes_sondes(): - conn = connect_to_mysql() - cursor = conn.cursor(dictionary=True) - query = """ - SELECT Id, Sonde, Debut_defaut, Etat - FROM Sondes.Alertes_Chaufferie - WHERE Etat != 'Acquitté' - ORDER BY Debut_defaut DESC \ - """ - cursor.execute(query) - result = cursor.fetchall() - cursor.close() - conn.close() - return result - - -def acquitter_alerte(id_alerte): - conn = connect_to_mysql() - cursor = conn.cursor() - query = "UPDATE Sondes.Alertes_Chaufferie SET Etat = 'Acquitté' WHERE Id = %s" - cursor.execute(query, (id_alerte,)) - conn.commit() - cursor.close() - conn.close()