From 2ddf2360e62c47919f2d8ea07d616547ebe83e06 Mon Sep 17 00:00:00 2001 From: ccunatbrule <32840852+DARKNAGAN@users.noreply.github.com> Date: Tue, 3 Sep 2024 12:17:44 +0200 Subject: [PATCH] CARIA.2.2 Update for the final presentation huge change with previous version --- .gitignore | 2 + WebControl/MainCLIControl.py | 130 +- WebControl/NOTE.txt | 13 +- .../apps/infrared_obstacle_avoidance.py | 52 +- WebControl/apps/infrared_tracking_objects.py | 35 - WebControl/apps/itineraire_create.py | 59 + WebControl/apps/itineraire_suivre.py | 75 + .../apps/itineraire_suivre_emergency.py | 170 ++ .../apps/itineraire_suivre_emergency_speed.py | 174 ++ WebControl/apps/lidar_speed_move.py | 56 + WebControl/apps/rfid_read_write_module.py | 31 + WebControl/apps/scenario_rfid.py | 71 + WebControl/css/styles.css | 42 +- WebControl/fixs/fix_motion.sh | 18 + WebControl/fixs/fix_rfid.sh | 10 + WebControl/fixs/reboot.sh | 7 + WebControl/images/Thumbs.db | Bin 22528 -> 22528 bytes .../requirements_server-car.txt} | 5 +- WebControl/js/bootstrap.bundle.min.js | 7 + WebControl/js/script.js | 145 +- WebControl/js/test_status.js | 21 + WebControl/logs/log.txt | 2458 ++++++++++++++++- WebControl/logs/motionlogs.txt | Bin 0 -> 4224 bytes WebControl/logs/resultats_tests.json | 1808 ++++++++++++ WebControl/logs/selected_steps.json | 78 + WebControl/logs/selected_steps_short.json | 22 + WebControl/logs/steps.json | 455 +++ WebControl/main.py | 246 +- WebControl/modules/AlphaBot.py | 375 ++- WebControl/modules/MFRC522-python.zip | Bin 99523 -> 0 bytes WebControl/modules/SimpleMFRC522.py | 89 + .../__pycache__/AlphaBot.cpython-39.pyc | Bin 0 -> 12372 bytes .../__pycache__/__init__.cpython-39.pyc | Bin 0 -> 137 bytes WebControl/modules/joyit_mfrc522/MFRC522.py | 413 +++ WebControl/modules/joyit_mfrc522/__init__.py | 4 + WebControl/templates/access.html | 57 + WebControl/templates/index.html | 222 +- WebControl/templates/tests.html | 45 +- WebControl/tests/infrared_obstacle_module.py | 59 +- WebControl/tests/lidar_module.py | 59 +- WebControl/tests/motor_speed_move.py | 75 +- WebControl/tests/rfid_open_door.py | 48 + WebControl/tests/rfid_read_write_module.py | 40 - WebControl/tests/servo_motor.py | 61 +- 44 files changed, 7080 insertions(+), 657 deletions(-) create mode 100644 .gitignore delete mode 100644 WebControl/apps/infrared_tracking_objects.py create mode 100644 WebControl/apps/itineraire_create.py create mode 100644 WebControl/apps/itineraire_suivre.py create mode 100644 WebControl/apps/itineraire_suivre_emergency.py create mode 100644 WebControl/apps/itineraire_suivre_emergency_speed.py create mode 100644 WebControl/apps/lidar_speed_move.py create mode 100644 WebControl/apps/rfid_read_write_module.py create mode 100644 WebControl/apps/scenario_rfid.py create mode 100644 WebControl/fixs/fix_motion.sh create mode 100644 WebControl/fixs/fix_rfid.sh create mode 100644 WebControl/fixs/reboot.sh rename WebControl/{package.txt => install/requirements_server-car.txt} (97%) create mode 100644 WebControl/js/bootstrap.bundle.min.js create mode 100644 WebControl/js/test_status.js create mode 100644 WebControl/logs/motionlogs.txt create mode 100644 WebControl/logs/resultats_tests.json create mode 100644 WebControl/logs/selected_steps.json create mode 100644 WebControl/logs/selected_steps_short.json create mode 100644 WebControl/logs/steps.json delete mode 100644 WebControl/modules/MFRC522-python.zip create mode 100644 WebControl/modules/SimpleMFRC522.py create mode 100644 WebControl/modules/__pycache__/AlphaBot.cpython-39.pyc create mode 100644 WebControl/modules/__pycache__/__init__.cpython-39.pyc create mode 100644 WebControl/modules/joyit_mfrc522/MFRC522.py create mode 100644 WebControl/modules/joyit_mfrc522/__init__.py create mode 100644 WebControl/templates/access.html create mode 100644 WebControl/tests/rfid_open_door.py delete mode 100644 WebControl/tests/rfid_read_write_module.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1f1c64b --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +Thumbs.db +.DS_Store diff --git a/WebControl/MainCLIControl.py b/WebControl/MainCLIControl.py index d0a7460..8ed50cb 100644 --- a/WebControl/MainCLIControl.py +++ b/WebControl/MainCLIControl.py @@ -25,69 +25,71 @@ def run_shell_fct(script): script_name = os.path.basename(script) # Se déplacer vers le répertoire du script et exécuter le script shell return subprocess.Popen(["sudo", "./" + script_name], cwd=script_dir) - -def main(): - python_scripts = [ - "apps/infrared_tracking_objects.py", - "apps/infrared_obstacle_avoidance.py", - "tests/servo_motor.py", - "tests/motor_speed_move.py", - "tests/rfid_read_write_module.py", - "tests/infrared_obstacle_module.py", - "tests/lidar_module.py" - ] - python_fct = [ - "WebControl/main.py" - ] - shell_fct = [ - ] - - # Liste pour stocker les PID des processus en cours d'exécution - running_processes = [] - - all_scripts = python_scripts + python_fct + shell_fct - - display_menu(all_scripts) - choice = input("Votre choix (entrez le numéro du script) : ") - - try: - choice_index = int(choice) - 1 - if choice_index < 0 or choice_index >= len(all_scripts): - raise ValueError() - - selected_script = all_scripts[choice_index] - - # Vérifie si le script est Python ou Shell et l'exécute en conséquence - if selected_script in python_scripts: - process = run_python_script(selected_script) - elif selected_script in python_fct: - process = run_python_fct(selected_script) - elif selected_script in shell_fct: - process = run_shell_fct(selected_script) - - # Ajouter le PID du processus à la liste - running_processes.append(process.pid) - - except (ValueError, IndexError): - print("Choix invalide.") - sys.exit(1) - - # Afficher les PID des processus en cours d'exécution - print("PID des processus en cours d'exécution :") - for pid in running_processes: - print(pid) - - # Attente de l'arrêt du programme - input("Appuyez sur Entrée pour quitter...") - - # Boucle pour terminer tous les processus en cours d'exécution - print("Termination des processus en cours...") - for pid in running_processes: - try: - os.kill(pid, signal.SIGTERM) - print(f"Processus {pid} terminé.") - except ProcessLookupError: - print(f"Le processus {pid} n'existe plus.") + if __name__ == "__main__": - main() + while True: + python_scripts = [ + "apps/scenario_rfid.py", + "apps/rfid_read_write_module.py", + "apps/lidar_speed_move.py", + "apps/infrared_obstacle_avoidance.py", + "tests/servo_motor.py", + "tests/rfid_open_door.py", + "tests/motor_speed_move.py", + "tests/lidar_module.py", + "tests/infrared_obstacle_module.py" + ] + python_fct = [ + # "WebControl/main.py" + ] + shell_fct = [ + # "fixs/reboot.sh" + # "fixs/fix_rfid.sh", + # "fixs/fix_motion.sh", + ] + + # Liste pour stocker les PID des processus en cours d'exécution + running_processes = [] + + all_scripts = python_scripts + python_fct + shell_fct + + display_menu(all_scripts) + choice = input("Votre choix (entrez le numéro du script) : ") + + try: + choice_index = int(choice) - 1 + if choice_index < 0 or choice_index >= len(all_scripts): + raise ValueError() + + selected_script = all_scripts[choice_index] + + # Vérifie si le script est Python ou Shell et l'exécute en conséquence + if selected_script in python_scripts: + process = run_python_script(selected_script) + elif selected_script in python_fct: + process = run_python_fct(selected_script) + elif selected_script in shell_fct: + process = run_shell_fct(selected_script) + + # Ajouter le PID du processus à la liste + running_processes.append(process.pid) + + except (ValueError, IndexError): + print("Choix invalide.") + sys.exit(1) + + # Afficher les PID des processus en cours d'exécution + print("PID des processus en cours d'exécution :") + for pid in running_processes: + print(pid) + # Attente de l'arrêt du programme + input("Appuyez sur Entrée pour quitter...\n") + # Boucle pour terminer tous les processus en cours d'exécution + print("Fermeture des processus en cours...") + for pid in running_processes: + try: + os.kill(pid, signal.SIGTERM) + print(f"Processus {pid} terminé.\n") + except ProcessLookupError: + print(f"Le processus {pid} n'existe plus.") \ No newline at end of file diff --git a/WebControl/NOTE.txt b/WebControl/NOTE.txt index a2325ec..67c47c2 100644 --- a/WebControl/NOTE.txt +++ b/WebControl/NOTE.txt @@ -1,3 +1,12 @@ crontab -e -@reboot sudo /usr/bin/motion -@reboot sh /home/christian/WebControl/webcontrol-launch.sh > /home/christian/WebControl/logs/log.txt 2>&1 \ No newline at end of file + @reboot /usr/bin/motion + @reboot /usr/bin/motion >> /home/christian/WebControl/logs/motionlogs.txt 2>&1 + @reboot sh /home/christian/WebControl/webcontrol-launch.sh >> /home/christian/WebControl/logs/log.txt 2>&1 + + ----------- + +sudo visudo + christian ALL=(ALL) NOPASSWD: /sbin/reboot + christian ALL=(ALL) NOPASSWD: /usr/bin/pkill + christian ALL=NOPASSWD: /usr/bin/python3 /home/christian/WebControl/main.py + christian ALL=NOPASSWD: /usr/bin/motion \ No newline at end of file diff --git a/WebControl/apps/infrared_obstacle_avoidance.py b/WebControl/apps/infrared_obstacle_avoidance.py index bbe68f0..9eab9ff 100644 --- a/WebControl/apps/infrared_obstacle_avoidance.py +++ b/WebControl/apps/infrared_obstacle_avoidance.py @@ -1,38 +1,36 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- import RPi.GPIO as GPIO -import time -import sys +import time, sys sys.path.append('/home/christian/WebControl/modules/') from AlphaBot import AlphaBot - Ab = AlphaBot() -speed = 100 -DR = 16 -DL = 19 -GPIO.setmode(GPIO.BCM) -GPIO.setwarnings(False) -GPIO.setup(DR,GPIO.IN,GPIO.PUD_UP) -GPIO.setup(DL,GPIO.IN,GPIO.PUD_UP) +status = "initialization" +duration = 0.1 +speed = 20 try: - while True: - DR_status = GPIO.input(DR) - DL_status = GPIO.input(DL) - if((DL_status == 1) and (DR_status == 1)): - Ab.forward(speed) - elif((DL_status == 1) and (DR_status == 0)): - Ab.left(speed) - elif((DL_status == 0) and (DR_status == 1)): - Ab.right(speed) - else: - Ab.backward(speed) - time.sleep(0.2) - Ab.left(speed) - time.sleep(0.2) - Ab.stop() - + start_time = time.time() # Enregistrer l'heure de début + while time.time() - start_time < 10: # Boucle pendant 5 seconde + OBSTACLE_PIN_status = GPIO.input(Ab.OBSTACLE_PIN) + if OBSTACLE_PIN_status == 1: + Ab.forward(duration, speed) + status = "operation successful" + else: + Ab.emergencystop() + status = "emergency stop successful" except KeyboardInterrupt: - GPIO.cleanup(); + print("Interruption par l'utilisateur.") + status = "interrupted" +finally: + Ab.cleanup() +# Vérification finale et affichage du statut +if status == "operation successful" or status == "emergency stop successful": + print(f"Le composant fonctionne correctement: {status}.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) diff --git a/WebControl/apps/infrared_tracking_objects.py b/WebControl/apps/infrared_tracking_objects.py deleted file mode 100644 index 223bf1d..0000000 --- a/WebControl/apps/infrared_tracking_objects.py +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -import RPi.GPIO as GPIO -import time -import sys -sys.path.append('/home/christian/WebControl/modules/') -from AlphaBot import AlphaBot - -Ab = AlphaBot() - -DR = 16 -DL = 19 - -GPIO.setmode(GPIO.BCM) -GPIO.setwarnings(False) -GPIO.setup(DR,GPIO.IN,GPIO.PUD_UP) -GPIO.setup(DL,GPIO.IN,GPIO.PUD_UP) -Ab.stop() -speed=100 -try: - while True: - - DR_status = GPIO.input(DR) - DL_status = GPIO.input(DL) - if((DL_status == 0) and (DR_status == 0)): - Ab.forward(speed) - elif((DL_status == 1) and (DR_status == 0)): - Ab.right(speed) - elif((DL_status == 0) and (DR_status == 1)): - Ab.left(speed) - else: - Ab.stop() -except KeyboardInterrupt: - GPIO.cleanup(); - diff --git a/WebControl/apps/itineraire_create.py b/WebControl/apps/itineraire_create.py new file mode 100644 index 0000000..ca6b05f --- /dev/null +++ b/WebControl/apps/itineraire_create.py @@ -0,0 +1,59 @@ +import requests, json, time + +def get_directions(origin, destination, api_key): + url = f"https://maps.googleapis.com/maps/api/directions/json?origin={origin}&destination={destination}&key={api_key}" + response = requests.get(url) + if response.status_code == 200: + directions = response.json() + return directions + else: + return None + +def save_steps_to_file(directions, filename): + if directions and 'routes' in directions and len(directions['routes']) > 0: + steps = [] + for route in directions['routes']: + for leg in route['legs']: + for step in leg['steps']: + steps.append(step) + with open(filename, 'w', encoding='utf-8') as f: + json.dump(steps, f, indent=2, ensure_ascii=False) + +def save_selected_steps_to_file(directions, filename): + selected_steps = [] + if directions and 'routes' in directions and len(directions['routes']) > 0: + for route in directions['routes']: + for leg in route['legs']: + for step in leg['steps']: + selected_step = { + 'distance_value': step['distance']['value'], + 'maneuver': step.get('maneuver', 'maneuver-unspecified') + } + selected_steps.append(selected_step) + with open(filename, 'w', encoding='utf-8') as f: + json.dump(selected_steps, f, indent=2, ensure_ascii=False) + +# Paramètres +origin = "48.8224, 2.2748" # Coordonnées pour Paris (latitude, longitude) +destination = "48.67912602858551, 2.3860270345466024" # Coordonnées pour Lyon (latitude, longitude) +api_key = "AIzaSyD6WRlNBTn27rEoYbIAlxw9U_Nr_iNqLJc" + + +# Obtenir les directions +directions = get_directions(origin, destination, api_key) +print("Préparons ensemble votre itinéraire !") +time.sleep(2) +print("Veuillez saisir l'adresse de départ et l'adresse d'arrivée.") +time.sleep(2) +print("Calcul de l'itinéraire en cours : de Paris à Lyon.") +time.sleep(2) + +# Sauvegarder les étapes complètes dans un fichier JSON +steps_filename = '/home/christian/WebControl/logs/steps.json' +save_steps_to_file(directions, steps_filename) +# print(f"Les étapes complètes de l'itinéraire ont été sauvegardées dans le fichier {steps_filename}") + +# Sauvegarder les étapes sélectionnées dans un fichier JSON +selected_steps_filename = '/home/christian/WebControl/logs/selected_steps.json' +save_selected_steps_to_file(directions, selected_steps_filename) +# print(f"Les étapes sélectionnées de l'itinéraire ont été sauvegardées dans le fichier {selected_steps_filename}") \ No newline at end of file diff --git a/WebControl/apps/itineraire_suivre.py b/WebControl/apps/itineraire_suivre.py new file mode 100644 index 0000000..f6ccec8 --- /dev/null +++ b/WebControl/apps/itineraire_suivre.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import json, time, sys +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() +speed = 20 + +# Fonction pour calculer la durée en fonction de la distance +def calculate_duration(distance_value): + # Réglez la vitesse de traitement selon vos besoins + speed_factor = 0.001 # Exemple 0.01/100m:s | 0.001/1km/s + return distance_value * speed_factor + +# Lecture du fichier selected_steps.json et traitement des manoeuvres +def process_selected_steps(filename): + with open(filename, 'r', encoding='utf-8') as f: + selected_steps = json.load(f) + + for step in selected_steps: + maneuver = step['maneuver'] + distance_value = step['distance_value'] + + # Calcul de la durée en fonction de la distance + duration = calculate_duration(distance_value) + + if maneuver == "maneuver-unspecified": + Ab.maneuver_unspecified(duration) + elif maneuver == "turn-slight-left": + Ab.turn_slight_left(duration, speed) + elif maneuver == "turn-sharp-left": + Ab.turn_sharp_left(duration, speed) + elif maneuver == "u-turn-left": + Ab.u_turn_left(duration, speed) + elif maneuver == "turn-left": + Ab.left(duration, speed) + elif maneuver == "turn-slight-right": + Ab.turn_slight_right(duration, speed) + elif maneuver == "turn-sharp-right": + Ab.turn_sharp_right(duration, speed) + elif maneuver == "u-turn-right": + Ab.u_turn_right(duration, speed) + elif maneuver == "turn-right": + Ab.right(duration, speed) + elif maneuver == "straight": + Ab.forward(duration, speed) + elif maneuver == "ramp-left": + Ab.ramp_left(duration, speed) + elif maneuver == "ramp-right": + Ab.ramp_right(duration, speed) + elif maneuver == "merge": + Ab.merge(duration, speed) + elif maneuver == "fork-left": + Ab.fork_left(duration, speed) + elif maneuver == "fork-right": + Ab.fork_right(duration, speed) + elif maneuver == "ferry": + Ab.stop(duration) + elif maneuver == "ferry-train": + Ab.stop(duration) + elif maneuver == "roundabout-left": + Ab.roundabout_left(duration, speed) + elif maneuver == "roundabout-right": + Ab.roundabout_right(duration, speed) + else: + print(f"Manoeuvre inconnue : {maneuver}") + +# Nom du fichier contenant les étapes sélectionnées +selected_steps_filename = '/home/christian/WebControl/logs/selected_steps_short.json' + +# Appel de la fonction pour traiter les étapes sélectionnées +print("Le départ est prévu dans 10 secondes...") +time.sleep(10) +print("Départ imminent !") +process_selected_steps(selected_steps_filename) diff --git a/WebControl/apps/itineraire_suivre_emergency.py b/WebControl/apps/itineraire_suivre_emergency.py new file mode 100644 index 0000000..ed8fb2b --- /dev/null +++ b/WebControl/apps/itineraire_suivre_emergency.py @@ -0,0 +1,170 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import RPi.GPIO as GPIO +import json, time, sys, threading +from threading import Thread + +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() + +base_speed = 20 # Vitesse fixe de 20 +current_step_index = 0 +emergency_stop = False +remaining_duration = 0 +stop_event_obstacle = threading.Event() + + +# Fonction pour calculer la durée en fonction de la distance +def calculate_duration(distance_value): + speed_factor = 0.001 # Exemple 0.01/100m:s | 0.001/1km/s + return distance_value * speed_factor + +# Fonction pour surveiller les obstacles en arrière-plan +def monitor_obstacles(): + global emergency_stop, remaining_duration + while not stop_event_obstacle.is_set(): + DR_status = GPIO.input(Ab.OBSTACLE_PIN) + if DR_status == 0: # Obstacle détecté + Ab.emergencystop() + emergency_stop = True + while GPIO.input(Ab.OBSTACLE_PIN) == 0: # Attendre que l'obstacle soit dégagé + time.sleep(2) + print("Obstacle dégagé. Attente de 2 secondes avant de reprendre.") + emergency_stop = False + +# Fonction pour exécuter une manoeuvre avec arrêt d'urgence possible +def execute_maneuver(maneuver_function, duration, speed=None): + global remaining_duration + start_time = time.time() + while not emergency_stop and (time.time() - start_time) < duration: + time_slice = min(remaining_duration, duration - (time.time() - start_time)) + + # Appel de la fonction manoeuvre avec ou sans vitesse selon le besoin + if speed is not None: + maneuver_function(time_slice, speed) + else: + maneuver_function(time_slice) + + remaining_duration = duration - (time.time() - start_time) + +# Fonction pour traiter les étapes sélectionnées +def process_selected_steps(filename): + global current_step_index, remaining_duration + + with open(filename, 'r', encoding='utf-8') as f: + selected_steps = json.load(f) + + while current_step_index < len(selected_steps): + if emergency_stop: # Si arrêt d'urgence, attendre que l'obstacle soit dégagé + time.sleep(0.1) + continue + + step = selected_steps[current_step_index] + maneuver = step['maneuver'] + distance_value = step['distance_value'] + duration = calculate_duration(distance_value) + remaining_duration = duration # Initialiser la durée restante + + # Appel de la fonction de manoeuvre avec une vitesse fixe de 20 + if maneuver == "maneuver-unspecified": + execute_maneuver(Ab.maneuver_unspecified, duration) + elif maneuver == "turn-slight-left": + execute_maneuver(Ab.turn_slight_left, duration, base_speed) + elif maneuver == "turn-sharp-left": + execute_maneuver(Ab.turn_sharp_left, duration, base_speed) + elif maneuver == "u-turn-left": + execute_maneuver(Ab.u_turn_left, duration, base_speed) + elif maneuver == "turn-left": + execute_maneuver(Ab.left, duration, base_speed) + elif maneuver == "turn-slight-right": + execute_maneuver(Ab.turn_slight_right, duration, base_speed) + elif maneuver == "turn-sharp-right": + execute_maneuver(Ab.turn_sharp_right, duration, base_speed) + elif maneuver == "u-turn-right": + execute_maneuver(Ab.u_turn_right, duration, base_speed) + elif maneuver == "turn-right": + execute_maneuver(Ab.right, duration, base_speed) + elif maneuver == "straight": + execute_maneuver(Ab.forward, duration, base_speed) + elif maneuver == "ramp-left": + execute_maneuver(Ab.ramp_left, duration, base_speed) + elif maneuver == "ramp-right": + execute_maneuver(Ab.ramp_right, duration, base_speed) + elif maneuver == "merge": + execute_maneuver(Ab.merge, duration, base_speed) + elif maneuver == "fork-left": + execute_maneuver(Ab.fork_left, duration, base_speed) + elif maneuver == "fork-right": + execute_maneuver(Ab.fork_right, duration, base_speed) + elif maneuver == "ferry": + execute_maneuver(Ab.stop, duration) + elif maneuver == "ferry-train": + execute_maneuver(Ab.stop, duration) + elif maneuver == "roundabout-left": + execute_maneuver(Ab.roundabout_left, duration, base_speed) + elif maneuver == "roundabout-right": + execute_maneuver(Ab.roundabout_right, duration, base_speed) + else: + print(f"Manoeuvre inconnue : {maneuver}") + + # Incrémenter l'index de l'étape seulement si l'arrêt d'urgence n'a pas été déclenché + if not emergency_stop: + current_step_index += 1 + +# Nom du fichier contenant les étapes sélectionnées +selected_steps_filename = '/home/christian/WebControl/logs/selected_steps_short.json' + +# Démarrer la surveillance des obstacles dans un thread séparé +obstacle_thread = Thread(target=monitor_obstacles) +obstacle_thread.daemon = True +obstacle_thread.start() + +# Attendre avant de démarrer +print("Le départ est prévu dans 10 secondes...") +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +print("5 secondes...") +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +print("Départ imminent !") +try: + # Appel de la fonction pour traiter les étapes sélectionnées + process_selected_steps(selected_steps_filename) + status = "scenario successful" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + # Arrêter les threads + Ab.stop_event_obstacle.set() + # Attendre que les threads se terminent + obstacle_thread.join() + print("Fin de la surveillance d'obstacle") + Ab.cleanup() + +# Vérification finale et affichage du statut +if status in ["scenario successful"]: + print("Le scenario fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le scenario a rencontré un problème : {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/apps/itineraire_suivre_emergency_speed.py b/WebControl/apps/itineraire_suivre_emergency_speed.py new file mode 100644 index 0000000..ba6da1a --- /dev/null +++ b/WebControl/apps/itineraire_suivre_emergency_speed.py @@ -0,0 +1,174 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import RPi.GPIO as GPIO +import json, time, sys +from threading import Thread + +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() + +status = "initialization" + +base_speed = 20 # Vitesse fixe de 20 +current_step_index = 0 +emergency_stop = False +remaining_duration = 0 +adjusted_speed = Ab.vitesse_queue.get() + +# Fonction pour calculer la durée en fonction de la distance +def calculate_duration(distance_value): + speed_factor = 0.001 # Exemple 0.01/100m:s | 0.001/1km/s + return distance_value * speed_factor + +def execute_maneuver(maneuver_function, duration): + global remaining_duration + start_time = time.time() + while not emergency_stop and (time.time() - start_time) < duration: + time_slice = min(remaining_duration, duration - (time.time() - start_time)) + + # Lire la vitesse ajustée de la queue si disponible + if not Ab.vitesse_queue.empty(): + adjusted_speed = Ab.vitesse_queue.get() + else: + adjusted_speed = base_speed # Utiliser la vitesse de base si la queue est vide + + # Appel de la fonction manoeuvre avec la vitesse ajustée + maneuver_function(time_slice, adjusted_speed) + + remaining_duration = duration - (time.time() - start_time) + + +# Fonction pour traiter les étapes sélectionnées +def process_selected_steps(filename): + global current_step_index, remaining_duration + + with open(filename, 'r', encoding='utf-8') as f: + selected_steps = json.load(f) + + while current_step_index < len(selected_steps): + if emergency_stop: # Si arrêt d'urgence, attendre que l'obstacle soit dégagé + time.sleep(0.1) + continue + + step = selected_steps[current_step_index] + maneuver = step['maneuver'] + distance_value = step['distance_value'] + duration = calculate_duration(distance_value) + remaining_duration = duration # Initialiser la durée restante + + # Appel de la fonction de manoeuvre avec une vitesse fixe de 20 + if maneuver == "maneuver-unspecified": + execute_maneuver(Ab.maneuver_unspecified, adjusted_speed) + elif maneuver == "turn-slight-left": + execute_maneuver(Ab.turn_slight_left, duration, adjusted_speed) + elif maneuver == "turn-sharp-left": + execute_maneuver(Ab.turn_sharp_left, duration, adjusted_speed) + elif maneuver == "u-turn-left": + execute_maneuver(Ab.u_turn_left, duration, adjusted_speed) + elif maneuver == "turn-left": + execute_maneuver(Ab.left, duration, adjusted_speed) + elif maneuver == "turn-slight-right": + execute_maneuver(Ab.turn_slight_right, duration, adjusted_speed) + elif maneuver == "turn-sharp-right": + execute_maneuver(Ab.turn_sharp_right, duration, adjusted_speed) + elif maneuver == "u-turn-right": + execute_maneuver(Ab.u_turn_right, duration, adjusted_speed) + elif maneuver == "turn-right": + execute_maneuver(Ab.right, duration, adjusted_speed) + elif maneuver == "straight": + execute_maneuver(Ab.forward, duration, adjusted_speed) + elif maneuver == "ramp-left": + execute_maneuver(Ab.ramp_left, duration, adjusted_speed) + elif maneuver == "ramp-right": + execute_maneuver(Ab.ramp_right, duration, adjusted_speed) + elif maneuver == "merge": + execute_maneuver(Ab.merge, duration, adjusted_speed) + elif maneuver == "fork-left": + execute_maneuver(Ab.fork_left, duration, adjusted_speed) + elif maneuver == "fork-right": + execute_maneuver(Ab.fork_right, duration, adjusted_speed) + elif maneuver == "ferry": + execute_maneuver(Ab.stop, duration) + elif maneuver == "ferry-train": + execute_maneuver(Ab.stop, duration) + elif maneuver == "roundabout-left": + execute_maneuver(Ab.roundabout_left, duration, adjusted_speed) + elif maneuver == "roundabout-right": + execute_maneuver(Ab.roundabout_right, duration, adjusted_speed) + else: + print(f"Manoeuvre inconnue : {maneuver}") + + # Incrémenter l'index de l'étape seulement si l'arrêt d'urgence n'a pas été déclenché + if not emergency_stop: + current_step_index += 1 + +# Nom du fichier contenant les étapes sélectionnées +selected_steps_filename = '/home/christian/WebControl/logs/selected_steps_short.json' + +# Démarrer la surveillance des obstacle dans un thread séparé +vitesse_thread = Thread(target=Ab.monitor_vitesse) +vitesse_thread.daemon = True +vitesse_thread.start() +print("Surveillance de la vitesse en cours") + +# Démarrer la surveillance des obstacle dans un thread séparé +obstacle_thread = Thread(target=Ab.monitor_obstacle) +obstacle_thread.daemon = True +obstacle_thread.start() +print("Surveillance d'obstacle en cours") + +# Attendre avant de démarrer +print("Le départ est prévu dans 10 secondes...") +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +print("5 secondes...") +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) +time.sleep(1) +GPIO.output(Ab.RED_LIGHT, GPIO.LOW) +time.sleep(1) +print("Départ imminent !") +try: + # Appel de la fonction pour traiter les étapes sélectionnées + # Appel de la fonction pour traiter les étapes sélectionnées + process_selected_steps(selected_steps_filename) + status = "scenario successful" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + # Arrêter les threads + Ab.stop_event_vitesse.set() + Ab.stop_event_obstacle.set() + # Attendre que les threads se terminent + vitesse_thread.join() + obstacle_thread.join() + print("Fin de surveillance de la vitesse") + print("Fin de la surveillance d'obstacle") + + Ab.LIDAR_MODULE.close() # Fermeture propre du port série + Ab.cleanup() + +# Vérification finale et affichage du statut +if status in ["scenario successful"]: + print("Le scenario fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le scenario a rencontré un problème : {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/apps/lidar_speed_move.py b/WebControl/apps/lidar_speed_move.py new file mode 100644 index 0000000..0888ae2 --- /dev/null +++ b/WebControl/apps/lidar_speed_move.py @@ -0,0 +1,56 @@ +import time +import sys +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() + +# Variable de statut pour indiquer le bon fonctionnement +status = "initialization" + +# Durée limite d'exécution en secondes +time_limit = 10 +start_time = time.time() +try: + # Envoi de la commande pour initialiser le capteur + while True: + # Vérification si le temps limite est dépassé + if time.time() - start_time > time_limit: + break + + if Ab.LIDAR_MODULE.in_waiting >= 9: + if b'Y' == Ab.LIDAR_MODULE.read() and b'Y' == Ab.LIDAR_MODULE.read(): + Dist_L = Ab.LIDAR_MODULE.read() + Dist_H = Ab.LIDAR_MODULE.read() + Dist_Total = (Dist_H[0] * 256) + Dist_L[0] + for i in range(0, 5): + Ab.LIDAR_MODULE.read() # Lecture et ignore des octets supplémentaires + print("Distance à l'avant du véhicule:", Dist_Total, "cm") + status = "measurement successful" + + # Ajuster la vitesse en fonction de la distance LIDAR + vitesse_ajustee = Ab.ajuster_vitesse_selon_distance(Dist_Total) + + if vitesse_ajustee > 0: + Ab.forward(0.1, vitesse_ajustee) # Avancer avec la vitesse ajustée + else: + Ab.emergencystop() # S'arrêter si trop proche d'un obstacle + Ab.LIDAR_MODULE.reset_input_buffer() +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + Ab.LIDAR_MODULE.close() # Fermeture propre du port série + Ab.cleanup() + +# Vérification finale et affichage du statut +if status in ["measurement successful"]: + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) diff --git a/WebControl/apps/rfid_read_write_module.py b/WebControl/apps/rfid_read_write_module.py new file mode 100644 index 0000000..7022ac8 --- /dev/null +++ b/WebControl/apps/rfid_read_write_module.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import time +import sys +sys.path.append('/home/christian/WebControl/modules/') +from SimpleMFRC522 import SimpleMFRC522 +RFID_MODULE = SimpleMFRC522() +from AlphaBot import AlphaBot +Ab = AlphaBot() + +try: + # Lecture initiale du tag RFID + print("### Lecture RFID ###") + print("Approchez le tag RFID du capteur:") + print("(ID, Contenu)", RFID_MODULE.read()) + time.sleep(3) + # Écriture sur le tag RFID + data = "TEST RFID " + print("### Écriture RFID ###") + print("Valeur qui sera écrite:", data) + print("Approchez le tag RFID du capteur:") + RFID_MODULE.write(data) + print("Succès de l'écriture sur le tag RFID.") + time.sleep(3) # Attente courte avant de vérifier l'écriture + # Seconde lecture du tag RFID + print("### Lecture RFID ###") + print("Approchez le tag RFID du capteur:") + print("(ID, Contenu)", RFID_MODULE.read()) + time.sleep(3) +except Exception as e: + print(f"Erreur lors de l'écriture RFID: {e}") \ No newline at end of file diff --git a/WebControl/apps/scenario_rfid.py b/WebControl/apps/scenario_rfid.py new file mode 100644 index 0000000..9de1fe4 --- /dev/null +++ b/WebControl/apps/scenario_rfid.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import subprocess, time, sys +sys.path.append('/home/christian/WebControl/modules/') +from SimpleMFRC522 import SimpleMFRC522 +RFID_MODULE = SimpleMFRC522() +from AlphaBot import AlphaBot +Ab = AlphaBot() + +status = "initialization" +try: + while True: + time.sleep(3) + # Ab.set_angle(0) + print("La porte est actuellement fermée.\nVeuillez approcher votre badge RFID du capteur pour accéder au véhicule.") + id_rfid, text_rfid = RFID_MODULE.read() + rfid_content = RFID_MODULE.read() + if text_rfid == "TEST RFID ": + Ab.set_angle(90) + print(f"Bienvenue, {text_rfid.rstrip()} \nJe suis heureux de pouvoir partager un trajet avec vous !") + time.sleep(5) + print("Installez-vous confortablement !") + time.sleep(2) + print("Votre voiture autonome est prête à partir.") + try: + subprocess.run(['python3', 'apps/itineraire_create.py'], check=True) + try: + print("Nous préparons votre trajet en toute sécurité.") + Ab.set_angle(0) + # Changer si nécessaire 'apps/itineraire_suivre.py' en 'apps/itineraire_suivre_emergency.py' + subprocess.run(['python3', 'apps/itineraire_suivre_emergency.py'], check=True) + print("Merci d'avoir utilisé notre service !") + time.sleep(2) + Ab.set_angle(90) + print("Nous espérons que vous avez apprécié votre trajet.") + time.sleep(2) + print("À bientôt avec CARIA !") + status = "scenario successful" + except subprocess.CalledProcessError as e: + print(f"Erreur lors de l'exécution du script step2_suivre_itineraire: {e}") + status = "error" + except subprocess.CalledProcessError as e: + print(f"Erreur lors de l'exécution du script step1_prepare_itineraire: {e}") + status = "error" + elif text_rfid in ["CHRIS "]: + Ab.set_angle(90) + print(f"Bienvenue, {text_rfid.rstrip()}.\nLa porte du véhicule est maintenant ouverte!") + status = "scenario successful" + else: + Ab.set_angle(0) + print("Bonjour, vous n'êtes pas autorisé à entrer dans le véhicule.\nLa porte reste fermée.") + print(rfid_content) + time.sleep(2) + status = "interrupted" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + Ab.PWMSERVO.stop() + Ab.cleanup() + # Vérification finale et affichage du statut + if status == "movement successful": + print("Le scenario fonctionne correctement.") + fonctionnement_ok = True + else: + print(f"Le scenario a rencontré un problème: {status}.") + fonctionnement_ok = False +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) diff --git a/WebControl/css/styles.css b/WebControl/css/styles.css index c50a73d..535babd 100644 --- a/WebControl/css/styles.css +++ b/WebControl/css/styles.css @@ -17,7 +17,7 @@ input { .counter { position: relative; bottom: 98px; - left: 0px; + left: 50px; font-size: 48px; text-align: center; color: blue; @@ -47,42 +47,6 @@ input { transition: box-shadow 0.3s; border-radius: 50px; } -.button_fct { - margin: 10px 15px 10px 15px; - width: auto; - height: 50px; - transition: box-shadow 0.3s; - border-radius: 50px; -} -/* Button toogle */ -.button-container { - display: flex; - flex-direction: column; - align-items: flex-start; -} -input[type="checkbox"] { - margin: 10px 15px 10px 15px; - width: 50px; - height: 30px; - -webkit-appearance: none; - appearance: none; - background-color: #ddd; - border-radius: 25px; - position: relative; - cursor: pointer; -} -input[type="checkbox"]:before { - content: ''; - position: absolute; - width: 20px; - height: 20px; - border-radius: 50%; - background-color: white; - top: 50%; - left: 3px; - transform: translateY(-50%); - transition: 0.2s; -} -input[type="checkbox"]:checked:before { - left: calc(100% - 33px); +.form-check-input { + transform: scale(1.5); /* Augmente la taille du bouton */ } \ No newline at end of file diff --git a/WebControl/fixs/fix_motion.sh b/WebControl/fixs/fix_motion.sh new file mode 100644 index 0000000..0751f1f --- /dev/null +++ b/WebControl/fixs/fix_motion.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Arrêter le processus motion +if ! sudo pkill -f motion; then + echo "Erreur: Impossible d'arrêter le processus motion." + exit 1 +fi +# Attendre quelques secondes pour s'assurer que le processus est bien arrêté +sleep 5 +# Démarrer le processus motion +if ! sudo /usr/bin/motion &; then + echo "Erreur: Impossible de démarrer le processus motion." + exit 1 +fi +# Attendre quelques secondes pour s'assurer que le processus est bien démarré +sleep 5 +echo "Le service motion a été redémarré avec succès. Vous pouvez maintenant vérifier le fonctionnement sur l'interface web." +# Ouvrir l'interface web dans le navigateur par défaut +echo "Pour tester la vidéo, ouvrez le lien suivant dans votre navigateur : http://192.168.253.194:8081/" diff --git a/WebControl/fixs/fix_rfid.sh b/WebControl/fixs/fix_rfid.sh new file mode 100644 index 0000000..5b94153 --- /dev/null +++ b/WebControl/fixs/fix_rfid.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Naviguer vers le répertoire du module MFRC522 +cd modules/MFRC522-python + +# Installer le module MFRC522 +sudo python3 setup.py install + +# Confirmation de l'installation +echo "Installation du module MFRC522 terminée." diff --git a/WebControl/fixs/reboot.sh b/WebControl/fixs/reboot.sh new file mode 100644 index 0000000..42f0179 --- /dev/null +++ b/WebControl/fixs/reboot.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +# Afficher un message de confirmation +echo "Le Raspberry Pi va redémarrer maintenant." + +# Redémarrer le Raspberry Pi +sudo reboot diff --git a/WebControl/images/Thumbs.db b/WebControl/images/Thumbs.db index fe5fadfbcb52505e8ed738b90bb1cb5a0e877c93..12e48e3e2634ad8f83e5e5004d44ff969f261564 100644 GIT binary patch delta 56 zcmZqJz}T>XaYGIZ+ktIH{?GnyE@GL-%we^6V%@5F1%{gyIqow~HelhL#3g_bl;C>d F3jmTW7F_@U delta 56 zcmZqJz}T>XaYGIZ+X97lcGiuXi&*9{b0j6d@F_naeQ2{H$9=}h1}vPDxC9V_5?n8Q E0Y%jm!vFvP diff --git a/WebControl/package.txt b/WebControl/install/requirements_server-car.txt similarity index 97% rename from WebControl/package.txt rename to WebControl/install/requirements_server-car.txt index dc3c6a8..ae3289c 100644 --- a/WebControl/package.txt +++ b/WebControl/install/requirements_server-car.txt @@ -31,6 +31,7 @@ ExplorerHAT==0.4.2 Flask==1.1.2 Flask-SocketIO==5.3.6 fourletterphat==0.1.0 +future==1.0.0 gpiozero==1.6.2 greenlet==3.0.3 guizero==1.1.1 @@ -40,6 +41,7 @@ idna==2.10 ipykernel==5.4.3 ipython==7.20.0 ipython_genutils==0.2.0 +iso8601==2.1.0 isort==5.6.4 itsdangerous==1.1.0 jedi==0.18.0 @@ -96,7 +98,7 @@ pyOpenSSL==20.0.1 pyparsing==2.4.7 PyQt5==5.15.2 PyQt5-sip==12.8.1 -pyserial==3.5b0 +pyserial==3.5 pysmbc==1.0.23 python-apt==2.2.1 python-dateutil==2.8.1 @@ -122,6 +124,7 @@ semver==2.10.2 Send2Trash==1.6.0b1 sense-emu==1.2 sense-hat==2.6.0 +serial==0.0.97 simple-websocket==1.0.0 simplejpeg==1.6.4 simplejson==3.17.2 diff --git a/WebControl/js/bootstrap.bundle.min.js b/WebControl/js/bootstrap.bundle.min.js new file mode 100644 index 0000000..fe19d88 --- /dev/null +++ b/WebControl/js/bootstrap.bundle.min.js @@ -0,0 +1,7 @@ +/*! + * Bootstrap v5.3.0 (https://getbootstrap.com/) + * Copyright 2011-2023 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) + */ +!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).bootstrap=e()}(this,(function(){"use strict";const t=new Map,e={set(e,i,n){t.has(e)||t.set(e,new Map);const s=t.get(e);s.has(i)||0===s.size?s.set(i,n):console.error(`Bootstrap doesn't allow more than one instance per element. Bound instance: ${Array.from(s.keys())[0]}.`)},get:(e,i)=>t.has(e)&&t.get(e).get(i)||null,remove(e,i){if(!t.has(e))return;const n=t.get(e);n.delete(i),0===n.size&&t.delete(e)}},i="transitionend",n=t=>(t&&window.CSS&&window.CSS.escape&&(t=t.replace(/#([^\s"#']+)/g,((t,e)=>`#${CSS.escape(e)}`))),t),s=t=>{t.dispatchEvent(new Event(i))},o=t=>!(!t||"object"!=typeof t)&&(void 0!==t.jquery&&(t=t[0]),void 0!==t.nodeType),r=t=>o(t)?t.jquery?t[0]:t:"string"==typeof t&&t.length>0?document.querySelector(n(t)):null,a=t=>{if(!o(t)||0===t.getClientRects().length)return!1;const e="visible"===getComputedStyle(t).getPropertyValue("visibility"),i=t.closest("details:not([open])");if(!i)return e;if(i!==t){const e=t.closest("summary");if(e&&e.parentNode!==i)return!1;if(null===e)return!1}return e},l=t=>!t||t.nodeType!==Node.ELEMENT_NODE||!!t.classList.contains("disabled")||(void 0!==t.disabled?t.disabled:t.hasAttribute("disabled")&&"false"!==t.getAttribute("disabled")),c=t=>{if(!document.documentElement.attachShadow)return null;if("function"==typeof t.getRootNode){const e=t.getRootNode();return e instanceof ShadowRoot?e:null}return t instanceof ShadowRoot?t:t.parentNode?c(t.parentNode):null},h=()=>{},d=t=>{t.offsetHeight},u=()=>window.jQuery&&!document.body.hasAttribute("data-bs-no-jquery")?window.jQuery:null,f=[],p=()=>"rtl"===document.documentElement.dir,m=t=>{var e;e=()=>{const e=u();if(e){const i=t.NAME,n=e.fn[i];e.fn[i]=t.jQueryInterface,e.fn[i].Constructor=t,e.fn[i].noConflict=()=>(e.fn[i]=n,t.jQueryInterface)}},"loading"===document.readyState?(f.length||document.addEventListener("DOMContentLoaded",(()=>{for(const t of f)t()})),f.push(e)):e()},g=(t,e=[],i=t)=>"function"==typeof t?t(...e):i,_=(t,e,n=!0)=>{if(!n)return void g(t);const o=(t=>{if(!t)return 0;let{transitionDuration:e,transitionDelay:i}=window.getComputedStyle(t);const n=Number.parseFloat(e),s=Number.parseFloat(i);return n||s?(e=e.split(",")[0],i=i.split(",")[0],1e3*(Number.parseFloat(e)+Number.parseFloat(i))):0})(e)+5;let r=!1;const a=({target:n})=>{n===e&&(r=!0,e.removeEventListener(i,a),g(t))};e.addEventListener(i,a),setTimeout((()=>{r||s(e)}),o)},b=(t,e,i,n)=>{const s=t.length;let o=t.indexOf(e);return-1===o?!i&&n?t[s-1]:t[0]:(o+=i?1:-1,n&&(o=(o+s)%s),t[Math.max(0,Math.min(o,s-1))])},v=/[^.]*(?=\..*)\.|.*/,y=/\..*/,w=/::\d+$/,A={};let E=1;const T={mouseenter:"mouseover",mouseleave:"mouseout"},C=new Set(["click","dblclick","mouseup","mousedown","contextmenu","mousewheel","DOMMouseScroll","mouseover","mouseout","mousemove","selectstart","selectend","keydown","keypress","keyup","orientationchange","touchstart","touchmove","touchend","touchcancel","pointerdown","pointermove","pointerup","pointerleave","pointercancel","gesturestart","gesturechange","gestureend","focus","blur","change","reset","select","submit","focusin","focusout","load","unload","beforeunload","resize","move","DOMContentLoaded","readystatechange","error","abort","scroll"]);function O(t,e){return e&&`${e}::${E++}`||t.uidEvent||E++}function x(t){const e=O(t);return t.uidEvent=e,A[e]=A[e]||{},A[e]}function k(t,e,i=null){return Object.values(t).find((t=>t.callable===e&&t.delegationSelector===i))}function L(t,e,i){const n="string"==typeof e,s=n?i:e||i;let o=N(t);return C.has(o)||(o=t),[n,s,o]}function S(t,e,i,n,s){if("string"!=typeof e||!t)return;let[o,r,a]=L(e,i,n);if(e in T){const t=t=>function(e){if(!e.relatedTarget||e.relatedTarget!==e.delegateTarget&&!e.delegateTarget.contains(e.relatedTarget))return t.call(this,e)};r=t(r)}const l=x(t),c=l[a]||(l[a]={}),h=k(c,r,o?i:null);if(h)return void(h.oneOff=h.oneOff&&s);const d=O(r,e.replace(v,"")),u=o?function(t,e,i){return function n(s){const o=t.querySelectorAll(e);for(let{target:r}=s;r&&r!==this;r=r.parentNode)for(const a of o)if(a===r)return M(s,{delegateTarget:r}),n.oneOff&&P.off(t,s.type,e,i),i.apply(r,[s])}}(t,i,r):function(t,e){return function i(n){return M(n,{delegateTarget:t}),i.oneOff&&P.off(t,n.type,e),e.apply(t,[n])}}(t,r);u.delegationSelector=o?i:null,u.callable=r,u.oneOff=s,u.uidEvent=d,c[d]=u,t.addEventListener(a,u,o)}function D(t,e,i,n,s){const o=k(e[i],n,s);o&&(t.removeEventListener(i,o,Boolean(s)),delete e[i][o.uidEvent])}function I(t,e,i,n){const s=e[i]||{};for(const[o,r]of Object.entries(s))o.includes(n)&&D(t,e,i,r.callable,r.delegationSelector)}function N(t){return t=t.replace(y,""),T[t]||t}const P={on(t,e,i,n){S(t,e,i,n,!1)},one(t,e,i,n){S(t,e,i,n,!0)},off(t,e,i,n){if("string"!=typeof e||!t)return;const[s,o,r]=L(e,i,n),a=r!==e,l=x(t),c=l[r]||{},h=e.startsWith(".");if(void 0===o){if(h)for(const i of Object.keys(l))I(t,l,i,e.slice(1));for(const[i,n]of Object.entries(c)){const s=i.replace(w,"");a&&!e.includes(s)||D(t,l,r,n.callable,n.delegationSelector)}}else{if(!Object.keys(c).length)return;D(t,l,r,o,s?i:null)}},trigger(t,e,i){if("string"!=typeof e||!t)return null;const n=u();let s=null,o=!0,r=!0,a=!1;e!==N(e)&&n&&(s=n.Event(e,i),n(t).trigger(s),o=!s.isPropagationStopped(),r=!s.isImmediatePropagationStopped(),a=s.isDefaultPrevented());const l=M(new Event(e,{bubbles:o,cancelable:!0}),i);return a&&l.preventDefault(),r&&t.dispatchEvent(l),l.defaultPrevented&&s&&s.preventDefault(),l}};function M(t,e={}){for(const[i,n]of Object.entries(e))try{t[i]=n}catch(e){Object.defineProperty(t,i,{configurable:!0,get:()=>n})}return t}function j(t){if("true"===t)return!0;if("false"===t)return!1;if(t===Number(t).toString())return Number(t);if(""===t||"null"===t)return null;if("string"!=typeof t)return t;try{return JSON.parse(decodeURIComponent(t))}catch(e){return t}}function F(t){return t.replace(/[A-Z]/g,(t=>`-${t.toLowerCase()}`))}const H={setDataAttribute(t,e,i){t.setAttribute(`data-bs-${F(e)}`,i)},removeDataAttribute(t,e){t.removeAttribute(`data-bs-${F(e)}`)},getDataAttributes(t){if(!t)return{};const e={},i=Object.keys(t.dataset).filter((t=>t.startsWith("bs")&&!t.startsWith("bsConfig")));for(const n of i){let i=n.replace(/^bs/,"");i=i.charAt(0).toLowerCase()+i.slice(1,i.length),e[i]=j(t.dataset[n])}return e},getDataAttribute:(t,e)=>j(t.getAttribute(`data-bs-${F(e)}`))};class ${static get Default(){return{}}static get DefaultType(){return{}}static get NAME(){throw new Error('You have to implement the static method "NAME", for each component!')}_getConfig(t){return t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t}_mergeConfigObj(t,e){const i=o(e)?H.getDataAttribute(e,"config"):{};return{...this.constructor.Default,..."object"==typeof i?i:{},...o(e)?H.getDataAttributes(e):{},..."object"==typeof t?t:{}}}_typeCheckConfig(t,e=this.constructor.DefaultType){for(const[n,s]of Object.entries(e)){const e=t[n],r=o(e)?"element":null==(i=e)?`${i}`:Object.prototype.toString.call(i).match(/\s([a-z]+)/i)[1].toLowerCase();if(!new RegExp(s).test(r))throw new TypeError(`${this.constructor.NAME.toUpperCase()}: Option "${n}" provided type "${r}" but expected type "${s}".`)}var i}}class W extends ${constructor(t,i){super(),(t=r(t))&&(this._element=t,this._config=this._getConfig(i),e.set(this._element,this.constructor.DATA_KEY,this))}dispose(){e.remove(this._element,this.constructor.DATA_KEY),P.off(this._element,this.constructor.EVENT_KEY);for(const t of Object.getOwnPropertyNames(this))this[t]=null}_queueCallback(t,e,i=!0){_(t,e,i)}_getConfig(t){return t=this._mergeConfigObj(t,this._element),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}static getInstance(t){return e.get(r(t),this.DATA_KEY)}static getOrCreateInstance(t,e={}){return this.getInstance(t)||new this(t,"object"==typeof e?e:null)}static get VERSION(){return"5.3.0"}static get DATA_KEY(){return`bs.${this.NAME}`}static get EVENT_KEY(){return`.${this.DATA_KEY}`}static eventName(t){return`${t}${this.EVENT_KEY}`}}const B=t=>{let e=t.getAttribute("data-bs-target");if(!e||"#"===e){let i=t.getAttribute("href");if(!i||!i.includes("#")&&!i.startsWith("."))return null;i.includes("#")&&!i.startsWith("#")&&(i=`#${i.split("#")[1]}`),e=i&&"#"!==i?i.trim():null}return n(e)},z={find:(t,e=document.documentElement)=>[].concat(...Element.prototype.querySelectorAll.call(e,t)),findOne:(t,e=document.documentElement)=>Element.prototype.querySelector.call(e,t),children:(t,e)=>[].concat(...t.children).filter((t=>t.matches(e))),parents(t,e){const i=[];let n=t.parentNode.closest(e);for(;n;)i.push(n),n=n.parentNode.closest(e);return i},prev(t,e){let i=t.previousElementSibling;for(;i;){if(i.matches(e))return[i];i=i.previousElementSibling}return[]},next(t,e){let i=t.nextElementSibling;for(;i;){if(i.matches(e))return[i];i=i.nextElementSibling}return[]},focusableChildren(t){const e=["a","button","input","textarea","select","details","[tabindex]",'[contenteditable="true"]'].map((t=>`${t}:not([tabindex^="-"])`)).join(",");return this.find(e,t).filter((t=>!l(t)&&a(t)))},getSelectorFromElement(t){const e=B(t);return e&&z.findOne(e)?e:null},getElementFromSelector(t){const e=B(t);return e?z.findOne(e):null},getMultipleElementsFromSelector(t){const e=B(t);return e?z.find(e):[]}},R=(t,e="hide")=>{const i=`click.dismiss${t.EVENT_KEY}`,n=t.NAME;P.on(document,i,`[data-bs-dismiss="${n}"]`,(function(i){if(["A","AREA"].includes(this.tagName)&&i.preventDefault(),l(this))return;const s=z.getElementFromSelector(this)||this.closest(`.${n}`);t.getOrCreateInstance(s)[e]()}))};class q extends W{static get NAME(){return"alert"}close(){if(P.trigger(this._element,"close.bs.alert").defaultPrevented)return;this._element.classList.remove("show");const t=this._element.classList.contains("fade");this._queueCallback((()=>this._destroyElement()),this._element,t)}_destroyElement(){this._element.remove(),P.trigger(this._element,"closed.bs.alert"),this.dispose()}static jQueryInterface(t){return this.each((function(){const e=q.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}R(q,"close"),m(q);const V='[data-bs-toggle="button"]';class K extends W{static get NAME(){return"button"}toggle(){this._element.setAttribute("aria-pressed",this._element.classList.toggle("active"))}static jQueryInterface(t){return this.each((function(){const e=K.getOrCreateInstance(this);"toggle"===t&&e[t]()}))}}P.on(document,"click.bs.button.data-api",V,(t=>{t.preventDefault();const e=t.target.closest(V);K.getOrCreateInstance(e).toggle()})),m(K);const Q={endCallback:null,leftCallback:null,rightCallback:null},X={endCallback:"(function|null)",leftCallback:"(function|null)",rightCallback:"(function|null)"};class Y extends ${constructor(t,e){super(),this._element=t,t&&Y.isSupported()&&(this._config=this._getConfig(e),this._deltaX=0,this._supportPointerEvents=Boolean(window.PointerEvent),this._initEvents())}static get Default(){return Q}static get DefaultType(){return X}static get NAME(){return"swipe"}dispose(){P.off(this._element,".bs.swipe")}_start(t){this._supportPointerEvents?this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX):this._deltaX=t.touches[0].clientX}_end(t){this._eventIsPointerPenTouch(t)&&(this._deltaX=t.clientX-this._deltaX),this._handleSwipe(),g(this._config.endCallback)}_move(t){this._deltaX=t.touches&&t.touches.length>1?0:t.touches[0].clientX-this._deltaX}_handleSwipe(){const t=Math.abs(this._deltaX);if(t<=40)return;const e=t/this._deltaX;this._deltaX=0,e&&g(e>0?this._config.rightCallback:this._config.leftCallback)}_initEvents(){this._supportPointerEvents?(P.on(this._element,"pointerdown.bs.swipe",(t=>this._start(t))),P.on(this._element,"pointerup.bs.swipe",(t=>this._end(t))),this._element.classList.add("pointer-event")):(P.on(this._element,"touchstart.bs.swipe",(t=>this._start(t))),P.on(this._element,"touchmove.bs.swipe",(t=>this._move(t))),P.on(this._element,"touchend.bs.swipe",(t=>this._end(t))))}_eventIsPointerPenTouch(t){return this._supportPointerEvents&&("pen"===t.pointerType||"touch"===t.pointerType)}static isSupported(){return"ontouchstart"in document.documentElement||navigator.maxTouchPoints>0}}const U="next",G="prev",J="left",Z="right",tt="slid.bs.carousel",et="carousel",it="active",nt={ArrowLeft:Z,ArrowRight:J},st={interval:5e3,keyboard:!0,pause:"hover",ride:!1,touch:!0,wrap:!0},ot={interval:"(number|boolean)",keyboard:"boolean",pause:"(string|boolean)",ride:"(boolean|string)",touch:"boolean",wrap:"boolean"};class rt extends W{constructor(t,e){super(t,e),this._interval=null,this._activeElement=null,this._isSliding=!1,this.touchTimeout=null,this._swipeHelper=null,this._indicatorsElement=z.findOne(".carousel-indicators",this._element),this._addEventListeners(),this._config.ride===et&&this.cycle()}static get Default(){return st}static get DefaultType(){return ot}static get NAME(){return"carousel"}next(){this._slide(U)}nextWhenVisible(){!document.hidden&&a(this._element)&&this.next()}prev(){this._slide(G)}pause(){this._isSliding&&s(this._element),this._clearInterval()}cycle(){this._clearInterval(),this._updateInterval(),this._interval=setInterval((()=>this.nextWhenVisible()),this._config.interval)}_maybeEnableCycle(){this._config.ride&&(this._isSliding?P.one(this._element,tt,(()=>this.cycle())):this.cycle())}to(t){const e=this._getItems();if(t>e.length-1||t<0)return;if(this._isSliding)return void P.one(this._element,tt,(()=>this.to(t)));const i=this._getItemIndex(this._getActive());if(i===t)return;const n=t>i?U:G;this._slide(n,e[t])}dispose(){this._swipeHelper&&this._swipeHelper.dispose(),super.dispose()}_configAfterMerge(t){return t.defaultInterval=t.interval,t}_addEventListeners(){this._config.keyboard&&P.on(this._element,"keydown.bs.carousel",(t=>this._keydown(t))),"hover"===this._config.pause&&(P.on(this._element,"mouseenter.bs.carousel",(()=>this.pause())),P.on(this._element,"mouseleave.bs.carousel",(()=>this._maybeEnableCycle()))),this._config.touch&&Y.isSupported()&&this._addTouchEventListeners()}_addTouchEventListeners(){for(const t of z.find(".carousel-item img",this._element))P.on(t,"dragstart.bs.carousel",(t=>t.preventDefault()));const t={leftCallback:()=>this._slide(this._directionToOrder(J)),rightCallback:()=>this._slide(this._directionToOrder(Z)),endCallback:()=>{"hover"===this._config.pause&&(this.pause(),this.touchTimeout&&clearTimeout(this.touchTimeout),this.touchTimeout=setTimeout((()=>this._maybeEnableCycle()),500+this._config.interval))}};this._swipeHelper=new Y(this._element,t)}_keydown(t){if(/input|textarea/i.test(t.target.tagName))return;const e=nt[t.key];e&&(t.preventDefault(),this._slide(this._directionToOrder(e)))}_getItemIndex(t){return this._getItems().indexOf(t)}_setActiveIndicatorElement(t){if(!this._indicatorsElement)return;const e=z.findOne(".active",this._indicatorsElement);e.classList.remove(it),e.removeAttribute("aria-current");const i=z.findOne(`[data-bs-slide-to="${t}"]`,this._indicatorsElement);i&&(i.classList.add(it),i.setAttribute("aria-current","true"))}_updateInterval(){const t=this._activeElement||this._getActive();if(!t)return;const e=Number.parseInt(t.getAttribute("data-bs-interval"),10);this._config.interval=e||this._config.defaultInterval}_slide(t,e=null){if(this._isSliding)return;const i=this._getActive(),n=t===U,s=e||b(this._getItems(),i,n,this._config.wrap);if(s===i)return;const o=this._getItemIndex(s),r=e=>P.trigger(this._element,e,{relatedTarget:s,direction:this._orderToDirection(t),from:this._getItemIndex(i),to:o});if(r("slide.bs.carousel").defaultPrevented)return;if(!i||!s)return;const a=Boolean(this._interval);this.pause(),this._isSliding=!0,this._setActiveIndicatorElement(o),this._activeElement=s;const l=n?"carousel-item-start":"carousel-item-end",c=n?"carousel-item-next":"carousel-item-prev";s.classList.add(c),d(s),i.classList.add(l),s.classList.add(l),this._queueCallback((()=>{s.classList.remove(l,c),s.classList.add(it),i.classList.remove(it,c,l),this._isSliding=!1,r(tt)}),i,this._isAnimated()),a&&this.cycle()}_isAnimated(){return this._element.classList.contains("slide")}_getActive(){return z.findOne(".active.carousel-item",this._element)}_getItems(){return z.find(".carousel-item",this._element)}_clearInterval(){this._interval&&(clearInterval(this._interval),this._interval=null)}_directionToOrder(t){return p()?t===J?G:U:t===J?U:G}_orderToDirection(t){return p()?t===G?J:Z:t===G?Z:J}static jQueryInterface(t){return this.each((function(){const e=rt.getOrCreateInstance(this,t);if("number"!=typeof t){if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}else e.to(t)}))}}P.on(document,"click.bs.carousel.data-api","[data-bs-slide], [data-bs-slide-to]",(function(t){const e=z.getElementFromSelector(this);if(!e||!e.classList.contains(et))return;t.preventDefault();const i=rt.getOrCreateInstance(e),n=this.getAttribute("data-bs-slide-to");return n?(i.to(n),void i._maybeEnableCycle()):"next"===H.getDataAttribute(this,"slide")?(i.next(),void i._maybeEnableCycle()):(i.prev(),void i._maybeEnableCycle())})),P.on(window,"load.bs.carousel.data-api",(()=>{const t=z.find('[data-bs-ride="carousel"]');for(const e of t)rt.getOrCreateInstance(e)})),m(rt);const at="show",lt="collapse",ct="collapsing",ht='[data-bs-toggle="collapse"]',dt={parent:null,toggle:!0},ut={parent:"(null|element)",toggle:"boolean"};class ft extends W{constructor(t,e){super(t,e),this._isTransitioning=!1,this._triggerArray=[];const i=z.find(ht);for(const t of i){const e=z.getSelectorFromElement(t),i=z.find(e).filter((t=>t===this._element));null!==e&&i.length&&this._triggerArray.push(t)}this._initializeChildren(),this._config.parent||this._addAriaAndCollapsedClass(this._triggerArray,this._isShown()),this._config.toggle&&this.toggle()}static get Default(){return dt}static get DefaultType(){return ut}static get NAME(){return"collapse"}toggle(){this._isShown()?this.hide():this.show()}show(){if(this._isTransitioning||this._isShown())return;let t=[];if(this._config.parent&&(t=this._getFirstLevelChildren(".collapse.show, .collapse.collapsing").filter((t=>t!==this._element)).map((t=>ft.getOrCreateInstance(t,{toggle:!1})))),t.length&&t[0]._isTransitioning)return;if(P.trigger(this._element,"show.bs.collapse").defaultPrevented)return;for(const e of t)e.hide();const e=this._getDimension();this._element.classList.remove(lt),this._element.classList.add(ct),this._element.style[e]=0,this._addAriaAndCollapsedClass(this._triggerArray,!0),this._isTransitioning=!0;const i=`scroll${e[0].toUpperCase()+e.slice(1)}`;this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ct),this._element.classList.add(lt,at),this._element.style[e]="",P.trigger(this._element,"shown.bs.collapse")}),this._element,!0),this._element.style[e]=`${this._element[i]}px`}hide(){if(this._isTransitioning||!this._isShown())return;if(P.trigger(this._element,"hide.bs.collapse").defaultPrevented)return;const t=this._getDimension();this._element.style[t]=`${this._element.getBoundingClientRect()[t]}px`,d(this._element),this._element.classList.add(ct),this._element.classList.remove(lt,at);for(const t of this._triggerArray){const e=z.getElementFromSelector(t);e&&!this._isShown(e)&&this._addAriaAndCollapsedClass([t],!1)}this._isTransitioning=!0,this._element.style[t]="",this._queueCallback((()=>{this._isTransitioning=!1,this._element.classList.remove(ct),this._element.classList.add(lt),P.trigger(this._element,"hidden.bs.collapse")}),this._element,!0)}_isShown(t=this._element){return t.classList.contains(at)}_configAfterMerge(t){return t.toggle=Boolean(t.toggle),t.parent=r(t.parent),t}_getDimension(){return this._element.classList.contains("collapse-horizontal")?"width":"height"}_initializeChildren(){if(!this._config.parent)return;const t=this._getFirstLevelChildren(ht);for(const e of t){const t=z.getElementFromSelector(e);t&&this._addAriaAndCollapsedClass([e],this._isShown(t))}}_getFirstLevelChildren(t){const e=z.find(":scope .collapse .collapse",this._config.parent);return z.find(t,this._config.parent).filter((t=>!e.includes(t)))}_addAriaAndCollapsedClass(t,e){if(t.length)for(const i of t)i.classList.toggle("collapsed",!e),i.setAttribute("aria-expanded",e)}static jQueryInterface(t){const e={};return"string"==typeof t&&/show|hide/.test(t)&&(e.toggle=!1),this.each((function(){const i=ft.getOrCreateInstance(this,e);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t]()}}))}}P.on(document,"click.bs.collapse.data-api",ht,(function(t){("A"===t.target.tagName||t.delegateTarget&&"A"===t.delegateTarget.tagName)&&t.preventDefault();for(const t of z.getMultipleElementsFromSelector(this))ft.getOrCreateInstance(t,{toggle:!1}).toggle()})),m(ft);var pt="top",mt="bottom",gt="right",_t="left",bt="auto",vt=[pt,mt,gt,_t],yt="start",wt="end",At="clippingParents",Et="viewport",Tt="popper",Ct="reference",Ot=vt.reduce((function(t,e){return t.concat([e+"-"+yt,e+"-"+wt])}),[]),xt=[].concat(vt,[bt]).reduce((function(t,e){return t.concat([e,e+"-"+yt,e+"-"+wt])}),[]),kt="beforeRead",Lt="read",St="afterRead",Dt="beforeMain",It="main",Nt="afterMain",Pt="beforeWrite",Mt="write",jt="afterWrite",Ft=[kt,Lt,St,Dt,It,Nt,Pt,Mt,jt];function Ht(t){return t?(t.nodeName||"").toLowerCase():null}function $t(t){if(null==t)return window;if("[object Window]"!==t.toString()){var e=t.ownerDocument;return e&&e.defaultView||window}return t}function Wt(t){return t instanceof $t(t).Element||t instanceof Element}function Bt(t){return t instanceof $t(t).HTMLElement||t instanceof HTMLElement}function zt(t){return"undefined"!=typeof ShadowRoot&&(t instanceof $t(t).ShadowRoot||t instanceof ShadowRoot)}const Rt={name:"applyStyles",enabled:!0,phase:"write",fn:function(t){var e=t.state;Object.keys(e.elements).forEach((function(t){var i=e.styles[t]||{},n=e.attributes[t]||{},s=e.elements[t];Bt(s)&&Ht(s)&&(Object.assign(s.style,i),Object.keys(n).forEach((function(t){var e=n[t];!1===e?s.removeAttribute(t):s.setAttribute(t,!0===e?"":e)})))}))},effect:function(t){var e=t.state,i={popper:{position:e.options.strategy,left:"0",top:"0",margin:"0"},arrow:{position:"absolute"},reference:{}};return Object.assign(e.elements.popper.style,i.popper),e.styles=i,e.elements.arrow&&Object.assign(e.elements.arrow.style,i.arrow),function(){Object.keys(e.elements).forEach((function(t){var n=e.elements[t],s=e.attributes[t]||{},o=Object.keys(e.styles.hasOwnProperty(t)?e.styles[t]:i[t]).reduce((function(t,e){return t[e]="",t}),{});Bt(n)&&Ht(n)&&(Object.assign(n.style,o),Object.keys(s).forEach((function(t){n.removeAttribute(t)})))}))}},requires:["computeStyles"]};function qt(t){return t.split("-")[0]}var Vt=Math.max,Kt=Math.min,Qt=Math.round;function Xt(){var t=navigator.userAgentData;return null!=t&&t.brands&&Array.isArray(t.brands)?t.brands.map((function(t){return t.brand+"/"+t.version})).join(" "):navigator.userAgent}function Yt(){return!/^((?!chrome|android).)*safari/i.test(Xt())}function Ut(t,e,i){void 0===e&&(e=!1),void 0===i&&(i=!1);var n=t.getBoundingClientRect(),s=1,o=1;e&&Bt(t)&&(s=t.offsetWidth>0&&Qt(n.width)/t.offsetWidth||1,o=t.offsetHeight>0&&Qt(n.height)/t.offsetHeight||1);var r=(Wt(t)?$t(t):window).visualViewport,a=!Yt()&&i,l=(n.left+(a&&r?r.offsetLeft:0))/s,c=(n.top+(a&&r?r.offsetTop:0))/o,h=n.width/s,d=n.height/o;return{width:h,height:d,top:c,right:l+h,bottom:c+d,left:l,x:l,y:c}}function Gt(t){var e=Ut(t),i=t.offsetWidth,n=t.offsetHeight;return Math.abs(e.width-i)<=1&&(i=e.width),Math.abs(e.height-n)<=1&&(n=e.height),{x:t.offsetLeft,y:t.offsetTop,width:i,height:n}}function Jt(t,e){var i=e.getRootNode&&e.getRootNode();if(t.contains(e))return!0;if(i&&zt(i)){var n=e;do{if(n&&t.isSameNode(n))return!0;n=n.parentNode||n.host}while(n)}return!1}function Zt(t){return $t(t).getComputedStyle(t)}function te(t){return["table","td","th"].indexOf(Ht(t))>=0}function ee(t){return((Wt(t)?t.ownerDocument:t.document)||window.document).documentElement}function ie(t){return"html"===Ht(t)?t:t.assignedSlot||t.parentNode||(zt(t)?t.host:null)||ee(t)}function ne(t){return Bt(t)&&"fixed"!==Zt(t).position?t.offsetParent:null}function se(t){for(var e=$t(t),i=ne(t);i&&te(i)&&"static"===Zt(i).position;)i=ne(i);return i&&("html"===Ht(i)||"body"===Ht(i)&&"static"===Zt(i).position)?e:i||function(t){var e=/firefox/i.test(Xt());if(/Trident/i.test(Xt())&&Bt(t)&&"fixed"===Zt(t).position)return null;var i=ie(t);for(zt(i)&&(i=i.host);Bt(i)&&["html","body"].indexOf(Ht(i))<0;){var n=Zt(i);if("none"!==n.transform||"none"!==n.perspective||"paint"===n.contain||-1!==["transform","perspective"].indexOf(n.willChange)||e&&"filter"===n.willChange||e&&n.filter&&"none"!==n.filter)return i;i=i.parentNode}return null}(t)||e}function oe(t){return["top","bottom"].indexOf(t)>=0?"x":"y"}function re(t,e,i){return Vt(t,Kt(e,i))}function ae(t){return Object.assign({},{top:0,right:0,bottom:0,left:0},t)}function le(t,e){return e.reduce((function(e,i){return e[i]=t,e}),{})}const ce={name:"arrow",enabled:!0,phase:"main",fn:function(t){var e,i=t.state,n=t.name,s=t.options,o=i.elements.arrow,r=i.modifiersData.popperOffsets,a=qt(i.placement),l=oe(a),c=[_t,gt].indexOf(a)>=0?"height":"width";if(o&&r){var h=function(t,e){return ae("number"!=typeof(t="function"==typeof t?t(Object.assign({},e.rects,{placement:e.placement})):t)?t:le(t,vt))}(s.padding,i),d=Gt(o),u="y"===l?pt:_t,f="y"===l?mt:gt,p=i.rects.reference[c]+i.rects.reference[l]-r[l]-i.rects.popper[c],m=r[l]-i.rects.reference[l],g=se(o),_=g?"y"===l?g.clientHeight||0:g.clientWidth||0:0,b=p/2-m/2,v=h[u],y=_-d[c]-h[f],w=_/2-d[c]/2+b,A=re(v,w,y),E=l;i.modifiersData[n]=((e={})[E]=A,e.centerOffset=A-w,e)}},effect:function(t){var e=t.state,i=t.options.element,n=void 0===i?"[data-popper-arrow]":i;null!=n&&("string"!=typeof n||(n=e.elements.popper.querySelector(n)))&&Jt(e.elements.popper,n)&&(e.elements.arrow=n)},requires:["popperOffsets"],requiresIfExists:["preventOverflow"]};function he(t){return t.split("-")[1]}var de={top:"auto",right:"auto",bottom:"auto",left:"auto"};function ue(t){var e,i=t.popper,n=t.popperRect,s=t.placement,o=t.variation,r=t.offsets,a=t.position,l=t.gpuAcceleration,c=t.adaptive,h=t.roundOffsets,d=t.isFixed,u=r.x,f=void 0===u?0:u,p=r.y,m=void 0===p?0:p,g="function"==typeof h?h({x:f,y:m}):{x:f,y:m};f=g.x,m=g.y;var _=r.hasOwnProperty("x"),b=r.hasOwnProperty("y"),v=_t,y=pt,w=window;if(c){var A=se(i),E="clientHeight",T="clientWidth";A===$t(i)&&"static"!==Zt(A=ee(i)).position&&"absolute"===a&&(E="scrollHeight",T="scrollWidth"),(s===pt||(s===_t||s===gt)&&o===wt)&&(y=mt,m-=(d&&A===w&&w.visualViewport?w.visualViewport.height:A[E])-n.height,m*=l?1:-1),s!==_t&&(s!==pt&&s!==mt||o!==wt)||(v=gt,f-=(d&&A===w&&w.visualViewport?w.visualViewport.width:A[T])-n.width,f*=l?1:-1)}var C,O=Object.assign({position:a},c&&de),x=!0===h?function(t,e){var i=t.x,n=t.y,s=e.devicePixelRatio||1;return{x:Qt(i*s)/s||0,y:Qt(n*s)/s||0}}({x:f,y:m},$t(i)):{x:f,y:m};return f=x.x,m=x.y,l?Object.assign({},O,((C={})[y]=b?"0":"",C[v]=_?"0":"",C.transform=(w.devicePixelRatio||1)<=1?"translate("+f+"px, "+m+"px)":"translate3d("+f+"px, "+m+"px, 0)",C)):Object.assign({},O,((e={})[y]=b?m+"px":"",e[v]=_?f+"px":"",e.transform="",e))}const fe={name:"computeStyles",enabled:!0,phase:"beforeWrite",fn:function(t){var e=t.state,i=t.options,n=i.gpuAcceleration,s=void 0===n||n,o=i.adaptive,r=void 0===o||o,a=i.roundOffsets,l=void 0===a||a,c={placement:qt(e.placement),variation:he(e.placement),popper:e.elements.popper,popperRect:e.rects.popper,gpuAcceleration:s,isFixed:"fixed"===e.options.strategy};null!=e.modifiersData.popperOffsets&&(e.styles.popper=Object.assign({},e.styles.popper,ue(Object.assign({},c,{offsets:e.modifiersData.popperOffsets,position:e.options.strategy,adaptive:r,roundOffsets:l})))),null!=e.modifiersData.arrow&&(e.styles.arrow=Object.assign({},e.styles.arrow,ue(Object.assign({},c,{offsets:e.modifiersData.arrow,position:"absolute",adaptive:!1,roundOffsets:l})))),e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-placement":e.placement})},data:{}};var pe={passive:!0};const me={name:"eventListeners",enabled:!0,phase:"write",fn:function(){},effect:function(t){var e=t.state,i=t.instance,n=t.options,s=n.scroll,o=void 0===s||s,r=n.resize,a=void 0===r||r,l=$t(e.elements.popper),c=[].concat(e.scrollParents.reference,e.scrollParents.popper);return o&&c.forEach((function(t){t.addEventListener("scroll",i.update,pe)})),a&&l.addEventListener("resize",i.update,pe),function(){o&&c.forEach((function(t){t.removeEventListener("scroll",i.update,pe)})),a&&l.removeEventListener("resize",i.update,pe)}},data:{}};var ge={left:"right",right:"left",bottom:"top",top:"bottom"};function _e(t){return t.replace(/left|right|bottom|top/g,(function(t){return ge[t]}))}var be={start:"end",end:"start"};function ve(t){return t.replace(/start|end/g,(function(t){return be[t]}))}function ye(t){var e=$t(t);return{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function we(t){return Ut(ee(t)).left+ye(t).scrollLeft}function Ae(t){var e=Zt(t),i=e.overflow,n=e.overflowX,s=e.overflowY;return/auto|scroll|overlay|hidden/.test(i+s+n)}function Ee(t){return["html","body","#document"].indexOf(Ht(t))>=0?t.ownerDocument.body:Bt(t)&&Ae(t)?t:Ee(ie(t))}function Te(t,e){var i;void 0===e&&(e=[]);var n=Ee(t),s=n===(null==(i=t.ownerDocument)?void 0:i.body),o=$t(n),r=s?[o].concat(o.visualViewport||[],Ae(n)?n:[]):n,a=e.concat(r);return s?a:a.concat(Te(ie(r)))}function Ce(t){return Object.assign({},t,{left:t.x,top:t.y,right:t.x+t.width,bottom:t.y+t.height})}function Oe(t,e,i){return e===Et?Ce(function(t,e){var i=$t(t),n=ee(t),s=i.visualViewport,o=n.clientWidth,r=n.clientHeight,a=0,l=0;if(s){o=s.width,r=s.height;var c=Yt();(c||!c&&"fixed"===e)&&(a=s.offsetLeft,l=s.offsetTop)}return{width:o,height:r,x:a+we(t),y:l}}(t,i)):Wt(e)?function(t,e){var i=Ut(t,!1,"fixed"===e);return i.top=i.top+t.clientTop,i.left=i.left+t.clientLeft,i.bottom=i.top+t.clientHeight,i.right=i.left+t.clientWidth,i.width=t.clientWidth,i.height=t.clientHeight,i.x=i.left,i.y=i.top,i}(e,i):Ce(function(t){var e,i=ee(t),n=ye(t),s=null==(e=t.ownerDocument)?void 0:e.body,o=Vt(i.scrollWidth,i.clientWidth,s?s.scrollWidth:0,s?s.clientWidth:0),r=Vt(i.scrollHeight,i.clientHeight,s?s.scrollHeight:0,s?s.clientHeight:0),a=-n.scrollLeft+we(t),l=-n.scrollTop;return"rtl"===Zt(s||i).direction&&(a+=Vt(i.clientWidth,s?s.clientWidth:0)-o),{width:o,height:r,x:a,y:l}}(ee(t)))}function xe(t){var e,i=t.reference,n=t.element,s=t.placement,o=s?qt(s):null,r=s?he(s):null,a=i.x+i.width/2-n.width/2,l=i.y+i.height/2-n.height/2;switch(o){case pt:e={x:a,y:i.y-n.height};break;case mt:e={x:a,y:i.y+i.height};break;case gt:e={x:i.x+i.width,y:l};break;case _t:e={x:i.x-n.width,y:l};break;default:e={x:i.x,y:i.y}}var c=o?oe(o):null;if(null!=c){var h="y"===c?"height":"width";switch(r){case yt:e[c]=e[c]-(i[h]/2-n[h]/2);break;case wt:e[c]=e[c]+(i[h]/2-n[h]/2)}}return e}function ke(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=void 0===n?t.placement:n,o=i.strategy,r=void 0===o?t.strategy:o,a=i.boundary,l=void 0===a?At:a,c=i.rootBoundary,h=void 0===c?Et:c,d=i.elementContext,u=void 0===d?Tt:d,f=i.altBoundary,p=void 0!==f&&f,m=i.padding,g=void 0===m?0:m,_=ae("number"!=typeof g?g:le(g,vt)),b=u===Tt?Ct:Tt,v=t.rects.popper,y=t.elements[p?b:u],w=function(t,e,i,n){var s="clippingParents"===e?function(t){var e=Te(ie(t)),i=["absolute","fixed"].indexOf(Zt(t).position)>=0&&Bt(t)?se(t):t;return Wt(i)?e.filter((function(t){return Wt(t)&&Jt(t,i)&&"body"!==Ht(t)})):[]}(t):[].concat(e),o=[].concat(s,[i]),r=o[0],a=o.reduce((function(e,i){var s=Oe(t,i,n);return e.top=Vt(s.top,e.top),e.right=Kt(s.right,e.right),e.bottom=Kt(s.bottom,e.bottom),e.left=Vt(s.left,e.left),e}),Oe(t,r,n));return a.width=a.right-a.left,a.height=a.bottom-a.top,a.x=a.left,a.y=a.top,a}(Wt(y)?y:y.contextElement||ee(t.elements.popper),l,h,r),A=Ut(t.elements.reference),E=xe({reference:A,element:v,strategy:"absolute",placement:s}),T=Ce(Object.assign({},v,E)),C=u===Tt?T:A,O={top:w.top-C.top+_.top,bottom:C.bottom-w.bottom+_.bottom,left:w.left-C.left+_.left,right:C.right-w.right+_.right},x=t.modifiersData.offset;if(u===Tt&&x){var k=x[s];Object.keys(O).forEach((function(t){var e=[gt,mt].indexOf(t)>=0?1:-1,i=[pt,mt].indexOf(t)>=0?"y":"x";O[t]+=k[i]*e}))}return O}function Le(t,e){void 0===e&&(e={});var i=e,n=i.placement,s=i.boundary,o=i.rootBoundary,r=i.padding,a=i.flipVariations,l=i.allowedAutoPlacements,c=void 0===l?xt:l,h=he(n),d=h?a?Ot:Ot.filter((function(t){return he(t)===h})):vt,u=d.filter((function(t){return c.indexOf(t)>=0}));0===u.length&&(u=d);var f=u.reduce((function(e,i){return e[i]=ke(t,{placement:i,boundary:s,rootBoundary:o,padding:r})[qt(i)],e}),{});return Object.keys(f).sort((function(t,e){return f[t]-f[e]}))}const Se={name:"flip",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name;if(!e.modifiersData[n]._skip){for(var s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0===r||r,l=i.fallbackPlacements,c=i.padding,h=i.boundary,d=i.rootBoundary,u=i.altBoundary,f=i.flipVariations,p=void 0===f||f,m=i.allowedAutoPlacements,g=e.options.placement,_=qt(g),b=l||(_!==g&&p?function(t){if(qt(t)===bt)return[];var e=_e(t);return[ve(t),e,ve(e)]}(g):[_e(g)]),v=[g].concat(b).reduce((function(t,i){return t.concat(qt(i)===bt?Le(e,{placement:i,boundary:h,rootBoundary:d,padding:c,flipVariations:p,allowedAutoPlacements:m}):i)}),[]),y=e.rects.reference,w=e.rects.popper,A=new Map,E=!0,T=v[0],C=0;C=0,S=L?"width":"height",D=ke(e,{placement:O,boundary:h,rootBoundary:d,altBoundary:u,padding:c}),I=L?k?gt:_t:k?mt:pt;y[S]>w[S]&&(I=_e(I));var N=_e(I),P=[];if(o&&P.push(D[x]<=0),a&&P.push(D[I]<=0,D[N]<=0),P.every((function(t){return t}))){T=O,E=!1;break}A.set(O,P)}if(E)for(var M=function(t){var e=v.find((function(e){var i=A.get(e);if(i)return i.slice(0,t).every((function(t){return t}))}));if(e)return T=e,"break"},j=p?3:1;j>0&&"break"!==M(j);j--);e.placement!==T&&(e.modifiersData[n]._skip=!0,e.placement=T,e.reset=!0)}},requiresIfExists:["offset"],data:{_skip:!1}};function De(t,e,i){return void 0===i&&(i={x:0,y:0}),{top:t.top-e.height-i.y,right:t.right-e.width+i.x,bottom:t.bottom-e.height+i.y,left:t.left-e.width-i.x}}function Ie(t){return[pt,gt,mt,_t].some((function(e){return t[e]>=0}))}const Ne={name:"hide",enabled:!0,phase:"main",requiresIfExists:["preventOverflow"],fn:function(t){var e=t.state,i=t.name,n=e.rects.reference,s=e.rects.popper,o=e.modifiersData.preventOverflow,r=ke(e,{elementContext:"reference"}),a=ke(e,{altBoundary:!0}),l=De(r,n),c=De(a,s,o),h=Ie(l),d=Ie(c);e.modifiersData[i]={referenceClippingOffsets:l,popperEscapeOffsets:c,isReferenceHidden:h,hasPopperEscaped:d},e.attributes.popper=Object.assign({},e.attributes.popper,{"data-popper-reference-hidden":h,"data-popper-escaped":d})}},Pe={name:"offset",enabled:!0,phase:"main",requires:["popperOffsets"],fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.offset,o=void 0===s?[0,0]:s,r=xt.reduce((function(t,i){return t[i]=function(t,e,i){var n=qt(t),s=[_t,pt].indexOf(n)>=0?-1:1,o="function"==typeof i?i(Object.assign({},e,{placement:t})):i,r=o[0],a=o[1];return r=r||0,a=(a||0)*s,[_t,gt].indexOf(n)>=0?{x:a,y:r}:{x:r,y:a}}(i,e.rects,o),t}),{}),a=r[e.placement],l=a.x,c=a.y;null!=e.modifiersData.popperOffsets&&(e.modifiersData.popperOffsets.x+=l,e.modifiersData.popperOffsets.y+=c),e.modifiersData[n]=r}},Me={name:"popperOffsets",enabled:!0,phase:"read",fn:function(t){var e=t.state,i=t.name;e.modifiersData[i]=xe({reference:e.rects.reference,element:e.rects.popper,strategy:"absolute",placement:e.placement})},data:{}},je={name:"preventOverflow",enabled:!0,phase:"main",fn:function(t){var e=t.state,i=t.options,n=t.name,s=i.mainAxis,o=void 0===s||s,r=i.altAxis,a=void 0!==r&&r,l=i.boundary,c=i.rootBoundary,h=i.altBoundary,d=i.padding,u=i.tether,f=void 0===u||u,p=i.tetherOffset,m=void 0===p?0:p,g=ke(e,{boundary:l,rootBoundary:c,padding:d,altBoundary:h}),_=qt(e.placement),b=he(e.placement),v=!b,y=oe(_),w="x"===y?"y":"x",A=e.modifiersData.popperOffsets,E=e.rects.reference,T=e.rects.popper,C="function"==typeof m?m(Object.assign({},e.rects,{placement:e.placement})):m,O="number"==typeof C?{mainAxis:C,altAxis:C}:Object.assign({mainAxis:0,altAxis:0},C),x=e.modifiersData.offset?e.modifiersData.offset[e.placement]:null,k={x:0,y:0};if(A){if(o){var L,S="y"===y?pt:_t,D="y"===y?mt:gt,I="y"===y?"height":"width",N=A[y],P=N+g[S],M=N-g[D],j=f?-T[I]/2:0,F=b===yt?E[I]:T[I],H=b===yt?-T[I]:-E[I],$=e.elements.arrow,W=f&&$?Gt($):{width:0,height:0},B=e.modifiersData["arrow#persistent"]?e.modifiersData["arrow#persistent"].padding:{top:0,right:0,bottom:0,left:0},z=B[S],R=B[D],q=re(0,E[I],W[I]),V=v?E[I]/2-j-q-z-O.mainAxis:F-q-z-O.mainAxis,K=v?-E[I]/2+j+q+R+O.mainAxis:H+q+R+O.mainAxis,Q=e.elements.arrow&&se(e.elements.arrow),X=Q?"y"===y?Q.clientTop||0:Q.clientLeft||0:0,Y=null!=(L=null==x?void 0:x[y])?L:0,U=N+K-Y,G=re(f?Kt(P,N+V-Y-X):P,N,f?Vt(M,U):M);A[y]=G,k[y]=G-N}if(a){var J,Z="x"===y?pt:_t,tt="x"===y?mt:gt,et=A[w],it="y"===w?"height":"width",nt=et+g[Z],st=et-g[tt],ot=-1!==[pt,_t].indexOf(_),rt=null!=(J=null==x?void 0:x[w])?J:0,at=ot?nt:et-E[it]-T[it]-rt+O.altAxis,lt=ot?et+E[it]+T[it]-rt-O.altAxis:st,ct=f&&ot?function(t,e,i){var n=re(t,e,i);return n>i?i:n}(at,et,lt):re(f?at:nt,et,f?lt:st);A[w]=ct,k[w]=ct-et}e.modifiersData[n]=k}},requiresIfExists:["offset"]};function Fe(t,e,i){void 0===i&&(i=!1);var n,s,o=Bt(e),r=Bt(e)&&function(t){var e=t.getBoundingClientRect(),i=Qt(e.width)/t.offsetWidth||1,n=Qt(e.height)/t.offsetHeight||1;return 1!==i||1!==n}(e),a=ee(e),l=Ut(t,r,i),c={scrollLeft:0,scrollTop:0},h={x:0,y:0};return(o||!o&&!i)&&(("body"!==Ht(e)||Ae(a))&&(c=(n=e)!==$t(n)&&Bt(n)?{scrollLeft:(s=n).scrollLeft,scrollTop:s.scrollTop}:ye(n)),Bt(e)?((h=Ut(e,!0)).x+=e.clientLeft,h.y+=e.clientTop):a&&(h.x=we(a))),{x:l.left+c.scrollLeft-h.x,y:l.top+c.scrollTop-h.y,width:l.width,height:l.height}}function He(t){var e=new Map,i=new Set,n=[];function s(t){i.add(t.name),[].concat(t.requires||[],t.requiresIfExists||[]).forEach((function(t){if(!i.has(t)){var n=e.get(t);n&&s(n)}})),n.push(t)}return t.forEach((function(t){e.set(t.name,t)})),t.forEach((function(t){i.has(t.name)||s(t)})),n}var $e={placement:"bottom",modifiers:[],strategy:"absolute"};function We(){for(var t=arguments.length,e=new Array(t),i=0;iNumber.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_getPopperConfig(){const t={placement:this._getPlacement(),modifiers:[{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"offset",options:{offset:this._getOffset()}}]};return(this._inNavbar||"static"===this._config.display)&&(H.setDataAttribute(this._menu,"popper","static"),t.modifiers=[{name:"applyStyles",enabled:!1}]),{...t,...g(this._config.popperConfig,[t])}}_selectMenuItem({key:t,target:e}){const i=z.find(".dropdown-menu .dropdown-item:not(.disabled):not(:disabled)",this._menu).filter((t=>a(t)));i.length&&b(i,e,t===Xe,!i.includes(e)).focus()}static jQueryInterface(t){return this.each((function(){const e=ci.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}static clearMenus(t){if(2===t.button||"keyup"===t.type&&"Tab"!==t.key)return;const e=z.find(Ze);for(const i of e){const e=ci.getInstance(i);if(!e||!1===e._config.autoClose)continue;const n=t.composedPath(),s=n.includes(e._menu);if(n.includes(e._element)||"inside"===e._config.autoClose&&!s||"outside"===e._config.autoClose&&s)continue;if(e._menu.contains(t.target)&&("keyup"===t.type&&"Tab"===t.key||/input|select|option|textarea|form/i.test(t.target.tagName)))continue;const o={relatedTarget:e._element};"click"===t.type&&(o.clickEvent=t),e._completeHide(o)}}static dataApiKeydownHandler(t){const e=/input|textarea/i.test(t.target.tagName),i="Escape"===t.key,n=[Qe,Xe].includes(t.key);if(!n&&!i)return;if(e&&!i)return;t.preventDefault();const s=this.matches(Je)?this:z.prev(this,Je)[0]||z.next(this,Je)[0]||z.findOne(Je,t.delegateTarget.parentNode),o=ci.getOrCreateInstance(s);if(n)return t.stopPropagation(),o.show(),void o._selectMenuItem(t);o._isShown()&&(t.stopPropagation(),o.hide(),s.focus())}}P.on(document,Ue,Je,ci.dataApiKeydownHandler),P.on(document,Ue,ti,ci.dataApiKeydownHandler),P.on(document,Ye,ci.clearMenus),P.on(document,"keyup.bs.dropdown.data-api",ci.clearMenus),P.on(document,Ye,Je,(function(t){t.preventDefault(),ci.getOrCreateInstance(this).toggle()})),m(ci);const hi="show",di="mousedown.bs.backdrop",ui={className:"modal-backdrop",clickCallback:null,isAnimated:!1,isVisible:!0,rootElement:"body"},fi={className:"string",clickCallback:"(function|null)",isAnimated:"boolean",isVisible:"boolean",rootElement:"(element|string)"};class pi extends ${constructor(t){super(),this._config=this._getConfig(t),this._isAppended=!1,this._element=null}static get Default(){return ui}static get DefaultType(){return fi}static get NAME(){return"backdrop"}show(t){if(!this._config.isVisible)return void g(t);this._append();const e=this._getElement();this._config.isAnimated&&d(e),e.classList.add(hi),this._emulateAnimation((()=>{g(t)}))}hide(t){this._config.isVisible?(this._getElement().classList.remove(hi),this._emulateAnimation((()=>{this.dispose(),g(t)}))):g(t)}dispose(){this._isAppended&&(P.off(this._element,di),this._element.remove(),this._isAppended=!1)}_getElement(){if(!this._element){const t=document.createElement("div");t.className=this._config.className,this._config.isAnimated&&t.classList.add("fade"),this._element=t}return this._element}_configAfterMerge(t){return t.rootElement=r(t.rootElement),t}_append(){if(this._isAppended)return;const t=this._getElement();this._config.rootElement.append(t),P.on(t,di,(()=>{g(this._config.clickCallback)})),this._isAppended=!0}_emulateAnimation(t){_(t,this._getElement(),this._config.isAnimated)}}const mi=".bs.focustrap",gi="backward",_i={autofocus:!0,trapElement:null},bi={autofocus:"boolean",trapElement:"element"};class vi extends ${constructor(t){super(),this._config=this._getConfig(t),this._isActive=!1,this._lastTabNavDirection=null}static get Default(){return _i}static get DefaultType(){return bi}static get NAME(){return"focustrap"}activate(){this._isActive||(this._config.autofocus&&this._config.trapElement.focus(),P.off(document,mi),P.on(document,"focusin.bs.focustrap",(t=>this._handleFocusin(t))),P.on(document,"keydown.tab.bs.focustrap",(t=>this._handleKeydown(t))),this._isActive=!0)}deactivate(){this._isActive&&(this._isActive=!1,P.off(document,mi))}_handleFocusin(t){const{trapElement:e}=this._config;if(t.target===document||t.target===e||e.contains(t.target))return;const i=z.focusableChildren(e);0===i.length?e.focus():this._lastTabNavDirection===gi?i[i.length-1].focus():i[0].focus()}_handleKeydown(t){"Tab"===t.key&&(this._lastTabNavDirection=t.shiftKey?gi:"forward")}}const yi=".fixed-top, .fixed-bottom, .is-fixed, .sticky-top",wi=".sticky-top",Ai="padding-right",Ei="margin-right";class Ti{constructor(){this._element=document.body}getWidth(){const t=document.documentElement.clientWidth;return Math.abs(window.innerWidth-t)}hide(){const t=this.getWidth();this._disableOverFlow(),this._setElementAttributes(this._element,Ai,(e=>e+t)),this._setElementAttributes(yi,Ai,(e=>e+t)),this._setElementAttributes(wi,Ei,(e=>e-t))}reset(){this._resetElementAttributes(this._element,"overflow"),this._resetElementAttributes(this._element,Ai),this._resetElementAttributes(yi,Ai),this._resetElementAttributes(wi,Ei)}isOverflowing(){return this.getWidth()>0}_disableOverFlow(){this._saveInitialAttribute(this._element,"overflow"),this._element.style.overflow="hidden"}_setElementAttributes(t,e,i){const n=this.getWidth();this._applyManipulationCallback(t,(t=>{if(t!==this._element&&window.innerWidth>t.clientWidth+n)return;this._saveInitialAttribute(t,e);const s=window.getComputedStyle(t).getPropertyValue(e);t.style.setProperty(e,`${i(Number.parseFloat(s))}px`)}))}_saveInitialAttribute(t,e){const i=t.style.getPropertyValue(e);i&&H.setDataAttribute(t,e,i)}_resetElementAttributes(t,e){this._applyManipulationCallback(t,(t=>{const i=H.getDataAttribute(t,e);null!==i?(H.removeDataAttribute(t,e),t.style.setProperty(e,i)):t.style.removeProperty(e)}))}_applyManipulationCallback(t,e){if(o(t))e(t);else for(const i of z.find(t,this._element))e(i)}}const Ci=".bs.modal",Oi="hidden.bs.modal",xi="show.bs.modal",ki="modal-open",Li="show",Si="modal-static",Di={backdrop:!0,focus:!0,keyboard:!0},Ii={backdrop:"(boolean|string)",focus:"boolean",keyboard:"boolean"};class Ni extends W{constructor(t,e){super(t,e),this._dialog=z.findOne(".modal-dialog",this._element),this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._isShown=!1,this._isTransitioning=!1,this._scrollBar=new Ti,this._addEventListeners()}static get Default(){return Di}static get DefaultType(){return Ii}static get NAME(){return"modal"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||this._isTransitioning||P.trigger(this._element,xi,{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._isTransitioning=!0,this._scrollBar.hide(),document.body.classList.add(ki),this._adjustDialog(),this._backdrop.show((()=>this._showElement(t))))}hide(){this._isShown&&!this._isTransitioning&&(P.trigger(this._element,"hide.bs.modal").defaultPrevented||(this._isShown=!1,this._isTransitioning=!0,this._focustrap.deactivate(),this._element.classList.remove(Li),this._queueCallback((()=>this._hideModal()),this._element,this._isAnimated())))}dispose(){P.off(window,Ci),P.off(this._dialog,Ci),this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}handleUpdate(){this._adjustDialog()}_initializeBackDrop(){return new pi({isVisible:Boolean(this._config.backdrop),isAnimated:this._isAnimated()})}_initializeFocusTrap(){return new vi({trapElement:this._element})}_showElement(t){document.body.contains(this._element)||document.body.append(this._element),this._element.style.display="block",this._element.removeAttribute("aria-hidden"),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.scrollTop=0;const e=z.findOne(".modal-body",this._dialog);e&&(e.scrollTop=0),d(this._element),this._element.classList.add(Li),this._queueCallback((()=>{this._config.focus&&this._focustrap.activate(),this._isTransitioning=!1,P.trigger(this._element,"shown.bs.modal",{relatedTarget:t})}),this._dialog,this._isAnimated())}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.modal",(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():this._triggerBackdropTransition())})),P.on(window,"resize.bs.modal",(()=>{this._isShown&&!this._isTransitioning&&this._adjustDialog()})),P.on(this._element,"mousedown.dismiss.bs.modal",(t=>{P.one(this._element,"click.dismiss.bs.modal",(e=>{this._element===t.target&&this._element===e.target&&("static"!==this._config.backdrop?this._config.backdrop&&this.hide():this._triggerBackdropTransition())}))}))}_hideModal(){this._element.style.display="none",this._element.setAttribute("aria-hidden",!0),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._isTransitioning=!1,this._backdrop.hide((()=>{document.body.classList.remove(ki),this._resetAdjustments(),this._scrollBar.reset(),P.trigger(this._element,Oi)}))}_isAnimated(){return this._element.classList.contains("fade")}_triggerBackdropTransition(){if(P.trigger(this._element,"hidePrevented.bs.modal").defaultPrevented)return;const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._element.style.overflowY;"hidden"===e||this._element.classList.contains(Si)||(t||(this._element.style.overflowY="hidden"),this._element.classList.add(Si),this._queueCallback((()=>{this._element.classList.remove(Si),this._queueCallback((()=>{this._element.style.overflowY=e}),this._dialog)}),this._dialog),this._element.focus())}_adjustDialog(){const t=this._element.scrollHeight>document.documentElement.clientHeight,e=this._scrollBar.getWidth(),i=e>0;if(i&&!t){const t=p()?"paddingLeft":"paddingRight";this._element.style[t]=`${e}px`}if(!i&&t){const t=p()?"paddingRight":"paddingLeft";this._element.style[t]=`${e}px`}}_resetAdjustments(){this._element.style.paddingLeft="",this._element.style.paddingRight=""}static jQueryInterface(t,e){return this.each((function(){const i=Ni.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===i[t])throw new TypeError(`No method named "${t}"`);i[t](e)}}))}}P.on(document,"click.bs.modal.data-api",'[data-bs-toggle="modal"]',(function(t){const e=z.getElementFromSelector(this);["A","AREA"].includes(this.tagName)&&t.preventDefault(),P.one(e,xi,(t=>{t.defaultPrevented||P.one(e,Oi,(()=>{a(this)&&this.focus()}))}));const i=z.findOne(".modal.show");i&&Ni.getInstance(i).hide(),Ni.getOrCreateInstance(e).toggle(this)})),R(Ni),m(Ni);const Pi="show",Mi="showing",ji="hiding",Fi=".offcanvas.show",Hi="hidePrevented.bs.offcanvas",$i="hidden.bs.offcanvas",Wi={backdrop:!0,keyboard:!0,scroll:!1},Bi={backdrop:"(boolean|string)",keyboard:"boolean",scroll:"boolean"};class zi extends W{constructor(t,e){super(t,e),this._isShown=!1,this._backdrop=this._initializeBackDrop(),this._focustrap=this._initializeFocusTrap(),this._addEventListeners()}static get Default(){return Wi}static get DefaultType(){return Bi}static get NAME(){return"offcanvas"}toggle(t){return this._isShown?this.hide():this.show(t)}show(t){this._isShown||P.trigger(this._element,"show.bs.offcanvas",{relatedTarget:t}).defaultPrevented||(this._isShown=!0,this._backdrop.show(),this._config.scroll||(new Ti).hide(),this._element.setAttribute("aria-modal",!0),this._element.setAttribute("role","dialog"),this._element.classList.add(Mi),this._queueCallback((()=>{this._config.scroll&&!this._config.backdrop||this._focustrap.activate(),this._element.classList.add(Pi),this._element.classList.remove(Mi),P.trigger(this._element,"shown.bs.offcanvas",{relatedTarget:t})}),this._element,!0))}hide(){this._isShown&&(P.trigger(this._element,"hide.bs.offcanvas").defaultPrevented||(this._focustrap.deactivate(),this._element.blur(),this._isShown=!1,this._element.classList.add(ji),this._backdrop.hide(),this._queueCallback((()=>{this._element.classList.remove(Pi,ji),this._element.removeAttribute("aria-modal"),this._element.removeAttribute("role"),this._config.scroll||(new Ti).reset(),P.trigger(this._element,$i)}),this._element,!0)))}dispose(){this._backdrop.dispose(),this._focustrap.deactivate(),super.dispose()}_initializeBackDrop(){const t=Boolean(this._config.backdrop);return new pi({className:"offcanvas-backdrop",isVisible:t,isAnimated:!0,rootElement:this._element.parentNode,clickCallback:t?()=>{"static"!==this._config.backdrop?this.hide():P.trigger(this._element,Hi)}:null})}_initializeFocusTrap(){return new vi({trapElement:this._element})}_addEventListeners(){P.on(this._element,"keydown.dismiss.bs.offcanvas",(t=>{"Escape"===t.key&&(this._config.keyboard?this.hide():P.trigger(this._element,Hi))}))}static jQueryInterface(t){return this.each((function(){const e=zi.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}P.on(document,"click.bs.offcanvas.data-api",'[data-bs-toggle="offcanvas"]',(function(t){const e=z.getElementFromSelector(this);if(["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this))return;P.one(e,$i,(()=>{a(this)&&this.focus()}));const i=z.findOne(Fi);i&&i!==e&&zi.getInstance(i).hide(),zi.getOrCreateInstance(e).toggle(this)})),P.on(window,"load.bs.offcanvas.data-api",(()=>{for(const t of z.find(Fi))zi.getOrCreateInstance(t).show()})),P.on(window,"resize.bs.offcanvas",(()=>{for(const t of z.find("[aria-modal][class*=show][class*=offcanvas-]"))"fixed"!==getComputedStyle(t).position&&zi.getOrCreateInstance(t).hide()})),R(zi),m(zi);const Ri={"*":["class","dir","id","lang","role",/^aria-[\w-]*$/i],a:["target","href","title","rel"],area:[],b:[],br:[],col:[],code:[],div:[],em:[],hr:[],h1:[],h2:[],h3:[],h4:[],h5:[],h6:[],i:[],img:["src","srcset","alt","title","width","height"],li:[],ol:[],p:[],pre:[],s:[],small:[],span:[],sub:[],sup:[],strong:[],u:[],ul:[]},qi=new Set(["background","cite","href","itemtype","longdesc","poster","src","xlink:href"]),Vi=/^(?!javascript:)(?:[a-z0-9+.-]+:|[^&:/?#]*(?:[/?#]|$))/i,Ki=(t,e)=>{const i=t.nodeName.toLowerCase();return e.includes(i)?!qi.has(i)||Boolean(Vi.test(t.nodeValue)):e.filter((t=>t instanceof RegExp)).some((t=>t.test(i)))},Qi={allowList:Ri,content:{},extraClass:"",html:!1,sanitize:!0,sanitizeFn:null,template:"
"},Xi={allowList:"object",content:"object",extraClass:"(string|function)",html:"boolean",sanitize:"boolean",sanitizeFn:"(null|function)",template:"string"},Yi={entry:"(string|element|function|null)",selector:"(string|element)"};class Ui extends ${constructor(t){super(),this._config=this._getConfig(t)}static get Default(){return Qi}static get DefaultType(){return Xi}static get NAME(){return"TemplateFactory"}getContent(){return Object.values(this._config.content).map((t=>this._resolvePossibleFunction(t))).filter(Boolean)}hasContent(){return this.getContent().length>0}changeContent(t){return this._checkContent(t),this._config.content={...this._config.content,...t},this}toHtml(){const t=document.createElement("div");t.innerHTML=this._maybeSanitize(this._config.template);for(const[e,i]of Object.entries(this._config.content))this._setContent(t,i,e);const e=t.children[0],i=this._resolvePossibleFunction(this._config.extraClass);return i&&e.classList.add(...i.split(" ")),e}_typeCheckConfig(t){super._typeCheckConfig(t),this._checkContent(t.content)}_checkContent(t){for(const[e,i]of Object.entries(t))super._typeCheckConfig({selector:e,entry:i},Yi)}_setContent(t,e,i){const n=z.findOne(i,t);n&&((e=this._resolvePossibleFunction(e))?o(e)?this._putElementInTemplate(r(e),n):this._config.html?n.innerHTML=this._maybeSanitize(e):n.textContent=e:n.remove())}_maybeSanitize(t){return this._config.sanitize?function(t,e,i){if(!t.length)return t;if(i&&"function"==typeof i)return i(t);const n=(new window.DOMParser).parseFromString(t,"text/html"),s=[].concat(...n.body.querySelectorAll("*"));for(const t of s){const i=t.nodeName.toLowerCase();if(!Object.keys(e).includes(i)){t.remove();continue}const n=[].concat(...t.attributes),s=[].concat(e["*"]||[],e[i]||[]);for(const e of n)Ki(e,s)||t.removeAttribute(e.nodeName)}return n.body.innerHTML}(t,this._config.allowList,this._config.sanitizeFn):t}_resolvePossibleFunction(t){return g(t,[this])}_putElementInTemplate(t,e){if(this._config.html)return e.innerHTML="",void e.append(t);e.textContent=t.textContent}}const Gi=new Set(["sanitize","allowList","sanitizeFn"]),Ji="fade",Zi="show",tn=".modal",en="hide.bs.modal",nn="hover",sn="focus",on={AUTO:"auto",TOP:"top",RIGHT:p()?"left":"right",BOTTOM:"bottom",LEFT:p()?"right":"left"},rn={allowList:Ri,animation:!0,boundary:"clippingParents",container:!1,customClass:"",delay:0,fallbackPlacements:["top","right","bottom","left"],html:!1,offset:[0,6],placement:"top",popperConfig:null,sanitize:!0,sanitizeFn:null,selector:!1,template:'',title:"",trigger:"hover focus"},an={allowList:"object",animation:"boolean",boundary:"(string|element)",container:"(string|element|boolean)",customClass:"(string|function)",delay:"(number|object)",fallbackPlacements:"array",html:"boolean",offset:"(array|string|function)",placement:"(string|function)",popperConfig:"(null|object|function)",sanitize:"boolean",sanitizeFn:"(null|function)",selector:"(string|boolean)",template:"string",title:"(string|element|function)",trigger:"string"};class ln extends W{constructor(t,e){if(void 0===Ve)throw new TypeError("Bootstrap's tooltips require Popper (https://popper.js.org)");super(t,e),this._isEnabled=!0,this._timeout=0,this._isHovered=null,this._activeTrigger={},this._popper=null,this._templateFactory=null,this._newContent=null,this.tip=null,this._setListeners(),this._config.selector||this._fixTitle()}static get Default(){return rn}static get DefaultType(){return an}static get NAME(){return"tooltip"}enable(){this._isEnabled=!0}disable(){this._isEnabled=!1}toggleEnabled(){this._isEnabled=!this._isEnabled}toggle(){this._isEnabled&&(this._activeTrigger.click=!this._activeTrigger.click,this._isShown()?this._leave():this._enter())}dispose(){clearTimeout(this._timeout),P.off(this._element.closest(tn),en,this._hideModalHandler),this._element.getAttribute("data-bs-original-title")&&this._element.setAttribute("title",this._element.getAttribute("data-bs-original-title")),this._disposePopper(),super.dispose()}show(){if("none"===this._element.style.display)throw new Error("Please use show on visible elements");if(!this._isWithContent()||!this._isEnabled)return;const t=P.trigger(this._element,this.constructor.eventName("show")),e=(c(this._element)||this._element.ownerDocument.documentElement).contains(this._element);if(t.defaultPrevented||!e)return;this._disposePopper();const i=this._getTipElement();this._element.setAttribute("aria-describedby",i.getAttribute("id"));const{container:n}=this._config;if(this._element.ownerDocument.documentElement.contains(this.tip)||(n.append(i),P.trigger(this._element,this.constructor.eventName("inserted"))),this._popper=this._createPopper(i),i.classList.add(Zi),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.on(t,"mouseover",h);this._queueCallback((()=>{P.trigger(this._element,this.constructor.eventName("shown")),!1===this._isHovered&&this._leave(),this._isHovered=!1}),this.tip,this._isAnimated())}hide(){if(this._isShown()&&!P.trigger(this._element,this.constructor.eventName("hide")).defaultPrevented){if(this._getTipElement().classList.remove(Zi),"ontouchstart"in document.documentElement)for(const t of[].concat(...document.body.children))P.off(t,"mouseover",h);this._activeTrigger.click=!1,this._activeTrigger.focus=!1,this._activeTrigger.hover=!1,this._isHovered=null,this._queueCallback((()=>{this._isWithActiveTrigger()||(this._isHovered||this._disposePopper(),this._element.removeAttribute("aria-describedby"),P.trigger(this._element,this.constructor.eventName("hidden")))}),this.tip,this._isAnimated())}}update(){this._popper&&this._popper.update()}_isWithContent(){return Boolean(this._getTitle())}_getTipElement(){return this.tip||(this.tip=this._createTipElement(this._newContent||this._getContentForTemplate())),this.tip}_createTipElement(t){const e=this._getTemplateFactory(t).toHtml();if(!e)return null;e.classList.remove(Ji,Zi),e.classList.add(`bs-${this.constructor.NAME}-auto`);const i=(t=>{do{t+=Math.floor(1e6*Math.random())}while(document.getElementById(t));return t})(this.constructor.NAME).toString();return e.setAttribute("id",i),this._isAnimated()&&e.classList.add(Ji),e}setContent(t){this._newContent=t,this._isShown()&&(this._disposePopper(),this.show())}_getTemplateFactory(t){return this._templateFactory?this._templateFactory.changeContent(t):this._templateFactory=new Ui({...this._config,content:t,extraClass:this._resolvePossibleFunction(this._config.customClass)}),this._templateFactory}_getContentForTemplate(){return{".tooltip-inner":this._getTitle()}}_getTitle(){return this._resolvePossibleFunction(this._config.title)||this._element.getAttribute("data-bs-original-title")}_initializeOnDelegatedTarget(t){return this.constructor.getOrCreateInstance(t.delegateTarget,this._getDelegateConfig())}_isAnimated(){return this._config.animation||this.tip&&this.tip.classList.contains(Ji)}_isShown(){return this.tip&&this.tip.classList.contains(Zi)}_createPopper(t){const e=g(this._config.placement,[this,t,this._element]),i=on[e.toUpperCase()];return qe(this._element,t,this._getPopperConfig(i))}_getOffset(){const{offset:t}=this._config;return"string"==typeof t?t.split(",").map((t=>Number.parseInt(t,10))):"function"==typeof t?e=>t(e,this._element):t}_resolvePossibleFunction(t){return g(t,[this._element])}_getPopperConfig(t){const e={placement:t,modifiers:[{name:"flip",options:{fallbackPlacements:this._config.fallbackPlacements}},{name:"offset",options:{offset:this._getOffset()}},{name:"preventOverflow",options:{boundary:this._config.boundary}},{name:"arrow",options:{element:`.${this.constructor.NAME}-arrow`}},{name:"preSetPlacement",enabled:!0,phase:"beforeMain",fn:t=>{this._getTipElement().setAttribute("data-popper-placement",t.state.placement)}}]};return{...e,...g(this._config.popperConfig,[e])}}_setListeners(){const t=this._config.trigger.split(" ");for(const e of t)if("click"===e)P.on(this._element,this.constructor.eventName("click"),this._config.selector,(t=>{this._initializeOnDelegatedTarget(t).toggle()}));else if("manual"!==e){const t=e===nn?this.constructor.eventName("mouseenter"):this.constructor.eventName("focusin"),i=e===nn?this.constructor.eventName("mouseleave"):this.constructor.eventName("focusout");P.on(this._element,t,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusin"===t.type?sn:nn]=!0,e._enter()})),P.on(this._element,i,this._config.selector,(t=>{const e=this._initializeOnDelegatedTarget(t);e._activeTrigger["focusout"===t.type?sn:nn]=e._element.contains(t.relatedTarget),e._leave()}))}this._hideModalHandler=()=>{this._element&&this.hide()},P.on(this._element.closest(tn),en,this._hideModalHandler)}_fixTitle(){const t=this._element.getAttribute("title");t&&(this._element.getAttribute("aria-label")||this._element.textContent.trim()||this._element.setAttribute("aria-label",t),this._element.setAttribute("data-bs-original-title",t),this._element.removeAttribute("title"))}_enter(){this._isShown()||this._isHovered?this._isHovered=!0:(this._isHovered=!0,this._setTimeout((()=>{this._isHovered&&this.show()}),this._config.delay.show))}_leave(){this._isWithActiveTrigger()||(this._isHovered=!1,this._setTimeout((()=>{this._isHovered||this.hide()}),this._config.delay.hide))}_setTimeout(t,e){clearTimeout(this._timeout),this._timeout=setTimeout(t,e)}_isWithActiveTrigger(){return Object.values(this._activeTrigger).includes(!0)}_getConfig(t){const e=H.getDataAttributes(this._element);for(const t of Object.keys(e))Gi.has(t)&&delete e[t];return t={...e,..."object"==typeof t&&t?t:{}},t=this._mergeConfigObj(t),t=this._configAfterMerge(t),this._typeCheckConfig(t),t}_configAfterMerge(t){return t.container=!1===t.container?document.body:r(t.container),"number"==typeof t.delay&&(t.delay={show:t.delay,hide:t.delay}),"number"==typeof t.title&&(t.title=t.title.toString()),"number"==typeof t.content&&(t.content=t.content.toString()),t}_getDelegateConfig(){const t={};for(const[e,i]of Object.entries(this._config))this.constructor.Default[e]!==i&&(t[e]=i);return t.selector=!1,t.trigger="manual",t}_disposePopper(){this._popper&&(this._popper.destroy(),this._popper=null),this.tip&&(this.tip.remove(),this.tip=null)}static jQueryInterface(t){return this.each((function(){const e=ln.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(ln);const cn={...ln.Default,content:"",offset:[0,8],placement:"right",template:'',trigger:"click"},hn={...ln.DefaultType,content:"(null|string|element|function)"};class dn extends ln{static get Default(){return cn}static get DefaultType(){return hn}static get NAME(){return"popover"}_isWithContent(){return this._getTitle()||this._getContent()}_getContentForTemplate(){return{".popover-header":this._getTitle(),".popover-body":this._getContent()}}_getContent(){return this._resolvePossibleFunction(this._config.content)}static jQueryInterface(t){return this.each((function(){const e=dn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t]()}}))}}m(dn);const un="click.bs.scrollspy",fn="active",pn="[href]",mn={offset:null,rootMargin:"0px 0px -25%",smoothScroll:!1,target:null,threshold:[.1,.5,1]},gn={offset:"(number|null)",rootMargin:"string",smoothScroll:"boolean",target:"element",threshold:"array"};class _n extends W{constructor(t,e){super(t,e),this._targetLinks=new Map,this._observableSections=new Map,this._rootElement="visible"===getComputedStyle(this._element).overflowY?null:this._element,this._activeTarget=null,this._observer=null,this._previousScrollData={visibleEntryTop:0,parentScrollTop:0},this.refresh()}static get Default(){return mn}static get DefaultType(){return gn}static get NAME(){return"scrollspy"}refresh(){this._initializeTargetsAndObservables(),this._maybeEnableSmoothScroll(),this._observer?this._observer.disconnect():this._observer=this._getNewObserver();for(const t of this._observableSections.values())this._observer.observe(t)}dispose(){this._observer.disconnect(),super.dispose()}_configAfterMerge(t){return t.target=r(t.target)||document.body,t.rootMargin=t.offset?`${t.offset}px 0px -30%`:t.rootMargin,"string"==typeof t.threshold&&(t.threshold=t.threshold.split(",").map((t=>Number.parseFloat(t)))),t}_maybeEnableSmoothScroll(){this._config.smoothScroll&&(P.off(this._config.target,un),P.on(this._config.target,un,pn,(t=>{const e=this._observableSections.get(t.target.hash);if(e){t.preventDefault();const i=this._rootElement||window,n=e.offsetTop-this._element.offsetTop;if(i.scrollTo)return void i.scrollTo({top:n,behavior:"smooth"});i.scrollTop=n}})))}_getNewObserver(){const t={root:this._rootElement,threshold:this._config.threshold,rootMargin:this._config.rootMargin};return new IntersectionObserver((t=>this._observerCallback(t)),t)}_observerCallback(t){const e=t=>this._targetLinks.get(`#${t.target.id}`),i=t=>{this._previousScrollData.visibleEntryTop=t.target.offsetTop,this._process(e(t))},n=(this._rootElement||document.documentElement).scrollTop,s=n>=this._previousScrollData.parentScrollTop;this._previousScrollData.parentScrollTop=n;for(const o of t){if(!o.isIntersecting){this._activeTarget=null,this._clearActiveClass(e(o));continue}const t=o.target.offsetTop>=this._previousScrollData.visibleEntryTop;if(s&&t){if(i(o),!n)return}else s||t||i(o)}}_initializeTargetsAndObservables(){this._targetLinks=new Map,this._observableSections=new Map;const t=z.find(pn,this._config.target);for(const e of t){if(!e.hash||l(e))continue;const t=z.findOne(decodeURI(e.hash),this._element);a(t)&&(this._targetLinks.set(decodeURI(e.hash),e),this._observableSections.set(e.hash,t))}}_process(t){this._activeTarget!==t&&(this._clearActiveClass(this._config.target),this._activeTarget=t,t.classList.add(fn),this._activateParents(t),P.trigger(this._element,"activate.bs.scrollspy",{relatedTarget:t}))}_activateParents(t){if(t.classList.contains("dropdown-item"))z.findOne(".dropdown-toggle",t.closest(".dropdown")).classList.add(fn);else for(const e of z.parents(t,".nav, .list-group"))for(const t of z.prev(e,".nav-link, .nav-item > .nav-link, .list-group-item"))t.classList.add(fn)}_clearActiveClass(t){t.classList.remove(fn);const e=z.find("[href].active",t);for(const t of e)t.classList.remove(fn)}static jQueryInterface(t){return this.each((function(){const e=_n.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(window,"load.bs.scrollspy.data-api",(()=>{for(const t of z.find('[data-bs-spy="scroll"]'))_n.getOrCreateInstance(t)})),m(_n);const bn="ArrowLeft",vn="ArrowRight",yn="ArrowUp",wn="ArrowDown",An="active",En="fade",Tn="show",Cn='[data-bs-toggle="tab"], [data-bs-toggle="pill"], [data-bs-toggle="list"]',On=`.nav-link:not(.dropdown-toggle), .list-group-item:not(.dropdown-toggle), [role="tab"]:not(.dropdown-toggle), ${Cn}`;class xn extends W{constructor(t){super(t),this._parent=this._element.closest('.list-group, .nav, [role="tablist"]'),this._parent&&(this._setInitialAttributes(this._parent,this._getChildren()),P.on(this._element,"keydown.bs.tab",(t=>this._keydown(t))))}static get NAME(){return"tab"}show(){const t=this._element;if(this._elemIsActive(t))return;const e=this._getActiveElem(),i=e?P.trigger(e,"hide.bs.tab",{relatedTarget:t}):null;P.trigger(t,"show.bs.tab",{relatedTarget:e}).defaultPrevented||i&&i.defaultPrevented||(this._deactivate(e,t),this._activate(t,e))}_activate(t,e){t&&(t.classList.add(An),this._activate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.removeAttribute("tabindex"),t.setAttribute("aria-selected",!0),this._toggleDropDown(t,!0),P.trigger(t,"shown.bs.tab",{relatedTarget:e})):t.classList.add(Tn)}),t,t.classList.contains(En)))}_deactivate(t,e){t&&(t.classList.remove(An),t.blur(),this._deactivate(z.getElementFromSelector(t)),this._queueCallback((()=>{"tab"===t.getAttribute("role")?(t.setAttribute("aria-selected",!1),t.setAttribute("tabindex","-1"),this._toggleDropDown(t,!1),P.trigger(t,"hidden.bs.tab",{relatedTarget:e})):t.classList.remove(Tn)}),t,t.classList.contains(En)))}_keydown(t){if(![bn,vn,yn,wn].includes(t.key))return;t.stopPropagation(),t.preventDefault();const e=[vn,wn].includes(t.key),i=b(this._getChildren().filter((t=>!l(t))),t.target,e,!0);i&&(i.focus({preventScroll:!0}),xn.getOrCreateInstance(i).show())}_getChildren(){return z.find(On,this._parent)}_getActiveElem(){return this._getChildren().find((t=>this._elemIsActive(t)))||null}_setInitialAttributes(t,e){this._setAttributeIfNotExists(t,"role","tablist");for(const t of e)this._setInitialAttributesOnChild(t)}_setInitialAttributesOnChild(t){t=this._getInnerElement(t);const e=this._elemIsActive(t),i=this._getOuterElement(t);t.setAttribute("aria-selected",e),i!==t&&this._setAttributeIfNotExists(i,"role","presentation"),e||t.setAttribute("tabindex","-1"),this._setAttributeIfNotExists(t,"role","tab"),this._setInitialAttributesOnTargetPanel(t)}_setInitialAttributesOnTargetPanel(t){const e=z.getElementFromSelector(t);e&&(this._setAttributeIfNotExists(e,"role","tabpanel"),t.id&&this._setAttributeIfNotExists(e,"aria-labelledby",`${t.id}`))}_toggleDropDown(t,e){const i=this._getOuterElement(t);if(!i.classList.contains("dropdown"))return;const n=(t,n)=>{const s=z.findOne(t,i);s&&s.classList.toggle(n,e)};n(".dropdown-toggle",An),n(".dropdown-menu",Tn),i.setAttribute("aria-expanded",e)}_setAttributeIfNotExists(t,e,i){t.hasAttribute(e)||t.setAttribute(e,i)}_elemIsActive(t){return t.classList.contains(An)}_getInnerElement(t){return t.matches(On)?t:z.findOne(On,t)}_getOuterElement(t){return t.closest(".nav-item, .list-group-item")||t}static jQueryInterface(t){return this.each((function(){const e=xn.getOrCreateInstance(this);if("string"==typeof t){if(void 0===e[t]||t.startsWith("_")||"constructor"===t)throw new TypeError(`No method named "${t}"`);e[t]()}}))}}P.on(document,"click.bs.tab",Cn,(function(t){["A","AREA"].includes(this.tagName)&&t.preventDefault(),l(this)||xn.getOrCreateInstance(this).show()})),P.on(window,"load.bs.tab",(()=>{for(const t of z.find('.active[data-bs-toggle="tab"], .active[data-bs-toggle="pill"], .active[data-bs-toggle="list"]'))xn.getOrCreateInstance(t)})),m(xn);const kn="hide",Ln="show",Sn="showing",Dn={animation:"boolean",autohide:"boolean",delay:"number"},In={animation:!0,autohide:!0,delay:5e3};class Nn extends W{constructor(t,e){super(t,e),this._timeout=null,this._hasMouseInteraction=!1,this._hasKeyboardInteraction=!1,this._setListeners()}static get Default(){return In}static get DefaultType(){return Dn}static get NAME(){return"toast"}show(){P.trigger(this._element,"show.bs.toast").defaultPrevented||(this._clearTimeout(),this._config.animation&&this._element.classList.add("fade"),this._element.classList.remove(kn),d(this._element),this._element.classList.add(Ln,Sn),this._queueCallback((()=>{this._element.classList.remove(Sn),P.trigger(this._element,"shown.bs.toast"),this._maybeScheduleHide()}),this._element,this._config.animation))}hide(){this.isShown()&&(P.trigger(this._element,"hide.bs.toast").defaultPrevented||(this._element.classList.add(Sn),this._queueCallback((()=>{this._element.classList.add(kn),this._element.classList.remove(Sn,Ln),P.trigger(this._element,"hidden.bs.toast")}),this._element,this._config.animation)))}dispose(){this._clearTimeout(),this.isShown()&&this._element.classList.remove(Ln),super.dispose()}isShown(){return this._element.classList.contains(Ln)}_maybeScheduleHide(){this._config.autohide&&(this._hasMouseInteraction||this._hasKeyboardInteraction||(this._timeout=setTimeout((()=>{this.hide()}),this._config.delay)))}_onInteraction(t,e){switch(t.type){case"mouseover":case"mouseout":this._hasMouseInteraction=e;break;case"focusin":case"focusout":this._hasKeyboardInteraction=e}if(e)return void this._clearTimeout();const i=t.relatedTarget;this._element===i||this._element.contains(i)||this._maybeScheduleHide()}_setListeners(){P.on(this._element,"mouseover.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"mouseout.bs.toast",(t=>this._onInteraction(t,!1))),P.on(this._element,"focusin.bs.toast",(t=>this._onInteraction(t,!0))),P.on(this._element,"focusout.bs.toast",(t=>this._onInteraction(t,!1)))}_clearTimeout(){clearTimeout(this._timeout),this._timeout=null}static jQueryInterface(t){return this.each((function(){const e=Nn.getOrCreateInstance(this,t);if("string"==typeof t){if(void 0===e[t])throw new TypeError(`No method named "${t}"`);e[t](this)}}))}}return R(Nn),m(Nn),{Alert:q,Button:K,Carousel:rt,Collapse:ft,Dropdown:ci,Modal:Ni,Offcanvas:zi,Popover:dn,ScrollSpy:_n,Tab:xn,Toast:Nn,Tooltip:ln}})); +//# sourceMappingURL=bootstrap.bundle.min.js.map \ No newline at end of file diff --git a/WebControl/js/script.js b/WebControl/js/script.js index f553723..d981f59 100644 --- a/WebControl/js/script.js +++ b/WebControl/js/script.js @@ -1,119 +1,26 @@ - $(function(){ - var isTouchDevice = "ontouchstart" in document.documentElement ? true : false; - var BUTTON_DOWN = isTouchDevice ? "touchstart" : "mousedown"; - var BUTTON_UP = isTouchDevice ? "touchend" : "mouseup"; - - $("input[type='checkbox']").change(function() { - var id = this.id; - if (this.checked) { - $.post("/cmd", id, function(data, status){}); - } else { - $.post("/cmd", "stop", function(data, status){}); - } - }); - - $('input[type="range"]').change(function() { - var speed = this.value; - $.post('/cmd', {speed: speed}); - }); - }); - // Test - $(function() { - $('#servo').change(function() { - var isChecked = $(this).is(':checked'); - var action = isChecked ? 'start' : 'stop'; - $.post('/servo_motor', { action: action }); - }); - }); - $(function() { - $('#motor').change(function() { - var isChecked = $(this).is(':checked'); - var action = isChecked ? 'start' : 'stop'; - $.post('/motor_speed_move', { action: action }); - }); - }); - $(function() { - $('#obstacle').change(function() { - var isChecked = $(this).is(':checked'); - var action = isChecked ? 'start' : 'stop'; - $.post('/infrared_obstacle_module', { action: action }); - }); - }); - $(function () { - $("#lidar").change(function () { - var isChecked = $(this).is(":checked"); - var action = isChecked ? "start" : "stop"; - $.post("/lidar_module", { action: action }); - }); - }); - $(function () { - $("#rfidrw").change(function () { - var isChecked = $(this).is(":checked"); - var action = isChecked ? "start" : "stop"; - $.post("/rfid_read_write_module", { action: action }); - }); - }); - // Fonctionnalité - $(function () { - $("#ITO").change(function () { - var isChecked = $(this).is(":checked"); - var action = isChecked ? "start" : "stop"; - $.post("/infrared_tracking_objects", { action: action }); - }); - }); - $(function () { - $("#IOA").change(function () { - var isChecked = $(this).is(":checked"); - var action = isChecked ? "start" : "stop"; - $.post("/infrared_obstacle_avoidance", { - action: action, - }); - }); - }); + // Fonction pour mettre à jour l'angle de rotation de l'aiguille en fonction de la vitesse function updateRotation(speed) { const minSpeed = 0; // Vitesse minimale en km/h const maxSpeed = 120; // Vitesse maximale en km/h - const maxAngle = 138; // Angle maximal de l'aiguille (correspondant à la vitesse maximale) - - // Limiter la vitesse minimale - speed = Math.max(minSpeed, speed); - // Limiter la vitesse maximale - speed = Math.min(maxSpeed, speed); - - // Calcul de l'angle en fonction de la vitesse - const angle = (speed / maxSpeed) * maxAngle; - - // Mise à jour de l'aiguille avec le nouvel angle - updatePointerRotation(angle); -} - -// Fonction pour mettre à jour l'aiguille avec un nouvel angle -function updatePointerRotation(angle) { const minAngle = -130; // Angle minimal de l'aiguille - const maxAngle = 138; // Angle maximal de l'aiguille - - // Limiter l'angle minimum + const maxAngle = 138; // Angle maximal de l'aiguille (correspondant à la vitesse maximale) + // Limiter la vitesse et angle minimale + speed = Math.max(minSpeed, speed); + // Limiter la vitesse et angle maximale + speed = Math.min(maxSpeed, speed); + // Calcul de l'angle en fonction de la vitesse + var angle = (speed / maxSpeed) * maxAngle; angle = Math.max(minAngle, angle); - // Limiter l'angle maximum angle = Math.min(maxAngle, angle); - + // Mise à jour de l'aiguille avec le nouvel angle // Calculer la rotation en fonction de l'angle et de la direction let rotation = (angle + 112) * 1.923; // Convertir l'angle en rotation (360/242) - // Mise à jour de l'aiguille const pointer = document.getElementById("pointer"); pointer.style.transform = `translateX(-50%) rotate(${rotation}deg)`; } -// Fonction pour mettre à jour le compteur avec la nouvelle valeur de vitesse -function updateCounter(speed) { - const counter = document.getElementById("counter"); - // Ajouter des zéros devant la vitesse si elle est inférieure à 100 - const formattedSpeed = ("000" + speed).slice(-3); - counter.textContent = formattedSpeed; -} - $(function () { var isTouchDevice = "ontouchstart" in document.documentElement ? true : false; var BUTTON_DOWN = isTouchDevice ? "touchstart" : "mousedown"; @@ -131,12 +38,40 @@ $(function () { $("input").change(function () { var speed = this.value; + const counter = document.getElementById("counter"); $("#speed-display").text(speed); // Met à jour l'élément HTML avec l'id 'speed-display' avec la nouvelle valeur updateRotation(speed); // Met à jour l'aiguille avec la nouvelle vitesse - updateCounter(speed); // Met à jour le compteur avec la nouvelle vitesse - $.post("/cmd", { speed: speed }); // Envoie la nouvelle valeur de vitesse au serveur + // Ajouter des zéros devant la vitesse si elle est inférieure à 100 + const formattedSpeed = ("000" + speed).slice(-3); + counter.textContent = formattedSpeed; $.post("/cmd", { speed: speed }); // Envoie la nouvelle valeur de vitesse au serveur }); // Positionner l'aiguille à la valeur 50 lors de l'initialisation - updateRotation(50); + updateRotation(30); }); + +$(function () { + var isTouchDevice = "ontouchstart" in document.documentElement ? true : false; + var BUTTON_DOWN = isTouchDevice ? "touchstart" : "mousedown"; + var BUTTON_UP = isTouchDevice ? "touchend" : "mouseup"; + + $("input[type='checkbox']").change(function () { + var id = this.id; + if (this.checked) { + $.post("/cmd", id, function (data, status) {}); + } else { + $.post("/cmd", "stop", function (data, status) {}); + } + }); + + $('input[type="range"]').change(function () { + var speed = this.value; + $.post("/cmd", { speed: speed }); + }); +}); + +function confirmReboot() { + if (confirm("Êtes-vous sûr de vouloir redémarrer le Raspberry Pi ?")) { + document.getElementById("rebootForm").submit(); + } +} \ No newline at end of file diff --git a/WebControl/js/test_status.js b/WebControl/js/test_status.js new file mode 100644 index 0000000..f53d06e --- /dev/null +++ b/WebControl/js/test_status.js @@ -0,0 +1,21 @@ +$(document).ready(function () { + function updateTestStatus() { + $.getJSON("/test_status", function (data) { + let tableBody = $("#testStatusTable"); + tableBody.empty(); // Vider le tableau avant d'ajouter les nouvelles lignes + + // Parcourir les résultats des tests et ajouter une ligne pour chaque test + $.each(data, function (test, result) { + let status = result ? "Réussi" : "Échoué"; + let row = `${test}${status}`; + tableBody.append(row); + }); + }); + } + + // Mettre à jour l'état des tests toutes les 5 secondes + setInterval(updateTestStatus, 5000); + + // Appel initial pour charger l'état des tests immédiatement + updateTestStatus(); +}); diff --git a/WebControl/logs/log.txt b/WebControl/logs/log.txt index 1c315b1..8f4c9c0 100644 --- a/WebControl/logs/log.txt +++ b/WebControl/logs/log.txt @@ -1,20 +1,2442 @@ -Bottle v0.12.25 server starting up (using WSGIRefServer(ssl_context=))... -Listening on http://192.168.74.194:8000/ +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:16:50] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:16:51] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:16:51] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:16:51] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:17:21] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:17:21] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:17:24] "POST /restartMotion HTTP/1.1" 200 202 +192.168.253.237 - - [02/Sep/2024 13:17:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:18:32] "POST /restartMotion HTTP/1.1" 200 202 +192.168.253.237 - - [02/Sep/2024 13:18:36] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:18:36] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:28:01] "POST /restartPi HTTP/1.1" 200 108 +192.168.253.237 - - [02/Sep/2024 13:28:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:31:57] "POST /restartPi HTTP/1.1" 200 108 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:33:32] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:33:33] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:33:33] "GET /js/script.js HTTP/1.1" 200 3196 +192.168.253.237 - - [02/Sep/2024 13:33:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:33:48] "POST /restartMotion HTTP/1.1" 200 202 +192.168.253.237 - - [02/Sep/2024 13:33:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:33:52] "POST /restartMotion HTTP/1.1" 200 202 +192.168.253.237 - - [02/Sep/2024 13:38:43] "POST /restartMotion HTTP/1.1" 200 202 +192.168.253.237 - - [02/Sep/2024 13:38:46] "GET /restartMotion HTTP/1.1" 404 735 +192.168.253.237 - - [02/Sep/2024 13:38:54] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:38:54] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:38:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:38:58] "POST /restartPi HTTP/1.1" 200 108 +192.168.253.237 - - [02/Sep/2024 13:38:58] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:39:54] "POST /restartPi HTTP/1.1" 200 136 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:42:14] "POST / HTTP/1.1" 405 739 +192.168.253.237 - - [02/Sep/2024 13:42:17] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:42:17] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:42:17] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:42:48] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:42:48] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:42:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:42:56] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:42:57] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:00] "POST /restartMotion HTTP/1.1" 200 230 +192.168.253.237 - - [02/Sep/2024 13:43:00] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:43:57] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:43:57] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 13:43:57] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:44:58] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:44:58] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:45:02] "GET /main HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:45:20] "GET /main HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:45:23] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:45:23] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 13:45:23] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 13:45:23] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 13:45:24] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 13:45:24] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 13:45:24] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 13:45:24] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 13:46:58] "GET / HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:46:58] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:47:03] "POST /restartPi HTTP/1.1" 200 136 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:47:31] "POST / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:47:35] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:47:39] "GET /main HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:47:39] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:48:38] "GET /main HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:48:38] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:48:42] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 13:48:43] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:48:45] "POST /restartMotion HTTP/1.1" 200 230 +192.168.253.237 - - [02/Sep/2024 13:50:12] "POST / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:50:18] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:50:21] "GET /main HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:50:21] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:50:37] "POST /restartPi HTTP/1.1" 200 136 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 13:52:51] "POST / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 13:52:56] "GET /main HTTP/1.1" 200 10788 +192.168.253.237 - - [02/Sep/2024 13:52:56] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:56:06] "GET /main HTTP/1.1" 200 11817 +192.168.253.237 - - [02/Sep/2024 13:56:06] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:56:06] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:56:11] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:56:15] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:15] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:16] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:16] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:25] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:56:30] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:30] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:31] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:31] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:32] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:32] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:32] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:33] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:33] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:56:34] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:50] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:56:50] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:02] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:02] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:05] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:06] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:08] "GET /main HTTP/1.1" 200 11817 +192.168.253.237 - - [02/Sep/2024 13:57:08] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:09] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:10] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:10] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:11] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:11] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:12] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:12] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:13] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:13] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:57:14] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:57:30] "GET /main HTTP/1.1" 200 11817 +192.168.253.237 - - [02/Sep/2024 13:57:30] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 13:57:30] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:31] "GET /tests HTTP/1.1" 200 590 +192.168.253.237 - - [02/Sep/2024 13:57:31] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:31] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:57:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:02] "GET /main HTTP/1.1" 200 11823 +192.168.253.237 - - [02/Sep/2024 13:58:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:03] "GET /validate HTTP/1.1" 200 681 +192.168.253.237 - - [02/Sep/2024 13:58:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:04] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:08] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:08] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:09] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:09] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:09] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:10] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:11] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:11] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:12] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:12] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:34] "GET /main HTTP/1.1" 200 11768 +192.168.253.237 - - [02/Sep/2024 13:58:38] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 13:58:39] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:58:40] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:41] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 13:58:41] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 13:59:02] "GET /main HTTP/1.1" 200 11945 +192.168.253.237 - - [02/Sep/2024 13:59:02] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 14:01:30] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:01:30] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 14:01:34] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 14:01:36] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:01:36] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:01:37] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:01:37] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:01:40] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 14:01:41] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 14:01:42] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:01:43] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:01:43] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:01:44] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:01:44] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:01:45] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:02:12] "GET /validate HTTP/1.1" 200 681 +192.168.253.237 - - [02/Sep/2024 14:02:18] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:02:19] "GET /tests HTTP/1.1" 200 590 +192.168.253.237 - - [02/Sep/2024 14:02:26] "GET /validate HTTP/1.1" 200 681 +[0:motion] [NTC] [ALL] conf_load: Processing thread 0 - config file /etc/motion/motion.conf +[0:motion] [NTC] [ALL] motion_startup: Logging to file (/var/log/motion/motion.log) +192.168.253.237 - - [02/Sep/2024 14:02:54] "POST /restartMotion HTTP/1.1" 200 107 +192.168.253.237 - - [02/Sep/2024 14:03:00] "POST /main HTTP/1.1" 405 743 +192.168.253.237 - - [02/Sep/2024 14:03:08] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:03:15] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 14:03:18] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:03:29] "GET /main HTTP/1.1" 200 12046 +192.168.253.237 - - [02/Sep/2024 14:04:06] "GET /main HTTP/1.1" 200 12155 +192.168.253.237 - - [02/Sep/2024 14:04:06] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 14:04:40] "GET /main HTTP/1.1" 200 12155 +192.168.253.237 - - [02/Sep/2024 14:05:22] "GET /main HTTP/1.1" 200 12171 +192.168.253.237 - - [02/Sep/2024 14:05:40] "GET /main HTTP/1.1" 200 12171 +192.168.253.237 - - [02/Sep/2024 14:05:49] "GET /main HTTP/1.1" 200 12171 +192.168.253.237 - - [02/Sep/2024 14:06:05] "GET /validate HTTP/1.1" 200 681 +192.168.253.237 - - [02/Sep/2024 14:08:36] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:08:41] "GET /validate HTTP/1.1" 200 679 +192.168.253.237 - - [02/Sep/2024 14:09:16] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:09:31] "GET /validate HTTP/1.1" 200 680 +192.168.253.237 - - [02/Sep/2024 14:09:50] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:10:11] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:10:52] "GET /validate HTTP/1.1" 200 679 +192.168.253.237 - - [02/Sep/2024 14:14:29] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:14:48] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:15:09] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:15:42] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:16:41] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:17:09] "POST /validate HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 14:53:19] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 14:55:17] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 14:55:21] "GET /main HTTP/1.1" 200 12171 +192.168.253.237 - - [02/Sep/2024 14:55:21] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 14:55:21] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 14:55:21] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 14:55:22] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 14:55:22] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 14:55:22] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 14:55:23] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 14:55:37] "GET /tests HTTP/1.1" 200 590 +192.168.253.237 - - [02/Sep/2024 14:55:41] "GET /validate HTTP/1.1" 200 679 +192.168.253.237 - - [02/Sep/2024 14:55:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 14:55:55] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:55:56] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:55:57] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 14:55:57] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 14:55:57] "GET /main HTTP/1.1" 200 12171 +192.168.253.237 - - [02/Sep/2024 14:55:57] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 14:57:58] "GET /main HTTP/1.1" 200 11979 +192.168.253.237 - - [02/Sep/2024 14:57:58] "GET /main HTTP/1.1" 200 11979 +192.168.253.237 - - [02/Sep/2024 14:57:59] "GET /tests HTTP/1.1" 200 1785 +192.168.253.237 - - [02/Sep/2024 14:58:00] "GET /validate HTTP/1.1" 200 1874 +192.168.253.237 - - [02/Sep/2024 14:58:04] "GET /tests HTTP/1.1" 200 1785 +192.168.253.237 - - [02/Sep/2024 14:58:05] "GET /main HTTP/1.1" 200 11979 +192.168.253.237 - - [02/Sep/2024 14:58:07] "GET /tests HTTP/1.1" 200 1785 +192.168.253.237 - - [02/Sep/2024 14:58:08] "GET /main HTTP/1.1" 200 11979 +192.168.253.237 - - [02/Sep/2024 14:58:44] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 14:58:44] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 14:58:45] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 14:58:45] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 14:58:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 14:58:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /main HTTP/1.1" 200 11959 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 15:43:59] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 15:44:00] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 15:45:24] "GET / HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 15:45:32] "GET /main HTTP/1.1" 200 11959 +192.168.253.237 - - [02/Sep/2024 15:48:55] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 15:48:55] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 15:49:00] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 15:49:01] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 15:49:05] "GET /main HTTP/1.1" 200 11964 +192.168.253.237 - - [02/Sep/2024 15:49:30] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:30] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:31] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:31] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:32] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:32] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:33] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:33] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:33] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:33] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:34] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:34] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:35] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:35] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:36] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:36] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 15:49:38] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 15:49:39] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 15:49:41] "GET /main HTTP/1.1" 200 11964 +192.168.253.237 - - [02/Sep/2024 15:49:43] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 15:49:44] "POST /cmd HTTP/1.1" 200 40 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 15:54:36] "GET /validate HTTP/1.1" 200 1876 +192.168.253.237 - - [02/Sep/2024 15:55:14] "GET /main HTTP/1.1" 404 726 +192.168.253.237 - - [02/Sep/2024 15:58:17] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 15:58:18] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 15:58:18] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 15:58:19] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 15:58:20] "GET /tests HTTP/1.1" 200 1777 +192.168.253.237 - - [02/Sep/2024 15:58:21] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 15:58:25] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 15:58:31] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 15:59:20] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 15:59:22] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 15:59:26] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:00:03] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:00:06] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:08:07] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:08:07] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 16:08:12] "GET /tests HTTP/1.1" 200 1777 +192.168.253.237 - - [02/Sep/2024 16:08:14] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:08:16] "GET /tests HTTP/1.1" 200 1777 +192.168.253.237 - - [02/Sep/2024 16:08:18] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:08:19] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:10:44] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 16:10:45] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 16:10:47] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:10:48] "GET /tests HTTP/1.1" 200 1777 +192.168.253.237 - - [02/Sep/2024 16:10:49] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:11:42] "GET /tests HTTP/1.1" 200 1783 +192.168.253.237 - - [02/Sep/2024 16:11:45] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:11:53] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:12:01] "GET /tests HTTP/1.1" 200 1783 +192.168.253.237 - - [02/Sep/2024 16:12:03] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:12:05] "GET /tests HTTP/1.1" 200 1783 +192.168.253.237 - - [02/Sep/2024 16:12:06] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:12:54] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:12:55] "GET /tests HTTP/1.1" 200 1769 +192.168.253.237 - - [02/Sep/2024 16:12:56] "GET /tests HTTP/1.1" 200 1769 +192.168.253.237 - - [02/Sep/2024 16:12:57] "GET /tests HTTP/1.1" 200 1769 +192.168.253.237 - - [02/Sep/2024 16:13:20] "GET /validate HTTP/1.1" 200 1868 +192.168.253.237 - - [02/Sep/2024 16:13:57] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:16:46] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:16:47] "GET /tests HTTP/1.1" 200 1638 +192.168.253.237 - - [02/Sep/2024 16:16:49] "GET /validate HTTP/1.1" 200 1810 +192.168.253.237 - - [02/Sep/2024 16:16:52] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:16:53] "GET /tests HTTP/1.1" 200 1638 +192.168.253.237 - - [02/Sep/2024 16:16:55] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:16:56] "GET /tests HTTP/1.1" 200 1638 +192.168.253.237 - - [02/Sep/2024 16:16:57] "GET /validate HTTP/1.1" 200 1810 +192.168.253.237 - - [02/Sep/2024 16:17:37] "GET /tests HTTP/1.1" 200 1638 +192.168.253.237 - - [02/Sep/2024 16:17:46] "GET /validate HTTP/1.1" 200 1810 +192.168.253.237 - - [02/Sep/2024 16:17:47] "GET /tests HTTP/1.1" 200 1638 +192.168.253.237 - - [02/Sep/2024 16:17:57] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:18:22] "GET / HTTP/1.1" 200 11956 +192.168.253.237 - - [02/Sep/2024 16:18:23] "GET /validate HTTP/1.1" 200 1847 +192.168.253.237 - - [02/Sep/2024 16:21:30] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:21:31] "GET /access HTTP/1.1" 404 728 +192.168.253.237 - - [02/Sep/2024 16:21:35] "GET /access HTTP/1.1" 404 728 +192.168.253.237 - - [02/Sep/2024 16:21:43] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:21:51] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:23:32] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:23:52] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:23:54] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:24:57] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:25:05] "GET / HTTP/1.1" 200 11950 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 16:27:54] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:27:54] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 16:27:55] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:27:58] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:28:01] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:28:05] "GET /access HTTP/1.1" 200 2304 +192.168.253.237 - - [02/Sep/2024 16:28:14] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:03] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:29:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:07] "GET /access HTTP/1.1" 200 2304 +192.168.253.237 - - [02/Sep/2024 16:29:07] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:07] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:14] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:29:14] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:29:15] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:03] "GET /access HTTP/1.1" 200 2304 +192.168.253.237 - - [02/Sep/2024 16:30:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:05] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:30:05] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:05] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:08] "GET /access HTTP/1.1" 200 2304 +192.168.253.237 - - [02/Sep/2024 16:30:08] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:09] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:10] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:30:10] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:10] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:23] "GET /access HTTP/1.1" 200 2304 +192.168.253.237 - - [02/Sep/2024 16:30:23] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:23] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:42] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:30:43] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:54] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:30:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:30:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:31:48] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:31:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:31:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:31:55] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:31:55] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:31:55] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:01] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:32:01] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:01] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:23] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:32:23] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:23] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:24] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:32:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:25] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:32:25] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:25] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:26] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:32:26] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:32:26] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:41] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:33:41] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:45] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:33:47] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:33:47] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:50] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:33:50] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:50] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:33:53] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:33:53] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:34:20] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:34:20] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:34:20] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:34:53] "GET / HTTP/1.1" 200 11950 +192.168.253.237 - - [02/Sep/2024 16:34:53] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:34:53] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:36:45] "GET / HTTP/1.1" 200 13659 +192.168.253.237 - - [02/Sep/2024 16:36:45] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 16:42:33] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 16:42:33] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 16:42:36] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:42:36] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1459 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 16:42:42] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 16:42:42] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 16:42:54] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:42:54] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 16:52:23] "GET / HTTP/1.1" 200 13659 +192.168.253.237 - - [02/Sep/2024 16:52:24] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 16:52:33] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:52:45] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:45] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:46] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:47] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:47] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:48] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:48] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:49] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:49] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:50] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:50] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:51] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:52:51] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:24] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:53:26] "POST /cmd HTTP/1.1" 200 46 +192.168.253.237 - - [02/Sep/2024 16:53:27] "POST /cmd HTTP/1.1" 200 40 +[0:motion] [NTC] [ALL] conf_load: Processing thread 0 - config file /etc/motion/motion.conf +[0:motion] [NTC] [ALL] motion_startup: Logging to file (/var/log/motion/motion.log) +192.168.253.237 - - [02/Sep/2024 16:53:28] "POST /restartMotion HTTP/1.1" 200 107 +192.168.253.237 - - [02/Sep/2024 16:53:31] "POST /main HTTP/1.1" 405 743 +192.168.253.237 - - [02/Sep/2024 16:53:34] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:53:57] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:57] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:58] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:58] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:58] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:58] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:59] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:53:59] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:00] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:00] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:01] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:01] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:02] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:02] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:02] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:02] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:03] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:03] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:03] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:03] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:04] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:04] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:04] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:04] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:05] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:05] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:06] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:07] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:07] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:07] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:07] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 16:54:17] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:54:18] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 16:54:18] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:54:43] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:55:54] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:55:56] "POST /cmd HTTP/1.1" 200 46 +[0:motion] [NTC] [ALL] conf_load: Processing thread 0 - config file /etc/motion/motion.conf +[0:motion] [NTC] [ALL] motion_startup: Logging to file (/var/log/motion/motion.log) +192.168.253.237 - - [02/Sep/2024 16:55:57] "POST /restartMotion HTTP/1.1" 200 107 +192.168.253.237 - - [02/Sep/2024 16:55:58] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:56:00] "POST /main HTTP/1.1" 405 743 +192.168.253.237 - - [02/Sep/2024 16:56:03] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:56:11] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:56:39] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:56:55] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 16:56:56] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:56:57] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:56:57] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 16:56:57] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 16:56:58] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:56:59] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 16:56:59] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 16:57:28] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:57:30] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:57:30] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:57:32] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:57:32] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:57:33] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:57:34] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 16:57:35] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:57:36] "GET / HTTP/1.1" 200 13342 +192.168.253.237 - - [02/Sep/2024 16:57:40] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:57:42] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:59:01] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:59:01] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 16:59:05] "GET / HTTP/1.1" 200 13646 +192.168.253.237 - - [02/Sep/2024 16:59:11] "GET /policy.php HTTP/1.1" 404 732 +192.168.253.237 - - [02/Sep/2024 16:59:33] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:59:40] "GET /access HTTP/1.1" 200 2332 +192.168.253.237 - - [02/Sep/2024 16:59:59] "GET /access HTTP/1.1" 200 2514 +192.168.253.237 - - [02/Sep/2024 17:00:08] "GET / HTTP/1.1" 200 13646 +192.168.253.237 - - [02/Sep/2024 17:00:10] "GET /access HTTP/1.1" 200 2514 +192.168.253.237 - - [02/Sep/2024 17:00:18] "GET /tests HTTP/1.1" 200 1632 +192.168.253.237 - - [02/Sep/2024 17:02:19] "GET /tests HTTP/1.1" 200 1906 +192.168.253.237 - - [02/Sep/2024 17:02:20] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 17:02:24] "GET /tests HTTP/1.1" 200 1906 +192.168.253.237 - - [02/Sep/2024 17:02:27] "GET /access HTTP/1.1" 200 2422 +192.168.253.237 - - [02/Sep/2024 17:02:27] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:02:28] "GET / HTTP/1.1" 200 13469 +192.168.253.237 - - [02/Sep/2024 17:02:31] "GET /access HTTP/1.1" 200 2422 +192.168.253.237 - - [02/Sep/2024 17:10:11] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:10:11] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:10:11] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:10:13] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:10:15] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:10:16] "GET /tests HTTP/1.1" 200 2224 +192.168.253.237 - - [02/Sep/2024 17:10:23] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:10:26] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:12:18] "GET /tests HTTP/1.1" 200 2224 +192.168.253.237 - - [02/Sep/2024 17:12:18] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:12:18] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:12:19] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:12:21] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:12:38] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:12:38] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:13:50] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 17:13:51] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:13:51] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 17:13:52] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:13:52] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 17:13:53] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:13:53] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 17:13:54] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:14:03] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:14:03] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:14:55] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:15:21] "GET /tests HTTP/1.1" 200 2224 +192.168.253.237 - - [02/Sep/2024 17:15:21] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:15:59] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:16:05] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:16:06] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:16:07] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:16:08] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:16:15] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:16:17] "GET /access HTTP/1.1" 200 2765 +192.168.253.237 - - [02/Sep/2024 17:18:13] "GET /access HTTP/1.1" 200 2948 +192.168.253.237 - - [02/Sep/2024 17:18:13] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:18:43] "GET /access HTTP/1.1" 200 2851 +192.168.253.237 - - [02/Sep/2024 17:19:03] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:19:05] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:19:07] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:19:09] "GET / HTTP/1.1" 200 13505 +192.168.253.237 - - [02/Sep/2024 17:19:26] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:19:30] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:19:48] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:19:52] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:19:59] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:19:59] "GET /css/styles.css HTTP/1.1" 200 1948 +192.168.253.237 - - [02/Sep/2024 17:19:59] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 17:20:00] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 17:20:06] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:20:15] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:20:16] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:20:19] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:20:20] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:20:35] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:20:36] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:20:36] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:20:37] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:22:16] "GET /access HTTP/1.1" 200 2785 +192.168.253.237 - - [02/Sep/2024 17:22:16] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:22:16] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:22:35] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 17:23:05] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:23:07] "GET / HTTP/1.1" 200 13509 +192.168.253.237 - - [02/Sep/2024 17:23:07] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:23:17] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 17:23:24] "GET /access HTTP/1.1" 200 2693 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 17:21:28] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:21:28] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:21:28] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:21:31] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:21:31] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:21:31] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:21:37] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:21:37] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:21:37] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:29:50] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:29:50] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:29:50] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:31:13] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 17:31:16] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 17:31:18] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:32:17] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:32:17] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:32:17] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:35:41] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 17:35:41] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:35:41] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:36:12] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:36:13] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:36:15] "GET / HTTP/1.1" 200 11994 +192.168.253.237 - - [02/Sep/2024 17:37:00] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 17:37:01] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:37:03] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:37:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:37:39] "GET / HTTP/1.1" 200 12034 +192.168.253.237 - - [02/Sep/2024 17:37:39] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:37:39] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:37:50] "GET / HTTP/1.1" 200 12042 +192.168.253.237 - - [02/Sep/2024 17:37:51] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:37:51] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:38:14] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:14] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:15] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:15] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:15] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:15] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:16] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:16] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:17] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:17] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:17] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:17] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:18] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:18] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 17:38:55] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 17:38:55] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 17:39:35] "GET / HTTP/1.1" 200 12253 +192.168.253.237 - - [02/Sep/2024 17:39:35] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:39:35] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:41:21] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:41:21] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:42:29] "GET / HTTP/1.1" 200 12574 +192.168.253.237 - - [02/Sep/2024 17:42:29] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:42:29] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:42:29] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:42:29] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:42:45] "POST /cmd HTTP/1.1" 200 48 +192.168.253.237 - - [02/Sep/2024 17:42:45] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:42:48] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:42:48] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:42:48] "POST /cmd HTTP/1.1" 200 48 +192.168.253.237 - - [02/Sep/2024 17:42:48] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:43:04] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:43:05] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:43:05] "POST /cmd HTTP/1.1" 200 48 +192.168.253.237 - - [02/Sep/2024 17:43:05] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:43:06] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:43:06] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:44:16] "GET / HTTP/1.1" 200 11999 +192.168.253.237 - - [02/Sep/2024 17:44:16] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:44:16] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:44:16] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1178 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 17:44:34] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 17:44:34] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:44:38] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:44:38] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 17:47:09] "GET / HTTP/1.1" 200 12006 +192.168.253.237 - - [02/Sep/2024 17:47:09] "GET /css/styles.css HTTP/1.1" 200 1088 +192.168.253.237 - - [02/Sep/2024 17:47:09] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:47:09] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:47:37] "GET / HTTP/1.1" 200 12416 +192.168.253.237 - - [02/Sep/2024 17:47:37] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:47:37] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:47:37] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:47:40] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:47:40] "POST /cmd HTTP/1.1" 200 55 +192.168.253.237 - - [02/Sep/2024 17:47:43] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 17:47:43] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:49:08] "GET / HTTP/1.1" 200 12449 +192.168.253.237 - - [02/Sep/2024 17:49:08] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:49:08] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:49:08] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 17:49:09] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:49:10] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1229 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 17:49:10] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 17:49:16] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 17:49:17] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 17:58:54] "GET / HTTP/1.1" 200 13815 +192.168.253.237 - - [02/Sep/2024 17:58:55] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:58:55] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 17:58:55] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 17:58:55] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:01:05] "GET / HTTP/1.1" 200 13655 +192.168.253.237 - - [02/Sep/2024 18:01:05] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:01:05] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:01:05] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:01:33] "GET / HTTP/1.1" 200 12838 +192.168.253.237 - - [02/Sep/2024 18:01:33] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:01:33] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:03:53] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:03:53] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:03:53] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:03:53] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:05:27] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:05:27] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:05:27] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:05:27] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:06:24] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:06:24] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 18:06:24] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 18:06:25] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:07:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:07:22] "GET / HTTP/1.1" 200 13115 +192.168.253.237 - - [02/Sep/2024 18:07:22] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:07:22] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:07:22] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET / HTTP/1.1" 200 13115 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 18:07:35] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:07:36] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 18:07:36] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 18:07:36] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 18:07:36] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:08:08] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:08:08] "GET /css/styles.css HTTP/1.1" 200 1171 +192.168.253.237 - - [02/Sep/2024 18:08:08] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:08:08] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:08:26] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:08:26] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:08:26] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:08:26] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:08:35] "GET / HTTP/1.1" 200 13095 +192.168.253.237 - - [02/Sep/2024 18:08:35] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:08:35] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:08:35] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1281 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:10:39] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:10:39] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:10:40] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:10:41] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 18:11:27] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1425 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:11:27] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:11:29] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:11:29] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:29] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1431 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:11:29] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:11:30] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:11:30] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:30] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1435 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:11:30] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:11:32] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:11:32] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1439 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:11:43] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:11:43] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:43] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:44] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1444 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:11:46] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:11:46] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:46] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:11:47] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 18:13:15] "GET / HTTP/1.1" 200 13123 +192.168.253.237 - - [02/Sep/2024 18:13:15] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:13:15] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:13:15] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:13:24] "GET / HTTP/1.1" 200 12891 +192.168.253.237 - - [02/Sep/2024 18:13:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:13:24] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:13:49] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:14:49] "GET / HTTP/1.1" 200 12931 +192.168.253.237 - - [02/Sep/2024 18:14:49] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:14:49] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:14:49] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:14:49] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:19:35] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1448 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 18:19:35] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 18:19:36] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 18:19:37] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 18:19:58] "GET / HTTP/1.1" 200 12956 +192.168.253.237 - - [02/Sep/2024 18:19:58] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:19:58] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:19:58] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:20:51] "GET / HTTP/1.1" 200 12956 +192.168.253.237 - - [02/Sep/2024 18:20:51] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:20:51] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:21:19] "GET / HTTP/1.1" 200 12956 +192.168.253.237 - - [02/Sep/2024 18:21:19] "GET /css/styles.css HTTP/1.1" 200 1196 +192.168.253.237 - - [02/Sep/2024 18:21:19] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:21:19] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:21:24] "GET / HTTP/1.1" 200 12956 +192.168.253.237 - - [02/Sep/2024 18:21:24] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /css/styles.css HTTP/1.1" 200 1196 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 18:21:25] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:22:56] "GET / HTTP/1.1" 200 12956 +192.168.253.237 - - [02/Sep/2024 18:22:56] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:22:56] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:22:56] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:23:01] "GET / HTTP/1.1" 200 12944 +192.168.253.237 - - [02/Sep/2024 18:23:01] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:23:01] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:23:01] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:23:06] "GET / HTTP/1.1" 200 12944 +192.168.253.237 - - [02/Sep/2024 18:23:06] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:23:06] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:23:06] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:26:44] "GET / HTTP/1.1" 200 12995 +192.168.253.237 - - [02/Sep/2024 18:26:44] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:26:44] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:26:44] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:26:50] "GET / HTTP/1.1" 200 12995 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 18:26:51] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:26:52] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 18:26:52] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 18:26:52] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 18:26:52] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:29:12] "GET / HTTP/1.1" 200 12995 +192.168.253.237 - - [02/Sep/2024 18:29:12] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:29:12] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:29:12] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:29:18] "GET / HTTP/1.1" 200 13536 +192.168.253.237 - - [02/Sep/2024 18:29:18] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:29:18] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:29:36] "GET / HTTP/1.1" 200 13536 +192.168.253.237 - - [02/Sep/2024 18:29:44] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:29:44] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:33:30] "GET / HTTP/1.1" 200 13452 +192.168.253.237 - - [02/Sep/2024 18:33:30] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:33:35] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:33:35] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:34:18] "GET / HTTP/1.1" 200 13408 +192.168.253.237 - - [02/Sep/2024 18:34:21] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:34:21] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:34:48] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:34:48] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:34:48] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:34:48] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:35:10] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:35:10] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:35:56] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:35:56] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:37:03] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:37:03] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:37:03] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:37:03] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:37:03] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:38:01] "GET / HTTP/1.1" 200 13433 +192.168.253.237 - - [02/Sep/2024 18:38:02] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:38:02] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:38:11] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:11] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:12] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:12] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:12] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:12] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:13] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:13] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 18:38:22] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:38:22] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:38:22] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:39:11] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 18:39:12] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:39:12] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:39:12] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:39:12] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:12] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:39:13] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 18:39:14] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:39:14] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:39:14] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:14] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:14] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:39:15] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 18:39:16] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:39:17] "GET /tests HTTP/1.1" 200 2228 +192.168.253.237 - - [02/Sep/2024 18:39:17] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:17] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:39:17] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:18] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 18:39:19] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:39:23] "POST /cmd HTTP/1.1" 200 33 +192.168.253.237 - - [02/Sep/2024 18:39:24] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 18:39:24] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:39:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:24] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 18:39:24] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 18:39:29] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:40:14] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:40:23] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:40:23] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 18:40:23] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 18:40:24] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 18:40:28] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:41:11] "GET / HTTP/1.1" 200 13403 +192.168.253.127 - - [02/Sep/2024 18:42:27] "GET / HTTP/1.1" 200 13403 +192.168.253.127 - - [02/Sep/2024 18:42:27] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.127 - - [02/Sep/2024 18:42:27] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.127 - - [02/Sep/2024 18:42:28] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.127 - - [02/Sep/2024 18:42:29] "GET /favicon.ico HTTP/1.1" 404 733 +192.168.253.127 - - [02/Sep/2024 18:42:45] "POST /cmd HTTP/1.1" 200 33 +192.168.253.127 - - [02/Sep/2024 18:42:46] "POST /cmd HTTP/1.1" 200 40 +192.168.253.127 - - [02/Sep/2024 18:42:46] "GET / HTTP/1.1" 200 13403 +192.168.253.127 - - [02/Sep/2024 18:42:47] "POST /cmd HTTP/1.1" 200 33 +192.168.253.127 - - [02/Sep/2024 18:42:48] "POST /cmd HTTP/1.1" 200 40 +192.168.253.127 - - [02/Sep/2024 18:42:52] "GET /tests HTTP/1.1" 200 2228 +192.168.253.127 - - [02/Sep/2024 18:42:54] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:48:01] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:48:01] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:48:19] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:51:52] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:51:52] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:51:52] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:52:10] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:52:10] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:52:10] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 18:52:16] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 18:52:18] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 18:52:59] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 19:00:10] "POST /validate HTTP/1.1" 405 747 +192.168.253.237 - - [02/Sep/2024 19:00:25] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 19:00:25] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:00:29] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 19:00:47] "POST /validate HTTP/1.1" 405 747 +192.168.253.237 - - [02/Sep/2024 19:00:59] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 19:01:06] "GET /access HTTP/1.1" 200 2693 +192.168.253.237 - - [02/Sep/2024 19:02:22] "POST /access HTTP/1.1" 200 21 +192.168.253.237 - - [02/Sep/2024 19:02:33] "GET /access HTTP/1.1" 200 2692 +192.168.253.237 - - [02/Sep/2024 19:04:17] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 19:04:17] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:04:17] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:04:20] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:04:21] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:22] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:04:23] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:23] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 19:04:27] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:28] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:04:30] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:31] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:04:32] "POST /cmd HTTP/1.1" 200 38 +192.168.253.237 - - [02/Sep/2024 19:04:33] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:34] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:35] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:36] "POST /cmd HTTP/1.1" 200 43 +192.168.253.237 - - [02/Sep/2024 19:04:37] "POST /cmd HTTP/1.1" 200 43 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1508 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 19:04:37] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 19:04:37] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 19:04:39] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:39] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 19:04:46] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 19:04:50] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:04:51] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:04:59] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:05:00] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:05:04] "GET / HTTP/1.1" 200 13403 +192.168.253.237 - - [02/Sep/2024 19:05:08] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:05:09] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:05:11] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 19:05:12] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:05:13] "POST /cmd HTTP/1.1" 200 43 +192.168.253.237 - - [02/Sep/2024 19:05:14] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1846 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 19:05:14] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 19:05:14] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 19:05:21] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 19:05:22] "POST /cmd HTTP/1.1" 200 40 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 19:05:39] "POST /cmd HTTP/1.1" 200 46 +192.168.253.237 - - [02/Sep/2024 19:05:40] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:05:40] "POST /restartMotion HTTP/1.1" 200 203 +192.168.253.237 - - [02/Sep/2024 19:21:52] "GET / HTTP/1.1" 200 13404 +192.168.253.237 - - [02/Sep/2024 19:21:52] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:21:52] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:21:52] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:22:47] "GET / HTTP/1.1" 200 13404 +192.168.253.237 - - [02/Sep/2024 19:32:21] "GET / HTTP/1.1" 200 13422 +192.168.253.237 - - [02/Sep/2024 19:32:21] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:33:49] "GET / HTTP/1.1" 200 13423 +192.168.253.237 - - [02/Sep/2024 19:35:20] "GET / HTTP/1.1" 200 13451 +192.168.253.237 - - [02/Sep/2024 19:35:41] "GET / HTTP/1.1" 200 13462 +192.168.253.237 - - [02/Sep/2024 19:43:24] "GET / HTTP/1.1" 200 13465 +192.168.253.237 - - [02/Sep/2024 19:43:24] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:43:24] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 19:44:54] "POST /cmd HTTP/1.1" 200 42 +192.168.253.237 - - [02/Sep/2024 19:44:55] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 19:44:56] "POST /restartPi HTTP/1.1" 200 109 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 19:48:20] "GET / HTTP/1.1" 200 13479 +192.168.253.237 - - [02/Sep/2024 19:53:02] "GET / HTTP/1.1" 200 13485 +192.168.253.237 - - [02/Sep/2024 19:53:02] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:11:27] "GET / HTTP/1.1" 200 13528 +192.168.253.237 - - [02/Sep/2024 20:11:27] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:11:27] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:11:27] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:12:41] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:12:42] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:12:42] "GET / HTTP/1.1" 200 13528 +192.168.253.237 - - [02/Sep/2024 20:12:47] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:12:48] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:12:48] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 20:12:48] "POST /cmd HTTP/1.1" 200 41 +192.168.253.237 - - [02/Sep/2024 20:12:50] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:12:51] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:19] "POST /cmd HTTP/1.1" 200 46 +192.168.253.237 - - [02/Sep/2024 20:13:19] "POST /restartMotion HTTP/1.1" 200 203 +192.168.253.237 - - [02/Sep/2024 20:13:20] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:34] "GET / HTTP/1.1" 200 13528 +192.168.253.237 - - [02/Sep/2024 20:13:37] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:13:38] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:39] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:13:40] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:41] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:13:42] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:43] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:44] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:13:45] "POST /cmd HTTP/1.1" 200 38 +192.168.253.237 - - [02/Sep/2024 20:13:46] "POST /cmd HTTP/1.1" 200 38 +192.168.253.237 - - [02/Sep/2024 20:13:47] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:48] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:49] "POST /cmd HTTP/1.1" 200 43 +192.168.253.237 - - [02/Sep/2024 20:13:50] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:13:50] "GET / HTTP/1.1" 200 13528 +192.168.253.237 - - [02/Sep/2024 20:13:55] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:13:55] "POST /cmd HTTP/1.1" 200 29 +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Obstacle détecté +Obstacle détecté +Obstacle détecté +Obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Obstacle détecté +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:14:08] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:14:08] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1828 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:14:09] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 20:14:09] "POST /cmd HTTP/1.1" 200 56 +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 6 cm +Distance à l'avant du véhicule: 57 cm +Distance à l'avant du véhicule: 39 cm +Distance à l'avant du véhicule: 67 cm +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:14:20] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:14:21] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1832 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:14:22] "POST /cmd HTTP/1.1" 200 25 +192.168.253.237 - - [02/Sep/2024 20:14:22] "POST /cmd HTTP/1.1" 200 56 +Test de vitesse à 20% +Avancer pendant 0.5 secondes à une vitesse de 20 +Arrêt pendant 1 secondes +Reculer pendant 0.5 secondes à une vitesse de 20 +Arrêt pendant 1 secondes +Tourner à guauche pendant 0.5 secondes à une vitesse de 20 +Arrêt pendant 1 secondes +Tourner à droite pendant 0.5 secondes à une vitesse de 20 +Arrêt pendant 1 secondes +Test de vitesse à 50% +Avancer pendant 0.5 secondes à une vitesse de 50 +Arrêt pendant 1 secondes +Reculer pendant 0.5 secondes à une vitesse de 50 +Arrêt pendant 1 secondes +Tourner à guauche pendant 0.5 secondes à une vitesse de 50 +Arrêt pendant 1 secondes +Tourner à droite pendant 0.5 secondes à une vitesse de 50 +Arrêt pendant 1 secondes +Test de vitesse à 80% +Avancer pendant 0.5 secondes à une vitesse de 80 +Arrêt pendant 1 secondes +Reculer pendant 0.5 secondes à une vitesse de 80 +Arrêt pendant 1 secondes +Tourner à guauche pendant 0.5 secondes à une vitesse de 80 +Arrêt pendant 1 secondes +Tourner à droite pendant 0.5 secondes à une vitesse de 80 +Arrêt pendant 1 secondes +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:14:41] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:14:42] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1839 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:14:43] "POST /cmd HTTP/1.1" 200 23 +192.168.253.237 - - [02/Sep/2024 20:14:43] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:14:54] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:14:55] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1844 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:14:56] "POST /cmd HTTP/1.1" 200 29 +192.168.253.237 - - [02/Sep/2024 20:14:56] "POST /cmd HTTP/1.1" 200 56 +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Obstacle détecté +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:15:06] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:15:06] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:15:16] "POST /cmd HTTP/1.1" 200 46 +192.168.253.237 - - [02/Sep/2024 20:15:16] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:15:28] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:15:28] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:22:52] "GET / HTTP/1.1" 200 13515 +192.168.253.237 - - [02/Sep/2024 20:22:52] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:22:54] "POST /cmd HTTP/1.1" 200 46 +192.168.253.237 - - [02/Sep/2024 20:22:54] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:22:57] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:22:57] "POST /cmd HTTP/1.1" 200 56 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 20:17:32] "GET / HTTP/1.1" 200 13515 +192.168.253.237 - - [02/Sep/2024 20:25:21] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [02/Sep/2024 20:25:22] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:25:23] "POST /cmd HTTP/1.1" 200 38 +192.168.253.237 - - [02/Sep/2024 20:25:24] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:25:25] "POST /cmd HTTP/1.1" 200 43 +192.168.253.237 - - [02/Sep/2024 20:25:26] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:25:28] "POST /cmd HTTP/1.1" 200 43 +192.168.253.237 - - [02/Sep/2024 20:25:29] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:25:37] "POST /cmd HTTP/1.1" 200 57 +192.168.253.237 - - [02/Sep/2024 20:25:37] "POST /cmd HTTP/1.1" 200 56 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 53 cm +Avancer pendant 0.1 secondes à une vitesse de 37.1 +Distance à l'avant du véhicule: 37 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 31 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 32 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 35 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 40 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 45 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 51 cm +Avancer pendant 0.1 secondes à une vitesse de 35.7 +Distance à l'avant du véhicule: 54 cm +Avancer pendant 0.1 secondes à une vitesse de 37.800000000000004 +Distance à l'avant du véhicule: 64 cm +Avancer pendant 0.1 secondes à une vitesse de 44.800000000000004 +Distance à l'avant du véhicule: 56 cm +Avancer pendant 0.1 secondes à une vitesse de 39.2 +Distance à l'avant du véhicule: 47 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 39 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 34 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 31 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 27 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 21 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 17 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 15 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 16 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 24 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 32 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 39 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 43 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 46 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 51 cm +Avancer pendant 0.1 secondes à une vitesse de 35.7 +Distance à l'avant du véhicule: 57 cm +Avancer pendant 0.1 secondes à une vitesse de 39.9 +Distance à l'avant du véhicule: 63 cm +Avancer pendant 0.1 secondes à une vitesse de 44.1 +Distance à l'avant du véhicule: 70 cm +Avancer pendant 0.1 secondes à une vitesse de 49.0 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 63 cm +Avancer pendant 0.1 secondes à une vitesse de 44.1 +Distance à l'avant du véhicule: 47 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 41 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 56 cm +Avancer pendant 0.1 secondes à une vitesse de 39.2 +Distance à l'avant du véhicule: 31 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 24 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 19 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 18 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 21 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 27 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 66 cm +Avancer pendant 0.1 secondes à une vitesse de 46.2 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 45 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 51 cm +Avancer pendant 0.1 secondes à une vitesse de 35.7 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 65 cm +Avancer pendant 0.1 secondes à une vitesse de 45.5 +Distance à l'avant du véhicule: 37 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 29 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 21 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 17 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 12 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 13 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 16 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 24 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 51 cm +Avancer pendant 0.1 secondes à une vitesse de 35.7 +Distance à l'avant du véhicule: 49 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 39 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 41 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 43 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 44 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 38 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 27 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 19 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 16 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 11 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 12 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 13 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 13 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 13 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 12 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 12 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 16 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 19 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 25 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:26:04] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:26:05] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1194 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:26:05] "POST /cmd HTTP/1.1" 200 39 +192.168.253.237 - - [02/Sep/2024 20:26:05] "POST /cmd HTTP/1.1" 200 56 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement: operation successful. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:26:22] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:26:22] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1207 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:26:23] "POST /cmd HTTP/1.1" 200 57 +192.168.253.237 - - [02/Sep/2024 20:26:23] "POST /cmd HTTP/1.1" 200 56 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 39 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 36 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 33 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 26 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 21 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 17 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 15 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 10 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 10 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 9 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 11 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 17 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 30 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 31 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 19 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 11 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 11 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 10 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 11 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 14 cm +Arrêt pendant 0.1 secondes +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 69 cm +Avancer pendant 0.1 secondes à une vitesse de 48.3 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:28:06] "GET / HTTP/1.1" 200 13497 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1226 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:28:08] "POST /cmd HTTP/1.1" 200 57 +192.168.253.237 - - [02/Sep/2024 20:28:08] "POST /cmd HTTP/1.1" 200 56 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 30 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 19 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 7 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 10 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 8 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 12 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 60 cm +Avancer pendant 0.1 secondes à une vitesse de 42.0 +Distance à l'avant du véhicule: 41 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 33 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 22 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 14 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 8 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 15 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 35 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 37 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 40 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 42 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 39 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 36 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 31 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 27 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 24 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 19 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 14 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 68 cm +Avancer pendant 0.1 secondes à une vitesse de 47.6 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 67 cm +Avancer pendant 0.1 secondes à une vitesse de 46.900000000000006 +Distance à l'avant du véhicule: 54 cm +Avancer pendant 0.1 secondes à une vitesse de 37.800000000000004 +Distance à l'avant du véhicule: 20 cm +Avancer pendant 0.1 secondes à une vitesse de 20 +Distance à l'avant du véhicule: 15 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 9 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 7 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 8 cm +Arrêt d'urgence ! +Distance à l'avant du véhicule: 8 cm +Arrêt d'urgence ! +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1279 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:28:25] "POST /cmd HTTP/1.1" 200 30 +192.168.253.237 - - [02/Sep/2024 20:28:25] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:28:29] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:28:29] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:28:31] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1303 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:28:31] "POST /cmd HTTP/1.1" 200 36 +Distance à l'avant du véhicule: 68 cm +Distance à l'avant du véhicule: 68 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 67 cm +Distance à l'avant du véhicule: 68 cm +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Obstacle détecté +Obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Aucun obstacle détecté +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:28:39] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:28:39] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:29:45] "GET / HTTP/1.1" 200 13474 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1310 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:29:50] "POST /cmd HTTP/1.1" 200 36 +192.168.253.237 - - [02/Sep/2024 20:29:50] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:31:12] "GET / HTTP/1.1" 200 13474 +192.168.253.237 - - [02/Sep/2024 20:31:12] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:31:13] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1340 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:31:13] "POST /cmd HTTP/1.1" 200 36 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1383 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:31:23] "POST /cmd HTTP/1.1" 200 30 +192.168.253.237 - - [02/Sep/2024 20:31:23] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:31:28] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:31:28] "POST /cmd HTTP/1.1" 200 56 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1389 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:31:32] "POST /cmd HTTP/1.1" 200 39 +192.168.253.237 - - [02/Sep/2024 20:31:32] "POST /cmd HTTP/1.1" 200 56 +Positionné à 0° +Positionné à 45° +Positionné à 90° +Positionné à 135° +Positionné à 180° +Positionné à 0° +Nettoyage des GPIO effectué. +Le composant fonctionne correctement. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:31:41] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:31:42] "POST /cmd HTTP/1.1" 200 56 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement: operation successful. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:31:42] "GET / HTTP/1.1" 200 13485 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1396 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:31:46] "POST /cmd HTTP/1.1" 200 39 +192.168.253.237 - - [02/Sep/2024 20:31:46] "POST /cmd HTTP/1.1" 200 56 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement: operation successful. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:32:01] "POST /cmd HTTP/1.1" 200 56 +192.168.253.237 - - [02/Sep/2024 20:32:02] "POST /cmd HTTP/1.1" 200 40 +/usr/lib/python3.9/subprocess.py:1052: ResourceWarning: subprocess 1408 is still running + _warn("subprocess %s is still running" % self.pid, +ResourceWarning: Enable tracemalloc to get the object allocation traceback +192.168.253.237 - - [02/Sep/2024 20:32:03] "POST /cmd HTTP/1.1" 200 39 +192.168.253.237 - - [02/Sep/2024 20:32:03] "POST /cmd HTTP/1.1" 200 56 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Arrêt d'urgence ! +Arrêt d'urgence ! +Arrêt d'urgence ! +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Avancer pendant 0.1 secondes à une vitesse de 20 +Nettoyage des GPIO effectué. +Le composant fonctionne correctement: operation successful. +Résultats enregistrés avec succès. +192.168.253.237 - - [02/Sep/2024 20:32:16] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [02/Sep/2024 20:32:16] "POST /cmd HTTP/1.1" 200 56 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 20:53:59] "GET / HTTP/1.1" 200 13493 +192.168.253.237 - - [02/Sep/2024 20:53:59] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:53:59] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:53:59] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 20:54:51] "GET / HTTP/1.1" 200 13493 +192.168.253.237 - - [02/Sep/2024 20:54:54] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 20:54:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 20:55:19] "GET / HTTP/1.1" 200 13493 +192.168.253.237 - - [02/Sep/2024 20:55:19] "GET /css/styles.css HTTP/1.1" 200 1173 +192.168.253.237 - - [02/Sep/2024 20:55:19] "GET /fonts/SegmentLED.ttf HTTP/1.1" 200 1279304 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /css/bootstrap.min.css HTTP/1.1" 200 232803 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /images/pointer.png HTTP/1.1" 200 4224 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /js/jquery.js HTTP/1.1" 200 96381 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 200 80421 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /js/script.js HTTP/1.1" 200 3077 +192.168.253.237 - - [02/Sep/2024 20:55:20] "GET /images/speedometer.png HTTP/1.1" 200 68913 +192.168.253.237 - - [02/Sep/2024 20:55:23] "GET /js/bootstrap.bundle.min.js.map HTTP/1.1" 404 752 +192.168.253.237 - - [02/Sep/2024 20:55:23] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 747 +192.168.253.237 - - [02/Sep/2024 20:57:18] "GET / HTTP/1.1" 200 13501 +192.168.253.237 - - [02/Sep/2024 21:00:42] "GET / HTTP/1.1" 200 13501 +192.168.253.237 - - [02/Sep/2024 21:12:27] "GET / HTTP/1.1" 200 13411 +192.168.253.237 - - [02/Sep/2024 21:12:28] "GET /css/styles.css HTTP/1.1" 304 0 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 22:19:19] "GET / HTTP/1.1" 200 13381 +192.168.253.237 - - [02/Sep/2024 22:19:19] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 22:19:19] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 22:19:19] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 22:19:22] "GET /favicon.ico HTTP/1.1" 404 733 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [02/Sep/2024 23:31:47] "GET / HTTP/1.1" 200 13363 +192.168.253.237 - - [02/Sep/2024 23:31:47] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 23:31:47] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 23:31:47] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [02/Sep/2024 23:31:49] "GET /favicon.ico HTTP/1.1" 404 733 +192.168.253.237 - - [02/Sep/2024 23:31:53] "GET / HTTP/1.1" 200 13363 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +192.168.253.237 - - [03/Sep/2024 01:29:23] "GET / HTTP/1.1" 200 13458 +192.168.253.237 - - [03/Sep/2024 01:29:23] "GET /css/styles.css HTTP/1.1" 304 0 +192.168.253.237 - - [03/Sep/2024 01:29:23] "GET /js/bootstrap.bundle.min.js HTTP/1.1" 304 0 +192.168.253.237 - - [03/Sep/2024 01:29:23] "GET /js/script.js HTTP/1.1" 304 0 +192.168.253.237 - - [03/Sep/2024 01:29:38] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [03/Sep/2024 01:29:39] "POST /cmd HTTP/1.1" 200 40 +192.168.253.237 - - [03/Sep/2024 01:29:40] "POST /cmd HTTP/1.1" 200 31 +192.168.253.237 - - [03/Sep/2024 01:29:41] "POST /cmd HTTP/1.1" 200 40 +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ +Hit Ctrl-C to quit. + +Bottle v0.12.25 server starting up (using WSGIRefServer())... +Listening on http://192.168.253.194:8000/ Hit Ctrl-C to quit. -192.168.74.237 - - [15/May/2024 11:01:16] "GET / HTTP/1.1" 200 4592 -192.168.74.237 - - [15/May/2024 11:01:21] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:21] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:22] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:22] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:34] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:35] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:35] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:35] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:41] "POST /motor_speed_move HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:41] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:41] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:45] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:45] "POST /motor_speed_move HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:45] "POST /cmd HTTP/1.1" 200 2 -192.168.74.237 - - [15/May/2024 11:01:54] "GET /css/bootstrap.min.css.map HTTP/1.1" 404 746 diff --git a/WebControl/logs/motionlogs.txt b/WebControl/logs/motionlogs.txt new file mode 100644 index 0000000000000000000000000000000000000000..ec1dc5aadd297bde03f1e99d4bc9118dc339018c GIT binary patch literal 4224 zcmeHKu?oU46m;%ayio_6&e_DZh=W@xCA4V_)V`8Nzuz`-5<6NHF2f6imm?f^$4imP z8+*%rNyX`Moa!OZORBkVtBzG8>Fl`H<7j(B{_3=9D5HI7u!dUOX%gDkBBH#ubiSVy zpRr?SHG1XzeUOy1F#(+;+*Ul46CIm3%;{v8Z2oL5aPYJI;=QvOzNcUC3w~n&rXkOu e2j~HMSZ{uS-{3d+4SrktUmzcl56Fl0^5F?`L4{lZ literal 0 HcmV?d00001 diff --git a/WebControl/logs/resultats_tests.json b/WebControl/logs/resultats_tests.json new file mode 100644 index 0000000..959b47e --- /dev/null +++ b/WebControl/logs/resultats_tests.json @@ -0,0 +1,1808 @@ +[ + { + "date": "2024-08-30 17:54:47", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-08-30 18:00:03", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-08-30 18:01:46", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:06:57", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-08-30 18:08:02", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-08-30 18:09:58", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:10:08", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:10:42", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:34:30", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:34:36", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:35:12", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-08-30 18:35:19", + "nom": "tests/servo.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:21:15", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 12:29:04", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 12:33:58", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 12:34:10", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:35:01", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:35:16", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:50:10", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:50:26", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:50:52", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:51:09", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:51:18", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:52:07", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:52:24", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:53:06", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:53:17", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:53:27", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:53:38", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:53:48", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:54:14", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:54:25", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:54:36", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:55:04", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:55:15", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:55:33", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:55:42", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:55:52", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:56:21", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:56:36", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:57:16", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:57:26", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 12:57:58", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:02:10", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:02:22", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:03:01", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:04:55", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:05:07", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:05:32", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:06:23", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:06:43", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:07:28", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:07:37", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:08:22", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 13:08:33", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 14:16:41", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 14:23:01", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 14:27:23", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 14:27:50", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 14:31:33", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 14:38:17", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 14:39:19", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 14:49:24", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 14:59:28", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 15:03:02", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-01 15:07:49", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:08:01", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:11:10", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:11:30", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:13:42", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:13:51", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:17:21", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:17:39", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:18:21", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:18:30", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:18:33", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:18:38", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:19:19", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:24:50", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:28:18", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:29:50", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:29:55", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:31:05", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 15:31:39", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:06:14", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:08:49", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:09:05", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:10:58", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:12:42", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:12:56", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:13:34", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 16:15:31", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 16:21:35", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 16:21:40", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 16:22:33", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 16:28:02", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "test successful" + }, + { + "date": "2024-09-01 16:31:02", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle" + }, + { + "date": "2024-09-01 16:31:12", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-01 17:11:43", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-01 17:13:06", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle" + }, + { + "date": "2024-09-01 17:16:07", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-01 17:16:29", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-01 17:20:12", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-01 18:45:55", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "erreur s\u00e9rie" + }, + { + "date": "2024-09-01 23:20:10", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": false, + "status": "no obstacle detected" + }, + { + "date": "2024-09-01 23:20:47", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-01 23:21:06", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 23:21:24", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-01 23:29:16", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-01 23:29:42", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-01 23:30:33", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 23:30:38", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-01 23:40:27", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 23:40:49", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-01 23:41:21", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-01 23:41:37", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-01 23:42:31", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-01 23:43:37", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-01 23:43:59", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 00:34:41", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 00:36:15", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:38:31", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:38:46", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:39:04", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:39:15", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:40:24", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:40:52", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:43:14", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 00:43:53", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 00:44:05", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 00:55:57", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:02:52", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:03:33", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:03:42", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:09:45", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:10:05", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:10:15", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:12:14", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:12:54", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 01:13:10", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:13:29", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:14:10", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:14:41", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:15:05", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:18:49", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:54:34", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:57:47", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:57:58", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 01:58:40", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-02 01:58:48", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "Access denied" + }, + { + "date": "2024-09-02 01:58:59", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-02 02:00:36", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 02:05:57", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 02:06:17", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 02:07:53", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 02:13:54", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 02:18:51", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 09:47:37", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 09:48:04", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 09:51:44", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 09:53:37", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 10:15:00", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 10:15:06", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 10:50:09", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 12:20:43", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 12:21:09", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-02 12:21:21", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 12:21:32", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 12:26:36", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 15:36:32", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:36:47", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:37:32", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:47:26", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:48:29", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:48:44", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 15:49:04", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 16:03:47", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 16:04:44", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 16:42:42", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 16:42:52", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 17:39:04", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 17:44:43", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 17:49:19", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:10:49", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:11:36", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:11:38", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:11:39", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:11:52", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:11:55", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 18:19:44", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:04:46", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:05:24", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:16:31", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:18:50", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:20:15", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:21:26", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-02 19:25:45", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": false, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 19:30:10", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 19:32:14", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 19:33:44", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-02 19:34:24", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": false, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 19:35:13", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 19:35:35", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 19:40:03", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "time limit reached" + }, + { + "date": "2024-09-02 19:44:24", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 19:44:26", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 19:44:38", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-02 19:47:11", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 19:47:49", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "emergency stop successful" + }, + { + "date": "2024-09-02 19:48:10", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 19:50:45", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 19:51:01", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 19:51:26", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-02 19:51:48", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 19:52:15", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 19:52:48", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 19:55:32", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 19:56:04", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 19:57:07", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:06:25", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:07:37", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:08:04", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "emergency stop successful" + }, + { + "date": "2024-09-02 20:14:00", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 20:14:17", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:14:40", + "nom": "tests/motor_speed_move.py", + "fonctionnement_ok": true, + "status": "move successful" + }, + { + "date": "2024-09-02 20:14:52", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 20:15:02", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 20:25:48", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:26:15", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:26:33", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:28:18", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:28:32", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:28:36", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 20:31:32", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 20:31:42", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:31:56", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:32:13", + "nom": "apps/infrared_obstacle_avoidance.py", + "fonctionnement_ok": true, + "status": "operation successful" + }, + { + "date": "2024-09-02 20:46:38", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 20:51:45", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "obstacle detected" + }, + { + "date": "2024-09-02 20:52:00", + "nom": "tests/infrared_obstacle_module.py", + "fonctionnement_ok": true, + "status": "no obstacle detected" + }, + { + "date": "2024-09-02 20:52:25", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:52:47", + "nom": "tests/lidar_module.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-02 20:53:50", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 21:01:24", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:04:05", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:04:26", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:04:57", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:05:57", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:06:12", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:07:22", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:08:36", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:08:47", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 21:08:57", + "nom": "tests/servo_motor.py", + "fonctionnement_ok": true, + "status": "movement successful" + }, + { + "date": "2024-09-02 22:06:38", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 22:16:13", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 22:16:23", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 22:16:44", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 22:17:17", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 22:19:05", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:01:49", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-02 23:01:55", + "nom": "tests/rfid_open_door.py", + "fonctionnement_ok": true, + "status": "Access successful" + }, + { + "date": "2024-09-02 23:06:01", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:06:33", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:22:22", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:26:51", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:31:19", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:39:06", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-02 23:52:54", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:53:36", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-02 23:57:20", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-02 23:59:02", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 00:11:24", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-03 00:11:59", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 00:13:52", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-03 00:24:37", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": true, + "status": "measurement successful" + }, + { + "date": "2024-09-03 00:54:47", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:00:15", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:04:31", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:04:40", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:05:27", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-03 01:15:20", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:16:13", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-03 01:18:10", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-03 01:20:22", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:22:51", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": true, + "status": "scenario successful" + }, + { + "date": "2024-09-03 01:23:42", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": true, + "status": "scenario successful" + }, + { + "date": "2024-09-03 01:28:18", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:29:09", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": true, + "status": "scenario successful" + }, + { + "date": "2024-09-03 01:37:02", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:37:37", + "nom": "apps/itineraire_suivre_emergency.py", + "fonctionnement_ok": false, + "status": "error" + }, + { + "date": "2024-09-03 01:41:54", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:42:14", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:42:25", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:42:45", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:49:06", + "nom": "apps/lidar_speed_move.py", + "fonctionnement_ok": false, + "status": "initialization" + }, + { + "date": "2024-09-03 01:49:39", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:52:08", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:52:16", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:57:18", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 01:57:27", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + }, + { + "date": "2024-09-03 02:00:09", + "nom": "apps/scenario_rfid.py", + "fonctionnement_ok": false, + "status": "interrupted" + } +] \ No newline at end of file diff --git a/WebControl/logs/selected_steps.json b/WebControl/logs/selected_steps.json new file mode 100644 index 0000000..9f9a3a8 --- /dev/null +++ b/WebControl/logs/selected_steps.json @@ -0,0 +1,78 @@ +[ + { + "distance_value": 141, + "maneuver": "maneuver-unspecified" + }, + { + "distance_value": 231, + "maneuver": "turn-sharp-left" + }, + { + "distance_value": 397, + "maneuver": "maneuver-unspecified" + }, + { + "distance_value": 70, + "maneuver": "maneuver-unspecified" + }, + { + "distance_value": 160, + "maneuver": "turn-left" + }, + { + "distance_value": 407, + "maneuver": "turn-right" + }, + { + "distance_value": 424, + "maneuver": "turn-left" + }, + { + "distance_value": 960, + "maneuver": "roundabout-right" + }, + { + "distance_value": 2230, + "maneuver": "ramp-right" + }, + { + "distance_value": 5935, + "maneuver": "fork-right" + }, + { + "distance_value": 4403, + "maneuver": "fork-right" + }, + { + "distance_value": 3099, + "maneuver": "ramp-left" + }, + { + "distance_value": 391, + "maneuver": "keep-left" + }, + { + "distance_value": 1674, + "maneuver": "merge" + }, + { + "distance_value": 829, + "maneuver": "keep-left" + }, + { + "distance_value": 413, + "maneuver": "keep-left" + }, + { + "distance_value": 193, + "maneuver": "merge" + }, + { + "distance_value": 476, + "maneuver": "turn-left" + }, + { + "distance_value": 305, + "maneuver": "turn-right" + } +] \ No newline at end of file diff --git a/WebControl/logs/selected_steps_short.json b/WebControl/logs/selected_steps_short.json new file mode 100644 index 0000000..5be7d23 --- /dev/null +++ b/WebControl/logs/selected_steps_short.json @@ -0,0 +1,22 @@ +[ + { + "distance_value": 197, + "maneuver": "maneuver-unspecified" + }, + { + "distance_value": 1313, + "maneuver": "turn-right" + }, + { + "distance_value": 507, + "maneuver": "ramp-right" + }, + { + "distance_value": 4465, + "maneuver": "merge" + }, + { + "distance_value": 5935, + "maneuver": "fork-right" + } +] \ No newline at end of file diff --git a/WebControl/logs/steps.json b/WebControl/logs/steps.json new file mode 100644 index 0000000..52b75fd --- /dev/null +++ b/WebControl/logs/steps.json @@ -0,0 +1,455 @@ +[ + { + "distance": { + "text": "0.1 km", + "value": 141 + }, + "duration": { + "text": "1 min", + "value": 37 + }, + "end_location": { + "lat": 48.82129579999999, + "lng": 2.2737025 + }, + "html_instructions": "Head southwest on Rue de l'Abbé Grégoire toward Rue de la Glacière", + "polyline": { + "points": "kq~hHsj{LdAxBDHP`@@@JTDHDHDFLXBFJPJP" + }, + "start_location": { + "lat": 48.82214339999999, + "lng": 2.2751386 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.2 km", + "value": 231 + }, + "duration": { + "text": "1 min", + "value": 64 + }, + "end_location": { + "lat": 48.821996, + "lng": 2.276619 + }, + "html_instructions": "Sharp left onto Rue d'Alembert", + "maneuver": "turn-sharp-left", + "polyline": { + "points": "cl~hHsa{L@M@I?K?K?GAIAKAEAKAKIk@AEE_@AECSc@sDMs@GUEMCKCGKSY{@" + }, + "start_location": { + "lat": 48.82129579999999, + "lng": 2.2737025 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.4 km", + "value": 397 + }, + "duration": { + "text": "1 min", + "value": 71 + }, + "end_location": { + "lat": 48.8230712, + "lng": 2.2815447 + }, + "html_instructions": "Continue onto Rue de l'Abbé Derry", + "polyline": { + "points": "op~hH{s{LKFIs@COAM?O@y@@a@?u@CeAAg@AUCq@CSAQCWEYG]ESMg@ACQu@EOWgAa@}BAKCMAECESk@Qa@" + }, + "start_location": { + "lat": 48.821996, + "lng": 2.276619 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "70 m", + "value": 70 + }, + "duration": { + "text": "1 min", + "value": 21 + }, + "end_location": { + "lat": 48.8234637, + "lng": 2.2822848 + }, + "html_instructions": "Continue onto Rue du Chevalier de la Barre", + "polyline": { + "points": "ew~hHsr|LUm@M_@EKM_@CGCC?AAAAACAEE" + }, + "start_location": { + "lat": 48.8230712, + "lng": 2.2815447 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.2 km", + "value": 160 + }, + "duration": { + "text": "1 min", + "value": 41 + }, + "end_location": { + "lat": 48.8248221, + "lng": 2.2819013 + }, + "html_instructions": "Turn left onto Av. du Général de Gaulle/D71", + "maneuver": "turn-left", + "polyline": { + "points": "sy~hHgw|L_@Je@Ja@LQFG@_@HC@EB_@NC@WJIBA@A?A?A?A?A?AAA?AA?AAAACGK" + }, + "start_location": { + "lat": 48.8234637, + "lng": 2.2822848 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.4 km", + "value": 407 + }, + "duration": { + "text": "1 min", + "value": 82 + }, + "end_location": { + "lat": 48.8219346, + "lng": 2.2853073 + }, + "html_instructions": "Turn right onto Bd du Lycée/D50", + "maneuver": "turn-right", + "polyline": { + "points": "cb_iH{t|Lb@g@`DcEpFcHZ_@tAcBVU" + }, + "start_location": { + "lat": 48.8248221, + "lng": 2.2819013 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.4 km", + "value": 424 + }, + "duration": { + "text": "1 min", + "value": 83 + }, + "end_location": { + "lat": 48.8204157, + "lng": 2.2905512 + }, + "html_instructions": "Turn left onto Rue Antoine Fratacci/D50", + "maneuver": "turn-left", + "polyline": { + "points": "ap~hHej}L?EAG?E?A?C?I?G?ALuBD[BYDW@ADU?CVeAh@wBZsAZoAFSJc@Jm@@ELk@@EVgA`@_BFWFWFSJ]" + }, + "start_location": { + "lat": 48.8219346, + "lng": 2.2853073 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "1.0 km", + "value": 960 + }, + "duration": { + "text": "3 mins", + "value": 203 + }, + "end_location": { + "lat": 48.8253839, + "lng": 2.3004907 + }, + "html_instructions": "At the roundabout, take the 4th exit onto Rue Jean Bleuzen/D130", + "maneuver": "roundabout-right", + "polyline": { + "points": "sf~hH}j~L@@@?@?@@@?@?@?@?@?@ABA@A@A@A@A@A@C?A@A?A@A?C?A@A?A?C?A?C?C?AAC?A?CAA?CAA?AACAAACAAA?AA?AA?A?AAC?A?A?A?A@O_@GOGSGOGQe@eAOQi@kAMYO[o@sAEIYk@Wk@Yk@MUEMo@qAO]_@u@Qc@GMM[Sg@EKGSQ_@_@eACGEKIQm@_B?AM[IQ?CGKOc@G[AKAGAEAG_AeCM_@]eA[w@CICIGQIQM_@Si@GSYy@KSKWEICGIMIIIIECEEIAG?" + }, + "start_location": { + "lat": 48.8204157, + "lng": 2.2905512 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "2.2 km", + "value": 2230 + }, + "duration": { + "text": "4 mins", + "value": 219 + }, + "end_location": { + "lat": 48.8192297, + "lng": 2.3292151 + }, + "html_instructions": "Turn right to merge onto Blvd Périphérique", + "maneuver": "ramp-right", + "polyline": { + "points": "se_iHai`MU@VeB@A?A^mCJq@TiBD]Jw@Fs@RsB?ACa@J}@BUPqAJs@VoBFe@@C\\iCNaAJu@Fe@D[PmAHi@Da@DU@GVqBl@mEr@gF\\aCb@eD`@yCb@yCJ{@VgBRwAFe@F]N_ATiAJg@PcAD[Ly@VmBRwAZwBD]Hg@@MRuADUFi@NgANmA@ERuBH_A@MLgA@M@OLy@D_@Jq@Js@?CHo@F_@R{AHm@L}@Hm@Jw@PoAVgBFa@DYR}A?AVeB?CLgAVuBRuAJ{@" + }, + "start_location": { + "lat": 48.8253839, + "lng": 2.3004907 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "5.9 km", + "value": 5935 + }, + "duration": { + "text": "5 mins", + "value": 287 + }, + "end_location": { + "lat": 48.7705456, + "lng": 2.3452899 + }, + "html_instructions": "Keep right at the fork to continue on A6a", + "maneuver": "fork-right", + "polyline": { + "points": "e_~hHs|eMLI@AFa@BGF]@IFa@DQHYJw@Fg@@GBK@M@IFg@LeABYFg@@IDY@M?CHi@BO@I@G@IBIBMDQDMBK@IDMBIBGBGFMDKBGBIDIHODIJQHOLQHOHOPWNWLSLSLSHOBALUDKDGFOFOBGBKJWBKBK@GBI@IFg@L}@H_A@CBY@C?GBIBK@G?A@C@A@C?A@A@A@A@ABCBABCDAJEFCFCDADAFAFAD?B?B?B?B?D?D@D?D@FBH@FBLDh@PVHRFn@TTHTFVHVFTFTFVBVDT@J@P@N?J?L?B?VAFAPAVCTCVGVEDCPETIRIVKRKBCTMVQHGJI@AJIFEDC?ADCHKFIBA@A?A@A@EdBwAnBaBJKNM?AHIHGrAkAJInBeBPOVUVSPQj@e@RQJKFGNMpAiAJIHIROFGROTQPMbAm@~@e@TKZM^O`@Mj@QTGTEVGVE`@G\\E\\ED?RANADAXAx@AxC?dA@l@?T?v@?l@?n@@r@?X?P?T?X?X@VAN?ZATATAPAH?LAPCLCNCTEB?NEr@QBARGRIRI\\MRKFEb@URMRKPMJILKJINKFGDCr@m@HGb@_@f@c@TQTQTQPMVOFELINIl@[TKVKRIXKBAf@Oh@OVE@A^G`@G\\Ep@G^Ah@AL?H?P?N?X@H?L@XBD?`@D`@Dj@JhDh@NBzATH@XDz@N\\Dt@Lf@Dl@DH?J?F@f@?L@^Cb@Ab@C`@EB?ZEh@I\\INCPEJCTG`@ONE~@]PITIlBu@NIz@[f@QlAe@bBo@p@WTIf@ONGf@O`@K`@K\\I@?BAh@KREFATE\\EZEh@If@GTC^CFAb@CLAb@AVCN?H?TAJ?fA?^?P?^@X@f@B^@N@v@Ff@B^B\\BrBL`@BN@n@DVB^BB?|@F|@FL?F@R@F@bAFZ@VBl@D`AFf@DF?d@DJ?x@Df@DF@H?dAFX@B@T@fNz@v@Fn@Df@BJ@N@P@D?RBfAHR@n@FF@z@L" + }, + "start_location": { + "lat": 48.8192297, + "lng": 2.3292151 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "4.4 km", + "value": 4403 + }, + "duration": { + "text": "3 mins", + "value": 193 + }, + "end_location": { + "lat": 48.7348556, + "lng": 2.3655247 + }, + "html_instructions": "Keep right at the fork to continue on A106, follow signs for Aéroport Orly", + "maneuver": "fork-right", + "polyline": { + "points": "}nthHaaiMJX@?HBf@NTFp@X@?`@Pj@V`@Rf@XB@f@VVNXPDBTLTLPJRH\\LVHZH\\Hh@JNBF@P@j@Db@Bl@?@?d@Al@AX?z@AFAJ?d@CNBfEWLCf@GB?TEZGVCREj@Mp@Sn@QTI^Oh@SBAb@Q\\Q\\QVOVMv@e@LKl@c@NKZUf@c@VUPQb@a@DEj@k@hAgAzB{B`B_BjEgE\\]nGkGtAuAPQFGVUPSx@w@hAiAJI\\]JIJK@Ax@w@PSRSt@s@nDmD~B}BXYZYJM|@}@zAyABA^_@VYj@i@`@a@XY\\]ZW~F}FtAsAJKXYJKh@i@TSj@k@FIDCRSBCHITS`@c@FG|@{@v@w@TULKTUXYDCJKNOJKJIZYPONMPOROLKd@[^UDCFEFEBAPKLIZO`@STK\\M^On@Uj@STGbBi@JEPGRGFADCLEh@Q|@Yp@SXKVITGdA]^MXI~@Yz@YNG`@M`@M^Mv@Wl@QDA\\Mx@WVI`@MXKNERG|@YJE|Bu@PEHE@?DA|Bu@lBm@l@O" + }, + "start_location": { + "lat": 48.7705456, + "lng": 2.3452899 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "3.1 km", + "value": 3099 + }, + "duration": { + "text": "5 mins", + "value": 271 + }, + "end_location": { + "lat": 48.7074919, + "lng": 2.3713861 + }, + "html_instructions": "Exit on the left onto N7 toward Évry/Paray-Vieille-Poste/Athis-Mons", + "maneuver": "ramp-left", + "polyline": { + "points": "{omhHo_mMHU@ABCrAe@PIZKvAg@d@S@A`@]l@QbA]`@MXIpBo@\\MVIj@QdA]BAhA]vAe@XKf@OhBk@BAv@SnC{@fBk@RGzBq@vBs@n@Un@Un@Uh@O^MjC{@LEb@O\\INEXI^IHCJCJALCNCLCNAtAMD?FAfHOb@Ab@Ab@AjDIZAZ?vEKvCGbECF?hBGl@CPBRAd@AfAEj@CTAD?zAItCGn@A~@Ch@AD?TC^?~AEnCEfACb@A^?VAZAnAG\\CTARAx@?pAC|@CTAR?z@Cr@A~@Ax@A" + }, + "start_location": { + "lat": 48.7348556, + "lng": 2.3655247 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.4 km", + "value": 391 + }, + "duration": { + "text": "1 min", + "value": 45 + }, + "end_location": { + "lat": 48.7039886, + "lng": 2.3716268 + }, + "html_instructions": "Keep left", + "maneuver": "keep-left", + "polyline": { + "points": "ydhhHednMJGTAbAAlAC~AEl@Al@CxBED?NAZAF?NAtAEd@CJ@" + }, + "start_location": { + "lat": 48.7074919, + "lng": 2.3713861 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "1.7 km", + "value": 1674 + }, + "duration": { + "text": "4 mins", + "value": 258 + }, + "end_location": { + "lat": 48.6890215, + "lng": 2.3710222 + }, + "html_instructions": "Merge onto Av. François Mitterrand/N7
Continue to follow N7
", + "maneuver": "merge", + "polyline": { + "points": "}nghHuenMh@Av@?TARAvBEjBEp@AzAEx@?VAb@AdAEv@AjACh@?^?p@?f@Ax@AbAAJ?RBTBn@J~C^lANz@FbAJr@H|ARp@HB@xBXjAN^D`@FH@`BPx@LxCZp@Db@@F?Z@R@zB@\\ATAx@Ij@K\\G\\GHAh@Kf@MXKVI" + }, + "start_location": { + "lat": 48.7039886, + "lng": 2.3716268 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.8 km", + "value": 829 + }, + "duration": { + "text": "2 mins", + "value": 116 + }, + "end_location": { + "lat": 48.6828291, + "lng": 2.3771681 + }, + "html_instructions": "Keep left to continue on Av. de la Cr de France/N7
Continue to follow N7
", + "maneuver": "keep-left", + "polyline": { + "points": "kqdhH{anMxAm@LG@?\\Sd@UzA{@VOf@c@fAeAjAmAf@g@PSNQp@y@Z_@\\_@`@c@TWj@u@^g@h@q@@?RWd@k@TWl@u@h@q@Za@jAyA`AiAp@y@LQ" + }, + "start_location": { + "lat": 48.6890215, + "lng": 2.3710222 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.4 km", + "value": 413 + }, + "duration": { + "text": "1 min", + "value": 34 + }, + "end_location": { + "lat": 48.6799071, + "lng": 2.3806212 + }, + "html_instructions": "Keep left", + "maneuver": "keep-left", + "polyline": { + "points": "ujchHihoMLWn@y@FIHI\\c@Za@f@m@jAwAZa@Za@rAcBt@_ARUTYf@m@b@i@BELI" + }, + "start_location": { + "lat": 48.6828291, + "lng": 2.3771681 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.2 km", + "value": 193 + }, + "duration": { + "text": "1 min", + "value": 34 + }, + "end_location": { + "lat": 48.6785366, + "lng": 2.3822313 + }, + "html_instructions": "Merge onto Av. du Général de Gaulle/N7", + "maneuver": "merge", + "polyline": { + "points": "mxbhH{}oMzD{ELOfAuA" + }, + "start_location": { + "lat": 48.6799071, + "lng": 2.3806212 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.5 km", + "value": 476 + }, + "duration": { + "text": "2 mins", + "value": 108 + }, + "end_location": { + "lat": 48.68178, + "lng": 2.385035 + }, + "html_instructions": "Turn left onto Rue Carnot", + "maneuver": "turn-left", + "polyline": { + "points": "{obhH}gpMKSQYS[IQCQ?SAOAu@?SAI?CAEEIIYACAACCA?A?A?A?C@EBIFIHURA@C?A?A?AACCQWQQY[IIGEMGGCSKuAi@[MgAc@m@U]KQCQCWCC?GAGAAAAAA??AAACMAE?C?C?E@G?K" + }, + "start_location": { + "lat": 48.6785366, + "lng": 2.3822313 + }, + "travel_mode": "DRIVING" + }, + { + "distance": { + "text": "0.3 km", + "value": 305 + }, + "duration": { + "text": "1 min", + "value": 30 + }, + "end_location": { + "lat": 48.67910939999999, + "lng": 2.3859466 + }, + "html_instructions": "Turn right onto Quai de Châtillon/D931
Destination will be on the left
", + "maneuver": "turn-right", + "polyline": { + "points": "cdchHmypMXGr@IBAbBY~A[bAYNERGx@YrAe@HE" + }, + "start_location": { + "lat": 48.68178, + "lng": 2.385035 + }, + "travel_mode": "DRIVING" + } +] \ No newline at end of file diff --git a/WebControl/main.py b/WebControl/main.py index b2ff45e..2e73320 100644 --- a/WebControl/main.py +++ b/WebControl/main.py @@ -1,155 +1,180 @@ #!/usr/bin/python # -*- coding:utf-8 -*- -from bottle import get,post,run,route,request,template,static_file,TEMPLATE_PATH +from bottle import get,redirect,post,run,route,request,response,template,static_file,TEMPLATE_PATH from joyit_mfrc522 import SimpleMFRC522 from modules.AlphaBot import AlphaBot -import threading, socket, os, sys, time, subprocess, ssl +import threading, socket, os, sys, time, subprocess, ssl, json,signal TEMPLATE_PATH.append('/home/christian/WebControl/') -car = AlphaBot() +certfile = '/home/christian/WebControl/ssl/cert.pem' +keyfile = '/home/christian/WebControl/ssl/key.pem' +Ab = AlphaBot() script_process = None -speed = 50 # Valeur de vitesse par défaut +duration = 1 +speed = 30 +# Stocke les dernières données reçues +validation_results = {"name": None, "confidence": None} @get("/") def index(): - return template('templates/index') + # Chemin vers le fichier JSON + json_file_path = '/home/christian/WebControl/logs/resultats_tests.json' + + # Lire le fichier JSON + with open(json_file_path, 'r') as f: + data = json.load(f) + last_15_results = data[-10:][::-1] + return template('templates/index', message="", results=last_15_results) + @get("/tests") def tests(): return template("templates/tests") -# Test programmes -@post('/servo_motor') -def servo_motor(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'tests/servo_motor.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' -@post('/motor_speed_move') -def motor_speed_move(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'tests/motor_speed_move.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' -@post('/infrared_obstacle_module') -def infrared_obstacle_module(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'tests/infrared_obstacle_module.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' -@post('/lidar_module') -def lidar_module(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['sudo', 'python3', 'tests/lidar_module.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' -@post('/rfid_read_write_module') -def rfid_read_write_module(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'tests/rfid_read_write_module.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' +@get("/access") +def show_validation(): + # Rendre le fichier HTML access.html avec les résultats actuels + return template("templates/access",name=validation_results["name"],confidence=validation_results["confidence"],status="Aucune validation reçue" if not validation_results["name"] else "Succès") -# Fonctionnalité programmes -@post('/infrared_tracking_objects') -def infrared_tracking_objects(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'apps/infrared_tracking_objects.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' -@post('/infrared_obstacle_avoidance') -def infrared_obstacle_avoidance(): - global script_process # Assurez-vous d'utiliser la variable globale script_process dans cette fonction - action = request.forms.get('action') - if action == 'start': - script_process = subprocess.Popen(['python3', 'apps/infrared_obstacle_avoidance.py']) - elif action == 'stop' and script_process is not None: - script_process.terminate() # Arrêter le script si script_process est défini - return 'OK' +@post("/access") +def access(): + global validation_results + # Récupère les données de la requête + data = request.json + name = data.get('name') + confidence = data.get('confidence') + # Met à jour les résultats + validation_results["name"] = name + validation_results["confidence"] = confidence + # Affiche les résultats dans la console + print(f"Validation received: Name: {name}, Confidence: {confidence}") + # Répond avec un succès + response.status = 200 + return {"status": "success"} + +@post("/restartPi") +def restart_pi(): + try: + # Commande pour redémarrer le Raspberry Pi + subprocess.run('sudo reboot', shell=True, check=True) + message = "Redémarrage en cours..." + except Exception as e: + # Gestion des erreurs, retour d'un message d'erreur si la commande échoue + message = f"Erreur lors du redémarrage: {str(e)}" + # Retourne un message au client + return template('{{message}}
', message=message) + +@post("/restartMotion") +def restart_motion(): + try: + # Arrêter Motion si en cours + subprocess.run('sudo pkill -f motion', shell=True, check=True) + # Redémarrer Motion + subprocess.run('sudo /usr/bin/motion', shell=True, check=True) + message = 'Motion redémarré' + except subprocess.CalledProcessError as e: + # Gestion des erreurs si les commandes échouent + message = f"Erreur lors du redémarrage de Motion: {str(e)}" + # Retourner un message au client + return template('{{message}}
', message=message) @post("/cmd") def cmd(): - global speed # Déclarer speed comme variable globale pour pouvoir y accéder dans cette fonction + global speed, script_process + response.content_type = 'application/json' + + # Lecture du code de commande depuis la requête code = request.body.read().decode() - speed_str = request.POST.get('speed') + + # Récupération de la vitesse si elle est présente + speed_str = request.forms.get('speed') if speed_str is not None: try: speed = int(speed_str) if 0 <= speed <= 100: - car.setPWMA(speed) - car.setPWMB(speed) + Ab.setPWMA(speed) + Ab.setPWMB(speed) print("Vitesse définie à", speed) + else: + return json.dumps({"error": "La vitesse doit être comprise entre 0 et 100."}) except ValueError: - print("") # Invalid speed value + return json.dumps({"error": "La vitesse doit être un nombre entier."}) + try: + if code == "stop": + Ab.stop(duration) + message = 'Voiture arrêtée' + elif code == "forward": + Ab.forward(duration, speed) + message = 'Voiture en avant' + elif code == "backward": + Ab.backward(duration, speed) + message = 'Voiture en arrière' + elif code == "turnleft": + Ab.left(duration, speed) + message = 'Voiture tourne à gauche' + elif code == "turnright": + Ab.right(duration, speed) + message = 'Voiture tourne à droite' + # TESTS + elif code == "testServo": + script_process = subprocess.Popen(['python3', 'tests/servo_motor.py']) + message = 'Servo moteur OK' + elif code == "appRFIDCarDoor": + script_process = subprocess.Popen(['python3', 'tests/rfid_open_door.py']) + message = 'Module RFID Door OK' + elif code == "testRotor": + script_process = subprocess.Popen(['python3', 'tests/motor_speed_move.py']) + message = 'Moteurs OK' + elif code == "testLidar": + script_process = subprocess.Popen(['sudo', 'python3', 'tests/lidar_module.py']) + message = 'Module Lidar OK' + elif code == "testObstacle": + script_process = subprocess.Popen(['python3', 'tests/infrared_obstacle_module.py']) + message = 'Module IR obstacle OK' + #APPS + elif code == "appRFID": + script_process = subprocess.Popen(['python3', 'apps/rfid_read_write_module.py']) + message = 'Lecture et écriture RFID OK' + elif code == "appLidarSpeed": + script_process = subprocess.Popen(['sudo', 'python3', 'apps/lidar_speed_move.py']) + message = 'Régulation de la vitesse par Lidar OK' + elif code == "appEmergencyStop": + script_process = subprocess.Popen(['python3', 'apps/infrared_obstacle_avoidance.py']) + message = 'Emergency STOP par IR OK' + else: + return json.dumps({"error": f"Commande inconnue ({code})"}) + except Exception as e: + return json.dumps({"error": str(e)}) + return json.dumps({"message": message}) - if code == "stop": - car.stop() - elif code == "forward": - car.forward(speed) - elif code == "backward": - car.backward(speed) - elif code == "turnleft": - car.left(speed) - elif code == "turnright": - car.right(speed) - else: - print("") # Unknown command - return "OK" - -@route('/') +@route('/') def server_static(filename): return static_file(filename, root='./') -@route('/templates/') +@route('/templates/') def server_templates(filename): return static_file(filename, root='./templates/') -@route('/images/') +@route('/images/') def server_images(filename): return static_file(filename, root='./images/') -@route('/fonts/') +@route('/fonts/') def server_fonts(filename): return static_file(filename, root='./fonts/') -@route('/js/') +@route('/js/') def server_js(filename): return static_file(filename, root='./js/') -@route('/css/') +@route('/css/') def server_css(filename): return static_file(filename, root='./css/') -@route('/modules/') +@route('/modules/') def server_modules(filename): return static_file(filename, root='./modules/') -@route('/apps/') +@route('/apps/') def server_apps(filename): return static_file(filename, root='./apps/') -@route('/tests/') +@route('/tests/') def server_tests(filename): return static_file(filename, root='./tests/') -# Chemins vers le certificat SSL et la clé privée -certfile = '/home/christian/WebControl/ssl/cert.pem' -keyfile = '/home/christian/WebControl/ssl/key.pem' - -# Créez un contexte SSL -ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) -ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile) - def wait_for_network(): while True: try: @@ -159,9 +184,14 @@ def wait_for_network(): s.close() return localhost except OSError: - print("Le réseau est inaccessible. Réessai dans 5 secondes...") + print("Le réseau est inaccessible. Réessayer dans 5 secondes...") time.sleep(5) localhost = wait_for_network() -run(host=localhost, port=8000, server='wsgiref', debug=True, ssl_context=ssl_context) +# Créez un contexte SSL +# ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2) +# ssl_context.load_cert_chain(certfile=certfile, keyfile=keyfile) +# run(host=localhost, port=8000, server='wsgiref', debug=True, ssl_context=ssl_context) + +run(host=localhost, port=8000, server='wsgiref', debug=True) diff --git a/WebControl/modules/AlphaBot.py b/WebControl/modules/AlphaBot.py index 8c54932..541352f 100644 --- a/WebControl/modules/AlphaBot.py +++ b/WebControl/modules/AlphaBot.py @@ -1,21 +1,30 @@ +import time,json, os, serial, threading, queue import RPi.GPIO as GPIO -import time -import os +from datetime import datetime class AlphaBot(object): - def __init__(self, in1=12, in2=13, ena=6, in3=20, in4=21, enb=26): - self.IN1 = in1 - self.IN2 = in2 - self.IN3 = in3 - self.IN4 = in4 - self.ENA = ena - self.ENB = enb - # Définition des broches module d'évitement d'obstacles - DAOUT_PIN = 19 - AOUT_PIN = 16 + def __init__(self): + self.LIDAR_MODULE = serial.Serial('/dev/ttyAMA0', 115200, timeout=1) # SERIAL + self.LIDAR_MODULE.write(b'\x42\x57\x02\x00\x00\x00\x01\x06') + self.RED_LIGHT = 17 + self.OBSTACLE_PIN = 16 + self.SERVO_PIN = 27 + self.IN1 = 12 + self.IN2 = 13 + self.ENA = 6 + self.IN3 = 20 + self.IN4 = 21 + self.ENB = 26 + speed = 30 + self.stop_event_obstacle = threading.Event() + self.stop_event_vitesse = threading.Event() + self.vitesse_queue = queue.Queue() GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) + GPIO.setup(self.OBSTACLE_PIN, GPIO.IN, GPIO.PUD_UP) + GPIO.setup(self.SERVO_PIN, GPIO.OUT) + GPIO.setup(self.RED_LIGHT, GPIO.OUT) GPIO.setup(self.IN1, GPIO.OUT) GPIO.setup(self.IN2, GPIO.OUT) GPIO.setup(self.IN3, GPIO.OUT) @@ -24,52 +33,267 @@ class AlphaBot(object): GPIO.setup(self.ENB, GPIO.OUT) self.PWMA = GPIO.PWM(self.ENA, 500) # Utilisation d'une fréquence de 500 Hz pour le PWM self.PWMB = GPIO.PWM(self.ENB, 500) + self.PWMSERVO = GPIO.PWM(self.SERVO_PIN, 50) # Utilisation d'une fréquence de 50 Hz pour le servo self.PWMA.start(0) # Démarre avec un rapport cyclique de 0 (moteurs arrêtés) self.PWMB.start(0) + self.PWMSERVO.start(0) + GPIO.output(self.RED_LIGHT, GPIO.HIGH) - def stop(self): + + def ajuster_vitesse_selon_distance(self, distance, vitesse_max=70, vitesse_min=20): + if distance < 20: # Distance critique, arrêt + vitesse = 0 + elif distance < 50: # Très proche, ralentir + vitesse = vitesse_min + else: # Vitesse normale + vitesse = vitesse_max * (distance / 100) + vitesse = max(vitesse_min, min(vitesse, vitesse_max)) + return vitesse + + def set_angle(self, angle): + if 0 <= angle <= 180: + pulse_width_ms = (angle / 180) * (2 - 1) + 1 + duty_cycle = (pulse_width_ms / 20) * 100 + self.PWMSERVO.ChangeDutyCycle(duty_cycle) + # Calcul du temps nécessaire pour atteindre l'angle donné + movement_time = (angle / 60) * 0.15 # 0.12 sec pour 60 degrés + time.sleep(movement_time) + else: + print("Angle hors de portée. Le rapport cyclique doit être compris entre 2,5 et 12,5.") + + def blink_led(self, blink_duration=0.2): + self.blinking = True + while self.blinking: # Continue tant que blinking est True + GPIO.output(self.RED_LIGHT, GPIO.HIGH) + time.sleep(blink_duration) + GPIO.output(self.RED_LIGHT, GPIO.LOW) + time.sleep(blink_duration) + GPIO.output(self.RED_LIGHT, GPIO.LOW) + + # Fonction pour les manœuvres non spécifiées + def maneuver_unspecified(self, duration): + GPIO.output(self.RED_LIGHT, GPIO.HIGH) + print("Manoeuvre non spécifiée") + time.sleep(duration) + + def stop(self, duration): + GPIO.output(self.RED_LIGHT, GPIO.HIGH) GPIO.output(self.IN1, GPIO.LOW) GPIO.output(self.IN2, GPIO.LOW) GPIO.output(self.IN3, GPIO.LOW) GPIO.output(self.IN4, GPIO.LOW) self.PWMA.ChangeDutyCycle(0) self.PWMB.ChangeDutyCycle(0) - print("Le robot est arreté") - - def forward(self, speed): - GPIO.output(self.IN1, GPIO.HIGH) + print(f"Arrêt durant {duration} secondes") + time.sleep(duration) + GPIO.output(self.RED_LIGHT, GPIO.LOW) + + def emergencystop(self): + # Lancer le clignotement dans un thread séparé + blink_thread = threading.Thread(target=self.blink_led) + blink_thread.start() + GPIO.output(self.IN1, GPIO.LOW) GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(0) + self.PWMB.ChangeDutyCycle(0) + print("Arrêt d'urgence !") + time.sleep(0.1) + # Stopper le clignotement de la LED + self.blinking = False + blink_thread.join() # Attendre que le thread de clignotement se termine + + +# FORWARD MOVE + def forward(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) GPIO.output(self.IN3, GPIO.HIGH) GPIO.output(self.IN4, GPIO.LOW) self.PWMA.ChangeDutyCycle(speed) self.PWMB.ChangeDutyCycle(speed) + print(f"Avancer durant {duration} secondes à une vitesse de", speed) + time.sleep(duration) - print("Le robot avance avec une vitesse de", speed) + def ramp_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 1.5) + print(f"Traitement pour prendre la rampe de gauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def fork_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 1.1) + print(f"Traitement pour prendre la fourche de gauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def ramp_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed * 1.5) + self.PWMB.ChangeDutyCycle(speed) + print(f"Traitement pour prendre la rampe de droite durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) - def backward(self, speed): + def fork_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 1.1) + print(f"Traitement pour prendre la fourche de droite durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def merge(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed * 0.8) + self.PWMB.ChangeDutyCycle(speed * 0.8) + print(f"Traitement pour fusionner dans le trafic durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) +# BACKWARD MOVE + def backward(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) + GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.HIGH) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed) + print(f"Reculer durant {duration} secondes à une vitesse de", speed) + time.sleep(duration) + +# LEFT MOVE + def left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) GPIO.output(self.IN1, GPIO.LOW) GPIO.output(self.IN2, GPIO.HIGH) GPIO.output(self.IN3, GPIO.LOW) GPIO.output(self.IN4, GPIO.HIGH) self.PWMA.ChangeDutyCycle(speed) self.PWMB.ChangeDutyCycle(speed) - print("Le robot recul avec une vitesse de", speed) - - def left(self, speed): - GPIO.output(self.IN1, GPIO.HIGH) - GPIO.output(self.IN2, GPIO.LOW) - GPIO.output(self.IN3, GPIO.LOW) - GPIO.output(self.IN4, GPIO.LOW) - self.PWMA.ChangeDutyCycle(speed) - print("Le robot tourne à guauche avec une vitesse de", speed) - - def right(self, speed): + print(f"Tourner à guauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def turn_slight_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.HIGH) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 0.1) + print(f"Traitement pour tourner légèrement à gauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def turn_sharp_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.HIGH) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 1) + print(f"Traitement pour tourner brusquement à gauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def u_turn_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.HIGH) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed) + print(f"Traitement pour faire demi-tour à gauche durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration * 2) + + def roundabout_left(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.LOW) + GPIO.output(self.IN2, GPIO.HIGH) + GPIO.output(self.IN3, GPIO.LOW) + GPIO.output(self.IN4, GPIO.HIGH) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 0.5) + print(f"Traitement pour tourner à gauche au rond-point durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + +# RIGHT MOVE + def right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) GPIO.output(self.IN2, GPIO.LOW) GPIO.output(self.IN3, GPIO.HIGH) GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) self.PWMB.ChangeDutyCycle(speed) - print("Le robot tourne à droite avec une vitesse de", speed) + print(f"Tourner à droite durant {duration} secondes à une vitesse de", speed) + time.sleep(duration) + + def turn_slight_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) + GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed * 0.1) + self.PWMB.ChangeDutyCycle(speed) + print(f"Traitement pour tourner légèrement à droite durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def turn_sharp_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) + GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed * 1) + print(f"Traitement pour tourner brusquement à droite durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) + + def u_turn_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) + GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed) + self.PWMB.ChangeDutyCycle(speed) + print(f"Traitement pour faire demi-tour à droite durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration * 2) + + def roundabout_right(self, duration, speed): + GPIO.output(self.RED_LIGHT, GPIO.LOW) + GPIO.output(self.IN1, GPIO.HIGH) + GPIO.output(self.IN2, GPIO.LOW) + GPIO.output(self.IN3, GPIO.HIGH) + GPIO.output(self.IN4, GPIO.LOW) + self.PWMA.ChangeDutyCycle(speed * 0.5) + self.PWMB.ChangeDutyCycle(speed) + print(f"Traitement pour tourner à droite au rond-point durant {duration} secondes à une vitesse de", speed,"MPH") + time.sleep(duration) def setPWMA(self, value): """ @@ -94,26 +318,75 @@ class AlphaBot(object): self.PWMA.ChangeDutyCycle(left) self.PWMB.ChangeDutyCycle(right) - def objetrack_ir(self): - os.system('sudo python3 ~/AppControl/Infrared_Tracking_Objects.py') +# Fonction pour surveiller les obstacle en arrière-plan + def monitor_obstacle(self): + global emergency_stop + while not self.stop_event_obstacle.is_set(): + DR_status = GPIO.input(self.OBSTACLE_PIN) + if DR_status == 0: # Obstacle détecté + self.emergencystop() + emergency_stop = True + while GPIO.input(self.OBSTACLE_PIN) == 0: # Attendre que l'obstacle soit dégagé + time.sleep(0.1) + print("Obstacle dégagé. Attente de 5 secondes avant de reprendre.") + emergency_stop = False + time.sleep(0.05) # Pause légère pour éviter la surcharge du CPU - def linetrack_ir(self): - os.system('sudo python3 ~/AppControl/Infrared_Line_Tracking.py') + def monitor_vitesse(self): + try: + while not self.stop_event_vitesse.is_set(): + if self.LIDAR_MODULE.in_waiting >= 9: + if b'Y' == self.LIDAR_MODULE.read() and b'Y' == self.LIDAR_MODULE.read(): + Dist_L = self.LIDAR_MODULE.read() + Dist_H = self.LIDAR_MODULE.read() + Dist_Total = (Dist_H[0] * 256) + Dist_L[0] + for i in range(0, 5): + self.LIDAR_MODULE.read() # Lecture et ignore des octets supplémentaires + print("Distance à l'avant du véhicule:", Dist_Total, "cm") + # Définir les paramètres de vitesse + vitesse_max = 50 # Vitesse maximale en unités (à ajuster) + distance_min = 10 # Distance minimale pour une vitesse de 0 (en cm) + # Ajuster la vitesse en fonction de la distance mesurée + if Dist_Total <= distance_min: + vitesse_ajustee = 0 # Arrêter si trop proche + elif Dist_Total > 100: # Distance maximale où la vitesse est maximale + vitesse_ajustee = vitesse_max + else: + # Calculer la vitesse en fonction de la distance + vitesse_ajustee = int(vitesse_max * (Dist_Total - distance_min) / (100 - distance_min)) + # Mettre la vitesse ajustée dans la queue + self.vitesse_queue.put(vitesse_ajustee) + except Exception as e: + print(f"Erreur lors de la mesure de la vitesse: {e}") + # En cas d'erreur, vous pouvez décider de placer une valeur par défaut dans la queue + self.vitesse_queue.put(None) - def objetavoid_ir(self): - os.system('sudo python3 ~/AppControl/Infrared_Obstacle_Avoidance.py') + def cleanup(self): + GPIO.cleanup() + print("Nettoyage des GPIO effectué.") - def obstacleavoid_ultrason(self): - os.system('sudo python3 ~/AppControl/Ultrasonic_Obstacle_Avoidance.py') - - def move_ultrason(self): - os.system('sudo python3 ~/AppControl/Ultrasonic_Ranging.py') - - def control_ir(self): - os.system('sudo python3 ~/AppControl/Infrared_Remote_Control.py') - - def face_ia(self): - os.system('sudo python3 ~/AppControl/visage_camera_raspberry.py') - - def line_ia(self): - os.system('sudo python3 ~/AppControl/visage_camera_v2_raspberry.py') \ No newline at end of file + def enregistrer_resultats(self, nom_script, fonctionnement_ok, status): + # Préparer les données à enregistrer + nouveau_resultat = { + 'date': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), + 'nom': nom_script, + 'fonctionnement_ok': fonctionnement_ok, + 'status': status + } + # Chemin vers le fichier de logs + fichier_logs = './logs/resultats_tests.json' + # Charger les données existantes si le fichier existe + if os.path.exists(fichier_logs): + with open(fichier_logs, 'r') as f: + try: + resultats = json.load(f) + except json.JSONDecodeError: + resultats = [] + else: + resultats = [] + # Ajouter le nouveau résultat + resultats.append(nouveau_resultat) + # Enregistrer les résultats mis à jour dans le fichier JSON + with open(fichier_logs, 'w') as f: + json.dump(resultats, f, indent=4) + print("Résultats enregistrés avec succès.") \ No newline at end of file diff --git a/WebControl/modules/MFRC522-python.zip b/WebControl/modules/MFRC522-python.zip deleted file mode 100644 index 177364d06d60853a14d89ba512a9a768ad36ab2e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 99523 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 A3jhEB diff --git a/WebControl/modules/SimpleMFRC522.py b/WebControl/modules/SimpleMFRC522.py new file mode 100644 index 0000000..06a3d9a --- /dev/null +++ b/WebControl/modules/SimpleMFRC522.py @@ -0,0 +1,89 @@ +# Code by Simon Monk https://github.com/simonmonk/ + +from joyit_mfrc522 import MFRC522 + +class SimpleMFRC522: + + READER = None + + KEY = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] + BLOCK_ADDRS = [8, 9, 10] + + def __init__(self): + self.READER = MFRC522() + + def read(self): + id, text = self.read_no_block() + while not id: + id, text = self.read_no_block() + return id, text + + def read_id(self): + id = self.read_id_no_block() + while not id: + id = self.read_id_no_block() + return id + + def read_id_no_block(self): + (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) + if status != self.READER.MI_OK: + return None + (status, uid) = self.READER.MFRC522_Anticoll() + if status != self.READER.MI_OK: + return None + return self.uid_to_num(uid) + + def read_no_block(self): + (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) + if status != self.READER.MI_OK: + return None, None + (status, uid) = self.READER.MFRC522_Anticoll() + if status != self.READER.MI_OK: + return None, None + id = self.uid_to_num(uid) + self.READER.MFRC522_SelectTag(uid) + status = self.READER.MFRC522_Auth(self.READER.PICC_AUTHENT1A, 11, self.KEY, uid) + data = [] + text_read = '' + if status == self.READER.MI_OK: + for block_num in self.BLOCK_ADDRS: + block = self.READER.MFRC522_Read(block_num) + if block: + data += block + if data: + text_read = ''.join(chr(i) for i in data) + self.READER.MFRC522_StopCrypto1() + return id, text_read + + def write(self, text): + id, text_in = self.write_no_block(text) + while not id: + id, text_in = self.write_no_block(text) + return id, text_in + + def write_no_block(self, text): + (status, TagType) = self.READER.MFRC522_Request(self.READER.PICC_REQIDL) + if status != self.READER.MI_OK: + return None, None + (status, uid) = self.READER.MFRC522_Anticoll() + if status != self.READER.MI_OK: + return None, None + id = self.uid_to_num(uid) + self.READER.MFRC522_SelectTag(uid) + status = self.READER.MFRC522_Auth(self.READER.PICC_AUTHENT1A, 11, self.KEY, uid) + self.READER.MFRC522_Read(11) + if status == self.READER.MI_OK: + data = bytearray() + data.extend(bytearray(text.ljust(len(self.BLOCK_ADDRS) * 16).encode('ascii'))) + i = 0 + for block_num in self.BLOCK_ADDRS: + self.READER.MFRC522_Write(block_num, data[(i*16):(i+1)*16]) + i += 1 + self.READER.MFRC522_StopCrypto1() + return id, text[0:(len(self.BLOCK_ADDRS) * 16)] + + def uid_to_num(self, uid): + n = 0 + for i in range(0, 5): + n = n * 256 + uid[i] + return n diff --git a/WebControl/modules/__pycache__/AlphaBot.cpython-39.pyc b/WebControl/modules/__pycache__/AlphaBot.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..5d5e0f2eb394ba2417b4650f72b26b7cd60b8425 GIT binary patch literal 12372 zcmdT~TWlNId7djdq^PT9TfUDs_1bjSlI-10w%*Okk|kdPTXJl99kWTMW1f*jnH0zDRKfubmie*c-_ zkfKQ6c3UGP_@8rT&N;*L{nt6?xBL6E5 zsFVw`Xe$Lplxjg0rB={HsTXunrYh+|TBb2d*{B!=Lzb>eOl8_964RW_Q?-y~@*OF! z@8Aj2d|nO>X8Vp`syIcu(*9A=xP+gFNhC+2e}JdUO!-8@(=Rifr9P4I{4_IgMQ5`t z%ldF7#d544SJG^N4WcyI5F19BVIyoG$}AgY`%(6>1MDEm92;YYQ1-LK>I@+0zcCM{` z6wlAF;Y}c89mBt+b}nuokJ~9WBJQ8Sy<;0D+ehm`{dimbM6-@DCvlI~@CL1kN#NM% zd_6b8oV5wxe=>b@da@+_jV$dD?;!qZ68&o6dj{Gw_lS#fYG)Y5&Jd9!L~=y>iKK{( z64_7WFp=XRS4#hm33o1_%EioI3R9lLOLn=Cx+BUkcjNl(^lj_r!tC7}bD{p2mwYG8 z+@71YZd|{5Z86L(%-mU=zIm z8GnU4HY>Typ+2|fxPG|L^Q$$>p}JLl;Q4m3?1Uq27uWD)&vQckQQ!n9z9EYK__7sU z)vn&UzEDVej$f%VCsb!H-z@Z@_1NYv9_EEQ8bK{o@DEeB?#^0wZxz&qyNd<&*1emd z1~M(^OlY7kR)ZnF&HXS1yla6UYS*yvyb@}jQ(nT&n&Yr7iH`%s{~DiIsaBkc;tDT$ ze#v$x?l})GS6!c1%MdOtSp*+QRU2AA$oae<8gdlMtg$z>yD79jL3{rCQI)4k7V7!5j z?G~M|ugN`hDYP0Tw~&tS2wWpFL1T~GtAXb`+-i;l7pkt+obk)(;|+jFvH=Y717bsR z{d9uKv&R=nm6{*IhTMrTjnTp%79` z2UakltI~$tP=x`ISqj(F0z(+phDKLi!`GPcl*}tBer8@kxbssykQ2KiSV>8Dh)K(D zi_i8{a0{(zce(7CD^>29%rR?K?r(27i#%gL27z2*bip;!*r85wf$Knoo$dVUcw04Z)k3#3uoS7l&_G#o{z3leqcG^5Z21 zhtT_`?N*&&4RYaDUDK;=Zxu^RB}i31-F1~;!SB^xMViH2N1maw~9@7}BZQ_QeuwbANfv{rSo`ly}iXs0{cMzam%G8>3Lg#t^f zea*U`V=#$7hRT1Y3N#Vn#KP3VTRc&qt3_%Zka3#k9C~OHM6PevGp6Sht1ffA{9spz z4`2)@@4ycd86!fh;>2B!m|WtgiR@+tpQUT$mm(tUr$!!i0oOc|Q-ZtsCEr0ZR_{;1 zr@ni_#YDUQ1mgjc5G^KuDzC#jZm63Q1WVh{0b9z~RwHeS+OTuG+L?}aw%Nwmz74<| zL*C!4`vWY3dT?WiX>^z2Io2?qi$F5ApDB7jNWo<B>*=ZUnm`W0C)P4jB2RXD#`{d1AhM)6N4clu!?#s7Ok(Ek<& zd&F!>8Gu%_Gs-|Hkdo^M5?1XRSR}92{7^mN+4sUO3;#ipYoZS3_J$d_jv4!U zc(|=S3L?}(a7XBdFuX6QAX}=i$b1gZ&$`LuT3hsF%MVHJYKR~lbJ-4xE2u@Li{Hf1P`!EU8lOjvlVRxuF+*dmva{rWjJsW696~_b=G2nz zzivQA@yNeT)!%srkV^no0N52uewzU74JAbEp@8z~3qhH5e?3q(1;q z-@x)-Odc6WRJ&Uqp95l62pBIdulS^pdjyhVEC}SjM6X-@Uk{A27Zi523F!-|HeVzd zUr-uf0Z1WU0>~eB1CqjtT|l<__XaWwDmvoTRs{FC98?p$raU&=F9hatq~1GI^~p~4 zUJ5(}@-BHX+x1MmkNMnQDiwEG$>&I=E*$@#cf*nVK5!gJ1X6VE4dHWqd}k2c4k`Kg z_I5`Q{E9yQwo}B;N8;m!(|DF67e4%@BHeC&$9P~DACmX}t8SoDv@@Prf87fpNL}k?fO_@@ z=X1t3FAUC0=`6pFl?7iRlsZBiKSr&*y|ujk6CMRU1mQ~~IOGF=%PW&V5w7_c-O&^} zd??Z3&QZT^$kH1{K)W@)kbS@d54%nxntUZ-2P249Y#v3A|M(1C$2xFL2EBe*<3POa zO{iU)nHGiW;(bV;56*W%bjdCu2xm^EbdJPUXnGGZ-J$KT-tl8!U__-YqSoBH39Ogk_+_F&G{@UEV0%?MZZ91}XotAWex2RI%O z`cDtu6I8~rP)klb2K5H_b9(c3Z~sNSv5PIjHlNciY`jlG*v%#DB3S%YcYuUHZUs4_ zYj0Sd<8RuRO*?(<{-xVapSa(2#!WeE#)&WdF8%WUrW<_X9k3^c!|k3!fb>7z@QmML z4kwztXV~k(_SIizUe@EhJhZVZ7tTWEfjvcA#Ld5{7SJ? zt^4BM6+gXUFp)j*=&YZ?CcZfJLO;5mB1``$${R>W2aJnR5JJb!3vn8a$?%qIFK=&+ zo727z9TPkG@3xLvY#hRXS;!f1;ywTIEAf8U)>J;rNnFBI$+NInaV8e(B^S9coYIN- z4UobBWFk7bvgqilbs#JbC7Xv|nc3U8ZTo@ODbPceDiUF;Jjwl;A-u&IrIN*7je)O* zjWDWda=m5MI>+teLk541k{5+lBj;29`-BsJM?$}<0%e^mILajz&^9ITqodWlgY(U} zkI3*)4qwf@pDMG`w+E0D6ZZvwmi!bF=Tw%aT^wet>nyX5b|dvr z=09NSdfI&xce4*Q{ud1$tua5{(CPjdvTcxBhw_N@R9;8g-Kw#XX`}_$m3zoM(Ih|n zNAi;aSz1TFWBpA$sjp%DSo%yMIf?o+aTs(@x(_*7H-5)(vr#!IO-7QFo8KXzeg%A_ z`%&@<4pXHa%6|z?g3QMGI`ryUJ{?O-V6JU%t(0hM?_#JFD^bo5q0KLV)X&UuPWHYW z=cd4AR2(l5ud;3a<;#wcrBKBS8aL4| zR4E@TGxu@PsZlCLJ`-hFr0D-zHwsaCt&kP%#j08h<#xi zDLA$p)FNG!qf^gu+=;Ysf@1^Q0g{ z{$y!cT2J4XTxC+a2SL^FB?Wr)-Sd)Hn-o1{2sIL@H0s$%gL5$ck)`OQSNa; zb*q(dc&X|ZN%UOd60Pb(Bv1;2_$(V z(xNODXn93ms`>nPah-n`q%h=Gk-TFER&!m298Nk`O33G-<%aT7A=A9I$H?zb)`ad! zuNq0+8<<>DbI>Jx|2vh|DDMmP0esIYnnIb6<8u9Y@{-VXDvB0q3r(cVe_52%@ zX6f1$$Fjn#Wkq?IsOKysjoRht4xgl9v{l5Xh>%$GD@3jmAs@$Y5xGO;E|HIj+#~W$ zA_XEMj`$YUzD>j;ViTbtfES4{A`X!yA|)cLL>>}xi8P3iLh?T*($Z8>6Y8qs2H9ut zLl8K}Q`xN1ho5fbj1i-+?VC&Lty-Uv#y4y98^;Wd(_ApZ@1x*^Ru(m2_dC@Dq=V5<6H6{bc^(CuG_#s?AFAA-eEg4d+5j{ghQ>od>* literal 0 HcmV?d00001 diff --git a/WebControl/modules/__pycache__/__init__.cpython-39.pyc b/WebControl/modules/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b8103296185fe6f7d2fd1457bf6ec62244ee308a GIT binary patch literal 137 zcmYe~<>g`k0__(XX(0MBh(HF6K#l_t7qb9~6oz01O-8?!3`HPe1o2BxKO;XkRX;hS zD6_aEGciv;JT=KVKd+=HKSw_|KczG$wOBtsJ~J<~BtBlRpz;=n4MfxqWX@+GW&i*~ C;2wzp literal 0 HcmV?d00001 diff --git a/WebControl/modules/joyit_mfrc522/MFRC522.py b/WebControl/modules/joyit_mfrc522/MFRC522.py new file mode 100644 index 0000000..7c55fe3 --- /dev/null +++ b/WebControl/modules/joyit_mfrc522/MFRC522.py @@ -0,0 +1,413 @@ +#!/usr/bin/env python3 +# -*- coding: utf8 -*- +# +# Copyright 2014,2018 Mario Gomez +# +# This file is part of MFRC522-Python +# MFRC522-Python is a simple Python implementation for +# the MFRC522 NFC Card Reader for the Raspberry Pi. +# +# MFRC522-Python is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# MFRC522-Python is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with MFRC522-Python. If not, see . +# +from gpiozero import DigitalOutputDevice +import spidev +import signal +import time +import logging + +class MFRC522: + MAX_LEN = 16 + + PCD_IDLE = 0x00 + PCD_AUTHENT = 0x0E + PCD_RECEIVE = 0x08 + PCD_TRANSMIT = 0x04 + PCD_TRANSCEIVE = 0x0C + PCD_RESETPHASE = 0x0F + PCD_CALCCRC = 0x03 + + PICC_REQIDL = 0x26 + PICC_REQALL = 0x52 + PICC_ANTICOLL = 0x93 + PICC_SElECTTAG = 0x93 + PICC_AUTHENT1A = 0x60 + PICC_AUTHENT1B = 0x61 + PICC_READ = 0x30 + PICC_WRITE = 0xA0 + PICC_DECREMENT = 0xC0 + PICC_INCREMENT = 0xC1 + PICC_RESTORE = 0xC2 + PICC_TRANSFER = 0xB0 + PICC_HALT = 0x50 + + MI_OK = 0 + MI_NOTAGERR = 1 + MI_ERR = 2 + + Reserved00 = 0x00 + CommandReg = 0x01 + CommIEnReg = 0x02 + DivlEnReg = 0x03 + CommIrqReg = 0x04 + DivIrqReg = 0x05 + ErrorReg = 0x06 + Status1Reg = 0x07 + Status2Reg = 0x08 + FIFODataReg = 0x09 + FIFOLevelReg = 0x0A + WaterLevelReg = 0x0B + ControlReg = 0x0C + BitFramingReg = 0x0D + CollReg = 0x0E + Reserved01 = 0x0F + + Reserved10 = 0x10 + ModeReg = 0x11 + TxModeReg = 0x12 + RxModeReg = 0x13 + TxControlReg = 0x14 + TxAutoReg = 0x15 + TxSelReg = 0x16 + RxSelReg = 0x17 + RxThresholdReg = 0x18 + DemodReg = 0x19 + Reserved11 = 0x1A + Reserved12 = 0x1B + MifareReg = 0x1C + Reserved13 = 0x1D + Reserved14 = 0x1E + SerialSpeedReg = 0x1F + + Reserved20 = 0x20 + CRCResultRegM = 0x21 + CRCResultRegL = 0x22 + Reserved21 = 0x23 + ModWidthReg = 0x24 + Reserved22 = 0x25 + RFCfgReg = 0x26 + GsNReg = 0x27 + CWGsPReg = 0x28 + ModGsPReg = 0x29 + TModeReg = 0x2A + TPrescalerReg = 0x2B + TReloadRegH = 0x2C + TReloadRegL = 0x2D + TCounterValueRegH = 0x2E + TCounterValueRegL = 0x2F + + Reserved30 = 0x30 + TestSel1Reg = 0x31 + TestSel2Reg = 0x32 + TestPinEnReg = 0x33 + TestPinValueReg = 0x34 + TestBusReg = 0x35 + AutoTestReg = 0x36 + VersionReg = 0x37 + AnalogTestReg = 0x38 + TestDAC1Reg = 0x39 + TestDAC2Reg = 0x3A + TestADCReg = 0x3B + Reserved31 = 0x3C + Reserved32 = 0x3D + Reserved33 = 0x3E + Reserved34 = 0x3F + + serNum = [] + + def __init__(self, bus=0, device=0, spd=1000000, pin_mode=10, pin_rst=-1, debugLevel='WARNING'): + self.spi = spidev.SpiDev() + self.spi.open(bus, device) + self.spi.max_speed_hz = spd + + self.logger = logging.getLogger('mfrc522Logger') + self.logger.addHandler(logging.StreamHandler()) + level = logging.getLevelName(debugLevel) + self.logger.setLevel(level) + + if pin_rst == -1: + pin_rst = 15 + + self._RST = DigitalOutputDevice(pin_rst, initial_value=True) + self.MFRC522_Init() + + def MFRC522_Reset(self): + self.Write_MFRC522(self.CommandReg, self.PCD_RESETPHASE) + + def Write_MFRC522(self, addr, val): + val = self.spi.xfer2([(addr << 1) & 0x7E, val]) + + def Read_MFRC522(self, addr): + val = self.spi.xfer2([((addr << 1) & 0x7E) | 0x80, 0]) + return val[1] + + def Close_MFRC522(self): + self.spi.close() + + def SetBitMask(self, reg, mask): + tmp = self.Read_MFRC522(reg) + self.Write_MFRC522(reg, tmp | mask) + + def ClearBitMask(self, reg, mask): + tmp = self.Read_MFRC522(reg) + self.Write_MFRC522(reg, tmp & (~mask)) + + def AntennaOn(self): + temp = self.Read_MFRC522(self.TxControlReg) + if (~(temp & 0x03)): + self.SetBitMask(self.TxControlReg, 0x03) + + def AntennaOff(self): + self.ClearBitMask(self.TxControlReg, 0x03) + + def MFRC522_ToCard(self, command, sendData): + backData = [] + backLen = 0 + status = self.MI_ERR + irqEn = 0x00 + waitIRq = 0x00 + lastBits = None + n = 0 + + if command == self.PCD_AUTHENT: + irqEn = 0x12 + waitIRq = 0x10 + if command == self.PCD_TRANSCEIVE: + irqEn = 0x77 + waitIRq = 0x30 + + self.Write_MFRC522(self.CommIEnReg, irqEn | 0x80) + self.ClearBitMask(self.CommIrqReg, 0x80) + self.SetBitMask(self.FIFOLevelReg, 0x80) + + self.Write_MFRC522(self.CommandReg, self.PCD_IDLE) + + for i in range(len(sendData)): + self.Write_MFRC522(self.FIFODataReg, sendData[i]) + + self.Write_MFRC522(self.CommandReg, command) + + if command == self.PCD_TRANSCEIVE: + self.SetBitMask(self.BitFramingReg, 0x80) + + i = 2000 + while True: + n = self.Read_MFRC522(self.CommIrqReg) + i -= 1 + if ~((i != 0) and ~(n & 0x01) and ~(n & waitIRq)): + break + + self.ClearBitMask(self.BitFramingReg, 0x80) + + if i != 0: + if (self.Read_MFRC522(self.ErrorReg) & 0x1B) == 0x00: + status = self.MI_OK + + if n & irqEn & 0x01: + status = self.MI_NOTAGERR + + if command == self.PCD_TRANSCEIVE: + n = self.Read_MFRC522(self.FIFOLevelReg) + lastBits = self.Read_MFRC522(self.ControlReg) & 0x07 + if lastBits != 0: + backLen = (n - 1) * 8 + lastBits + else: + backLen = n * 8 + + if n == 0: + n = 1 + if n > self.MAX_LEN: + n = self.MAX_LEN + + for i in range(n): + backData.append(self.Read_MFRC522(self.FIFODataReg)) + else: + status = self.MI_ERR + + return (status, backData, backLen) + + def MFRC522_Request(self, reqMode): + status = None + backBits = None + TagType = [] + + self.Write_MFRC522(self.BitFramingReg, 0x07) + + TagType.append(reqMode) + (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, TagType) + + if ((status != self.MI_OK) | (backBits != 0x10)): + status = self.MI_ERR + + return (status, backBits) + + def MFRC522_Anticoll(self): + backData = [] + serNumCheck = 0 + + serNum = [] + + self.Write_MFRC522(self.BitFramingReg, 0x00) + + serNum.append(self.PICC_ANTICOLL) + serNum.append(0x20) + + (status, backData, backBits) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, serNum) + + if (status == self.MI_OK): + i = 0 + if len(backData) == 5: + for i in range(4): + serNumCheck = serNumCheck ^ backData[i] + if serNumCheck != backData[4]: + status = self.MI_ERR + else: + status = self.MI_ERR + + return (status, backData) + + def CalulateCRC(self, pIndata): + self.ClearBitMask(self.DivIrqReg, 0x04) + self.SetBitMask(self.FIFOLevelReg, 0x80) + + for i in range(len(pIndata)): + self.Write_MFRC522(self.FIFODataReg, pIndata[i]) + + self.Write_MFRC522(self.CommandReg, self.PCD_CALCCRC) + i = 0xFF + while True: + n = self.Read_MFRC522(self.DivIrqReg) + i -= 1 + if not ((i != 0) and not (n & 0x04)): + break + pOutData = [] + pOutData.append(self.Read_MFRC522(self.CRCResultRegL)) + pOutData.append(self.Read_MFRC522(self.CRCResultRegM)) + return pOutData + + def MFRC522_SelectTag(self, serNum): + backData = [] + buf = [] + buf.append(self.PICC_SElECTTAG) + buf.append(0x70) + + for i in range(5): + buf.append(serNum[i]) + + pOut = self.CalulateCRC(buf) + buf.append(pOut[0]) + buf.append(pOut[1]) + (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf) + + if (status == self.MI_OK) and (backLen == 0x18): + self.logger.debug("Size: " + str(backData[0])) + return backData[0] + else: + return 0 + + def MFRC522_Auth(self, authMode, BlockAddr, Sectorkey, serNum): + buff = [] + + # First byte should be the authMode (A or B) + buff.append(authMode) + + # Second byte is the trailerBlock (usually 7) + buff.append(BlockAddr) + + # Now we need to append the authKey which usually is 6 bytes of 0xFF + for i in range(len(Sectorkey)): + buff.append(Sectorkey[i]) + + # Next we append the first 4 bytes of the UID + for i in range(4): + buff.append(serNum[i]) + + # Now we start the authentication itself + (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_AUTHENT, buff) + + # Check if an error occurred + if not (status == self.MI_OK): + self.logger.error("AUTH ERROR!!") + if not (self.Read_MFRC522(self.Status2Reg) & 0x08) != 0: + self.logger.error("AUTH ERROR(status2reg & 0x08) != 0") + + # Return the status + return status + + def MFRC522_StopCrypto1(self): + self.ClearBitMask(self.Status2Reg, 0x08) + + def MFRC522_Read(self, blockAddr): + recvData = [] + recvData.append(self.PICC_READ) + recvData.append(blockAddr) + pOut = self.CalulateCRC(recvData) + recvData.append(pOut[0]) + recvData.append(pOut[1]) + (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, recvData) + if not (status == self.MI_OK): + self.logger.error("Error while reading!") + + if len(backData) == 16: + self.logger.debug("Sector " + str(blockAddr) + " " + str(backData)) + return backData + else: + return None + + def MFRC522_Write(self, blockAddr, writeData): + buff = [] + buff.append(self.PICC_WRITE) + buff.append(blockAddr) + crc = self.CalulateCRC(buff) + buff.append(crc[0]) + buff.append(crc[1]) + (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buff) + if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): + status = self.MI_ERR + + self.logger.debug("%s backdata &0x0F == 0x0A %s" % (backLen, backData[0] & 0x0F)) + if status == self.MI_OK: + buf = [] + for i in range(16): + buf.append(writeData[i]) + + crc = self.CalulateCRC(buf) + buf.append(crc[0]) + buf.append(crc[1]) + (status, backData, backLen) = self.MFRC522_ToCard(self.PCD_TRANSCEIVE, buf) + if not (status == self.MI_OK) or not (backLen == 4) or not ((backData[0] & 0x0F) == 0x0A): + self.logger.error("Error while writing") + if status == self.MI_OK: + self.logger.debug("Data written") + + + def MFRC522_DumpClassic1K(self, key, uid): + for i in range(64): + status = self.MFRC522_Auth(self.PICC_AUTHENT1A, i, key, uid) + # Check if authenticated + if status == self.MI_OK: + self.MFRC522_Read(i) + else: + self.logger.error("Authentication error") + + def MFRC522_Init(self): + self.MFRC522_Reset() + + self.Write_MFRC522(self.TModeReg, 0x8D) + self.Write_MFRC522(self.TPrescalerReg, 0x3E) + self.Write_MFRC522(self.TReloadRegL, 30) + self.Write_MFRC522(self.TReloadRegH, 0) + + self.Write_MFRC522(self.TxAutoReg, 0x40) + self.Write_MFRC522(self.ModeReg, 0x3D) + self.AntennaOn() diff --git a/WebControl/modules/joyit_mfrc522/__init__.py b/WebControl/modules/joyit_mfrc522/__init__.py new file mode 100644 index 0000000..f793966 --- /dev/null +++ b/WebControl/modules/joyit_mfrc522/__init__.py @@ -0,0 +1,4 @@ +from .MFRC522 import MFRC522 +from .SimpleMFRC522 import SimpleMFRC522 + +name = "joyit_mfrc522" diff --git a/WebControl/templates/access.html b/WebControl/templates/access.html new file mode 100644 index 0000000..e70088a --- /dev/null +++ b/WebControl/templates/access.html @@ -0,0 +1,57 @@ + + + + Home CARIA1 + + + + + + + + + +
+

Interface d'accès

+
+
+

Dernière validation reçue

+

Nom: {{name}}

+

Confiance: {{confidence}}

+

Status: {{status}}

+
+
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/WebControl/templates/index.html b/WebControl/templates/index.html index 50623f4..5f63715 100644 --- a/WebControl/templates/index.html +++ b/WebControl/templates/index.html @@ -1,90 +1,194 @@ - admin AUTO1 + Home CARIA1 - + -
-

Interface d'administration

-
-
-
Vitesse de déplacement
-
-
-
- Needle -
-
-
050
- + +
+
+

Interface d'administration

+
+
+
Vitesse de déplacement
+
+
+
+ Needle +
+
+
030
+
-
-
- +
+
+
+
Contrôle des déplacements
+
+
+
+ +
-
- -
-
- -
-
-
- +
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+
+
+
+
+
+
Caméra
+
+ Camera +
+
+
+
+
+

Test de fonctionnement

+
+
+
Composants
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
-
-
-
Caméra
-
- +
+
+
Fonctionnalités
+
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
-
-
-

Test de fonctionnement

-
-
-
Composants
-
-
- - - - - +
+
+
Dépannage
+
+
+ +
+
+ +
+
-
-
Fonctionnalités
-
-
- - +
+

Historique des programmes

+ +
+
+ + + + + + + + + + + % for result in results: + + + + + + + % end + +
DateNom du TestFonctionnement OKStatus
{{ result['date'] }}{{ result['nom'] }}{{ 'Oui' if result['fonctionnement_ok'] else 'Non' }}{{ result['status'] }}
+
+
+
+
-
+ diff --git a/WebControl/templates/tests.html b/WebControl/templates/tests.html index 389a83b..7396874 100644 --- a/WebControl/templates/tests.html +++ b/WebControl/templates/tests.html @@ -1,19 +1,48 @@ + Test CARIA1 - CARIA - - + + - -
-

Interface de tests


- -
+ +
+

Interface de tests

+
+
+
+
+
+ + diff --git a/WebControl/tests/infrared_obstacle_module.py b/WebControl/tests/infrared_obstacle_module.py index 29ac6fe..910497a 100644 --- a/WebControl/tests/infrared_obstacle_module.py +++ b/WebControl/tests/infrared_obstacle_module.py @@ -1,26 +1,43 @@ #!/usr/bin/env python3 -# -*- coding:utf-8 -*- +# -*- coding: utf-8 -*- import RPi.GPIO as GPIO -import time +import time, sys +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() -ObstaclePin = 16 +status = "initialization" +DURATION_LIMIT = 5 -def setup(): - GPIO.setmode(GPIO.BCM) - GPIO.setup(ObstaclePin, GPIO.IN) - -def loop(): - while True: - if GPIO.input(ObstaclePin) == GPIO.LOW: - print("Obstacle détecté") - else: - print("Aucun obstacle détecté") - time.sleep(0.5) # Attendre un peu entre les lectures pour éviter les faux positifs - - -if __name__ == '__main__': - setup() +try: + start_time = time.time() # Enregistrer l'heure de début try: - loop() - except KeyboardInterrupt: - GPIO.cleanup() + while time.time() - start_time < DURATION_LIMIT: + if GPIO.input(Ab.OBSTACLE_PIN) == GPIO.LOW: + print("Obstacle détecté") + GPIO.output(Ab.RED_LIGHT, GPIO.HIGH) + status = "obstacle detected" + else: + print("Aucun obstacle détecté") + GPIO.output(Ab.RED_LIGHT, GPIO.LOW) + status = "no obstacle detected" + time.sleep(0.5) # Attendre un peu entre les lectures pour éviter les faux positifs + except Exception as e: + print(f"Erreur pendant l'exécution: {e}") + status = "erreur" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +finally: + GPIO.output(Ab.RED_LIGHT, GPIO.LOW) + Ab.cleanup() + +# Vérification finale et affichage du statut +if status in ["obstacle detected", "no obstacle detected"]: + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/tests/lidar_module.py b/WebControl/tests/lidar_module.py index d536ff1..5e2cd22 100644 --- a/WebControl/tests/lidar_module.py +++ b/WebControl/tests/lidar_module.py @@ -1,23 +1,50 @@ -import serial import time +import sys +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot + +Ab = AlphaBot() + +# Variable de statut pour indiquer le bon fonctionnement +status = "initialization" + +# Durée limite d'exécution en secondes +time_limit = 7 +start_time = time.time() try: - ser = serial.Serial('/dev/ttyAMA0', 115200, timeout=1) - - # Envoi de la commande pour initialiser le capteur - ser.write(b'\x42\x57\x02\x00\x00\x00\x01\x06') - while True: - if ser.in_waiting >= 9: - if b'Y' == ser.read() and b'Y' == ser.read(): - Dist_L = ser.read() - Dist_H = ser.read() + # Vérification si le temps limite est dépassé + if time.time() - start_time > time_limit: + break + + if Ab.LIDAR_MODULE.in_waiting >= 9: + if b'Y' == Ab.LIDAR_MODULE.read() and b'Y' == Ab.LIDAR_MODULE.read(): + Dist_L = Ab.LIDAR_MODULE.read() + Dist_H = Ab.LIDAR_MODULE.read() Dist_Total = (Dist_H[0] * 256) + Dist_L[0] for i in range(0, 5): - ser.read() # Lecture et ignore des octets supplémentaires - print("Distance:", Dist_Total, "cm") -except serial.SerialException as e: - print("Erreur série:", e) + Ab.LIDAR_MODULE.read() # Lecture et ignore des octets supplémentaires + print("Distance à l'avant du véhicule:", Dist_Total, "cm") + status = "measurement successful" + time.sleep(1) + Ab.LIDAR_MODULE.reset_input_buffer() +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" finally: - if 'ser' in locals(): - ser.close() # Fermeture propre du port série + Ab.LIDAR_MODULE.close() # Fermeture propre du port série + Ab.cleanup() + +# Vérification finale et affichage du statut +if status in ["measurement successful"]: + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/tests/motor_speed_move.py b/WebControl/tests/motor_speed_move.py index 0eea39d..2fa108e 100644 --- a/WebControl/tests/motor_speed_move.py +++ b/WebControl/tests/motor_speed_move.py @@ -1,45 +1,46 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import time import sys sys.path.append('/home/christian/WebControl/modules/') from AlphaBot import AlphaBot +Ab = AlphaBot() +# Variable de statut pour indiquer le bon fonctionnement +status = "initialization" # Test de la classe AlphaBot avec différentes vitesses pour les moteurs individuels -def test_alphabot_speed(): - bot = AlphaBot() - try: - while True: # Boucle infinie - for speed in range(20, 101, 40): - print(f"Test de vitesse à {speed}%") - - # Vérifier si speed est une chaîne non vide - if speed != '': - # Test des moteurs en avance - bot.forward(speed) - time.sleep(1) - bot.stop() - time.sleep(0.5) - - # Test des moteurs en arrière - bot.backward(speed) - time.sleep(1) - bot.stop() - time.sleep(0.5) - - # Test du moteur gauche en avant et moteur droit en arrière - bot.left(speed) - time.sleep(1) - bot.stop() - time.sleep(0.5) - - # Test du moteur gauche en arrière et moteur droit en avant - bot.right(speed) - time.sleep(1) - bot.stop() - time.sleep(0.5) - except KeyboardInterrupt: - bot.cleanup() -if __name__ == "__main__": - test_alphabot_speed() +duration = 0.5 +try: + for speed in range(20, 81, 30): + print(f"Test de vitesse à {speed}%") + # Test des moteurs en avance + Ab.forward(duration, speed) + Ab.stop(1) + # Test des moteurs en arrière + Ab.backward(duration, speed) + Ab.stop(1) + # Test du moteur gauche en avant et moteur droit en arrière + Ab.left(duration, speed) + Ab.stop(1) + # Test du moteur gauche en arrière et moteur droit en avant + Ab.right(duration, speed) + Ab.stop(1) + status = "move successful" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors du test: {e}") + status = "error" +finally: + Ab.cleanup() + +# Vérification finale et affichage du statut +if status == "move successful": + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/tests/rfid_open_door.py b/WebControl/tests/rfid_open_door.py new file mode 100644 index 0000000..49e53c7 --- /dev/null +++ b/WebControl/tests/rfid_open_door.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +import time, sys +sys.path.append('/home/christian/WebControl/modules/') +from SimpleMFRC522 import SimpleMFRC522 +RFID_MODULE = SimpleMFRC522() +from AlphaBot import AlphaBot +Ab = AlphaBot() + +status = "initialization" +fonctionnement_ok = False + +# Lecture initiale du tag RFID +try: + print("La porte est actuellement fermée.\nVeuillez approcher votre badge RFID du capteur pour accéder au véhicule.") + id_rfid, text_rfid = RFID_MODULE.read() + if text_rfid in ["CHRIS "]: + Ab.set_angle(90) + print(f"Salut {text_rfid.rstrip()}, votre accès est validé avec succès.\nLa porte du véhicule est maintenant ouverte!") + status = "Access successful" + elif text_rfid == "TEST RFID ": + Ab.set_angle(90) + print(f"Bienvenue, {text_rfid.rstrip()}.\nLa porte du véhicule est maintenant ouverte!") + status = "Access successful" + else: + print("Bonjour, vous n'êtes pas autorisé à entrer dans le véhicule.\nLa porte reste fermée.") + status = "Access denied" + print(f"(ID, Text)",id_rfid, text_rfid) + time.sleep(2) +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + Ab.PWMSERVO.stop() +time.sleep(2) + +# Vérification finale et affichage du statut +if status == "Access successful": + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False + +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file diff --git a/WebControl/tests/rfid_read_write_module.py b/WebControl/tests/rfid_read_write_module.py deleted file mode 100644 index 69d0a40..0000000 --- a/WebControl/tests/rfid_read_write_module.py +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/bin/env python - -# Importation des bibliothèques -import time -from gpiozero import LED -from joyit_mfrc522 import SimpleMFRC522 - -# Initialisation de l'objet pour le module RFID -reader = SimpleMFRC522() - -# Fonction pour la lecture du tag RFID -def read_rfid(): - print("### Lecture RFID ###") - print("Approchez le tag RFID du capteur:") - id, text = reader.read() - print("ID:", id) - print("Contenu:", text) - time.sleep(5) - -# Fonction pour l'écriture sur le tag RFID avec gestion des erreurs -def write_rfid(data, max_attempts=3): - print("### Écriture RFID ###") - print("Valeur qui sera écrite:", data) - print("Approchez le tag RFID du capteur:") - try: - reader.write(data) - print("Succès de l'écriture sur le tag RFID.") - time.sleep(3) # Attente courte avant de vérifier l'écriture - except Exception as e: - print(f"Erreur lors de l'écriture RFID: {e}") - time.sleep(3) # Attendre avant de réessayer - -# Lecture initiale du tag RFID -read_rfid() - -# Écriture sur le tag RFID -write_rfid("TEST RFID") - -# Seconde lecture du tag RFID -read_rfid() diff --git a/WebControl/tests/servo_motor.py b/WebControl/tests/servo_motor.py index 0ca90aa..e97ce8c 100644 --- a/WebControl/tests/servo_motor.py +++ b/WebControl/tests/servo_motor.py @@ -1,31 +1,40 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- -import RPi.GPIO as GPIO -import time +import time,sys +sys.path.append('/home/christian/WebControl/modules/') +from AlphaBot import AlphaBot +Ab = AlphaBot() -# Définir la broche GPIO pour le signal du servo-moteur -SERVO_PIN = 27 +status = "initialization" +try: + Ab.set_angle(0) + print("Positionné à 0°") + time.sleep(2) + Ab.set_angle(90) + print("Positionné à 90°") + time.sleep(2) + Ab.set_angle(180) + print("Positionné à 180°") + time.sleep(2) + Ab.set_angle(0) + print("Positionné à 0°") + status = "movement successful" +except KeyboardInterrupt: + print("Interruption par l'utilisateur.") + status = "interrupted" +except Exception as e: + print(f"Erreur lors de l'exécution: {e}") + status = "error" +finally: + Ab.PWMSERVO.stop() + Ab.cleanup() -def setup(): - GPIO.setmode(GPIO.BCM) - GPIO.setup(SERVO_PIN, GPIO.OUT) +# Vérification finale et affichage du statut +if status == "movement successful": + print("Le composant fonctionne correctement.") + fonctionnement_ok = True +else: + print(f"Le composant a rencontré un problème: {status}.") + fonctionnement_ok = False -def set_angle(angle): - pwm = GPIO.PWM(SERVO_PIN, 50) # Fréquence PWM de 50 Hz - pwm.start(2.5) # Position neutre (angle de 0 degrés) - duty_cycle = angle / 18.0 + 2.5 # Convertir l'angle en devoir (duty cycle) - pwm.ChangeDutyCycle(duty_cycle) - time.sleep(0.5) # Attendre que le servo atteigne la position désirée - pwm.stop() - -if __name__ == '__main__': - try: - setup() - while True: - # Faire tourner le servo-moteur de 0 à 180 degrés avec un pas de 30 degrés - for angle in range(0, 181, 30): - print("Rotation du servo moteur à {} degrés".format(angle)) - set_angle(angle) - time.sleep(1) - except KeyboardInterrupt: - GPIO.cleanup() +Ab.enregistrer_resultats(sys.argv[0], fonctionnement_ok, status) \ No newline at end of file