← Projets

Réseau de Capteurs Distribué — Supervision Environnementale

Sorbonne UniversitéComposants et Programmation Répartie (CPS)Janv. — Mai 2024

Prototype d'un système de supervision réparti fondé sur la notion de réseau de capteurs environnementaux, librement inspiré d'un prototype existant de surveillance de systèmes cyber-physiques. Les entités du réseau sont implantées comme des composants BCM4Java qui s'interconnectent et propagent des requêtes de manière distribuée pour détecter des alertes (départ de feu de forêt, mesures environnementales).

Architecture du réseau de capteurs

Le réseau est organisé en maillage géographique : chaque nœud connaît ses voisins dans les quatre directions cardinales (NE, NW, SE, SW). Un composant registre global gère l'inscription des nœuds et la découverte des voisins lors de leur arrivée dans le réseau.

Figure 1 — Réseau de capteurs avec 13 nœuds positionnés sur une grille géographique

Lorsqu'un nœud rejoint le réseau, il s'inscrit auprès du registre via l'interface RegistrationCI, reçoit en retour la liste de ses voisins directs, puis établit des connexions bidirectionnelles avec chacun d'eux via l'interface SensorNodeP2PCI. Si un nouveau voisin est plus proche qu'un voisin existant dans une direction donnée, les connexions sont remises à jour dynamiquement.

Langage de requêtes

Un langage de requêtes dédié permet d'exprimer deux types de requêtes propagées sur le réseau :

  • Requêtes de collecte (GQuery) — liste d'identifiants de capteurs dont on veut récupérer les valeurs courantes sur chaque nœud parcouru.
  • Requêtes booléennes (BQuery) — expression booléenne évaluée sur chaque nœud ; retourne la liste des nœuds où elle est vraie.

Chaque requête est accompagnée d'une continuation précisant les nœuds suivants à parcourir :

  • ECont — continuation vide (un seul nœud).
  • DCont dirs hops — continuation directionnelle : propagation dans les directions indiquées jusqu'à un nombre maximal de sauts.
  • FCont base distance — continuation inondation : tous les nœuds dans un rayon géographique maximal depuis une position de référence.

Exemple de requête booléenne détectant un départ de feu de forêt et se propageant vers le nord-est sur 2 sauts :

new BQuery(
    new AndBExp(
        new GeqCExp(new SRand("température"), new CRand(50.0)),
        new GeqCExp(new SRand("fumée"), new CRand(3.0))
    ),
    new DCont(new FDirs(Direction.NE), 2)
)

Exécution synchrone en style direct

Dans la première implantation, un nœud recevant une requête via RequestingCI#execute évalue localement la partie collecte ou booléenne, puis appelle synchronement chacun de ses voisins faisant partie de la continuation via SensorNodeP2PCI#execute. Il attend les résultats de ces appels, les fusionne avec son résultat local et retourne l'ensemble à son appelant.

Cette approche présente une limite de performance : le thread de chaque nœud reste occupé tant que ses voisins — et les voisins de ses voisins — n'ont pas retourné leurs résultats.

Exécution asynchrone en style passage à la continuation

La seconde implantation utilise des appels asynchrones (executeAsync). Chaque nœud calcule son résultat local, l'ajoute aux résultats accumulés via ExecutionStateI#addToCurrentResult, puis propage la continuation de requête à ses voisins sans en attendre les résultats.

Les nœuds feuilles (sans voisin dans la continuation) envoient directement le résultat partiel au composant client via RequestResultCI#acceptRequestResult. Le client agrège tous les résultats partiels reçus dans un délai de temporisation maximal.

Cette approche exploite le parallélisme : lors de la propagation vers plusieurs voisins, l'arborescence d'appels se développe simultanément, permettant un débit plus élevé sous charge.

Gestion de la concurrence

L'introduction de l'asynchronisme nécessite une gestion explicite de la concurrence :

  • Séparation des opérations en groupes traités par des pools de threads distincts (requêtes entrantes, propagation P2P, registre).
  • Sections critiques protégeant l'accès aux valeurs de capteurs et aux structures de voisinage mises à jour dynamiquement lors des arrivées/départs de nœuds.
  • Expérimentations avec 1, 2, 5 et 10 threads par pool pour mesurer l'impact sur le débit de requêtes traitées par seconde.

Scénario de démonstration

Le scénario final implique 5 composants clients et 50 composants nœuds organisés sur une grille géographique. Les actions (inscriptions des nœuds, envois de requêtes, mises à jour des capteurs) sont planifiées via une horloge accélérée (AcceleratedClock BCM4Java) synchronisée entre toutes les JVM, avec un facteur d'accélération de 60 (1 minute simulée = 1 seconde réelle).

// détection d'un feu en n7, puis propagation vers le nord-est
// étape 1 : requête booléenne (température > 50 ET fumée > 3) sur nœuds initiaux
// étape 2 : requête de collecte (vitesse-vent, direction-vent) sur n7
// étape 3 : requête directionnelle NE depuis n7 → n5 → n3 pour délimiter la zone
50nœuds capteurs dans le scénario final
2 modessynchrone direct + asynchrone continuation
3 typescontinuation ECont · DCont · FCont

Stack

Java
BCM4JavaBCM4Java

Encadrant

Jacques Malenfant

Professeur des universités — Sorbonne Université / LIP6