diff --git a/composants/test/ALARM_V1.py b/composants/byPanda/ALARM_V1.py similarity index 99% rename from composants/test/ALARM_V1.py rename to composants/byPanda/ALARM_V1.py index 8431b57..f56dda1 100644 --- a/composants/test/ALARM_V1.py +++ b/composants/byPanda/ALARM_V1.py @@ -241,5 +241,3 @@ def boucle_principale(): # ════════════════════════════════════════════════════════════════════════════ -if __name__ == "__main__": - boucle_principale() diff --git a/composants/byPanda/DHT11.py b/composants/byPanda/DHT11.py index 25d5bca..b521098 100644 --- a/composants/byPanda/DHT11.py +++ b/composants/byPanda/DHT11.py @@ -1,19 +1,14 @@ import Adafruit_DHT as dht -import time as t -import RPi.GPIO as GPIO -GPIO.setmode(GPIO.BOARD) +# On définit juste le capteur et la broche (Rappel : 25 en BCM = broche physique 22) capteur = dht.DHT11 pin = 25 def lire_temperature(): humidite, temperature = dht.read_retry(capteur, pin) - + + # On renvoie la température au script principal ! if temperature is not None: - print("Temp :", temperature, "°C") + return temperature else: - print("Erreur") - - t.sleep(2) - -lire_temperature() + return 0 # Sécurité si le capteur bugge, pour ne pas faire planter l'affichage \ No newline at end of file diff --git a/composants/byPanda/board1main.py b/composants/byPanda/board1main.py index a074cde..b9f3492 100644 --- a/composants/byPanda/board1main.py +++ b/composants/byPanda/board1main.py @@ -1,5 +1,5 @@ import time -from alarme import SystemeAlarme +from ALARM_V1 import * from porterfid import SystemePorteRFID # ------------------------------------------------------------ @@ -16,15 +16,18 @@ alarme = SystemeAlarme() porte = SystemePorteRFID() + def call_board1(): try: while True: # Mise à jour des deux modules locaux - alarme.mettreAJour() + ALARM_V1.boucle_principale() porte.mettreAJour() time.sleep(0.05) except KeyboardInterrupt: + porte.cleanup() + alarme.cleanup() print("\nArrêt manuel du programme.") finally: diff --git a/composants/byPanda/bouton.py b/composants/byPanda/bouton.py index b8cdaec..7168b6f 100644 --- a/composants/byPanda/bouton.py +++ b/composants/byPanda/bouton.py @@ -1,6 +1,7 @@ import RPi.GPIO as GPIO import time as t from septsegments import afficher_temperature +from DHT11 import lire_temperature GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) @@ -11,32 +12,43 @@ GPIO.setup(bouton_up, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.setup(bouton_down, GPIO.IN, pull_up_down=GPIO.PUD_UP) def test_boutons(): - temperature = 18 - + # 1. On lit la vraie température au démarrage + temperature_DHT = lire_temperature() + # 2. On fixe la température qu'on souhaite (la cible) + temperature_cible = 18 etatPrecedent_up = GPIO.input(bouton_up) etatPrecedent_down = GPIO.input(bouton_down) - print("Test lancé ! Appuie sur UP (23) pour monter, DOWN (24) pour descendre.") + print("Thermostat lancé ! Appuie sur UP (23) ou DOWN (24).") + + # On affiche une première fois pour que l'écran ne soit pas vide au lancement + afficher_temperature(temperature_DHT, temperature_cible) while True: etat_up = GPIO.input(bouton_up) etat_down = GPIO.input(bouton_down) + + # --- BOUTON UP --- if etat_up != etatPrecedent_up: if etat_up == 0: print("Bouton UP Appuyé ⬆️") - temperature += 1 - if temperature >= 40: - temperature = 40 - afficher_temperature(21,temperature) + temperature_cible += 1 + if temperature_cible >= 40: + temperature_cible = 40 + # On met à jour l'écran + afficher_temperature(temperature_DHT, temperature_cible) etatPrecedent_up = etat_up + + # --- BOUTON DOWN --- if etat_down != etatPrecedent_down: if etat_down == 0: print("Bouton DOWN Appuyé ⬇️") - temperature -= 1 - if temperature <= 0: - temperature = 0 - afficher_temperature(21,temperature) + temperature_cible -= 1 + if temperature_cible <= 0: + temperature_cible = 0 + # On met à jour l'écran + afficher_temperature(temperature_DHT, temperature_cible) etatPrecedent_down = etat_down t.sleep(0.05) diff --git a/composants/byPanda/septsegments.py b/composants/byPanda/septsegments.py index 99f8442..8226f0b 100644 --- a/composants/byPanda/septsegments.py +++ b/composants/byPanda/septsegments.py @@ -19,4 +19,5 @@ def afficher_temperature(temperature, temperature_moyenne): disp.show(texte_ecran) except Exception as e: - print(f"Erreur d'affichage : {e}") \ No newline at end of file + print(f"Erreur d'affichage : {e}") + execpt keybo \ No newline at end of file diff --git a/fastapi/main.py b/fastapi/main.py index 982340a..821b007 100644 --- a/fastapi/main.py +++ b/fastapi/main.py @@ -19,6 +19,13 @@ from etatsysteme import EtatSysteme from septsegments import afficher_temperature app = FastAPI(title="L'API des loustiques") +app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=False, + allow_methods=["*"], + allow_headers=["*"], +) controleur_lumieres = SystemeLumieres() controleur_thermostat = SystemeThermostat() @@ -66,21 +73,11 @@ async def read_temp(): return {"success": False, "message": str(e)} -app.add_middleware( - CORSMiddleware, - allow_origins=["*"], # Autorise tous les sites web (le fameux "*") - allow_credentials=False, # (Doit être False quand on met "*") - allow_methods=["*"], # Autorise toutes les méthodes (GET, POST, etc.) - allow_headers=["*"], # Autorise tous les en-têtes -) + if __name__ == "__main__": - # On prépare les chemins proprement pour éviter les erreurs de parenthèses - # (Vérifie bien que le dossier 'web_secu' est bien dans le dossier racine de ton Pi 2) chemin_cle = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'key.pem') chemin_cert = os.path.join(BASE_DIR, 'web_secu', 'ssl', 'cert.pem') - - # On lance Uvicorn avec la bonne syntaxe uvicorn.run( "main:app", host="0.0.0.0", diff --git a/fastapi/run_api.sh b/fastapi/run_api.sh index 205e34c..346c824 100755 --- a/fastapi/run_api.sh +++ b/fastapi/run_api.sh @@ -65,4 +65,5 @@ EOF sleep 1 touch /var/log/loustique.log chown ${SUDO_USER}:${SUDO_USER} /var/log/loustique.log +venv/bin/python composants/test/bouton.py venv/bin/python main.py diff --git a/flask/main.py b/flask/main.py index 5c3531a..9b91a50 100644 --- a/flask/main.py +++ b/flask/main.py @@ -1,7 +1,9 @@ from flask import Flask, render_template, request, jsonify +import requests from flask_talisman import Talisman from led import led import os +import threading import sys import log from add_user import add_user @@ -48,7 +50,6 @@ def call_led(): else: SystemeLumieres.eteindreLumieres() return jsonify({"success": True}) -# Variable temporaire pour stocker le dernier badge scanné dernier_badge_scanne = None @app.route("/rfid-scan", methods=["POST"]) @@ -56,47 +57,29 @@ def rfid_scan(): global dernier_badge_scanne data = request.get_json() badge_id = data.get("badge_id") - - # On va créer cette fonction dans ton fichier auth.py juste après username = auth.get_user_by_rfid(badge_id) - if username: - # Le badge est dans la base de données ! On autorise. dernier_badge_scanne = username return jsonify({"success": True, "username": username}) else: - # Badge inconnu return jsonify({"success": False}) @app.route("/check-rfid-login", methods=["GET"]) def check_rfid_login(): global dernier_badge_scanne global current_user - - # Si le Raspberry Pi a signalé un badge validé récemment if dernier_badge_scanne: user = dernier_badge_scanne - - # On valide la connexion côté serveur current_user = user - - # On vide la variable pour ne pas le reconnecter en boucle à l'infini dernier_badge_scanne = None return jsonify({"success": True, "username": user}) return jsonify({"success": False}) - - - @app.route("/alarme",methods=["POST"]) def armer_alarme(): SystemeAlarme.armer() return jsonify({"success": True}) - - - - @app.route("/admin") def admin_page(): return render_template("admin.html") @@ -131,22 +114,32 @@ def get_users(): users = auth.get_users() return jsonify({"success": True, "users": users}) -@app.route("/api/relais-pi2/", methods=["GET"]) +@app.route("/api/", methods=["GET"]) def relais_pi2(action): - """ - Flask sert de relais. Le navigateur demande à Flask, et Flask demande au Pi 2. - """ + url_pi2 = f"https://pi32.local:8000/{action}" + print(f"\n[RELAIS] 1. Tentative de contact avec le Pi 2 : {url_pi2}") + try: - # L'adresse de ton Pi 2 - url_pi2 = f"https://pi32.local:8000/{action}" - - # Le Pi 1 fait la requête ! verify=False permet d'ignorer le faux certificat reponse = requests.get(url_pi2, timeout=5, verify=False) - - return jsonify(reponse.json()) - + print(f"[RELAIS] 2. Code HTTP reçu du Pi 2 : {reponse.status_code}") + print(f"[RELAIS] 3. Texte brut reçu du Pi 2 : {reponse.text}") + if not reponse.ok: + return jsonify({ + "success": False, + "message": f"Le Pi 2 a refusé la requête (Code {reponse.status_code})" + }), reponse.status_code + + # Si tout va bien, on tente d'extraire le JSON + try: + data = reponse.json() + return jsonify(data) + except ValueError: + print("[RELAIS] 4. ERREUR : Le Pi 2 n'a pas renvoyé de JSON valide.") + return jsonify({"success": False, "message": "Réponse invalide du Pi 2"}), 502 + except Exception as e: - return jsonify({"success": False, "message": str(e)}) + print(f"[RELAIS] ERREUR CRITIQUE : Impossible de joindre le Pi 2. Raison : {e}") + return jsonify({"success": False, "message": f"Erreur de connexion : {str(e)}"}), 500 if __name__ == "__main__": diff --git a/flask/templates/dashboard.html b/flask/templates/dashboard.html index 0f74813..08223ed 100644 --- a/flask/templates/dashboard.html +++ b/flask/templates/dashboard.html @@ -234,14 +234,14 @@
Heure locale
--:--
-
--
- -
+
--
+ +
Température
-
--
-
+
-- °C
+ -
+
Porte
--
@@ -273,7 +273,7 @@ Allumer la LED - @@ -306,7 +306,7 @@ setInterval(updateClock, 1000); - + /* async function callAlarm() { try { const res = await fetch('/alarme', { @@ -316,10 +316,34 @@ showToast("alarme activée !"); } catch { showToast("Erreur lors de l'appel alarme."); + }*/ + + async function get_temperature() { + try { + const res = await fetch('/api/temperature', { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + + const data = await res.json(); + + + if (data.success) { + document.getElementById("temp-display").textContent = data.temperature + " °C"; + } else { + document.getElementById("temp-display").textContent = "Erreur"; + console.error("Erreur de température :", data.message); + } + } catch (e) { + document.getElementById("temp-display").textContent = "Hors ligne"; + console.error("Impossible de joindre le relais pour la température."); } + } + get_temperature(); + setInterval(get_temperature, 60000); async function call_led_down() { try { - const res = await fetch('https://pi32.local:8000down_led', { + const res = await fetch('/api/down_led', { method: 'GET', headers: { 'Content-Type': 'application/json' } }); @@ -327,10 +351,10 @@ } catch { showToast("Erreur lors de l'appel board1."); }} - } - async function call_led_up() { + + async function call_led_up() { try { - const res = await fetch('https://pi32.local:8000/up_led', { + const res = await fetch('/api/up_led', { method: 'GET', headers: { 'Content-Type': 'application/json' } });