From 9cffbe092862f39770889fbcb2cde72bb164d56f Mon Sep 17 00:00:00 2001 From: "Roger A. Light" Date: Thu, 23 Dec 2021 22:30:36 +0000 Subject: [PATCH] Basic client publish example using websockets. --- .gitignore | 2 + examples/publish/Makefile | 23 ++++ examples/publish/basic-1.c | 15 ++- examples/publish/basic-websockets-1.c | 148 ++++++++++++++++++++++++++ 4 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 examples/publish/Makefile create mode 100644 examples/publish/basic-websockets-1.c diff --git a/.gitignore b/.gitignore index 59afc2dc..24cdf54a 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,8 @@ docker/local/mosq.tar.gz examples/mysql_log/mosquitto_mysql_log examples/temperature_conversion/mqtt_temperature_conversion +examples/publish/basic-1 +examples/publish/basic-websockets-1 lib/cpp/libmosquittopp.so* lib/cpp/libmosquittopp.a diff --git a/examples/publish/Makefile b/examples/publish/Makefile new file mode 100644 index 00000000..d0877a5f --- /dev/null +++ b/examples/publish/Makefile @@ -0,0 +1,23 @@ +include ../../config.mk + +.PHONY: all + +all : basic-1 basic-websockets-1 + +basic-1 : basic-1.o + ${CROSS_COMPILE}${CC} $^ -o $@ ../../lib/libmosquitto.so.${SOVERSION} + +basic-websockets-1 : basic-websockets-1.o + ${CROSS_COMPILE}${CC} $^ -o $@ ../../lib/libmosquitto.so.${SOVERSION} + +basic-1.o : basic-1.c ../../lib/libmosquitto.so.${SOVERSION} + ${CROSS_COMPILE}${CC} -c $< -o $@ -I../../include ${CPPFLAGS} ${CFLAGS} + +basic-websockets-1.o : basic-websockets-1.c ../../lib/libmosquitto.so.${SOVERSION} + ${CROSS_COMPILE}${CC} -c $< -o $@ -I../../include ${CPPFLAGS} ${CFLAGS} + +../../lib/libmosquitto.so.${SOVERSION} : + $(MAKE) -C ../../lib + +clean : + -rm -f *.o sub_single sub_multiple diff --git a/examples/publish/basic-1.c b/examples/publish/basic-1.c index f2ad98a0..955fcff6 100644 --- a/examples/publish/basic-1.c +++ b/examples/publish/basic-1.c @@ -8,10 +8,15 @@ #include #include +#ifndef UNUSED +# define UNUSED(A) (void)(A) +#endif /* Callback called when the client receives a CONNACK message from the broker. */ void on_connect(struct mosquitto *mosq, void *obj, int reason_code) { + UNUSED(obj); + /* Print out the connection result. mosquitto_connack_string() produces an * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 * clients is mosquitto_reason_string(). @@ -36,6 +41,9 @@ void on_connect(struct mosquitto *mosq, void *obj, int reason_code) * received a PUBCOMP from the broker. */ void on_publish(struct mosquitto *mosq, void *obj, int mid) { + UNUSED(mosq); + UNUSED(obj); + printf("Message with mid %d has been published.\n", mid); } @@ -43,7 +51,7 @@ void on_publish(struct mosquitto *mosq, void *obj, int mid) int get_temperature(void) { sleep(1); /* Prevent a storm of messages - this pretend sensor works at 1Hz */ - return random()%100; + return (int)random()%100; } /* This function pretends to read some data from a sensor and publish it.*/ @@ -68,7 +76,7 @@ void publish_sensor_data(struct mosquitto *mosq) * qos = 2 - publish with QoS 2 for this example * retain = false - do not use the retained message feature for this message */ - rc = mosquitto_publish(mosq, NULL, "example/temperature", strlen(payload), payload, 2, false); + rc = mosquitto_publish(mosq, NULL, "example/temperature", (int)strlen(payload), payload, 2, false); if(rc != MOSQ_ERR_SUCCESS){ fprintf(stderr, "Error publishing: %s\n", mosquitto_strerror(rc)); } @@ -80,6 +88,9 @@ int main(int argc, char *argv[]) struct mosquitto *mosq; int rc; + UNUSED(argc); + UNUSED(argv); + /* Required before calling other mosquitto functions */ mosquitto_lib_init(); diff --git a/examples/publish/basic-websockets-1.c b/examples/publish/basic-websockets-1.c new file mode 100644 index 00000000..a72a1a1a --- /dev/null +++ b/examples/publish/basic-websockets-1.c @@ -0,0 +1,148 @@ +/* + * This example shows how to publish messages from outside of the Mosquitto network loop. + * + * This is identical to basic-1.c apart from that it uses WebSockets. + */ + +#include +#include +#include +#include +#include + +#ifndef UNUSED +# define UNUSED(A) (void)(A) +#endif + +/* Callback called when the client receives a CONNACK message from the broker. */ +void on_connect(struct mosquitto *mosq, void *obj, int reason_code) +{ + UNUSED(obj); + + /* Print out the connection result. mosquitto_connack_string() produces an + * appropriate string for MQTT v3.x clients, the equivalent for MQTT v5.0 + * clients is mosquitto_reason_string(). + */ + printf("on_connect: %s\n", mosquitto_connack_string(reason_code)); + if(reason_code != 0){ + /* If the connection fails for any reason, we don't want to keep on + * retrying in this example, so disconnect. Without this, the client + * will attempt to reconnect. */ + mosquitto_disconnect(mosq); + } + + /* You may wish to set a flag here to indicate to your application that the + * client is now connected. */ +} + + +/* Callback called when the client knows to the best of its abilities that a + * PUBLISH has been successfully sent. For QoS 0 this means the message has + * been completely written to the operating system. For QoS 1 this means we + * have received a PUBACK from the broker. For QoS 2 this means we have + * received a PUBCOMP from the broker. */ +void on_publish(struct mosquitto *mosq, void *obj, int mid) +{ + UNUSED(mosq); + UNUSED(obj); + + printf("Message with mid %d has been published.\n", mid); +} + + +int get_temperature(void) +{ + sleep(1); /* Prevent a storm of messages - this pretend sensor works at 1Hz */ + return (int)random()%100; +} + +/* This function pretends to read some data from a sensor and publish it.*/ +void publish_sensor_data(struct mosquitto *mosq) +{ + char payload[20]; + int temp; + int rc; + + /* Get our pretend data */ + temp = get_temperature(); + /* Print it to a string for easy human reading - payload format is highly + * application dependent. */ + snprintf(payload, sizeof(payload), "%d", temp); + + /* Publish the message + * mosq - our client instance + * *mid = NULL - we don't want to know what the message id for this message is + * topic = "example/temperature" - the topic on which this message will be published + * payloadlen = strlen(payload) - the length of our payload in bytes + * payload - the actual payload + * qos = 2 - publish with QoS 2 for this example + * retain = false - do not use the retained message feature for this message + */ + rc = mosquitto_publish(mosq, NULL, "example/temperature", (int)strlen(payload), payload, 2, false); + if(rc != MOSQ_ERR_SUCCESS){ + fprintf(stderr, "Error publishing: %s\n", mosquitto_strerror(rc)); + } +} + + +int main(int argc, char *argv[]) +{ + struct mosquitto *mosq; + int rc; + + UNUSED(argc); + UNUSED(argv); + + /* Required before calling other mosquitto functions */ + mosquitto_lib_init(); + + /* Create a new client instance. + * id = NULL -> ask the broker to generate a client id for us + * clean session = true -> the broker should remove old sessions when we connect + * obj = NULL -> we aren't passing any of our private data for callbacks + */ + mosq = mosquitto_new(NULL, true, NULL); + if(mosq == NULL){ + fprintf(stderr, "Error: Out of memory.\n"); + return 1; + } + mosquitto_int_option(mosq, MOSQ_OPT_TRANSPORT, MOSQ_T_WEBSOCKETS); + + /* Configure callbacks. This should be done before connecting ideally. */ + mosquitto_connect_callback_set(mosq, on_connect); + mosquitto_publish_callback_set(mosq, on_publish); + + /* Connect to test.mosquitto.org on port 1883, with a keepalive of 60 seconds. + * This call makes the socket connection only, it does not complete the MQTT + * CONNECT/CONNACK flow, you should use mosquitto_loop_start() or + * mosquitto_loop_forever() for processing net traffic. */ + rc = mosquitto_connect(mosq, "test.mosquitto.org", 8080, 60); + if(rc != MOSQ_ERR_SUCCESS){ + mosquitto_destroy(mosq); + fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); + return 1; + } + + /* Run the network loop in a background thread, this call returns quickly. */ + rc = mosquitto_loop_start(mosq); + if(rc != MOSQ_ERR_SUCCESS){ + mosquitto_destroy(mosq); + fprintf(stderr, "Error: %s\n", mosquitto_strerror(rc)); + return 1; + } + + /* At this point the client is connected to the network socket, but may not + * have completed CONNECT/CONNACK. + * It is fairly safe to start queuing messages at this point, but if you + * want to be really sure you should wait until after a successful call to + * the connect callback. + * In this case we know it is 1 second before we start publishing. + */ + while(1){ + publish_sensor_data(mosq); + } + + mosquitto_lib_cleanup(); + return 0; +} +