Remise en état des fichiers

This commit is contained in:
2025-07-26 13:18:20 +02:00
parent 970fcc542a
commit 70e9ba9c64
16 changed files with 239 additions and 203 deletions

26
.env Normal file
View File

@@ -0,0 +1,26 @@
#connexion mysql
DB_HOST=162.19.78.131
DB_USER=Michel
DB_PASSWORD=wuP^wu&6xjx61bh*kjS^4
DB_NAME=Sondes
# paramètres mail
SMTP_HOST=smtp.mail.ovh.net
SMTP_PORT=465
EMAIL_FROM=services@domo91.fr
EMAIL_PASSWORD=6ZiCsVtSf9@nEHv@$^0
EMAIL_DESTINATAIRES=services@domo91.fr
# connexion OVH pour les SMS
OVH_APP_KEY=f725d07b2f98a195
OVH_APP_SECRET=5ca392a0a728e2395edd426bb1e11ad6
OVH_CONSUMER_KEY=305f2e8611e58b83930de84ee65c99f9
OVH_ENDPOINT=ovh-eu
OVH_SMS_ACCOUNT=sms-jm164396-1
OVH_SMS_SENDER=DOMO91FR
OVH_SERVICE_NAME=sms-jm164396-1
SMS_RECEIVER=+33635164680
ENVOI_SMS=1
PHONE_SACLAY=+33682069405,+33650270939
PHONE_MEUDON=+33666271128
PHONE_ADMIN=+33635164680

2
.gitignore vendored
View File

@@ -7,8 +7,6 @@
# 👉 Environnement virtuel # 👉 Environnement virtuel
.venv/ .venv/
venv/ venv/
env/
.env
# 👉 Fichiers Python compilés # 👉 Fichiers Python compilés
__pycache__/ __pycache__/

View File

@@ -2,6 +2,7 @@
<module type="PYTHON_MODULE" version="4"> <module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.venv" /> <excludeFolder url="file://$MODULE_DIR$/.venv" />
</content> </content>
<orderEntry type="jdk" jdkName="Python 3.13 (Gestion_sondes)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Python 3.13 (Gestion_sondes)" jdkType="Python SDK" />

View File

@@ -1,6 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import streamlit as st import streamlit as st
import mysql.connector
import pandas as pd import pandas as pd
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.dates as mdates import matplotlib.dates as mdates
@@ -10,7 +9,7 @@ import random
from dotenv import load_dotenv from dotenv import load_dotenv
from datetime import datetime, date, time from datetime import datetime, date, time
import bcrypt import bcrypt
from .utils_db import connect_to_mysql
# Charger les variables d'environnement # Charger les variables d'environnement
load_dotenv() load_dotenv()
@@ -22,12 +21,6 @@ if "authenticated" not in st.session_state:
st.title("📡 Supervision Températures") st.title("📡 Supervision Températures")
db_config = {
"host": os.getenv("DB_HOST"),
"user": os.getenv("DB_USER"),
"password": os.getenv("DB_PASSWORD"),
"database": os.getenv("DB_NAME")
}
def get_connection(): def get_connection():
return mysql.connector.connect(**db_config) return mysql.connector.connect(**db_config)
@@ -181,7 +174,7 @@ if not st.session_state.get("authenticated"):
if result["Expiration"] and result["Expiration"] < date.today(): if result["Expiration"] and result["Expiration"] < date.today():
st.sidebar.error("⛔ Votre accès a expiré. Veuillez contacter un administrateur.") st.sidebar.error("⛔ Votre accès a expiré. Veuillez contacter un administrateur.")
cursor.close() cursor.close()
conn.close()sondes conn.close()
st.stop() st.stop()
st.session_state["authenticated"] = True st.session_state["authenticated"] = True
st.session_state["role"] = result["role"] st.session_state["role"] = result["role"]

49
app/Logs/monitor.csv Normal file
View File

@@ -0,0 +1,49 @@
Date;Lieu;Sonde;Température;Seuil;État
2025-07-26 13:04:30;Saclay;Congelateur;-14.75;-15.0;Dépassement
2025-07-26 12:59:27;Saclay;Congelateur;-11.25;-15.0;Dépassement
2025-07-26 12:54:25;Saclay;Congelateur;-6.50;-15.0;Dépassement
2025-07-26 12:49:22;Saclay;Congelateur;-4.75;-15.0;Dépassement
2025-07-26 12:44:19;Saclay;Congelateur;-7.75;-15.0;Dépassement
2025-07-26 12:39:17;Saclay;Congelateur;-11.50;-15.0;Dépassement
2025-07-26 13:04:30;Saclay;BOF;1.75;8.0;Normal
2025-07-26 12:59:28;Saclay;BOF;2.25;8.0;Normal
2025-07-26 12:54:25;Saclay;BOF;1.00;8.0;Normal
2025-07-26 12:49:22;Saclay;BOF;2.00;8.0;Normal
2025-07-26 12:44:20;Saclay;BOF;0.75;8.0;Normal
2025-07-26 12:39:17;Saclay;BOF;2.00;8.0;Normal
2025-07-26 13:04:31;Saclay;Viandes;21.00;6.0;Dépassement
2025-07-26 12:59:28;Saclay;Viandes;21.00;6.0;Dépassement
2025-07-26 12:54:26;Saclay;Viandes;20.75;6.0;Dépassement
2025-07-26 12:49:23;Saclay;Viandes;21.00;6.0;Dépassement
2025-07-26 12:44:20;Saclay;Viandes;20.75;6.0;Dépassement
2025-07-26 12:39:18;Saclay;Viandes;21.00;6.0;Dépassement
2025-07-26 13:04:31;Saclay;Legumes;5.25;10.0;Normal
2025-07-26 12:59:29;Saclay;Legumes;4.25;10.0;Normal
2025-07-26 12:54:26;Saclay;Legumes;2.75;10.0;Normal
2025-07-26 12:49:23;Saclay;Legumes;5.50;10.0;Normal
2025-07-26 12:44:21;Saclay;Legumes;5.00;10.0;Normal
2025-07-26 12:39:18;Saclay;Legumes;3.75;10.0;Normal
2025-07-26 13:04:32;Saclay;MeP;6.25;8.0;Normal
2025-07-26 12:59:29;Saclay;MeP;7.75;8.0;Normal
2025-07-26 12:54:27;Saclay;MeP;7.00;8.0;Normal
2025-07-26 12:49:24;Saclay;MeP;5.75;8.0;Normal
2025-07-26 12:44:21;Saclay;MeP;3.25;8.0;Normal
2025-07-26 12:39:19;Saclay;MeP;4.75;8.0;Normal
2025-07-26 07:09:45;Meudon;Viandes;3.94;6.0;Normal
2025-07-25 14:37:50;Meudon;Viandes;3.94;6.0;Normal
2025-07-25 14:32:11;Meudon;Viandes;3.94;6.0;Normal
2025-07-25 14:30:20;Meudon;Viandes;3.94;6.0;Normal
2025-07-24 11:00:36;Meudon;Viandes;3.94;6.0;Normal
2025-07-24 10:41:08;Meudon;Viandes;3.94;6.0;Normal
2025-07-26 07:09:45;Meudon;Poissons;3.94;6.0;Normal
2025-07-25 14:37:50;Meudon;Poissons;3.94;6.0;Normal
2025-07-25 14:32:11;Meudon;Poissons;3.94;6.0;Normal
2025-07-25 14:30:20;Meudon;Poissons;3.94;6.0;Normal
2025-07-24 11:00:36;Meudon;Poissons;3.94;6.0;Normal
2025-07-24 10:41:08;Meudon;Poissons;3.94;6.0;Normal
2025-07-26 07:09:45;Meudon;BOF;3.00;8.0;Normal
2025-07-25 14:37:50;Meudon;BOF;3.00;8.0;Normal
2025-07-25 14:32:11;Meudon;BOF;3.00;8.0;Normal
2025-07-25 14:30:20;Meudon;BOF;3.00;8.0;Normal
2025-07-24 11:00:36;Meudon;BOF;3.00;8.0;Normal
2025-07-24 10:41:08;Meudon;BOF;3.00;8.0;Normal
1 Date Lieu Sonde Température Seuil État
2 2025-07-26 13:04:30 Saclay Congelateur -14.75 -15.0 Dépassement
3 2025-07-26 12:59:27 Saclay Congelateur -11.25 -15.0 Dépassement
4 2025-07-26 12:54:25 Saclay Congelateur -6.50 -15.0 Dépassement
5 2025-07-26 12:49:22 Saclay Congelateur -4.75 -15.0 Dépassement
6 2025-07-26 12:44:19 Saclay Congelateur -7.75 -15.0 Dépassement
7 2025-07-26 12:39:17 Saclay Congelateur -11.50 -15.0 Dépassement
8 2025-07-26 13:04:30 Saclay BOF 1.75 8.0 Normal
9 2025-07-26 12:59:28 Saclay BOF 2.25 8.0 Normal
10 2025-07-26 12:54:25 Saclay BOF 1.00 8.0 Normal
11 2025-07-26 12:49:22 Saclay BOF 2.00 8.0 Normal
12 2025-07-26 12:44:20 Saclay BOF 0.75 8.0 Normal
13 2025-07-26 12:39:17 Saclay BOF 2.00 8.0 Normal
14 2025-07-26 13:04:31 Saclay Viandes 21.00 6.0 Dépassement
15 2025-07-26 12:59:28 Saclay Viandes 21.00 6.0 Dépassement
16 2025-07-26 12:54:26 Saclay Viandes 20.75 6.0 Dépassement
17 2025-07-26 12:49:23 Saclay Viandes 21.00 6.0 Dépassement
18 2025-07-26 12:44:20 Saclay Viandes 20.75 6.0 Dépassement
19 2025-07-26 12:39:18 Saclay Viandes 21.00 6.0 Dépassement
20 2025-07-26 13:04:31 Saclay Legumes 5.25 10.0 Normal
21 2025-07-26 12:59:29 Saclay Legumes 4.25 10.0 Normal
22 2025-07-26 12:54:26 Saclay Legumes 2.75 10.0 Normal
23 2025-07-26 12:49:23 Saclay Legumes 5.50 10.0 Normal
24 2025-07-26 12:44:21 Saclay Legumes 5.00 10.0 Normal
25 2025-07-26 12:39:18 Saclay Legumes 3.75 10.0 Normal
26 2025-07-26 13:04:32 Saclay MeP 6.25 8.0 Normal
27 2025-07-26 12:59:29 Saclay MeP 7.75 8.0 Normal
28 2025-07-26 12:54:27 Saclay MeP 7.00 8.0 Normal
29 2025-07-26 12:49:24 Saclay MeP 5.75 8.0 Normal
30 2025-07-26 12:44:21 Saclay MeP 3.25 8.0 Normal
31 2025-07-26 12:39:19 Saclay MeP 4.75 8.0 Normal
32 2025-07-26 07:09:45 Meudon Viandes 3.94 6.0 Normal
33 2025-07-25 14:37:50 Meudon Viandes 3.94 6.0 Normal
34 2025-07-25 14:32:11 Meudon Viandes 3.94 6.0 Normal
35 2025-07-25 14:30:20 Meudon Viandes 3.94 6.0 Normal
36 2025-07-24 11:00:36 Meudon Viandes 3.94 6.0 Normal
37 2025-07-24 10:41:08 Meudon Viandes 3.94 6.0 Normal
38 2025-07-26 07:09:45 Meudon Poissons 3.94 6.0 Normal
39 2025-07-25 14:37:50 Meudon Poissons 3.94 6.0 Normal
40 2025-07-25 14:32:11 Meudon Poissons 3.94 6.0 Normal
41 2025-07-25 14:30:20 Meudon Poissons 3.94 6.0 Normal
42 2025-07-24 11:00:36 Meudon Poissons 3.94 6.0 Normal
43 2025-07-24 10:41:08 Meudon Poissons 3.94 6.0 Normal
44 2025-07-26 07:09:45 Meudon BOF 3.00 8.0 Normal
45 2025-07-25 14:37:50 Meudon BOF 3.00 8.0 Normal
46 2025-07-25 14:32:11 Meudon BOF 3.00 8.0 Normal
47 2025-07-25 14:30:20 Meudon BOF 3.00 8.0 Normal
48 2025-07-24 11:00:36 Meudon BOF 3.00 8.0 Normal
49 2025-07-24 10:41:08 Meudon BOF 3.00 8.0 Normal

View File

@@ -2,9 +2,10 @@ import os
import time import time
from datetime import datetime, timedelta from datetime import datetime, timedelta
from pathlib import Path from pathlib import Path
from db_utils import connect_to_mysql from app.utils_db import connect_to_mysql
from dotenv import load_dotenv from dotenv import load_dotenv
from utils_sms import envoyer_sms from app.utils_sms import envoyer_sms
if os.name != 'nt': if os.name != 'nt':
log_dir = Path('/home/debian/Gestion_sondes/Logs') log_dir = Path('/home/debian/Gestion_sondes/Logs')
@@ -37,7 +38,13 @@ def surveiller():
table_temp = lieu table_temp = lieu
table_alertes = f"Alertes_{lieu}" table_alertes = f"Alertes_{lieu}"
cursor.execute("SELECT Sonde, Temp_Max FROM `Chambres_froides` WHERE Lieu=%s AND Etat='ON'", (lieu,)) cursor.execute("""
SELECT Sonde, Temp_Max
FROM Sondes.Chambres_froides
WHERE Lieu = %s
AND Etat = 'ON'
AND En_entretien = 0
""", (lieu,))
sondes = cursor.fetchall() sondes = cursor.fetchall()
for sonde in sondes: for sonde in sondes:

View File

@@ -1,25 +1,12 @@
import streamlit as st import streamlit as st
import pandas as pd import pandas as pd
import mysql.connector
from utils.db import (
get_latest_chaufferie,
get_history_by_sonde,
verifier_utilisateur_commun,
lire_alertes_sondes,
acquitter_alerte
)
import altair as alt import altair as alt
from dotenv import load_dotenv from dotenv import load_dotenv
import os from .utils_db import connect_to_mysql
st.set_page_config(page_title="Tech Chaufferie", layout="wide") st.set_page_config(page_title="Tech Chaufferie", layout="wide")
load_dotenv() # charger .env à la racine du projet load_dotenv() # charger .env à la racine du projet
# Accès aux variables d'environnement
MYSQL_HOST = os.getenv("DB_HOST")
MYSQL_USER = os.getenv("DB_USER")
MYSQL_PASSWORD = os.getenv("DB_PASSWORD")
MYSQL_DATABASE = os.getenv("DB_NAME")
def login_commun(): def login_commun():
login = st.text_input("Identifiant", type="default") login = st.text_input("Identifiant", type="default")
@@ -108,12 +95,6 @@ if sonde_selection:
conn = None conn = None
cursor = None cursor = None
try: try:
conn = mysql.connector.connect(
host=MYSQL_HOST,
user=MYSQL_USER,
password=MYSQL_PASSWORD,
database=MYSQL_DATABASE
)
cursor = conn.cursor() cursor = conn.cursor()
# Vérifie s'il existe déjà une alerte en cours # Vérifie s'il existe déjà une alerte en cours

0
app/_init_.py Normal file
View File

View File

@@ -1,26 +1,7 @@
# utils/db.py # utils/db.py
import mysql.connector
import os
import sys
import logging
from datetime import datetime from datetime import datetime
from app.utils_db import connect_to_mysql # ✅ Import centralisé
def connect_to_mysql(db_name: str = None):
"""Connexion à MySQL via variables d'environnement."""
try:
mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"),
database=db_name if db_name else os.getenv("DB_NAME")
)
return mydb
except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1)
def get_latest_chaufferie(): def get_latest_chaufferie():
"""Renvoie les dernières valeurs par sonde dans la table 'Chaufferie'.""" """Renvoie les dernières valeurs par sonde dans la table 'Chaufferie'."""
@@ -28,10 +9,10 @@ def get_latest_chaufferie():
cursor = db.cursor(dictionary=True) cursor = db.cursor(dictionary=True)
query = """ query = """
SELECT c1.* SELECT c1.*
FROM Chaufferie c1 FROM Sondes.Chaufferie c1
INNER JOIN ( INNER JOIN (
SELECT Sonde, MAX(Date) AS MaxDate SELECT Sonde, MAX(Date) AS MaxDate
FROM Chaufferie FROM Sondes.Chaufferie
GROUP BY Sonde GROUP BY Sonde
) c2 ON c1.Sonde = c2.Sonde AND c1.Date = c2.MaxDate ) c2 ON c1.Sonde = c2.Sonde AND c1.Date = c2.MaxDate
ORDER BY c1.Sonde; ORDER BY c1.Sonde;
@@ -48,7 +29,7 @@ def get_history_by_sonde(sonde: str, start: datetime, end: datetime):
db = connect_to_mysql() db = connect_to_mysql()
cursor = db.cursor(dictionary=True) cursor = db.cursor(dictionary=True)
query = """ query = """
SELECT * FROM Chaufferie SELECT * FROM Sondes.Chaufferie
WHERE Sonde = %s AND Date BETWEEN %s AND %s WHERE Sonde = %s AND Date BETWEEN %s AND %s
ORDER BY Date; ORDER BY Date;
""" """
@@ -64,8 +45,8 @@ def verifier_utilisateur_commun(utilisateur: str, motdepasse: str):
db = connect_to_mysql() db = connect_to_mysql()
cursor = db.cursor(dictionary=True) cursor = db.cursor(dictionary=True)
query = """ query = """
SELECT * FROM MotsDePasse SELECT * FROM Sondes.MotsDePasse
WHERE utilisateur = %s AND motdepasse = %s AND role = 'utilisateur' WHERE utilisateur = %s AND mot_de_passe = %s AND role = 'utilisateur'
""" """
cursor.execute(query, (utilisateur, motdepasse)) cursor.execute(query, (utilisateur, motdepasse))
result = cursor.fetchone() result = cursor.fetchone()
@@ -79,7 +60,7 @@ def lire_alertes_sondes():
db = connect_to_mysql() db = connect_to_mysql()
cursor = db.cursor(dictionary=True) cursor = db.cursor(dictionary=True)
query = """ query = """
SELECT * FROM Alertes_Chaufferie SELECT * FROM Sondes.Alertes_Chaufferie
WHERE Etat != 'Acquitté' WHERE Etat != 'Acquitté'
ORDER BY Debut_defaut DESC ORDER BY Debut_defaut DESC
""" """
@@ -94,7 +75,7 @@ def acquitter_alerte(id_alerte: int):
"""Met à jour une alerte comme acquittée dans la base.""" """Met à jour une alerte comme acquittée dans la base."""
db = connect_to_mysql() db = connect_to_mysql()
cursor = db.cursor() cursor = db.cursor()
query = "UPDATE Alertes_Chaufferie SET Etat = 'Acquitté' WHERE Id = %s" query = "UPDATE Sondes.Alertes_Chaufferie SET Etat = 'Acquitté' WHERE Id = %s"
cursor.execute(query, (id_alerte,)) cursor.execute(query, (id_alerte,))
db.commit() db.commit()
cursor.close() cursor.close()

View File

@@ -1,35 +1,35 @@
import os import os
import logging import logging
def setup_logger(log_filename: str, dossier_logs: str = "/var/log/Cuisine_Saclay") -> None: def setup_logger(log_filename: str, dossier_logs: str = "/var/log/Cuisine_Saclay") -> None:
""" """
Configure le logger pour écrire à la fois dans un fichier et sur la console. Configure le logger pour écrire à la fois dans un fichier et sur la console.
:param log_filename: Nom du fichier de log (exemple : 'Cuisine_Saclay.log') :param log_filename: Nom du fichier de log (exemple : 'Cuisine_Saclay.log')
:param dossier_logs: Dossier enregistrer les logs (par défaut : /var/log/Cuisine_Saclay) :param dossier_logs: Dossier enregistrer les logs (par défaut : /var/log/Cuisine_Saclay)
""" """
# 📁 Créer le dossier s'il n'existe pas # 📁 Créer le dossier s'il n'existe pas
os.makedirs(dossier_logs, exist_ok=True) os.makedirs(dossier_logs, exist_ok=True)
# 📄 Chemin complet du fichier de log # 📄 Chemin complet du fichier de log
logfile = os.path.join(dossier_logs, log_filename) logfile = os.path.join(dossier_logs, log_filename)
# 📝 Configuration de base du logger (fichier) # 📝 Configuration de base du logger (fichier)
logging.basicConfig( logging.basicConfig(
filename=logfile, filename=logfile,
level=logging.INFO, level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s", format="%(asctime)s - %(levelname)s - %(message)s",
filemode="a" # ajouter au fichier existant filemode="a" # ajouter au fichier existant
) )
# 🔔 Ajout de la sortie console # 🔔 Ajout de la sortie console
console = logging.StreamHandler() console = logging.StreamHandler()
console.setLevel(logging.INFO) console.setLevel(logging.INFO)
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s") formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
console.setFormatter(formatter) console.setFormatter(formatter)
# 👇 Ajouter le handler console au logger racine # 👇 Ajouter le handler console au logger racine
logging.getLogger('').addHandler(console) logging.getLogger('').addHandler(console)
logging.info(f"Logger initialisé. Fichier de log : {logfile}") logging.info(f"Logger initialisé. Fichier de log : {logfile}")

View File

@@ -1,48 +1,48 @@
import argparse import argparse
import paho.mqtt.client as mqtt_client import paho.mqtt.client as mqtt_client
from dotenv import load_dotenv from dotenv import load_dotenv
import logging import logging
from logger_config import setup_logger from app.logger_config import setup_logger
from db_utils import connect_to_mysql from utils_db import connect_to_mysql
from functools import partial from functools import partial
def on_message(table_sql, _client, _userdata, msg): def on_message(table_sql, _client, _userdata, msg):
try: try:
logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}") logging.info(f"Message reçu sur {msg.topic}: {msg.payload.decode()}")
cursor = mydb.cursor() cursor = mydb.cursor()
sonde_name = '/'.join(msg.topic.split('/')[1:]) sonde_name = '/'.join(msg.topic.split('/')[1:])
sql = f"INSERT INTO {table_sql} (Sonde, Temperature) VALUES (%s, %s)" sql = f"INSERT INTO {table_sql} (Sonde, Temperature) VALUES (%s, %s)"
val = (sonde_name, msg.payload.decode()) val = (sonde_name, msg.payload.decode())
cursor.execute(sql, val) cursor.execute(sql, val)
mydb.commit() mydb.commit()
logging.info(f"Insertion réussie : {val}") logging.info(f"Insertion réussie : {val}")
except Exception as e: except Exception as e:
logging.error(f"Erreur lors de l'insertion du message : {e}") logging.error(f"Erreur lors de l'insertion du message : {e}")
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--log", required=True, help="Nom du fichier de log") parser.add_argument("--log", required=True, help="Nom du fichier de log")
parser.add_argument("--table", required=True, help="Nom complet de la table SQL") parser.add_argument("--table", required=True, help="Nom complet de la table SQL")
parser.add_argument("--topic", required=True, help="Topic MQTT à écouter") parser.add_argument("--topic", required=True, help="Topic MQTT à écouter")
args = parser.parse_args() args = parser.parse_args()
# 📋 Initialiser le logger # 📋 Initialiser le logger
setup_logger(args.log) setup_logger(args.log)
# 🔑 Charger les variables d'environnement # 🔑 Charger les variables d'environnement
load_dotenv() load_dotenv()
# 🔌 Connexion MySQL # 🔌 Connexion MySQL
mydb = connect_to_mysql() mydb = connect_to_mysql()
# 📡 Connexion MQTT # 📡 Connexion MQTT
try: try:
client = mqtt_client.Client() client = mqtt_client.Client()
client.username_pw_set("Bwps", "scJ5ACj2keRfI^") client.username_pw_set("Bwps", "scJ5ACj2keRfI^")
client.on_message = partial(on_message, args.table) client.on_message = partial(on_message, args.table)
client.connect("54.36.188.119", 1883, 60) client.connect("54.36.188.119", 1883, 60)
client.subscribe(args.topic) client.subscribe(args.topic)
logging.info(f"Connexion MQTT réussie et abonnement au topic '{args.topic}'.") logging.info(f"Connexion MQTT réussie et abonnement au topic '{args.topic}'.")
client.loop_forever() client.loop_forever()
except Exception as err: except Exception as err:
logging.error(f"Erreur MQTT : {err}") logging.error(f"Erreur MQTT : {err}")

View File

View File

@@ -3,7 +3,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from dotenv import load_dotenv from dotenv import load_dotenv
import os import os
import db_utils import utils_db
import logging import logging
from utils_sms import envoyer_sms from utils_sms import envoyer_sms
@@ -62,7 +62,7 @@ def clear_state(site):
os.remove(state_file) os.remove(state_file)
def main(): def main():
cnx = db_utils.connect_to_mysql() # ← appel via db_utils cnx = utils_db.connect_to_mysql() # ← appel via db_utils
cursor = cnx.cursor() cursor = cnx.cursor()
now = datetime.now() now = datetime.now()

View File

@@ -1,23 +1,23 @@
import mysql.connector import mysql.connector
import os import os
import sys import sys
import logging import logging
def connect_to_mysql(db_name: str = None): def connect_to_mysql(db_name: str = None):
""" """
Se connecte à MySQL. Par défaut, utilise la base spécifiée dans DB_NAME, Se connecte à MySQL. Par défaut, utilise la base spécifiée dans DB_NAME,
mais peut être redirigé vers une autre base en passant db_name. mais peut être redirigé vers une autre base en passant db_name.
""" """
try: try:
sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages") # à ajuster si inutile sys.path.insert(0, "/myenv/lib/python3.11.2/site-packages") # à ajuster si inutile
mydb = mysql.connector.connect( mydb = mysql.connector.connect(
host=os.getenv("DB_HOST"), host=os.getenv("DB_HOST"),
user=os.getenv("DB_USER"), user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD"), password=os.getenv("DB_PASSWORD"),
database=db_name if db_name else os.getenv("DB_NAME") database=db_name if db_name else os.getenv("DB_NAME")
) )
logging.info(f"Connexion MySQL à la base {mydb.database} réussie.") logging.info(f"Connexion MySQL à la base {mydb.database} réussie.")
return mydb return mydb
except mysql.connector.Error as err: except mysql.connector.Error as err:
logging.error(f"Erreur de connexion MySQL : {err}") logging.error(f"Erreur de connexion MySQL : {err}")
sys.exit(1) sys.exit(1)

View File

@@ -1,34 +1,34 @@
import os import os
import ovh import ovh
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
def envoyer_sms(message: str, lieu: str = ""): def envoyer_sms(message: str, lieu: str = ""):
try: try:
client = ovh.Client( client = ovh.Client(
endpoint=os.getenv("OVH_ENDPOINT"), endpoint=os.getenv("OVH_ENDPOINT"),
application_key=os.getenv("OVH_APP_KEY"), application_key=os.getenv("OVH_APP_KEY"),
application_secret=os.getenv("OVH_APP_SECRET"), application_secret=os.getenv("OVH_APP_SECRET"),
consumer_key=os.getenv("OVH_CONSUMER_KEY"), consumer_key=os.getenv("OVH_CONSUMER_KEY"),
) )
services = client.get('/sms/') services = client.get('/sms/')
if not services: if not services:
print("❌ Aucun service SMS OVH trouvé", flush=True) print("❌ Aucun service SMS OVH trouvé", flush=True)
return return
service_name = services[0] service_name = services[0]
numero_dest = os.getenv("NUMERO_DESTINATAIRE") numero_dest = os.getenv("NUMERO_DESTINATAIRE")
result = client.post(f'/sms/{service_name}/jobs', result = client.post(f'/sms/{service_name}/jobs',
sender='Monitor', sender='Monitor',
message=message, message=message,
receivers=[numero_dest], receivers=[numero_dest],
noStopClause=True noStopClause=True
) )
print(f"📱 SMS envoyé à {numero_dest} pour {lieu}. Job ID : {result['ids']}", flush=True) print(f"📱 SMS envoyé à {numero_dest} pour {lieu}. Job ID : {result['ids']}", flush=True)
except Exception as e: except Exception as e:
print(f"Erreur envoi SMS : {e}", flush=True) print(f"Erreur envoi SMS : {e}", flush=True)