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