➟ Communiquer avec un Robot via UDP en Node.js

Dans le cadre de l’un de mes projets, je dois développer un logiciel backend Node.js capable de dialoguer avec un robot en utilisant le protocole UDP (User Datagram Protocol).

Nous allons donc voir dans cet article comment mettre en place cette communication en utilisant deux scripts JavaScript : l’un pour simuler l’envoi des données par le robot robot-simulator.js et l’autre pour recevoir ces données robot-udp-service.js. Nous allons détailler ces scripts et expliquer leur fonctionnement.

Cette solution permet de transmettre des données optimisées, minimisant ainsi la taille des paquets pour une communication efficace et rapide.

Do you speak robot?

Le Protocole UDP

UDP est un protocole de communication rapide mais non fiable. Contrairement à TCP, il n’assure pas la livraison des paquets et ne garantit pas leur ordre. Cependant, sa rapidité en fait un excellent choix pour des applications temps réel ou où la vitesse est cruciale.

Diagramme Séquentiel de la Communication

Diagramme Séquentiel de la Communication

Explication de la Structure des Données

Les données, au niveau du robot, sont optimisées pour minimiser la taille des paquets envoyés. Voici comment les données sont structurées sur deux octets :

Octet 1
Bits 0-1 : num1
Bits 2-7 : charCode (6 bits)
Octet 2
Bits 0-1 : charCode (suite, 2 bits)
Bits 2-7 : num2

num1 : un nombre entre 0 et 3, codé sur 2 bits.
charCode : le code ASCII d’un caractère (a-z), codé sur 8 bits (6 bits dans le premier octet, 2 bits dans le second).
num2 : un nombre entre 0 et 63, codé sur 6 bits dans le second octet.

Il va donc falloir restructurer ses données pour les exploiter dans le service de réception. Nous allons pour cela utiliser des techniques de décalage et de masquage de bits pour extraire les différentes parties des octets.

Script de Simulation du Robot : robot-simulator.js

Ce script simule le comportement du robot en envoyant des messages UDP structurés au service de réception.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
// Importation du module 'dgram' pour créer des sockets UDP
const dgram = require('dgram');
// Création d'un socket UDP
const socket = dgram.createSocket('udp4');

// Adresse IP et port du service de réception
const SERVICE_IP = '127.0.0.1';
const SERVICE_PORT = 5501;

let messageCount = 0; // Compteur pour les messages envoyés

// Fonction pour générer un entier aléatoire entre 'min' et 'max'
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}

// Fonction pour créer un message structuré
function createStructuredMessage() {
let buffer = Buffer.alloc(2);

// Génération des données
let num1 = getRandomInt(0, 3); // Nombre entre 0 et 3
let charCode = getRandomInt(97, 122); // Code ASCII pour une lettre minuscule (a-z)
let char = String.fromCharCode(charCode); // Conversion du code ASCII en caractère
let num2 = getRandomInt(0, 63); // Nombre entre 0 et 63

// Premier octet : bits 0-1 pour 'num1', bits 2-7 pour 'charCode' (6 premiers bits)
buffer[0] = (num & 0b11) | ((charCode & 0b111111) << 2);

// Deuxième octet : bits 0-1 pour 'charCode' (2 derniers bits), bits 2-7 pour 'num2'
buffer[1] = ((charCode >> 6) & 0b11) | ((num2 & 0b111111) << 2);

return { buffer, num1, char, num2 };
}

// Fonction pour envoyer un message structuré au service
function sendMessageToService(buffer, serviceIp, servicePort, num1, char, num2) {
messageCount++;
socket.send(buffer, servicePort, serviceIp, (err) => {
if (err) {
console.error('Erreur lors de l\'envoi du message:', err);
} else {
console.log(`Message envoyé ${messageCount} - Num1: ${num1}, Char: ${char}, Num2: ${num2}`);
}
});
}

// Envoi périodique de messages structurés toutes les 500 millisecondes
setInterval(() => {
const { buffer, num1, char, num2 } = createStructuredMessage();
sendMessageToService(buffer, SERVICE_IP, SERVICE_PORT, num1, char, num2);
}, 500);

// Gestion des erreurs du socket
socket.on('error', (err) => {
console.error('Erreur du socket:', err);
socket.close();
});

// Gestion de la fermeture du socket
socket.on('close', () => {
console.log('Socket fermé');
});

Script de Réception des Données : robot-udp-service.js

Ce script écoute les messages UDP envoyés par le robot. Il décode les messages structurés et affiche les données reçues.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
// Importation du module 'dgram' pour créer des sockets UDP
const dgram = require('dgram');
// Création d'un socket UDP
const socket = dgram.createSocket('udp4');

// Adresses IP et ports pour la communication avec le robot et le service local
const ROBOT_IP = '10.5.0.2';
const ROBOT_PORT = 6501;

const LOCAL_IP = '0.0.0.0';
const LOCAL_PORT = 5501;

let messageCount = 0; // Compteur pour les messages reçus

// Fonction pour envoyer un message au robot
function sendMessageToRobot(message, robotIp, robotPort) {
const messageBuffer = Buffer.from(message);
socket.send(messageBuffer, robotPort, robotIp, (err) => {
if (err) {
console.error('Erreur lors de l\'envoi du message:', err);
} else {
console.log('Message envoyé au robot:', message);
}
});
}

// Fonction pour décoder un message structuré reçu
function parseStructuredMessage(buffer) {
// Premier octet : extraction des 2 premiers bits pour 'num1' et des 6 suivants pour 'charCode'
let num1 = buffer[0] & 0b11;
let charCode = (buffer[0] >> 2) & 0b111111;

// Deuxième octet : extraction des 2 premiers bits restants de 'charCode' et des 6 bits suivants pour 'num2'
charCode |= (buffer[1] & 0b11) << 6;
let num2 = (buffer[1] >> 2) & 0b111111;

let char = String.fromCharCode(charCode);

return { num1, char, num2 };
}

// Fonction pour gérer la réception des messages
function handleIncomingMessage(msg, rinfo) {
const parsedMessage = parseStructuredMessage(msg);
messageCount++;
console.log(`Message reçu ${messageCount} - Num1: ${parsedMessage.num1}, Char: ${parsedMessage.char}, Num2: ${parsedMessage.num2}`);
}

// Configuration de l'événement 'message' pour le socket
socket.on('message', handleIncomingMessage);

// Liaison du socket à une adresse IP et un port locaux
socket.bind(LOCAL_PORT, LOCAL_IP, () => {
console.log(`Serveur UDP en écoute sur ${LOCAL_IP}:${LOCAL_PORT}`);
});

// Envoi d'un message initial au robot
sendMessageToRobot('Hello, Robot!', ROBOT_IP, ROBOT_PORT);

// Gestion des erreurs du socket
socket.on('error', (err) => {
console.error('Erreur du socket:', err);
socket.close();
});

// Gestion de la fermeture du socket
socket.on('close', () => {
console.log('Socket fermé');
});

Exécution des Scripts

Communication avec le robot

Conclusion

Ces scripts montrent comment envoyer et recevoir des messages UDP structurés en Node.js. Cette technique peut être adaptée pour divers types de communication en temps réel où la rapidité est cruciale. En suivant et adaptant ces exemples, vous pourrez implémenter des solutions similaires pour vos propres projets.

Jérémy @ Code Alchimie


Une idée de business en ligne ? Un saas à développer ? Une boutique en ligne à créer ?
Essayer mon-plan-action.fr pour vous aider à démarrer votre projet en ligne.

Mon Plan Action