Files
Gestion_sondes/scripts/Technique.py
2025-07-26 10:04:07 +02:00

183 lines
6.2 KiB
Python

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.")