commit | author | age
|
d6b4a7
|
1 |
/* |
G |
2 |
* coreMQTT v2.1.1 |
|
3 |
* Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
|
4 |
* |
|
5 |
* SPDX-License-Identifier: MIT |
|
6 |
* |
|
7 |
* Permission is hereby granted, free of charge, to any person obtaining a copy of |
|
8 |
* this software and associated documentation files (the "Software"), to deal in |
|
9 |
* the Software without restriction, including without limitation the rights to |
|
10 |
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of |
|
11 |
* the Software, and to permit persons to whom the Software is furnished to do so, |
|
12 |
* subject to the following conditions: |
|
13 |
* |
|
14 |
* The above copyright notice and this permission notice shall be included in all |
|
15 |
* copies or substantial portions of the Software. |
|
16 |
* |
|
17 |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
18 |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
19 |
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
20 |
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
21 |
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
22 |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
23 |
*/ |
|
24 |
|
|
25 |
/** |
|
26 |
* @file core_mqtt.h |
|
27 |
* @brief User-facing functions of the MQTT 3.1.1 library. |
|
28 |
*/ |
|
29 |
#ifndef CORE_MQTT_H |
|
30 |
#define CORE_MQTT_H |
|
31 |
|
|
32 |
/* *INDENT-OFF* */ |
|
33 |
#ifdef __cplusplus |
|
34 |
extern "C" { |
|
35 |
#endif |
|
36 |
/* *INDENT-ON* */ |
|
37 |
|
|
38 |
/* Include MQTT serializer library. */ |
|
39 |
#include "core_mqtt_serializer.h" |
|
40 |
|
|
41 |
/* Include transport interface. */ |
|
42 |
#include "transport_interface.h" |
|
43 |
|
|
44 |
/** |
|
45 |
* @cond DOXYGEN_IGNORE |
|
46 |
* The current version of this library. |
|
47 |
*/ |
|
48 |
#define MQTT_LIBRARY_VERSION "v2.1.1" |
|
49 |
/** @endcond */ |
|
50 |
|
|
51 |
/** |
|
52 |
* @ingroup mqtt_constants |
|
53 |
* @brief Invalid packet identifier. |
|
54 |
* |
|
55 |
* Zero is an invalid packet identifier as per MQTT v3.1.1 spec. |
|
56 |
*/ |
|
57 |
#define MQTT_PACKET_ID_INVALID ( ( uint16_t ) 0U ) |
|
58 |
|
|
59 |
/* Structures defined in this file. */ |
|
60 |
struct MQTTPubAckInfo; |
|
61 |
struct MQTTContext; |
|
62 |
struct MQTTDeserializedInfo; |
|
63 |
|
|
64 |
/** |
|
65 |
* @ingroup mqtt_callback_types |
|
66 |
* @brief Application provided function to query the time elapsed since a given |
|
67 |
* epoch in milliseconds. |
|
68 |
* |
|
69 |
* @note The timer should be a monotonic timer. It just needs to provide an |
|
70 |
* incrementing count of milliseconds elapsed since a given epoch. |
|
71 |
* |
|
72 |
* @return The time elapsed in milliseconds. |
|
73 |
*/ |
|
74 |
typedef uint32_t (* MQTTGetCurrentTimeFunc_t )( void ); |
|
75 |
|
|
76 |
/** |
|
77 |
* @ingroup mqtt_callback_types |
|
78 |
* @brief Application callback for receiving incoming publishes and incoming |
|
79 |
* acks. |
|
80 |
* |
|
81 |
* @note This callback will be called only if packets are deserialized with a |
|
82 |
* result of #MQTTSuccess or #MQTTServerRefused. The latter can be obtained |
|
83 |
* when deserializing a SUBACK, indicating a broker's rejection of a subscribe. |
|
84 |
* |
|
85 |
* @param[in] pContext Initialized MQTT context. |
|
86 |
* @param[in] pPacketInfo Information on the type of incoming MQTT packet. |
|
87 |
* @param[in] pDeserializedInfo Deserialized information from incoming packet. |
|
88 |
*/ |
|
89 |
typedef void (* MQTTEventCallback_t )( struct MQTTContext * pContext, |
|
90 |
struct MQTTPacketInfo * pPacketInfo, |
|
91 |
struct MQTTDeserializedInfo * pDeserializedInfo ); |
|
92 |
|
|
93 |
/** |
|
94 |
* @ingroup mqtt_enum_types |
|
95 |
* @brief Values indicating if an MQTT connection exists. |
|
96 |
*/ |
|
97 |
typedef enum MQTTConnectionStatus |
|
98 |
{ |
|
99 |
MQTTNotConnected, /**< @brief MQTT Connection is inactive. */ |
|
100 |
MQTTConnected /**< @brief MQTT Connection is active. */ |
|
101 |
} MQTTConnectionStatus_t; |
|
102 |
|
|
103 |
/** |
|
104 |
* @ingroup mqtt_enum_types |
|
105 |
* @brief The state of QoS 1 or QoS 2 MQTT publishes, used in the state engine. |
|
106 |
*/ |
|
107 |
typedef enum MQTTPublishState |
|
108 |
{ |
|
109 |
MQTTStateNull = 0, /**< @brief An empty state with no corresponding PUBLISH. */ |
|
110 |
MQTTPublishSend, /**< @brief The library will send an outgoing PUBLISH packet. */ |
|
111 |
MQTTPubAckSend, /**< @brief The library will send a PUBACK for a received PUBLISH. */ |
|
112 |
MQTTPubRecSend, /**< @brief The library will send a PUBREC for a received PUBLISH. */ |
|
113 |
MQTTPubRelSend, /**< @brief The library will send a PUBREL for a received PUBREC. */ |
|
114 |
MQTTPubCompSend, /**< @brief The library will send a PUBCOMP for a received PUBREL. */ |
|
115 |
MQTTPubAckPending, /**< @brief The library is awaiting a PUBACK for an outgoing PUBLISH. */ |
|
116 |
MQTTPubRecPending, /**< @brief The library is awaiting a PUBREC for an outgoing PUBLISH. */ |
|
117 |
MQTTPubRelPending, /**< @brief The library is awaiting a PUBREL for an incoming PUBLISH. */ |
|
118 |
MQTTPubCompPending, /**< @brief The library is awaiting a PUBCOMP for an outgoing PUBLISH. */ |
|
119 |
MQTTPublishDone /**< @brief The PUBLISH has been completed. */ |
|
120 |
} MQTTPublishState_t; |
|
121 |
|
|
122 |
/** |
|
123 |
* @ingroup mqtt_enum_types |
|
124 |
* @brief Packet types used in acknowledging QoS 1 or QoS 2 publishes. |
|
125 |
*/ |
|
126 |
typedef enum MQTTPubAckType |
|
127 |
{ |
|
128 |
MQTTPuback, /**< @brief PUBACKs are sent in response to a QoS 1 PUBLISH. */ |
|
129 |
MQTTPubrec, /**< @brief PUBRECs are sent in response to a QoS 2 PUBLISH. */ |
|
130 |
MQTTPubrel, /**< @brief PUBRELs are sent in response to a PUBREC. */ |
|
131 |
MQTTPubcomp /**< @brief PUBCOMPs are sent in response to a PUBREL. */ |
|
132 |
} MQTTPubAckType_t; |
|
133 |
|
|
134 |
/** |
|
135 |
* @ingroup mqtt_enum_types |
|
136 |
* @brief The status codes in the SUBACK response to a subscription request. |
|
137 |
*/ |
|
138 |
typedef enum MQTTSubAckStatus |
|
139 |
{ |
|
140 |
MQTTSubAckSuccessQos0 = 0x00, /**< @brief Success with a maximum delivery at QoS 0. */ |
|
141 |
MQTTSubAckSuccessQos1 = 0x01, /**< @brief Success with a maximum delivery at QoS 1. */ |
|
142 |
MQTTSubAckSuccessQos2 = 0x02, /**< @brief Success with a maximum delivery at QoS 2. */ |
|
143 |
MQTTSubAckFailure = 0x80 /**< @brief Failure. */ |
|
144 |
} MQTTSubAckStatus_t; |
|
145 |
|
|
146 |
/** |
|
147 |
* @ingroup mqtt_struct_types |
|
148 |
* @brief An element of the state engine records for QoS 1 or Qos 2 publishes. |
|
149 |
*/ |
|
150 |
typedef struct MQTTPubAckInfo |
|
151 |
{ |
|
152 |
uint16_t packetId; /**< @brief The packet ID of the original PUBLISH. */ |
|
153 |
MQTTQoS_t qos; /**< @brief The QoS of the original PUBLISH. */ |
|
154 |
MQTTPublishState_t publishState; /**< @brief The current state of the publish process. */ |
|
155 |
} MQTTPubAckInfo_t; |
|
156 |
|
|
157 |
/** |
|
158 |
* @ingroup mqtt_struct_types |
|
159 |
* @brief A struct representing an MQTT connection. |
|
160 |
*/ |
|
161 |
typedef struct MQTTContext |
|
162 |
{ |
|
163 |
/** |
|
164 |
* @brief State engine records for outgoing publishes. |
|
165 |
*/ |
|
166 |
MQTTPubAckInfo_t * outgoingPublishRecords; |
|
167 |
|
|
168 |
/** |
|
169 |
* @brief State engine records for incoming publishes. |
|
170 |
*/ |
|
171 |
MQTTPubAckInfo_t * incomingPublishRecords; |
|
172 |
|
|
173 |
/** |
|
174 |
* @brief The maximum number of outgoing publish records. |
|
175 |
*/ |
|
176 |
size_t outgoingPublishRecordMaxCount; |
|
177 |
|
|
178 |
/** |
|
179 |
* @brief The maximum number of incoming publish records. |
|
180 |
*/ |
|
181 |
size_t incomingPublishRecordMaxCount; |
|
182 |
|
|
183 |
/** |
|
184 |
* @brief The transport interface used by the MQTT connection. |
|
185 |
*/ |
|
186 |
TransportInterface_t transportInterface; |
|
187 |
|
|
188 |
/** |
|
189 |
* @brief The buffer used in sending and receiving packets from the network. |
|
190 |
*/ |
|
191 |
MQTTFixedBuffer_t networkBuffer; |
|
192 |
|
|
193 |
/** |
|
194 |
* @brief The next available ID for outgoing MQTT packets. |
|
195 |
*/ |
|
196 |
uint16_t nextPacketId; |
|
197 |
|
|
198 |
/** |
|
199 |
* @brief Whether the context currently has a connection to the broker. |
|
200 |
*/ |
|
201 |
MQTTConnectionStatus_t connectStatus; |
|
202 |
|
|
203 |
/** |
|
204 |
* @brief Function used to get millisecond timestamps. |
|
205 |
*/ |
|
206 |
MQTTGetCurrentTimeFunc_t getTime; |
|
207 |
|
|
208 |
/** |
|
209 |
* @brief Callback function used to give deserialized MQTT packets to the application. |
|
210 |
*/ |
|
211 |
MQTTEventCallback_t appCallback; |
|
212 |
|
|
213 |
/** |
|
214 |
* @brief Timestamp of the last packet sent by the library. |
|
215 |
*/ |
|
216 |
uint32_t lastPacketTxTime; |
|
217 |
|
|
218 |
/** |
|
219 |
* @brief Timestamp of the last packet received by the library. |
|
220 |
*/ |
|
221 |
uint32_t lastPacketRxTime; |
|
222 |
|
|
223 |
/** |
|
224 |
* @brief Whether the library sent a packet during a call of #MQTT_ProcessLoop or |
|
225 |
* #MQTT_ReceiveLoop. |
|
226 |
*/ |
|
227 |
bool controlPacketSent; |
|
228 |
|
|
229 |
/** |
|
230 |
* @brief Index to keep track of the number of bytes received in network buffer. |
|
231 |
*/ |
|
232 |
size_t index; |
|
233 |
|
|
234 |
/* Keep alive members. */ |
|
235 |
uint16_t keepAliveIntervalSec; /**< @brief Keep Alive interval. */ |
|
236 |
uint32_t pingReqSendTimeMs; /**< @brief Timestamp of the last sent PINGREQ. */ |
|
237 |
bool waitingForPingResp; /**< @brief If the library is currently awaiting a PINGRESP. */ |
|
238 |
} MQTTContext_t; |
|
239 |
|
|
240 |
/** |
|
241 |
* @ingroup mqtt_struct_types |
|
242 |
* @brief Struct to hold deserialized packet information for an #MQTTEventCallback_t |
|
243 |
* callback. |
|
244 |
*/ |
|
245 |
typedef struct MQTTDeserializedInfo |
|
246 |
{ |
|
247 |
uint16_t packetIdentifier; /**< @brief Packet ID of deserialized packet. */ |
|
248 |
MQTTPublishInfo_t * pPublishInfo; /**< @brief Pointer to deserialized publish info. */ |
|
249 |
MQTTStatus_t deserializationResult; /**< @brief Return code of deserialization. */ |
|
250 |
} MQTTDeserializedInfo_t; |
|
251 |
|
|
252 |
/** |
|
253 |
* @brief Initialize an MQTT context. |
|
254 |
* |
|
255 |
* This function must be called on an #MQTTContext_t before any other function. |
|
256 |
* |
|
257 |
* @note The #MQTTGetCurrentTimeFunc_t function for querying time must be defined. If |
|
258 |
* there is no time implementation, it is the responsibility of the application |
|
259 |
* to provide a dummy function to always return 0, provide 0 timeouts for |
|
260 |
* all calls to #MQTT_Connect, #MQTT_ProcessLoop, and #MQTT_ReceiveLoop and configure |
|
261 |
* the #MQTT_RECV_POLLING_TIMEOUT_MS and #MQTT_SEND_TIMEOUT_MS configurations |
|
262 |
* to be 0. This will result in loop functions running for a single iteration, and |
|
263 |
* #MQTT_Connect relying on #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT to receive the CONNACK packet. |
|
264 |
* |
|
265 |
* @param[in] pContext The context to initialize. |
|
266 |
* @param[in] pTransportInterface The transport interface to use with the context. |
|
267 |
* @param[in] getTimeFunction The time utility function which can return the amount of time |
|
268 |
* (in milliseconds) elapsed since a given epoch. This function will be used to ensure that |
|
269 |
* timeouts in the API calls are met and keep-alive messages are sent on time. |
|
270 |
* @param[in] userCallback The user callback to use with the context to notify about incoming |
|
271 |
* packet events. |
|
272 |
* @param[in] pNetworkBuffer Network buffer provided for the context. This buffer will be used |
|
273 |
* to receive incoming messages from the broker. This buffer must remain valid and in scope |
|
274 |
* for the entire lifetime of the @p pContext and must not be used by another context and/or |
|
275 |
* application. |
|
276 |
* |
|
277 |
* @return #MQTTBadParameter if invalid parameters are passed; |
|
278 |
* #MQTTSuccess otherwise. |
|
279 |
* |
|
280 |
* <b>Example</b> |
|
281 |
* @code{c} |
|
282 |
* |
|
283 |
* // Function for obtaining a timestamp. |
|
284 |
* uint32_t getTimeStampMs(); |
|
285 |
* // Callback function for receiving packets. |
|
286 |
* void eventCallback( |
|
287 |
* MQTTContext_t * pContext, |
|
288 |
* MQTTPacketInfo_t * pPacketInfo, |
|
289 |
* MQTTDeserializedInfo_t * pDeserializedInfo |
|
290 |
* ); |
|
291 |
* // Network send. |
|
292 |
* int32_t networkSend( NetworkContext_t * pContext, const void * pBuffer, size_t bytes ); |
|
293 |
* // Network receive. |
|
294 |
* int32_t networkRecv( NetworkContext_t * pContext, void * pBuffer, size_t bytes ); |
|
295 |
* |
|
296 |
* MQTTContext_t mqttContext; |
|
297 |
* TransportInterface_t transport; |
|
298 |
* MQTTFixedBuffer_t fixedBuffer; |
|
299 |
* // Create a globally accessible buffer which remains in scope for the entire duration |
|
300 |
* // of the MQTT context. |
|
301 |
* uint8_t buffer[ 1024 ]; |
|
302 |
* |
|
303 |
* // Clear context. |
|
304 |
* memset( ( void * ) &mqttContext, 0x00, sizeof( MQTTContext_t ) ); |
|
305 |
* |
|
306 |
* // Set transport interface members. |
|
307 |
* transport.pNetworkContext = &someTransportContext; |
|
308 |
* transport.send = networkSend; |
|
309 |
* transport.recv = networkRecv; |
|
310 |
* |
|
311 |
* // Set buffer members. |
|
312 |
* fixedBuffer.pBuffer = buffer; |
|
313 |
* fixedBuffer.size = 1024; |
|
314 |
* |
|
315 |
* status = MQTT_Init( &mqttContext, &transport, getTimeStampMs, eventCallback, &fixedBuffer ); |
|
316 |
* |
|
317 |
* if( status == MQTTSuccess ) |
|
318 |
* { |
|
319 |
* // Do something with mqttContext. The transport and fixedBuffer structs were |
|
320 |
* // copied into the context, so the original structs do not need to stay in scope. |
|
321 |
* // However, the memory pointed to by the fixedBuffer.pBuffer must remain in scope. |
|
322 |
* } |
|
323 |
* @endcode |
|
324 |
*/ |
|
325 |
/* @[declare_mqtt_init] */ |
|
326 |
MQTTStatus_t MQTT_Init( MQTTContext_t * pContext, |
|
327 |
const TransportInterface_t * pTransportInterface, |
|
328 |
MQTTGetCurrentTimeFunc_t getTimeFunction, |
|
329 |
MQTTEventCallback_t userCallback, |
|
330 |
const MQTTFixedBuffer_t * pNetworkBuffer ); |
|
331 |
/* @[declare_mqtt_init] */ |
|
332 |
|
|
333 |
/** |
|
334 |
* @brief Initialize an MQTT context for QoS > 0. |
|
335 |
* |
|
336 |
* This function must be called on an #MQTTContext_t after MQTT_Init and before any other function. |
|
337 |
* |
|
338 |
* @param[in] pContext The context to initialize. |
|
339 |
* @param[in] pOutgoingPublishRecords Pointer to memory which will be used to store state of outgoing |
|
340 |
* publishes. |
|
341 |
* @param[in] outgoingPublishCount Maximum number of records which can be kept in the memory |
|
342 |
* pointed to by @p pOutgoingPublishRecords. |
|
343 |
* @param[in] pIncomingPublishRecords Pointer to memory which will be used to store state of incoming |
|
344 |
* publishes. |
|
345 |
* @param[in] incomingPublishCount Maximum number of records which can be kept in the memory |
|
346 |
* pointed to by @p pIncomingPublishRecords. |
|
347 |
* |
|
348 |
* @return #MQTTBadParameter if invalid parameters are passed; |
|
349 |
* #MQTTSuccess otherwise. |
|
350 |
* |
|
351 |
* <b>Example</b> |
|
352 |
* @code{c} |
|
353 |
* |
|
354 |
* // Function for obtaining a timestamp. |
|
355 |
* uint32_t getTimeStampMs(); |
|
356 |
* // Callback function for receiving packets. |
|
357 |
* void eventCallback( |
|
358 |
* MQTTContext_t * pContext, |
|
359 |
* MQTTPacketInfo_t * pPacketInfo, |
|
360 |
* MQTTDeserializedInfo_t * pDeserializedInfo |
|
361 |
* ); |
|
362 |
* // Network send. |
|
363 |
* int32_t networkSend( NetworkContext_t * pContext, const void * pBuffer, size_t bytes ); |
|
364 |
* // Network receive. |
|
365 |
* int32_t networkRecv( NetworkContext_t * pContext, void * pBuffer, size_t bytes ); |
|
366 |
* |
|
367 |
* MQTTContext_t mqttContext; |
|
368 |
* TransportInterface_t transport; |
|
369 |
* MQTTFixedBuffer_t fixedBuffer; |
|
370 |
* uint8_t buffer[ 1024 ]; |
|
371 |
* const size_t outgoingPublishCount = 30; |
|
372 |
* MQTTPubAckInfo_t outgoingPublishes[ outgoingPublishCount ]; |
|
373 |
* |
|
374 |
* // Clear context. |
|
375 |
* memset( ( void * ) &mqttContext, 0x00, sizeof( MQTTContext_t ) ); |
|
376 |
* |
|
377 |
* // Set transport interface members. |
|
378 |
* transport.pNetworkContext = &someTransportContext; |
|
379 |
* transport.send = networkSend; |
|
380 |
* transport.recv = networkRecv; |
|
381 |
* |
|
382 |
* // Set buffer members. |
|
383 |
* fixedBuffer.pBuffer = buffer; |
|
384 |
* fixedBuffer.size = 1024; |
|
385 |
* |
|
386 |
* status = MQTT_Init( &mqttContext, &transport, getTimeStampMs, eventCallback, &fixedBuffer ); |
|
387 |
* |
|
388 |
* if( status == MQTTSuccess ) |
|
389 |
* { |
|
390 |
* // We do not expect any incoming publishes in this example, therefore the incoming |
|
391 |
* // publish pointer is NULL and the count is zero. |
|
392 |
* status = MQTT_InitStatefulQoS( &mqttContext, outgoingPublishes, outgoingPublishCount, NULL, 0 ); |
|
393 |
* |
|
394 |
* // Now QoS1 and/or QoS2 publishes can be sent with this context. |
|
395 |
* } |
|
396 |
* @endcode |
|
397 |
*/ |
|
398 |
/* @[declare_mqtt_initstatefulqos] */ |
|
399 |
MQTTStatus_t MQTT_InitStatefulQoS( MQTTContext_t * pContext, |
|
400 |
MQTTPubAckInfo_t * pOutgoingPublishRecords, |
|
401 |
size_t outgoingPublishCount, |
|
402 |
MQTTPubAckInfo_t * pIncomingPublishRecords, |
|
403 |
size_t incomingPublishCount ); |
|
404 |
/* @[declare_mqtt_initstatefulqos] */ |
|
405 |
|
|
406 |
/** |
|
407 |
* @brief Establish an MQTT session. |
|
408 |
* |
|
409 |
* This function will send MQTT CONNECT packet and receive a CONNACK packet. The |
|
410 |
* send and receive from the network is done through the transport interface. |
|
411 |
* |
|
412 |
* The maximum time this function waits for a CONNACK is decided in one of the |
|
413 |
* following ways: |
|
414 |
* 1. If @p timeoutMs is greater than 0: |
|
415 |
* #MQTTContext_t.getTime is used to ensure that the function does not wait |
|
416 |
* more than @p timeoutMs for CONNACK. |
|
417 |
* 2. If @p timeoutMs is 0: |
|
418 |
* The network receive for CONNACK is retried up to the number of times |
|
419 |
* configured by #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT. |
|
420 |
* |
|
421 |
* @note If a dummy #MQTTGetCurrentTimeFunc_t was passed to #MQTT_Init, then a |
|
422 |
* timeout value of 0 MUST be passed to the API, and the #MQTT_RECV_POLLING_TIMEOUT_MS |
|
423 |
* and #MQTT_SEND_TIMEOUT_MS timeout configurations MUST be set to 0. |
|
424 |
* |
|
425 |
* @param[in] pContext Initialized MQTT context. |
|
426 |
* @param[in] pConnectInfo MQTT CONNECT packet information. |
|
427 |
* @param[in] pWillInfo Last Will and Testament. Pass NULL if Last Will and |
|
428 |
* Testament is not used. |
|
429 |
* @param[in] timeoutMs Maximum time in milliseconds to wait for a CONNACK packet. |
|
430 |
* A zero timeout makes use of the retries for receiving CONNACK as configured with |
|
431 |
* #MQTT_MAX_CONNACK_RECEIVE_RETRY_COUNT. |
|
432 |
* @param[out] pSessionPresent This value will be set to true if a previous session |
|
433 |
* was present; otherwise it will be set to false. It is only relevant if not |
|
434 |
* establishing a clean session. |
|
435 |
* |
|
436 |
* @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to |
|
437 |
* hold the MQTT packet; |
|
438 |
* #MQTTBadParameter if invalid parameters are passed; |
|
439 |
* #MQTTSendFailed if transport send failed; |
|
440 |
* #MQTTRecvFailed if transport receive failed for CONNACK; |
|
441 |
* #MQTTNoDataAvailable if no data available to receive in transport until |
|
442 |
* the @p timeoutMs for CONNACK; |
|
443 |
* #MQTTSuccess otherwise. |
|
444 |
* |
|
445 |
* @note This API may spend more time than provided in the timeoutMS parameters in |
|
446 |
* certain conditions as listed below: |
|
447 |
* |
|
448 |
* 1. Timeouts are incorrectly configured - If the timeoutMS is less than the |
|
449 |
* transport receive timeout and if a CONNACK packet is not received within |
|
450 |
* the transport receive timeout, the API will spend the transport receive |
|
451 |
* timeout (which is more time than the timeoutMs). It is the case of incorrect |
|
452 |
* timeout configuration as the timeoutMs parameter passed to this API must be |
|
453 |
* greater than the transport receive timeout. Please refer to the transport |
|
454 |
* interface documentation for more details about timeout configurations. |
|
455 |
* |
|
456 |
* 2. Partial CONNACK packet is received right before the expiry of the timeout - It |
|
457 |
* is possible that first two bytes of CONNACK packet (packet type and remaining |
|
458 |
* length) are received right before the expiry of the timeoutMS. In that case, |
|
459 |
* the API makes one more network receive call in an attempt to receive the remaining |
|
460 |
* 2 bytes. In the worst case, it can happen that the remaining 2 bytes are never |
|
461 |
* received and this API will end up spending timeoutMs + transport receive timeout. |
|
462 |
* |
|
463 |
* <b>Example</b> |
|
464 |
* @code{c} |
|
465 |
* |
|
466 |
* // Variables used in this example. |
|
467 |
* MQTTStatus_t status; |
|
468 |
* MQTTConnectInfo_t connectInfo = { 0 }; |
|
469 |
* MQTTPublishInfo_t willInfo = { 0 }; |
|
470 |
* bool sessionPresent; |
|
471 |
* // This is assumed to have been initialized before calling this function. |
|
472 |
* MQTTContext_t * pContext; |
|
473 |
* |
|
474 |
* // True for creating a new session with broker, false if we want to resume an old one. |
|
475 |
* connectInfo.cleanSession = true; |
|
476 |
* // Client ID must be unique to broker. This field is required. |
|
477 |
* connectInfo.pClientIdentifier = "someClientID"; |
|
478 |
* connectInfo.clientIdentifierLength = strlen( connectInfo.pClientIdentifier ); |
|
479 |
* |
|
480 |
* // The following fields are optional. |
|
481 |
* // Value for keep alive. |
|
482 |
* connectInfo.keepAliveSeconds = 60; |
|
483 |
* // Optional username and password. |
|
484 |
* connectInfo.pUserName = "someUserName"; |
|
485 |
* connectInfo.userNameLength = strlen( connectInfo.pUserName ); |
|
486 |
* connectInfo.pPassword = "somePassword"; |
|
487 |
* connectInfo.passwordLength = strlen( connectInfo.pPassword ); |
|
488 |
* |
|
489 |
* // The last will and testament is optional, it will be published by the broker |
|
490 |
* // should this client disconnect without sending a DISCONNECT packet. |
|
491 |
* willInfo.qos = MQTTQoS0; |
|
492 |
* willInfo.pTopicName = "/lwt/topic/name"; |
|
493 |
* willInfo.topicNameLength = strlen( willInfo.pTopicName ); |
|
494 |
* willInfo.pPayload = "LWT Message"; |
|
495 |
* willInfo.payloadLength = strlen( "LWT Message" ); |
|
496 |
* |
|
497 |
* // Send the connect packet. Use 100 ms as the timeout to wait for the CONNACK packet. |
|
498 |
* status = MQTT_Connect( pContext, &connectInfo, &willInfo, 100, &sessionPresent ); |
|
499 |
* |
|
500 |
* if( status == MQTTSuccess ) |
|
501 |
* { |
|
502 |
* // Since we requested a clean session, this must be false |
|
503 |
* assert( sessionPresent == false ); |
|
504 |
* |
|
505 |
* // Do something with the connection. |
|
506 |
* } |
|
507 |
* @endcode |
|
508 |
*/ |
|
509 |
/* @[declare_mqtt_connect] */ |
|
510 |
MQTTStatus_t MQTT_Connect( MQTTContext_t * pContext, |
|
511 |
const MQTTConnectInfo_t * pConnectInfo, |
|
512 |
const MQTTPublishInfo_t * pWillInfo, |
|
513 |
uint32_t timeoutMs, |
|
514 |
bool * pSessionPresent ); |
|
515 |
/* @[declare_mqtt_connect] */ |
|
516 |
|
|
517 |
/** |
|
518 |
* @brief Sends MQTT SUBSCRIBE for the given list of topic filters to |
|
519 |
* the broker. |
|
520 |
* |
|
521 |
* @param[in] pContext Initialized MQTT context. |
|
522 |
* @param[in] pSubscriptionList Array of MQTT subscription info. |
|
523 |
* @param[in] subscriptionCount The number of elements in @ pSubscriptionList |
|
524 |
* array. |
|
525 |
* @param[in] packetId Packet ID generated by #MQTT_GetPacketId. |
|
526 |
* |
|
527 |
* @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to |
|
528 |
* hold the MQTT packet; |
|
529 |
* #MQTTBadParameter if invalid parameters are passed; |
|
530 |
* #MQTTSendFailed if transport write failed; |
|
531 |
* #MQTTSuccess otherwise. |
|
532 |
* |
|
533 |
* <b>Example</b> |
|
534 |
* @code{c} |
|
535 |
* |
|
536 |
* // Variables used in this example. |
|
537 |
* MQTTStatus_t status; |
|
538 |
* MQTTSubscribeInfo_t subscriptionList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 }; |
|
539 |
* uint16_t packetId; |
|
540 |
* // This context is assumed to be initialized and connected. |
|
541 |
* MQTTContext_t * pContext; |
|
542 |
* // This is assumed to be a list of filters we want to subscribe to. |
|
543 |
* const char * filters[ NUMBER_OF_SUBSCRIPTIONS ]; |
|
544 |
* |
|
545 |
* // Set each subscription. |
|
546 |
* for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) |
|
547 |
* { |
|
548 |
* subscriptionList[ i ].qos = MQTTQoS0; |
|
549 |
* // Each subscription needs a topic filter. |
|
550 |
* subscriptionList[ i ].pTopicFilter = filters[ i ]; |
|
551 |
* subscriptionList[ i ].topicFilterLength = strlen( filters[ i ] ); |
|
552 |
* } |
|
553 |
* |
|
554 |
* // Obtain a new packet id for the subscription. |
|
555 |
* packetId = MQTT_GetPacketId( pContext ); |
|
556 |
* |
|
557 |
* status = MQTT_Subscribe( pContext, &subscriptionList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, packetId ); |
|
558 |
* |
|
559 |
* if( status == MQTTSuccess ) |
|
560 |
* { |
|
561 |
* // We must now call MQTT_ReceiveLoop() or MQTT_ProcessLoop() to receive the SUBACK. |
|
562 |
* // If the broker accepts the subscription we can now receive publishes |
|
563 |
* // on the requested topics. |
|
564 |
* } |
|
565 |
* @endcode |
|
566 |
*/ |
|
567 |
/* @[declare_mqtt_subscribe] */ |
|
568 |
MQTTStatus_t MQTT_Subscribe( MQTTContext_t * pContext, |
|
569 |
const MQTTSubscribeInfo_t * pSubscriptionList, |
|
570 |
size_t subscriptionCount, |
|
571 |
uint16_t packetId ); |
|
572 |
/* @[declare_mqtt_subscribe] */ |
|
573 |
|
|
574 |
/** |
|
575 |
* @brief Publishes a message to the given topic name. |
|
576 |
* |
|
577 |
* @param[in] pContext Initialized MQTT context. |
|
578 |
* @param[in] pPublishInfo MQTT PUBLISH packet parameters. |
|
579 |
* @param[in] packetId packet ID generated by #MQTT_GetPacketId. |
|
580 |
* |
|
581 |
* @return #MQTTNoMemory if pBuffer is too small to hold the MQTT packet; |
|
582 |
* #MQTTBadParameter if invalid parameters are passed; |
|
583 |
* #MQTTSendFailed if transport write failed; |
|
584 |
* #MQTTSuccess otherwise. |
|
585 |
* |
|
586 |
* <b>Example</b> |
|
587 |
* @code{c} |
|
588 |
* |
|
589 |
* // Variables used in this example. |
|
590 |
* MQTTStatus_t status; |
|
591 |
* MQTTPublishInfo_t publishInfo; |
|
592 |
* uint16_t packetId; |
|
593 |
* // This context is assumed to be initialized and connected. |
|
594 |
* MQTTContext_t * pContext; |
|
595 |
* |
|
596 |
* // QoS of publish. |
|
597 |
* publishInfo.qos = MQTTQoS1; |
|
598 |
* publishInfo.pTopicName = "/some/topic/name"; |
|
599 |
* publishInfo.topicNameLength = strlen( publishInfo.pTopicName ); |
|
600 |
* publishInfo.pPayload = "Hello World!"; |
|
601 |
* publishInfo.payloadLength = strlen( "Hello World!" ); |
|
602 |
* |
|
603 |
* // Packet ID is needed for QoS > 0. |
|
604 |
* packetId = MQTT_GetPacketId( pContext ); |
|
605 |
* |
|
606 |
* status = MQTT_Publish( pContext, &publishInfo, packetId ); |
|
607 |
* |
|
608 |
* if( status == MQTTSuccess ) |
|
609 |
* { |
|
610 |
* // Since the QoS is > 0, we will need to call MQTT_ReceiveLoop() |
|
611 |
* // or MQTT_ProcessLoop() to process the publish acknowledgments. |
|
612 |
* } |
|
613 |
* @endcode |
|
614 |
*/ |
|
615 |
/* @[declare_mqtt_publish] */ |
|
616 |
MQTTStatus_t MQTT_Publish( MQTTContext_t * pContext, |
|
617 |
const MQTTPublishInfo_t * pPublishInfo, |
|
618 |
uint16_t packetId ); |
|
619 |
/* @[declare_mqtt_publish] */ |
|
620 |
|
|
621 |
/** |
|
622 |
* @brief Cancels an outgoing publish callback (only for QoS > QoS0) by |
|
623 |
* removing it from the pending ACK list. |
|
624 |
* |
|
625 |
* @note This cannot cancel the actual publish as that might have already |
|
626 |
* been sent to the broker. This only removes the details of the given packet |
|
627 |
* ID from the list of unACKed packet. That allows the caller to free any memory |
|
628 |
* associated with the publish payload, topic string etc. Also, after this API |
|
629 |
* call, the user provided callback will not be invoked when the ACK packet is |
|
630 |
* received. |
|
631 |
* |
|
632 |
* @param[in] pContext Initialized MQTT context. |
|
633 |
* @param[in] packetId packet ID corresponding to the outstanding publish. |
|
634 |
* |
|
635 |
* @return #MQTTBadParameter if invalid parameters are passed; |
|
636 |
* #MQTTSuccess otherwise. |
|
637 |
*/ |
|
638 |
/* @[declare_mqtt_cancelcallback] */ |
|
639 |
MQTTStatus_t MQTT_CancelCallback( const MQTTContext_t * pContext, |
|
640 |
uint16_t packetId ); |
|
641 |
/* @[declare_mqtt_cancelcallback] */ |
|
642 |
|
|
643 |
/** |
|
644 |
* @brief Sends an MQTT PINGREQ to broker. |
|
645 |
* |
|
646 |
* @param[in] pContext Initialized and connected MQTT context. |
|
647 |
* |
|
648 |
* @return #MQTTNoMemory if pBuffer is too small to hold the MQTT packet; |
|
649 |
* #MQTTBadParameter if invalid parameters are passed; |
|
650 |
* #MQTTSendFailed if transport write failed; |
|
651 |
* #MQTTSuccess otherwise. |
|
652 |
*/ |
|
653 |
/* @[declare_mqtt_ping] */ |
|
654 |
MQTTStatus_t MQTT_Ping( MQTTContext_t * pContext ); |
|
655 |
/* @[declare_mqtt_ping] */ |
|
656 |
|
|
657 |
/** |
|
658 |
* @brief Sends MQTT UNSUBSCRIBE for the given list of topic filters to |
|
659 |
* the broker. |
|
660 |
* |
|
661 |
* @param[in] pContext Initialized MQTT context. |
|
662 |
* @param[in] pSubscriptionList List of MQTT subscription info. |
|
663 |
* @param[in] subscriptionCount The number of elements in pSubscriptionList. |
|
664 |
* @param[in] packetId packet ID generated by #MQTT_GetPacketId. |
|
665 |
* |
|
666 |
* @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to |
|
667 |
* hold the MQTT packet; |
|
668 |
* #MQTTBadParameter if invalid parameters are passed; |
|
669 |
* #MQTTSendFailed if transport write failed; |
|
670 |
* #MQTTSuccess otherwise. |
|
671 |
* |
|
672 |
* <b>Example</b> |
|
673 |
* @code{c} |
|
674 |
* |
|
675 |
* // Variables used in this example. |
|
676 |
* MQTTStatus_t status; |
|
677 |
* MQTTSubscribeInfo_t unsubscribeList[ NUMBER_OF_SUBSCRIPTIONS ] = { 0 }; |
|
678 |
* uint16_t packetId; |
|
679 |
* // This context is assumed to be initialized and connected. |
|
680 |
* MQTTContext_t * pContext; |
|
681 |
* // This is assumed to be a list of filters we want to unsubscribe from. |
|
682 |
* const char * filters[ NUMBER_OF_SUBSCRIPTIONS ]; |
|
683 |
* |
|
684 |
* // Set information for each unsubscribe request. |
|
685 |
* for( int i = 0; i < NUMBER_OF_SUBSCRIPTIONS; i++ ) |
|
686 |
* { |
|
687 |
* unsubscribeList[ i ].pTopicFilter = filters[ i ]; |
|
688 |
* unsubscribeList[ i ].topicFilterLength = strlen( filters[ i ] ); |
|
689 |
* |
|
690 |
* // The QoS field of MQTT_SubscribeInfo_t is unused for unsubscribing. |
|
691 |
* } |
|
692 |
* |
|
693 |
* // Obtain a new packet id for the unsubscribe request. |
|
694 |
* packetId = MQTT_GetPacketId( pContext ); |
|
695 |
* |
|
696 |
* status = MQTT_Unsubscribe( pContext, &unsubscribeList[ 0 ], NUMBER_OF_SUBSCRIPTIONS, packetId ); |
|
697 |
* |
|
698 |
* if( status == MQTTSuccess ) |
|
699 |
* { |
|
700 |
* // We must now call MQTT_ReceiveLoop() or MQTT_ProcessLoop() to receive the UNSUBACK. |
|
701 |
* // After this the broker should no longer send publishes for these topics. |
|
702 |
* } |
|
703 |
* @endcode |
|
704 |
*/ |
|
705 |
/* @[declare_mqtt_unsubscribe] */ |
|
706 |
MQTTStatus_t MQTT_Unsubscribe( MQTTContext_t * pContext, |
|
707 |
const MQTTSubscribeInfo_t * pSubscriptionList, |
|
708 |
size_t subscriptionCount, |
|
709 |
uint16_t packetId ); |
|
710 |
/* @[declare_mqtt_unsubscribe] */ |
|
711 |
|
|
712 |
/** |
|
713 |
* @brief Disconnect an MQTT session. |
|
714 |
* |
|
715 |
* @param[in] pContext Initialized and connected MQTT context. |
|
716 |
* |
|
717 |
* @return #MQTTNoMemory if the #MQTTContext_t.networkBuffer is too small to |
|
718 |
* hold the MQTT packet; |
|
719 |
* #MQTTBadParameter if invalid parameters are passed; |
|
720 |
* #MQTTSendFailed if transport send failed; |
|
721 |
* #MQTTSuccess otherwise. |
|
722 |
*/ |
|
723 |
/* @[declare_mqtt_disconnect] */ |
|
724 |
MQTTStatus_t MQTT_Disconnect( MQTTContext_t * pContext ); |
|
725 |
/* @[declare_mqtt_disconnect] */ |
|
726 |
|
|
727 |
/** |
|
728 |
* @brief Loop to receive packets from the transport interface. Handles keep |
|
729 |
* alive. |
|
730 |
* |
|
731 |
* @note If a dummy timer function, #MQTTGetCurrentTimeFunc_t, is passed to the library, |
|
732 |
* then the keep-alive mechanism is not supported by the #MQTT_ProcessLoop API. |
|
733 |
* In that case, the #MQTT_ReceiveLoop API function should be used instead. |
|
734 |
* |
|
735 |
* @param[in] pContext Initialized and connected MQTT context. |
|
736 |
* |
|
737 |
* @note Calling this function blocks the calling context for a time period that |
|
738 |
* depends on the passed the configuration macros, #MQTT_RECV_POLLING_TIMEOUT_MS |
|
739 |
* and #MQTT_SEND_TIMEOUT_MS, and the underlying transport interface implementation |
|
740 |
* timeouts, unless an error occurs. The blocking period also depends on the execution time of the |
|
741 |
* #MQTTEventCallback_t callback supplied to the library. It is recommended that the supplied |
|
742 |
* #MQTTEventCallback_t callback does not contain blocking operations to prevent potential |
|
743 |
* non-deterministic blocking period of the #MQTT_ProcessLoop API call. |
|
744 |
* |
|
745 |
* @return #MQTTBadParameter if context is NULL; |
|
746 |
* #MQTTRecvFailed if a network error occurs during reception; |
|
747 |
* #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ; |
|
748 |
* #MQTTBadResponse if an invalid packet is received; |
|
749 |
* #MQTTKeepAliveTimeout if the server has not sent a PINGRESP before |
|
750 |
* #MQTT_PINGRESP_TIMEOUT_MS milliseconds; |
|
751 |
* #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an |
|
752 |
* invalid transition for the internal state machine; |
|
753 |
* #MQTTNeedMoreBytes if MQTT_ProcessLoop has received |
|
754 |
* incomplete data; it should be called again (probably after a delay); |
|
755 |
* #MQTTSuccess on success. |
|
756 |
* |
|
757 |
* <b>Example</b> |
|
758 |
* @code{c} |
|
759 |
* |
|
760 |
* // Variables used in this example. |
|
761 |
* MQTTStatus_t status; |
|
762 |
* // This context is assumed to be initialized and connected. |
|
763 |
* MQTTContext_t * pContext; |
|
764 |
* |
|
765 |
* while( true ) |
|
766 |
* { |
|
767 |
* status = MQTT_ProcessLoop( pContext ); |
|
768 |
* |
|
769 |
* if( status != MQTTSuccess && status != MQTTNeedMoreBytes ) |
|
770 |
* { |
|
771 |
* // Determine the error. It's possible we might need to disconnect |
|
772 |
* // the underlying transport connection. |
|
773 |
* } |
|
774 |
* else |
|
775 |
* { |
|
776 |
* // Other application functions. |
|
777 |
* } |
|
778 |
* } |
|
779 |
* @endcode |
|
780 |
*/ |
|
781 |
/* @[declare_mqtt_processloop] */ |
|
782 |
MQTTStatus_t MQTT_ProcessLoop( MQTTContext_t * pContext ); |
|
783 |
/* @[declare_mqtt_processloop] */ |
|
784 |
|
|
785 |
/** |
|
786 |
* @brief Loop to receive packets from the transport interface. Does not handle |
|
787 |
* keep alive. |
|
788 |
* |
|
789 |
* @note If a dummy #MQTTGetCurrentTimeFunc_t was passed to #MQTT_Init, then the |
|
790 |
* #MQTT_RECV_POLLING_TIMEOUT_MS and #MQTT_SEND_TIMEOUT_MS timeout configurations |
|
791 |
* MUST be set to 0. |
|
792 |
* |
|
793 |
* @param[in] pContext Initialized and connected MQTT context. |
|
794 |
* |
|
795 |
* @note Calling this function blocks the calling context for a time period that |
|
796 |
* depends on the the configuration macros, #MQTT_RECV_POLLING_TIMEOUT_MS and |
|
797 |
* #MQTT_SEND_TIMEOUT_MS, and the underlying transport interface implementation |
|
798 |
* timeouts, unless an error occurs. The blocking period also depends on the execution time of the |
|
799 |
* #MQTTEventCallback_t callback supplied to the library. It is recommended that the supplied |
|
800 |
* #MQTTEventCallback_t callback does not contain blocking operations to prevent potential |
|
801 |
* non-deterministic blocking period of the #MQTT_ReceiveLoop API call. |
|
802 |
* |
|
803 |
* @return #MQTTBadParameter if context is NULL; |
|
804 |
* #MQTTRecvFailed if a network error occurs during reception; |
|
805 |
* #MQTTSendFailed if a network error occurs while sending an ACK or PINGREQ; |
|
806 |
* #MQTTBadResponse if an invalid packet is received; |
|
807 |
* #MQTTIllegalState if an incoming QoS 1/2 publish or ack causes an |
|
808 |
* invalid transition for the internal state machine; |
|
809 |
* #MQTTNeedMoreBytes if MQTT_ReceiveLoop has received |
|
810 |
* incomplete data; it should be called again (probably after a delay); |
|
811 |
* #MQTTSuccess on success. |
|
812 |
* |
|
813 |
* <b>Example</b> |
|
814 |
* @code{c} |
|
815 |
* |
|
816 |
* // Variables used in this example. |
|
817 |
* MQTTStatus_t status; |
|
818 |
* uint32_t keepAliveMs = 60 * 1000; |
|
819 |
* // This context is assumed to be initialized and connected. |
|
820 |
* MQTTContext_t * pContext; |
|
821 |
* |
|
822 |
* while( true ) |
|
823 |
* { |
|
824 |
* status = MQTT_ReceiveLoop( pContext ); |
|
825 |
* |
|
826 |
* if( status != MQTTSuccess && status != MQTTNeedMoreBytes ) |
|
827 |
* { |
|
828 |
* // Determine the error. It's possible we might need to disconnect |
|
829 |
* // the underlying transport connection. |
|
830 |
* } |
|
831 |
* else |
|
832 |
* { |
|
833 |
* // Since this function does not send pings, the application may need |
|
834 |
* // to in order to comply with keep alive. |
|
835 |
* if( ( pContext->getTime() - pContext->lastPacketTxTime ) > keepAliveMs ) |
|
836 |
* { |
|
837 |
* status = MQTT_Ping( pContext ); |
|
838 |
* } |
|
839 |
* |
|
840 |
* // Other application functions. |
|
841 |
* } |
|
842 |
* } |
|
843 |
* @endcode |
|
844 |
*/ |
|
845 |
/* @[declare_mqtt_receiveloop] */ |
|
846 |
MQTTStatus_t MQTT_ReceiveLoop( MQTTContext_t * pContext ); |
|
847 |
/* @[declare_mqtt_receiveloop] */ |
|
848 |
|
|
849 |
/** |
|
850 |
* @brief Get a packet ID that is valid according to the MQTT 3.1.1 spec. |
|
851 |
* |
|
852 |
* @param[in] pContext Initialized MQTT context. |
|
853 |
* |
|
854 |
* @return A non-zero number. |
|
855 |
*/ |
|
856 |
/* @[declare_mqtt_getpacketid] */ |
|
857 |
uint16_t MQTT_GetPacketId( MQTTContext_t * pContext ); |
|
858 |
/* @[declare_mqtt_getpacketid] */ |
|
859 |
|
|
860 |
/** |
|
861 |
* @brief A utility function that determines whether the passed topic filter and |
|
862 |
* topic name match according to the MQTT 3.1.1 protocol specification. |
|
863 |
* |
|
864 |
* @param[in] pTopicName The topic name to check. |
|
865 |
* @param[in] topicNameLength Length of the topic name. |
|
866 |
* @param[in] pTopicFilter The topic filter to check. |
|
867 |
* @param[in] topicFilterLength Length of topic filter. |
|
868 |
* @param[out] pIsMatch If the match is performed without any error, that is if the |
|
869 |
* return value is MQTTSuccess, then and only then the value in this parameter is valid |
|
870 |
* and updated. In such a case, if the topic filter and the topic name match, then this |
|
871 |
* value is set to true; otherwise if there is no match then it is set to false. |
|
872 |
* |
|
873 |
* @note The API assumes that the passed topic name is valid to meet the |
|
874 |
* requirements of the MQTT 3.1.1 specification. Invalid topic names (for example, |
|
875 |
* containing wildcard characters) should not be passed to the function. |
|
876 |
* Also, the API checks validity of topic filter for wildcard characters ONLY if |
|
877 |
* the passed topic name and topic filter do not have an exact string match. |
|
878 |
* |
|
879 |
* @return Returns one of the following: |
|
880 |
* - #MQTTBadParameter, if any of the input parameters is invalid. |
|
881 |
* - #MQTTSuccess, if the matching operation was performed. |
|
882 |
* |
|
883 |
* <b>Example</b> |
|
884 |
* @code{c} |
|
885 |
* |
|
886 |
* // Variables used in this example. |
|
887 |
* const char * pTopic = "topic/match/1"; |
|
888 |
* const char * pFilter = "topic/#"; |
|
889 |
* MQTTStatus_t status = MQTTSuccess; |
|
890 |
* bool match = false; |
|
891 |
* |
|
892 |
* status = MQTT_MatchTopic( pTopic, strlen( pTopic ), pFilter, strlen( pFilter ), &match ); |
|
893 |
* // Our parameters were valid, so this will return success. |
|
894 |
* assert( status == MQTTSuccess ); |
|
895 |
* |
|
896 |
* // For this specific example, we already know this value is true. This |
|
897 |
* // check is placed here as an example for use with variable topic names. |
|
898 |
* if( match ) |
|
899 |
* { |
|
900 |
* // Application can decide what to do with the matching topic name. |
|
901 |
* } |
|
902 |
* @endcode |
|
903 |
*/ |
|
904 |
MQTTStatus_t MQTT_MatchTopic( const char * pTopicName, |
|
905 |
const uint16_t topicNameLength, |
|
906 |
const char * pTopicFilter, |
|
907 |
const uint16_t topicFilterLength, |
|
908 |
bool * pIsMatch ); |
|
909 |
|
|
910 |
/** |
|
911 |
* @brief Parses the payload of an MQTT SUBACK packet that contains status codes |
|
912 |
* corresponding to topic filter subscription requests from the original |
|
913 |
* subscribe packet. |
|
914 |
* |
|
915 |
* Each return code in the SUBACK packet corresponds to a topic filter in the |
|
916 |
* SUBSCRIBE Packet being acknowledged. |
|
917 |
* The status codes can be one of the following: |
|
918 |
* - 0x00 - Success - Maximum QoS 0 |
|
919 |
* - 0x01 - Success - Maximum QoS 1 |
|
920 |
* - 0x02 - Success - Maximum QoS 2 |
|
921 |
* - 0x80 - Failure |
|
922 |
* Refer to #MQTTSubAckStatus_t for the status codes. |
|
923 |
* |
|
924 |
* @param[in] pSubackPacket The SUBACK packet whose payload is to be parsed. |
|
925 |
* @param[out] pPayloadStart This is populated with the starting address |
|
926 |
* of the payload (or return codes for topic filters) in the SUBACK packet. |
|
927 |
* @param[out] pPayloadSize This is populated with the size of the payload |
|
928 |
* in the SUBACK packet. It represents the number of topic filters whose |
|
929 |
* SUBACK status is present in the packet. |
|
930 |
* |
|
931 |
* @return Returns one of the following: |
|
932 |
* - #MQTTBadParameter if the input SUBACK packet is invalid. |
|
933 |
* - #MQTTSuccess if parsing the payload was successful. |
|
934 |
* |
|
935 |
* <b>Example</b> |
|
936 |
* @code{c} |
|
937 |
* |
|
938 |
* // Global variable used in this example. |
|
939 |
* // This is assumed to be the subscription list in the original SUBSCRIBE packet. |
|
940 |
* MQTTSubscribeInfo_t pSubscribes[ NUMBER_OF_SUBSCRIPTIONS ]; |
|
941 |
* |
|
942 |
* // MQTT_GetSubAckStatusCodes is intended to be used from the application |
|
943 |
* // callback that is called by the library in MQTT_ProcessLoop or MQTT_ReceiveLoop. |
|
944 |
* void eventCallback( |
|
945 |
* MQTTContext_t * pContext, |
|
946 |
* MQTTPacketInfo_t * pPacketInfo, |
|
947 |
* MQTTDeserializedInfo_t * pDeserializedInfo |
|
948 |
* ) |
|
949 |
* { |
|
950 |
* MQTTStatus_t status = MQTTSuccess; |
|
951 |
* uint8_t * pCodes; |
|
952 |
* size_t numCodes; |
|
953 |
* |
|
954 |
* if( pPacketInfo->type == MQTT_PACKET_TYPE_SUBACK ) |
|
955 |
* { |
|
956 |
* status = MQTT_GetSubAckStatusCodes( pPacketInfo, &pCodes, &numCodes ); |
|
957 |
* |
|
958 |
* // Since the pointers to the payload and payload size are not NULL, and |
|
959 |
* // we use the packet info struct passed to the app callback (verified |
|
960 |
* // to be valid by the library), this function must return success. |
|
961 |
* assert( status == MQTTSuccess ); |
|
962 |
* // The server must send a response code for each topic filter in the |
|
963 |
* // original SUBSCRIBE packet. |
|
964 |
* assert( numCodes == NUMBER_OF_SUBSCRIPTIONS ); |
|
965 |
* |
|
966 |
* for( int i = 0; i < numCodes; i++ ) |
|
967 |
* { |
|
968 |
* // The only failure code is 0x80 = MQTTSubAckFailure. |
|
969 |
* if( pCodes[ i ] == MQTTSubAckFailure ) |
|
970 |
* { |
|
971 |
* // The subscription failed, we may want to retry the |
|
972 |
* // subscription in pSubscribes[ i ] outside of this callback. |
|
973 |
* } |
|
974 |
* else |
|
975 |
* { |
|
976 |
* // The subscription was granted, but the maximum QoS may be |
|
977 |
* // lower than what was requested. We can verify the granted QoS. |
|
978 |
* if( pSubscribes[ i ].qos != pCodes[ i ] ) |
|
979 |
* { |
|
980 |
* LogWarn( ( |
|
981 |
* "Requested QoS %u, but granted QoS %u for %s", |
|
982 |
* pSubscribes[ i ].qos, pCodes[ i ], pSubscribes[ i ].pTopicFilter |
|
983 |
* ) ); |
|
984 |
* } |
|
985 |
* } |
|
986 |
* } |
|
987 |
* } |
|
988 |
* // Handle other packet types. |
|
989 |
* } |
|
990 |
* @endcode |
|
991 |
*/ |
|
992 |
/* @[declare_mqtt_getsubackstatuscodes] */ |
|
993 |
MQTTStatus_t MQTT_GetSubAckStatusCodes( const MQTTPacketInfo_t * pSubackPacket, |
|
994 |
uint8_t ** pPayloadStart, |
|
995 |
size_t * pPayloadSize ); |
|
996 |
/* @[declare_mqtt_getsubackstatuscodes] */ |
|
997 |
|
|
998 |
/** |
|
999 |
* @brief Error code to string conversion for MQTT statuses. |
|
1000 |
* |
|
1001 |
* @param[in] status The status to convert to a string. |
|
1002 |
* |
|
1003 |
* @return The string representation of the status. |
|
1004 |
*/ |
|
1005 |
/* @[declare_mqtt_status_strerror] */ |
|
1006 |
const char * MQTT_Status_strerror( MQTTStatus_t status ); |
|
1007 |
/* @[declare_mqtt_status_strerror] */ |
|
1008 |
|
|
1009 |
/* *INDENT-OFF* */ |
|
1010 |
#ifdef __cplusplus |
|
1011 |
} |
|
1012 |
#endif |
|
1013 |
/* *INDENT-ON* */ |
|
1014 |
|
|
1015 |
#endif /* ifndef CORE_MQTT_H */ |