Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / lwip / repo / lwip / doc / mqtt_client.txt
1 MQTT client for lwIP
2
3 Author: Erik Andersson
4
5 Details of the MQTT protocol can be found at:
6 http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html 
7
8 -----------------------------------------------------------------
9 1. Initial steps, reserve memory and make connection to server:
10
11 1.1: Provide storage
12
13 Static allocation:
14   mqtt_client_t static_client;
15   example_do_connect(&static_client);
16
17 Dynamic allocation:
18   mqtt_client_t *client = mqtt_client_new();
19   if(client != NULL) {
20     example_do_connect(&client);
21   }
22   
23 1.2: Establish Connection with server
24
25 void example_do_connect(mqtt_client_t *client)
26 {
27   struct mqtt_connect_client_info_t ci;
28   err_t err;
29   
30   /* Setup an empty client info structure */
31   memset(&ci, 0, sizeof(ci));
32   
33   /* Minimal amount of information required is client identifier, so set it here */ 
34   ci.client_id = "lwip_test";
35   
36   /* Initiate client and connect to server, if this fails immediately an error code is returned
37      otherwise mqtt_connection_cb will be called with connection result after attempting 
38      to establish a connection with the server. 
39      For now MQTT version 3.1.1 is always used */
40   
41   err = mqtt_client_connect(client, ip_addr, MQTT_PORT, mqtt_connection_cb, 0, &ci);
42   
43   /* For now just print the result code if something goes wrong
44   if(err != ERR_OK) {
45     printf("mqtt_connect return %d\n", err);
46   }
47 }
48
49 Connection to server can also be probed by calling mqtt_client_is_connected(client) 
50
51 -----------------------------------------------------------------
52 2. Implementing the connection status callback
53
54
55 static void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
56 {
57   err_t err;
58   if(status == MQTT_CONNECT_ACCEPTED) {
59     printf("mqtt_connection_cb: Successfully connected\n");
60     
61     /* Setup callback for incoming publish requests */
62     mqtt_set_inpub_callback(client, mqtt_incoming_publish_cb, mqtt_incoming_data_cb, arg);
63     
64     /* Subscribe to a topic named "subtopic" with QoS level 1, call mqtt_sub_request_cb with result */ 
65     err = mqtt_subscribe(client, "subtopic", 1, mqtt_sub_request_cb, arg);
66
67     if(err != ERR_OK) {
68       printf("mqtt_subscribe return: %d\n", err);
69     }
70   } else {
71     printf("mqtt_connection_cb: Disconnected, reason: %d\n", status);
72     
73     /* Its more nice to be connected, so try to reconnect */
74     example_do_connect(client);
75   }  
76 }
77
78 static void mqtt_sub_request_cb(void *arg, err_t result)
79 {
80   /* Just print the result code here for simplicity, 
81      normal behaviour would be to take some action if subscribe fails like 
82      notifying user, retry subscribe or disconnect from server */
83   printf("Subscribe result: %d\n", result);
84 }
85
86 -----------------------------------------------------------------
87 3. Implementing callbacks for incoming publish and data
88
89 /* The idea is to demultiplex topic and create some reference to be used in data callbacks
90    Example here uses a global variable, better would be to use a member in arg
91    If RAM and CPU budget allows it, the easiest implementation might be to just take a copy of
92    the topic string and use it in mqtt_incoming_data_cb
93 */
94 static int inpub_id;
95 static void mqtt_incoming_publish_cb(void *arg, const char *topic, u32_t tot_len)
96 {
97   printf("Incoming publish at topic %s with total length %u\n", topic, (unsigned int)tot_len);
98
99   /* Decode topic string into a user defined reference */
100   if(strcmp(topic, "print_payload") == 0) {
101     inpub_id = 0;
102   } else if(topic[0] == 'A') {
103     /* All topics starting with 'A' might be handled at the same way */
104     inpub_id = 1;
105   } else {
106     /* For all other topics */
107     inpub_id = 2;
108   }
109 }
110
111 static void mqtt_incoming_data_cb(void *arg, const u8_t *data, u16_t len, u8_t flags)
112 {
113   printf("Incoming publish payload with length %d, flags %u\n", len, (unsigned int)flags);
114
115   if(flags & MQTT_DATA_FLAG_LAST) {
116     /* Last fragment of payload received (or whole part if payload fits receive buffer
117        See MQTT_VAR_HEADER_BUFFER_LEN)  */
118
119     /* Call function or do action depending on reference, in this case inpub_id */
120     if(inpub_id == 0) {
121       /* Don't trust the publisher, check zero termination */
122       if(data[len-1] == 0) {
123         printf("mqtt_incoming_data_cb: %s\n", (const char *)data);
124       }
125     } else if(inpub_id == 1) {
126       /* Call an 'A' function... */
127     } else {
128       printf("mqtt_incoming_data_cb: Ignoring payload...\n");
129     }
130   } else {
131     /* Handle fragmented payload, store in buffer, write to file or whatever */
132   }
133 }
134
135 -----------------------------------------------------------------
136 4. Using outgoing publish
137
138
139 void example_publish(mqtt_client_t *client, void *arg)
140 {
141   const char *pub_payload= "PubSubHubLubJub";
142   err_t err;
143   u8_t qos = 2; /* 0 1 or 2, see MQTT specification */
144   u8_t retain = 0; /* No don't retain such crappy payload... */
145   err = mqtt_publish(client, "pub_topic", pub_payload, strlen(pub_payload), qos, retain, mqtt_pub_request_cb, arg);
146   if(err != ERR_OK) {
147     printf("Publish err: %d\n", err);
148   }
149 }
150
151 /* Called when publish is complete either with sucess or failure */
152 static void mqtt_pub_request_cb(void *arg, err_t result)
153 {
154   if(result != ERR_OK) {
155     printf("Publish result: %d\n", result);
156   }
157 }
158
159 -----------------------------------------------------------------
160 5. Disconnecting
161
162 Simply call mqtt_disconnect(client)