diff --git a/.idea/.gitignore b/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/.idea/.name b/.idea/.name
new file mode 100644
index 0000000..2da3cfe
--- /dev/null
+++ b/.idea/.name
@@ -0,0 +1 @@
+Général.py
\ No newline at end of file
diff --git a/.idea/Gestion sondes.iml b/.idea/Gestion sondes.iml
new file mode 100644
index 0000000..2c80e12
--- /dev/null
+++ b/.idea/Gestion sondes.iml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..ae1cb4c
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000..5c9a7d8
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Alerte_journalière.py b/Alerte_journalière.py
new file mode 100644
index 0000000..2833953
--- /dev/null
+++ b/Alerte_journalière.py
@@ -0,0 +1,68 @@
+import mysql.connector
+from datetime import datetime
+import smtplib
+from email.mime.text import MIMEText
+
+# --- Config base de données ---
+config = {
+ "host": "54.36.188.119",
+ "user": "michel",
+ "password": "#SO2&1nf%mZ@jfh",
+ "database": "Sondes"
+}
+
+
+# --- Config email ---
+def envoyer_mail(sujet, message, destinataires):
+ msg = MIMEText(message, "plain", "utf-8")
+ msg['Subject'] = sujet
+ msg['From'] = 'alertes_saclay@domo91.fr'
+ msg['To'] = ', '.join(destinataires)
+
+ try:
+ with smtplib.SMTP_SSL('smtp.mail.ovh.net', 465) as server:
+ server.login('alertes_saclay@domo91.fr', 'Kdpke674y23Feq^H')
+ server.sendmail(msg['From'], destinataires, msg.as_string())
+ print("📧 Mail récapitulatif envoyé avec succès.")
+ except Exception as e:
+ print(f"Erreur envoi mail : {e}")
+
+
+# --- Exécution principale ---
+try:
+ conn = mysql.connector.connect(**config)
+ cursor = conn.cursor(dictionary=True)
+
+ # Rechercher toutes les tables d'alertes
+ cursor.execute("SHOW TABLES LIKE 'Alertes_%'")
+ tables = [list(row.values())[0] for row in cursor.fetchall()]
+
+ message = ""
+ total_alertes = 0
+
+ for table in tables:
+ lieu = table.replace("Alertes_", "")
+ cursor.execute(f"SELECT Sonde, Debut_defaut FROM {table} WHERE Status = 'En cours'")
+ alertes = cursor.fetchall()
+
+ if alertes:
+ message += f"\n📍 **Site : {lieu}**\n"
+ for alerte in alertes:
+ debut = alerte['Debut_defaut'].strftime("%Y-%m-%d %H:%M")
+ message += f"🔔 Sonde : {alerte['Sonde']} | Depuis : {debut}\n"
+ total_alertes += len(alertes)
+
+ if total_alertes > 0:
+ envoyer_mail(
+ sujet="🚨 Récapitulatif des alertes en cours - 7h00",
+ message=message,
+ destinataires=["services@domo91.fr"]
+ )
+ else:
+ print("✅ Aucune alerte en cours à 7h00.")
+
+ cursor.close()
+ conn.close()
+
+except Exception as e:
+ print(f"Erreur script alerte journalière : {e}")
diff --git a/Chat-Id.py b/Chat-Id.py
new file mode 100644
index 0000000..a5bd401
--- /dev/null
+++ b/Chat-Id.py
@@ -0,0 +1,36 @@
+import requests
+import json
+
+# Remplace par ton token de bot Telegram
+token = "8128378340:AAF2sO3gaH1XpMNya_pEslzerqokoCiFRGs"
+
+url = f"https://api.telegram.org/bot{token}/getUpdates"
+
+try:
+ response = requests.get(url)
+ data = response.json()
+
+ print("🔍 Récupération des chats Telegram récents...\n")
+
+ if "result" in data:
+ chats = set()
+
+ for update in data["result"]:
+ message = update.get("message") or update.get("edited_message")
+ if not message:
+ continue
+
+ chat = message["chat"]
+ chat_id = chat["id"]
+ chat_title = chat.get("title") or chat.get("username") or chat.get("first_name") or "Inconnu"
+
+ if chat_id not in chats:
+ chats.add(chat_id)
+ print(f"➡️ Chat : {chat_title} | ID : {chat_id}")
+
+ if not chats:
+ print("⚠️ Aucun chat trouvé. Envoie un message depuis un groupe ou une discussion avec le bot.")
+ else:
+ print("❌ Erreur : aucune donnée 'result' trouvée dans la réponse.")
+except Exception as e:
+ print(f"Erreur lors de la récupération des chats : {e}")
diff --git a/Chaufferie.py b/Chaufferie.py
new file mode 100644
index 0000000..73eab00
--- /dev/null
+++ b/Chaufferie.py
@@ -0,0 +1,30 @@
+import paho.mqtt.client as mqtt
+import mysql.connector
+
+# Configuration de la connexion MySQL
+mydb = mysql.connector.connect(
+ host="54.36.188.119",
+ user="michel",
+ password="#SO2&1nf%mZ@jfh",
+ database="Sondes"
+)
+
+# Fonction de callback quand un message est reçu
+def on_message(_client, _userdata, msg):
+ print(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
+ cursor = mydb.cursor()
+ frigo_name = msg.topic.split('/')[-1] # Prend la dernière partie après le "/"
+ sql = "INSERT INTO Chaufferie (Sonde, Temperature) VALUES (%s, %s)"
+ val = (frigo_name, msg.payload.decode())
+ cursor.execute(sql, val)
+ mydb.commit()
+
+# Configuration du client MQTT
+client = mqtt.Client()
+client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
+client.on_message = on_message
+
+client.connect("54.36.188.119", 1883, 60)
+client.subscribe("Module_01/#") # S'abonner à tous les topics commençant par Saclay
+
+client.loop_forever() # Rester connecté en continu pour écouter les messages
diff --git a/Connexion_mysql.py b/Connexion_mysql.py
new file mode 100644
index 0000000..53c7c10
--- /dev/null
+++ b/Connexion_mysql.py
@@ -0,0 +1,9 @@
+import mysql.connector
+
+conn = mysql.connector.connect(
+ host="54.36.188.119",
+ user="michel",
+ password="#SO2&1nf%mZ@jfh",
+ database="Sondes"
+)
+print("Connexion OK")
\ No newline at end of file
diff --git a/Général.py b/Général.py
new file mode 100644
index 0000000..9ddce6c
--- /dev/null
+++ b/Général.py
@@ -0,0 +1,323 @@
+import requests
+import mysql.connector
+from datetime import datetime, timedelta
+import time
+import sys
+import os
+import schedule
+
+def connect_db():
+ return mysql.connector.connect(
+ host="54.36.188.119",
+ user="michel",
+ password="#SO2&1nf%mZ@jfh",
+ database="Sondes"
+ )
+
+def envoi_etat_quotidien(cursor, site):
+ token = "5714323406:AAGSj9jrfBHbfxubz3ooabPEizI8aBOLnvE"
+ chat_id = get_chat_id(cursor, site)
+ etat_sondes(cursor, site, chat_id, token)
+ print(f"[INFO] État des sondes envoyé pour le site {site}.")
+
+def get_active_sondes(cursor, site):
+ query = "SELECT Sonde, Temp_Max FROM Chambres_froides WHERE Lieu = %s AND Etat = 'On';"
+ cursor.execute(query, (site,))
+ result = cursor.fetchall()
+ return {row[0]: float(row[1]) for row in result}
+
+
+def check_temperature_limits(cursor, table_historique, sonde, limite, duree=30):
+ temps_limite = datetime.now() - timedelta(minutes=duree)
+ query = f"""
+ SELECT Temperature
+ FROM {table_historique}
+ WHERE Sonde = %s AND Date >= %s
+ ORDER BY Date DESC LIMIT 6;
+ """
+ cursor.execute(query, (sonde, temps_limite))
+ result = cursor.fetchall()
+ if len(result) == 6 and all(float(temp[0]) > limite for temp in result):
+ return True, float(result[0][0])
+ return False, None
+
+def simulate_alert(db, cursor, site, sonde, chat_id, token):
+ table_alertes = f"Alertes_{site}"
+ print(f"[TEST] tentative d'insertion de sonde : {sonde} dans table {table_alertes}")
+
+ try:
+ query = f"""
+ INSERT INTO {table_alertes} (Sonde, Debut_defaut, Status)
+ VALUES (%s, NOW(), 'test')
+ ON DUPLICATE KEY UPDATE Debut_defaut = NOW(), Status = 'test';
+ """
+ cursor.execute(query, (sonde,))
+ db.commit()
+ print(f"[TEST] insertion ou mise à jour réussie pour {sonde}.")
+ except Exception as e:
+ print(f"[ERREUR] lors de l'insertion test : {e}")
+
+ message = f"⚠️ TEST ALERTE : Simulation d'une alerte pour la sonde {sonde}."
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ try:
+ requests.get(url, params={'chat_id': chat_id, 'text': message})
+ except Exception as e:
+ print(f"[ERREUR] lors de l'envoi Telegram : {e}")
+
+def create_alert(db, cursor, table_alertes, sonde, temperature):
+ query = f"""
+ INSERT INTO {table_alertes} (Sonde, Debut_defaut, Status)
+ VALUES (%s, NOW(), 'en cours');
+ """
+ cursor.execute(query, (sonde,))
+ send_telegram_message(sonde, temperature)
+ print(f"Alerte créée pour la sonde {sonde}")
+ db.commit()
+
+def resolve_alert(cursor, table_alertes, sonde):
+ query = f"""
+ UPDATE {table_alertes}
+ SET Status = 'résolu'
+ WHERE Sonde = %s AND Status = 'en cours';
+ """
+ cursor.execute(query, (sonde,))
+ print(f"Alerte résolue pour la sonde {sonde}")
+
+def acquitter_alerte(cursor, site, sonde, chat_id, token):
+ table_alertes = f"Alertes_{site}"
+ query = f"""
+ UPDATE {table_alertes}
+ SET Status = 'acquittée'
+ WHERE Sonde = %s AND Status IN ('en cours', 'test');
+ """
+ cursor.execute(query, (sonde,))
+ lignes_modifiees = cursor.rowcount
+
+ if lignes_modifiees > 0:
+ message = f"✅ Alerte acquittée pour la sonde {sonde} par commande Telegram."
+ else:
+ message = f"ℹ️ Aucune alerte active à acquitter pour la sonde {sonde}."
+
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ try:
+ requests.get(url, params={'chat_id': chat_id, 'text': message})
+ except Exception as e:
+ print(f"[ERREUR] envoi message Telegram : {e}")
+
+def send_telegram_message(sonde, temperature):
+ token = "5714323406:AAGSj9jrfBHbfxubz3ooabPEizI8aBOLnvE"
+ chat_id = "-1002442631825"
+ message = f"⚠️ Alerte température : La sonde {sonde} dépasse la limite avec une température de {temperature}°C."
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ params = {'chat_id': chat_id, 'text': message}
+ try:
+ response = requests.get(url, params=params)
+ if response.status_code == 200:
+ print(f"Message envoyé via Telegram pour la sonde {sonde}.")
+ else:
+ print(f"Erreur lors de l'envoi du message Telegram : {response.status_code}")
+ except Exception as e:
+ print(f"Erreur lors de l'envoi du message Telegram : {e}")
+
+
+def get_chat_id(cursor, site):
+ cursor.execute("SELECT Chat_ID FROM Sites WHERE Nom = %s;", (site,))
+ result = cursor.fetchone()
+ if result:
+ return result[0]
+ else:
+ print(f"Aucun Chat_ID trouvé pour le site {site}")
+ return None
+
+def passer_en_maintenance(cursor, site, sonde, chat_id, token):
+ try:
+ query = """
+ UPDATE Chambres_froides
+ SET Etat = 'Off'
+ WHERE Lieu = %s AND Sonde = %s;
+ """
+ cursor.execute(query, (site, sonde))
+ lignes_modifiees = cursor.rowcount
+
+ if lignes_modifiees > 0:
+ message = f"🛠️ La sonde {sonde} a été passée en mode maintenance (OFF)."
+ else:
+ message = f"⚠️ Sonde {sonde} introuvable pour le site {site}."
+
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ requests.get(url, params={'chat_id': chat_id, 'text': message})
+
+ except Exception as e:
+ print(f"[ERREUR] lors du passage en maintenance : {e}")
+
+def reactiver_sonde(cursor, site, sonde, chat_id, token):
+ try:
+ query = """
+ UPDATE Chambres_froides
+ SET Etat = 'On'
+ WHERE Lieu = %s AND Sonde = %s;
+ """
+ cursor.execute(query, (site, sonde))
+ lignes_modifiees = cursor.rowcount
+
+ if lignes_modifiees > 0:
+ message = f"✅ La sonde {sonde} a été réactivée (ON)."
+ else:
+ message = f"⚠️ Sonde {sonde} introuvable pour le site {site}."
+
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ requests.get(url, params={'chat_id': chat_id, 'text': message})
+
+ except Exception as e:
+ print(f"[ERREUR] lors de la réactivation : {e}")
+
+def etat_sondes(cursor, site, chat_id, token):
+ query = "SELECT Sonde, Etat FROM Chambres_froides WHERE Lieu = %s ORDER BY Sonde;"
+ cursor.execute(query, (site,))
+ result = cursor.fetchall()
+
+ message = f"📊 État des sondes - {site} :\n"
+ for sonde, etat in result:
+ symbole = "🟢" if etat.upper() == "ON" else "🔴"
+ message += f"{symbole} {sonde} ({etat.upper()})\n"
+
+ url = f"https://api.telegram.org/bot{token}/sendMessage"
+ requests.get(url, params={'chat_id': chat_id, 'text': message})
+
+def monitor_temperatures_simple(site, db, cursor):
+ table_historique = site
+ table_alertes = f"Alertes_{site}"
+ sondes = get_active_sondes(cursor, site)
+ print(f"[MONITORING] Sondes actives pour {site} : {sondes}")
+
+ for sonde, limite in sondes.items():
+ alert_needed, temperature = check_temperature_limits(cursor, table_historique, sonde, limite)
+ if alert_needed:
+ create_alert(db, cursor, table_alertes, sonde, temperature)
+ else:
+ resolve_alert(cursor, table_alertes, sonde)
+
+ db.commit()
+ print("[MONITORING] Vérification des sondes terminée.")
+
+def monitor_temperatures(site):
+ db = connect_db()
+ cursor = db.cursor()
+
+ table_historique = site # Ex: Saclay
+ table_alertes = f"Alertes_{site}" # Ex: Alertes_Saclay
+
+ sondes = get_active_sondes(cursor, site)
+ print(f"Sondes actives pour le site {site} :", sondes)
+
+ for sonde, limite in sondes.items():
+ alert_needed, temperature = check_temperature_limits(cursor, table_historique, sonde, limite)
+ if alert_needed:
+ create_alert(db, cursor, table_alertes, sonde, temperature)
+ else:
+ resolve_alert(cursor, table_alertes, sonde)
+
+ db.commit()
+ listen_for_commands(db, cursor, site)
+ cursor.close()
+ db.close()
+
+def listen_for_commands(db, cursor, site):
+ token = "5714323406:AAGSj9jrfBHbfxubz3ooabPEizI8aBOLnvE"
+ chat_id = get_chat_id(cursor, site)
+ offset_file = os.path.join(os.path.dirname(__file__), f"last_update_id_{site}.txt")
+
+ try:
+ with open(offset_file, 'r') as f:
+ last_update_id = int(f.read().strip())
+ except FileNotFoundError:
+ last_update_id = None
+
+ url = f"https://api.telegram.org/bot{token}/getUpdates"
+ if last_update_id is not None:
+ url += f"?offset={last_update_id + 1}"
+
+ try:
+ response = requests.get(url)
+ data = response.json()
+
+ if "result" in data:
+ for update in data["result"]:
+ update_id = update["update_id"]
+
+ if "message" in update:
+ message = update["message"]["text"]
+ print(f"[CMD] Message reçu : {message}")
+
+ if message.lower().startswith("/etat"):
+ etat_sondes(cursor, site, chat_id, token)
+
+ elif message.lower().startswith("/acquitter"):
+ parts = message.strip().split(" ", 1)
+ if len(parts) == 2 and parts[1].strip():
+ sonde = parts[1].strip()
+ acquitter_alerte(cursor, site, sonde, chat_id, token)
+ db.commit()
+ else:
+ erreur_msg = "❌ Utilisation incorrecte. Format attendu : /acquitter "
+ requests.get(f"https://api.telegram.org/bot{token}/sendMessage",
+ params={'chat_id': chat_id, 'text': erreur_msg})
+ elif message.lower().startswith("/maintenance"):
+ parts = message.strip().split(" ", 1)
+ if len(parts) == 2 and parts[1].strip():
+ sonde = parts[1].strip()
+ passer_en_maintenance(cursor, site, sonde, chat_id, token)
+ db.commit()
+ else:
+ erreur_msg = "❌ Utilisation incorrecte. Format attendu : /maintenance "
+ requests.get(f"https://api.telegram.org/bot{token}/sendMessage",
+ params={'chat_id': chat_id, 'text': erreur_msg})
+ elif message.lower().startswith("/reactiver"):
+ parts = message.strip().split(" ", 1)
+ if len(parts) == 2 and parts[1].strip():
+ sonde = parts[1].strip()
+ reactiver_sonde(cursor, site, sonde, chat_id, token)
+ db.commit()
+ else:
+ erreur_msg = "❌ Utilisation incorrecte. Format attendu : /reactiver "
+ requests.get(f"https://api.telegram.org/bot{token}/sendMessage",
+ params={'chat_id': chat_id, 'text': erreur_msg})
+ elif message.lower().startswith("/test"):
+ parts = message.strip().split(" ", 1)
+ if len(parts) == 2 and parts[1].strip():
+ sonde = parts[1].strip()
+ simulate_alert(db, cursor, site, sonde, chat_id, token)
+ else:
+ erreur_msg = "❌ Utilisation incorrecte. Format attendu : /test "
+ requests.get(f"https://api.telegram.org/bot{token}/sendMessage",
+ params={'chat_id': chat_id, 'text': erreur_msg})
+
+ with open(offset_file, 'w') as f:
+ f.write(str(update_id))
+
+ except Exception as e:
+ print(f"Erreur lors de la lecture des commandes Telegram : {e}")
+
+
+def main():
+ site = sys.argv[1] if len(sys.argv) > 1 else "Saclay"
+ db = connect_db()
+ cursor = db.cursor()
+
+ # ✅ Planification : tous les jours à 07:00 → état des sondes
+ schedule.every().day.at("07:00").do(envoi_etat_quotidien, cursor=cursor, site=site)
+
+ # ✅ Planification : toutes les 2m30 → surveillance
+ schedule.every(2).minutes.do(monitor_temperatures_simple, site=site, db=db, cursor=cursor)
+
+ try:
+ while True:
+ schedule.run_pending()
+ listen_for_commands(db, cursor, site)
+ time.sleep(2) # petite pause pour ne pas surcharger Telegram
+ finally:
+ cursor.close()
+ db.close()
+
+if __name__ == "__main__":
+ main()
diff --git a/Purge_Alertes_saclay.py b/Purge_Alertes_saclay.py
new file mode 100644
index 0000000..72a5d1b
--- /dev/null
+++ b/Purge_Alertes_saclay.py
@@ -0,0 +1,17 @@
+import mysql.connector
+
+config = {
+ "host": "54.36.188.119",
+ "user": "michel",
+ "password": "#SO2&1nf%mZ@jfh",
+ "database": "Sondes"
+}
+
+conn = mysql.connector.connect(**config)
+cursor = conn.cursor()
+cursor.execute("DELETE FROM Alertes_Saclay WHERE Debut_defaut < NOW() - INTERVAL 7 DAY")
+conn.commit()
+cursor.close()
+conn.close()
+
+print("✅ Alertes de plus de 7 jours supprimées.")
diff --git a/Scripts/Redémarrage.sh b/Scripts/Redémarrage.sh
new file mode 100644
index 0000000..b11e5e3
--- /dev/null
+++ b/Scripts/Redémarrage.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+# Fonction pour vérifier et relancer un processus
+check_and_restart() {
+ process_name="$1"
+ log_file="$2"
+ script_path="$3"
+
+ # Vérifier si le processus est actif
+ if pgrep -af "$process_name" > /dev/null; then
+ echo "Le processus $process_name est actif."
+ else
+ echo "Le processus $process_name est mort."
+
+ # Demander à l'utilisateur s'il souhaite relancer le processus
+ read -p "Voulez-vous relancer le processus $process_name ? (O/N) " choice
+ if [ "$choice" = "O" ] || [ "$choice" = "o" ]; then
+ echo "Relancer le processus $process_name."
+ nohup python3 $script_path > $log_file 2>&1 &
+ else
+ echo "Ne rien faire pour le processus $process_name."
+ fi
+ fi
+}
+
+# Afficher les processus Python3 actifs et les vérifier
+echo "Vérification des processus Python3 :"
+check_and_restart "Cuisine.py" "/root/python/log/cuisine_saclay_output.log" "/root/python/Cuisine_saclay.py"
+check_and_restart "Chaufferie.py" "/root/python/log/chaufferie_output.log" "/root/python/Chaufferie.py"
+check_and_restart "Alertes_telegram.py" "/root/python/log/Alertes_telegram_output.log" "/root/python/Alertes_telegram.py"
diff --git a/Scripts/backup_mysql.sh b/Scripts/backup_mysql.sh
new file mode 100644
index 0000000..8bfdf53
--- /dev/null
+++ b/Scripts/backup_mysql.sh
@@ -0,0 +1,3 @@
+# mysqldump --defaults-file=/root/my.cnf -u michel Sondes > /root/syno/Sondes-$(date +%Y%m%d).sql
+# mysqldump --defaults-file=/root/my.cnf -u michel --databases Sondes Best_Western >/root/syno/BW-$(date +%Y%m%d).sql
+mysqldump --defaults-file=/root/my.cnf -u michel --databases Best_Western Sondes >/root/syno/BW-$(date +%Y%m%d).sql
diff --git a/Scripts/check_docker.sh b/Scripts/check_docker.sh
new file mode 100644
index 0000000..5d0a06d
--- /dev/null
+++ b/Scripts/check_docker.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+
+# Fonction pour vérifier et redémarrer un container Docker
+check_and_restart_container() {
+ container_name="$1"
+
+ # Vérifier si le container est en cours d'exécution
+ if docker ps --format '{{.Names}}' | grep -q "$container_name"; then
+ echo "Le container $container_name est en cours d'exécution."
+ else
+ echo "Le container $container_name n'est pas en cours d'exécution."
+
+ # Demander à l'utilisateur s'il souhaite redémarrer le container
+ read -p "Voulez-vous redémarrer le container $container_name ? (O/N) " choice
+ if [ "$choice" = "O" ] || [ "$choice" = "o" ]; then
+ echo "Redémarrer le container $container_name."
+ docker restart $container_name
+ else
+ echo "Ne rien faire pour le container $container_name."
+ fi
+ fi
+}
+
+# Afficher les containers Docker actifs et les vérifier
+echo "Vérification des containers Docker :"
+check_and_restart_container "domoticz"
+check_and_restart_container "postfix"
diff --git a/Scripts/verifie_scripts.sh b/Scripts/verifie_scripts.sh
new file mode 100644
index 0000000..aa833e5
--- /dev/null
+++ b/Scripts/verifie_scripts.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+# Fonction pour vérifier et relancer un processus
+check_and_restart() {
+ process_name="$1"
+ log_file="$2"
+
+ # Vérifier si le processus est actif
+ if pgrep -af "$process_name" > /dev/null; then
+ echo "Le processus $process_name est actif."
+ else
+ echo "Le processus $process_name est mort."
+
+ # Demander à l'utilisateur s'il souhaite relancer le processus
+ read -p "Voulez-vous relancer le processus $process_name ? (O/N) " choice
+ if [ "$choice" = "O" ] || [ "$choice" = "o" ]; then
+ echo "Relancer le processus $process_name."
+ nohup $process_name > $log_file 2>&1 &
+ else
+ echo "Ne rien faire pour le processus $process_name."
+ fi
+ fi
+}
+
+# Afficher les processus Python3 actifs et les vérifier
+echo "Vérification des processus Python3 :"
+check_and_restart "python3 /root/python/Cuisine_saclay.py" "/root/python/log/cuisine_saclay_output.log"
+check_and_restart "python3 /root/python/Chaufferie.py" "/root/python/log/chaufferie_output.log"
+check_and_restart "python3 /root/python/Alertes_telegram.py" "/root/python/log/Alertes_telegram_output.log"
diff --git a/Streamlit.py b/Streamlit.py
index 0c7fa0e..887aec3 100644
--- a/Streamlit.py
+++ b/Streamlit.py
@@ -8,7 +8,7 @@ import matplotlib.pyplot as plt
import matplotlib.dates as mdates
st.set_page_config(page_title="Domo91 - Surveillance", layout="wide")
-st.title("📡 Supervision Températures Multisites")
+st.title("📡 Supervision Températures")
# --- Configuration base de données ---
db_config = {
@@ -76,8 +76,6 @@ if st.session_state.get("page") == "analyse_logs":
with st.sidebar:
- st.markdown("# 🌡️ **Domo91**")
- st.markdown("Monitoring chambres froides industrielles")
st.header("🔐 Connexion")
if not st.session_state["authenticated"]:
login = st.text_input("Nom d'utilisateur")
@@ -112,7 +110,7 @@ if st.session_state["authenticated"]:
try:
conn = mysql.connector.connect(**db_config)
cursor = conn.cursor(dictionary=True)
- sites_possibles = ["Saclay", "Meudon"]
+ sites_possibles = ["Saclay", "Meudon", "Roissy"]
if st.session_state["role"] == "superviseur":
site_selectionne = st.selectbox("📍 Choisissez un site :", sites_possibles)
else:
@@ -129,30 +127,7 @@ if st.session_state["authenticated"]:
df["Date"] = pd.to_datetime(df["Date"])
sondes = sorted(df["Sonde"].unique())
sonde_choisie = st.selectbox("🧪 Choisissez une sonde :", sondes)
- df_sonde = df[df["Sonde"] == sonde_choisie].copy()
- df_sonde["Heure"] = df_sonde["Date"].dt.hour
-
- # 🕓 Filtres horaires
- st.markdown("### 🕒 Filtrer par moment de la journée")
- col1, col2, col3 = st.columns(3)
- filtre_matin = col1.checkbox("Matin (06h-12h)", value=True)
- filtre_apresmidi = col2.checkbox("Après-midi (12h-18h)", value=True)
- filtre_nuit = col3.checkbox("Nuit (18h-06h)", value=True)
-
- # Construction du filtre combiné
- filtres = []
- if filtre_matin:
- filtres.append(df_sonde["Heure"].between(6, 11))
- if filtre_apresmidi:
- filtres.append(df_sonde["Heure"].between(12, 17))
- if filtre_nuit:
- filtres.append((df_sonde["Heure"] >= 18) | (df_sonde["Heure"] < 6))
-
- if filtres:
- filtre_combiné = filtres[0]
- for f in filtres[1:]:
- filtre_combiné |= f
- df_sonde = df_sonde[filtre_combiné]
+ df_sonde = df[df["Sonde"] == sonde_choisie]
cursor.execute("SELECT Temp_Max FROM Chambres_froides WHERE Lieu = %s AND Sonde = %s", (site_selectionne, sonde_choisie))
seuil = cursor.fetchone()
seuil_temp = seuil["Temp_Max"] if seuil else 10
diff --git a/Test_mail.py b/Test_mail.py
new file mode 100644
index 0000000..b0183c7
--- /dev/null
+++ b/Test_mail.py
@@ -0,0 +1,23 @@
+import smtplib
+from email.mime.text import MIMEText
+
+def envoyer_mail(sujet, message, destinataires):
+ msg = MIMEText(message)
+ msg['Subject'] = sujet
+ msg['From'] = 'alertes_saclay@domo91.fr'
+ msg['To'] = ', '.join(destinataires)
+
+ try:
+ with smtplib.SMTP_SSL('smtp.mail.ovh.net', 465) as server:
+ server.login('alertes_saclay@domo91.fr', 'Kdpke674y23Feq^H')
+ server.sendmail(msg['From'], destinataires, msg.as_string())
+ print(f"📧 Mail envoyé à {destinataires}")
+ except Exception as e:
+ print(f"Erreur envoi mail : {e}")
+
+# --- Test d'envoi ---
+envoyer_mail(
+ sujet="🧪 Test d'envoi d'alerte",
+ message="Ceci est un test de l'envoi d'e-mail via alertes_saclay@domo91.fr.",
+ destinataires=["services@domo91.fr"]
+)
diff --git a/Tracker.py b/Tracker.py
new file mode 100644
index 0000000..b35cecb
--- /dev/null
+++ b/Tracker.py
@@ -0,0 +1,106 @@
+import paho.mqtt.client as mqtt
+import mysql.connector
+import re # Import de la bibliothèque des expressions régulières
+
+
+# Configuration de la base de données MySQL
+db_config = {
+ 'user': 'superviseur', # Remplacez par votre utilisateur MySQL
+ 'password': 'Bto7Lm_z]m!BFH!*', # Remplacez par votre mot de passe MySQL
+ 'host': '54.36.188.119', # Adresse de votre serveur MySQL (localhost si en local)
+ 'database': 'Sondes' # Nom de la base de données MySQL
+}
+
+
+def convertir_rom_id_en_hexa(rom_id):
+ # On découpe la chaîne rom_id en paires de deux caractères
+ hex_parts = [f"0x{rom_id[i:i + 2]}" for i in range(0, len(rom_id), 2)]
+ return ",".join(hex_parts)
+
+
+# Connexion à la base de données MySQL
+def connect_db():
+ return mysql.connector.connect(**db_config)
+
+
+# Fonction pour vérifier si la sonde est déjà présente dans la base
+def sonde_deja_presente(rom_id):
+ conn = connect_db()
+ cursor = conn.cursor()
+ try:
+ # Vérifier si la sonde existe déjà dans la base
+ cursor.execute("SELECT COUNT(*) FROM Tracker WHERE rom_id = %s", (rom_id,))
+ result = cursor.fetchone()
+ return result[0] > 0 # Si le nombre est supérieur à 0, la sonde est déjà présente
+
+ except mysql.connector.Error as err:
+ print(f"Erreur MySQL lors de la vérification de la sonde : {err}")
+ return False
+
+ finally:
+ cursor.close()
+ conn.close()
+
+
+# Fonction pour insérer les sondes dans la base de données
+def inserer_sonde(rom_id):
+ if sonde_deja_presente(rom_id):
+ print(f"Sonde {rom_id} déjà présente dans la base de données. Aucune insertion effectuée.")
+ return
+
+ conn = connect_db()
+ cursor = conn.cursor()
+ try:
+ # Conversion en hexadécimal
+ rom_id_hexa = convertir_rom_id_en_hexa(rom_id)
+
+ # Insertion de rom_id et de sa version hexa dans la base
+ cursor.execute("INSERT INTO Tracker (rom_id, hexa) VALUES (%s, %s)", (rom_id, rom_id_hexa))
+ conn.commit()
+ print(f"Sonde {rom_id} insérée dans la base de données avec son format hexa {rom_id_hexa}.")
+
+ except mysql.connector.Error as err:
+ print(f"Erreur MySQL : {err}")
+
+ finally:
+ cursor.close()
+ conn.close()
+
+
+# Fonction de callback pour gérer les messages MQTT
+def on_message(_client, _userdata, message):
+ payload = message.payload.decode()
+ print(f"Message reçu : {payload}")
+
+ # Utilisation de re pour extraire les ROM IDs (Sonde [rom_id])
+ rom_ids = re.findall(r"[0-9a-fA-F]{16}", payload) # Capturer les IDs de 16 caractères
+ if rom_ids:
+ for rom_id in rom_ids:
+ inserer_sonde(rom_id)
+ else:
+ print("Aucun ROM ID trouvé dans le message.")
+
+
+# Configuration du client MQTT
+mqtt_broker = "46.105.92.116"
+mqtt_port = 1883 # Vérifiez si votre broker utilise un autre port
+mqtt_user = "Bwps"
+mqtt_password = "scJ5ACj2keRfI^"
+mqtt_topic = "Tracker/sondes"
+
+client = mqtt.Client()
+
+# Authentification MQTT
+client.username_pw_set(mqtt_user, mqtt_password)
+
+# Configuration du callback pour les messages MQTT
+client.on_message = on_message
+
+# Connexion au broker MQTT
+client.connect(mqtt_broker, mqtt_port, 60)
+
+# Souscription au topic Tracker/sondes
+client.subscribe(mqtt_topic)
+
+# Démarrer la boucle MQTT
+client.loop_forever()
diff --git a/logs_analyse.py b/logs_analyse.py
new file mode 100644
index 0000000..5630e30
--- /dev/null
+++ b/logs_analyse.py
@@ -0,0 +1,39 @@
+import streamlit as st
+import pandas as pd
+import matplotlib.pyplot as plt
+
+# --- Chargement des données ---
+try:
+ df = pd.read_csv("/home/debian/travail/logs_monitor.csv", sep=";", parse_dates=["Date"])
+except FileNotFoundError:
+ st.error("📂 Le fichier de log n'a pas été trouvé.")
+ st.stop()
+
+st.title("🧾 Analyse des scans Monitor.py")
+
+# --- Filtres ---
+df["Date_str"] = df["Date"].dt.date
+dates_dispo = sorted(df["Date_str"].unique(), reverse=True)
+date_selection = st.selectbox("📅 Sélectionnez une date :", dates_dispo)
+
+lieux = sorted(df["Lieu"].unique())
+lieu_selection = st.selectbox("📍 Site :", lieux)
+
+df_filtré = df[(df["Date_str"] == date_selection) & (df["Lieu"] == lieu_selection)]
+
+sondes = sorted(df_filtré["Sonde"].unique())
+sonde_selection = st.selectbox("🧪 Sonde :", sondes)
+
+df_sonde = df_filtré[df_filtré["Sonde"] == sonde_selection]
+
+# --- Graphique température ---
+fig, ax = plt.subplots(figsize=(10, 4))
+ax.plot(df_sonde["Date"], df_sonde["Température"], marker='o')
+ax.set_title(f"Évolution de la température - {sonde_selection}")
+ax.set_xlabel("Heure")
+ax.set_ylabel("Température (°C)")
+st.pyplot(fig)
+
+# --- Tableau complet du jour/sonde sélectionnés ---
+st.markdown("### 📋 Détail des scans")
+st.dataframe(df_sonde[["Date", "Sonde", "Température", "Seuil", "État"]], use_container_width=True)
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000..eee1a33
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,9 @@
+mysql~=0.0.3
+mysql-connector-python~=9.2.0
+pandas~=2.2.3
+DateTime~=5.5
+streamlit~=1.44.1
+matplotlib~=3.10.1
+paho-mqtt~=2.1.0
+requests~=2.32.3
+schedule~=1.2.2
\ No newline at end of file