MQTT
struct mg_mqtt_opts
struct mg_mqtt_opts {
struct mg_str user; // Username, can be empty
struct mg_str pass; // Password, can be empty
struct mg_str client_id; // Client ID
struct mg_str topic; // message/subscription topic
struct mg_str message; // message content
uint8_t qos; // message quality of service
uint8_t version; // Can be 4 (3.1.1), or 5. If 0, assume 4
uint16_t keepalive; // Keep-alive timer in seconds
uint16_t retransmit_id; // For PUBLISH, init to 0
bool retain; // Retain flag
bool clean; // Clean session flag
struct mg_mqtt_prop *props; // MQTT5 props array
size_t num_props; // number of props
struct mg_mqtt_prop *will_props; // Valid only for CONNECT packet (MQTT5)
size_t num_will_props; // Number of will props
};
Structure used when connecting to a broker and when sending messages, to specify connection options and last-will message or to specify message and options
struct mg_mqtt_message
struct mg_mqtt_message {
struct mg_str topic; // Parsed topic for PUBLISH
struct mg_str data; // Parsed message for PUBLISH
struct mg_str dgram; // Whole MQTT packet, including headers
uint16_t id; // For PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, PUBLISH
uint8_t cmd; // MQTT command, one of MQTT_CMD_*
uint8_t qos; // Quality of service
uint8_t ack; // CONNACK return code, 0 = success
size_t props_start; // Offset to the start of the properties (MQTT5)
size_t props_size; // Length of the properties
};
Structure representing an MQTT packet, either control or data
mg_mqtt_connect()
struct mg_connection *mg_mqtt_connect(struct mg_mgr *mgr, const char *url,
const struct mg_mqtt_opts *opts,
mg_event_handler_t fn, void *fn_data);
Create a client MQTT connection
Parameters:
mgr- Event manager to useurl- Specifies the broker URL, e.g.mqtt://cloud.hivemq.com. If this URL is 'mqtts', theis_tlsflag will be setopts- pointer to MQTT options like client ID, clean session, last will, etc. Can be NULLfn- The event handler functionfn_data- an arbitrary pointer, which will be stored in the connection structure asc->fn_data, so the event handler can use it when called.
Return value: created connection, or NULL on error. Possible errors are: not enough memory, a NULL URL, or, in the case of our built-in TCP/IP stack, the network not being ready.
Note: This function does not connect to a broker; it allocates the required resources and
starts the TCP connection process. Once that connection is established, an MG_EV_CONNECT event is
sent to the connection event handler, then the MQTT connection process is started (by means of mg_mqtt_login()); and once the MQTT connection request gets a response from the broker, an MG_EV_MQTT_OPEN event is sent to the connection event handler; connection results are inside a struct mg_mqtt_message
Usage example:
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_CONNECT) {
// TCP connection succeeded,
// If target URL is TLS, set it up
} else if (ev == MG_EV_MQTT_OPEN) {
// MQTT connection process finished
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if(mm->ack) // MQTT connection succeeded
}
}
mg_mqtt_connect(&mgr, "mqtt://test.org:1883", NULL, fn, NULL);
or
struct mg_mqtt_opts opts = {.qos = 1,
.retain = true,
.topic = mg_str("mytopic"),
.message = mg_str("goodbye")};
mg_mqtt_connect(&mgr, "mqtt://test.org:1883", &opts, fn, NULL);
mg_mqtt_listen()
struct mg_connection *mg_mqtt_listen(struct mg_mgr *mgr, const char *url,
mg_event_handler_t fn, void *fn_data);
Create an MQTT listener (act like a broker).
Parameters:
mgr- Event manager to useurl- Specifies the local IP address and port to listen on, e.g.mqtt://0.0.0.0:1883. If this URL is 'mqtts', theis_tlsflag will be setfn- The event handler functionfn_data- an arbitrary pointer, which will be stored in the connection structure asc->fn_data, so the event handler can use it when called.
Return value: Pointer to the created connection or NULL on error
Usage example:
struct mg_connection *c = mg_mqtt_listen(&mgr, "mqtt://0.0.0.0:1883", fn, arg);
if (c == NULL) return -1; // Could not create connection
mg_mqtt_login()
void mg_mqtt_login(struct mg_connection *c, const struct mg_mqtt_opts *opts);
Send MQTT CONNECT request. Once the MQTT connection request gets a response from the broker, an MG_EV_MQTT_OPEN event is sent to the connection event handler.
This function is usually called by mg_mqtt_connect(), you will only need to call it when you manually start the MQTT connect process, e.g: when using MQTT over WebSocket. Connection results are inside a struct mg_mqtt_message
Parameters:
c- Connection to useopts- pointer to MQTT connect options, containing user name and password to use, if any, and other options
Return value: None
Usage example:
// Mongoose event handler
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_WS_OPEN) {
// WS connection established. Perform MQTT login
struct mg_mqtt_opts opts = {.qos = 1,
.retain = true,
.topic = mg_str("mytopic"),
.message = mg_str("goodbye")};
mg_mqtt_login(c, &opts);
} else if (ev == MG_EV_MQTT_OPEN) {
// MQTT connection process finished
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if(mm->ack) // MQTT connection succeeded
}
}
mg_mqtt_pub()
uint16_t mg_mqtt_pub(struct mg_connection *c, const struct mg_mqtt_opts *opts);
Publish a message to a specified topic, each contained in a struct msg_str
Note: This function does not actually send the message, it delivers to the underlying TCP/IP stack which will be checked later when the manager runs.
Note that Mongoose does not handle retries for QoS 1 and 2. That has to be handled by the application in the event handler, if needed. You can check if a publish request with QoS 1 or 2 succeeded by catching MG_EV_MQTT_CMD events and checking for reception of PUBACK/PUBREC and PUBCOMP messsages; and their result codes inside a struct mg_mqtt_message
Parameters:
c- Connection to useopts- pointer to publish MQTT options, like QoS, and retain flag. The message body is expected atopts->message, the topic atopts->topic; both as mg_str
Return value: When using QoS other than 0, this function returns the id field sent to the broker, suitable to be held in opts->retransmit_id for a possible retransmission. See this tutorial. Discard the returned value if not interested in doing retransmissions, and initialize opts->retransmit_id as 0.
Usage example:
struct mg_mqtt_opts pub_opts = {.topic = mg_str("mytopic"),
.message = mg_str("hello"),
.qos = 1,
.retain = false};
mg_mqtt_pub(c, &pub_opts);
mg_mqtt_sub()
void mg_mqtt_sub(struct mg_connection *c, const struct mg_mqtt_opts *opts);
Subscribe to a topic specified as a struct msg_str. You can check if a subscription request succeeded by catching MG_EV_MQTT_CMD events and checking for reception of a PUBACK messsage and its result code inside the struct mg_mqtt_message
Reception of a message will trigger an MG_EV_MQTT_MSG event providing a struct mg_mqtt_message. Note that Mongoose does not handle broker retries for QoS 2 and duplicated messages have to be handled by the application in the event handler, if required
Parameters:
c- Connection to useopts- pointer to subscription MQTT options, like QoS. The topic is expected atopts->topicas an mg_str
Return value: None
// Mongoose event handler
void fn(struct mg_connection *c, int ev, void *evd, void *fnd) {
if (ev == MG_EV_MQTT_MSG) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
MG_INFO(("%.*s\t%.*s", (int) mm->topic.len, mm->topic.buf),
(int) mm->data.len, mm->data.buf);
}
}
struct mg_mqtt_opts sub_opts = {.topic = mg_str("mytopic"),
.qos = 1};
mg_mqtt_sub(c, &sub_opts);
mg_mqtt_send_header()
void mg_mqtt_send_header(struct mg_connection *c, uint8_t cmd, uint8_t flags, uint32_t len);
Send an MQTT command header. Useful in handling QoS 2 and MQTT server implementations. The command can be one of the following:
#define MQTT_CMD_CONNECT 1
#define MQTT_CMD_CONNACK 2
#define MQTT_CMD_PUBLISH 3
#define MQTT_CMD_PUBACK 4
#define MQTT_CMD_PUBREC 5
#define MQTT_CMD_PUBREL 6
#define MQTT_CMD_PUBCOMP 7
#define MQTT_CMD_SUBSCRIBE 8
#define MQTT_CMD_SUBACK 9
#define MQTT_CMD_UNSUBSCRIBE 10
#define MQTT_CMD_UNSUBACK 11
#define MQTT_CMD_PINGREQ 12
#define MQTT_CMD_PINGRESP 13
#define MQTT_CMD_DISCONNECT 14
Parameters:
c- Connection to usecmd- Command (see above)flags- Command flags (see MQTT specs)len- Size of what follows this header
Return value: None
Usage example:
// Mongoose event handler
void fn(struct mg_connection *c, int ev, void *ev_data) {
if (ev == MG_EV_MQTT_CMD) {
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
if (mm->cmd == MQTT_CMD_CONNECT) {
uint8_t response[] = {0, 0};
mg_mqtt_send_header(c, MQTT_CMD_CONNACK, 0, sizeof(response)); // Send acknowledgement
mg_send(c, response, sizeof(response));
}
}
}
mg_mqtt_ping()
void mg_mqtt_ping(struct mg_connection *c);
Send an MQTT_CMD_PINGREQ command via mg_mqtt_send_header()
Parameters:
c- Connection to use
Return value: None
Usage example:
// Send periodic pings to all (MQTT over) WS connections
static void timer_fn(void *arg) {
struct mg_mgr *mgr = (struct mg_mgr *) arg;
for (struct mg_connection *c = mgr->conns; c != NULL; c = c->next) {
if (c->is_websocket) mg_mqtt_ping(c);
}
}
mg_mqtt_parse()
int mg_mqtt_parse(const uint8_t *buf, size_t len, struct mg_mqtt_message *m);
Parse a buffer and fill an mg_mqtt_message structure if it contains a valid MQTT packet.
Parameters:
buf- buffer with MQTT packet to parselen- buffer lengthm- pointer to a struct mg_mqtt_message to be filled with the parsed message
Return value: MQTT_OK if message is successfully parsed, MQTT_INCOMPLETE if message
isn't fully received and MQTT_MALFORMED if message has a wrong format.
Usage example:
// Iterate over all MQTT frames contained in buf, len
struct mg_mqtt_message mm;
while ((mg_mqtt_parse(buf, len, &mm)) == MQTT_OK) {
switch (mm.cmd) {
case MQTT_CMD_CONNACK:
...
}
buf += mm.dgram.len;
len -= mm.dgram.len;
}
mg_mqtt_unsub()
void mg_mqtt_unsub(struct mg_connection *c, const struct mg_mqtt_opts *opts);
Remove subscription (unsubscribe) to a topic previously subscribed to using mg_mqtt_sub().
Parameters:
c- Connection to useopts- pointer to MQTT options. The topic is expected atopts->topicas an mg_str
Return value: None
struct mg_mqtt_opts sub_opts = {.topic = mg_str("mytopic"),
.qos = 1};
mg_mqtt_sub(c, &sub_opts);
...
mg_mqtt_unsub(c, &sub_opts);
mg_mqtt_disconnect()
void mg_mqtt_disconnect(struct mg_connection *c, const struct mg_mqtt_opts *opts);
End an client MQTT connection
Note: This function does not destroy a connection; it just sends a disconnect request to the broker. Once the connection is terminated, an MG_EV_CLOSE event will be sent to the connection event handler
Parameters:
c- Connection to useopts- pointer to MQTT options, can be NULL for MQTT 3.1.1 connections
Return value: None