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

  1. Modéliser le comportement d’un système d’alarme complexe (Machine à États).
  2. Comprendre la syntaxe YAML utilisée par ESPHome et Home Assistant.
  3. 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

  1. Ouvrez le fichier secu00_base.yaml.
  2. Téléversez-le sur votre carte ESP32-S3.
  3. 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 :

  1. Attend 10 secondes.
  2. Vérifie si on est toujours en état “Armement en cours” (État 3).
  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)

  1. Persistance : Faites en sorte que l’état de l’alarme soit mémorisé même si on débranche la carte (restore_value: yes).
  2. Flash Caméra : Ajoutez une action pour prendre une photo (snapshot) automatiquement lors d’une intrusion.
  3. Code PIN : (Avancé) Utilisez Home Assistant pour exiger un code PIN virtuel avant de pouvoir désarmer.