import streamlit as st import pandas as pd import mysql.connector from utils.db import ( get_latest_chaufferie, get_history_by_sonde, verifier_utilisateur_commun, lire_alertes_sondes, acquitter_alerte ) import altair as alt from dotenv import load_dotenv import os st.set_page_config(page_title="Tech Chaufferie", layout="wide") load_dotenv() # charger .env à la racine du projet # Accès aux variables d'environnement MYSQL_HOST = os.getenv("DB_HOST") MYSQL_USER = os.getenv("DB_USER") MYSQL_PASSWORD = os.getenv("DB_PASSWORD") MYSQL_DATABASE = os.getenv("DB_NAME") def login_commun(): login = st.text_input("Identifiant", type="default") password = st.text_input("Mot de passe", type="password") if st.button("Se connecter"): user = verifier_utilisateur_commun(login, password) if user: st.session_state["authenticated"] = True st.session_state["utilisateur"] = user["NomUtilisateur"] st.success("✅ Connexion réussie") st.rerun() else: st.error("❌ Identifiants incorrects ou expirés") # Authentification if "authenticated" not in st.session_state: st.session_state["authenticated"] = False if not st.session_state["authenticated"]: st.title("🔧 Suivi des sondes de la chaufferie") st.subheader("🔐 Connexion technicien chaufferie") login_commun() st.stop() with st.sidebar: st.markdown(f"👤 Connecté en tant que **{st.session_state['utilisateur']}**") if st.button("🔓 Se déconnecter"): st.session_state.clear() st.rerun() # --- Affichage principal --- st.title("🔧 Suivi des sondes de la chaufferie") data = get_latest_chaufferie() df = pd.DataFrame(data) # Ajout d'un statut couleur def statut(temp): if temp > 75: return "❌ Très chaud" elif temp > 60: return "⚠️ Surveiller" else: return "✅ OK" df["Statut"] = df["Temperature"].apply(statut) # Séparer par topic for topic in df["Topic"].unique(): st.subheader(f"Zone : {topic}") st.dataframe(df[df["Topic"] == topic][["Sonde", "Temperature", "Date", "Statut"]], use_container_width=True) # Graphique historique st.markdown("---") st.header("📈 Historique par sonde (24h)") # Ce bloc doit exister pour que sonde_selection soit défini sonde_selection = st.selectbox("Choisir une sonde à afficher", df["Sonde"].unique()) if sonde_selection: historique = get_history_by_sonde(sonde_selection) if historique: df_hist = pd.DataFrame(historique) df_hist["Date"] = pd.to_datetime(df_hist["Date"]) df_hist["Temperature"] = pd.to_numeric(df_hist["Temperature"], errors="coerce") # ✅ Message si -127°C détecté if (df_hist["Temperature"] <= -126).any(): st.error("🚨 Sonde défaillante détectée (-127°C). Vérification urgente requise.") # ✅ Ligne limite (modifiable ici) limite = 80 ligne_limite = alt.Chart(pd.DataFrame({ "y": [limite] })).mark_rule(color="red").encode(y="y") # ✅ Points rouge si erreur (-127°C) alerte_sonde = alt.Chart(df_hist[df_hist["Temperature"] <= -126]).mark_point( shape="cross", color="red", size=100 ).encode( x="Date:T", y="Temperature:Q", tooltip=["Date:T", "Temperature:Q"] ) # Insérer une alerte dans Mysql en cas de sonde défectueuse def inserer_alerte_defaut_sonde(sonde): conn = None cursor = None try: conn = mysql.connector.connect( host=MYSQL_HOST, user=MYSQL_USER, password=MYSQL_PASSWORD, database=MYSQL_DATABASE ) cursor = conn.cursor() # Vérifie s'il existe déjà une alerte en cours query_check = """ SELECT COUNT(*) FROM Alertes_Chaufferie WHERE Sonde = %s AND Etat = 'En cours' """ cursor.execute(query_check, (sonde,)) count = cursor.fetchone()[0] if count == 0: # Date du premier -127°C détecté date_defaut = df_hist[df_hist["Temperature"] <= -126]["Date"].min() query_insert = """ INSERT INTO Alertes_Chaufferie (Sonde, Debut_defaut, Etat) VALUES (%s, %s, 'En cours') """ cursor.execute(query_insert, (sonde, date_defaut)) conn.commit() except Exception as e: st.warning(f"⚠️ Erreur enregistrement alerte : {e}") finally: if cursor: cursor.close() if conn and conn.is_connected(): conn.close() # 🔁 Appel de la fonction si -127 détecté if (df_hist["Temperature"] <= -126).any(): inserer_alerte_defaut_sonde(sonde_selection, df_hist["Date"].min()) # ✅ Graphique principal chart = alt.Chart(df_hist).mark_line().encode( x=alt.X("Date:T", title="Date"), y=alt.Y("Temperature:Q", title="Température (°C)", scale=alt.Scale(domain=[-130, 100])), tooltip=["Date:T", "Temperature:Q"] ).properties( width=900, height=400, title=f"Évolution sur 24h de {sonde_selection}" ) st.altair_chart(chart + ligne_limite + alerte_sonde, use_container_width=True) else: st.info("Aucune donnée disponible pour cette sonde dans les dernières 24h.") st.markdown("---") st.header("🧯 Alertes sondes défaillantes") alertes = lire_alertes_sondes() if alertes: for alerte in alertes: col1, col2, col3, col4 = st.columns([3, 3, 2, 2]) col1.markdown(f"**Sonde :** {alerte['Sonde']}") col2.markdown(f"**Défaut depuis :** {alerte['Debut_defaut'].strftime('%Y-%m-%d %H:%M')}") col3.markdown(f"**État :** :orange[{alerte['Etat']}]") if alerte['Etat'] != 'Acquitté': if col4.button("✅ Acquitter", key=f"acquitter_{alerte['Id']}"): acquitter_alerte(alerte['Id']) st.rerun() else: st.success("Aucune alerte active.")