Files
Gestion_sondes/Monitor.py
2025-07-23 10:46:27 +02:00

176 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import mysql.connector
from datetime import datetime, timedelta
import time
from dotenv import load_dotenv
import os
from pathlib import Path
import ovh
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")
}
print("▶️ Lancement Monitor.py")
# --- Fonction denvoi de SMS ---
def envoyer_sms_ovh(message, lieu):
client = ovh.Client(
endpoint=os.getenv("OVH_ENDPOINT"), # ex : 'ovh-eu'
application_key=os.getenv("OVH_APP_KEY"),
application_secret=os.getenv("OVH_APP_SECRET"),
consumer_key=os.getenv("OVH_CONSUMER_KEY"),
)
try:
services = client.get('/sms/')
if not services:
print("❌ Aucun service SMS OVH trouvé", flush=True)
return
service_name = services[0]
numero_dest = os.getenv("NUMERO_DESTINATAIRE")
result = client.post(f'/sms/{service_name}/jobs',
sender='Monitor',
message=message,
receivers=[numero_dest],
noStopClause=True
)
print(f"📱 SMS envoyé à {numero_dest} pour {lieu}. Job ID : {result['ids']}", flush=True)
except Exception as e:
print(f"Erreur envoi SMS : {e}", flush=True)
# --- Suivi des alertes actives pour rappels ---
alertes_actives = {}
# --- 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)
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')}"
)
if ENVOI_SMS:
envoyer_sms_ovh(message, lieu)
alertes_actives[nom_sonde] = maintenant
else:
dernier_envoi = alertes_actives.get(nom_sonde)
if dernier_envoi and (maintenant - dernier_envoi >= timedelta(hours=1)):
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')}"
)
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,))
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)
df_logs.to_csv(log_dir / "monitor.csv", sep=";", index=False)
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