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