167 lines
4.4 KiB
Python
167 lines
4.4 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Mqtt_saclay.py
|
|
Récupère les mesures MQTT du site Saclay et les insère dans la table Sondes.Saclay.
|
|
"""
|
|
|
|
import os
|
|
import logging
|
|
from logging.handlers import RotatingFileHandler
|
|
|
|
import mysql.connector
|
|
from mysql.connector import Error
|
|
|
|
import paho.mqtt.client as mqtt
|
|
from paho.mqtt.client import CallbackAPIVersion
|
|
|
|
from dotenv import load_dotenv
|
|
|
|
# =========================
|
|
# Chargement du .env
|
|
# =========================
|
|
load_dotenv()
|
|
|
|
DB_HOST = os.getenv("DB_HOST")
|
|
DB_USER = os.getenv("DB_USER")
|
|
DB_PASS = os.getenv("DB_PASS")
|
|
DB_NAME = os.getenv("DB_NAME")
|
|
|
|
MQTT_HOST = "162.19.78.131"
|
|
MQTT_USER = "sondes"
|
|
MQTT_PASS = "3J@bjYP0"
|
|
MQTT_PORT = int(os.getenv("MQTT_PORT", 1883))
|
|
|
|
GYRO_TOPIC_SACLAY = os.getenv("GYRO_MQTT_TOPIC_SACLAY", "Saclay/gyrophare")
|
|
TABLE_NAME = "Saclay"
|
|
|
|
# =========================
|
|
# Logging
|
|
# =========================
|
|
def setup_logging():
|
|
logger = logging.getLogger()
|
|
logger.setLevel(logging.INFO)
|
|
|
|
formatter = logging.Formatter(
|
|
"%(asctime)s - %(levelname)s - %(message)s", datefmt="%Y-%m-%d %H:%M:%S"
|
|
)
|
|
|
|
# Console
|
|
console = logging.StreamHandler()
|
|
console.setFormatter(formatter)
|
|
logger.addHandler(console)
|
|
|
|
# Logs fichier
|
|
log_dir = os.getenv("LOG_DIR", "./Logs")
|
|
try:
|
|
os.makedirs(log_dir, exist_ok=True)
|
|
file_handler = RotatingFileHandler(
|
|
os.path.join(log_dir, "Mqtt_saclay.log"),
|
|
maxBytes=1_000_000,
|
|
backupCount=5,
|
|
encoding="utf-8",
|
|
)
|
|
file_handler.setFormatter(formatter)
|
|
logger.addHandler(file_handler)
|
|
except Exception as e:
|
|
logging.warning("Impossible de créer le fichier de log : %s", e)
|
|
|
|
|
|
# =========================
|
|
# Accès MySQL
|
|
# =========================
|
|
def insert_temperature(sonde: str, temperature: float) -> None:
|
|
try:
|
|
conn = mysql.connector.connect(
|
|
host=DB_HOST,
|
|
user=DB_USER,
|
|
password=DB_PASS,
|
|
database=DB_NAME,
|
|
)
|
|
|
|
cursor = conn.cursor()
|
|
sql = f"INSERT INTO {TABLE_NAME} (Sonde, Temperature) VALUES (%s, %s)"
|
|
cursor.execute(sql, (sonde, temperature))
|
|
conn.commit()
|
|
|
|
logging.info("Insertion OK -> %s = %.2f", sonde, temperature)
|
|
|
|
except Error as e:
|
|
logging.exception("Erreur MySQL pour la sonde %s : %s", sonde, e)
|
|
|
|
finally:
|
|
try:
|
|
if cursor:
|
|
cursor.close()
|
|
if conn and conn.is_connected():
|
|
conn.close()
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
# =========================
|
|
# Callbacks MQTT (API v2)
|
|
# =========================
|
|
def on_connect(client, userdata, flags, reason_code, properties=None):
|
|
if reason_code == 0:
|
|
logging.info("Connecté au broker MQTT (%s)", MQTT_HOST)
|
|
client.subscribe("Saclay/#")
|
|
logging.info("Abonné au topic : Saclay/#")
|
|
else:
|
|
logging.error("Échec de connexion MQTT, code retour = %s", reason_code)
|
|
|
|
|
|
def on_message(client, userdata, msg: mqtt.MQTTMessage):
|
|
topic = msg.topic
|
|
payload_raw = msg.payload.decode("utf-8", errors="ignore").strip()
|
|
|
|
logging.debug("Msg reçu : topic=%s payload=%s", topic, payload_raw)
|
|
|
|
if topic == GYRO_TOPIC_SACLAY:
|
|
return # on ignore le gyrophare
|
|
|
|
sonde = topic.split("/")[-1] if "/" in topic else topic
|
|
|
|
try:
|
|
value = float(payload_raw.replace(",", "."))
|
|
except ValueError:
|
|
logging.warning("Payload non numérique (topic=%s payload=%s)", topic, payload_raw)
|
|
return
|
|
|
|
insert_temperature(sonde, value)
|
|
|
|
|
|
# =========================
|
|
# Programme principal
|
|
# =========================
|
|
def main():
|
|
setup_logging()
|
|
logging.info("Démarrage du script Mqtt_saclay")
|
|
|
|
client = mqtt.Client(
|
|
client_id="Mqtt_saclay_client",
|
|
callback_api_version=CallbackAPIVersion.VERSION2
|
|
)
|
|
client.username_pw_set(MQTT_USER, MQTT_PASS)
|
|
|
|
client.on_connect = on_connect
|
|
client.on_message = on_message
|
|
|
|
try:
|
|
client.connect(MQTT_HOST, MQTT_PORT, keepalive=60)
|
|
except Exception as e:
|
|
logging.exception("Impossible de se connecter au broker MQTT : %s", e)
|
|
return
|
|
|
|
logging.info("Boucle MQTT en cours (Ctrl+C pour arrêter)...")
|
|
try:
|
|
client.loop_forever()
|
|
except KeyboardInterrupt:
|
|
logging.info("Arrêt demandé par l'utilisateur.")
|
|
finally:
|
|
client.disconnect()
|
|
logging.info("Déconnexion MQTT.")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|