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.