UE1.3 · 5 ECTS

Réseaux & Protocoles IoT

25h CM + 25h TP — 6 séances. WiFi, MQTT, LoRa, sécurité et architecture cloud pour l'Internet des Objets. Maîtrisez les protocoles qui connectent les objets intelligents.

6 Séances 25h CM 25h TP 5 ECTS
1

Modèle OSI et protocoles réseau

Semaine 1CM+TP · 2h
Comprendre le modèle OSI à 7 couches
Savoir expliquer
Maîtriser les différences entre TCP et UDP
Savoir faire
Calculer les sous-réseaux et plages d'adresses IP
Savoir analyser
Diagnostiquer une connectivité avec ping et traceroute
Savoir produire

1. Modèle OSI — 7 couches

Le modèle OSI (Open Systems Interconnection) est un standard de communication en réseau divisé en 7 couches. Chaque couche fournit des services à la couche supérieure et consomme ceux de la couche inférieure. Dans l'IoT, les couches 1 (Physique), 3 (Réseau), 4 (Transport) et 7 (Application) sont essentielles.

CoucheNomRôleExemple IoT
7ApplicationInterface utilisateur/réseauMQTT, HTTP, CoAP
6PrésentationCodage, chiffrementTLS, JSON, CBOR
5SessionGestion des sessionsMQTT session persistante
4TransportFiabilité, segmentationTCP (MQTT), UDP (CoAP)
3RéseauRoutage, adressageIPv4, IPv6, 6LoWPAN
2LiaisonAccès au médiaWiFi 802.11, LoRa, BLE
1PhysiqueTransmission bitsRF 2.4 GHz, 868 MHz

2. TCP vs UDP

TCP (Transmission Control Protocol) est orienté connexion, fiable et ordonné — idéal pour MQTT et HTTP. UDP (User Datagram Protocol) est sans connexion, plus rapide mais sans garantie — utilisé par CoAP, DNS, DHCP.

PropriétéTCPUDP
ConnexionOrienté connexion (3-way handshake)Sans connexion
FiabilitéAccusé de réception, retransmissionAucune garantie
OrdreMaintenuNon garanti
VitessePlus lent (overhead)Rapide
Cas IoTMQTT, HTTP/2, WebSocketCoAP, LoRaWAN, DNS

3. Adressage IP et sous-réseaux

Une adresse IPv4 est codée sur 32 bits (4 octets). Le masque de sous-réseau détermine la partie réseau et la partie hôte. Exemple : 192.168.1.0/24 signifie masque 255.255.255.0 soit 256 adresses dont 254 utilisables pour les hôtes.

💡 Calcul rapide
192.168.1.0/24 → 28 - 2 = 254 hôtes. Plage : 192.168.1.1 à 192.168.1.254. Broadcast : 192.168.1.255. Dans un sous-réseau /30, seules 2 adresses sont utilisables — idéal pour liaison point-à-point IoT.
calculs_reseau.pyPython
import ipaddress

reseau = ipaddress.IPv4Network("192.168.1.0/24", strict=False)
print(f"Réseau : {reseau.network_address}")
print(f"Masque : {reseau.netmask}")
print(f"Broadcast : {reseau.broadcast_address}")
print(f"Nombre d'hôtes : {reseau.num_addresses - 2}")
print(f"Plage : {list(reseau.hosts())[0]} – {list(reseau.hosts())[-1]}")

# Sous-réseau pour liaison IoT (/30)
lien_iot = ipaddress.IPv4Network("10.0.0.0/30", strict=False)
print(f"Adresse lien IoT : {list(lien_iot.hosts())[0]}")
# → 10.0.0.1 et 10.0.0.2 utilisables

4. Commandes de diagnostic réseau

TerminalBash
ping 192.168.1.1              # Tester la connectivité
ping -c 4 google.com          # 4 paquets seulement

traceroute 8.8.8.8            # Chemin vers DNS Google (macOS)
traceroute -n 8.8.8.8         # Sans résolution DNS

ipconfig getifaddr en0        # IP locale macOS
ip a                          # IP locale Linux/WSL

nslookup google.com           # Résolution DNS
netstat -an | grep :1883      # Voir connexions MQTT
Exercice 1 — Modèle OSI et protocoles réseau

a) Identifiez à quelle couche OSI appartiennent : LoRa, WiFi 802.11, MQTT, IP, TLS, Ethernet. Justifiez chaque réponse.

b) Calculez le nombre d'hôtes disponibles pour les masques : /25, /26, /27, /28, /29, /30. Quel masque recommandez-vous pour connecter 12 capteurs IoT ?

c) Sur le réseau 10.0.50.0/24, déterminez : adresse réseau, broadcast, plage hôtes, et nombre total d'adresses utilisables.

d) BONUS — Écrivez un script Python qui prend une adresse IP et un masque, et affiche toutes les informations du sous-réseau.

✓ Corrigé 1

a) LoRa = Couche 1 (Physique) + Couche 2 (Liaison) ; WiFi 802.11 = Couches 1+2 ; MQTT = Couche 7 (Application) ; IP = Couche 3 (Réseau) ; TLS = Couche 5-6 (Session/Présentation) ; Ethernet = Couches 1+2.

b) /25=126, /26=62, /27=30, /28=14, /29=6, /30=2. Pour 12 capteurs → /27 (30 hôtes) pour avoir de la marge.

c) 10.0.50.0/24 : réseau=10.0.50.0, broadcast=10.0.50.255, plage=10.0.50.1–10.0.50.254, 254 hôtes.

2

WiFi et connexion IoT avec ESP32

Semaine 2CM+TP · 2h
Comprendre les normes WiFi (802.11 b/g/n/ac/ax)
Savoir expliquer
Configurer SSID, WPA2/WPA3 et analyser RSSI
Savoir faire
Connecter un ESP32 à un point d'accès WiFi
Savoir analyser
Diagnostiquer la qualité du signal WiFi
Savoir produire

1. Normes WiFi pour l'IoT

Le WiFi est le protocole réseau local le plus répandu. Pour l'IoT, les normes les plus pertinentes sont le WiFi 4 (802.11n, 2.4 GHz) pour sa portée et sa compatibilité, et le WiFi 6 (802.11ax) pour sa gestion efficace de nombreux périphériques. L'ESP32 supporte le 802.11 b/g/n en 2.4 GHz.

NormeBandeDébit maxPortéeIoT
802.11b2.4 GHz11 Mbps~50 mLegacy
802.11g2.4 GHz54 Mbps~50 mESP8266
802.11n2.4/5 GHz600 Mbps~70 mESP32
802.11ax (WiFi 6)2.4/5/6 GHz9.6 Gbps~70 mIoT massif

2. SSID, sécurité et RSSI

Le SSID est le nom du réseau WiFi. La sécurité repose sur WPA2 (standard) ou WPA3 (récent). Le RSSI (Received Signal Strength Indicator) mesure la puissance du signal reçu, en dBm. Plus la valeur est proche de 0, meilleur est le signal.

💡 Interprétation RSSI

RSSI de -50 à -70 dBm : Bon signal, connexion stable pour l'IoT.

RSSI < -80 dBm : Mauvais signal, pertes de paquets probables, déconnexions possibles.

RSSI = -30 dBm : Excellent signal (à moins d'1 mètre du point d'accès).

esp32_wifi_scan.inoArduino (ESP32)
#include <WiFi.h>

void setup() {
  Serial.begin(115200);

  WiFi.mode(WIFI_STA);
  WiFi.disconnect();
  delay(100);
  Serial.println("Scan WiFi en cours...");
}

void loop() {
  int n = WiFi.scanNetworks();
  if (n == 0) {
    Serial.println("Aucun réseau trouvé");
  } else {
    Serial.printf("%d réseau(x) trouvé(s)\n", n);
    for (int i = 0; i < n; i++) {
      Serial.printf("  %d: %s | RSSI: %d dBm | %s\n",
        i + 1,
        WiFi.SSID(i).c_str(),
        WiFi.RSSI(i),
        WiFi.encryptionType(i) == WIFI_AUTH_OPEN ? "Ouvert" : "Sécurisé"
      );
    }
  }
  delay(10000);
}

3. Connexion ESP32 au WiFi

esp32_wifi_connect.inoArduino (ESP32)
#include <WiFi.h>

const char* SSID     = "MUST_IoT_Lab";
const char* PASSWORD = "MotDePasseWiFi";

void setup() {
  Serial.begin(115200);
  Serial.printf("Connexion à %s...\n", SSID);

  WiFi.begin(SSID, PASSWORD);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("\n✓ Connecté !");
  Serial.printf("IP : %s\n", WiFi.localIP().toString().c_str());
  Serial.printf("RSSI : %d dBm\n", WiFi.RSSI());
}

void loop() {
  long rssi = WiFi.RSSI();
  Serial.printf("RSSI: %d dBm — ", rssi);

  if (rssi > -50)       Serial.println("Excellent");
  else if (rssi > -70)  Serial.println("Bon");
  else if (rssi > -80)  Serial.println("Moyen");
  else                    Serial.println("Mauvais");

  delay(5000);
}
Exercice 2 — WiFi et connexion IoT

a) Scannez les réseaux WiFi environnants avec l'ESP32. Affichez SSID, RSSI et type de sécurité pour chaque réseau.

b) Connectez l'ESP32 à un point d'accès WiFi. Affichez l'adresse IP obtenue et le RSSI initial.

c) Déplacez l'ESP32 et observez l'évolution du RSSI. À partir de quelle distance le signal passe-t-il sous -80 dBm ?

d) BONUS — Programmez l'ESP32 pour qu'il tente de se reconnecter automatiquement en cas de perte de connexion, avec un message sur le port série.

✓ Corrigé 2 — Reconnexion automatique
esp32_wifi_reconnect.inoArduino (ESP32)
#include <WiFi.h>

const char* SSID = "MUST_IoT_Lab";
const char* PWD  = "MotDePasseWiFi";

void setup() {
  Serial.begin(115200);
  WiFi.begin(SSID, PWD);
  Serial.print("Connexion");
}

void reconnect_wifi() {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("\n⚠ Connexion perdue. Reconnexion...");
    WiFi.disconnect();
    WiFi.begin(SSID, PWD);
    while (WiFi.status() != WL_CONNECTED) {
      delay(500); Serial.print(".");
    }
    Serial.println("\n✓ Reconnecté !");
  }
}

void loop() {
  reconnect_wifi();
  Serial.printf("RSSI: %d dBm\n", WiFi.RSSI());
  delay(10000);
}
3

MQTT — Publish/Subscribe pour IoT

Semaine 3CM+TP · 2h
Comprendre le modèle publish/subscribe MQTT
Savoir expliquer
Installer et configurer un broker Mosquitto
Savoir faire
Utiliser les topics hiérarchiques et les wildcards
Savoir analyser
Publier et s'abonner depuis ESP32 et Python
Savoir produire

1. Protocole MQTT

MQTT (Message Queuing Telemetry Transport) est un protocole publish/subscribe léger conçu pour l'IoT. Il fonctionne au-dessus de TCP/IP et permet une communication asynchrone entre des appareils avec un en-tête minimal (2 octets seulement). Un broker central gère la distribution des messages.

📖 Concepts clés MQTT

Broker : Serveur central (Mosquitto, HiveMQ, EMQX) qui reçoit les publications et les redistribue aux abonnés.

Topic : Chaîne hiérarchique qui identifie un flux de données. Ex: must/toliara/batiment-A/salle-1/temperature.

Retained message : Dernier message conservé par le broker. Tout nouvel abonné le reçoit immédiatement.

QoS : Quality of Service — 0 (au plus une fois), 1 (au moins une fois), 2 (exactement une fois).

2. Topics hiérarchiques et wildcards

Les topics MQTT sont organisés hiérarchiquement avec des slashs. Deux wildcards permettent de s'abonner à plusieurs topics à la fois :

WildcardDescriptionExemple
+Remplace UN niveaumust/+/temperature → capte tous les bâtiments
#Remplace TOUS les niveaux restantsmust/toliara/# → capte tout le campus
Bash
# Installation broker Mosquitto (macOS)
brew install mosquitto

# Démarrer le broker
mosquitto -v

# Dans un autre terminal — s'abonner à un topic
mosquitto_sub -h localhost -t "must/toliara/#" -v

# Publier un message
mosquitto_pub -h localhost -t "must/toliara/batiment-A/salle-1/temperature" \
  -m "28.5" -r

# Avec wildcards
mosquitto_sub -h localhost -t "must/+/temperature" -v
mosquitto_sub -h localhost -t "must/toliara/#" -v

3. MQTT depuis ESP32

esp32_mqtt_dht.inoArduino (ESP32)
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>

const char* SSID        = "MUST_IoT_Lab";
const char* PASSWORD    = "MotDePasseWiFi";
const char* MQTT_BROKER = "192.168.1.100";
const int   MQTT_PORT   = 1883;
const char* TOPIC_TEMP  = "must/toliara/batiment-A/salle-1/temperature";
const char* TOPIC_HUM   = "must/toliara/batiment-A/salle-1/humidite";
const char* CLIENT_ID   = "esp32-salle1";

WiFiClient espClient;
PubSubClient mqtt(espClient);
DHT dht(4, DHT22);

void reconnect() {
  while (!mqtt.connected()) {
    Serial.print("MQTT...");
    if (mqtt.connect(CLIENT_ID)) {
      Serial.println(" OK");
      mqtt.subscribe("must/toliara/batiment-A/commande");
    } else {
      Serial.printf(" Echec (%d)\n", mqtt.state());
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(SSID, PASSWORD);
  while (WiFi.status() != WL_CONNECTED) { delay(500); }
  mqtt.setServer(MQTT_BROKER, MQTT_PORT);
}

void loop() {
  if (!mqtt.connected()) reconnect();
  mqtt.loop();

  float temp = dht.readTemperature();
  float hum  = dht.readHumidity();

  mqtt.publish(TOPIC_TEMP, String(temp, 1).c_str(), true);
  mqtt.publish(TOPIC_HUM,  String(hum, 1).c_str(),  true);

  Serial.printf("Publié : T=%.1f°C H=%.1f%%\n", temp, hum);
  delay(10000);
}

4. Client MQTT en Python

mqtt_subscriber.pyPython
import paho.mqtt.client as mqtt

BROKER = "localhost"
TOPICS = [("must/toliara/#", 0)]

def on_message(client, userdata, msg):
    print(f"[{msg.topic}] {msg.payload.decode()}")

client = mqtt.Client()
client.on_message = on_message
client.connect(BROKER, 1883, 60)
client.subscribe(TOPICS)
print("En écoute sur must/toliara/# ...")
client.loop_forever()
Exercice 3 — MQTT Publish/Subscribe

a) Installez Mosquitto sur votre machine. Lancez le broker et testez avec mosquitto_pub et mosquitto_sub.

b) Connectez l'ESP32 avec un capteur DHT22 au broker MQTT. Publiez température et humidité sur des topics distincts toutes les 10 secondes.

c) Écrivez un abonné Python qui écoute tous les topics must/toliara/# et affiche les données en temps réel.

d) BONUS — Ajoutez un topic de commande : depuis Python, publiez "ON"/"OFF" sur un topic auquel l'ESP32 est abonné pour contrôler une LED à distance.

✓ Corrigé 3 — Contrôle LED via MQTT
esp32_mqtt_led.ino (extrait)Arduino (ESP32)
void callback(char* topic, byte* payload, unsigned int length) {
  String message;
  for (int i = 0; i < length; i++) message += (char)payload[i];

  if (String(topic) == "must/toliara/batiment-A/commande") {
    if (message == "ON")  { digitalWrite(LED_PIN, HIGH); Serial.println("LED ON"); }
    if (message == "OFF") { digitalWrite(LED_PIN, LOW);  Serial.println("LED OFF"); }
  }
}

// Dans setup()
mqtt.setCallback(callback);
mqtt.subscribe("must/toliara/batiment-A/commande");
4

LoRa et LPWAN pour zones rurales

Semaine 4CM+TP · 2h
Comprendre la technologie LoRa et ses avantages
Savoir expliquer
Comparer LoRaWAN, WiFi, BLE et NB-IoT
Savoir faire
Choisir la bonne technologie selon la distance et le débit
Savoir analyser
Programmer un émetteur/récepteur LoRa avec ESP32
Savoir produire

1. LoRa — Long Range, Low Power

LoRa (Long Range) est une technologie de modulation radio brevetée par Semtech qui permet de transmettre des données sur de très longues distances (2 à 15 km) avec une consommation électrique minimale (quelques mA). Elle utilise la bande ISM 868 MHz (Europe) ou 915 MHz (Amériques) sans licence. À Madagascar, la bande 868 MHz est libre d'utilisation.

TechnologiePortéeDébitConsommationCas d'usage
LoRa2–15 km0.3–50 kbps~10 mA émissionCapteurs agricoles, compteurs d'eau
WiFi~50 m100+ Mbps~100 mAStreaming, domotique intérieur
BLE~10 m1–2 Mbps~5 mAWearables, balises
NB-IoT1–10 km~200 kbps~10 mACompteurs, ville intelligente (4G)
⚠️ Compromis débit/portée

LoRa : 0.3 kbps à 15 km de portée — idéal pour quelques octets par heure (température, niveau d'eau).

WiFi : 100+ Mbps à 50 m — idéal pour la vidéo et les mises à jour firmware.

Plus le facteur d'étalement (SF) est élevé, plus la portée augmente mais plus le débit diminue.

2. LoRaWAN — L'architecture réseau

LoRaWAN est le protocole réseau qui définit l'architecture de communication : les capteurs (end devices) communiquent avec des gateways reliées à un serveur réseau. Les messages sont chiffrés de bout en bout (AES-128). Il existe 3 classes d'appareils :

  • Classe A (bidirectionnelle) : L'appareil envoie puis écoute brièvement. Défaut standard, consommation minimale.
  • Classe B (balises) : L'appareil s'ouvre périodiquement à des moments planifiés.
  • Classe C (écoute continue) : L'appareil écoute en permanence. Consommation maximale.

3. Communication LoRa avec modules SX1276/78

Les modules LoRa (SX1276, SX1278) se connectent à l'ESP32 via SPI. La bibliothèque LoRa.h simplifie l'envoi et la réception. Les paramètres clés sont la fréquence, le facteur d'étalement (SF7–SF12), la bande passante et le taux de codage.

lora_emetteur.inoArduino (ESP32)
#include <LoRa.h>

const long FREQUENCE = 868E6;  // 868 MHz (Europe/Madagascar)
const int SF = 12;             // Facteur d'étalement max portée
const int CS_PIN = 5;
const int RST_PIN = 14;
const int DIO0_PIN = 2;

void setup() {
  Serial.begin(115200);
  LoRa.setPins(CS_PIN, RST_PIN, DIO0_PIN);

  if (!LoRa.begin(FREQUENCE)) {
    Serial.println("Erreur LoRa !");
    while (1);
  }

  LoRa.setSpreadingFactor(SF);
  Serial.println("Émetteur LoRa prêt (868 MHz)");
}

int compteur = 0;

void loop() {
  float temperature = 28.5 + random(-10, 10) / 10.0;
  float humidite    = 65.0 + random(-5, 5) / 10.0;

  LoRa.beginPacket();
  LoRa.print("MUST_IOT,");
  LoRa.print(compteur);  LoRa.print(",");
  LoRa.print(temperature, 1); LoRa.print(",");
  LoRa.print(humidite, 1);
  LoRa.endPacket();

  Serial.printf("Paquet %d envoyé : T=%.1f H=%.1f\n",
    compteur, temperature, humidite);
  compteur++;
  delay(60000);
}
lora_recepteur.inoArduino (ESP32)
#include <LoRa.h>

const long FREQUENCE = 868E6;

void setup() {
  Serial.begin(115200);
  if (!LoRa.begin(FREQUENCE)) {
    Serial.println("Erreur LoRa !");
    while (1);
  }
  LoRa.setSpreadingFactor(12);
  Serial.println("Récepteur LoRa prêt");
}

void loop() {
  int taille = LoRa.parsePacket();
  if (taille == 0) return;

  String message = "";
  while (LoRa.available()) {
    message += (char)LoRa.read();
  }

  Serial.printf("Reçu [RSSI=%d dBm | SNR=%.1f dB] : %s\n",
    LoRa.packetRssi(),
    LoRa.packetSnr(),
    message.c_str());
}
Exercice 4 — LoRa et LPWAN

a) Câblez deux modules LoRa (SX1278) sur deux ESP32. Programmez l'émetteur et le récepteur.

b) Mesurez le RSSI et le SNR à différentes distances (5 m, 20 m, 100 m, si possible 500 m). Documentez les résultats.

c) Comparez la portée LoRa avec le WiFi (ESP32) : à quelle distance chaque technologie perd-elle la connexion ?

d) BONUS — Ajoutez un capteur DHT22 à l'émetteur et un affichage LCD I2C au récepteur pour créer une station météo LoRa complète.

✓ Corrigé 4 — Station météo LoRa

Le montage complet combine l'émetteur LoRa avec DHT22 et le récepteur avec LCD I2C. Les messages sont formatés en CSV : MUST_IOT,seq,temperature,humidite. Le facteur d'étalement SF12 offre la portée maximale mais réduit le débit à environ 300 bps — suffisant pour une mesure par minute.

5

Sécurité des réseaux IoT

Semaine 5CM+TP · 2h
Identifier les vecteurs d'attaque sur les réseaux IoT
Savoir expliquer
Configurer TLS sur MQTT (port 8883)
Savoir faire
Mettre en place l'authentification des appareils
Savoir analyser
Comprendre le firmware signing et la mise à jour sécurisée
Savoir produire

1. Enjeux de sécurité IoT

Les objets connectés sont souvent la cible d'attaques : prise de contrôle à distance, espionnage des données, botnets (Mirai). Les contraintes des appareils IoT (mémoire limitée, batterie, processeur lent) rendent la sécurité plus difficile. Les quatre piliers sont : l'authentification, le chiffrement, l'intégrité et la mise à jour.

Vecteur d'attaqueDescriptionMitigation
Écoute réseauCapture des paquets non chiffrésTLS/SSL sur MQTT (8883)
Appareil non authentifiéFaux capteur qui injecte des donnéesCertificats X.509 par appareil
Firmware non signéCode malveillant injecté lors de la MAJSignature cryptographique du firmware
Déni de serviceSaturation du broker MQTTRate limiting, quotas par client
Mot de passe faibleBrute-force sur le brokerAuthentification strong + MFA

2. TLS sur MQTT — Port 8883

Le MQTT standard (port 1883) transmet en clair. Pour sécuriser les échanges, on utilise MQTT over TLS (port 8883). Le broker Mosquitto peut être configuré avec un certificat serveur et optionnellement des certificats clients.

mosquitto_tls.confBash
# Configuration Mosquitto avec TLS
listener 8883
certfile /etc/mosquitto/certs/server.crt
keyfile  /etc/mosquitto/certs/server.key
tls_version tlsv1.2

# Authentification par certificat client optionnelle
require_certificate false
use_identity_as_username false

# Authentification par mot de passe
password_file /etc/mosquitto/passwd
esp32_mqtt_tls.inoArduino (ESP32)
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

const char* MQTT_BROKER = "broker.must-iot.mg";
const int   MQTT_PORT   = 8883;

// Certificat CA (Let's Encrypt, AutoSign, etc.)
static const char* CA_CERT = R"EOF(
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
...
-----END CERTIFICATE-----
)EOF";

WiFiClientSecure espClient;
PubSubClient mqtt(espClient);

void setup() {
  Serial.begin(115200);
  WiFi.begin("SSID", "PASS");
  while (WiFi.status() != WL_CONNECTED) delay(500);

  espClient.setCACert(CA_CERT);
  // Optionnel : certificat client
  // espClient.setCertificate(CLIENT_CERT);
  // espClient.setPrivateKey(PRIVATE_KEY);

  mqtt.setServer(MQTT_BROKER, MQTT_PORT);
  mqtt.connect("esp32-must-01", "username", "password");
  Serial.println("MQTT TLS connecté sur port 8883 ✓");
}

3. Authentification et intégrité des firmwares

Le firmware signing garantit que le code exécuté par l'appareil provient bien du fabricant. La signature numérique (RSA ou ECDSA) est vérifiée au démarrage. L'OTA sécurisé utilise HTTPS/TLS et vérifie la signature avant d'appliquer la mise à jour.

💡 Bonnes pratiques
  • Changez les mots de passe par défaut (admin/admin, root/root)
  • Utilisez MQTT sur port 8883 (TLS) — jamais 1883 en production
  • Désactivez les ports et services inutiles sur les appareils
  • Segmentez le réseau IoT (VLAN dédié) du réseau principal
  • Auditez régulièrement les appareils connectés
Exercice 5 — Sécurité IoT

a) Générez une autorité de certification (CA) auto-signée et un certificat serveur avec OpenSSL.

b) Configurez Mosquitto avec TLS sur le port 8883. Testez la connexion avec mosquitto_pub et mosquitto_sub en TLS.

c) Connectez l'ESP32 au broker sécurisé (TLS). Vérifiez que la communication est chiffrée en capturant les paquets avec Wireshark.

d) BONUS — Ajoutez certificat client et mots de passe. Implémentez un mécanisme de firmware signing avec une clé privée RSA 2048 bits.

✓ Corrigé 5 — Génération certificats OpenSSL
Bash
# 1. Créer l'Autorité de Certification (CA)
openssl req -new -x509 -days 3650 -extensions v3_ca \
  -keyout ca.key -out ca.crt \
  -subj "/C=MG/ST=Toliara/L=Toliara/O=MUST/CN=CA IoT MUST"

# 2. Créer le certificat serveur
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr \
  -subj "/C=MG/ST=Toliara/O=MUST/CN=broker.must-iot.mg"
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
  -CAcreateserial -out server.crt -days 365

# 3. Vérifier
openssl verify -CAfile ca.crt server.crt
6

Architecture Cloud IoT

Semaine 6CM+TP · 2h
Comprendre l'architecture d'une plateforme Cloud IoT
Savoir expliquer
Configurer AWS IoT Core ou Azure IoT Hub
Savoir faire
Visualiser les données IoT avec Grafana et InfluxDB
Savoir analyser
Mettre en place un pipeline IoT complet du capteur au dashboard
Savoir produire

1. Architecture Cloud IoT

Une architecture Cloud IoT typique comprend 4 couches : les capteurs/actionneurs (périphérie), la connectivité (passerelle), le cloud (ingestion/stockage/analyse) et la visualisation (dashboard). AWS IoT Core et Azure IoT Hub sont les deux plateformes les plus utilisées.

CoucheComposantRôle
1 — PériphérieESP32, capteurs, actionneursAcquisition et action
2 — ConnectivitéWiFi, LoRa, MQTT brokerTransport des données
3 — CloudAWS IoT / Azure IoT / InfluxDBIngestion, stockage, règles
4 — VisualisationGrafana, Node-RED dashboardAffichage et alertes

2. AWS IoT Core et Azure IoT Hub

FonctionnalitéAWS IoT CoreAzure IoT Hub
ProtocoleMQTT, HTTP, WebSocketMQTT, HTTPS, AMQP
AuthentificationCertificats X.509, IAMSAS tokens, X.509, AD
RèglesAWS IoT Rules → S3, DynamoDBMessage Routing → Storage, Functions
ChiffrementTLS 1.2+TLS 1.2+
CoûtPay-as-you-go (messages)Pay-as-you-go (messages)

3. Pipeline complet — ESP32 → MQTT → InfluxDB → Grafana

Une solution 100% open source pour visualiser les données IoT : l'ESP32 publie en MQTT, Telegraf collecte et écrit dans InfluxDB (base de données time-series), et Grafana affiche les dashboards en temps réel.

docker-compose.ymlYAML
version: "3.8"
services:
  mosquitto:
    image: eclipse-mosquitto
    ports:
      - "1883:1883"
      - "8883:8883"

  telegraf:
    image: telegraf
    depends_on: [mosquitto, influxdb]
    volumes:
      - ./telegraf.conf:/etc/telegraf/telegraf.conf

  influxdb:
    image: influxdb:2
    ports:
      - "8086:8086"
    environment:
      DOCKER_INFLUXDB_INIT_MODE: setup
      DOCKER_INFLUXDB_INIT_USERNAME: admin
      DOCKER_INFLUXDB_INIT_PASSWORD: password
      DOCKER_INFLUXDB_INIT_ORG: MUST
      DOCKER_INFLUXDB_INIT_BUCKET: iot

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    depends_on: [influxdb]
telegraf.confTOML
[[inputs.mqtt_consumer]]
  servers     = ["tcp://mosquitto:1883"]
  topics      = ["must/toliara/#"]
  data_format = "value"
  name_override = "capteurs"

[[outputs.influxdb_v2]]
  urls        = ["http://influxdb:8086"]
  token       = "mon_token_influxdb"
  organization = "MUST"
  bucket      = "iot"

4. Dashboard Grafana

Grafana permet de créer des dashboards interactifs avec des graphiques, jauges et alertes. Les variables de template (ex: capteur_id, bâtiment) filtrent dynamiquement les données.

💡 Variables Grafana

Créez une variable $capteur avec la requête InfluxDB : SHOW TAG VALUES ON "iot" FROM "capteurs" WITH KEY = "device". Les panneaux utiliseront WHERE device = '$capteur' pour filtrer automatiquement.

Exercice 6 — Architecture Cloud IoT

a) Déployez la stack Docker : Mosquitto + Telegraf + InfluxDB + Grafana avec docker-compose.

b) Configurez l'ESP32 pour publier les données sur Mosquitto. Vérifiez que Telegraf les consomme et les écrit dans InfluxDB.

c) Créez un dashboard Grafana avec 3 panneaux : température (line chart), humidité (jauge) et nombre de messages reçus (stat).

d) BONUS — Ajoutez une alerte Grafana : si température > 40°C, envoyez une notification par email ou WebHook.

✓ Corrigé 6 — Pipeline IoT complet
Vérification pipelineBash
# 1. Lancer la stack
docker-compose up -d

# 2. Vérifier Mosquitto
docker logs mosquitto

# 3. Voir les données dans InfluxDB
docker exec influxdb influx query \
  'from(bucket:"iot") |> range(start:-1h)'

# 4. Accéder à Grafana sur http://localhost:3000
# 5. Ajouter InfluxDB comme datasource (URL: http://influxdb:8086)
# 6. Créer un dashboard : Panel type "Time series" avec la requête
#    from(bucket:"iot") |> range(start:-1h) |> filter(fn:(r)=>r._field=="temperature")