Projet IUT R&T • SAE 204 • Semestre 2 • 10 mars → 11 juin 2026

Sonde Météorologique

Analyse et gestion thermique en milieu éducatif.

L'objectif de ce projet est d'étudier la gestion thermique dans une salle de classe. Les données environnementales (UV et luminosité) sont captées par un microcontrôleur STM32 WB55, transmises en Bluetooth Low Energy vers un Raspberry Pi, acheminées via MQTT vers un VPS, stockées en base de données et visualisées sur Grafana et un afficheur M5Stack.

1. Objectif et Problématique

Comment mesurer et analyser en temps réel les conditions environnementales d'une salle de classe (UV, luminosité, température, humidité, pression) pour optimiser le confort thermique des occupants ? La démarche s'appuie sur un diagramme des exigences qui modélise notre problématique centrale.

┌──────────────────────────────────────────────────────────────┐
│                  Sonde Météorologique SAE:204                │
│              Gestion thermique en salle de classe            │
└──────────────────┬───────────────────────────────────────────┘
                   │
       ┌───────────┼────────────┐
       ▼           ▼            ▼
┌─────────────┐ ┌──────────────┐ ┌─────────────────┐
│  Acquisition │ │ Transmission │ │    Affichage     │
│  des données │ │  sans fil    │ │   des données    │
│   (capteurs) │ │    (BLE)     │ │   (M5Stack +     │
│              │ │              │ │    Grafana)      │
└──────┬───────┘ └──────────────┘ └─────────────────┘
       │
  ┌────┴──────────────┐
  ▼                   ▼
Mesurer UV       Mesurer Temp.
& Luminosité     Humidité & Pression
            

2. Matériel nécessaire

L'ensemble du matériel est fourni par l'IUT (kit environnement prêté), à l'exception du VPS utilisé pour le broker MQTT.

2× STM32 WB55 (Nucleo)

Microcontrôleur principal du projet. Il lit les capteurs Grove (UV + lumière) et émet les données via Bluetooth Low Energy sous le nom Sonde_V3. Bibliothèque STM32duinoBLE v1.4.1. Firmware BLE coprocesseur RF v16.12.0.27.

  • ADC 12 bits (valeurs 0–4095)
  • Broche UV : PA0 (capteur GUVA-S12D)
  • Broche lumière : PA1 (capteur Grove v1.2)
  • Upload via STM32CubeProgrammer (SWD)

Kit Environnement (prêté)

Ensemble de capteurs analogiques montés sur shield :

  • Capteur UV Grove GUVA-S12D — sortie tension → indice UV 0–12 via table Seeed officielle
  • Capteur de lumière Grove v1.2 — luminosité en pourcentage
  • 2 câbles shield de connexion

Raspberry Pi 3B+

Passerelle BLE → MQTT. Il reçoit les données en Bluetooth Low Energy depuis la STM32 (via bleak) et les publie sur le broker Mosquitto du VPS (via paho-mqtt). Stocke également un historique CSV horodaté sur carte microSD 32 Go.

  • OS : Raspberry Pi OS 64-bit Lite
  • Python 3 + bleak + paho-mqtt
  • Connecté via hotspot mobile (eduroam incompatible)
  • Accès VPS via clé SSH ed25519

Afficheur 2Core M5Stack

Interface visuelle temps réel. Affiche l'indice UV et la luminosité. Passe en mode alerte si déconnecté du broker MQTT.

  • Connexion Wi-Fi → broker Mosquitto VPS
  • Abonnement au topic sonde/meteo
  • Reconnexion automatique si perte réseau
  • Interface designée et codée par Unsal

Infrastructure VPS + VMs

Un VPS Ionos (broker MQTT Mosquitto central) héberge le point de collecte des données. Quatre machines virtuelles KVM/QEMU tournent sur le réseau privé de l'IUT (10.144.x.x) :

  • VM MariaDB — stockage SQL des mesures brutes
  • VM InfluxDB — séries temporelles
  • VM Grafana — dashboards temps réel (port 3000)
  • VM Icinga2 — supervision réseau + IcingaWeb2

Stockage local

Carte microSD 32 Go insérée dans le Raspberry Pi pour la persistance locale des données en cas de coupure réseau.

  • Fichiers CSV horodatés : sonde_YYYY-MM-DD.csv
  • Répertoire : ./data_sonde/
  • Publication simultanée sur MQTT et écriture CSV

3. Architecture technique — Flux de données

Les données traversent cinq couches depuis les capteurs physiques jusqu'aux dashboards de visualisation. Chaque étape a été testée et validée par le membre responsable.

 ┌─────────────────────────────────────────────────────────────────────┐
 │  STM32 WB55                                                         │
 │  Capteurs : UV (GUVA-S12D) · Luminosité (Grove v1.2)               │
 │  ↓ Émission BLE  (nom : "Sonde_V3", 2 caractéristiques GATT)       │
 └──────────────────────────────┬──────────────────────────────────────┘
                                │  Bluetooth Low Energy
 ┌──────────────────────────────▼──────────────────────────────────────┐
 │  Raspberry Pi 3B+                                                   │
 │  Script ble-rpi.py (bleak) → lit les 2 chars GATT                  │
 │  ↓ Publication MQTT  (topic : sonde/meteo)                          │
 │  ↓ Écriture CSV horodatée sur microSD 32 Go                        │
 └──────────────────────────────┬──────────────────────────────────────┘
                                │  MQTT via réseau mobile / internet
 ┌──────────────────────────────▼──────────────────────────────────────┐
 │  VPS Ionos — Broker Mosquitto                                       │
 │  Auth. par login/mot de passe · accès anonyme désactivé            │
 │  Script vps-bridge.py → monitoring temps réel en console           │
 │  ↓ Distribution aux VMs (réseau privé)                             │
 └──────┬───────────────────────────────────────────────┬─────────────┘
        │                                               │
 ┌──────▼──────────────┐                    ┌──────────▼──────────────┐
 │  VM MariaDB         │                    │  VM InfluxDB            │
 │  Stockage SQL brut  │                    │  Séries temporelles     │
 └──────┬──────────────┘                    └──────────┬──────────────┘
        └──────────────────┬────────────────────────────┘
                           │
                  ┌────────▼────────┐       ┌─────────────────────────┐
                  │  VM Grafana     │       │  M5Stack (Wi-Fi MQTT)   │
                  │  Dashboards     │       │  UV · Luminosité        │
                  │  port :3000     │       │  Reconnexion auto       │
                  └─────────────────┘       └─────────────────────────┘
                           │
                  ┌────────▼────────┐
                  │  VM Icinga2     │
                  │  Supervision    │
                  │  IcingaWeb2     │
                  └─────────────────┘
                
⚠️ Contrainte réseau résolue : Le réseau eduroam de l'IUT (WPA2-Enterprise) est incompatible avec Raspberry Pi OS Lite. Solution retenue : hotspot mobile personnel pour connecter le RPi à internet, et un VPS Ionos avec IP publique comme broker MQTT central, accessible depuis n'importe quel réseau.

4. Code Source

Voici l'intégralité des scripts développés par l'équipe, dans leur version finale déposée sur HUBJ Teams le 11 juin 2026. Les données sensibles (identifiants, adresses réseau) ont été retirées.

helina.ino — STM32 WB55 : acquisition UV + Lumière + émission BLE Arduino / C++ ✍️ Helina & Unsal — 11/06/2026
// Projet : SAE 204 - Sonde Météo (Mode UV & Lumière)
#include <STM32duinoBLE.h>

#define PIN_A A0   // Capteur UV  (GUVA-S12D)
#define PIN_B A1   // Capteur Lumière (Grove v1.2)

// ── Service BLE et 2 caractéristiques GATT ──────────────────────────
BLEService meteoService("19B10000-E8F2-537E-4F6C-D104768A1214");

BLEFloatCharacteristic uvCharacteristic   ("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);
BLEFloatCharacteristic lightCharacteristic("19B10002-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify);

// ── Table officielle Seeed GUVA-S12D : tension (mV) → indice UV ─────
int tensionVersUVIndex(float mV) {
  if (mV < 50)   return 0;  else if (mV < 227)  return 1;
  else if (mV < 318)  return 2;  else if (mV < 408)  return 3;
  else if (mV < 503)  return 4;  else if (mV < 606)  return 5;
  else if (mV < 696)  return 6;  else if (mV < 795)  return 7;
  else if (mV < 881)  return 8;  else if (mV < 976)  return 9;
  else if (mV < 1079) return 10; else if (mV < 1170) return 11;
  else return 12;
}

// ── Lecture lissée (moyenne sur N itérations) ────────────────────────
float lireMoyenne(int pin, int iterations) {
  long somme = 0;
  for (int i = 0; i < iterations; i++) {
    somme += analogRead(pin);
    delay(5);
  }
  return (float)somme / iterations;
}

void setup() {
  Serial.begin(115200);
  unsigned long debut = millis();
  while (!Serial && millis() - debut < 3000);
  Serial.println("\n=== SAE 204 Sonde V3 — Mode UV & Lumière ===");

  analogReadResolution(12); // ADC 12 bits → 0 à 4095
  pinMode(PIN_A, INPUT);
  pinMode(PIN_B, INPUT);

  // Initialisation BLE
  if (!BLE.begin()) {
    Serial.println("[ERREUR] BLE en panne !");
    while (1);
  }
  BLE.setLocalName("Sonde_V3");
  BLE.setAdvertisedService(meteoService);
  meteoService.addCharacteristic(uvCharacteristic);
  meteoService.addCharacteristic(lightCharacteristic);
  BLE.addService(meteoService);

  uvCharacteristic.writeValue(0.0);
  lightCharacteristic.writeValue(0.0);
  BLE.advertise();
  Serial.println("[OK] BLE actif — En attente de connexion...");
}

void loop() {
  BLEDevice central = BLE.central();
  if (central) {
    Serial.print("Connecté : ");
    Serial.println(central.address());

    while (central.connected()) {
      float rawA = lireMoyenne(PIN_A, 10);
      float rawB = lireMoyenne(PIN_B, 10);

      float mV_A     = rawA * (3300.0 / 4095.0);
      float indiceUV = (float)tensionVersUVIndex(mV_A);
      float lumPct   = (rawB / 4095.0) * 100.0;

      // Envoi BLE
      uvCharacteristic.writeValue(indiceUV);
      lightCharacteristic.writeValue(lumPct);

      // Diagnostic série
      Serial.println("─────────────────────────────────────────");
      Serial.print("A0 brut: "); Serial.print(rawA, 0);
      Serial.print(" | A1 brut: "); Serial.println(rawB, 0);
      Serial.print("UV (A0): "); Serial.print(indiceUV, 0);
      Serial.print(" | Lum (A1): "); Serial.print(lumPct, 1); Serial.println("%");
      delay(1000);
    }
    Serial.println("Déconnecté.");
  }
}
m5stack.ino — M5Core2 : affichage Wi-Fi + MQTT Arduino / C++ ✍️ Unsal — 11/06/2026
// Auteur : Unsal
// Projet : SAE 204 - Affichage Météo sur M5Core2 (Wi-Fi + MQTT VPS)
#include <M5Core2.h>
#include <WiFi.h>
#include <PubSubClient.h>

// --- Configuration Réseau Wi-Fi ---
const char* ssid     = "VOTRE_SSID";      // Remplacer par votre réseau
const char* password = "VOTRE_PASSWORD";  // Remplacer par votre mot de passe

// --- Configuration MQTT (Mosquitto sur VPS) ---
const char* mqtt_server = "ADRESSE_VPS";  // IP du VPS Ionos
const int   mqtt_port   = 1883;
const char* mqtt_user   = "sae204";
const char* mqtt_pass   = "VOTRE_PASS";   // Mot de passe MQTT

// --- Topic MQTT ---
const char* topic_meteo = "sonde/meteo";

WiFiClient   espClient;
PubSubClient client(espClient);

// --- Interface Graphique ---
void dessinerInterface() {
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextSize(2);

  // Bandeau Titre
  M5.Lcd.fillRect(0, 0, 320, 30, BLUE);
  M5.Lcd.setTextColor(WHITE, BLUE);
  M5.Lcd.setCursor(10, 5);
  M5.Lcd.print("Sonde Meteo V3 - R&T");

  // Labels fixes
  M5.Lcd.setTextColor(YELLOW, BLACK);
  M5.Lcd.setCursor(20, 80);
  M5.Lcd.print("Indice UV  :");
  M5.Lcd.setTextColor(CYAN, BLACK);
  M5.Lcd.setCursor(20, 140);
  M5.Lcd.print("Luminosite :");
}

// --- Callback : déclenché à chaque message MQTT reçu ---
void callback(char* topic, byte* payload, unsigned int length) {
  // Reconstruction du message texte
  String message = "";
  for (int i = 0; i < length; i++) {
    message += (char)payload[i];
  }
  Serial.print("Message recu [");
  Serial.print(topic);
  Serial.print("] : ");
  Serial.println(message);

  // Traitement uniquement sur le bon topic
  if (String(topic) == topic_meteo) {
    int indexVirgule = message.indexOf(',');
    if (indexVirgule != -1) {
      // Découpage  "UV:4,LUM:36.3"
      String partieUV  = message.substring(0, indexVirgule);
      String partieLum = message.substring(indexVirgule + 1);
      partieUV.replace("UV:", "");
      partieLum.replace("LUM:", "");

      // Mise à jour de l'écran
      M5.Lcd.fillRect(180, 80,  100, 30, BLACK);
      M5.Lcd.setCursor(180, 80);
      M5.Lcd.setTextColor(YELLOW, BLACK);
      M5.Lcd.print(partieUV);

      M5.Lcd.fillRect(180, 140, 100, 30, BLACK);
      M5.Lcd.setCursor(180, 140);
      M5.Lcd.setTextColor(CYAN, BLACK);
      M5.Lcd.print(partieLum);
      M5.Lcd.print(" %");
    } else {
      Serial.println("Format non reconnu (virgule manquante).");
    }
  }
}

// --- Reconnexion MQTT automatique ---
void reconnect() {
  while (!client.connected()) {
    Serial.print("Connexion au broker Mosquitto...");
    M5.Lcd.fillRect(0, 210, 320, 30, BLACK);
    M5.Lcd.setTextColor(RED, BLACK);
    M5.Lcd.setCursor(10, 215);
    M5.Lcd.print("MQTT Deconnecte...");

    if (client.connect("M5Core2_sae204", mqtt_user, mqtt_pass)) {
      Serial.println("Connecte !");
      M5.Lcd.fillRect(0, 210, 320, 30, BLACK);
      M5.Lcd.setTextColor(GREEN, BLACK);
      M5.Lcd.setCursor(10, 215);
      M5.Lcd.print("MQTT Connecte (VPS) !");
      client.subscribe(topic_meteo);
    } else {
      Serial.print("Echec, code : ");
      Serial.print(client.state());
      Serial.println(" → Nouvel essai dans 5s");
      delay(5000);
    }
  }
}

void setup() {
  M5.begin();
  dessinerInterface();

  M5.Lcd.setTextColor(WHITE, BLACK);
  M5.Lcd.setCursor(10, 215);
  M5.Lcd.print("Connexion Wi-Fi...");

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  M5.Lcd.fillRect(0, 210, 320, 30, BLACK);
  M5.Lcd.setTextColor(GREEN, BLACK);
  M5.Lcd.setCursor(10, 215);
  M5.Lcd.print("Wi-Fi OK !");
  delay(1500);

  client.setServer(mqtt_server, mqtt_port);
  client.setCallback(callback);
}

void loop() {
  M5.update();
  if (!client.connected()) {
    reconnect();
  }
  client.loop();
}
ble-rpi.py — Raspberry Pi : réception BLE → publication MQTT Python 3 ✍️ Mohamed-Bedis · Unsal · Jonathan — 09/06/2026
import asyncio
import struct
import paho.mqtt.client as mqtt
from bleak import BleakClient, BleakScanner

# ── Configuration BLE ────────────────────────────────────────────────
DEVICE_NAME     = "Sonde_V3"
UV_CHAR_UUID    = "19B10001-E8F2-537E-4F6C-D104768A1214"
LIGHT_CHAR_UUID = "19B10002-E8F2-537E-4F6C-D104768A1214"

# ── Configuration MQTT ───────────────────────────────────────────────
MQTT_BROKER = "localhost"   # IP du VPS Ionos en prod
MQTT_PORT   = 1883

try:
    mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
except AttributeError:
    mqtt_client = mqtt.Client()

async def main():
    try:
        mqtt_client.connect(MQTT_BROKER, MQTT_PORT, 60)
        mqtt_client.loop_start()
        print(f"✅ Connecté au broker MQTT ({MQTT_BROKER})")
    except Exception as e:
        print(f"❌ Erreur MQTT : {e}")
        return

    print(f"🔍 Recherche de la sonde BLE '{DEVICE_NAME}'...")
    devices = await BleakScanner.discover(timeout=10.0)

    target_device = None
    for d in devices:
        if d.name == DEVICE_NAME:
            target_device = d
            break

    if not target_device:
        print("❌ Sonde introuvable.")
        mqtt_client.loop_stop()
        return

    print(f"✅ Sonde trouvée ! Connexion BLE en cours...")

    async with BleakClient(target_device, timeout=20.0) as client:
        print("🚀 Connecté ! Transfert des données vers Mosquitto...")

        while True:
            try:
                # Lecture des 2 caractéristiques GATT
                uv_bytes    = await client.read_gatt_char(UV_CHAR_UUID)
                light_bytes = await client.read_gatt_char(LIGHT_CHAR_UUID)

                # Décodage float little-endian
                uv_val    = struct.unpack('<f', uv_bytes)[0]
                light_val = struct.unpack('<f', light_bytes)[0]

                # Formatage payload → "UV:4,LUM:36.3"
                payload = f"UV:{uv_val:.0f},LUM:{light_val:.1f}"
                mqtt_client.publish("sonde/meteo", payload)
                print(f"[MQTT ✅] {payload}")

            except Exception as e:
                print(f"[⚠] Erreur lecture BLE : {e}")
                break

            await asyncio.sleep(1)

asyncio.run(main())
vps-bridge.py — VPS : monitoring Mosquitto en temps réel Python 3 ✍️ Jonathan — 09/06/2026
#!/usr/bin/env python3
"""
SAE 204 — Monitoring VPS Mosquitto
Affiche en temps réel les données reçues du RPi.
Jonathan
"""
import paho.mqtt.client as mqtt
from datetime import datetime

MQTT_HOST  = "localhost"
MQTT_PORT  = 1883
MQTT_TOPIC = "sonde/meteo"
# Identifiants définis via variables d'environnement sur le VPS

compteur = 0

def on_connect(client, userdata, connect_flags, reason_code, properties=None):
    if reason_code == 0:
        print("╔══════════════════════════════════════════════════╗")
        print("║      SAE204 — Monitoring VPS Mosquitto           ║")
        print("╚══════════════════════════════════════════════════╝")
        print(f"[✅] Connecté au broker ({MQTT_HOST}:{MQTT_PORT})")
        client.subscribe(MQTT_TOPIC)
        print(f"[📡] En écoute sur : {MQTT_TOPIC}")
        print("[⏳] En attente des données du RPi...\n")
    else:
        print(f"[❌] Erreur connexion : {reason_code}")

def on_message(client, userdata, msg):
    global compteur
    compteur += 1
    payload = msg.payload.decode("utf-8")
    ts = datetime.now().strftime("%H:%M:%S")

    try:
        parties = dict(p.split(":") for p in payload.split(","))
        uv  = parties.get("UV",  "—")
        lum = parties.get("LUM", "—")

        print(f"┌─ [{ts}] Message #{compteur} reçu du RPi ──────────────")
        print(f"│  📦 Payload brut  : {payload}")
        print(f"│")
        print(f"│  ☀️  UV Index      : {uv}")
        print(f"│  💡 Luminosité    : {lum}%")
        print(f"│")
        print(f"│  → Dispatché aux VMs (MariaDB, InfluxDB) ✅")
        print(f"│  → Dispatché au M5Stack (WiFi MQTT)      ✅")
        print(f"└───────────────────────────────────────────────────\n")

    except Exception as e:
        print(f"[⚠] Données mal formées : {payload} ({e})")

try:
    client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
except AttributeError:
    client = mqtt.Client()

client.on_connect = on_connect
client.on_message = on_message
client.connect(MQTT_HOST, MQTT_PORT, 60)
client.loop_forever()

5. Répartition des Rôles

Chaque membre est responsable d'un domaine technique précis, couvrant à la fois le volet Programmer et Administrer de la SAE.

Membre Rôle Responsabilités détaillées
Helina Expert Hardware & Acquisition Câblage propre des capteurs Grove (UV GUVA-S12D + lumière v1.2) sur le WB55. Lecture analogique via ADC 12 bits (PA0/PA1). Formatage des données pour l'envoi BLE. Mise en place, installation et configuration de la VM Grafana (visualisation, dashboards InfluxDB + MariaDB, port 3000, IP statique, VNC).
Mohamed-Bedis Spécialiste Communication BLE Configuration du protocole Bluetooth Low Energy sur le WB55 (bibliothèque STM32duinoBLE v1.4.1, firmware RF v16.12.0.27). Définition du service GATT et des 5 caractéristiques (UV, lumière, humidité, pression, température). Vérification de la réception côté Raspberry Pi et M5Stack.
Jonathan Maître Infrastructure & Stockage Configuration Raspberry Pi 3B+ (OS, réseau, accès VPS). Adaptation du script BLE de Bédis pour le RPi (asyncio, gestion erreurs, mode démo). Écriture CSV horodatée sur microSD. VPS Ionos — broker Mosquitto (auth. activée, accès anonyme désactivé). VM Icinga2 (supervision réseau, IcingaWeb2). Script vps-bridge.py de monitoring temps réel. Sauvegardes rsync.
Unsal Designer UI / Affichage Programmation de l'afficheur 2Core M5Stack. Interface de visualisation claire et lisible des données en temps réel. Mode alerte (fond rouge) si température > 30°C. Contribution au code STM32 final (temp2.ino).

6. Journal d'Avancement

Suivi semaine par semaine des étapes clés du projet, avec les problèmes rencontrés et les solutions apportées.

📅 Semaine 1 — 5 au 9 mai 2026

Lancement du projet & répartition des rôles

  • Réunion d'équipe : validation du sujet Sonde Météorologique, répartition des 4 rôles.
  • Récupération du matériel IUT : WB55, M5Stack 2Core, Raspberry Pi 3B+, capteurs Grove, microSD 32 Go.
  • Lecture de la documentation technique du WB55 et des bibliothèques Grove.
  • Rédaction du diagramme des exigences (analyse thermique en salle).
  • [Jonathan] Flash du Raspberry Pi OS 64-bit Lite sur microSD via Raspberry Pi Imager. Activation SSH.
  • [Jonathan] Configuration réseau RPi via hotspot mobile (eduroam WPA2-Enterprise incompatible). Accès SSH VPS via clé ed25519.
  • [Jonathan] Installation Python 3 + bleak + paho-mqtt sur le RPi.
  • Mise en place du journal de projet sur Benelos par Jonathan.
📅 Semaine 2 — 12 au 16 mai 2026

Configuration Arduino IDE & premiers tests capteurs

  • Installation d'Arduino IDE sur macOS (VM Parallels Windows) + support STM32 WB55 via STM32duino.
  • Premiers tests de lecture des capteurs Grove — problème de broches inversées (PA0/PA1) résolu.
  • Correction du coefficient UV : passage à la table officielle Seeed GUVA-S12D (résultat conforme UV 4).
  • Résolution problème upload ST-LINK : configuration STM32CubeProgrammer (SWD) + passage USB à Windows via Parallels.
  • Installation bibliothèque STM32duinoBLE v1.4.1. Vérification firmware BLE RF → v16.12.0.27 déjà présent ✅
📅 Semaine 3 — 19 au 30 mai 2026

Première tentative Arduino IDE · Création du projet HUBJ

  • [Jonathan — 20/05] Tentative : Arduino IDE ne trouve pas la carte. Abandon de cette approche, bascule vers STM32CubeProgrammer (SWD) uniquement.
  • [Jonathan — 19/05] Création du projet "SAE204" sur Skynium HUBJ Teams.
  • Définition de l'architecture complète du volet Administrer : VPS Ionos, VMs MariaDB/InfluxDB/Grafana/Icinga2.
  • Identification du problème eduroam → solution VPS Ionos comme broker MQTT central.
📅 Semaine 4 — 1 au 5 juin 2026

Intégration BLE complète · Validation de la chaîne MQTT

  • [Unsal — 01/06] Configuration indice UV et température sur la STM32 — dépôt du code sur HUBJ.
  • [Jonathan — 02/06] Réception du script BLE de Bédis. Adaptation pour RPi 3B+ : correction asyncio, gestion erreurs, ajout mode --demo.
  • [Jonathan — 02/06] Validation chaîne complète en mode démo : données simulées → CSV horodaté généré sur microSD ✅
  • [Jonathan — 02/06] Test MQTT : publish depuis RPi → subscribe sur VPS Ionos Mosquitto → données reçues en temps réel ✅
  • Code affichage M5Stack finalisé par Unsal (interface temps réel + alertes rouge si T° > 30°C).
  • [Jonathan — 05/06] Rédaction note de préparation à l'oral (sommaire, ODD, démonstration).
📅 Semaine 5 — 8 au 10 juin 2026

Codes finaux · Documentation wiki

  • [Jonathan — 08/06] Dépôt de vps-bridge.py (monitoring Mosquitto en temps réel).
  • [Unsal — 08/06] Finalisation de ble-rpi.py.
  • [Unsal — 09/06] Dépôt du code STM32 temp2.ino (Sonde_V3).
  • [Jonathan — 09/06] Ajustements finaux sur les scripts STM32 et vps-bridge.py.
  • Mise à jour du wiki Benelos — documentation complète des parties Programmer et Administrer.
  • [10/06/2026] Rapport PDF généré et diffusé à tous les membres via HUBJ.
📅 Semaine 6 — 11 juin 2026 · Clôture du projet

Soutenance · Livraison finale · Projet terminé ✅

  • [Unsal — 11/06 matin] Dépôt de m5stack.ino — version finale de l'afficheur M5Core2 (Wi-Fi + MQTT VPS, reconnexion automatique, interface UV + Luminosité).
  • [Unsal — 11/06 matin] Mise à jour finale de helina.ino — version propre avec uniquement UV et Luminosité via BLE.
  • [Jonathan — 11/06] Suppression de temp2.ino (remplacé par helina.ino version finale).
  • [Helina & Unsal — 11/06] Réalisation des wikis Benelos et Trappist — documentation finale partagée.
  • [11/06/2026] Soutenance orale du projet SAE204 — présentation de 30 minutes + démonstration.
  • [Jonathan — 11/06 11:42] Projet marqué comme Terminé sur HUBJ Teams — 8/8 tâches à 100%.

7. Difficultés rencontrées & Solutions

Un projet d'intégration réel rencontre toujours des obstacles. Voici les principaux et comment l'équipe les a surmontés.

Arduino IDE ne détecte pas la carte WB55

Le Board part number affichait "Generic WB15CCUx" — l'upload échouait avec "No debug probe detected".

Solution : sélectionner impérativement Nucleo WB55RG dans les cartes STM32. Configuration de STM32CubeProgrammer (SWD) + passage USB à la VM Windows via Parallels.
Réseau eduroam incompatible avec Raspberry Pi OS Lite

WPA2-Enterprise de l'IUT ne peut pas être configuré sur RPi OS Lite sans interface graphique.

Solution : hotspot mobile personnel pour le RPi + VPS Ionos avec IP publique comme broker MQTT central accessible depuis n'importe quel réseau.
Broches PA0/PA1 inversées sur les capteurs Grove

Les premières lectures donnaient l'UV sur la broche de lumière et vice-versa.

Solution : diagnostic via moniteur série + torche pour identifier physiquement chaque capteur. Correction des #define dans le code.
HTS221 non détecté au démarrage

Le capteur de température/humidité nécessite un temps de chauffe avant d'être stable.

Solution : ajout d'un delay(2000) après l'Enable() dans le setup + vérification de l'ID (0xBC attendu).
IcingaWeb2 refusait la connexion (hash bcrypt)

La base IDO était vide, le schéma n'avait pas été importé, et le mot de passe n'était pas au bon format bcrypt.

Solution en 3 étapes : import du schéma SQL IDO, correction du fichier ido-mysql.conf, injection SQL directe du hash bcrypt correct.
Coordination et synchronisation d'équipe

Développement modulaire en parallèle → incompatibilités lors de la mise en commun des modules.

Solution : utilisation de HUBJ Teams pour le partage de code versionné, notes partagées et réunions de synchronisation régulières.

8. État des tâches (HUBJ Teams)

Projet terminé le 11 juin 2026 — 8/8 tâches à 100%.

Hardware & Acquisition
Helina
Terminée · 100%
Connection de la carte à l'ordinateur
Unsal, Helina, Jonathan
Terminée · 100%
Refaire les capteurs (Sonde_V3)
Jonathan, Unsal, Helina
Terminée · 100%
Revoir Mosquitto RPi → VPS → VMs
Jonathan
Terminée · 100%
Suivi Jonathan
Jonathan
Terminée · 100%
Designer UI / Affichage M5Stack
Unsal
Terminée · 100%
Faire le wiki (Trappist + Benelos)
Helina, Unsal
Terminée · 100%
Infrastructure & Stockage
Jonathan
Terminée · 100%

9. L'Équipe du Projet

Unsal

Unsal

Designer UI / Affichage

M5Stack · STM32 (temp2.ino)

Helina

Helina

Hardware & Acquisition

Capteurs Grove · VM Grafana

Mohamed-Bedis

Mohamed-Bedis

Communication BLE

STM32duinoBLE · GATT

Jonathan

Jonathan

Infrastructure & Stockage

RPi · VPS Mosquitto · Icinga2