CoAP est un protocole de communication dédié aux objets connectés : basé sur UDP et REST, il permet de diminuer au maximum le contenu des messages pour économiser les ressources des objets lors des transferts de données.
Nous allons voir ici comment implémenter votre propre client, à l'aide de la spécification du protocole. Le but est d'être capable d'envoyer, de la manière la plus simple possible, des données à un serveur CoAP exposant des services. Niveau matériel, un Arduino Mega avec un shield Ethernet communique avec un serveur Java.
Commençons par la structure des messages. Ce chapitre de la spécification nous explique comment les structurer :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
Ver | T | TKL | Code | Message ID | |
Token | |||||
Options | |||||
Terminator | Payload |
Je vous laisse vous référer à la spécification pour la signification des champs. Un peu plus en détails, les Options suivent un format propre :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
Ver | T | TKL | Code | Message ID | |
Token | |||||
Delta | Length | Value | |||
Terminator | Payload |
Ici nous allons construire un message contenant :
- version : 1
- type : Request
- TKL : 0 (pas de Token)
- Code : POST
- vers le service : "/sensors"
- contenu : "test"
Voici ce que cela donne :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
1 | Request | 0 | POST | Message ID | |
Uri-Path | 7 | URI segment "sensors" | |||
Terminator | "test" |
Chaque Option possède un code "Option Number" propre. Par exemple, "Uri-Path" qui permet d'indiquer un segment de l'adresse du service, a pour code 11. Le Delta se calcule alors en additionnant le code de l'option avec celles des précédentes :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
1 | Request | 0 | POST | Message ID | |
0+11 | 7 | "sensors" | |||
Terminator | "test" |
Si l'on veut spécifier plusieurs options du même type, il n'est pas nécessaire d'additionner le code. Par exemple, pour pointer sur le service "/sensors/temp" :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
1 | Request | 0 | POST | Message ID | |
0+11 | 7 | "sensors" | |||
0+11+0 | 4 | "temp" | |||
Terminator | "test" |
En revanche, pour une autre Option, par exemple "Max-Age" qui a le code 14 :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
1 | Request | 0 | POST | Message ID | |
0+11 | 7 | "sensors" | |||
0+11+14 | 2 | 12 | |||
Terminator | "test" |
Revenons à notre exemple et transformons tout en valeurs selon la spec et notre cas :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
1 | 1 | 0 | 0.02 | 52942 | |
11 | 7 | "sensors" | |||
Terminator | "test" |
Ce qui nous donne, en binaire en respectant la longueur des champs (pour les champs les plus simples) :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
01 | 01 | 00000 | 00000010 | 1100111011001110 | |
1011 | 0111 | "sensors" | |||
11 | 11 | 1111 | "test" |
Enfin, pour se faciliter l'envoi via le contrôleur Ethernet, dont la librairie est prévue pour traiter des "char" sur 8 bits, il suffit de transformer le résultat en concaténant les bits par 8 :
8 bits | 8 bits | 8 bits | 8 bits | ||
---|---|---|---|---|---|
0x50 | 0x02 | 0xCE | 0xCE | ||
0xB7 | "sensors" | ||||
0xFF | "test" |
En pratique, un petit exemple de code Arduino pour envoyer nos données :
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
char coapacket[18];
EthernetUDP udp;
void loop() {
coapacket[0] = 0x50;
coapacket[1] = 0x02;
coapacket[2] = 0xce;
coapacket[3] = 0xce;
coapacket[4] = 0xB7;
coapacket[5] = 's';
coapacket[6] = 'e';
coapacket[7] = 'n';
coapacket[8] = 's';
coapacket[9] = 'o';
coapacket[10] = 'r';
coapacket[11] = 's';
coapacket[12] = 0xff;
coapacket[13] = 't';
coapacket[14] = 'e';
coapacket[15] = 's';
coapacket[16] = 't';
coapacket[17] = '\0';
udp.beginPacket(serverIP, 5683);
udp.write(coapacket);
udp.endPacket();
}
Voilà tout!
0 commentaires:
Enregistrer un commentaire