import time import RPi.GPIO as GPIO GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) class SystemeAlarme: def __init__(self): """ Initialise les composants liés à l'alarme. Cette classe gère uniquement la logique locale de sécurité : - le capteur PIR - le buzzer - la LED RGB de statut - le clavier 4x4 Elle ne dépend d'aucune autre partie du projet. """ # ----------------------------- # Définition des pins physiques # ----------------------------- self.pinPir = 15 self.pinBuzzer = 18 self.pinLedRouge = 17 self.pinLedVerte = 27 self.pinLedBleue = 22 # Clavier 4x4 # 4 lignes + 4 colonnes self.lignes = [5, 6, 13, 19] self.colonnes = [26, 12, 16, 20] # Disposition classique d'un clavier 4x4 self.touches = [ ["1", "2", "3", "A"], ["4", "5", "6", "B"], ["7", "8", "9", "C"], ["*", "0", "#", "D"] ] # ----------------------------- # Variables de fonctionnement # ----------------------------- self.codeSecret = "1234" self.codeSaisi = "" # Etats possibles : # - desarme # - arme # - alarme self.etat = "desarme" # Anti-rebond clavier self.derniereLecture = 0 self.delaiLecture = 0.25 self.initialiserGPIO() self.mettreAJourEtat() def initialiserGPIO(self): """Configure les broches du Raspberry Pi pour l'alarme.""" GPIO.setup(self.pinPir, GPIO.IN) GPIO.setup(self.pinBuzzer, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.pinLedRouge, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.pinLedVerte, GPIO.OUT, initial=GPIO.LOW) GPIO.setup(self.pinLedBleue, GPIO.OUT, initial=GPIO.LOW) for pin in self.lignes: GPIO.setup(pin, GPIO.OUT, initial=GPIO.LOW) for pin in self.colonnes: GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) def definirCouleur(self, rouge, vert, bleu): """ Allume la LED RGB selon la couleur voulue. Paramètres : - rouge : True / False - vert : True / False - bleu : True / False """ GPIO.output(self.pinLedRouge, GPIO.HIGH if rouge else GPIO.LOW) GPIO.output(self.pinLedVerte, GPIO.HIGH if vert else GPIO.LOW) GPIO.output(self.pinLedBleue, GPIO.HIGH if bleu else GPIO.LOW) def mettreAJourEtat(self): """ Met à jour les sorties selon l'état actuel du système. - desarme : LED verte, buzzer éteint - arme : LED bleue, buzzer éteint - alarme : LED rouge, buzzer allumé """ if self.etat == "desarme": self.definirCouleur(False, True, False) GPIO.output(self.pinBuzzer, GPIO.LOW) elif self.etat == "arme": self.definirCouleur(False, False, True) GPIO.output(self.pinBuzzer, GPIO.LOW) elif self.etat == "alarme": self.definirCouleur(True, False, False) GPIO.output(self.pinBuzzer, GPIO.HIGH) def armer(self): """Passe le système en mode armé.""" self.etat = "arme" self.codeSaisi = "" self.mettreAJourEtat() print("Alarme activée.") def desarmer(self): """Passe le système en mode désarmé.""" self.etat = "desarme" self.codeSaisi = "" self.mettreAJourEtat() print("Alarme désactivée.") def declencherAlarme(self): """ Déclenche l'alarme si un mouvement est détecté alors que le système est armé. """ if self.etat != "alarme": self.etat = "alarme" self.codeSaisi = "" self.mettreAJourEtat() print("Intrusion détectée : alarme déclenchée.") def lireClavier(self): """ Scanne le clavier 4x4. Retour : - la touche détectée - None si aucune touche n'est pressée """ maintenant = time.time() if maintenant - self.derniereLecture < self.delaiLecture: return None for indexLigne, ligne in enumerate(self.lignes): GPIO.output(ligne, GPIO.HIGH) for indexColonne, colonne in enumerate(self.colonnes): if GPIO.input(colonne) == GPIO.HIGH: GPIO.output(ligne, GPIO.LOW) self.derniereLecture = maintenant # Petite attente pour éviter la lecture multiple time.sleep(0.05) return self.touches[indexLigne][indexColonne] GPIO.output(ligne, GPIO.LOW) return None def validerCode(self): """ Vérifie le code saisi. Si le code est correct : - alarme désarmée -> armée - alarme armée -> désarmée - alarme déclenchée -> désarmée Si le code est faux : - on efface la saisie """ if self.codeSaisi == self.codeSecret: if self.etat == "desarme": self.armer() else: self.desarmer() else: print("Code incorrect.") self.codeSaisi = "" def traiterClavier(self, touche): """ Gère la logique du clavier : - chiffres : ajout au code saisi - * : efface la saisie - # : valide le code """ if touche is None: return print("Touche appuyée :", touche) if touche == "*": self.codeSaisi = "" print("Saisie effacée.") return if touche == "#": self.validerCode() return if touche.isdigit(): if len(self.codeSaisi) < 8: self.codeSaisi += touche print("Code en cours :", "*" * len(self.codeSaisi)) def surveillerPIR(self): """ Vérifie le capteur de mouvement. Si un mouvement est détecté alors que l'alarme est armée, on passe en état d'alarme. """ mouvement = GPIO.input(self.pinPir) == GPIO.HIGH if self.etat == "arme" and mouvement: self.declencherAlarme() def mettreAJour(self): """ Fonction appelée en boucle dans le programme principal. Elle : - lit le clavier - traite la touche appuyée - surveille le PIR - synchronise LED et buzzer avec l'état courant """ touche = self.lireClavier() self.traiterClavier(touche) self.surveillerPIR() self.mettreAJourEtat() def cleanup(self): """ Remet les sorties dans un état propre à la fermeture. """ GPIO.output(self.pinBuzzer, GPIO.LOW) self.definirCouleur(False, False, False)