Add French docstrings and README

- Docstrings for all modules, classes and methods
- README.md with installation and usage instructions
- Update CLAUDE.md with dns.py

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-26 18:25:20 +01:00
parent 9f3c052e2a
commit b0d571ae26
8 changed files with 341 additions and 18 deletions

View File

@@ -1,6 +1,17 @@
#!/usr/bin/env python3
"""
LAN Checker - Network health monitoring with MQTT reporting for Home Assistant.
LAN Checker - Surveillance réseau avec reporting MQTT pour Home Assistant.
Ce script vérifie périodiquement l'état de services et équipements réseau,
puis publie les résultats via MQTT en utilisant le protocole MQTT Discovery
de Home Assistant pour créer automatiquement les entités.
Usage:
python lan_checker.py [-c CONFIG]
Exemples:
python lan_checker.py
python lan_checker.py -c /etc/lan_checker/config.yaml
"""
import argparse
@@ -24,13 +35,47 @@ logger = logging.getLogger(__name__)
class LanChecker:
"""
Gestionnaire principal de surveillance réseau.
Charge la configuration, établit la connexion MQTT, exécute les
vérifications périodiques et publie les résultats.
Attributes:
config: Configuration chargée depuis le fichier YAML.
mqtt_client: Client MQTT pour la publication des résultats.
running: Flag d'exécution de la boucle principale.
checks: Liste des vérifications configurées.
"""
def __init__(self, config_path: str):
"""
Initialise le gestionnaire.
Args:
config_path: Chemin vers le fichier de configuration YAML.
Raises:
FileNotFoundError: Si le fichier de configuration n'existe pas.
"""
self.config = self._load_config(config_path)
self.mqtt_client: mqtt.Client | None = None
self.running = False
self.checks = []
def _load_config(self, config_path: str) -> dict:
"""
Charge la configuration depuis un fichier YAML.
Args:
config_path: Chemin vers le fichier de configuration.
Returns:
Dictionnaire contenant la configuration.
Raises:
FileNotFoundError: Si le fichier n'existe pas.
"""
path = Path(config_path)
if not path.exists():
raise FileNotFoundError(f"Configuration file not found: {config_path}")
@@ -39,6 +84,12 @@ class LanChecker:
return yaml.safe_load(f)
def _setup_mqtt(self):
"""
Configure et connecte le client MQTT.
Utilise les paramètres de la section 'mqtt' de la configuration.
Configure l'authentification si un nom d'utilisateur est fourni.
"""
mqtt_config = self.config["mqtt"]
self.mqtt_client = mqtt.Client(
mqtt.CallbackAPIVersion.VERSION2,
@@ -62,6 +113,19 @@ class LanChecker:
self.mqtt_client.loop_start()
def _on_mqtt_connect(self, client, userdata, flags, reason_code, properties):
"""
Callback appelé lors de la connexion au broker MQTT.
Publie les messages de découverte Home Assistant si la connexion
est réussie.
Args:
client: Instance du client MQTT.
userdata: Données utilisateur (non utilisé).
flags: Flags de connexion.
reason_code: Code de résultat de la connexion.
properties: Propriétés MQTT v5 (non utilisé).
"""
if reason_code == 0:
logger.info("Connected to MQTT broker")
self._publish_discovery()
@@ -69,15 +133,35 @@ class LanChecker:
logger.error(f"MQTT connection failed: {reason_code}")
def _on_mqtt_disconnect(self, client, userdata, flags, reason_code, properties):
"""
Callback appelé lors de la déconnexion du broker MQTT.
Args:
client: Instance du client MQTT.
userdata: Données utilisateur (non utilisé).
flags: Flags de déconnexion.
reason_code: Code de raison de la déconnexion.
properties: Propriétés MQTT v5 (non utilisé).
"""
logger.warning(f"Disconnected from MQTT broker: {reason_code}")
def _publish_discovery(self):
"""Publish MQTT Discovery messages for Home Assistant."""
"""
Publie les messages MQTT Discovery pour Home Assistant.
Pour chaque check configuré, publie:
- Un binary_sensor pour l'état online/offline
- Un sensor pour la latence (temps de réponse)
- Un sensor pour la température (SNMP uniquement, si configuré)
Les entités sont automatiquement créées dans Home Assistant
grâce au protocole MQTT Discovery.
"""
for check in self.config["checks"]:
device_id = check["id"]
device_name = check["name"]
# Binary sensor for online/offline status
# Binary sensor pour l'état online/offline
status_config = {
"name": f"{device_name} Status",
"unique_id": f"lan_checker_{device_id}_status",
@@ -99,7 +183,7 @@ class LanChecker:
retain=True
)
# Sensor for response time
# Sensor pour le temps de réponse
latency_config = {
"name": f"{device_name} Latency",
"unique_id": f"lan_checker_{device_id}_latency",
@@ -121,7 +205,7 @@ class LanChecker:
retain=True
)
# Sensor for temperature (SNMP only, if temperature_oid configured)
# Sensor pour la température (SNMP uniquement)
if check.get("type") == "snmp" and check.get("temperature_oid"):
temp_config = {
"name": f"{device_name} Temperature",
@@ -147,7 +231,12 @@ class LanChecker:
logger.info(f"Published discovery for: {device_name}")
def _setup_checks(self):
"""Initialize check instances from configuration."""
"""
Initialise les instances de checkers depuis la configuration.
Parcourt la liste des checks dans la configuration et crée
une instance du checker approprié pour chacun.
"""
for check_config in self.config["checks"]:
check_type = check_config["type"]
if check_type not in CHECKERS:
@@ -165,7 +254,13 @@ class LanChecker:
})
def _run_check(self, check: dict):
"""Execute a single check and publish results."""
"""
Exécute une vérification et publie le résultat via MQTT.
Args:
check: Dictionnaire contenant l'id, le nom, le checker
et l'intervalle de vérification.
"""
result = check["checker"].check()
state = "online" if result.success else "offline"
@@ -177,7 +272,7 @@ class LanChecker:
}
if result.details:
# Extract temperature for SNMP checks
# Extrait la température des détails pour la mettre à la racine
if "temperature" in result.details:
payload["temperature"] = result.details.pop("temperature")
if result.details:
@@ -190,7 +285,12 @@ class LanChecker:
logger.log(log_level, f"{check['name']}: {state} - {result.message}")
def run(self):
"""Main loop."""
"""
Lance la boucle principale de surveillance.
Configure MQTT, initialise les checkers, puis exécute les
vérifications en boucle selon leurs intervalles respectifs.
"""
self._setup_mqtt()
self._setup_checks()
@@ -208,7 +308,11 @@ class LanChecker:
time.sleep(1)
def stop(self):
"""Stop the checker gracefully."""
"""
Arrête proprement le gestionnaire.
Stoppe la boucle principale et déconnecte le client MQTT.
"""
logger.info("Stopping LAN Checker...")
self.running = False
if self.mqtt_client:
@@ -217,6 +321,12 @@ class LanChecker:
def main():
"""
Point d'entrée principal.
Parse les arguments de ligne de commande, configure les gestionnaires
de signaux et lance le checker.
"""
parser = argparse.ArgumentParser(description="LAN Checker - Network health monitoring")
parser.add_argument(
"-c", "--config",
@@ -228,6 +338,7 @@ def main():
checker = LanChecker(args.config)
def signal_handler(sig, frame):
"""Gestionnaire de signaux pour arrêt propre."""
checker.stop()
sys.exit(0)