TP : Modélisation et Implémentation d’un Système de Sécurité IoT
Durée : 3h – 4h Matériel : Kit ESP32-S3 Freenove (Laser, PIR, Caméra) Documentation Officielle : https://esphome.io/
🎯 Objectifs
- Modéliser le comportement d’un système d’alarme complexe (Machine à États).
- Comprendre la syntaxe YAML utilisée par ESPHome et Home Assistant.
- Implémenter une logique conditionnelle et temporelle sur un microcontrôleur.
📂 Fichiers fournis
secu00_base.yaml: Le code “squelette” contenant la configuration matérielle (WiFi, Pins, Capteurs, Caméra) mais aucune logique.
Partie 1 : Prise en main et Analyse
- Ouvrez le fichier
secu00_base.yaml. - Téléversez-le sur votre carte ESP32-S3.
- Ouvrez l’interface web de la carte (ou Home Assistant) et testez les composants un par un :
- Appuyez sur le bouton “BOOT” : Vérifiez qu’un message apparaît dans les Logs.
- Passez la main devant le PIR : Vérifiez le log.
- Coupez le faisceau Laser : Vérifiez le log.
- Allumez le Laser et la LED RGB manuellement.
Question : Pourquoi rien ne se passe (pas de clignotement, pas d’armement) quand vous appuyez sur le bouton pour l’instant ?
Partie 2 : Modélisation (UML)
Avant de coder, vous devez définir comment le système réagit. Dessinez le Diagramme d’État (State Machine) du système.
Les États à gérer :
- 0 : DÉSARMÉ (Repos, LED Verte).
- 1 : ARMÉ (Surveillance active, Laser Allumé, LED Rouge).
- 2 : INTRUSION (Alerte déclenchée, Sirène/Strobe Police).
- 3 : ARMEMENT EN COURS (Temporisation de 10s avant d’être armé, LED Jaune clignotante).
Les Transitions à définir :
- Que se passe-t-il si j’appuie sur le bouton quand je suis en 0 ?
- Que se passe-t-il si le délai de 10s se termine quand je suis en 3 ?
- Que se passe-t-il si j’appuie sur le bouton (Annulation) quand je suis en 3 ?
- Que se passe-t-il si le PIR détecte un mouvement quand je suis en 1 ? Et en 0 ?
Avant de commencer à écrire, il est crucial de comprendre comment vos diagrammes se traduisent dans le langage d’ESPHome. Le YAML n’est pas magique : c’est simplement une description textuelle de votre modèle.
Voici le dictionnaire de traduction UML ESPHome.
1. Le Diagramme de Composants (Matériel)
Ce diagramme définit “Qui est connecté où”.
| Concept UML | Concept ESPHome (YAML) | Exemple |
|---|---|---|
| Interface / Port | pin: |
pin: 40 |
| Acteur (Sortie) | output: ou light: |
light: ... id: laser |
| Capteur (Entrée) | binary_sensor: ou sensor: |
binary_sensor: ... id: pir |
Exemple de traduction :
En UML, le Laser est connecté au Port 40.
En YAML :
output: - platform: gpio pin: 40
2. Le Diagramme d’État (Logique)
Ce diagramme définit “Comment le système réagit aux événements”. C’est le cœur de votre TP.
| Concept UML | Concept ESPHome (YAML) | Exemple |
|---|---|---|
| État (State) | Variable Globale (globals) |
id(etat_alarme) == 1 |
| Événement (Event) | Déclencheur (on_...) |
on_press: (Bouton appuyé) |
Garde (Guard) [Si Armé] |
Condition (if) |
if: condition: ... |
| Transition | Action d’écriture (set) |
globals.set: value: '2' |
| Action | Action physique | light.turn_on: |
Exemple de traduction :
En UML : Transition de “Armé” vers “Intrusion” déclenchée par le PIR.
Armed –(Mouvement [Si Armé])–> Intrusion / Allumer Sirène
En YAML :
# L'Événement (Mouvement) on_press: - if: # La Garde [Si Armé] condition: lambda: 'return id(etat_alarme) == 1;' then: # La Transition (Changement d'état) - globals.set: id: etat_alarme value: '2' # L'Action (Allumer Sirène) - light.turn_on: siren
3. Le Diagramme de Séquence (Temps)
Ce diagramme gère la chronologie, notamment les délais.
| Concept UML | Concept ESPHome (YAML) |
|---|---|
| Ligne de vie (Lifeline) | Le composant esphome principal |
| Délai / Timer | script: avec delay: |
| Message Asynchrone | script.execute: |
Astuce pour le TP :
Si votre diagramme de séquence montre une attente de 10 secondes pendant laquelle le système ne doit pas être bloqué, vous DEVEZ utiliser un script. Si vous utilisez juste delay: 10s dans un bouton, tout le reste (capteurs, WiFi) sera gelé pendant 10 secondes !
Partie 3 : Mémento Syntaxe YAML (Aide)
Vous n’avez jamais fait de YAML ? Pas de panique. Voici les structures dont vous aurez besoin. Adaptez ces exemples à votre projet.
A. Créer une variable (Mémoire)
Pour stocker l’état (0, 1, 2, 3), on utilise une variable globale (int).
Documentation : ESPHome Globals
globals:
- id: ma_variable_memoire
type: int
restore_value: no
initial_value: '0'
B. Lire et Modifier la variable
Dans une automatisation (ex: on_press), on utilise globals.set pour écrire et une petite ligne de C++ (Lambda) pour lire.
on_press:
# Lire la variable (Condition)
- if:
condition:
lambda: 'return id(ma_variable_memoire) == 5;' # Si la variable vaut 5
# Modifier la variable (Action)
then:
- globals.set:
id: ma_variable_memoire
value: '10'
C. Structure Conditionnelle (If / Then / Else)
C’est la base de toute logique. Documentation : Automations
on_press:
- if:
condition:
# Votre condition ici
lambda: 'return id(mon_capteur).state == true;'
then:
# Actions si VRAI
- logger.log: "C'est Vrai !"
- light.turn_on: ma_lumiere
else:
# Actions si FAUX
- logger.log: "C'est Faux !"
- light.turn_off: ma_lumiere
D. Gérer le Temps (Script)
Pour faire un délai (compte à rebours) sans bloquer la carte, on utilise un script. Documentation : Script Component
1. Définir le script :
script:
- id: mon_compte_a_rebours
then:
- delay: 5s
- logger.log: "5 secondes écoulées !"
# Ici, vous pouvez changer l'état de la variable globale
2. Lancer ou Stopper le script (depuis un bouton) :
on_press:
- script.execute: mon_compte_a_rebours
# ou pour annuler :
- script.stop: mon_compte_a_rebours
E. Contrôler la LED RGB et le Texte
Documentation : Light Component
# Allumer en Rouge
- light.turn_on:
id: board_led
red: 100%
green: 0%
blue: 0%
effect: "none" # Important pour arrêter un clignotement précédent
# Lancer un effet spécial (défini dans le squelette)
- light.turn_on:
id: board_led
effect: "Police Mode"
# Mettre à jour le texte de statut (Feedback utilisateur)
- lambda: 'id(etat_texte).publish_state("MON NOUVEAU TEXTE");'
Partie 4 : Implémentation
À vous de jouer ! Modifiez le fichier secu00_base.yaml pour implémenter votre diagramme d’état. Procédez par étapes :
Étape 1 : La Mémoire
Ajoutez la section globals pour créer une variable etat_alarme initialisée à 0.
Étape 2 : Le Délai d’Armement
Créez un script qui :
- Attend 10 secondes.
- Vérifie si on est toujours en état “Armement en cours” (État 3).
- Si oui, passe la variable à “Armé” (État 1), allume le Laser et met la LED en Rouge.
Étape 3 : Le Cerveau (Bouton Alarme)
Modifiez le on_press du boot_button. Il doit gérer la logique principale :
- Si on est Désarmé (0) : On passe en “En cours” (3), on lance le script, on met la LED en Jaune.
- Sinon (Pour tout le reste) : On repasse à 0, on STOPPE le script (très important !), on éteint le Laser et on met la LED en Vert.
Étape 4 : Les Déclencheurs (PIR et Laser)
Modifiez le pir et le laser_beam_status.
- Ajoutez une condition : Ils ne doivent déclencher l’alarme QUE SI la variable est à 1 (Armé).
- Si la condition est vraie : Passez la variable à 2 (Intrusion) et lancez l’effet “Police Mode”.
🚀 Pour aller plus loin (Bonus)
- Persistance : Faites en sorte que l’état de l’alarme soit mémorisé même si on débranche la carte (
restore_value: yes). - Flash Caméra : Ajoutez une action pour prendre une photo (snapshot) automatiquement lors d’une intrusion.
- Code PIN : (Avancé) Utilisez Home Assistant pour exiger un code PIN virtuel avant de pouvoir désarmer.