Ressources informatiques

Ressources informatiques

Ressources informatiques

Publier et souscrire à un topic MQTT en langage C

Documentations :

Installer la librairie

pi@raspberrypi:~ $ sudo  apt-get install libmosquitto-dev

Coder un programme permettant de publier à un topic sans couche SSL

Coder > fichier mosquittoPublishSubscribe.c

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <threads.h>
#include <mosquitto.h>

#define PORT_SERVEUR_MQTT 1883
#define ADRESSE_IP_SERVEUR_MQTT "192.168.56.101"
#define KEEPALIVE 60

// MQTT Utilisateur : user1, mot de passe : bonjour
#define USER_MQTT "user1"
#define PASSWORD_MQTT "bonjour"

#define TOPIC_IOT1_TEMPERATURE "iot1/temperature"
#define TOPIC_IOT1_HUMIDITE "iot1/humidite"

void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message)
{
   float valeur;
   if (message->payloadlen)
   {
      // printf("--------------------------------%s %s\n", message->topic, message->payload);
      if (strcmp(TOPIC_IOT1_HUMIDITE, message->topic) == 0)
      {
         valeur = atof(message->payload);
         printf("%s -> %0.2f\n", TOPIC_IOT1_HUMIDITE, valeur);
      }
   }
   fflush(stdout);
}

static int threadSubscribe(void *argument)
{
  int retourThread;
  struct mosquitto *clientMosquitto = (struct mosquitto *)argument;

   mosquitto_message_callback_set(clientMosquitto, my_message_callback);
   mosquitto_subscribe(clientMosquitto, NULL, "#", 0);
   mosquitto_loop_forever(clientMosquitto, -1, 1);

   return retourThread;
}

int main(int argc, char *argv[])
{
   struct mosquitto *clientMosquitto;
   char payload[100];
   float temperature = 0.0f;
   thrd_t  idThread; // Identifiant du thread

   // Initialiser la librairie
   mosquitto_lib_init();

   // Créer un client mosquitto
   clientMosquitto = mosquitto_new(NULL, true, NULL);
   if (clientMosquitto == NULL)
   {perror("mosquitto_new()");return -1;
   }

   // Définir le callback de réception des messages
   mosquitto_message_callback_set(clientMosquitto, my_message_callback);

   // Définir l'utilisateur et le mot de passe
   mosquitto_username_pw_set(clientMosquitto, USER_MQTT, PASSWORD_MQTT);

   // Effectuer la connexion
   if (mosquitto_connect(clientMosquitto, ADRESSE_IP_SERVEUR_MQTT, PORT_SERVEUR_MQTT, KEEPALIVE) != MOSQ_ERR_SUCCESS)
   {perror("mosquitto_new()");return -1;}

   // Démarrer un thread
    if (thrd_create(&idThread, &threadSubscribe, (void *)clientMosquitto)  != thrd_success)
    {perror("thrd_create() :"); return -1;}

   // Publier le topic -> QOs = 1 ; retain = true
   while (1)
   {
      temperature = 22.3;
      sprintf(payload, "%0.2f", temperature);
      mosquitto_publish(clientMosquitto, NULL, TOPIC_IOT1_TEMPERATURE, strlen(payload), payload, 1, true);
      sleep(1);
   }
   mosquitto_destroy(clientMosquitto);
   mosquitto_lib_cleanup();

   return 0;
}

Compiler

pi@raspberrypi:~ $  gcc -o mosquittoPublishSubscribe -std=c11 -pthread mosquittoPublishSubscribe.c -lmosquitto

Abonnement

doe@debian:~$ mosquitto_sub  -h localhost -u user1 -P bonjour -t 'iot1/temperature'
22.30
22.30
22.30
22.30

Publication

doe@debian:~$ mosquitto_pub -h localhost -u 'user2' -P bonjour -t 'iot1/humidite' -q 1 -r -m 50.2
doe@debian:~$ mosquitto_pub -h localhost -u 'user2' -P bonjour -t 'iot1/humidite' -q 1 -r -m 50.3
doe@debian:~$ mosquitto_pub -h localhost -u 'user2' -P bonjour -t 'iot1/humidite' -q 1 -r -m 50.4

Abonnement et publication

pi@raspberrypi:~ $ ./mosquittoPublishSubscribe                                  
iot1/humidite -> 50.20
iot1/humidite -> 50.30
iot1/humidite -> 50.40

Coder un programme permettant de publier à un topic avec une couche SSL

Coder > fichier mosquittoPublishSubscribe.c

doe@client1:~$ cat mosquittoPublishSubscribeSSL.c
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <threads.h>
#include <mosquitto.h>
#define PORT_SERVEUR_MQTT 8883
#define ADRESSE_IP_SERVEUR_MQTT "broker.btscielmichelet.lan"
#define KEEPALIVE 60

// MQTT Utilisateur : user1, mot de passe : IOTPasswd
#define USER_MQTT "user1"
#define PASSWORD_MQTT "IOTPasswd"

// certificat serveur
#define CA_CRT "ca.crt"

// Cle privee et certificat client
#define CLIENT_KEY "client1.key"
#define CLIENT_CRT "client1.crt"

#define TOPIC_IOT1_HUMIDITE "iot1/humidite"
#define TOPIC_IOT1_TEMPERATURE "iot1/temperature"

void on_connect(struct mosquitto *mosq, void *obj, int reason_code) {
    printf("Connect: callback, rc=%d\n", reason_code);
}

void on_disconnect(struct mosquitto *mosq, void *obj, int rc) {
    printf("Disconnect: callback, rc=%d\n", rc);
}

void on_log(struct mosquitto *mosq, void *obj, int level, const char *str) {
    printf("Log: %s\n", str);
}

void my_message_callback(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *message) {
   float valeur;

   if(message->payloadlen){
      if (strcmp(TOPIC_IOT1_HUMIDITE, message->topic) == 0)
      {
         valeur = atof(message->payload);
         printf("%s -> %0.2f\n", TOPIC_IOT1_HUMIDITE, valeur);
      }
   } else {
     printf("%s (null)\n", message->topic);
   }
   fflush(stdout);
}

static int threadSubscribe(void *argument)
{
  int retourThread;
  struct mosquitto *clientMosquitto = (struct mosquitto *)argument;

   mosquitto_message_callback_set(clientMosquitto, my_message_callback);
   mosquitto_subscribe(clientMosquitto, NULL, TOPIC_IOT1_HUMIDITE, 0);
   mosquitto_loop_forever(clientMosquitto, -1, 1);

   return retourThread;
}

int main(int argc, char *argv[]) {
   struct       mosquitto *clientMosquitto;
   char payload[100];
   float temperature = 0.0f;
   thrd_t  idThread; // Identifiant du thread

   // Initialiser la librairie
   mosquitto_lib_init();

   // Créer un client mosquitto
   clientMosquitto = mosquitto_new(NULL, true, NULL);
   if (clientMosquitto == NULL)
   {perror("mosquitto_new()");return -1;}

   mosquitto_connect_callback_set(clientMosquitto, on_connect);
   mosquitto_disconnect_callback_set(clientMosquitto, on_disconnect);
   mosquitto_log_callback_set(clientMosquitto, on_log);

   // Définir le callback de réception des messages
   mosquitto_message_callback_set(clientMosquitto, my_message_callback);

   // Définir l'utilisateur et le mot de passe
   mosquitto_username_pw_set(clientMosquitto, USER_MQTT, PASSWORD_MQTT);

   // Définir la sécurité SSL
   int retour = mosquitto_tls_set(clientMosquitto, CA_CRT, NULL, CLIENT_CRT, CLIENT_KEY, NULL);
   if (retour !=  MOSQ_ERR_SUCCESS)
   {fprintf(stderr, "Error setting TLS options: %s\n", mosquitto_strerror(retour)); return -1;}

   retour = mosquitto_tls_opts_set(clientMosquitto, 1, "tlsv1.2", NULL);
   if (retour != MOSQ_ERR_SUCCESS) {
       fprintf(stderr, "Error setting TLS options: %s\n", mosquitto_strerror(retour));
       return 1;
   }

   // Effectuer la connexion
   retour = mosquitto_connect(clientMosquitto, ADRESSE_IP_SERVEUR_MQTT, PORT_SERVEUR_MQTT, KEEPALIVE);
   if (retour != MOSQ_ERR_SUCCESS)
   {fprintf(stderr, "Unable to connect: %s\n", mosquitto_strerror(retour)); return -1;}

   // Démarrer un thread
   if (thrd_create(&idThread, &threadSubscribe, (void *)clientMosquitto)  != thrd_success)
   {perror("thrd_create() :"); return -1;}

   // Publier le topic -> QOs = 1 ; retain = false
   temperature = 22.3;
   while (1)
   {
     temperature = temperature + 0.1;
     sprintf(payload, "%0.2f", temperature);
     mosquitto_publish(clientMosquitto, NULL, TOPIC_IOT1_TEMPERATURE, strlen(payload), payload, 1, false);
     sleep(1);
   }

   mosquitto_destroy(clientMosquitto);
   mosquitto_lib_cleanup();

   return 0;
}

Compiler

pi@raspberrypi:~ $  gcc -o mosquittoPublishSubscribeSSL -std=c11 -pthread mosquittoPublishSubscribeSSL.c -lmosquitto

Abonnement

doe@client2:~$ mosquitto_sub  -h broker.btscielmichelet.lan -u user1 -P IOTPasswd -p 8883 --cafile ca.crt --cert client2.crt --key client2.key -d -t '#'
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending SUBSCRIBE (Mid: 1, Topic: #, QoS: 0, Options: 0x00)
Client (null) received SUBACK
Subscribed (mid: 1): 0
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
25.70
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.40
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.50
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.60
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.70
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
57
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.80
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
22.90
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
23.00
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
23.10
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
56
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
23.20
Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
23.30

Publication

doe@client1:~$ mosquitto_pub  -h broker.btscielmichelet.lan -u user1 -P IOTPasswd -p 8883 --cafile ca.crt --cert client1.crt --key client1.key -d -t 'iot1/humidite' -m 57
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'iot1/humidite', ... (2 bytes))
Client (null) sending DISCONNECT
doe@client1:~$ mosquitto_pub  -h broker.btscielmichelet.lan -u user1 -P IOTPasswd -p 8883 --cafile ca.crt --cert client1.crt --key client1.key -d -t 'iot1/humidite' -m 56
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'iot1/humidite', ... (2 bytes))
Client (null) sending DISCONNECT

Abonnement et publication

doe@client1:~$ ./mosquittoPublishSubscribeSSL
Log: Client (null) sending CONNECT
Log: Client (null) sending PUBLISH (d0, q1, r0, m1, 'iot1/temperature', ... (5 bytes))
Log: Client (null) sending SUBSCRIBE (Mid: 2, Topic: iot1/humidite, QoS: 0, Options: 0x00)
Log: Client (null) received CONNACK (0)
Connect: callback, rc=0
Log: Client (null) received PUBACK (Mid: 1, RC:0)
Log: Client (null) received SUBACK
Log: Client (null) sending PUBLISH (d0, q1, r0, m3, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 3, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m4, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 4, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m5, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 5, RC:0)
Log: Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
iot1/humidite -> 57.00
Log: Client (null) sending PUBLISH (d0, q1, r0, m6, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 6, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m7, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 7, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m8, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 8, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m9, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 9, RC:0)
Log: Client (null) received PUBLISH (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
iot1/humidite -> 56.00
Log: Client (null) sending PUBLISH (d0, q1, r0, m10, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 10, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m11, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 11, RC:0)
Log: Client (null) sending PUBLISH (d0, q1, r0, m12, 'iot1/temperature', ... (5 bytes))
Log: Client (null) received PUBACK (Mid: 12, RC:0)

Log sur le serveur

adminX@broker:~$ sudo tail -20 /var/log/mosquitto/mosquitto.log
[sudo] Mot de passe de adminX :
1716891458: New client connected from 192.168.56.201:45544 as auto-AAC83219-F431-3615-F589-D680BD289DD6 (p2, c1, k60, u'user1').
1716891458: No will message specified.
1716891458: Sending CONNACK to auto-AAC83219-F431-3615-F589-D680BD289DD6 (0, 0)
1716891458: Received PUBLISH from auto-AAC83219-F431-3615-F589-D680BD289DD6 (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
1716891458: Sending PUBLISH to auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
1716891458: Sending PUBLISH to auto-A001B2A5-DA2B-F370-6EF8-731574F9B6B1 (d0, q0, r0, m0, 'iot1/humidite', ... (2 bytes))
1716891458: Received DISCONNECT from auto-AAC83219-F431-3615-F589-D680BD289DD6
1716891458: Client auto-AAC83219-F431-3615-F589-D680BD289DD6 disconnected.
1716891458: Received PUBLISH from auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (d0, q1, r0, m10, 'iot1/temperature', ... (5 bytes))
1716891458: Sending PUBLISH to auto-A001B2A5-DA2B-F370-6EF8-731574F9B6B1 (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
1716891458: Sending PUBACK to auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (m10, rc0)
1716891459: Received PUBLISH from auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (d0, q1, r0, m11, 'iot1/temperature', ... (5 bytes))
1716891459: Sending PUBLISH to auto-A001B2A5-DA2B-F370-6EF8-731574F9B6B1 (d0, q0, r0, m0, 'iot1/temperature', ... (5 bytes))
1716891459: Sending PUBACK to auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (m11, rc0)
1716891460: Received DISCONNECT from auto-A001B2A5-DA2B-F370-6EF8-731574F9B6B1
1716891460: Client auto-A001B2A5-DA2B-F370-6EF8-731574F9B6B1 disconnected.
1716891460: Received PUBLISH from auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (d0, q1, r0, m12, 'iot1/temperature', ... (5 bytes))
1716891460: Sending PUBACK to auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 (m12, rc0)
1716891461: OpenSSL Error[0]: error:0A000126:SSL routines::unexpected eof while reading
1716891461: Client auto-A6B99D4D-CC18-73B4-D81A-C2571EA27C83 closed its connection.