Aller au contenu

Arc42 — Section 3 : Contexte système

3.1 Contexte métier

ExploreIOT Dashboard s'inscrit dans un réseau IoT LoRaWAN standard. Le système reçoit des trames de capteurs de terrain, les traite, les stocke, et les expose à des opérateurs humains via un dashboard web. Le projet supporte deux modes de fonctionnement : - Mode simulation (par défaut) : l'environnement réseau réel (gateway physique, serveur Chirpstack) est simulé par un worker Python (publisher.py) qui publie des mesures réalistes sur le broker MQTT local. - Mode production : Chirpstack v4 est déployé en tant que service Docker réel via le profil Docker Compose --profile chirpstack.

Mosquitto et Chirpstack : deux rôles différents

Il ne faut pas confondre les deux :

  • Chirpstack = le serveur réseau LoRaWAN. Il gère le déchiffrement des trames radio, l'authentification des capteurs (OTAA/ABP), et la communication avec les gateways. En sortie, il publie les données décodées sur un broker MQTT.
  • Mosquitto = le broker MQTT. C'est un simple routeur de messages publish/subscribe. Il ne "comprend" pas LoRaWAN — il transmet les messages d'un producteur vers les consommateurs abonnés.

Dans ce projet : Mosquitto est bien déployé (conteneur Docker). Chirpstack peut être absent (mode simulation, publisher.py simule son rôle) ou déployé en tant que service réel (mode production via docker compose --profile chirpstack up).

Simulation :        publisher.py (simule Chirpstack) → Mosquitto → Subscriber
Production réelle :  Capteur → Gateway → Chirpstack v4 → Mosquitto → Subscriber

Chirpstack v4 maintenant disponible

Chirpstack v4 est maintenant disponible en tant que profil Docker Compose. Voir section 7.1 pour les instructions de déploiement.


3.2 Diagramme de contexte C4

graph TB
    TECH["👤 Technicien IoT<br/><i>Surveille les capteurs<br/>via le navigateur web</i>"]
    ETUD["👤 Étudiant<br/><i>Explore le pipeline LoRaWAN<br/>via le convertisseur</i>"]

    subgraph ExploreIOT["ExploreIOT Dashboard"]
        SYS["📊 Système ExploreIOT<br/><i>Dashboard de supervision IoT<br/>Pipeline LoRaWAN complet</i>"]
    end

    CAPTEURS["📡 Capteurs Dragino LHT65<br/><i>Température + Humidité<br/>LoRaWAN 868 MHz</i>"]
    GW["📶 Gateway LoRaWAN<br/><i>Pont radio LoRa → IP</i>"]
    CS["⚙️ Chirpstack v4<br/><i>Serveur réseau LoRaWAN<br/>(réel ou simulé)</i>"]

    TECH -->|"HTTP / WebSocket"| SYS
    ETUD -->|"HTTP"| SYS
    CAPTEURS -->|"LoRaWAN radio"| GW
    GW -->|"MQTT / UDP"| CS
    CS -->|"MQTT publish<br/>JSON + base64"| SYS

    style SYS fill:#1168bd,color:#fff,stroke:#0b4884
    style TECH fill:#08427b,color:#fff
    style ETUD fill:#08427b,color:#fff
    style CAPTEURS fill:#999,color:#fff
    style GW fill:#999,color:#fff
    style CS fill:#999,color:#fff

Acteurs

Acteur Rôle
Technicien IoT Utilisateur principal — surveille le parc de capteurs, configure les alertes, exporte les données
Étudiant Utilisateur pédagogique — explore le convertisseur LoRaWAN pour comprendre l'encodage binaire

Systèmes externes

Système Description
Capteurs Dragino LHT65 Capteurs physiques LoRaWAN (simulés par publisher.py en développement)
Gateway LoRaWAN Pont radio-IP (simulé par publisher.py en développement)
Chirpstack v4 Serveur réseau LoRaWAN — disponible en mode réel via docker compose --profile chirpstack up

3.3 Acteurs et systèmes externes

Capteurs Dragino LHT65

Les capteurs Dragino LHT65 sont des capteurs IoT LoRaWAN commerciaux mesurant la température et l'humidité. Ils encodent leurs mesures dans une trame binaire compacte (payload de quelques octets) et la transmettent via le protocole radio LoRa à longue portée.

Dans ce projet, leur comportement est simulé par publisher.py, qui génère des mesures réalistes (via generer_mesure()) et les encode au format binaire identique via app/payload_codec.py (struct.pack('>HH', temp*100, hum*10)).

Gateway LoRaWAN

La gateway LoRaWAN est le pont radio entre les capteurs (protocole LoRa sur 868 MHz en Europe) et le réseau IP. Elle reçoit les trames radio des capteurs et les transmet au serveur réseau LoRaWAN via MQTT ou UDP.

Dans ce projet, la gateway est simulée — son rôle est intégré dans publisher.py.

Chirpstack v4 : réel ou simulé

Chirpstack est le serveur réseau LoRaWAN open source de référence. Il décode les trames LoRaWAN, gère l'authentification des appareils, et publie les données décodées sur un broker MQTT selon un format JSON standardisé.

Le projet supporte deux modes :

Mode simulation : Chirpstack est remplacé par publisher.py, qui : 1. Génère une mesure aléatoire réaliste 2. L'encode en binaire (struct.pack) 3. L'encode en base64 (comme Chirpstack le ferait) 4. Publie le message JSON sur le topic application/{app_id}/device/{device_id}/event/up

Ce mode permet de tester le pipeline complet sans infrastructure physique.

Mode production : Chirpstack v4 est déployé en tant que service Docker réel via le profil --profile chirpstack. Il est alors configuré pour communiquer avec le gateway bridge et publier directement sur Mosquitto.

Mosquitto — Broker MQTT

Eclipse Mosquitto est le broker MQTT open source utilisé comme bus de messages central. Il découple le producteur de données (publisher.py) du consommateur (subscriber.py). Ce découplage est essentiel : le subscriber peut redémarrer sans perte de message (QoS 1), et de nouveaux consommateurs peuvent s'abonner sans modifier le publisher.

Configuration : port 1883 (MQTT), pas de TLS en développement local.

Subscriber — Worker Python

Le subscriber est un processus Python autonome qui : 1. S'abonne au topic MQTT application/+/device/+/event/up 2. Reçoit chaque message publié par le publisher 3. Décode le payload base64 et binaire 4. Valide les valeurs (plages physiques acceptables) 5. Insère la mesure en base de données via psycopg2 6. Notifie FastAPI via asyncio.run_coroutine_threadsafe() pour le broadcast WebSocket

PostgreSQL

Base de données relationnelle qui stocke : - Les appareils enregistrés (devices) - Les mesures time-series (mesures) - Les alertes générées (alerts)

Le schéma est versionné via Alembic pour permettre l'évolution sans perte de données.

FastAPI — API REST + WebSocket

Le coeur applicatif du backend. Il expose : - GET /devices — liste des appareils - GET /devices/{id}/mesures — historique des mesures avec pagination - GET /stats — statistiques agrégées (min, max, moyenne) - GET /alerts — alertes actives et historique - GET /status — statut détaillé de tous les services (API, DB, MQTT, WS, Publisher) - GET /debug/recent-messages — buffer des 50 derniers messages MQTT bruts - WebSocket /ws — canal temps réel pour le push des nouvelles mesures - GET /health — health check pour Docker et les outils de monitoring

Dashboard Next.js

L'interface utilisateur construite avec Next.js et Recharts. Elle propose trois vues principales :

  • Dashboard : supervision temps réel des capteurs (graphiques, statistiques, alertes, export CSV/PDF)
  • Convertisseur : pipeline d'encodage/décodage LoRaWAN interactif + 4 outils pédagogiques (manipulateur de bits, corruption, overhead, complément à 2)
  • Pipeline : visualisation animée des 8 étapes du parcours d'une mesure avec 3 modes (live, pas à pas, inspecteur de protocoles)

Fonctionnalités transversales : - Connexion WebSocket pour recevoir les mesures en temps réel - Glossaire interactif (15 termes avec tooltips contextuels) - Panneau de statut des services en mode API (ConnectionStatus) - Export en CSV et PDF des données affichées - Toggle Mock/API avec vérification de santé automatique

Technicien IoT (utilisateur final)

L'opérateur qui utilise le dashboard via son navigateur web. Il consulte l'état des capteurs, vérifie les alertes, et exporte les données pour un rapport ou une analyse externe.


3.4 Flux de données

Etape De Vers Protocole Format
1 Capteur Dragino Gateway LoRaWAN (radio) Binaire chiffré
2 Gateway Chirpstack MQTT/UDP Trame LoRaWAN brute
3 publisher.py (simule Chirpstack) Mosquitto MQTT JSON avec payload base64
4 Mosquitto Subscriber MQTT callback JSON
5 Subscriber PostgreSQL psycopg2 INSERT SQL
6 Subscriber FastAPI asyncio Appel coroutine interne
7 FastAPI Dashboard WebSocket JSON
8 FastAPI Dashboard HTTP REST JSON
9 Technicien Dashboard HTTP/WS

3.5 Frontières du système

Le système ExploreIOT Dashboard prend en charge : - La reception et le stockage des données MQTT - La persistance et la requête des données historiques - L'exposition des données via REST et WebSocket - La détection d'anomalies et la génération d'alertes - L'affichage temps réel et l'export

Le système ne prend pas en charge : - La gestion des clés de chiffrement LoRaWAN (Join Server) - La configuration des gateways physiques - L'envoi de commandes vers les capteurs (downlink) - L'authentification multi-utilisateurs (un seul niveau d'accès par clé API)


3.6 Modèle Conceptuel de Données (MERISE MCD)

Le MCD représente les entités du domaine et leurs associations, indépendamment de toute implémentation technique.

erDiagram
    CAPTEUR ||--o{ MESURE : "produit"
    CAPTEUR {
        string device_eui PK "Identifiant unique EUI-64"
        string nom "Nom convivial"
        string type_capteur "Dragino LHT65"
        string localisation "Emplacement physique"
    }
    MESURE {
        int id PK "Identifiant auto"
        float temperature "Valeur en °C"
        float humidite "Valeur en %"
        datetime recu_le "Horodatage reception"
    }
    CAPTEUR ||--o{ ALERTE : "declenche"
    ALERTE {
        string type "TEMPERATURE_ELEVEE ou CAPTEUR_SILENCIEUX"
        float valeur "Valeur depassant le seuil"
        string message "Description lisible"
        datetime recu_le "Horodatage detection"
    }

Entités

Entité Description Identifiant
CAPTEUR Appareil physique IoT LoRaWAN (Dragino LHT65) device_eui (EUI-64, 16 hex)
MESURE Relevé de température et humidité à un instant T id (auto-incrémenté)
ALERTE Anomalie détectée par analyse des mesures Composite (device_eui, recu_le)

Associations

Association Cardinalité Description
CAPTEUR — MESURE 1,N Un capteur produit 0 à N mesures
CAPTEUR — ALERTE 1,N Un capteur déclenche 0 à N alertes

Implémentation actuelle

Dans l'implémentation actuelle, l'entité CAPTEUR n'a pas de table dédiée — les capteurs sont identifiés par leur device_id dans la table mesures. Les noms sont gérés côté frontend (device-registry.ts). Les alertes sont calculées dynamiquement à partir des mesures récentes (pas de table alertes persistante).