From 0ab04110ad21b623a9813a5d6c0ac4507259bc5c Mon Sep 17 00:00:00 2001 From: maxime Date: Wed, 1 Apr 2026 16:17:21 +0200 Subject: [PATCH] maj alarme --- composants/test/ALARM_V1.py | 490 ++++++++++++++++++------------------ 1 file changed, 245 insertions(+), 245 deletions(-) diff --git a/composants/test/ALARM_V1.py b/composants/test/ALARM_V1.py index ae051ce..8431b57 100644 --- a/composants/test/ALARM_V1.py +++ b/composants/test/ALARM_V1.py @@ -1,245 +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() + +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 = 22 +PIN_LED_B = 27 +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()