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-2024 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 2.4.0
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  osMemset(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
248  return ERROR_INVALID_LENGTH;
249 
250  //Save client identifier
251  osStrcpy(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,
271  MqttSnQosLevel qos, bool_t retain)
272 {
273  //Check parameters
274  if(context == NULL || topic == NULL)
276 
277  //Make sure the length of the Will topic is acceptable
279  return ERROR_INVALID_LENGTH;
280 
281  //Save Will topic
282  osStrcpy(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  osMemcpy(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  osMemset(context->topicTable, 0, sizeof(context->topicTable));
525  osMemset(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,
635  MqttSnQosLevel qos, bool_t retain, bool_t dup, uint16_t *msgId)
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  {
655  publishMsgId = *msgId;
656  }
657  else
658  {
659  publishMsgId = 0;
660  }
661 
662  //Publish procedure
663  while(!error)
664  {
665  //Get current time
666  time = osGetSystemTime();
667 
668  //Check current state
669  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
670  {
671  //Save current time
672  context->startTime = time;
673 
674  //Check whether the register procedure is needed
676  mqttSnClientFindTopicName(context, topicName) == 0 &&
678  {
679  //The message identifier allows the sender to match a message with
680  //its corresponding acknowledgment
682 
683  //To register a topic name a client sends a REGISTER message to
684  //the gateway
685  error = mqttSnClientSendRegister(context, topicName);
686  }
687  else
688  {
689  //The message ID is only relevant in case of QoS levels 1 and 2
691  {
692  //The message identifier allows the sender to match a message with
693  //its corresponding acknowledgment
694  if(!dup)
695  publishMsgId = mqttSnClientGenerateMessageId(context);
696  }
697  else
698  {
699  //For QoS level 0, the message identifier is coded 0x0000
700  publishMsgId = 0;
701  }
702 
703  //The client can start publishing data relating to the registered
704  //topic name by sending PUBLISH messages to the gateway
705  error = mqttSnClientSendPublish(context, publishMsgId, topicName,
706  message, length, qos, retain, dup);
707 
708  //In the QoS 0, no response is sent by the receiver and no retry
709  //is performed by the sender
711  break;
712  }
713  }
714  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
715  {
716  //Check whether the transmission of the PUBLISH message has started
717  if(context->msgType == MQTT_SN_MSG_TYPE_PUBLISH ||
718  context->msgType == MQTT_SN_MSG_TYPE_PUBREL)
719  {
720  //Restore the message identifier that was used to send the first
721  //PUBLISH message
722  if(!dup)
723  publishMsgId = context->msgId;
724  }
725 
726  //Check whether the timeout has elapsed
727  if(timeCompare(time, context->startTime + context->timeout) >= 0)
728  {
729  //Abort the retransmission procedure
730  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
731  //Report a timeout error
732  error = ERROR_TIMEOUT;
733  }
734  else if(timeCompare(time, context->retransmitStartTime +
736  {
737  //If the retry timer times out and the expected gateway's reply
738  //is not received, the client retransmits the message
739  if(context->msgType == MQTT_SN_MSG_TYPE_REGISTER)
740  {
741  //Retransmit REGISTER message
742  error = mqttSnClientSendRegister(context, topicName);
743  }
744  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBLISH)
745  {
746  //Retransmit PUBLISH message
747  error = mqttSnClientSendPublish(context, publishMsgId,
748  topicName, message, length, qos, retain, TRUE);
749  }
750  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBREL)
751  {
752  //Retransmit PUBREL message
753  error = mqttSnClientSendPubRel(context, context->msgId);
754  }
755  else
756  {
757  //Report an error
758  error = ERROR_INVALID_TYPE;
759  }
760  }
761  else
762  {
763  //Wait for the gateway's reply
765  }
766  }
767  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
768  {
769  //Update MQTT-SN client state
770  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
771 
772  //Check whether the transmission of the PUBLISH message has started
773  if(context->msgType == MQTT_SN_MSG_TYPE_PUBACK ||
774  context->msgType == MQTT_SN_MSG_TYPE_PUBREC ||
775  context->msgType == MQTT_SN_MSG_TYPE_PUBCOMP)
776  {
777  //Restore the message identifier that was used to send the first
778  //PUBLISH message
779  if(!dup)
780  publishMsgId = context->msgId;
781  }
782 
783  //Check the type of the received message
784  if(context->msgType == MQTT_SN_MSG_TYPE_REGACK)
785  {
786  //If the registration has not been accepted, the failure reason is
787  //encoded in the return code field of the REGACK message
788  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
789  {
790  //Save the topic ID assigned by the gateway
791  error = mqttSnClientAddTopic(context, topicName, context->topicId);
792  }
793  else
794  {
795  //The registration request has been rejected by the gateway
796  error = ERROR_REQUEST_REJECTED;
797  }
798  }
799  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBACK)
800  {
801  //If the publish request has not been accepted, the failure reason
802  //is encoded in the return code field of the PUBACK message
803  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
804  {
805  //Check QoS level
806  if(qos == MQTT_SN_QOS_LEVEL_2)
807  {
808  //Unexpected PUBREC message received
809  error = ERROR_UNEXPECTED_MESSAGE;
810  }
811  else
812  {
813  //A PUBACK message has been received
814  break;
815  }
816  }
817  else
818  {
819  //The publish request has been rejected by the gateway
820  error = ERROR_REQUEST_REJECTED;
821  }
822  }
823  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBREC)
824  {
825  //Check QoS level
826  if(qos == MQTT_SN_QOS_LEVEL_2)
827  {
828  //A PUBREL packet is the response to a PUBREC packet. It is the
829  //third packet of the QoS 2 protocol exchange
830  error = mqttSnClientSendPubRel(context, context->msgId);
831  }
832  else
833  {
834  //Unexpected PUBREC message received
835  error = ERROR_UNEXPECTED_MESSAGE;
836  }
837  }
838  else if(context->msgType == MQTT_SN_MSG_TYPE_PUBCOMP)
839  {
840  //A PUBCOMP message has been received
841  break;
842  }
843  else
844  {
845  //Report an error
847  }
848  }
849  else
850  {
851  //Invalid state
852  error = ERROR_NOT_CONNECTED;
853  }
854  }
855 
856  //Return the message identifier that was used to send the PUBLISH message
857  if(msgId != NULL)
858  *msgId = publishMsgId;
859 
860  //Return status code
861  return error;
862 }
863 
864 
865 /**
866  * @brief Subscribe to topic
867  * @param[in] context Pointer to the MQTT-SN client context
868  * @param[in] topicName Topic filter
869  * @param[in] qos Maximum QoS level at which the server can send application
870  * messages to the client
871  * @return Error code
872  **/
873 
876 {
877  error_t error;
878  systime_t time;
879 
880  //Check parameters
881  if(context == NULL || topicName == NULL)
883 
884  //Initialize status code
885  error = NO_ERROR;
886 
887  //Topic subscribe procedure
888  while(!error)
889  {
890  //Get current time
891  time = osGetSystemTime();
892 
893  //Check current state
894  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
895  {
896  //The message identifier allows the sender to match a message with
897  //its corresponding acknowledgment
899 
900  //Save current time
901  context->startTime = time;
902 
903  //Send SUBSCRIBE message
904  error = mqttSnClientSendSubscribe(context, topicName, qos);
905  }
906  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
907  {
908  //Check whether the timeout has elapsed
909  if(timeCompare(time, context->startTime + context->timeout) >= 0)
910  {
911  //Abort the retransmission procedure
912  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
913  //Report a timeout error
914  error = ERROR_TIMEOUT;
915  }
916  else if(timeCompare(time, context->retransmitStartTime +
918  {
919  //If the retry timer times out and the expected gateway's reply
920  //is not received, the client retransmits the message
921  error = mqttSnClientSendSubscribe(context, topicName, qos);
922  }
923  else
924  {
925  //Wait for the gateway's reply
927  }
928  }
929  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
930  {
931  //Update MQTT-SN client state
932  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
933 
934  //Check the type of the received message
935  if(context->msgType == MQTT_SN_MSG_TYPE_SUBACK)
936  {
937  //If the subscribe request has not been accepted, the failure reason
938  //is encoded in the return code field of the SUBACK message
939  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
940  {
941  //The topic ID field is not relevant in case of subscriptions to a
942  //topic name which contains wildcard characters
943  if(osStrchr(topicName, '#') == NULL && osStrchr(topicName, '+') == NULL)
944  {
945  //Save the topic ID assigned by the gateway
946  error = mqttSnClientAddTopic(context, topicName, context->topicId);
947  }
948 
949  //A SUBACK message has been received
950  break;
951  }
952  else
953  {
954  //The subscribe request has been rejected by the gateway
955  error = ERROR_REQUEST_REJECTED;
956  }
957  }
958  else
959  {
960  //Report an error
962  }
963  }
964  else
965  {
966  //Invalid state
967  error = ERROR_NOT_CONNECTED;
968  }
969  }
970 
971  //Return status code
972  return error;
973 }
974 
975 
976 /**
977  * @brief Unsubscribe from topic
978  * @param[in] context Pointer to the MQTT-SN client context
979  * @param[in] topicName Topic filter
980  * @return Error code
981  **/
982 
984  const char_t *topicName)
985 {
986  error_t error;
987  systime_t time;
988 
989  //Check parameters
990  if(context == NULL || topicName == NULL)
992 
993  //Initialize status code
994  error = NO_ERROR;
995 
996  //Topic unsubscribe procedure
997  while(!error)
998  {
999  //Get current time
1000  time = osGetSystemTime();
1001 
1002  //Check current state
1003  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1004  {
1005  //The message identifier allows the sender to match a message with
1006  //its corresponding acknowledgment
1008 
1009  //Save current time
1010  context->startTime = time;
1011 
1012  //Send UNSUBSCRIBE message
1013  error = mqttSnClientSendUnsubscribe(context, topicName);
1014  }
1015  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1016  {
1017  //Check whether the timeout has elapsed
1018  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1019  {
1020  //Abort the retransmission procedure
1021  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1022  //Report a timeout error
1023  error = ERROR_TIMEOUT;
1024  }
1025  else if(timeCompare(time, context->retransmitStartTime +
1027  {
1028  //If the retry timer times out and the expected gateway's reply
1029  //is not received, the client retransmits the message
1030  error = mqttSnClientSendUnsubscribe(context, topicName);
1031  }
1032  else
1033  {
1034  //Wait for the gateway's reply
1036  }
1037  }
1038  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1039  {
1040  //Update MQTT-SN client state
1041  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1042 
1043  //Check the type of the received message
1044  if(context->msgType == MQTT_SN_MSG_TYPE_UNSUBACK)
1045  {
1046  //An UNSUBACK message has been received
1047  break;
1048  }
1049  else
1050  {
1051  //Report an error
1052  error = ERROR_UNEXPECTED_RESPONSE;
1053  }
1054  }
1055  else
1056  {
1057  //Invalid state
1058  error = ERROR_NOT_CONNECTED;
1059  }
1060  }
1061 
1062  //Return status code
1063  return error;
1064 }
1065 
1066 
1067 /**
1068  * @brief Send ping request
1069  * @param[in] context Pointer to the MQTT-SN client context
1070  * @return Error code
1071  **/
1072 
1074 {
1075  error_t error;
1076  systime_t time;
1077 
1078  //Make sure the MQTT-SN client context is valid
1079  if(context == NULL)
1080  return ERROR_INVALID_PARAMETER;
1081 
1082  //Initialize status code
1083  error = NO_ERROR;
1084 
1085  //Send PINGREQ packet and wait for PINGRESP packet to be received
1086  while(!error)
1087  {
1088  //Get current time
1089  time = osGetSystemTime();
1090 
1091  //Check current state
1092  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1093  {
1094  //Save current time
1095  context->startTime = time;
1096  context->retransmitStartTime = time;
1097 
1098  //Send PINGREQ message
1099  error = mqttSnClientSendPingReq(context);
1100 
1101  //Update MQTT-SN client state
1102  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1103  context->msgType = MQTT_SN_MSG_TYPE_PINGREQ;
1104  }
1105  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1106  {
1107  //Check whether the timeout has elapsed
1108  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1109  {
1110  //Abort the retransmission procedure
1111  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1112  //Report a timeout error
1113  error = ERROR_TIMEOUT;
1114  }
1115  else if(timeCompare(time, context->retransmitStartTime +
1117  {
1118  //If the retry timer times out and the expected gateway's reply
1119  //is not received, the client retransmits the message
1120  error = mqttSnClientSendPingReq(context);
1121 
1122  //Save the time at which the message was sent
1123  context->retransmitStartTime = time;
1124  }
1125  else
1126  {
1127  //Wait for the gateway's reply
1129  }
1130  }
1131  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1132  {
1133  //Update MQTT-SN client state
1134  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1135 
1136  //Check the type of the received message
1137  if(context->msgType == MQTT_SN_MSG_TYPE_PINGRESP)
1138  {
1139  //A PINGRESP message has been received
1140  break;
1141  }
1142  else
1143  {
1144  //Report an error
1145  error = ERROR_UNEXPECTED_RESPONSE;
1146  }
1147  }
1148  else
1149  {
1150  //Invalid state
1151  error = ERROR_NOT_CONNECTED;
1152  }
1153  }
1154 
1155  //Return status code
1156  return error;
1157 }
1158 
1159 
1160 /**
1161  * @brief Update the Will message
1162  * @param[in] context Pointer to the MQTT-SN client context
1163  * @param[in] topic Will topic name
1164  * @param[in] message Will message
1165  * @param[in] length Length of the Will message
1166  * @param[in] qos QoS level to be used when publishing the Will message
1167  * @param[in] retain This flag specifies if the Will message is to be retained
1168  * @return Error code
1169  **/
1170 
1172  const char_t *topic, const void *message, size_t length,
1173  MqttSnQosLevel qos, bool_t retain)
1174 {
1175  error_t error;
1176  systime_t time;
1177 
1178  //Check parameters
1179  if(context == NULL || topic == NULL)
1180  return ERROR_INVALID_PARAMETER;
1181  if(message == NULL && length != 0)
1182  return ERROR_INVALID_PARAMETER;
1183 
1184  //Initialize status code
1185  error = NO_ERROR;
1186 
1187  //Publish procedure
1188  while(!error)
1189  {
1190  //Get current time
1191  time = osGetSystemTime();
1192 
1193  //Check current state
1194  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1195  {
1196  //Update the Will message
1197  error = mqttSnClientSetWillMessage(context, topic, message, length,
1198  qos, retain);
1199 
1200  //Check status code
1201  if(!error)
1202  {
1203  //Save current time
1204  context->startTime = time;
1205 
1206  //Send WILLTOPICUPD message
1207  error = mqttSnClientSendWillTopicUpd(context);
1208  }
1209  }
1210  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1211  {
1212  //Check whether the timeout has elapsed
1213  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1214  {
1215  //Abort the retransmission procedure
1216  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
1217  //Report a timeout error
1218  error = ERROR_TIMEOUT;
1219  }
1220  else if(timeCompare(time, context->retransmitStartTime +
1222  {
1223  //If the retry timer times out and the expected gateway's reply
1224  //is not received, the client retransmits the message
1225  if(context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICUPD)
1226  {
1227  //Retransmit WILLTOPICUPD message
1228  error = mqttSnClientSendWillTopicUpd(context);
1229  }
1230  else if(context->msgType == MQTT_SN_MSG_TYPE_WILLMSGUPD)
1231  {
1232  //Retransmit WILLMSGUPD message
1233  error = mqttSnClientSendWillMsgUpd(context);
1234  }
1235  else
1236  {
1237  //Report an error
1238  error = ERROR_INVALID_TYPE;
1239  }
1240  }
1241  else
1242  {
1243  //Wait for the gateway's reply
1245  }
1246  }
1247  else if(context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1248  {
1249  //Update MQTT-SN client state
1250  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1251 
1252  //Check the type of the received message
1253  if(context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICRESP)
1254  {
1255  //If the WILLTOPICUPD has not been accepted, the failure reason
1256  //is encoded in the return code field of the WILLTOPICRESP
1257  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
1258  {
1259  //Valid Will topic?
1260  if(context->willMessage.topic[0] != '\0')
1261  {
1262  //Send WILLMSGUPD message
1263  error = mqttSnClientSendWillMsgUpd(context);
1264  }
1265  else
1266  {
1267  //An empty WILLTOPIC message is used by a client to delete
1268  //the Will topic and the Will message stored in the server
1269  break;
1270  }
1271  }
1272  else
1273  {
1274  //The WILLTOPICUPD request has been rejected by the gateway
1275  error = ERROR_REQUEST_REJECTED;
1276  }
1277  }
1278  else if(context->msgType == MQTT_SN_MSG_TYPE_WILLMSGRESP)
1279  {
1280  //If the WILLMSGUPD has not been accepted, the failure reason
1281  //is encoded in the return code field of the WILLMSGRESP
1282  if(context->returnCode == MQTT_SN_RETURN_CODE_ACCEPTED)
1283  {
1284  //The WILLMSGUPD request has been accepted by the gateway
1285  break;
1286  }
1287  else
1288  {
1289  //The WILLMSGUPD request has been rejected by the gateway
1290  error = ERROR_REQUEST_REJECTED;
1291  }
1292  }
1293  else
1294  {
1295  //Report an error
1296  error = ERROR_UNEXPECTED_RESPONSE;
1297  }
1298  }
1299  else
1300  {
1301  //Invalid state
1302  error = ERROR_NOT_CONNECTED;
1303  }
1304  }
1305 
1306  //Return status code
1307  return error;
1308 }
1309 
1310 
1311 /**
1312  * @brief Retrieve return code
1313  * @param[in] context Pointer to the MQTT-SN client context
1314  * @param[out] returnCode Return code
1315  * @return Error code
1316  **/
1317 
1320 {
1321  //Check parameters
1322  if(context == NULL || returnCode == NULL)
1323  return ERROR_INVALID_PARAMETER;
1324 
1325  //Retrieve return code
1326  *returnCode = context->returnCode;
1327 
1328  //Successful processing
1329  return NO_ERROR;
1330 }
1331 
1332 
1333 /**
1334  * @brief Process MQTT-SN client events
1335  * @param[in] context Pointer to the MQTT-SN client context
1336  * @param[in] timeout Maximum time to wait before returning
1337  * @return Error code
1338  **/
1339 
1341 {
1342  error_t error;
1343 
1344  //Make sure the MQTT-SN client context is valid
1345  if(context == NULL)
1346  return ERROR_INVALID_PARAMETER;
1347 
1348  //Make sure the MQTT-SN client is connected
1349  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE ||
1350  context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ ||
1351  context->state == MQTT_SN_CLIENT_STATE_RESP_RECEIVED)
1352  {
1353  //Process MQTT-SN client events
1354  error = mqttSnClientProcessEvents(context, timeout);
1355  }
1356  else
1357  {
1358  //Invalid state
1359  error = ERROR_NOT_CONNECTED;
1360  }
1361 
1362  //Return status code
1363  return error;
1364 }
1365 
1366 
1367 /**
1368  * @brief Disconnect from the MQTT-SN gateway
1369  * @param[in] context Pointer to the MQTT-SN client context
1370  * @param[in] duration Sleep duration, in milliseconds
1371  * @return Error code
1372  **/
1373 
1376 {
1377  error_t error;
1378  systime_t time;
1379 
1380  //Make sure the MQTT-SN client context is valid
1381  if(context == NULL)
1382  return ERROR_INVALID_PARAMETER;
1383 
1384  //Initialize status code
1385  error = NO_ERROR;
1386 
1387  //Disconnect procedure
1388  while(!error)
1389  {
1390  //Get current time
1391  time = osGetSystemTime();
1392 
1393  //Check current state
1394  if(context->state == MQTT_SN_CLIENT_STATE_ACTIVE)
1395  {
1396  //Save current time
1397  context->startTime = time;
1398 
1399  //The DISCONNECT message is sent by a client to indicate that it
1400  //wants to close the connection
1401  error = mqttSnClientSendDisconnect(context, duration / 1000);
1402  }
1403  else if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ)
1404  {
1405  //Check whether the timeout has elapsed
1406  if(timeCompare(time, context->startTime + context->timeout) >= 0)
1407  {
1408  //Terminate DTLS connection
1410 
1411  //Report a timeout error
1412  error = ERROR_TIMEOUT;
1413  }
1414  else if(timeCompare(time, context->retransmitStartTime +
1416  {
1417  //If the retry timer times out and the expected gateway's reply
1418  //is not received, the client retransmits the message
1419  error = mqttSnClientSendDisconnect(context, duration / 1000);
1420  }
1421  else
1422  {
1423  //Wait for the gateway's reply
1425  }
1426  }
1427  else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTING)
1428  {
1429  //Terminate DTLS connection
1430  error = mqttSnClientShutdownConnection(context);
1431  //Close network connection
1432  mqttSnClientCloseConnection(context);
1433 
1434  //The connection is closed
1435  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
1436  }
1437  else if(context->state == MQTT_SN_CLIENT_STATE_DISCONNECTED)
1438  {
1439  //The MQTT-SN client is disconnected
1440  break;
1441  }
1442  else
1443  {
1444  //Invalid state
1445  error = ERROR_WRONG_STATE;
1446  }
1447  }
1448 
1449  //Any error to report?
1450  if(error != NO_ERROR && error != ERROR_WOULD_BLOCK)
1451  {
1452  //Close network connection
1453  mqttSnClientCloseConnection(context);
1454  //Update MQTT-SN client state
1455  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTED;
1456  }
1457 
1458  //Return status code
1459  return error;
1460 }
1461 
1462 
1463 /**
1464  * @brief Release MQTT-SN client context
1465  * @param[in] context Pointer to the MQTT-SN client context
1466  **/
1467 
1469 {
1470  //Make sure the MQTT-SN client context is valid
1471  if(context != NULL)
1472  {
1473  //Close connection
1474  mqttSnClientCloseConnection(context);
1475 
1476 #if (MQTT_SN_CLIENT_DTLS_SUPPORT == ENABLED)
1477  //Release DTLS session state
1478  tlsFreeSessionState(&context->dtlsSession);
1479 #endif
1480 
1481  //Clear MQTT-SN client context
1482  osMemset(context, 0, sizeof(MqttSnClientContext));
1483  }
1484 }
1485 
1486 #endif
uint8_t message[]
Definition: chap.h:154
unsigned int uint_t
Definition: compiler_port.h:50
char char_t
Definition: compiler_port.h:48
int bool_t
Definition: compiler_port.h:53
Debugging facilities.
uint32_t time
error_t
Error codes.
Definition: error.h:43
@ ERROR_WOULD_BLOCK
Definition: error.h:96
@ ERROR_INVALID_TYPE
Definition: error.h:115
@ ERROR_TIMEOUT
Definition: error.h:95
@ ERROR_NOT_CONNECTED
Definition: error.h:80
@ ERROR_UNEXPECTED_RESPONSE
Definition: error.h:70
@ NO_ERROR
Success.
Definition: error.h:44
@ ERROR_REQUEST_REJECTED
Definition: error.h:271
@ ERROR_WRONG_STATE
Definition: error.h:209
@ ERROR_INVALID_LENGTH
Definition: error.h:111
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
@ ERROR_UNEXPECTED_MESSAGE
Definition: error.h:194
Ipv4Addr destIpAddr
Definition: ipcp.h:80
uint8_t dup
Definition: mqtt_common.h:182
uint8_t qos
Definition: mqtt_common.h:181
error_t mqttSnClientGetReturnCode(MqttSnClientContext *context, MqttSnReturnCode *returnCode)
Retrieve return code.
error_t mqttSnClientRegisterPublishCallback(MqttSnClientContext *context, MqttSnClientPublishCallback callback)
Register publish callback function.
error_t mqttSnClientSetWillMessage(MqttSnClientContext *context, const char_t *topic, const void *message, size_t length, MqttSnQosLevel qos, bool_t retain)
Specify the Will message.
error_t mqttSnClientSetPredefinedTopics(MqttSnClientContext *context, MqttSnPredefinedTopic *predefinedTopics, uint_t size)
Set the list of predefined topics.
error_t mqttSnClientSetGateway(MqttSnClientContext *context, const IpAddr *gwIpAddr, uint16_t gwPort)
Specify the address of the gateway.
error_t mqttSnClientSetTimeout(MqttSnClientContext *context, systime_t timeout)
Set communication timeout.
error_t mqttSnClientSearchGateway(MqttSnClientContext *context, const IpAddr *destIpAddr, uint16_t destPort)
Search for a gateway.
error_t mqttSnClientSetIdentifier(MqttSnClientContext *context, const char_t *clientId)
Set client identifier.
error_t mqttSnClientPing(MqttSnClientContext *context)
Send ping request.
error_t mqttSnClientConnect(MqttSnClientContext *context, bool_t cleanSession)
Establish connection with the MQTT-SN gateway.
error_t mqttSnClientUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Unsubscribe from topic.
error_t mqttSnClientSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Subscribe to topic.
error_t mqttSnClientDisconnect(MqttSnClientContext *context, systime_t duration)
Disconnect from the MQTT-SN gateway.
error_t mqttSnClientTask(MqttSnClientContext *context, systime_t timeout)
Process MQTT-SN client events.
error_t mqttSnClientInit(MqttSnClientContext *context)
Initialize MQTT-SN client context.
void mqttSnClientDeinit(MqttSnClientContext *context)
Release MQTT-SN client context.
error_t mqttSnClientBindToInterface(MqttSnClientContext *context, NetInterface *interface)
Bind the MQTT-SN client to a particular network interface.
error_t mqttSnClientSetKeepAlive(MqttSnClientContext *context, systime_t keepAlive)
Set keep-alive value.
error_t mqttSnClientSetTransportProtocol(MqttSnClientContext *context, MqttSnTransportProtocol transportProtocol)
Set the transport protocol to be used.
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 mqttSnClientRegisterDtlsInitCallback(MqttSnClientContext *context, MqttSnClientDtlsInitCallback callback)
Register DTLS initialization callback function.
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.
MQTT-SN client.
error_t(* MqttSnClientDtlsInitCallback)(MqttSnClientContext *context, TlsContext *dtlsContext)
DTLS initialization callback.
#define MQTT_SN_CLIENT_MAX_WILL_PAYLOAD_LEN
#define MQTT_SN_CLIENT_RETRY_TIMEOUT
void(* MqttSnClientPublishCallback)(MqttSnClientContext *context, const char_t *topic, const uint8_t *message, size_t length, MqttSnQosLevel qos, bool_t retain)
PUBLISH message received callback.
#define MQTT_SN_CLIENT_SEARCH_DELAY
#define MQTT_SN_CLIENT_MAX_ID_LEN
#define MQTT_SN_CLIENT_TICK_INTERVAL
@ MQTT_SN_CLIENT_STATE_SEARCHING
@ MQTT_SN_CLIENT_STATE_ACTIVE
@ MQTT_SN_CLIENT_STATE_DISCONNECTED
@ MQTT_SN_CLIENT_STATE_RESP_RECEIVED
@ MQTT_SN_CLIENT_STATE_CONNECTING
@ MQTT_SN_CLIENT_STATE_DISCONNECTING
@ MQTT_SN_CLIENT_STATE_SENDING_REQ
#define MQTT_SN_CLIENT_DEFAULT_KEEP_ALIVE
#define MQTT_SN_CLIENT_MAX_WILL_TOPIC_LEN
#define MqttSnClientContext
#define MQTT_SN_CLIENT_DEFAULT_TIMEOUT
error_t mqttSnClientSendConnect(MqttSnClientContext *context, bool_t cleanSession)
Send CONNECT message.
error_t mqttSnClientSendWillMsgUpd(MqttSnClientContext *context)
Send WILLMSGUPD message.
error_t mqttSnClientSendDisconnect(MqttSnClientContext *context, uint16_t duration)
Send DISCONNECT message.
error_t mqttSnClientSendSearchGw(MqttSnClientContext *context, uint8_t radius, const IpAddr *destIpAddr, uint16_t destPort)
Send SEARCHGW message.
error_t mqttSnClientSendPingReq(MqttSnClientContext *context)
Send PINGREQ 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 mqttSnClientSendPubRel(MqttSnClientContext *context, uint16_t msgId)
Send PUBREL message.
error_t mqttSnClientSendRegister(MqttSnClientContext *context, const char_t *topicName)
Send REGISTER message.
error_t mqttSnClientSendUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Send UNSUBSCRIBE message.
error_t mqttSnClientSendSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Send SUBSCRIBE message.
error_t mqttSnClientSendWillTopicUpd(MqttSnClientContext *context)
Send WILLTOPICUPD message.
MQTT-SN message formatting and parsing.
error_t mqttSnClientProcessEvents(MqttSnClientContext *context, systime_t timeout)
Process MQTT-SN client events.
uint16_t mqttSnClientFindTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a given topic name.
bool_t mqttSnClientIsShortTopicName(const char_t *topicName)
Check whether a topic name is a short topic name.
uint16_t mqttSnClientFindPredefTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a predefined topic name.
error_t mqttSnClientAddTopic(MqttSnClientContext *context, const char_t *topicName, uint16_t topicId)
Add a new entry to the topic table.
uint16_t mqttSnClientGenerateMessageId(MqttSnClientContext *context)
Generate a new message identifier.
Helper functions for MQTT-SN client.
void mqttSnClientCloseConnection(MqttSnClientContext *context)
Close network connection.
error_t mqttSnClientOpenConnection(MqttSnClientContext *context, bool_t secure)
Open network connection.
error_t mqttSnClientShutdownConnection(MqttSnClientContext *context)
Shutdown network connection.
error_t mqttSnClientEstablishConnection(MqttSnClientContext *context)
Establish network connection.
Transport protocol abstraction layer.
@ MQTT_SN_MSG_TYPE_WILLTOPICRESP
@ MQTT_SN_MSG_TYPE_SUBACK
@ MQTT_SN_MSG_TYPE_PINGREQ
@ MQTT_SN_MSG_TYPE_UNSUBACK
@ MQTT_SN_MSG_TYPE_GWINFO
@ MQTT_SN_MSG_TYPE_PUBLISH
@ MQTT_SN_MSG_TYPE_WILLTOPICUPD
@ MQTT_SN_MSG_TYPE_PUBACK
@ MQTT_SN_MSG_TYPE_REGISTER
@ MQTT_SN_MSG_TYPE_PINGRESP
@ MQTT_SN_MSG_TYPE_WILLMSGUPD
@ MQTT_SN_MSG_TYPE_PUBREC
@ MQTT_SN_MSG_TYPE_WILLMSGRESP
@ MQTT_SN_MSG_TYPE_PUBCOMP
@ MQTT_SN_MSG_TYPE_PUBREL
@ MQTT_SN_MSG_TYPE_REGACK
@ MQTT_SN_MSG_TYPE_CONNACK
MqttSnTransportProtocol
MQTT-SN transport protocols.
@ MQTT_SN_TRANSPORT_PROTOCOL_UDP
UDP protocol.
uint16_t msgId
MqttSnQosLevel
Quality of service level.
@ MQTT_SN_QOS_LEVEL_1
At least once delivery.
@ MQTT_SN_QOS_LEVEL_2
Exactly once delivery.
uint16_t duration
char_t topicName[]
uint8_t returnCode
MqttSnReturnCode
MQTT-SN return codes.
@ MQTT_SN_RETURN_CODE_ACCEPTED
char_t clientId[]
uint32_t netGetRandRange(uint32_t min, uint32_t max)
Generate a random value in the specified range.
Definition: net.c:416
TCP/IP stack core.
#define NetInterface
Definition: net.h:36
#define osMemset(p, value, length)
Definition: os_port.h:135
#define osMemcpy(dest, src, length)
Definition: os_port.h:141
#define timeCompare(t1, t2)
Definition: os_port.h:40
#define osStrchr(s, c)
Definition: os_port.h:195
#define osStrlen(s)
Definition: os_port.h:165
#define TRUE
Definition: os_port.h:50
#define FALSE
Definition: os_port.h:46
#define osStrcpy(s1, s2)
Definition: os_port.h:207
systime_t osGetSystemTime(void)
Retrieve system time.
uint32_t systime_t
System time.
IP network address.
Definition: ip.h:79
Predefined topic.
uint8_t length
Definition: tcp.h:368
uint16_t destPort
Definition: tcp.h:340
void tlsFreeSessionState(TlsSessionState *session)
Properly dispose a session state.
Definition: tls.c:2743
error_t tlsInitSessionState(TlsSessionState *session)
Initialize session state.
Definition: tls.c:2600