🧩 Merge auto develop → product
This commit is contained in:
35
Monitor.py
35
Monitor.py
@@ -1,4 +1,4 @@
|
|||||||
# Surveillance continue avec envoi d'alertes par email + log CSV
|
# Surveillance continue avec envoi d'alertes par email + rappels + log CSV
|
||||||
import mysql.connector
|
import mysql.connector
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import time
|
import time
|
||||||
@@ -19,7 +19,10 @@ config = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# --- Destinataires email ---
|
# --- Destinataires email ---
|
||||||
destinataires = ['services@domo91.fr,cuisine@bw-paris-saclay.com>']
|
destinataires = ['services@domo91.fr', 'michel-68000@hotmail.fr']
|
||||||
|
|
||||||
|
# --- Suivi des alertes actives pour rappels ---
|
||||||
|
alertes_actives = {}
|
||||||
|
|
||||||
# --- Fonction d'envoi de mail ---
|
# --- Fonction d'envoi de mail ---
|
||||||
def envoyer_mail(sujet, message, destinataires):
|
def envoyer_mail(sujet, message, destinataires):
|
||||||
@@ -37,6 +40,7 @@ def envoyer_mail(sujet, message, destinataires):
|
|||||||
|
|
||||||
# --- Fonction de surveillance ---
|
# --- Fonction de surveillance ---
|
||||||
def surveiller():
|
def surveiller():
|
||||||
|
global alertes_actives
|
||||||
log_entries = []
|
log_entries = []
|
||||||
try:
|
try:
|
||||||
conn = mysql.connector.connect(**config)
|
conn = mysql.connector.connect(**config)
|
||||||
@@ -63,7 +67,6 @@ def surveiller():
|
|||||||
""", (nom_sonde,))
|
""", (nom_sonde,))
|
||||||
relevés = cursor.fetchall()
|
relevés = cursor.fetchall()
|
||||||
|
|
||||||
# Log CSV : tous les relevés analysés
|
|
||||||
for r in relevés:
|
for r in relevés:
|
||||||
log_entries.append({
|
log_entries.append({
|
||||||
"Date": r['Date'],
|
"Date": r['Date'],
|
||||||
@@ -91,14 +94,30 @@ def surveiller():
|
|||||||
(nom_sonde,)
|
(nom_sonde,)
|
||||||
)
|
)
|
||||||
print(f"🚨 Alerte déclenchée pour {nom_sonde} ({lieu})", flush=True)
|
print(f"🚨 Alerte déclenchée pour {nom_sonde} ({lieu})", flush=True)
|
||||||
|
|
||||||
sujet = f"🚨 ALERTE TEMPÉRATURE - {nom_sonde} ({lieu})"
|
sujet = f"🚨 ALERTE TEMPÉRATURE - {nom_sonde} ({lieu})"
|
||||||
message = (
|
message = (
|
||||||
f"La sonde '{nom_sonde}' du site '{lieu}' a dépassé le seuil de {seuil}°C "
|
f"La sonde '{nom_sonde}' du site '{lieu}' a dépassé le seuil de {seuil}°C "
|
||||||
f"depuis plus de 30 minutes.\nHeure : {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
|
f"depuis plus de 30 minutes.\nHeure : {maintenant.strftime('%Y-%m-%d %H:%M:%S')}"
|
||||||
)
|
)
|
||||||
envoyer_mail(sujet, message, destinataires)
|
envoyer_mail(sujet, message, destinataires)
|
||||||
|
|
||||||
# Acquittement automatique
|
# 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')}"
|
||||||
|
)
|
||||||
|
envoyer_mail(sujet, message, destinataires)
|
||||||
|
alertes_actives[nom_sonde] = maintenant
|
||||||
|
|
||||||
|
# Vérifier retour à la normale (Acquittement)
|
||||||
cursor.execute(f"""
|
cursor.execute(f"""
|
||||||
SELECT Temperature FROM {table_temp}
|
SELECT Temperature FROM {table_temp}
|
||||||
WHERE Sonde = %s
|
WHERE Sonde = %s
|
||||||
@@ -112,11 +131,14 @@ def surveiller():
|
|||||||
WHERE Sonde = %s AND Status IN ('En cours', 'Test')
|
WHERE Sonde = %s AND Status IN ('En cours', 'Test')
|
||||||
""", (nom_sonde,))
|
""", (nom_sonde,))
|
||||||
|
|
||||||
|
# Nettoyage du suivi si normalisé
|
||||||
|
if nom_sonde in alertes_actives:
|
||||||
|
del alertes_actives[nom_sonde]
|
||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
|
|
||||||
# Enregistrer le log
|
|
||||||
if log_entries:
|
if log_entries:
|
||||||
df_logs = pd.DataFrame(log_entries)
|
df_logs = pd.DataFrame(log_entries)
|
||||||
df_logs.to_csv("/home/debian/travail/Logs/monitor.csv", sep=";", index=False)
|
df_logs.to_csv("/home/debian/travail/Logs/monitor.csv", sep=";", index=False)
|
||||||
@@ -129,3 +151,4 @@ while True:
|
|||||||
print(f"📡 Vérification à {datetime.now()}", flush=True)
|
print(f"📡 Vérification à {datetime.now()}", flush=True)
|
||||||
surveiller()
|
surveiller()
|
||||||
time.sleep(300) # 5 minutes
|
time.sleep(300) # 5 minutes
|
||||||
|
|
||||||
|
|||||||
@@ -291,7 +291,7 @@ if st.session_state["authenticated"]:
|
|||||||
st.session_state["selected_date"] = selected_date
|
st.session_state["selected_date"] = selected_date
|
||||||
|
|
||||||
cursor.execute(
|
cursor.execute(
|
||||||
f"SELECT * FROM `{site_selectionne}` WHERE DATE(Date) = %s ORDER BY Sonde, Date",
|
f"SELECT * FROM `{site_selectionne}` WHERE DATE(Date) = %s ORDER BY Sonde, Date DESC",
|
||||||
(selected_date.strftime("%Y-%m-%d"),)
|
(selected_date.strftime("%Y-%m-%d"),)
|
||||||
)
|
)
|
||||||
rows = cursor.fetchall()
|
rows = cursor.fetchall()
|
||||||
|
|||||||
@@ -9,35 +9,53 @@ load_dotenv()
|
|||||||
HOST = os.getenv("SSH_HOST")
|
HOST = os.getenv("SSH_HOST")
|
||||||
USER = os.getenv("SSH_USER")
|
USER = os.getenv("SSH_USER")
|
||||||
KEY = os.getenv("SSH_KEY")
|
KEY = os.getenv("SSH_KEY")
|
||||||
|
PASSPHRASE = os.getenv("SSH_KEY_PASSPHRASE")
|
||||||
|
|
||||||
|
root = tk.Tk()
|
||||||
|
root.withdraw()
|
||||||
|
|
||||||
|
# 🛡 Vérifie que le fichier existe
|
||||||
|
if not os.path.exists(KEY):
|
||||||
|
messagebox.showerror("❌ Erreur", f"Clé SSH introuvable :\n{KEY}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# 🛡 Vérifie que la clé est lisible par paramiko
|
||||||
|
try:
|
||||||
|
paramiko.RSAKey.from_private_key_file(KEY, password=PASSPHRASE)
|
||||||
|
except paramiko.PasswordRequiredException:
|
||||||
|
messagebox.showerror("❌ Clé protégée", "La clé est protégée par une passphrase, mais aucune n'a été fournie.")
|
||||||
|
exit(1)
|
||||||
|
except paramiko.SSHException:
|
||||||
|
messagebox.showerror("❌ Erreur de format", "Le fichier de clé n’est pas au format OpenSSH.\n\nSolution : Exporter depuis PuTTYgen → Conversions > Export OpenSSH key")
|
||||||
|
exit(1)
|
||||||
|
except Exception as e:
|
||||||
|
messagebox.showerror("❌ Autre erreur", f"{e}")
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
# ✅ Si la clé est valide, on continue
|
||||||
client = paramiko.SSHClient()
|
client = paramiko.SSHClient()
|
||||||
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
||||||
|
|
||||||
try:
|
try:
|
||||||
client.connect(hostname=HOST, username=USER, key_filename=KEY)
|
client.connect(
|
||||||
|
hostname=HOST,
|
||||||
|
username=USER,
|
||||||
|
key_filename=KEY,
|
||||||
|
passphrase=PASSPHRASE
|
||||||
|
)
|
||||||
|
|
||||||
stdin, stdout, stderr = client.exec_command("bash ~/travail/Gestion_sondes/scripts/deploy_all.sh")
|
stdin, stdout, stderr = client.exec_command("bash ~/travail/Gestion_sondes/scripts/deploy_all.sh")
|
||||||
|
|
||||||
output = stdout.read().decode()
|
output = stdout.read().decode()
|
||||||
errors = stderr.read().decode()
|
errors = stderr.read().decode()
|
||||||
|
|
||||||
if "Déploiement complet terminé avec succès" in output:
|
if "Déploiement complet terminé avec succès" in output:
|
||||||
success = True
|
messagebox.showinfo("✅ Déploiement réussi", "Le déploiement s'est bien déroulé.")
|
||||||
else:
|
else:
|
||||||
success = False
|
messagebox.showwarning("⚠️ Déploiement incomplet", f"Vérifie les logs :\n\n{errors}")
|
||||||
|
|
||||||
# Affichage de la notification visuelle
|
|
||||||
root = tk.Tk()
|
|
||||||
root.withdraw() # cache la fenêtre principale
|
|
||||||
|
|
||||||
if success:
|
|
||||||
messagebox.showinfo("Déploiement terminé", "✅ Le déploiement s'est bien déroulé !")
|
|
||||||
else:
|
|
||||||
messagebox.showwarning("Déploiement partiel", f"⚠️ Déploiement incomplet. Vérifiez les logs.\n\n{errors}")
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
root = tk.Tk()
|
messagebox.showerror("❌ Erreur SSH", f"{e}")
|
||||||
root.withdraw()
|
|
||||||
messagebox.showerror("Erreur SSH", f"❌ Erreur : {e}")
|
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
client.close()
|
client.close()
|
||||||
|
|||||||
Reference in New Issue
Block a user