diff --git a/composants/byPanda/alarme.py b/composants/byPanda/alarme.py index 3797530..2ff2448 100644 --- a/composants/byPanda/alarme.py +++ b/composants/byPanda/alarme.py @@ -1,7 +1,7 @@ import time import RPi.GPIO as GPIO -GPIO.setmode(GPIO.BOARD) +GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) @@ -22,17 +22,17 @@ class SystemeAlarme: # ----------------------------- # Définition des pins physiques # ----------------------------- - self.pinPir = 22 - self.pinBuzzer = 12 + self.pinPir = 15 + self.pinBuzzer = 18 - self.pinLedRouge = 11 - self.pinLedVerte = 13 - self.pinLedBleue = 15 + self.pinLedRouge = 17 + self.pinLedVerte = 27 + self.pinLedBleue = 22 # Clavier 4x4 # 4 lignes + 4 colonnes - self.lignes = [29, 31, 33, 35] - self.colonnes = [37, 32, 36, 38] + self.lignes = [5, 6, 13, 19] + self.colonnes = [26, 12, 16, 20] # Disposition classique d'un clavier 4x4 self.touches = [ @@ -243,4 +243,4 @@ class SystemeAlarme: Remet les sorties dans un état propre à la fermeture. """ GPIO.output(self.pinBuzzer, GPIO.LOW) - self.definirCouleur(False, False, False) + self.definirCouleur(False, False, False) \ No newline at end of file diff --git a/composants/byPanda/board1main.py b/composants/byPanda/board1main.py index 4f8e05f..a074cde 100644 --- a/composants/byPanda/board1main.py +++ b/composants/byPanda/board1main.py @@ -15,17 +15,19 @@ from porterfid import SystemePorteRFID alarme = SystemeAlarme() porte = SystemePorteRFID() -try: - while True: - # Mise à jour des deux modules locaux - alarme.mettreAJour() - porte.mettreAJour() - time.sleep(0.05) -except KeyboardInterrupt: - print("\nArrêt manuel du programme.") +def call_board1(): + try: + while True: + # Mise à jour des deux modules locaux + alarme.mettreAJour() + porte.mettreAJour() + time.sleep(0.05) -finally: - # On remet les sorties dans un état propre avant de quitter - alarme.cleanup() - porte.cleanup() + except KeyboardInterrupt: + print("\nArrêt manuel du programme.") + + finally: + # On remet les sorties dans un état propre avant de quitter + alarme.cleanup() + porte.cleanup() diff --git a/composants/byPanda/porterfid.py b/composants/byPanda/porterfid.py index e8b6c2a..8f9814f 100644 --- a/composants/byPanda/porterfid.py +++ b/composants/byPanda/porterfid.py @@ -8,7 +8,7 @@ import urllib3 # On cache le gros texte d'avertissement orange (InsecureRequestWarning) urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) -GPIO.setmode(GPIO.BOARD) +GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) @@ -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 = 40 + self.pinLed = 21 GPIO.setup(self.pinLed, GPIO.OUT, initial=GPIO.LOW) self.lecteur = SimpleMFRC522() diff --git a/composants/test/ALARM_V1.py b/composants/test/ALARM_V1.py new file mode 100644 index 0000000..ae051ce --- /dev/null +++ b/composants/test/ALARM_V1.py @@ -0,0 +1,245 @@ + +import RPi.GPIO as GPIO +import time +import threading + +# ── Numérotation BCM ──────────────────────────────────────────────────────── +GPIO.setmode(GPIO.BCM) +GPIO.setwarnings(False) + +# ── Broches ───────────────────────────────────────────────────────────────── +PIN_LED_R = 17 +PIN_LED_G = 27 +PIN_LED_B = 22 +PIN_PIR = 15 +PIN_BUZZER = 18 + +# Keypad 4x4 — 4 lignes (sorties) + 4 colonnes (entrées pull-up) +ROWS = [5, 6, 13, 19] # R1 R2 R3 R4 +COLS = [26, 12, 16, 20] # C1 C2 C3 C4 + +KEYPAD_MAP = [ + ['1', '2', '3', 'A'], + ['4', '5', '6', 'B'], + ['7', '8', '9', 'C'], + ['*', '0', '#', 'D'], +] + +# ── Code secret (modifiable ici) ───────────────────────────────────────────── +CODE_SECRET = "1234" + +# ── Configuration GPIO ─────────────────────────────────────────────────────── +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) + +# ── État global ────────────────────────────────────────────────────────────── +etat = "desarmee" +etat_lock = threading.Lock() + +_stop_buzzer = threading.Event() +_thread_buzzer = None + + +# ════════════════════════════════════════════════════════════════════════════ +# LED RGB +# ════════════════════════════════════════════════════════════════════════════ + +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() + + +# ════════════════════════════════════════════════════════════════════════════ +# Buzzer +# ════════════════════════════════════════════════════════════════════════════ + +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) + + +# ════════════════════════════════════════════════════════════════════════════ +# Keypad 4x4 +# ════════════════════════════════════════════════════════════════════════════ + +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) # anti-rebond + while GPIO.input(col) == GPIO.LOW: + pass # attente relâchement + GPIO.output(row, GPIO.HIGH) + return KEYPAD_MAP[i][j] + GPIO.output(row, GPIO.HIGH) + return None + +def lire_code(nb_chiffres=4, timeout=30): + """ + Attend nb_chiffres touches numériques sur le keypad. + Retourne la chaîne saisie ou '' si timeout. + """ + saisi = "" + debut = time.time() + print(" Code : ", end="", flush=True) + while len(saisi) < nb_chiffres: + if time.time() - debut > timeout: + print("\n [Timeout — saisie annulée]") + return "" + touche = lire_touche() + if touche and touche.isdigit(): + saisi += touche + print("*", end="", flush=True) + time.sleep(0.05) + print() + return saisi + + +# ════════════════════════════════════════════════════════════════════════════ +# Transitions d'état +# ════════════════════════════════════════════════════════════════════════════ + +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) # 2 petits bips = armée avec succès + 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() + + +# ════════════════════════════════════════════════════════════════════════════ +# Thread : surveillance PIR +# ════════════════════════════════════════════════════════════════════════════ + +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) + + +# ════════════════════════════════════════════════════════════════════════════ +# Boucle principale +# ════════════════════════════════════════════════════════════════════════════ + +def boucle_principale(): + global etat + + # Démarrage : LED bleue (désarmée) + passer_en_desarmee() + + # Thread PIR en arrière-plan + 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 + + # ── DÉSARMÉE : attente d'un code pour armer ────────────────────── + if etat_local == "desarmee": + print(" → Saisir le code pour ARMER :") + code = lire_code(nb_chiffres=len(CODE_SECRET)) + if code == CODE_SECRET: + print(" ✔ Code correct → armement") + passer_en_armee() + elif code != "": + print(" ✘ Code incorrect") + bip(nb=1, duree=0.4) # 1 bip long = erreur + + # ── ARMÉE : le thread PIR gère le déclenchement ────────────────── + elif etat_local == "armee": + time.sleep(0.1) + + # ── DÉCLENCHÉE : attente du code pour désarmer ─────────────────── + elif etat_local == "declenchee": + print(" → Saisir le code pour DÉSARMER :") + code = lire_code(nb_chiffres=len(CODE_SECRET)) + if code == CODE_SECRET: + print(" ✔ Code correct → désarmement") + passer_en_desarmee() + 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()