mqtt_sn_client.c
Go to the documentation of this file.
1 /**
2  * @file mqtt_sn_client.c
3  * @brief MQTT-SN client
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneTCP Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @author Oryx Embedded SARL (www.oryx-embedded.com)
26  * @version 1.9.0
27  **/
28 
29 //Switch to the appropriate trace level
30 #define TRACE_LEVEL MQTT_SN_TRACE_LEVEL
31 
32 //Dependencies
33 #include "core/net.h"
34 #include "mqtt_sn/mqtt_sn_client.h"
38 #include "debug.h"
39 
40 //Check TCP/IP stack configuration
41 #if (MQTT_SN_CLIENT_SUPPORT == ENABLED)
42 
43 
44 /**
45  * @brief Initialize MQTT-SN client context
46  * @param[in] context Pointer to the MQTT-SN client context
47  * @return Error code
48  **/
49 
51 {
52 #if (MQTT_SN_CLIENT_DTLS_SUPPORT == ENABLED)
53  error_t error;
54 #endif
55 
56  //Make sure the MQTT-SN client context is valid
57  if(context == NULL)
59 
60  //Clear MQTT-SN client context
61  memset(context, 0, sizeof(MqttSnClientContext));
62 
63 #if (MQTT_SN_CLIENT_DTLS_SUPPORT == ENABLED)
64  //Initialize DTLS session state
65  error = tlsInitSessionState(&context->dtlsSession);
66  //Any error to report?
67  if(error)
68  return error;
69 #endif
70 
71  //Initialize MQTT-SN client state
72  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
73 
74  //Default transport protocol
75  context->transportProtocol = MQTT_SN_TRANSPORT_PROTOCOL_UDP;
76  //Default timeout
77  context->timeout = MQTT_SN_CLIENT_DEFAULT_TIMEOUT;
78  //Default keep-alive time interval
79  context->keepAlive = MQTT_SN_CLIENT_DEFAULT_KEEP_ALIVE;
80 
81  //Initialize message identifier
82  context->msgId = 0;
83 
84  //Successful initialization
85  return NO_ERROR;
86 }
87 
88 
89 /**
90  * @brief Set the transport protocol to be used
91  * @param[in] context Pointer to the MQTT-SN client context
92  * @param[in] transportProtocol Transport protocol to be used (UDP or DTLS)
93  * @return Error code
94  **/
95 
97  MqttSnTransportProtocol transportProtocol)
98 {
99  //Make sure the MQTT-SN client context is valid
100  if(context == NULL)
102 
103  //Save the transport protocol to be used
104  context->transportProtocol = transportProtocol;
105 
106  //Successful processing
107  return NO_ERROR;
108 }
109 
110 
111 #if (MQTT_SN_CLIENT_DTLS_SUPPORT == ENABLED)
112 
113 /**
114  * @brief Register DTLS initialization callback function
115  * @param[in] context Pointer to the MQTT-SN client context
116  * @param[in] callback DTLS initialization callback function
117  * @return Error code
118  **/
119 
122 {
123  //Check parameters
124  if(context == NULL || callback == NULL)
126 
127  //Save callback function
128  context->dtlsInitCallback = callback;
129 
130  //Successful processing
131  return NO_ERROR;
132 }
133 
134 #endif
135 
136 
137 /**
138  * @brief Register publish callback function
139  * @param[in] context Pointer to the MQTT-SN client context
140  * @param[in] callback Callback function to be called when a PUBLISH message
141  * is received
142  * @return Error code
143  **/
144 
147 {
148  //Make sure the MQTT-SN client context is valid
149  if(context == NULL)
151 
152  //Save callback function
153  context->publishCallback = callback;
154 
155  //Successful processing
156  return NO_ERROR;
157 }
158 
159 
160 /**
161  * @brief Set the list of predefined topics
162  * @param[in] context Pointer to the MQTT-SN client context
163  * @param[in] predefinedTopics List of predefined topics
164  * @param[in] size Number of predefined topics
165  * @return Error code
166  **/
167 
169  MqttSnPredefinedTopic *predefinedTopics, uint_t size)
170 {
171  //Make sure the MQTT-SN client context is valid
172  if(context == NULL)
174 
175  //Check parameters
176  if(predefinedTopics == NULL && size != 0)
178 
179  //Save the list of predefined topics
180  context->predefinedTopicTable = predefinedTopics;
181  context->predefinedTopicTableSize = size;
182 
183  //Successful processing
184  return NO_ERROR;
185 }
186 
187 
188 /**
189  * @brief Set communication timeout
190  * @param[in] context Pointer to the MQTT-SN client context
191  * @param[in] timeout Timeout value, in milliseconds
192  * @return Error code
193  **/
194 
196 {
197  //Make sure the MQTT-SN client context is valid
198  if(context == NULL)
200 
201  //Save timeout value
202  context->timeout = timeout;
203 
204  //Successful processing
205  return NO_ERROR;
206 }
207 
208 
209 /**
210  * @brief Set keep-alive value
211  * @param[in] context Pointer to the MQTT-SN client context
212  * @param[in] keepAlive Keep-alive interval, in milliseconds
213  * @return Error code
214  **/
215 
217 {
218  //Make sure the MQTT-SN client context is valid
219  if(context == NULL)
221 
222  //Save keep-alive value
223  context->keepAlive = keepAlive;
224 
225  //Successful processing
226  return NO_ERROR;
227 }
228 
229 
230 /**
231  * @brief Set client identifier
232  * @param[in] context Pointer to the MQTT-SN client context
233  * @param[in] clientId NULL-terminated string containing the client identifier
234  * @return Error code
235  **/
236 
238  const char_t *clientId)
239 {
240  //Check parameters
241  if(context == NULL || clientId == NULL)
243 
244  //Make sure the length of the client identifier is acceptable
245  if(strlen(clientId) > MQTT_SN_CLIENT_MAX_ID_LEN)
246  return ERROR_INVALID_LENGTH;
247 
248  //Save client identifier
249  strcpy(context->clientId, clientId);
250 
251  //Successful processing
252  return NO_ERROR;
253 }
254 
255 
256 /**
257  * @brief Specify the Will message
258  * @param[in] context Pointer to the MQTT-SN client context
259  * @param[in] topic Will topic name
260  * @param[in] message Will message
261  * @param[in] length Length of the Will message
262  * @param[in] qos QoS level to be used when publishing the Will message
263  * @param[in] retain This flag specifies if the Will message is to be retained
264  * @return Error code
265  **/
266 
268  const char_t *topic, const void *message, size_t length,
270 {
271  //Check parameters
272  if(context == NULL || topic == NULL)
274 
275  //Make sure the length of the Will topic is acceptable
276  if(strlen(topic) > MQTT_SN_CLIENT_MAX_WILL_TOPIC_LEN)
277  return ERROR_INVALID_LENGTH;
278 
279  //Save Will topic
280  strcpy(context->willMessage.topic, topic);
281 
282  //Any message payload
283  if(length > 0)
284  {
285  //Sanity check
286  if(message == NULL)
288 
289  //Make sure the length of the Will message payload is acceptable
291  return ERROR_INVALID_LENGTH;
292 
293  //Save Will message payload
294  memcpy(context->willMessage.payload, message, length);
295  }
296 
297  //Length of the Will message payload
298  context->willMessage.length = length;
299 
300  //QoS level to be used when publishing the Will message
301  context->willMessage.flags.qos = qos;
302  //This flag specifies if the Will message is to be retained
303  context->willMessage.flags.retain = retain;
304 
305  //Successful processing
306  return NO_ERROR;
307 }
308 
309 
310 /**
311  * @brief Bind the MQTT-SN client to a particular network interface
312  * @param[in] context Pointer to the MQTT-SN client context
313  * @param[in] interface Network interface to be used
314  * @return Error code
315  **/
316 
318  NetInterface *interface)
319 {
320  //Make sure the MQTT-SN client context is valid
321  if(context == NULL)
323 
324  //Explicitly associate the MQTT client with the specified interface
325  context->interface = interface;
326 
327  //Successful processing
328  return NO_ERROR;
329 }
330 
331 
332 /**
333  * @brief Specify the address of the gateway
334  * @param[in] context Pointer to the MQTT-SN client context
335  * @param[in] gwIpAddr Gateway IP address
336  * @param[in] gwPort Gateway port number
337  * @return Error code
338  **/
339 
341  const IpAddr *gwIpAddr, uint16_t gwPort)
342 {
343  //Check parameters
344  if(context == NULL || gwIpAddr == NULL)
346 
347  //Save the IP address and the port number of the MQTT-SN gateway
348  context->gwIpAddr = *gwIpAddr;
349  context->gwPort = gwPort;
350 
351  //Successful processing
352  return NO_ERROR;
353 }
354 
355 
356 /**
357  * @brief Search for a gateway
358  * @param[in] context Pointer to the MQTT-SN client context
359  * @param[in] destIpAddr Destination IP address
360  * @param[in] destPort Destination port number
361  * @return Error code
362  **/
363 
365  const IpAddr *destIpAddr, uint16_t destPort)
366 {
367  error_t error;
368  systime_t time;
369 
370  //Check parameters
371  if(context == NULL || destIpAddr == NULL)
373 
374  //Initialize status code
375  error = NO_ERROR;
376 
377  //Gateway discovery procedure
378  while(!error)
379  {
380  //Get current time
381  time = osGetSystemTime();
382 
383  //Check current state
384  if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
385  {
386  //Open network connection
387  error = mqttSnClientOpenConnection(context, FALSE);
388 
389  //Check status code
390  if(!error)
391  {
392  //Save current time
393  context->startTime = time;
394  context->retransmitStartTime = time;
395 
396  //To prevent broadcast storms when multiple clients start searching
397  //for GW almost at the same time, the sending of the SEARCHGW message
398  //is delayed by a random time between 0 and TSEARCHGW
399  context->retransmitTimeout = netGetRandRange(0,
401 
402  //Start searching for gateways
403  context->state = MQTT_SN_CLIENT_STATE_SEARCHING;
404  }
405  }
406  else if(context->state == MQTT_SN_CLIENT_STATE_SEARCHING)
407  {
408  //Check whether the timeout has elapsed
409  if(timeCompare(time, context->startTime + context->timeout) >= 0)
410  {
411  //Abort the retransmission procedure
412  error = ERROR_TIMEOUT;
413  }
414  else if(timeCompare(time, context->retransmitStartTime +
415  context->retransmitTimeout) >= 0)
416  {
417  //Set retransmission timeout
418  context->retransmitTimeout = MQTT_SN_CLIENT_RETRY_TIMEOUT;
419 
420  //If the retry timer times out and the expected gateway's reply
421  //is not received, the client retransmits the message
422  error = mqttSnClientSendSearchGw(context, 0, destIpAddr, destPort);
423  }
424  else
425  {
426  //Wait for the gateway's reply
428  }
429  }
430  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
431  {
432  //Check the type of the received message
433  if(context->msgType == MQTT_SN_MSG_TYPE_GWINFO)
434  {
435  //Close network connection
437 
438  //A MQTT-SN gateway has been found
439  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
440  break;
441  }
442  else
443  {
444  //Report an error
446  }
447  }
448  else
449  {
450  //Invalid state
451  error = ERROR_WRONG_STATE;
452  }
453  }
454 
455  //Any error to report?
456  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
457  {
458  //Clean up side effects
460  //Update MQTT-SN client state
461  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
462  }
463 
464  //Return status code
465  return error;
466 }
467 
468 
469 /**
470  * @brief Establish connection with the MQTT-SN gateway
471  * @param[in] context Pointer to the MQTT-SN client context
472  * @param[in] cleanSession If this flag is set, then the client and server
473  * must discard any previous session and start a new one
474  * @return Error code
475  **/
476 
478 {
479  error_t error;
480  systime_t time;
481 
482  //Make sure the MQTT-SN client context is valid
483  if(context == NULL)
485 
486  //Initialize status code
487  error = NO_ERROR;
488 
489  //Establish connection with the MQTT-SN gateway
490  while(!error)
491  {
492  //Get current time
493  time = osGetSystemTime();
494 
495  //Check current state
496  if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
497  {
498  //Open network connection
499  error = mqttSnClientOpenConnection(context, TRUE);
500 
501  //Check status code
502  if(!error)
503  {
504  //Save current time
505  context->startTime = time;
506  //Update MQTT-SN client state
507  context->state = MQTT_SN_CLIENT_STATE_CONNECTING;
508  }
509  }
510  else if(context->state == MQTT_SN_CLIENT_STATE_CONNECTING)
511  {
512  //Establish DTLS connection
513  error = mqttSnClientEstablishConnection(context);
514 
515  //Check status code
516  if(error == NO_ERROR)
517  {
518  //Check whether the CleanSession flag is set
519  if(cleanSession)
520  {
521  //Discard previous session state
522  memset(context->topicTable, 0, sizeof(context->topicTable));
523  memset(context->msgIdTable, 0, sizeof(context->msgIdTable));
524  }
525 
526  //The CONNECT message is sent by a client to setup a connection
527  error = mqttSnClientSendConnect(context, cleanSession);
528  }
529  else if(error == ERROR_WOULD_BLOCK || error == ERROR_TIMEOUT)
530  {
531  //Check whether the timeout has elapsed
532  if(timeCompare(time, context->startTime + context->timeout) >= 0)
533  {
534  //Report an error
535  error = ERROR_TIMEOUT;
536  }
537  }
538  else
539  {
540  //Failed to establish DTLS connection
541  }
542  }
543  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
544  {
545  //Check whether the timeout has elapsed
546  if(timeCompare(time, context->startTime + context->timeout) >= 0)
547  {
548  //Abort the retransmission procedure
549  error = ERROR_TIMEOUT;
550  }
551  else if(timeCompare(time, context->retransmitStartTime +
553  {
554  //If the retry timer times out and the expected gateway's reply
555  //is not received, the client retransmits the message
556  error = mqttSnClientSendConnect(context, cleanSession);
557  }
558  else
559  {
560  //Wait for the gateway's reply
562  }
563  }
564  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
565  {
566  //Check the type of the received message
567  if(context->msgType == MQTT_SN_MSG_TYPE_CONNACK)
568  {
569  //If the connection request has not been accepted, the failure reason
570  //is encoded in the return code field of the CONNACK message
571  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
572  {
573  //The connection request has been accepted by the gateway
574  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
575  }
576  else
577  {
578  //Terminate DTLS connection
580 
581  //The connection request has been rejected by the gateway
582  error = ERROR_REQUEST_REJECTED;
583  }
584  }
585  else
586  {
587  //Report an error
589  }
590  }
591  else if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
592  {
593  //The MQTT-SN client is connected
594  break;
595  }
596  else
597  {
598  //Invalid state
599  error = ERROR_WRONG_STATE;
600  }
601  }
602 
603  //Any error to report?
604  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
605  {
606  //Clean up side effects
608  //Update MQTT-SN client state
609  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
610  }
611 
612  //Return status code
613  return error;
614 }
615 
616 
617 /**
618  * @brief Publish message
619  * @param[in] context Pointer to the MQTT-SN client context
620  * @param[in] topicName Topic name
621  * @param[in] message Message payload
622  * @param[in] length Length of the message payload
623  * @param[in] qos QoS level to be used when publishing the message
624  * @param[in] retain This flag specifies if the message is to be retained
625  * @param[in] dup This flag specifies if the message is sent for the first
626  * time or if the message is retransmitted
627  * @param[in,out] msgId Message identifier used to send the PUBLISH message
628  * @return Error code
629  **/
630 
632  const char_t *topicName, const void *message, size_t length,
634 {
635  error_t error;
636  systime_t time;
637  uint16_t publishMsgId;
638 
639  //Check parameters
640  if(context == NULL || topicName == NULL)
642  if(message == NULL && length != 0)
644  if(dup && msgId == NULL)
646 
647  //Initialize status code
648  error = NO_ERROR;
649 
650  //Initialize message identifier
651  if(dup)
652  publishMsgId = *msgId;
653  else
654  publishMsgId = 0;
655 
656  //Publish procedure
657  while(!error)
658  {
659  //Get current time
660  time = osGetSystemTime();
661 
662  //Check current state
663  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
664  {
665  //Save current time
666  context->startTime = time;
667 
668  //Check whether the register procedure is needed
670  mqttSnClientFindTopicName(context, topicName) == 0 &&
672  {
673  //The message identifier allows the sender to match a message with
674  //its corresponding acknowledgment
676 
677  //To register a topic name a client sends a REGISTER message to
678  //the gateway
679  error = mqttSnClientSendRegister(context, topicName);
680  }
681  else
682  {
683  //The message ID is only relevant in case of QoS levels 1 and 2
685  {
686  //The message identifier allows the sender to match a message with
687  //its corresponding acknowledgment
688  if(!dup)
689  publishMsgId = mqttSnClientGenerateMessageId(context);
690  }
691  else
692  {
693  //For QoS level 0, the message identifier is coded 0x0000
694  publishMsgId = 0;
695  }
696 
697  //The client can start publishing data relating to the registered
698  //topic name by sending PUBLISH messages to the gateway
699  error = mqttSnClientSendPublish(context, publishMsgId, topicName,
700  message, length, qos, retain, dup);
701 
702  //In the QoS 0, no response is sent by the receiver and no retry
703  //is performed by the sender
705  break;
706  }
707  }
708  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
709  {
710  //Check whether the transmission of the PUBLISH message has started
711  if(context->msgType == MQTT_SN_MSG_TYPE_PUBLISH ||
712  context->msgType == MQTT_SN_MSG_TYPE_PUBREL)
713  {
714  //Restore the message identifier that was used to send the first
715  //PUBLISH message
716  if(!dup)
717  publishMsgId = context->msgId;
718  }
719 
720  //Check whether the timeout has elapsed
721  if(timeCompare(time, context->startTime + context->timeout) >= 0)
722  {
723  //Abort the retransmission procedure
724  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
725  //Report a timeout error
726  error = ERROR_TIMEOUT;
727  }
728  else if(timeCompare(time, context->retransmitStartTime +
730  {
731  //If the retry timer times out and the expected gateway's reply
732  //is not received, the client retransmits the message
733  if(context->msgType == MQTT_SN_MSG_TYPE_REGISTER)
734  {
735  //Retransmit REGISTER message
736  error = mqttSnClientSendRegister(context, topicName);
737  }
738  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBLISH)
739  {
740  //Retransmit PUBLISH message
741  error = mqttSnClientSendPublish(context, publishMsgId,
743  }
744  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBREL)
745  {
746  //Retransmit PUBREL message
747  error = mqttSnClientSendPubRel(context, context->msgId);
748  }
749  else
750  {
751  //Report an error
752  error = ERROR_INVALID_TYPE;
753  }
754  }
755  else
756  {
757  //Wait for the gateway's reply
759  }
760  }
761  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
762  {
763  //Update MQTT-SN client state
764  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
765 
766  //Check whether the transmission of the PUBLISH message has started
767  if(context->msgType == MQTT_SN_MSG_TYPE_PUBACK ||
768  context->msgType == MQTT_SN_MSG_TYPE_PUBREC ||
769  context->msgType == MQTT_SN_MSG_TYPE_PUBCOMP)
770  {
771  //Restore the message identifier that was used to send the first
772  //PUBLISH message
773  if(!dup)
774  publishMsgId = context->msgId;
775  }
776 
777  //Check the type of the received message
778  if(context->msgType == MQTT_SN_MSG_TYPE_REGACK)
779  {
780  //If the registration has not been accepted, the failure reason is
781  //encoded in the return code field of the REGACK message
782  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
783  {
784  //Save the topic ID assigned by the gateway
785  error = mqttSnClientAddTopic(context, topicName, context->topicId);
786  }
787  else
788  {
789  //The registration request has been rejected by the gateway
790  error = ERROR_REQUEST_REJECTED;
791  }
792  }
793  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBACK)
794  {
795  //If the publish request has not been accepted, the failure reason
796  //is encoded in the return code field of the PUBACK message
797  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
798  {
799  //Check QoS level
800  if(qos == MQTT_SN_QOS_LEVEL_2)
801  {
802  //Unexpected PUBREC message received
803  error = ERROR_UNEXPECTED_MESSAGE;
804  }
805  else
806  {
807  //A PUBACK message has been received
808  break;
809  }
810  }
811  else
812  {
813  //The publish request has been rejected by the gateway
814  error = ERROR_REQUEST_REJECTED;
815  }
816  }
817  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBREC)
818  {
819  //Check QoS level
820  if(qos == MQTT_SN_QOS_LEVEL_2)
821  {
822  //A PUBREL packet is the response to a PUBREC packet. It is the
823  //third packet of the QoS 2 protocol exchange
824  error = mqttSnClientSendPubRel(context, context->msgId);
825  }
826  else
827  {
828  //Unexpected PUBREC message received
829  error = ERROR_UNEXPECTED_MESSAGE;
830  }
831  }
832  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBCOMP)
833  {
834  //A PUBCOMP message has been received
835  break;
836  }
837  else
838  {
839  //Report an error
841  }
842  }
843  else
844  {
845  //Invalid state
846  error = ERROR_NOT_CONNECTED;
847  }
848  }
849 
850  //Return the message identifier that was used to send the PUBLISH message
851  if(msgId != NULL)
852  *msgId = publishMsgId;
853 
854  //Return status code
855  return error;
856 }
857 
858 
859 /**
860  * @brief Subscribe to topic
861  * @param[in] context Pointer to the MQTT-SN client context
862  * @param[in] topicName Topic filter
863  * @param[in] qos Maximum QoS level at which the server can send application
864  * messages to the client
865  * @return Error code
866  **/
867 
870 {
871  error_t error;
872  systime_t time;
873 
874  //Check parameters
875  if(context == NULL || topicName == NULL)
877 
878  //Initialize status code
879  error = NO_ERROR;
880 
881  //Topic subscribe procedure
882  while(!error)
883  {
884  //Get current time
885  time = osGetSystemTime();
886 
887  //Check current state
888  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
889  {
890  //The message identifier allows the sender to match a message with
891  //its corresponding acknowledgment
893 
894  //Save current time
895  context->startTime = time;
896 
897  //Send SUBSCRIBE message
898  error = mqttSnClientSendSubscribe(context, topicName, qos);
899  }
900  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
901  {
902  //Check whether the timeout has elapsed
903  if(timeCompare(time, context->startTime + context->timeout) >= 0)
904  {
905  //Abort the retransmission procedure
906  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
907  //Report a timeout error
908  error = ERROR_TIMEOUT;
909  }
910  else if(timeCompare(time, context->retransmitStartTime +
912  {
913  //If the retry timer times out and the expected gateway's reply
914  //is not received, the client retransmits the message
915  error = mqttSnClientSendSubscribe(context, topicName, qos);
916  }
917  else
918  {
919  //Wait for the gateway's reply
921  }
922  }
923  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
924  {
925  //Update MQTT-SN client state
926  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
927 
928  //Check the type of the received message
929  if(context->msgType == MQTT_SN_MSG_TYPE_SUBACK)
930  {
931  //If the subscribe request has not been accepted, the failure reason
932  //is encoded in the return code field of the SUBACK message
933  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
934  {
935  //The topic ID field is not relevant in case of subscriptions to a
936  //topic name which contains wildcard characters
937  if(strchr(topicName, '#') == NULL && strchr(topicName, '+') == NULL)
938  {
939  //Save the topic ID assigned by the gateway
940  error = mqttSnClientAddTopic(context, topicName, context->topicId);
941  }
942 
943  //A SUBACK message has been received
944  break;
945  }
946  else
947  {
948  //The subscribe request has been rejected by the gateway
949  error = ERROR_REQUEST_REJECTED;
950  }
951  }
952  else
953  {
954  //Report an error
956  }
957  }
958  else
959  {
960  //Invalid state
961  error = ERROR_NOT_CONNECTED;
962  }
963  }
964 
965  //Return status code
966  return error;
967 }
968 
969 
970 /**
971  * @brief Unsubscribe from topic
972  * @param[in] context Pointer to the MQTT-SN client context
973  * @param[in] topicName Topic filter
974  * @return Error code
975  **/
976 
978  const char_t *topicName)
979 {
980  error_t error;
981  systime_t time;
982 
983  //Check parameters
984  if(context == NULL || topicName == NULL)
986 
987  //Initialize status code
988  error = NO_ERROR;
989 
990  //Topic unsubscribe procedure
991  while(!error)
992  {
993  //Get current time
994  time = osGetSystemTime();
995 
996  //Check current state
997  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
998  {
999  //The message identifier allows the sender to match a message with
1000  //its corresponding acknowledgment
1002 
1003  //Save current time
1004  context->startTime = time;
1005 
1006  //Send UNSUBSCRIBE message
1007  error = mqttSnClientSendUnsubscribe(context, topicName);
1008  }
1009  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1010  {
1011  //Check whether the timeout has elapsed
1012  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1013  {
1014  //Abort the retransmission procedure
1015  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1016  //Report a timeout error
1017  error = ERROR_TIMEOUT;
1018  }
1019  else if(timeCompare(time, context->retransmitStartTime +
1021  {
1022  //If the retry timer times out and the expected gateway's reply
1023  //is not received, the client retransmits the message
1024  error = mqttSnClientSendUnsubscribe(context, topicName);
1025  }
1026  else
1027  {
1028  //Wait for the gateway's reply
1030  }
1031  }
1032  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1033  {
1034  //Update MQTT-SN client state
1035  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1036 
1037  //Check the type of the received message
1038  if(context->msgType == MQTT_SN_MSG_TYPE_UNSUBACK)
1039  {
1040  //An UNSUBACK message has been received
1041  break;
1042  }
1043  else
1044  {
1045  //Report an error
1046  error = ERROR_UNEXPECTED_RESPONSE;
1047  }
1048  }
1049  else
1050  {
1051  //Invalid state
1052  error = ERROR_NOT_CONNECTED;
1053  }
1054  }
1055 
1056  //Return status code
1057  return error;
1058 }
1059 
1060 
1061 /**
1062  * @brief Send ping request
1063  * @param[in] context Pointer to the MQTT-SN client context
1064  * @return Error code
1065  **/
1066 
1068 {
1069  error_t error;
1070  systime_t time;
1071 
1072  //Make sure the MQTT-SN client context is valid
1073  if(context == NULL)
1074  return ERROR_INVALID_PARAMETER;
1075 
1076  //Initialize status code
1077  error = NO_ERROR;
1078 
1079  //Send PINGREQ packet and wait for PINGRESP packet to be received
1080  while(!error)
1081  {
1082  //Get current time
1083  time = osGetSystemTime();
1084 
1085  //Check current state
1086  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1087  {
1088  //Save current time
1089  context->startTime = time;
1090  context->retransmitStartTime = time;
1091 
1092  //Send PINGREQ message
1093  error = mqttSnClientSendPingReq(context);
1094 
1095  //Update MQTT-SN client state
1096  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1097  context->msgType = MQTT_SN_MSG_TYPE_PINGREQ;
1098  }
1099  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1100  {
1101  //Check whether the timeout has elapsed
1102  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1103  {
1104  //Abort the retransmission procedure
1105  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1106  //Report a timeout error
1107  error = ERROR_TIMEOUT;
1108  }
1109  else if(timeCompare(time, context->retransmitStartTime +
1111  {
1112  //If the retry timer times out and the expected gateway's reply
1113  //is not received, the client retransmits the message
1114  error = mqttSnClientSendPingReq(context);
1115 
1116  //Save the time at which the message was sent
1117  context->retransmitStartTime = time;
1118  }
1119  else
1120  {
1121  //Wait for the gateway's reply
1123  }
1124  }
1125  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1126  {
1127  //Update MQTT-SN client state
1128  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1129 
1130  //Check the type of the received message
1131  if(context->msgType == MQTT_SN_MSG_TYPE_PINGRESP)
1132  {
1133  //A PINGRESP message has been received
1134  break;
1135  }
1136  else
1137  {
1138  //Report an error
1139  error = ERROR_UNEXPECTED_RESPONSE;
1140  }
1141  }
1142  else
1143  {
1144  //Invalid state
1145  error = ERROR_NOT_CONNECTED;
1146  }
1147  }
1148 
1149  //Return status code
1150  return error;
1151 }
1152 
1153 
1154 /**
1155  * @brief Update the Will message
1156  * @param[in] context Pointer to the MQTT-SN client context
1157  * @param[in] topic Will topic name
1158  * @param[in] message Will message
1159  * @param[in] length Length of the Will message
1160  * @param[in] qos QoS level to be used when publishing the Will message
1161  * @param[in] retain This flag specifies if the Will message is to be retained
1162  * @return Error code
1163  **/
1164 
1166  const char_t *topic, const void *message, size_t length,
1168 {
1169  error_t error;
1170  systime_t time;
1171 
1172  //Check parameters
1173  if(context == NULL || topic == NULL)
1174  return ERROR_INVALID_PARAMETER;
1175  if(message == NULL && length != 0)
1176  return ERROR_INVALID_PARAMETER;
1177 
1178  //Initialize status code
1179  error = NO_ERROR;
1180 
1181  //Publish procedure
1182  while(!error)
1183  {
1184  //Get current time
1185  time = osGetSystemTime();
1186 
1187  //Check current state
1188  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1189  {
1190  //Update the Will message
1191  error = mqttSnClientSetWillMessage(context, topic, message, length,
1192  qos, retain);
1193 
1194  //Check status code
1195  if(!error)
1196  {
1197  //Save current time
1198  context->startTime = time;
1199 
1200  //Send WILLTOPICUPD message
1201  error = mqttSnClientSendWillTopicUpd(context);
1202  }
1203  }
1204  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1205  {
1206  //Check whether the timeout has elapsed
1207  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1208  {
1209  //Abort the retransmission procedure
1210  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1211  //Report a timeout error
1212  error = ERROR_TIMEOUT;
1213  }
1214  else if(timeCompare(time, context->retransmitStartTime +
1216  {
1217  //If the retry timer times out and the expected gateway's reply
1218  //is not received, the client retransmits the message
1219  if(context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICUPD)
1220  {
1221  //Retransmit WILLTOPICUPD message
1222  error = mqttSnClientSendWillTopicUpd(context);
1223  }
1224  else if(context->msgType == MQTT_SN_MSG_TYPE_WILLMSGUPD)
1225  {
1226  //Retransmit WILLMSGUPD message
1227  error = mqttSnClientSendWillMsgUpd(context);
1228  }
1229  else
1230  {
1231  //Report an error
1232  error = ERROR_INVALID_TYPE;
1233  }
1234  }
1235  else
1236  {
1237  //Wait for the gateway's reply
1239  }
1240  }
1241  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1242  {
1243  //Update MQTT-SN client state
1244  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1245 
1246  //Check the type of the received message
1247  if(context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICRESP)
1248  {
1249  //If the WILLTOPICUPD has not been accepted, the failure reason
1250  //is encoded in the return code field of the WILLTOPICRESP
1251  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
1252  {
1253  //Valid Will topic?
1254  if(context->willMessage.topic[0] != '\0')
1255  {
1256  //Send WILLMSGUPD message
1257  error = mqttSnClientSendWillMsgUpd(context);
1258  }
1259  else
1260  {
1261  //An empty WILLTOPIC message is used by a client to delete
1262  //the Will topic and the Will message stored in the server
1263  break;
1264  }
1265  }
1266  else
1267  {
1268  //The WILLTOPICUPD request has been rejected by the gateway
1269  error = ERROR_REQUEST_REJECTED;
1270  }
1271  }
1272  else if(context->msgType == MQTT_SN_MSG_TYPE_WILLMSGRESP)
1273  {
1274  //If the WILLMSGUPD has not been accepted, the failure reason
1275  //is encoded in the return code field of the WILLMSGRESP
1276  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
1277  {
1278  //The WILLMSGUPD request has been accepted by the gateway
1279  break;
1280  }
1281  else
1282  {
1283  //The WILLMSGUPD request has been rejected by the gateway
1284  error = ERROR_REQUEST_REJECTED;
1285  }
1286  }
1287  else
1288  {
1289  //Report an error
1290  error = ERROR_UNEXPECTED_RESPONSE;
1291  }
1292  }
1293  else
1294  {
1295  //Invalid state
1296  error = ERROR_NOT_CONNECTED;
1297  }
1298  }
1299 
1300  //Return status code
1301  return error;
1302 }
1303 
1304 
1305 /**
1306  * @brief Retrieve return code
1307  * @param[in] context Pointer to the MQTT-SN client context
1308  * @param[out] returnCode Return code
1309  * @return Error code
1310  **/
1311 
1314 {
1315  //Check parameters
1316  if(context == NULL || returnCode == NULL)
1317  return ERROR_INVALID_PARAMETER;
1318 
1319  //Retrieve return code
1320  *returnCode = context->returnCode;
1321 
1322  //Successful processing
1323  return NO_ERROR;
1324 }
1325 
1326 
1327 /**
1328  * @brief Process MQTT-SN client events
1329  * @param[in] context Pointer to the MQTT-SN client context
1330  * @param[in] timeout Maximum time to wait before returning
1331  * @return Error code
1332  **/
1333 
1335 {
1336  error_t error;
1337 
1338  //Make sure the MQTT-SN client context is valid
1339  if(context == NULL)
1340  return ERROR_INVALID_PARAMETER;
1341 
1342  //Make sure the MQTT-SN client is connected
1343  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE ||
1344  context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ ||
1345  context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1346  {
1347  //Process MQTT-SN client events
1348  error = mqttSnClientProcessEvents(context, timeout);
1349  }
1350  else
1351  {
1352  //Invalid state
1353  error = ERROR_NOT_CONNECTED;
1354  }
1355 
1356  //Return status code
1357  return error;
1358 }
1359 
1360 
1361 /**
1362  * @brief Disconnect from the MQTT-SN gateway
1363  * @param[in] context Pointer to the MQTT-SN client context
1364  * @return Error code
1365  **/
1366 
1368 {
1369  error_t error;
1370  systime_t time;
1371 
1372  //Make sure the MQTT-SN client context is valid
1373  if(context == NULL)
1374  return ERROR_INVALID_PARAMETER;
1375 
1376  //Initialize status code
1377  error = NO_ERROR;
1378 
1379  //Disconnect procedure
1380  while(!error)
1381  {
1382  //Get current time
1383  time = osGetSystemTime();
1384 
1385  //Check current state
1386  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1387  {
1388  //Save current time
1389  context->startTime = time;
1390 
1391  //The DISCONNECT message is sent by a client to indicate that it
1392  //wants to close the connection
1393  error = mqttSnClientSendDisconnect(context, 0);
1394  }
1395  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1396  {
1397  //Check whether the timeout has elapsed
1398  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1399  {
1400  //Terminate DTLS connection
1402 
1403  //Report a timeout error
1404  error = ERROR_TIMEOUT;
1405  }
1406  else if(timeCompare(time, context->retransmitStartTime +
1408  {
1409  //If the retry timer times out and the expected gateway's reply
1410  //is not received, the client retransmits the message
1411  error = mqttSnClientSendDisconnect(context, 0);
1412  }
1413  else
1414  {
1415  //Wait for the gateway's reply
1417  }
1418  }
1419  else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTING)
1420  {
1421  //Terminate DTLS connection
1422  error = mqttSnClientShutdownConnection(context);
1423  //Close network connection
1424  mqttSnClientCloseConnection(context);
1425 
1426  //The connection is closed
1427  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
1428  }
1429  else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
1430  {
1431  //The MQTT-SN client is disconnected
1432  break;
1433  }
1434  else
1435  {
1436  //Invalid state
1437  error = ERROR_WRONG_STATE;
1438  }
1439  }
1440 
1441  //Any error to report?
1442  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
1443  {
1444  //Close network connection
1445  mqttSnClientCloseConnection(context);
1446  //Update MQTT-SN client state
1447  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
1448  }
1449 
1450  //Return status code
1451  return error;
1452 }
1453 
1454 
1455 /**
1456  * @brief Release MQTT-SN client context
1457  * @param[in] context Pointer to the MQTT-SN client context
1458  **/
1459 
1461 {
1462  //Make sure the MQTT-SN client context is valid
1463  if(context != NULL)
1464  {
1465  //Close connection
1466  mqttSnClientCloseConnection(context);
1467 
1468 #if (MQTT_SN_CLIENT_DTLS_SUPPORT == ENABLED)
1469  //Release DTLS session state
1470  tlsFreeSessionState(&context->dtlsSession);
1471 #endif
1472 
1473  //Clear MQTT-SN client context
1474  memset(context, 0, sizeof(MqttSnClientContext));
1475  }
1476 }
1477 
1478 #endif
uint8_t returnCode
error_t mqttSnClientTask(MqttSnClientContext *context, systime_t timeout)
Process MQTT-SN client events.
uint32_t systime_t
Definition: compiler_port.h:44
error_t mqttSnClientShutdownConnection(MqttSnClientContext *context)
Shutdown network connection.
error_t mqttSnClientBindToInterface(MqttSnClientContext *context, NetInterface *interface)
Bind the MQTT-SN client to a particular network interface.
uint16_t destPort
Definition: tcp.h:301
#define timeCompare(t1, t2)
Definition: os_port.h:40
char char_t
Definition: compiler_port.h:41
#define MQTT_SN_CLIENT_DEFAULT_KEEP_ALIVE
error_t mqttSnClientSetGateway(MqttSnClientContext *context, const IpAddr *gwIpAddr, uint16_t gwPort)
Specify the address of the gateway.
Exactly once delivery.
At least once delivery.
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t time
TCP/IP stack core.
Debugging facilities.
error_t mqttSnClientSetTimeout(MqttSnClientContext *context, systime_t timeout)
Set communication timeout.
uint8_t message[]
Definition: chap.h:150
error_t mqttSnClientRegisterDtlsInitCallback(MqttSnClientContext *context, MqttSnClientDtlsInitCallback callback)
Register DTLS initialization callback function.
Invalid parameter.
Definition: error.h:45
Transport protocol abstraction layer.
#define MQTT_SN_CLIENT_DEFAULT_TIMEOUT
#define MQTT_SN_CLIENT_TICK_INTERVAL
IP network address.
Definition: ip.h:57
error_t mqttSnClientAddTopic(MqttSnClientContext *context, const char_t *topicName, uint16_t topicId)
Add a new entry to the topic table.
error_t mqttSnClientUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Unsubscribe from topic.
#define MQTT_SN_CLIENT_RETRY_TIMEOUT
MqttSnQosLevel
Quality of service level.
MQTT-SN message parsing and formatting.
#define MQTT_SN_CLIENT_MAX_WILL_TOPIC_LEN
error_t mqttSnClientPing(MqttSnClientContext *context)
Send ping request.
error_t tlsInitSessionState(TlsSessionState *session)
Initialize session state.
Definition: tls.c:2312
error_t mqttSnClientDisconnect(MqttSnClientContext *context)
Disconnect from the MQTT-SN gateway.
uint16_t msgId
error_t mqttSnClientSendWillMsgUpd(MqttSnClientContext *context)
Send WILLMSGUPD message.
uint8_t qos
Definition: mqtt_common.h:177
#define TRUE
Definition: os_port.h:48
error_t mqttSnClientRegisterPublishCallback(MqttSnClientContext *context, MqttSnClientPublishCallback callback)
Register publish callback function.
error_t mqttSnClientSendRegister(MqttSnClientContext *context, const char_t *topicName)
Send REGISTER message.
error_t mqttSnClientSendPingReq(MqttSnClientContext *context)
Send PINGREQ message.
error_t mqttSnClientSendWillTopicUpd(MqttSnClientContext *context)
Send WILLTOPICUPD message.
#define MqttSnClientContext
uint16_t mqttSnClientFindPredefTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a predefined topic name.
error_t mqttSnClientSendDisconnect(MqttSnClientContext *context, uint16_t duration)
Send DISCONNECT message.
error_t mqttSnClientSendPublish(MqttSnClientContext *context, uint16_t msgId, const char_t *topicName, const uint8_t *data, size_t length, MqttSnQosLevel qos, bool_t retain, bool_t dup)
Send PUBLISH message.
error_t mqttSnClientUpdateWillMessage(MqttSnClientContext *context, const char_t *topic, const void *message, size_t length, MqttSnQosLevel qos, bool_t retain)
Update the Will message.
uint8_t cleanSession
error_t mqttSnClientSendConnect(MqttSnClientContext *context, bool_t cleanSession)
Send CONNECT message.
error_t mqttSnClientProcessEvents(MqttSnClientContext *context, systime_t timeout)
Process MQTT-SN client events.
void tlsFreeSessionState(TlsSessionState *session)
Properly dispose a session state.
Definition: tls.c:2594
char_t clientId[]
void(* MqttSnClientPublishCallback)(MqttSnClientContext *context, const char_t *topic, const uint8_t *message, size_t length, MqttSnQosLevel qos, bool_t retain)
PUBLISH message received callback.
void mqttSnClientCloseConnection(MqttSnClientContext *context)
Close network connection.
Predefined topic.
error_t mqttSnClientSearchGateway(MqttSnClientContext *context, const IpAddr *destIpAddr, uint16_t destPort)
Search for a gateway.
error_t(* MqttSnClientDtlsInitCallback)(MqttSnClientContext *context, TlsContext *dtlsContext)
DTLS initialization callback.
error_t mqttSnClientInit(MqttSnClientContext *context)
Initialize MQTT-SN client context.
char_t topicName[]
MqttSnTransportProtocol
MQTT-SN transport protocols.
error_t mqttSnClientSetWillMessage(MqttSnClientContext *context, const char_t *topic, const void *message, size_t length, MqttSnQosLevel qos, bool_t retain)
Specify the Will message.
#define MQTT_SN_CLIENT_MAX_WILL_PAYLOAD_LEN
error_t mqttSnClientPublish(MqttSnClientContext *context, const char_t *topicName, const void *message, size_t length, MqttSnQosLevel qos, bool_t retain, bool_t dup, uint16_t *msgId)
Publish message.
#define MQTT_SN_CLIENT_SEARCH_DELAY
error_t mqttSnClientSendUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Send UNSUBSCRIBE message.
Success.
Definition: error.h:42
error_t mqttSnClientSetPredefinedTopics(MqttSnClientContext *context, MqttSnPredefinedTopic *predefinedTopics, uint_t size)
Set the list of predefined topics.
int32_t netGetRandRange(int32_t min, int32_t max)
Get a random value in the specified range.
Definition: net.c:1554
error_t mqttSnClientGetReturnCode(MqttSnClientContext *context, MqttSnReturnCode *returnCode)
Retrieve return code.
error_t
Error codes.
Definition: error.h:40
uint8_t retain
Definition: mqtt_common.h:176
error_t mqttSnClientSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Subscribe to topic.
error_t mqttSnClientSendSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Send SUBSCRIBE message.
error_t mqttSnClientSetTransportProtocol(MqttSnClientContext *context, MqttSnTransportProtocol transportProtocol)
Set the transport protocol to be used.
Ipv4Addr destIpAddr
Definition: ipcp.h:76
error_t mqttSnClientConnect(MqttSnClientContext *context, bool_t cleanSession)
Establish connection with the MQTT-SN gateway.
unsigned int uint_t
Definition: compiler_port.h:43
uint16_t mqttSnClientFindTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a given topic name.
#define NetInterface
Definition: net.h:34
error_t mqttSnClientSetIdentifier(MqttSnClientContext *context, const char_t *clientId)
Set client identifier.
MqttSnReturnCode
MQTT-SN return codes.
error_t mqttSnClientSetKeepAlive(MqttSnClientContext *context, systime_t keepAlive)
Set keep-alive value.
#define MQTT_SN_CLIENT_MAX_ID_LEN
uint8_t dup
Definition: mqtt_common.h:178
uint16_t mqttSnClientGenerateMessageId(MqttSnClientContext *context)
Generate a new message identifier.
void mqttSnClientDeinit(MqttSnClientContext *context)
Release MQTT-SN client context.
bool_t mqttSnClientIsShortTopicName(const char_t *topicName)
Check whether a topic name is a short topic name.
MQTT-SN client.
uint8_t length
Definition: dtls_misc.h:140
Helper functions for MQTT-SN client.
error_t mqttSnClientOpenConnection(MqttSnClientContext *context, bool_t secure)
Open network connection.
error_t mqttSnClientEstablishConnection(MqttSnClientContext *context)
Establish network connection.
#define FALSE
Definition: os_port.h:44
int bool_t
Definition: compiler_port.h:47
error_t mqttSnClientSendSearchGw(MqttSnClientContext *context, uint8_t radius, const IpAddr *destIpAddr, uint16_t destPort)
Send SEARCHGW message.
error_t mqttSnClientSendPubRel(MqttSnClientContext *context, uint16_t msgId)
Send PUBREL message.