Améliorer la gestion des configurations et des captures dans les scripts de timelapse

This commit is contained in:
2025-04-27 17:06:55 +02:00
parent 610d220c3f
commit 2013c2cf41
6 changed files with 230 additions and 45 deletions

View File

@@ -26,43 +26,90 @@ def main():
# Récupérer le statut de la caméra depuis l'API # Récupérer le statut de la caméra depuis l'API
camera_status = api_client.get_camera_status() camera_status = api_client.get_camera_status()
if camera_status is None: # Vérifier si la configuration actuelle est déjà active et non terminée
logging.error("Impossible d'obtenir le statut de la caméra depuis l'API") is_active_config = config.get("config_active", False)
return images_remaining = config.get("nb_images_restantes", 0)
# Mettre à jour la configuration locale
api_client.update_camera_config(camera_status)
# Vérifier l'état de maintenance if camera_status is None:
logging.warning("Impossible d'obtenir le statut de la caméra depuis l'API")
if is_active_config and images_remaining > 0:
logging.info("Utilisation de la configuration locale existante")
return
logging.info("Aucune configuration active et impossibilité de récupérer le statut")
return
# Vérifier l'état de maintenance en priorité
if camera_status.get("maintenance", False): if camera_status.get("maintenance", False):
logging.info("Caméra en mode maintenance, aucune action nécessaire") logging.info("Caméra en mode maintenance, aucune action nécessaire")
# Mettre à jour la configuration pour refléter le mode maintenance
config.update_config({"maintenance": True, "config_active": False})
return return
# Vérifier si un arrêt de la procédure est demandé # Vérifier si un arrêt de la procédure est demandé
if camera_status.get("stop_flag", False): if camera_status.get("stop_flag", False):
logging.info("Arrêt de la procédure en cours...") logging.info("Arrêt de la procédure en cours...")
# Supprimer le fichier de configuration s'il existe # Réinitialiser les configurations actives
config.delete_config_file() config.update_config({
"config_active": False,
"nb_images_restantes": 0,
"stop_current_config": True
})
# Confirmer l'arrêt au serveur
confirmed = api_client.confirm_stop()
if confirmed:
logging.info("Arrêt confirmé au serveur")
else:
logging.warning("Échec de la confirmation d'arrêt au serveur")
# Configuration d'un redémarrage régulier pour vérifier les nouvelles configurations
config.set("restart_interval", 120) # 2 minutes
# Confirmer l'arrêt
api_client.confirm_stop()
return return
# Vérifier s'il y a une configuration à appliquer # Vérifier si le système est en IDLE et si une configuration est déjà active
if not camera_status.get("idle", True): is_idle = camera_status.get("idle", True)
logging.info("Configuration active détectée")
if is_idle:
# Obtenir les paramètres logging.info("Système en mode IDLE")
interval = camera_status.get("interval", 3) if is_active_config:
# Si le nombre d'images est atteint, désactiver la configuration
# Envoyer l'intervalle au microcontrôleur if images_remaining <= 0:
logging.info(f"Envoi de l'intervalle au microcontrôleur: {interval}s") logging.info("Configuration terminée: nombre d'images atteint")
micro_controller.send_interval(interval) config.update_config({"config_active": False})
else:
# Éteindre le système après configuration logging.info(f"Configuration active: il reste {images_remaining} images à capturer")
logging.info("Configuration terminée, arrêt du système") else:
subprocess.run(["sudo", "shutdown", "now"]) logging.info("Aucune configuration active, attente en mode IDLE")
# Configuration d'un redémarrage régulier pour vérifier les nouvelles configurations
config.set("restart_interval", 120) # 2 minutes
return
# Si on arrive ici, il y a une nouvelle configuration à appliquer
logging.info("Nouvelle configuration active détectée")
# Mettre à jour la configuration locale
config_update = {
"config_active": True,
"maintenance": False,
"timelapse": camera_status.get("interval", 3),
"conf_nb_images": camera_status.get("nb_images", 1),
"nb_images_restantes": camera_status.get("nb_images", 1),
"stop_current_config": False,
"idle": is_idle
}
config.update_config(config_update)
# Envoyer l'intervalle au microcontrôleur
interval = camera_status.get("interval", 3)
logging.info(f"Envoi de l'intervalle au microcontrôleur: {interval}s")
micro_controller.send_interval(interval)
# Éteindre le système après configuration (mais ne pas arrêter en prod)
# logging.info("Configuration terminée, arrêt du système")
# subprocess.run(["sudo", "shutdown", "now"])
except Exception as e: except Exception as e:
logging.error(f"Erreur dans le script d'automatisation: {e}") logging.error(f"Erreur dans le script d'automatisation: {e}")

View File

@@ -9,8 +9,10 @@ Remplace l'ancien Send_data_stocked.py
import os import os
import sys import sys
import logging import logging
import time
from timelapse.config import config from timelapse.config import config
from timelapse.capture import timelapse_manager from timelapse.capture import timelapse_manager
from timelapse.api_client import api_client
def main(): def main():
@@ -21,14 +23,46 @@ def main():
logging.info("Démarrage de la synchronisation des données hors ligne") logging.info("Démarrage de la synchronisation des données hors ligne")
try: try:
# Vérifier la connexion au serveur
camera_status = api_client.get_camera_status()
if camera_status is None:
logging.error("Impossible de se connecter au serveur. Synchronisation reportée.")
sys.exit(1)
# Vérifier si le système est en maintenance
if camera_status.get("maintenance", False):
logging.info("Caméra en mode maintenance, aucune synchronisation effectuée")
sys.exit(0)
# Synchroniser les captures hors ligne # Synchroniser les captures hors ligne
start_time = time.time()
sync_count = timelapse_manager.sync_offline_captures() sync_count = timelapse_manager.sync_offline_captures()
duration = time.time() - start_time
if sync_count > 0: if sync_count > 0:
logging.info(f"Synchronisation réussie de {sync_count} captures") logging.info(f"Synchronisation réussie de {sync_count} captures en {duration:.2f} secondes")
# Vérifier s'il reste des images à synchroniser
remaining_offline = timelapse_manager.count_offline_captures()
if remaining_offline > 0:
logging.info(f"Il reste encore {remaining_offline} captures à synchroniser")
else:
logging.info("Toutes les captures hors ligne ont été synchronisées")
else: else:
logging.info("Aucune capture à synchroniser") logging.info("Aucune capture à synchroniser")
# Vérifier si un arrêt est demandé
if camera_status.get("stop_flag", False):
logging.info("Demande d'arrêt détectée, confirmation au serveur")
api_client.confirm_stop()
# Réinitialiser l'état actif
config.update_config({
"config_active": False,
"nb_images_restantes": 0,
"stop_current_config": True
})
except Exception as e: except Exception as e:
logging.error(f"Erreur lors de la synchronisation des données: {e}") logging.error(f"Erreur lors de la synchronisation des données: {e}")
sys.exit(1) sys.exit(1)

View File

@@ -95,17 +95,35 @@ class APIClient:
return False return False
try: try:
# Récupérer l'état actuel pour comparaison
is_currently_active = config.get("config_active", False)
current_nb_images = config.get("conf_nb_images", 0)
# Vérifier si c'est une nouvelle configuration
is_new_config = (not is_currently_active and not status.get("idle", True))
# Préparer la mise à jour
config_update = { config_update = {
"maintenance": status.get("maintenance", False), "maintenance": status.get("maintenance", False),
"timelapse": status.get("interval", 3), "timelapse": status.get("interval", 3),
"conf_nb_images": status.get("nb_images", 1), "conf_nb_images": status.get("nb_images", 1),
"nb_images_restantes": status.get("nb_images", 1), "idle": status.get("idle", True),
"set_config": status.get("idle", False),
"stop_current_config": status.get("stop_flag", False) "stop_current_config": status.get("stop_flag", False)
} }
# Ne mettre à jour le nombre d'images restantes que pour une nouvelle configuration
# ou si la configuration est réinitialisée
if is_new_config or status.get("stop_flag", False):
config_update["nb_images_restantes"] = status.get("nb_images", 1)
config_update["config_active"] = not status.get("idle", True)
if is_new_config:
logging.info(f"Nouvelle configuration: {status.get('nb_images', 1)} images à capturer")
# Mise à jour de la configuration
config.update_config(config_update) config.update_config(config_update)
logging.info("Configuration mise à jour depuis l'API") logging.info("Configuration mise à jour depuis l'API")
return True return True
except Exception as e: except Exception as e:

View File

@@ -167,21 +167,62 @@ class TimelapseCaptureManager:
Args: Args:
online: Si la caméra est connectée au serveur online: Si la caméra est connectée au serveur
Returns:
bool: True si la séquence est terminée (toutes les images capturées), False sinon
""" """
# Vérifier si la configuration est active
is_active = config.get("config_active", False)
is_stopped = config.get("stop_current_config", False)
if not is_active or is_stopped:
logging.info("Aucune configuration active ou configuration arrêtée")
return True
# Vérifier si des images sont restantes à capturer # Vérifier si des images sont restantes à capturer
remaining_images = config.get("nb_images_restantes", 0) remaining_images = config.get("nb_images_restantes", 0)
if remaining_images > 0: if remaining_images <= 0:
logging.info(f"Démarrage d'une séquence de capture ({remaining_images} images restantes)") logging.info("Toutes les images ont été capturées")
# Désactiver la configuration active
# Capturer une image config.update_config({"config_active": False})
self.single_capture(online) return True
logging.info(f"Démarrage d'une séquence de capture ({remaining_images} images restantes)")
# Capturer une image
result = self.single_capture(online)
if result:
# Décrémenter le compteur d'images restantes # Décrémenter le compteur d'images restantes
remaining_images = config.decrement_remaining_images() remaining_images = config.decrement_remaining_images()
logging.info(f"Images restantes: {remaining_images}") logging.info(f"Images restantes: {remaining_images}")
# Vérifier si c'était la dernière image
if remaining_images <= 0:
logging.info("Toutes les images ont été capturées")
# Désactiver la configuration active
config.update_config({"config_active": False})
return True
else: else:
logging.info("Aucune image restante à capturer") logging.error("Échec de la séquence de capture")
return False
def count_offline_captures(self):
"""
Compte le nombre de captures hors ligne en attente de synchronisation.
Returns:
int: Nombre de captures hors ligne
"""
if not os.path.exists(self.offline_dir):
return 0
offline_dirs = [d for d in os.listdir(self.offline_dir)
if os.path.isdir(os.path.join(self.offline_dir, d))]
return len(offline_dirs)
# Instance globale du gestionnaire de capture # Instance globale du gestionnaire de capture

View File

@@ -23,22 +23,41 @@ def main():
logging.info("Démarrage de la capture d'images en mode hors ligne") logging.info("Démarrage de la capture d'images en mode hors ligne")
try: try:
# Chargement de la configuration # Vérifier si une configuration active existe
is_active_config = config.get("config_active", False)
is_stopped = config.get("stop_current_config", False)
remaining_images = config.get("nb_images_restantes", 0) remaining_images = config.get("nb_images_restantes", 0)
interval = config.get("timelapse", 3) # Intervalle par défaut: 3 secondes
logging.info(f"Configuration: {remaining_images} images à capturer, intervalle de {interval}s") # Si arrêté ou pas de configuration active, ne rien faire
if is_stopped:
if remaining_images <= 0: logging.info("Configuration arrêtée, aucune action à effectuer")
logging.info("Aucune image à capturer en mode hors ligne")
return return
# Exécuter la séquence de capture en mode hors ligne if not is_active_config:
timelapse_manager.run_capture_sequence(online=False) logging.info("Aucune configuration active en mode hors ligne")
return
if remaining_images <= 0:
logging.info("Aucune image restante à capturer")
# Désactiver la configuration puisqu'elle est terminée
config.update_config({"config_active": False})
return
# Envoi de l'intervalle au microcontrôleur si nécessaire logging.info(f"Configuration: {remaining_images} images à capturer")
if interval > 0:
# Exécuter la séquence de capture en mode hors ligne
sequence_completed = timelapse_manager.run_capture_sequence(online=False)
# Obtenir l'intervalle de timelapse pour le microcontrôleur si nécessaire
interval = config.get("timelapse", 3)
if interval > 0 and is_active_config and not sequence_completed:
logging.info(f"Envoi de l'intervalle au microcontrôleur: {interval}s")
micro_controller.send_interval(interval) micro_controller.send_interval(interval)
else:
# Si la séquence est terminée, réinitialiser l'intervalle
if sequence_completed:
logging.info("Séquence terminée, réinitialisation de l'intervalle")
micro_controller.send_interval(0) # 0 pour désactiver
except Exception as e: except Exception as e:
logging.error(f"Erreur lors de la capture en mode hors ligne: {e}") logging.error(f"Erreur lors de la capture en mode hors ligne: {e}")

View File

@@ -28,6 +28,14 @@ def main():
if status is None: if status is None:
logging.error("Impossible d'obtenir le statut de la caméra depuis l'API") logging.error("Impossible d'obtenir le statut de la caméra depuis l'API")
# Dans le cas où une configuration active existe déjà, continuer avec celle-ci
if config.get("config_active", False) and config.get("nb_images_restantes", 0) > 0:
logging.info("Utilisation de la configuration locale existante")
timelapse_manager.run_capture_sequence(online=False) # Mode hors ligne si API inaccessible
else:
logging.info("Pas de configuration active, abandon de la capture")
sys.exit(1) sys.exit(1)
# Mise à jour de la configuration # Mise à jour de la configuration
@@ -42,10 +50,28 @@ def main():
if status.get("stop_flag", False): if status.get("stop_flag", False):
logging.info("Demande d'arrêt détectée, confirmation au serveur") logging.info("Demande d'arrêt détectée, confirmation au serveur")
api_client.confirm_stop() api_client.confirm_stop()
# Réinitialiser l'état actif
config.update_config({
"config_active": False,
"nb_images_restantes": 0
})
sys.exit(0)
# Si le mode est IDLE et qu'aucune configuration n'est active, ne rien faire
if status.get("idle", True) and not config.get("config_active", False):
logging.info("Mode IDLE, aucune action à effectuer")
sys.exit(0) sys.exit(0)
# Exécuter la séquence de capture # Exécuter la séquence de capture
timelapse_manager.run_capture_sequence(online=True) sequence_completed = timelapse_manager.run_capture_sequence(online=True)
# Si la séquence est terminée (toutes les images capturées), notifier l'API
if sequence_completed and config.get("nb_images_restantes", 0) <= 0:
logging.info("Toutes les images ont été capturées, notification au serveur")
# TODO: Implémenter une méthode pour notifier la fin de la séquence
# api_client.notify_sequence_complete()
except Exception as e: except Exception as e:
logging.error(f"Erreur lors de la capture en mode connecté: {e}") logging.error(f"Erreur lors de la capture en mode connecté: {e}")