176 lines
6.4 KiB
Python
176 lines
6.4 KiB
Python
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 d’envoi 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
|