Vous êtes sur la page 1sur 5

U NI V ERS I TÉ DE J ENDO UBA

I NS TI TU T S UP É RI EU R DE L’I NF O RM ATI QU E DU K EF

TP 3 : "Développement d'une Application de Collecte de Données


IoT en Java avec Sockets UDP"

Matière : Développement d’applications réparties Niveau : 3 em e LSI


Responsable : Hanen Samaali A U : 2023 / 2024

Objectif principal :
Le but principal de ce TP est d'enseigner aux étudiants les concepts fondamentaux de
la collecte de données dans un contexte IoT (Internet des Objets) en utilisant le
protocole de communication UDP. Il vise à familiariser les étudiants avec la création
d'applications distribuées qui collectent des données à partir de capteurs répartis sur
un réseau. Il comprend trois composants principaux :
Serveur de Collecte de Données (DataCollectionServer) : Cette classe représente le
serveur central chargé de recevoir, traiter et afficher les données provenant de
capteurs IoT répartis sur un réseau. Le serveur attribue également des numéros de
capteur uniques aux capteurs.
Simulateur de Capteur (SensorSimulator) : Cette classe simule un capteur IoT en
générant des données simulées (par exemple, la température) et en les envoyant au
serveur de collecte de données via UDP. Chaque simulateur de capteur est identifié
par un numéro unique attribué par le serveur de numérotation des capteurs.
Serveur de Numérotation des Capteurs (SensorNumberServer) : Ce serveur attribue
des numéros de capteur uniques aux simulateurs de capteurs qui en font la demande.
Il assure ainsi que chaque capteur a un numéro d'identification unique.
Le TP enseigne les concepts clés suivants :
La gestion des sockets UDP pour la communication réseau.
La collecte de données provenant de capteurs répartis sur un réseau.
L'attribution de numéros de capteur uniques pour identifier chaque capteur.
1
La simulation de capteurs IoT et la génération de données simulées.
La coordination entre les simulateurs de capteurs et le serveur central.

1. DataCollectionServer (Serveur de Collecte de Données) :


Fonctionnalités clés :

1. Crée un DatagramSocket pour écouter sur un port donné (dans cet exemple, le
port 9876) afin de recevoir les données des capteurs.

2. Dans une boucle infinie (while(true)), attend la réception de données en


écoutant le DatagramSocket.

3. Lorsqu'une donnée est reçue, elle est extraite du DatagramPacket et affichée à


la console, indiquant de quel capteur proviennent les données.

4. Gère les numéros de capteur en associant chaque adresse IP de capteur à un


numéro de capteur unique

import java.net.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class DataCollectionServer {


// Un objet DatagramSocket est créé pour gérer la communication UDP. Il est
initialement déclaré à null.
public static void main(String[] args) {DatagramSocket socket = null;
Map<InetAddress, Integer> sensorMap = new HashMap<>(); // Pour associer
l'adresse IP au numéro de capteur

try {
socket = new DatagramSocket(9876);
//Le socket UDP est créé et lié au port 9876 pour écouter les données entrantes.

System.out.println("Serveur de collecte de données IoT en


attente...");
//Le serveur entre dans une boucle infinie pour écouter en permanence les données
des capteurs.
while (true) {
//Un tableau de bytes est créé pour stocker les données reçues.
byte[] receiveData = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveData,
receiveData.length);
//Le socket attend et reçoit un paquet UDP entrant et le stocke dans receivePacket.
socket.receive(receivePacket);

String sensorData = new String(receivePacket.getData(), 0,


receivePacket.getLength());

// Les données reçues du capteur sont affichées à la console.


2
System.out.println("Données reçues du capteur : ");

System.out.println(sensorData);
}
} catch (IOException e) {
e.printStackTrace();
//le socket est fermé proprement pour libérer les ressources lorsque le programme se
termin
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}

2. SensorSimulator (Simulateur de Capteur) :


Fonctionnalités clés :

1. Crée un DatagramSocket pour envoyer des données au serveur de collecte de


données.

2. Dans une boucle infinie (while(true)), génère des données simulées


(température) à intervalles réguliers et les formate en une chaîne de caractères.

3. Demande un numéro de capteur unique au serveur de numérotation des


capteurs.

4. Envoie ces données formatées au serveur de collecte de données en les


encapsulant dans un DatagramPacket, en utilisant le numéro de capteur pour
identifier le capteur.

import java.net.*;
import java.io.*;
import java.util.Random;// Importation de la classe Random pour générer des nombres
aléatoires.

public class SensorSimulator {


public static void main(String[] args) {
// Un objet DatagramSocket est créé pour gérer la communication UDP.
try (DatagramSocket socket = new DatagramSocket()) {
InetAddress serverAddress = InetAddress.getByName("127.0.0.1");
//Adresse IP du serveur
int serverPort = 9876; // Port du serveur de collecte de données

Random random = new Random();

// Demander un numéro de capteur au serveur de numérotation


Socket numberServerSocket = new Socket("127.0.0.1", 12345);
// Un flux d'entrée d'objet est créé pour recevoir le numéro de capteur attribué par
3
le serveur de numérotation.
ObjectInputStream inputStream = new
ObjectInputStream(numberServerSocket.getInputStream());
// Le numéro de capteur est lu à partir du flux d'entrée.
int sensorNumber = inputStream.readInt();
numberServerSocket.close();
// Le simulateur entre dans une boucle infinie pour générer et envoyer
périodiquement des données de température.

while (true) {
// Une température simulée est générée à l'aide d'un générateur de nombres
aléatoires. La température varie entre 20°C et 30°C.
random.nextFloat() génère un nombre décimal aléatoire entre 0 (inclus) et 1
(exclus). En d'autres termes, il génère un nombre à virgule flottante (float)
aléatoire dans l'intervalle [0, 1).

double temperature = 20 + random.nextFloat() * 10;

// Envoie les données au serveur de collecte de données


String sensorData = "Température du capteur " + sensorNumber + " :
" + temperature + " °C";
// Les données sont converties en tableau de bytes pour être envoyées via UDP.
byte[] sendData = sensorData.getBytes();
// Un paquet UDP est créé pour encapsuler les données et spécifier l'adresse IP et
le port du serveur de collecte de données.
DatagramPacket sendPacket = new DatagramPacket(sendData,
sendData.length, serverAddress, serverPort);
// Les données sont envoyées au serveur de collecte de données via le socket UDP.
socket.send(sendPacket);

Thread.sleep(5000); // Attendez 5 secondes avant la prochaine


collecte de données
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}

3. Serveur de Numérotation des Capteurs (SensorNumberServer) :


Fonctionnalités clés :

1. Crée un ServerSocket pour attendre les demandes de numéros de capteur.

2. Gère un compteur atomique (sensorCounter) pour attribuer des numéros de


capteur uniques.

3. Accepte les demandes de numéro de capteur des simulateurs de capteur et leur


attribue un numéro de capteur unique.

4. Envoie le numéro de capteur attribué au simulateur de capteur qui en fait la


demande.
4
import java.net.*;
import java.io.*;
import java.util.concurrent.atomic.AtomicInteger;

public class SensorNumberServer {


// Un compteur atomique est initialisé à 0. Cela permet d'attribuer de manière
atomique des numéros de capteur uniques
private static AtomicInteger sensorCounter = new AtomicInteger(0);
// Cette méthode est utilisée pour attribuer un numéro de capteur unique à chaque
client qui en fait la demande. Elle utilise le compteur atomique pour générer un
nouveau numéro de capteur à chaque appel.

public static int assignSensorNumber() {


return sensorCounter.incrementAndGet();
}

public static void main(String[] args) {

// Un objet ServerSocket est créé pour écouter les demandes de numéro de capteur sur
le port 12345.
try (ServerSocket serverSocket = new ServerSocket(12345)) {
System.out.println("Serveur de numérotation des capteurs en
attente...");
// Le serveur entre dans une boucle infinie pour attendre en permanence les demandes
de numéro de capteur des clients.
while (true) {
//Lorsqu'une connexion TCP est établie avec un client, un objet Socket est créé pour
gérer la communication avec ce client.
Socket clientSocket = serverSocket.accept();
System.out.println("Nouvelle demande de numéro de capteur
reçue.");
int sensorNumber = assignSensorNumber(); // Un numéro de capteur
unique est attribué au client en appelant la méthode
assignSensorNumber()
sensorNumber); System.out.println("Numéro de capteur attribué : " +

// Envoyer le numéro de capteur au client


ObjectOutputStream outputStream = new
ObjectOutputStream(clientSocket.getOutputStream());
outputStream.writeInt(sensorNumber);
outputStream.flush();//Le flux de sortie est vidé pour s'assurer
que toutes les données sont envoyées.

clientSocket.close(); // La connexion avec le client est fermée


après avoir envoyé le numéro de capteur.
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

Vous aimerez peut-être aussi