diff --git a/composants/byPanda/porterfid.py b/composants/byPanda/porterfid.py index 8f9814f..96e3404 100644 --- a/composants/byPanda/porterfid.py +++ b/composants/byPanda/porterfid.py @@ -19,7 +19,7 @@ class SystemePorteRFID: Gère le lecteur RFID et la LED de la porte. L'authentification est maintenant gérée par le serveur Flask et MariaDB. """ - self.pinLed = 21 + self.pinLed = 4 GPIO.setup(self.pinLed, GPIO.OUT, initial=GPIO.LOW) self.lecteur = SimpleMFRC522() diff --git a/composants/byPanda/septsegments.py b/composants/byPanda/septsegments.py index df660e5..99f8442 100644 --- a/composants/byPanda/septsegments.py +++ b/composants/byPanda/septsegments.py @@ -1,8 +1,13 @@ import tm1637 import time as t +_display = None -display = tm1637.TM1637(clk=4, dio=17) -display.brightness(2) +def get_display(): + global _display + if _display is None: + _display = tm1637.TM1637(clk=4, dio=17) + _display.brightness(2) + return _display def afficher_temperature(temperature, temperature_moyenne): print(f"Test affichage: Cible {temperature} | Moyenne {temperature_moyenne}") @@ -10,8 +15,8 @@ def afficher_temperature(temperature, temperature_moyenne): temp1 = int(temperature) temp2 = int(temperature_moyenne) texte_ecran = f"{temp1:02d}{temp2:02d}" - - display.show(texte_ecran) + disp = get_display() + disp.show(texte_ecran) except Exception as e: print(f"Erreur d'affichage : {e}") \ No newline at end of file diff --git a/composants/test/ALARM_V2.py b/composants/test/ALARM_V2.py new file mode 100644 index 0000000..8c53e22 --- /dev/null +++ b/composants/test/ALARM_V2.py @@ -0,0 +1,205 @@ +import RPi.GPIO as GPIO +import time +import threading + +GPIO.setmode(GPIO.BCM) +GPIO.setwarnings(False) + +PIN_LED_R = 17 +PIN_LED_G = 22 +PIN_LED_B = 27 +PIN_PIR = 15 +PIN_BUZZER = 18 + +ROWS = [5, 6, 13, 19] +COLS = [26, 12, 16, 20] + +KEYPAD_MAP = [ + ['1', '2', '3', 'A'], + ['4', '5', '6', 'B'], + ['7', '8', '9', 'C'], + ['*', '0', '#', 'D'], +] + +CODE_SECRET = "1234" + +GPIO.setup(PIN_LED_R, GPIO.OUT, initial=GPIO.LOW) +GPIO.setup(PIN_LED_G, GPIO.OUT, initial=GPIO.LOW) +GPIO.setup(PIN_LED_B, GPIO.OUT, initial=GPIO.LOW) +GPIO.setup(PIN_BUZZER, GPIO.OUT, initial=GPIO.LOW) +GPIO.setup(PIN_PIR, GPIO.IN) + +for row in ROWS: + GPIO.setup(row, GPIO.OUT, initial=GPIO.HIGH) +for col in COLS: + GPIO.setup(col, GPIO.IN, pull_up_down=GPIO.PUD_UP) + +etat = "desarmee" +etat_lock = threading.Lock() + +_stop_buzzer = threading.Event() +_thread_buzzer = None + +def led(r=False, g=False, b=False): + """Allume la LED RGB avec la couleur voulue.""" + GPIO.output(PIN_LED_R, GPIO.HIGH if r else GPIO.LOW) + GPIO.output(PIN_LED_G, GPIO.HIGH if g else GPIO.LOW) + GPIO.output(PIN_LED_B, GPIO.HIGH if b else GPIO.LOW) + +def led_bleu(): led(b=True) +def led_vert(): led(g=True) +def led_rouge(): led(r=True) +def led_off(): led() + +def bip(nb=1, duree=0.08, pause=0.12): + """Émet nb bip(s) courts.""" + for _ in range(nb): + GPIO.output(PIN_BUZZER, GPIO.HIGH) + time.sleep(duree) + GPIO.output(PIN_BUZZER, GPIO.LOW) + time.sleep(pause) + +def _buzzer_continu(stop_event: threading.Event): + """Boucle interne : buzzer ON/OFF jusqu'à stop_event.""" + while not stop_event.is_set(): + GPIO.output(PIN_BUZZER, GPIO.HIGH) + time.sleep(0.5) + GPIO.output(PIN_BUZZER, GPIO.LOW) + time.sleep(0.5) + GPIO.output(PIN_BUZZER, GPIO.LOW) + +def lire_touche(): + """ + Scan matriciel : met chaque ligne à LOW tour à tour + et lit les colonnes. Retourne la touche ou None. + """ + for i, row in enumerate(ROWS): + GPIO.output(row, GPIO.LOW) + for j, col in enumerate(COLS): + if GPIO.input(col) == GPIO.LOW: + time.sleep(0.05) + while GPIO.input(col) == GPIO.LOW: + pass + GPIO.output(row, GPIO.HIGH) + return KEYPAD_MAP[i][j] + GPIO.output(row, GPIO.HIGH) + return None + +def lire_code(timeout=30): + saisi = "" + debut = time.time() + print(" Code (# pour valider, * pour effacer) : ", end="", flush=True) + while True: + if time.time() - debut > timeout: + print("\n [Timeout — saisie annulée]") + return "" + touche = lire_touche() + if touche is None: + time.sleep(0.05) + continue + if touche == '#': + print() + return saisi + elif touche == '*': + if saisi: + saisi = saisi[:-1] + print("\b \b", end="", flush=True) + elif touche.isdigit(): + saisi += touche + print("*", end="", flush=True) + time.sleep(0.05) + +def passer_en_desarmee(): + global etat, _thread_buzzer + _stop_buzzer.set() + if _thread_buzzer and _thread_buzzer.is_alive(): + _thread_buzzer.join() + with etat_lock: + etat = "desarmee" + led_bleu() + print("[ÉTAT] ● DÉSARMÉE — LED bleue") + +def passer_en_armee(): + global etat + with etat_lock: + etat = "armee" + led_vert() + bip(nb=2) + print("[ÉTAT] ● ARMÉE — LED verte — PIR actif") + +def passer_en_declenchee(): + global etat, _thread_buzzer + with etat_lock: + etat = "declenchee" + led_rouge() + print("[ÉTAT] ● DÉCLENCHÉE — LED rouge — buzzer actif") + _stop_buzzer.clear() + _thread_buzzer = threading.Thread( + target=_buzzer_continu, args=(_stop_buzzer,), daemon=True + ) + _thread_buzzer.start() + +def _surveiller_pir(stop_evt: threading.Event): + """Lit le PIR toutes les 100 ms. Déclenche si mouvement et armée.""" + print("[PIR] Surveillance démarrée") + while not stop_evt.is_set(): + with etat_lock: + etat_local = etat + if etat_local == "armee" and GPIO.input(PIN_PIR) == GPIO.HIGH: + print("[PIR] ⚠ Mouvement détecté !") + passer_en_declenchee() + time.sleep(0.1) + +def boucle_principale(): + global etat + + passer_en_desarmee() + + stop_pir = threading.Event() + thread_pir = threading.Thread( + target=_surveiller_pir, args=(stop_pir,), daemon=True + ) + thread_pir.start() + + print("\n=== Système d'alarme démarré ===") + print(" Tapez le code sur le keypad pour armer / désarmer.\n") + + try: + while True: + with etat_lock: + etat_local = etat + + if etat_local == "desarmee": + print(" → Saisir le code pour ARMER :") + code = lire_code() # CORRECTION ICI + if code == CODE_SECRET: + print(" ✔ Code correct → armement") + passer_en_armee() + elif code != "": + print(" ✘ Code incorrect") + bip(nb=1, duree=0.4) + + elif etat_local == "armee": + time.sleep(0.1) + + elif etat_local == "declenchee": + print(" → Saisir le code pour DÉSARMER :") + code = lire_code() # CORRECTION ICI + if code == CODE_SECRET: + print(" ✔ Code correct → désarmement") + passer_en_desarmee() # AJOUT : pour que l'alarme s'arrête vraiment + elif code != "": + print(" ✘ Code incorrect — alarme maintenue") + + except KeyboardInterrupt: + print("\n[INFO] Arrêt demandé (Ctrl+C)") + + finally: + stop_pir.set() + _stop_buzzer.set() + led_off() + GPIO.cleanup() + print("[INFO] GPIO libérés. Fin du programme.") + +if __name__ == "__main__": + boucle_principale() \ No newline at end of file diff --git a/fastapi/main.py b/fastapi/main.py index 2620f94..982340a 100644 --- a/fastapi/main.py +++ b/fastapi/main.py @@ -1,7 +1,9 @@ import os import sys from fastapi import FastAPI +from fastapi.middleware.cors import CORSMiddleware import RPi.GPIO as GPIO +import uvicorn GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) @@ -13,7 +15,7 @@ sys.path.insert(0, composants) from lumieres import SystemeLumieres from thermostat import SystemeThermostat #from volets import SystemeVolets -from etatsystemes import EtatSysteme +from etatsysteme import EtatSysteme from septsegments import afficher_temperature app = FastAPI(title="L'API des loustiques") @@ -56,13 +58,33 @@ async def read_temp(): return {"success": False, "message": "Impossible de lire le capteur DHT11"} etatSysteme.signalerOk() - afficher_temperature(temp) + afficher_temperature(temp, 18) return {"success": True, "temperature": temp} except Exception as e: etatSysteme.signalerProbleme() 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__": - import uvicorn - uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True) + # 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", + port=8000, + ssl_keyfile=chemin_cle, + ssl_certfile=chemin_cert + ) \ No newline at end of file diff --git a/flask/index.html b/flask/index.html new file mode 100644 index 0000000..cdc66cc --- /dev/null +++ b/flask/index.html @@ -0,0 +1,222 @@ + + +
+ + +Connectez-vous via mot de passe ou avec votre bagde pour accéder à votre espace.
+ +