MQTT Client¶
MQTT client v3.1.1 implementation, based on callback (non-netconn) connection API.
1/*
2 * MQTT client example with ESP device.
3 *
4 * Once device is connected to network,
5 * it will try to connect to mosquitto test server and start the MQTT.
6 *
7 * If successfully connected, it will publish data to "esp8266_mqtt_topic" topic every x seconds.
8 *
9 * To check if data are sent, you can use mqtt-spy PC software to inspect
10 * test.mosquitto.org server and subscribe to publishing topic
11 */
12
13#include "lwesp/apps/lwesp_mqtt_client.h"
14#include "lwesp/lwesp.h"
15#include "lwesp/lwesp_timeout.h"
16#include "mqtt_client.h"
17
18/**
19 * \brief MQTT client structure
20 */
21static lwesp_mqtt_client_p
22mqtt_client;
23
24/**
25 * \brief Client ID is structured from ESP station MAC address
26 */
27static char
28mqtt_client_id[13];
29
30/**
31 * \brief Connection information for MQTT CONNECT packet
32 */
33static const lwesp_mqtt_client_info_t
34mqtt_client_info = {
35 .id = mqtt_client_id, /* The only required field for connection! */
36
37 .keep_alive = 10,
38 // .user = "test_username",
39 // .pass = "test_password",
40};
41
42static void mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt);
43static void example_do_connect(lwesp_mqtt_client_p client);
44static uint32_t retries = 0;
45
46/**
47 * \brief Custom callback function for ESP events
48 */
49static lwespr_t
50mqtt_lwesp_cb(lwesp_evt_t* evt) {
51 switch (lwesp_evt_get_type(evt)) {
52#if LWESP_CFG_MODE_STATION
53 case LWESP_EVT_WIFI_GOT_IP: {
54 example_do_connect(mqtt_client); /* Start connection after we have a connection to network client */
55 break;
56 }
57#endif /* LWESP_CFG_MODE_STATION */
58 default:
59 break;
60 }
61 return lwespOK;
62}
63
64/**
65 * \brief MQTT client thread
66 * \param[in] arg: User argument
67 */
68void
69mqtt_client_thread(void const* arg) {
70 lwesp_mac_t mac;
71
72 lwesp_evt_register(mqtt_lwesp_cb); /* Register new callback for general events from ESP stack */
73
74 /* Get station MAC to format client ID */
75 if (lwesp_sta_getmac(&mac, NULL, NULL, 1) == lwespOK) {
76 snprintf(mqtt_client_id, sizeof(mqtt_client_id), "%02X%02X%02X%02X%02X%02X",
77 (unsigned)mac.mac[0], (unsigned)mac.mac[1], (unsigned)mac.mac[2],
78 (unsigned)mac.mac[3], (unsigned)mac.mac[4], (unsigned)mac.mac[5]
79 );
80 } else {
81 strcpy(mqtt_client_id, "unknown");
82 }
83 printf("MQTT Client ID: %s\r\n", mqtt_client_id);
84
85 /*
86 * Create a new client with 256 bytes of RAW TX data
87 * and 128 bytes of RAW incoming data
88 */
89 mqtt_client = lwesp_mqtt_client_new(256, 128);/* Create new MQTT client */
90 if (lwesp_sta_is_joined()) { /* If ESP is already joined to network */
91 example_do_connect(mqtt_client); /* Start connection to MQTT server */
92 }
93
94 /* Make dummy delay of thread */
95 while (1) {
96 lwesp_delay(1000);
97 }
98}
99
100/**
101 * \brief Timeout callback for MQTT events
102 * \param[in] arg: User argument
103 */
104void
105mqtt_timeout_cb(void* arg) {
106 static uint32_t num = 10;
107 lwesp_mqtt_client_p client = arg;
108 lwespr_t res;
109
110 static char tx_data[20];
111
112 if (lwesp_mqtt_client_is_connected(client)) {
113 sprintf(tx_data, "R: %u, N: %u", (unsigned)retries, (unsigned)num);
114 if ((res = lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", tx_data, LWESP_U16(strlen(tx_data)), LWESP_MQTT_QOS_EXACTLY_ONCE, 0, (void*)((uintptr_t)num))) == lwespOK) {
115 printf("Publishing %d...\r\n", (int)num);
116 num++;
117 } else {
118 printf("Cannot publish...: %d\r\n", (int)res);
119 }
120 }
121 lwesp_timeout_add(10000, mqtt_timeout_cb, client);
122}
123
124/**
125 * \brief MQTT event callback function
126 * \param[in] client: MQTT client where event occurred
127 * \param[in] evt: Event type and data
128 */
129static void
130mqtt_cb(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t* evt) {
131 switch (lwesp_mqtt_client_evt_get_type(client, evt)) {
132 /*
133 * Connect event
134 * Called if user successfully connected to MQTT server
135 * or even if connection failed for some reason
136 */
137 case LWESP_MQTT_EVT_CONNECT: { /* MQTT connect event occurred */
138 lwesp_mqtt_conn_status_t status = lwesp_mqtt_client_evt_connect_get_status(client, evt);
139
140 if (status == LWESP_MQTT_CONN_STATUS_ACCEPTED) {
141 printf("MQTT accepted!\r\n");
142 /*
143 * Once we are accepted by server,
144 * it is time to subscribe to different topics
145 * We will subscrive to "mqtt_lwesp_example_topic" topic,
146 * and will also set the same name as subscribe argument for callback later
147 */
148 lwesp_mqtt_client_subscribe(client, "esp8266_mqtt_topic", LWESP_MQTT_QOS_EXACTLY_ONCE, "esp8266_mqtt_topic");
149
150 /* Start timeout timer after 5000ms and call mqtt_timeout_cb function */
151 lwesp_timeout_add(5000, mqtt_timeout_cb, client);
152 } else {
153 printf("MQTT server connection was not successful: %d\r\n", (int)status);
154
155 /* Try to connect all over again */
156 example_do_connect(client);
157 }
158 break;
159 }
160
161 /*
162 * Subscribe event just happened.
163 * Here it is time to check if it was successful or failed attempt
164 */
165 case LWESP_MQTT_EVT_SUBSCRIBE: {
166 const char* arg = lwesp_mqtt_client_evt_subscribe_get_argument(client, evt); /* Get user argument */
167 lwespr_t res = lwesp_mqtt_client_evt_subscribe_get_result(client, evt); /* Get result of subscribe event */
168
169 if (res == lwespOK) {
170 printf("Successfully subscribed to %s topic\r\n", arg);
171 if (!strcmp(arg, "esp8266_mqtt_topic")) { /* Check topic name we were subscribed */
172 /* Subscribed to "esp8266_mqtt_topic" topic */
173
174 /*
175 * Now publish an even on example topic
176 * and set QoS to minimal value which does not guarantee message delivery to received
177 */
178 lwesp_mqtt_client_publish(client, "esp8266_mqtt_topic", "test_data", 9, LWESP_MQTT_QOS_AT_MOST_ONCE, 0, (void*)1);
179 }
180 }
181 break;
182 }
183
184 /* Message published event occurred */
185 case LWESP_MQTT_EVT_PUBLISH: {
186 uint32_t val = (uint32_t)(uintptr_t)lwesp_mqtt_client_evt_publish_get_argument(client, evt);/* Get user argument, which is in fact our custom number */
187
188 printf("Publish event, user argument on message was: %d\r\n", (int)val);
189 break;
190 }
191
192 /*
193 * A new message was published to us
194 * and now it is time to read the data
195 */
196 case LWESP_MQTT_EVT_PUBLISH_RECV: {
197 const char* topic = lwesp_mqtt_client_evt_publish_recv_get_topic(client, evt);
198 size_t topic_len = lwesp_mqtt_client_evt_publish_recv_get_topic_len(client, evt);
199 const uint8_t* payload = lwesp_mqtt_client_evt_publish_recv_get_payload(client, evt);
200 size_t payload_len = lwesp_mqtt_client_evt_publish_recv_get_payload_len(client, evt);
201
202 LWESP_UNUSED(payload);
203 LWESP_UNUSED(payload_len);
204 LWESP_UNUSED(topic);
205 LWESP_UNUSED(topic_len);
206 break;
207 }
208
209 /* Client is fully disconnected from MQTT server */
210 case LWESP_MQTT_EVT_DISCONNECT: {
211 printf("MQTT client disconnected!\r\n");
212 example_do_connect(client); /* Connect to server all over again */
213 break;
214 }
215
216 default:
217 break;
218 }
219}
220
221/** Make a connection to MQTT server in non-blocking mode */
222static void
223example_do_connect(lwesp_mqtt_client_p client) {
224 if (client == NULL) {
225 return;
226 }
227
228 /*
229 * Start a simple connection to open source
230 * MQTT server on mosquitto.org
231 */
232 retries++;
233 lwesp_timeout_remove(mqtt_timeout_cb);
234 lwesp_mqtt_client_connect(mqtt_client, "test.mosquitto.org", 1883, mqtt_cb, &mqtt_client_info);
235}
- group LWESP_APP_MQTT_CLIENT
MQTT client.
Typedefs
-
typedef struct lwesp_mqtt_client *lwesp_mqtt_client_p¶
Pointer to lwesp_mqtt_client_t structure.
-
typedef void (*lwesp_mqtt_evt_fn)(lwesp_mqtt_client_p client, lwesp_mqtt_evt_t *evt)¶
MQTT event callback function.
- Param client
[in] MQTT client
- Param evt
[in] MQTT event with type and related data
Enums
-
enum lwesp_mqtt_qos_t¶
Quality of service enumeration.
Values:
-
enumerator LWESP_MQTT_QOS_AT_MOST_ONCE¶
Delivery is not guaranteed to arrive, but can arrive
up to 1 time
= non-critical packets where losses are allowed
-
enumerator LWESP_MQTT_QOS_AT_LEAST_ONCE¶
Delivery is quaranteed
at least once
, but it may be delivered multiple times with the same content
-
enumerator LWESP_MQTT_QOS_EXACTLY_ONCE¶
Delivery is quaranteed
exactly once
= very critical packets such as billing informations or similar
-
enumerator LWESP_MQTT_QOS_AT_MOST_ONCE¶
-
enum lwesp_mqtt_state_t¶
State of MQTT client.
Values:
-
enumerator LWESP_MQTT_CONN_DISCONNECTED¶
Connection with server is not established
-
enumerator LWESP_MQTT_CONN_CONNECTING¶
Client is connecting to server
-
enumerator LWESP_MQTT_CONN_DISCONNECTING¶
Client connection is disconnecting from server
-
enumerator LWESP_MQTT_CONNECTING¶
MQTT client is connecting… CONNECT command has been sent to server
-
enumerator LWESP_MQTT_CONNECTED¶
MQTT is fully connected and ready to send data on topics
-
enumerator LWESP_MQTT_CONN_DISCONNECTED¶
-
enum lwesp_mqtt_evt_type_t¶
MQTT event types.
Values:
-
enumerator LWESP_MQTT_EVT_CONNECT¶
MQTT client connect event
-
enumerator LWESP_MQTT_EVT_SUBSCRIBE¶
MQTT client subscribed to specific topic
-
enumerator LWESP_MQTT_EVT_UNSUBSCRIBE¶
MQTT client unsubscribed from specific topic
-
enumerator LWESP_MQTT_EVT_PUBLISH¶
MQTT client publish message to server event.
Note
When publishing packet with quality of service LWESP_MQTT_QOS_AT_MOST_ONCE, you may not receive event, even if packet was successfully sent, thus do not rely on this event for packet with
qos = LWESP_MQTT_QOS_AT_MOST_ONCE
-
enumerator LWESP_MQTT_EVT_PUBLISH_RECV¶
MQTT client received a publish message from server
-
enumerator LWESP_MQTT_EVT_DISCONNECT¶
MQTT client disconnected from MQTT server
-
enumerator LWESP_MQTT_EVT_KEEP_ALIVE¶
MQTT keep-alive sent to server and reply received
-
enumerator LWESP_MQTT_EVT_CONNECT¶
-
enum lwesp_mqtt_conn_status_t¶
List of possible results from MQTT server when executing connect command.
Values:
-
enumerator LWESP_MQTT_CONN_STATUS_ACCEPTED¶
Connection accepted and ready to use
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_PROTOCOL_VERSION¶
Connection Refused, unacceptable protocol version
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_ID¶
Connection refused, identifier rejected
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_SERVER¶
Connection refused, server unavailable
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_USER_PASS¶
Connection refused, bad user name or password
-
enumerator LWESP_MQTT_CONN_STATUS_REFUSED_NOT_AUTHORIZED¶
Connection refused, not authorized
-
enumerator LWESP_MQTT_CONN_STATUS_TCP_FAILED¶
TCP connection to server was not successful
-
enumerator LWESP_MQTT_CONN_STATUS_ACCEPTED¶
Functions
-
lwesp_mqtt_client_p lwesp_mqtt_client_new(size_t tx_buff_len, size_t rx_buff_len)¶
Allocate a new MQTT client structure.
- Parameters
tx_buff_len – [in] Length of raw data output buffer
rx_buff_len – [in] Length of raw data input buffer
- Returns
Pointer to new allocated MQTT client structure or
NULL
on failure
-
void lwesp_mqtt_client_delete(lwesp_mqtt_client_p client)¶
Delete MQTT client structure.
Note
MQTT client must be disconnected first
- Parameters
client – [in] MQTT client
-
lwespr_t lwesp_mqtt_client_connect(lwesp_mqtt_client_p client, const char *host, lwesp_port_t port, lwesp_mqtt_evt_fn evt_fn, const lwesp_mqtt_client_info_t *info)¶
Connect to MQTT server.
Note
After TCP connection is established, CONNECT packet is automatically sent to server
-
lwespr_t lwesp_mqtt_client_disconnect(lwesp_mqtt_client_p client)¶
Disconnect from MQTT server.
-
uint8_t lwesp_mqtt_client_is_connected(lwesp_mqtt_client_p client)¶
Test if client is connected to server and accepted to MQTT protocol.
Note
Function will return error if TCP is connected but MQTT not accepted
- Parameters
client – [in] MQTT client
- Returns
1
on success,0
otherwise
-
lwespr_t lwesp_mqtt_client_subscribe(lwesp_mqtt_client_p client, const char *topic, lwesp_mqtt_qos_t qos, void *arg)¶
Subscribe to MQTT topic.
- Parameters
client – [in] MQTT client
topic – [in] Topic name to subscribe to
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t
arg – [in] User custom argument used in callback
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
lwespr_t lwesp_mqtt_client_unsubscribe(lwesp_mqtt_client_p client, const char *topic, void *arg)¶
Unsubscribe from MQTT topic.
-
lwespr_t lwesp_mqtt_client_publish(lwesp_mqtt_client_p client, const char *topic, const void *payload, uint16_t len, lwesp_mqtt_qos_t qos, uint8_t retain, void *arg)¶
Publish a new message on specific topic.
- Parameters
client – [in] MQTT client
topic – [in] Topic to send message to
payload – [in] Message data
payload_len – [in] Length of payload data
qos – [in] Quality of service. This parameter can be a value of lwesp_mqtt_qos_t enumeration
retain – [in] Retian parameter value
arg – [in] User custom argument used in callback
- Returns
lwespOK on success, member of lwespr_t enumeration otherwise
-
void *lwesp_mqtt_client_get_arg(lwesp_mqtt_client_p client)¶
Get user argument on client.
- Parameters
client – [in] MQTT client handle
- Returns
User argument
-
void lwesp_mqtt_client_set_arg(lwesp_mqtt_client_p client, void *arg)¶
Set user argument on client.
- Parameters
client – [in] MQTT client handle
arg – [in] User argument
-
struct lwesp_mqtt_client_info_t¶
- #include <lwesp_mqtt_client.h>
MQTT client information structure.
Public Members
-
const char *id¶
Client unique identifier. It is required and must be set by user
-
const char *user¶
Authentication username. Set to
NULL
if not required
-
const char *pass¶
Authentication password, set to
NULL
if not required
-
uint16_t keep_alive¶
Keep-alive parameter in units of seconds. When set to
0
, functionality is disabled (not recommended)
-
const char *will_topic¶
Will topic
-
const char *will_message¶
Will message
-
lwesp_mqtt_qos_t will_qos¶
Will topic quality of service
-
const char *id¶
-
struct lwesp_mqtt_request_t¶
- #include <lwesp_mqtt_client.h>
MQTT request object.
Public Members
-
uint8_t status¶
Entry status flag for in use or pending bit
-
uint16_t packet_id¶
Packet ID generated by client on publish
-
void *arg¶
User defined argument
-
uint32_t expected_sent_len¶
Number of total bytes which must be sent on connection before we can say “packet was sent”.
-
uint32_t timeout_start_time¶
Timeout start time in units of milliseconds
-
uint8_t status¶
-
struct lwesp_mqtt_evt_t¶
- #include <lwesp_mqtt_client.h>
MQTT event structure for callback function.
Public Members
-
lwesp_mqtt_evt_type_t type¶
Event type
-
lwesp_mqtt_conn_status_t status¶
Connection status with MQTT
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] connect¶
Event for connecting to server
-
uint8_t is_accepted¶
Status if client was accepted to MQTT prior disconnect event
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] disconnect¶
Event for disconnecting from server
-
void *arg¶
User argument for callback function
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] sub_unsub_scribed¶
Event for (un)subscribe to/from topics
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] publish¶
Published event
-
const uint8_t *topic¶
Pointer to topic identifier
-
size_t topic_len¶
Length of topic
-
const void *payload¶
Topic payload
-
size_t payload_len¶
Length of topic payload
-
uint8_t dup¶
Duplicate flag if message was sent again
-
lwesp_mqtt_qos_t qos¶
Received packet quality of service
-
struct lwesp_mqtt_evt_t::[anonymous]::[anonymous] publish_recv¶
Publish received event
-
union lwesp_mqtt_evt_t::[anonymous] evt¶
Event data parameters
-
lwesp_mqtt_evt_type_t type¶
-
typedef struct lwesp_mqtt_client *lwesp_mqtt_client_p¶
- group LWESP_APP_MQTT_CLIENT_EVT
Event helper functions.
Connect event
Note
Use these functions on LWESP_MQTT_EVT_CONNECT event
-
lwesp_mqtt_client_evt_connect_get_status(client, evt)¶
Get connection status.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Connection status. Member of lwesp_mqtt_conn_status_t
Disconnect event
Note
Use these functions on LWESP_MQTT_EVT_DISCONNECT event
-
lwesp_mqtt_client_evt_disconnect_is_accepted(client, evt)¶
Check if MQTT client was accepted by server when disconnect event occurred.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
1
on success,0
otherwise
Subscribe/unsubscribe event
Note
Use these functions on LWESP_MQTT_EVT_SUBSCRIBE or LWESP_MQTT_EVT_UNSUBSCRIBE events
-
lwesp_mqtt_client_evt_subscribe_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_subscribe.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
-
lwesp_mqtt_client_evt_subscribe_get_result(client, evt)¶
Get result of subscribe event.
-
lwesp_mqtt_client_evt_unsubscribe_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_unsubscribe.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
Publish receive event
Note
Use these functions on LWESP_MQTT_EVT_PUBLISH_RECV event
-
lwesp_mqtt_client_evt_publish_recv_get_topic(client, evt)¶
Get topic from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Topic name
-
lwesp_mqtt_client_evt_publish_recv_get_topic_len(client, evt)¶
Get topic length from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Topic length
-
lwesp_mqtt_client_evt_publish_recv_get_payload(client, evt)¶
Get payload from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Packet payload
-
lwesp_mqtt_client_evt_publish_recv_get_payload_len(client, evt)¶
Get payload length from received publish packet.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Payload length
-
lwesp_mqtt_client_evt_publish_recv_is_duplicate(client, evt)¶
Check if packet is duplicated.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
1
if duplicated,0
otherwise
-
lwesp_mqtt_client_evt_publish_recv_get_qos(client, evt)¶
Get received quality of service.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
Member of lwesp_mqtt_qos_t enumeration
Publish event
Note
Use these functions on LWESP_MQTT_EVT_PUBLISH event
-
lwesp_mqtt_client_evt_publish_get_argument(client, evt)¶
Get user argument used on lwesp_mqtt_client_publish.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
User argument
Defines
-
lwesp_mqtt_client_evt_get_type(client, evt)¶
Get MQTT event type.
- Parameters
client – [in] MQTT client
evt – [in] Event handle
- Returns
MQTT Event type, value of lwesp_mqtt_evt_type_t enumeration
-
lwesp_mqtt_client_evt_connect_get_status(client, evt)¶