mqtt_sn_client_message.c
Go to the documentation of this file.
1 /**
2  * @file mqtt_sn_client_message.c
3  * @brief MQTT-SN message parsing and formatting
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"
41 #include "mqtt_sn/mqtt_sn_debug.h"
42 #include "debug.h"
43 
44 //Check TCP/IP stack configuration
45 #if (MQTT_SN_CLIENT_SUPPORT == ENABLED)
46 
47 
48 /**
49  * @brief Process incoming MQTT-SN message
50  * @param[in] context Pointer to the MQTT-SN client context
51  * @param[in] message Pointer to the received MQTT-SN message
52  * @param[in] ipAddr Source IP address
53  * @param[in] port Source port
54  * @return Error code
55  **/
56 
58  MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
59 {
60  error_t error;
62 
63  //Parse MQTT-SN message header
64  error = mqttSnParseHeader(message, &type);
65 
66  //Check status code
67  if(!error)
68  {
69  //Debug message
70  TRACE_INFO("%s message received (%" PRIuSIZE " bytes)...\r\n",
72 
73  //Dump the contents of the message for debugging purpose
74  mqttSnDumpMessage(message->buffer, message->length);
75 
76  //Check message type
77  switch(type)
78  {
79  //GWINFO message received?
81  //Process incoming GWINFO message
82  error = mqttSnClientProcessGwInfo(context, message, ipAddr, port);
83  break;
84  //CONNACK message received?
86  //Process incoming CONNACK message
87  error = mqttSnClientProcessConnAck(context, message);
88  break;
89  //WILLTOPICREQ message received?
91  //Process incoming WILLTOPICREQ message
92  error = mqttSnClientProcessWillTopicReq(context, message);
93  break;
94  //WILLMSGREQ message received?
96  //Process incoming WILLMSGREQ message
97  error = mqttSnClientProcessWillMsgReq(context, message);
98  break;
99  //REGISTER message received?
101  //Process incoming REGISTER message
102  error = mqttSnClientProcessRegister(context, message);
103  break;
104  //REGACK message received?
106  //Process incoming REGACK message
107  error = mqttSnClientProcessRegAck(context, message);
108  break;
109  //PUBLISH message received?
111  //Process incoming PUBLISH message
112  error = mqttSnClientProcessPublish(context, message);
113  break;
114  //PUBACK message received?
116  //Process incoming PUBACK message
117  error = mqttSnClientProcessPubAck(context, message);
118  break;
119  //PUBREC message received?
121  //Process incoming PUBREC message
122  error = mqttSnClientProcessPubRec(context, message);
123  break;
124  //PUBREL message received?
126  //Process incoming PUBREL message
127  error = mqttSnClientProcessPubRel(context, message);
128  break;
129  //PUBCOMP message received?
131  //Process incoming PUBCOMP message
132  error = mqttSnClientProcessPubComp(context, message);
133  break;
134  //SUBACK message received?
136  //Process incoming SUBACK message
137  error = mqttSnClientProcessSubAck(context, message);
138  break;
139  //UNSUBACK message received?
141  //Process incoming UNSUBACK message
142  error = mqttSnClientProcessUnsubAck(context, message);
143  break;
144  //PINGREQ message received?
146  //Process incoming PINGREQ message
147  error = mqttSnClientProcessPingReq(context, message);
148  break;
149  //PINGRESP message received?
151  //Process incoming PINGRESP message
152  error = mqttSnClientProcessPingResp(context, message);
153  break;
154  //DISCONNECT message received?
156  //Process incoming DISCONNECT message
157  error = mqttSnClientProcessDisconnect(context, message);
158  break;
159  //WILLTOPICRESP message received?
161  //Process incoming DISCONNECT message
162  error = mqttSnClientProcessWillTopicResp(context, message);
163  break;
164  //WILLMSGRESP message received?
166  //Process incoming DISCONNECT message
167  error = mqttSnClientProcessWillMsgResp(context, message);
168  break;
169  //Unknown message received?
170  default:
171  //Report an error
172  error = ERROR_INVALID_TYPE;
173  break;
174  }
175  }
176  else
177  {
178  //Debug message
179  TRACE_WARNING("Invalid message received (%" PRIuSIZE " bytes)...\r\n",
180  message->length);
181 
182  //Dump the contents of the message
183  TRACE_DEBUG_ARRAY(" ", message->buffer, message->length);
184  }
185 
186  //Return status code
187  return error;
188 }
189 
190 
191 /**
192  * @brief Process incoming GWINFO message
193  * @param[in] context Pointer to the MQTT-SN client context
194  * @param[in] message Pointer to the received MQTT-SN message
195  * @param[in] ipAddr Source IP address
196  * @param[in] port Source port
197  * @return Error code
198  **/
199 
201  const MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
202 {
203  error_t error;
204  uint8_t gwId;
205  const uint8_t *gwAdd;
206  size_t gwAddLen;
207 
208  //Parse GWINFO message
209  error = mqttSnParseGwInfo(message, &gwId, &gwAdd, &gwAddLen);
210 
211  //Valid message received?
212  if(!error)
213  {
214  //Check current state
215  if(context->state == MQTT_SN_CLIENT_STATE_SEARCHING)
216  {
217  //Notify the application that a GWINFO message has been received
218  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
219  context->msgType = MQTT_SN_MSG_TYPE_GWINFO;
220  context->gwIpAddr = *ipAddr;
221  context->gwPort = port;
222  }
223  }
224 
225  //Return status code
226  return error;
227 }
228 
229 
230 /**
231  * @brief Process incoming CONNACK message
232  * @param[in] context Pointer to the MQTT-SN client context
233  * @param[in] message Pointer to the received MQTT-SN message
234  * @return Error code
235  **/
236 
238  const MqttSnMessage *message)
239 {
240  error_t error;
242 
243  //Parse CONNACK message
245 
246  //Valid message received?
247  if(!error)
248  {
249  //Check current state
250  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
251  context->msgType == MQTT_SN_MSG_TYPE_CONNECT)
252  {
253  //Notify the application that a CONNACK message has been received
254  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
255  context->msgType = MQTT_SN_MSG_TYPE_CONNACK;
256  context->returnCode = returnCode;
257 
258  //The MQTT-SN gateway is alive
259  context->keepAliveCounter = 0;
260  }
261  }
262 
263  //Return status code
264  return error;
265 }
266 
267 
268 /**
269  * @brief Process incoming WILLTOPICREQ message
270  * @param[in] context Pointer to the MQTT-SN client context
271  * @param[in] message Pointer to the received MQTT-SN message
272  * @return Error code
273  **/
274 
276  const MqttSnMessage *message)
277 {
278  error_t error;
279 
280  //Parse WILLTOPICREQ message
282 
283  //Valid message received?
284  if(!error)
285  {
286  //The WILLTOPIC message is sent by a client as response to the WILLTOPICREQ
287  //message for transferring its Will topic name to the GW
288  error = mqttSnClientSendWillTopic(context);
289  }
290 
291  //Return status code
292  return error;
293 }
294 
295 
296 /**
297  * @brief Process incoming WILLMSGREQ message
298  * @param[in] context Pointer to the MQTT-SN client context
299  * @param[in] message Pointer to the received MQTT-SN message
300  * @return Error code
301  **/
302 
304  const MqttSnMessage *message)
305 {
306  error_t error;
307 
308  //Parse WILLMSGREQ message
310 
311  //Valid message received?
312  if(!error)
313  {
314  //The WILLMSG message is sent by a client as response to a WILLMSGREQ
315  //for transferring its Will message to the GW
316  error = mqttSnClientSendWillMsg(context);
317  }
318 
319  //Return status code
320  return error;
321 }
322 
323 
324 /**
325  * @brief Process incoming REGISTER message
326  * @param[in] context Pointer to the MQTT-SN client context
327  * @param[in] message Pointer to the received MQTT-SN message
328  * @return Error code
329  **/
330 
332  const MqttSnMessage *message)
333 {
334  error_t error;
335  uint16_t msgId;
336  uint16_t topicId;
337  const char_t *topicName;
339 
340  //Parse REGISTER message
342 
343  //Valid message received?
344  if(!error)
345  {
346  //Save the topic ID assigned by the gateway
347  error = mqttSnClientAddTopic(context, topicName, topicId);
348 
349  //Check status code
350  if(!error)
352  else
354 
355  //The client sends a REGACK message to acknowledge the receipt and
356  //processing of a REGISTER message
357  error = mqttSnClientSendRegAck(context, msgId, topicId, returnCode);
358  }
359 
360  //Return status code
361  return error;
362 }
363 
364 
365 /**
366  * @brief Process incoming REGACK message
367  * @param[in] context Pointer to the MQTT-SN client context
368  * @param[in] message Pointer to the received MQTT-SN message
369  * @return Error code
370  **/
371 
373  const MqttSnMessage *message)
374 {
375  error_t error;
376  uint16_t msgId;
377  uint16_t topicId;
379 
380  //Parse REGACK message
382 
383  //Valid message received?
384  if(!error)
385  {
386  //Check current state
387  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
388  context->msgType == MQTT_SN_MSG_TYPE_REGISTER &&
389  context->msgId == msgId)
390  {
391  //Notify the application that a REGACK message has been received
392  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
393  context->msgType = MQTT_SN_MSG_TYPE_REGACK;
394  context->topicId = topicId;
395  context->returnCode = returnCode;
396 
397  //The MQTT-SN gateway is alive
398  context->keepAliveCounter = 0;
399  }
400  }
401 
402  //Return status code
403  return error;
404 }
405 
406 
407 /**
408  * @brief Process incoming PUBLISH message
409  * @param[in] context Pointer to the MQTT-SN client context
410  * @param[in] message Pointer to the received MQTT-SN message
411  * @return Error code
412  **/
413 
415  const MqttSnMessage *message)
416 {
417  error_t error;
418  bool_t duplicate;
419  uint16_t msgId;
420  uint16_t topicId;
421  const uint8_t *data;
422  size_t dataLen;
425 
426  //Parse PUBLISH message
428  &data, &dataLen);
429 
430  //Valid message received?
431  if(!error)
432  {
433  //Check QoS level
434  if(flags.qos == MQTT_SN_QOS_LEVEL_1)
435  {
436  //Deliver the message to the application
438  data, dataLen);
439 
440  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
441  error = mqttSnClientSendPubAck(context, msgId, topicId, returnCode);
442  }
443  else if(flags.qos == MQTT_SN_QOS_LEVEL_2)
444  {
445  //Check whether the ownership of the QoS 2 message has already been
446  //transferred to the client
447  duplicate = mqttSnClientIsDuplicateMessageId(context, msgId);
448 
449  //Duplicate message?
450  if(duplicate)
451  {
452  //In QoS 2, the receiver must not cause duplicate messages to be
453  //delivered to any onward recipients
454  error = mqttSnClientSendPubRec(context, msgId);
455  }
456  else
457  {
458  //Accept the ownership of the QoS 2 message
459  error = mqttSnClientStoreMessageId(context, msgId);
460 
461  //Check status code
462  if(!error)
463  {
464  //Initiate onward delivery of the application message
466  data, dataLen);
467  }
468  else
469  {
470  //The message identifier cannot be saved
472  }
473 
474  //Check whether the PUBLISH message has been accepted
476  {
477  //A PUBREC packet is the response to a PUBLISH packet with QoS 2.
478  //It is the second packet of the QoS 2 protocol exchange
479  error = mqttSnClientSendPubRec(context, msgId);
480  }
481  else
482  {
483  //Discard message identifier
485 
486  //Reject the PUBLISH message
487  error = mqttSnClientSendPubAck(context, msgId, topicId,
488  returnCode);
489  }
490  }
491  }
492  else
493  {
494  //Deliver the message to the application
496  data, dataLen);
497 
498  //In QoS 0, the receiver always accepts the message
499  error = NO_ERROR;
500  }
501  }
502 
503  //Return status code
504  return error;
505 }
506 
507 
508 /**
509  * @brief Process incoming PUBACK message
510  * @param[in] context Pointer to the MQTT-SN client context
511  * @param[in] message Pointer to the received MQTT-SN message
512  * @return Error code
513  **/
514 
516  const MqttSnMessage *message)
517 {
518  error_t error;
519  uint16_t msgId;
520  uint16_t topicId;
522 
523  //Parse PUBACK message
525 
526  //Valid message received?
527  if(!error)
528  {
529  //Check current state
530  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
531  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
532  context->msgId == msgId)
533  {
534  //Notify the application that a PUBACK message has been received
535  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
536  context->msgType = MQTT_SN_MSG_TYPE_PUBACK;
537  context->returnCode = returnCode;
538 
539  //The MQTT-SN gateway is alive
540  context->keepAliveCounter = 0;
541  }
542  }
543 
544  //Return status code
545  return error;
546 }
547 
548 
549 /**
550  * @brief Process incoming PUBREC message
551  * @param[in] context Pointer to the MQTT-SN client context
552  * @param[in] message Pointer to the received MQTT-SN message
553  * @return Error code
554  **/
555 
557  const MqttSnMessage *message)
558 {
559  error_t error;
560  uint16_t msgId;
561 
562  //Parse PUBREC message
563  error = mqttSnParsePubRec(message, &msgId);
564 
565  //Valid message received?
566  if(!error)
567  {
568  //Check current state
569  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
570  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
571  context->msgId == msgId)
572  {
573  //Notify the application that a PUBREC message has been received
574  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
575  context->msgType = MQTT_SN_MSG_TYPE_PUBREC;
576 
577  //The MQTT-SN gateway is alive
578  context->keepAliveCounter = 0;
579  }
580  }
581 
582  //Return status code
583  return error;
584 }
585 
586 
587 /**
588  * @brief Process incoming PUBREL message
589  * @param[in] context Pointer to the MQTT-SN client context
590  * @param[in] message Pointer to the received MQTT-SN message
591  * @return Error code
592  **/
593 
595  const MqttSnMessage *message)
596 {
597  error_t error;
598  uint16_t msgId;
599 
600  //Parse PUBREL message
601  error = mqttSnParsePubRel(message, &msgId);
602 
603  //Valid message received?
604  if(!error)
605  {
606  //Discard message identifier
608 
609  //A PUBCOMP message is the response to a PUBREL packet. It is the fourth
610  //and final message of the QoS 2 protocol exchange
611  error = mqttSnClientSendPubComp(context, msgId);
612  }
613 
614  //Return status code
615  return error;
616 }
617 
618 
619 /**
620  * @brief Process incoming PUBCOMP message
621  * @param[in] context Pointer to the MQTT-SN client context
622  * @param[in] message Pointer to the received MQTT-SN message
623  * @return Error code
624  **/
625 
627  const MqttSnMessage *message)
628 {
629  error_t error;
630  uint16_t msgId;
631 
632  //Parse PUBCOMP message
633  error = mqttSnParsePubComp(message, &msgId);
634 
635  //Valid message received?
636  if(!error)
637  {
638  //Check current state
639  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
640  context->msgType == MQTT_SN_MSG_TYPE_PUBREL &&
641  context->msgId == msgId)
642  {
643  //Notify the application that a PUBCOMP message has been received
644  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
645  context->msgType = MQTT_SN_MSG_TYPE_PUBCOMP;
646 
647  //The MQTT-SN gateway is alive
648  context->keepAliveCounter = 0;
649  }
650  }
651 
652  //Return status code
653  return error;
654 }
655 
656 
657 /**
658  * @brief Process incoming SUBACK message
659  * @param[in] context Pointer to the MQTT-SN client context
660  * @param[in] message Pointer to the received MQTT-SN message
661  * @return Error code
662  **/
663 
665  const MqttSnMessage *message)
666 {
667  error_t error;
668  uint16_t msgId;
669  uint16_t topicId;
672 
673  //Parse SUBACK message
675 
676  //Valid message received?
677  if(!error)
678  {
679  //Check current state
680  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
681  context->msgType == MQTT_SN_MSG_TYPE_SUBSCRIBE &&
682  context->msgId == msgId)
683  {
684  //Notify the application that a SUBACK message has been received
685  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
686  context->msgType = MQTT_SN_MSG_TYPE_SUBACK;
687  context->topicId = topicId;
688  context->returnCode = returnCode;
689 
690  //The MQTT-SN gateway is alive
691  context->keepAliveCounter = 0;
692  }
693  }
694 
695  //Return status code
696  return error;
697 }
698 
699 
700 /**
701  * @brief Process incoming UNSUBACK message
702  * @param[in] context Pointer to the MQTT-SN client context
703  * @param[in] message Pointer to the received MQTT-SN message
704  * @return Error code
705  **/
706 
708  const MqttSnMessage *message)
709 {
710  error_t error;
711  uint16_t msgId;
712 
713  //Parse UNSUBACK message
714  error = mqttSnParseUnsubAck(message, &msgId);
715 
716  //Valid message received?
717  if(!error)
718  {
719  //Check current state
720  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
721  context->msgType == MQTT_SN_MSG_TYPE_UNSUBSCRIBE &&
722  context->msgId == msgId)
723  {
724  //Notify the application that a UNSUBACK message has been received
725  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
726  context->msgType = MQTT_SN_MSG_TYPE_UNSUBACK;
727 
728  //The MQTT-SN gateway is alive
729  context->keepAliveCounter = 0;
730  }
731  }
732 
733  //Return status code
734  return error;
735 }
736 
737 
738 /**
739  * @brief Process incoming PINGREQ message
740  * @param[in] context Pointer to the MQTT-SN client context
741  * @param[in] message Pointer to the received MQTT-SN message
742  * @return Error code
743  **/
744 
746  const MqttSnMessage *message)
747 {
748  error_t error;
749  const char_t *clientId;
750 
751  //Parse PINGREQ message
753 
754  //Valid message received?
755  if(!error)
756  {
757  //A client shall answer with a PINGRESP message when it receives a
758  //PINGREQ message from the GW to which it is connected
759  error = mqttSnClientSendPingResp(context);
760  }
761 
762  //Return status code
763  return error;
764 }
765 
766 
767 /**
768  * @brief Process incoming PINGRESP message
769  * @param[in] context Pointer to the MQTT-SN client context
770  * @param[in] message Pointer to the received MQTT-SN message
771  * @return Error code
772  **/
773 
775  const MqttSnMessage *message)
776 {
777  error_t error;
778 
779  //Parse PINGRESP message
780  error = mqttSnParsePingResp(message);
781 
782  //Valid message received?
783  if(!error)
784  {
785  //Check current state
786  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
787  context->msgType == MQTT_SN_MSG_TYPE_PINGREQ)
788  {
789  //Notify the application that a PINGRESP message has been received
790  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
791  context->msgType = MQTT_SN_MSG_TYPE_PINGRESP;
792  }
793 
794  //The MQTT-SN gateway is alive
795  context->keepAliveCounter = 0;
796  }
797 
798  //Return status code
799  return error;
800 }
801 
802 
803 /**
804  * @brief Process incoming DISCONNECT message
805  * @param[in] context Pointer to the MQTT-SN client context
806  * @param[in] message Pointer to the received MQTT-SN message
807  * @return Error code
808  **/
809 
811  const MqttSnMessage *message)
812 {
813  error_t error;
814  uint16_t duration;
815 
816  //Parse DISCONNECT message
818 
819  //Valid message received?
820  if(!error)
821  {
822  //The gateway indicates that it wants to close the connection
823  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
824  }
825 
826  //Return status code
827  return error;
828 }
829 
830 
831 /**
832  * @brief Process incoming WILLTOPICRESP message
833  * @param[in] context Pointer to the MQTT-SN client context
834  * @param[in] message Pointer to the received MQTT-SN message
835  * @return Error code
836  **/
837 
839  const MqttSnMessage *message)
840 {
841  error_t error;
843 
844  //Parse WILLTOPICRESP message
846 
847  //Valid message received?
848  if(!error)
849  {
850  //Check current state
851  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
852  context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICUPD)
853  {
854  //Notify the application that a WILLTOPICRESP message has been received
855  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
856  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICRESP;
857  context->returnCode = returnCode;
858 
859  //The MQTT-SN gateway is alive
860  context->keepAliveCounter = 0;
861  }
862  }
863 
864  //Return status code
865  return error;
866 }
867 
868 
869 /**
870  * @brief Process incoming WILLMSGRESP message
871  * @param[in] context Pointer to the MQTT-SN client context
872  * @param[in] message Pointer to the received MQTT-SN message
873  * @return Error code
874  **/
875 
877  const MqttSnMessage *message)
878 {
879  error_t error;
881 
882  //Parse WILLMSGRESP message
884 
885  //Valid message received?
886  if(!error)
887  {
888  //Check current state
889  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
890  context->msgType == MQTT_SN_MSG_TYPE_WILLMSGUPD)
891  {
892  //Notify the application that a WILLMSGRESP message has been received
893  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
894  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGRESP;
895  context->returnCode = returnCode;
896 
897  //The MQTT-SN gateway is alive
898  context->keepAliveCounter = 0;
899  }
900  }
901 
902  //Return status code
903  return error;
904 }
905 
906 
907 /**
908  * @brief Send SEARCHGW message
909  * @param[in] context Pointer to the MQTT-SN client context
910  * @param[in] radius Broadcast radius of SEARCHGW message
911  * @param[in] destIpAddr Destination IP address
912  * @param[in] destPort Destination port number
913  * @return Error code
914  **/
915 
917  const IpAddr *destIpAddr, uint16_t destPort)
918 {
919  error_t error;
920 
921  //Format SEARCHGW message
922  error = mqttSnFormatSearchGw(&context->message, radius);
923 
924  //Check status code
925  if(!error)
926  {
927  //Debug message
928  TRACE_INFO("Sending SEARCHGW message (%" PRIuSIZE " bytes)...\r\n",
929  context->message.length);
930 
931  //Dump the contents of the message for debugging purpose
932  mqttSnDumpMessage(context->message.buffer, context->message.length);
933 
934  //Send MQTT-SN message
936  context->message.buffer, context->message.length);
937 
938  //Save the time at which the message was sent
939  context->retransmitStartTime = osGetSystemTime();
940  }
941 
942  //Return status code
943  return error;
944 }
945 
946 
947 /**
948  * @brief Send CONNECT message
949  * @param[in] context Pointer to the MQTT-SN client context
950  * @param[in] cleanSession If this flag is set, then the client and server
951  * must discard any previous session and start a new one
952  * @return Error code
953  **/
954 
957 {
958  error_t error;
959  systime_t time;
961 
962  //The flags contains a number of parameters specifying the behavior of
963  //the MQTT-SN connection
964  flags.all = 0;
965 
966  //If CleanSession is set to 1, the client and server must discard any
967  //previous session and start a new one
968  if(cleanSession)
969  flags.cleanSession = TRUE;
970 
971  //If the client supplies a zero-byte Client Identifier, the client must
972  //also set CleanSession to 1
973  if(context->clientId[0] == '\0')
974  flags.cleanSession = TRUE;
975 
976  //Check whether a valid Will message has been specified
977  if(context->willMessage.topic[0] != '\0')
978  flags.will = TRUE;
979 
980  //Format CONNECT message
981  error = mqttSnFormatConnect(&context->message, flags,
982  context->keepAlive / 1000, context->clientId);
983 
984  //Check status code
985  if(!error)
986  {
987  //Debug message
988  TRACE_INFO("Sending CONNECT message (%" PRIuSIZE " bytes)...\r\n",
989  context->message.length);
990 
991  //Dump the contents of the message for debugging purpose
992  mqttSnDumpMessage(context->message.buffer, context->message.length);
993 
994  //Send MQTT-SN message
995  error = mqttSnClientSendDatagram(context, context->message.buffer,
996  context->message.length);
997 
998  //Get current time
999  time = osGetSystemTime();
1000 
1001  //Save the time at which the message was sent
1002  context->retransmitStartTime = time;
1003  context->keepAliveTimestamp = time;
1004 
1005  //Update MQTT-SN client state
1006  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1007  context->msgType = MQTT_SN_MSG_TYPE_CONNECT;
1008  }
1009 
1010  //Return status code
1011  return error;
1012 }
1013 
1014 
1015 /**
1016  * @brief Send WILLTOPIC message
1017  * @param[in] context Pointer to the MQTT-SN client context
1018  * @return Error code
1019  **/
1020 
1022 {
1023  error_t error;
1024 
1025  //Format WILLTOPIC message
1026  error = mqttSnFormatWillTopic(&context->message,
1027  context->willMessage.flags, context->willMessage.topic);
1028 
1029  //Check status code
1030  if(!error)
1031  {
1032  //Debug message
1033  TRACE_INFO("Sending WILLTOPIC message (%" PRIuSIZE " bytes)...\r\n",
1034  context->message.length);
1035 
1036  //Dump the contents of the message for debugging purpose
1037  mqttSnDumpMessage(context->message.buffer, context->message.length);
1038 
1039  //Send MQTT-SN message
1040  error = mqttSnClientSendDatagram(context, context->message.buffer,
1041  context->message.length);
1042  }
1043 
1044  //Return status code
1045  return error;
1046 }
1047 
1048 
1049 /**
1050  * @brief Send WILLMSG message
1051  * @param[in] context Pointer to the MQTT-SN client context
1052  * @return Error code
1053  **/
1054 
1056 {
1057  error_t error;
1058 
1059  //Format WILLMSG message
1060  error = mqttSnFormatWillMsg(&context->message,
1061  context->willMessage.payload, context->willMessage.length);
1062 
1063  //Check status code
1064  if(!error)
1065  {
1066  //Debug message
1067  TRACE_INFO("Sending WILLMSG message (%" PRIuSIZE " bytes)...\r\n",
1068  context->message.length);
1069 
1070  //Dump the contents of the message for debugging purpose
1071  mqttSnDumpMessage(context->message.buffer, context->message.length);
1072 
1073  //Send MQTT-SN message
1074  error = mqttSnClientSendDatagram(context, context->message.buffer,
1075  context->message.length);
1076  }
1077 
1078  //Return status code
1079  return error;
1080 }
1081 
1082 
1083 /**
1084  * @brief Send REGISTER message
1085  * @param[in] context Pointer to the MQTT-SN client context
1086  * @param[in] topicName Topic name
1087  * @return Error code
1088  **/
1089 
1091  const char_t *topicName)
1092 {
1093  error_t error;
1094  systime_t time;
1095 
1096  //Format REGISTER message
1097  error = mqttSnFormatRegister(&context->message, context->msgId, 0,
1098  topicName);
1099 
1100  //Check status code
1101  if(!error)
1102  {
1103  //Debug message
1104  TRACE_INFO("Sending REGISTER message (%" PRIuSIZE " bytes)...\r\n",
1105  context->message.length);
1106 
1107  //Dump the contents of the message for debugging purpose
1108  mqttSnDumpMessage(context->message.buffer, context->message.length);
1109 
1110  //Send MQTT-SN message
1111  error = mqttSnClientSendDatagram(context, context->message.buffer,
1112  context->message.length);
1113 
1114  //Get current time
1115  time = osGetSystemTime();
1116 
1117  //Save the time at which the message was sent
1118  context->retransmitStartTime = time;
1119  context->keepAliveTimestamp = time;
1120 
1121  //Update MQTT-SN client state
1122  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1123  context->msgType = MQTT_SN_MSG_TYPE_REGISTER;
1124  }
1125 
1126  //Return status code
1127  return error;
1128 }
1129 
1130 
1131 /**
1132  * @brief Send REGACK message
1133  * @param[in] context Pointer to the MQTT-SN client context
1134  * @param[in] msgId Message identifier
1135  * @param[in] topicId Topic identifier
1136  * @param[in] returnCode Return code
1137  * @return Error code
1138  **/
1139 
1142 {
1143  error_t error;
1144 
1145  //Format REGACK message
1146  error = mqttSnFormatRegAck(&context->message, msgId, topicId, returnCode);
1147 
1148  //Check status code
1149  if(!error)
1150  {
1151  //Debug message
1152  TRACE_INFO("Sending REGACK message (%" PRIuSIZE " bytes)...\r\n",
1153  context->message.length);
1154 
1155  //Dump the contents of the message for debugging purpose
1156  mqttSnDumpMessage(context->message.buffer, context->message.length);
1157 
1158  //Send MQTT-SN message
1159  error = mqttSnClientSendDatagram(context, context->message.buffer,
1160  context->message.length);
1161  }
1162 
1163  //Return status code
1164  return error;
1165 }
1166 
1167 
1168 /**
1169  * @brief Send PUBLISH message
1170  * @param[in] context Pointer to the MQTT-SN client context
1171  * @param[in] msgId Message identifier
1172  * @param[in] topicName Short topic name
1173  * @param[in] data Message payload
1174  * @param[in] length Length of the message payload
1175  * @param[in] qos QoS level to be used when publishing the message
1176  * @param[in] retain This flag specifies if the message is to be retained
1177  * @param[in] dup This flag specifies if the message is sent for the first
1178  * time or if the message is retransmitted
1179  * @return Error code
1180  **/
1181 
1183  uint16_t msgId, const char_t *topicName, const uint8_t *data,
1185 {
1186  error_t error;
1187  systime_t time;
1188  uint16_t topicId;
1190 
1191  //Initialize status code
1192  error = NO_ERROR;
1193 
1194  //Reset unused flags
1195  flags.all = 0;
1196  //Set QoS level
1197  flags.qos = qos;
1198  //Set RETAIN flag
1199  flags.retain = retain;
1200  //set DUP flag
1201  flags.dup = dup;
1202 
1203  //Short topic name?
1205  {
1206  //The PUBLISH message contains a short topic name
1207  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1208  //The value of the topic ID is not relevant
1209  topicId = 0;
1210  }
1211  else
1212  {
1213  //Check whether a predefined topic ID has been registered
1215 
1216  //Predefined topic ID found?
1218  {
1219  //The PUBLISH message contains a predefined topic ID
1220  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1221  }
1222  else
1223  {
1224  //Check whether the topic name has been registered
1226 
1227  //Topic ID found?
1229  {
1230  //The PUBLISH message contains a normal topic ID
1231  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_ID;
1232  }
1233  else
1234  {
1235  //The topic name has not been registered
1236  error = ERROR_NOT_FOUND;
1237  }
1238  }
1239  }
1240 
1241  //Check status code
1242  if(!error)
1243  {
1244  //Format PUBLISH message
1245  error = mqttSnFormatPublish(&context->message, flags, msgId,
1247  }
1248 
1249  //Check status code
1250  if(!error)
1251  {
1252  //Debug message
1253  TRACE_INFO("Sending PUBLISH message (%" PRIuSIZE " bytes)...\r\n",
1254  context->message.length);
1255 
1256  //Dump the contents of the message for debugging purpose
1257  mqttSnDumpMessage(context->message.buffer, context->message.length);
1258 
1259  //Send MQTT-SN message
1260  error = mqttSnClientSendDatagram(context, context->message.buffer,
1261  context->message.length);
1262 
1263  //Get current time
1264  time = osGetSystemTime();
1265 
1266  //Check QoS level
1268  {
1269  //Save the time at which the message was sent
1270  context->retransmitStartTime = time;
1271  context->keepAliveTimestamp = time;
1272 
1273  //Update MQTT-SN client state
1274  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1275  context->msgType = MQTT_SN_MSG_TYPE_PUBLISH;
1276  }
1277  else
1278  {
1279  //In the QoS 0, no response is sent by the receiver and no retry
1280  //is performed by the sender
1281  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1282  }
1283  }
1284 
1285  //Return status code
1286  return error;
1287 }
1288 
1289 
1290 /**
1291  * @brief Send PUBACK message
1292  * @param[in] context Pointer to the MQTT-SN client context
1293  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1294  * @param[in] topicId Topic identifier
1295  * @param[in] returnCode Return code
1296  * @return Error code
1297  **/
1298 
1301 {
1302  error_t error;
1303 
1304  //Format PUBACK message
1305  error = mqttSnFormatPubAck(&context->message, msgId, topicId, returnCode);
1306 
1307  //Check status code
1308  if(!error)
1309  {
1310  //Debug message
1311  TRACE_INFO("Sending PUBACK message (%" PRIuSIZE " bytes)...\r\n",
1312  context->message.length);
1313 
1314  //Dump the contents of the message for debugging purpose
1315  mqttSnDumpMessage(context->message.buffer, context->message.length);
1316 
1317  //Send MQTT-SN message
1318  error = mqttSnClientSendDatagram(context, context->message.buffer,
1319  context->message.length);
1320  }
1321 
1322  //Return status code
1323  return error;
1324 }
1325 
1326 
1327 /**
1328  * @brief Send PUBREC message
1329  * @param[in] context Pointer to the MQTT-SN client context
1330  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1331  * @return Error code
1332  **/
1333 
1335 {
1336  error_t error;
1337 
1338  //Format PUBREC message
1339  error = mqttSnFormatPubRec(&context->message, msgId);
1340 
1341  //Check status code
1342  if(!error)
1343  {
1344  //Debug message
1345  TRACE_INFO("Sending PUBREC message (%" PRIuSIZE " bytes)...\r\n",
1346  context->message.length);
1347 
1348  //Dump the contents of the message for debugging purpose
1349  mqttSnDumpMessage(context->message.buffer, context->message.length);
1350 
1351  //Send MQTT-SN message
1352  error = mqttSnClientSendDatagram(context, context->message.buffer,
1353  context->message.length);
1354  }
1355 
1356  //Return status code
1357  return error;
1358 }
1359 
1360 
1361 /**
1362  * @brief Send PUBREL message
1363  * @param[in] context Pointer to the MQTT-SN client context
1364  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1365  * @return Error code
1366  **/
1367 
1369 {
1370  error_t error;
1371  systime_t time;
1372 
1373  //Format PUBREL message
1374  error = mqttSnFormatPubRel(&context->message, msgId);
1375 
1376  //Check status code
1377  if(!error)
1378  {
1379  //Debug message
1380  TRACE_INFO("Sending PUBREL message (%" PRIuSIZE " bytes)...\r\n",
1381  context->message.length);
1382 
1383  //Dump the contents of the message for debugging purpose
1384  mqttSnDumpMessage(context->message.buffer, context->message.length);
1385 
1386  //Send MQTT-SN message
1387  error = mqttSnClientSendDatagram(context, context->message.buffer,
1388  context->message.length);
1389 
1390  //Get current time
1391  time = osGetSystemTime();
1392 
1393  //Save the time at which the message was sent
1394  context->retransmitStartTime = time;
1395  context->keepAliveTimestamp = time;
1396 
1397  //Update MQTT-SN client state
1398  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1399  context->msgType = MQTT_SN_MSG_TYPE_PUBREL;
1400  }
1401 
1402  //Return status code
1403  return error;
1404 }
1405 
1406 
1407 /**
1408  * @brief Send PUBCOMP message
1409  * @param[in] context Pointer to the MQTT-SN client context
1410  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1411  * @return Error code
1412  **/
1413 
1415 {
1416  error_t error;
1417 
1418  //Format PUBCOMP message
1419  error = mqttSnFormatPubComp(&context->message, msgId);
1420 
1421  //Check status code
1422  if(!error)
1423  {
1424  //Debug message
1425  TRACE_INFO("Sending PUBCOMP message (%" PRIuSIZE " bytes)...\r\n",
1426  context->message.length);
1427 
1428  //Dump the contents of the message for debugging purpose
1429  mqttSnDumpMessage(context->message.buffer, context->message.length);
1430 
1431  //Send MQTT-SN message
1432  error = mqttSnClientSendDatagram(context, context->message.buffer,
1433  context->message.length);
1434  }
1435 
1436  //Return status code
1437  return error;
1438 }
1439 
1440 
1441 /**
1442  * @brief Send SUBSCRIBE message
1443  * @param[in] context Pointer to the MQTT-SN client context
1444  * @param[in] topicName Topic filter
1445  * @param[in] qos Maximum QoS level at which the server can send application
1446  * messages to the client
1447  * @return Error code
1448  **/
1449 
1452 {
1453  error_t error;
1454  systime_t time;
1455  uint16_t topicId;
1457 
1458  //Initialize status code
1459  error = NO_ERROR;
1460 
1461  //Reset unused flags
1462  flags.all = 0;
1463  //Set QoS level
1464  flags.qos = qos;
1465 
1466  //Check whether a predefined topic ID has been registered
1468 
1469  //Predefined topic ID found?
1471  {
1472  //The SUBSCRIBE message contains a predefined topic ID
1473  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1474  }
1475  else
1476  {
1477  //Short topic name?
1479  {
1480  //The SUBSCRIBE message contains a short topic name
1481  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1482  }
1483  else
1484  {
1485  //The SUBSCRIBE message contains a normal topic name
1486  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1487  }
1488 
1489  //Format SUBSCRIBE message
1490  error = mqttSnFormatSubscribe(&context->message, flags,
1491  context->msgId, topicId, topicName);
1492  }
1493 
1494  //Check status code
1495  if(!error)
1496  {
1497  //Debug message
1498  TRACE_INFO("Sending SUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1499  context->message.length);
1500 
1501  //Dump the contents of the message for debugging purpose
1502  mqttSnDumpMessage(context->message.buffer, context->message.length);
1503 
1504  //Send MQTT-SN message
1505  error = mqttSnClientSendDatagram(context, context->message.buffer,
1506  context->message.length);
1507 
1508  //Get current time
1509  time = osGetSystemTime();
1510 
1511  //Save the time at which the message was sent
1512  context->retransmitStartTime = time;
1513  context->keepAliveTimestamp = time;
1514 
1515  //Update MQTT-SN client state
1516  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1517  context->msgType = MQTT_SN_MSG_TYPE_SUBSCRIBE;
1518  }
1519 
1520  //Return status code
1521  return error;
1522 }
1523 
1524 
1525 /**
1526  * @brief Send UNSUBSCRIBE message
1527  * @param[in] context Pointer to the MQTT-SN client context
1528  * @param[in] topicName Topic filter
1529  * @return Error code
1530  **/
1531 
1533  const char_t *topicName)
1534 {
1535  error_t error;
1536  systime_t time;
1537  uint16_t topicId;
1539 
1540  //Initialize status code
1541  error = NO_ERROR;
1542 
1543  //Reset unused flags
1544  flags.all = 0;
1545 
1546  //Check whether a predefined topic ID has been registered
1548 
1549  //Predefined topic ID found?
1551  {
1552  //The UNSUBSCRIBE message contains a predefined topic ID
1553  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1554  }
1555  else
1556  {
1557  //Short topic name?
1558  if(strlen(topicName) == 2 && strchr(topicName, '#') == NULL &&
1559  strchr(topicName, '+') == NULL)
1560  {
1561  //The UNSUBSCRIBE message contains a short topic name
1562  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1563  }
1564  else
1565  {
1566  //The UNSUBSCRIBE message contains a normal topic name
1567  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1568  }
1569 
1570  //Format UNSUBSCRIBE message
1571  error = mqttSnFormatUnsubscribe(&context->message, flags,
1572  context->msgId, topicId, topicName);
1573  }
1574 
1575  //Check status code
1576  if(!error)
1577  {
1578  //Debug message
1579  TRACE_INFO("Sending UNSUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1580  context->message.length);
1581 
1582  //Dump the contents of the message for debugging purpose
1583  mqttSnDumpMessage(context->message.buffer, context->message.length);
1584 
1585  //Send MQTT-SN message
1586  error = mqttSnClientSendDatagram(context, context->message.buffer,
1587  context->message.length);
1588 
1589  //Get current time
1590  time = osGetSystemTime();
1591 
1592  //Save the time at which the message was sent
1593  context->retransmitStartTime = time;
1594  context->keepAliveTimestamp = time;
1595 
1596  //Update MQTT-SN client state
1597  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1598  context->msgType = MQTT_SN_MSG_TYPE_UNSUBSCRIBE;
1599  }
1600 
1601  //Return status code
1602  return error;
1603 }
1604 
1605 
1606 /**
1607  * @brief Send PINGREQ message
1608  * @param[in] context Pointer to the MQTT-SN client context
1609  * @return Error code
1610  **/
1611 
1613 {
1614  error_t error;
1615 
1616  //Format PINGREQ message
1617  error = mqttSnFormatPingReq(&context->message, context->clientId);
1618 
1619  //Check status code
1620  if(!error)
1621  {
1622  //Debug message
1623  TRACE_INFO("Sending PINGREQ message (%" PRIuSIZE " bytes)...\r\n",
1624  context->message.length);
1625 
1626  //Dump the contents of the message for debugging purpose
1627  mqttSnDumpMessage(context->message.buffer, context->message.length);
1628 
1629  //Send MQTT-SN message
1630  error = mqttSnClientSendDatagram(context, context->message.buffer,
1631  context->message.length);
1632 
1633  //Save the time at which the message was sent
1634  context->keepAliveTimestamp = osGetSystemTime();
1635  }
1636 
1637  //Return status code
1638  return error;
1639 }
1640 
1641 
1642 /**
1643  * @brief Send PINGRESP message
1644  * @param[in] context Pointer to the MQTT-SN client context
1645  * @return Error code
1646  **/
1647 
1649 {
1650  error_t error;
1651 
1652  //Format PINGRESP message
1653  error = mqttSnFormatPingResp(&context->message);
1654 
1655  //Check status code
1656  if(!error)
1657  {
1658  //Debug message
1659  TRACE_INFO("Sending PINGRESP message (%" PRIuSIZE " bytes)...\r\n",
1660  context->message.length);
1661 
1662  //Dump the contents of the message for debugging purpose
1663  mqttSnDumpMessage(context->message.buffer, context->message.length);
1664 
1665  //Send MQTT-SN message
1666  error = mqttSnClientSendDatagram(context, context->message.buffer,
1667  context->message.length);
1668  }
1669 
1670  //Return status code
1671  return error;
1672 }
1673 
1674 
1675 /**
1676  * @brief Send DISCONNECT message
1677  * @param[in] context Pointer to the MQTT-SN client context
1678  * @param[in] duration Value of the sleep timer
1679  * @return Error code
1680  **/
1681 
1683  uint16_t duration)
1684 {
1685  error_t error;
1686 
1687  //Format DISCONNECT message
1688  error = mqttSnFormatDisconnect(&context->message, duration);
1689 
1690  //Check status code
1691  if(!error)
1692  {
1693  //Debug message
1694  TRACE_INFO("Sending DISCONNECT message (%" PRIuSIZE " bytes)...\r\n",
1695  context->message.length);
1696 
1697  //Dump the contents of the message for debugging purpose
1698  mqttSnDumpMessage(context->message.buffer, context->message.length);
1699 
1700  //Send MQTT-SN message
1701  error = mqttSnClientSendDatagram(context, context->message.buffer,
1702  context->message.length);
1703 
1704  //Save the time at which the message was sent
1705  context->retransmitStartTime = osGetSystemTime();
1706 
1707  //Update MQTT-SN client state
1708  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1709  context->msgType = MQTT_SN_MSG_TYPE_DISCONNECT;
1710  }
1711 
1712  //Return status code
1713  return error;
1714 }
1715 
1716 
1717 /**
1718  * @brief Send WILLTOPICUPD message
1719  * @param[in] context Pointer to the MQTT-SN client context
1720  * @return Error code
1721  **/
1722 
1724 {
1725  error_t error;
1726  systime_t time;
1727 
1728  //Format WILLTOPICUPD message
1729  error = mqttSnFormatWillTopicUpd(&context->message,
1730  context->willMessage.flags, context->willMessage.topic);
1731 
1732  //Check status code
1733  if(!error)
1734  {
1735  //Debug message
1736  TRACE_INFO("Sending WILLTOPICUPD message (%" PRIuSIZE " bytes)...\r\n",
1737  context->message.length);
1738 
1739  //Dump the contents of the message for debugging purpose
1740  mqttSnDumpMessage(context->message.buffer, context->message.length);
1741 
1742  //Send MQTT-SN message
1743  error = mqttSnClientSendDatagram(context, context->message.buffer,
1744  context->message.length);
1745 
1746  //Get current time
1747  time = osGetSystemTime();
1748 
1749  //Save the time at which the message was sent
1750  context->retransmitStartTime = time;
1751  context->keepAliveTimestamp = time;
1752 
1753  //Update MQTT-SN client state
1754  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1755  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICUPD;
1756  }
1757 
1758  //Return status code
1759  return error;
1760 }
1761 
1762 
1763 /**
1764  * @brief Send WILLMSGUPD message
1765  * @param[in] context Pointer to the MQTT-SN client context
1766  * @return Error code
1767  **/
1768 
1770 {
1771  error_t error;
1772  systime_t time;
1773 
1774  //Format WILLMSGUPD message
1775  error = mqttSnFormatWillMsgUpd(&context->message,
1776  context->willMessage.payload, context->willMessage.length);
1777 
1778  //Check status code
1779  if(!error)
1780  {
1781  //Debug message
1782  TRACE_INFO("Sending WILLMSGUPD message (%" PRIuSIZE " bytes)...\r\n",
1783  context->message.length);
1784 
1785  //Dump the contents of the message for debugging purpose
1786  mqttSnDumpMessage(context->message.buffer, context->message.length);
1787 
1788  //Send MQTT-SN message
1789  error = mqttSnClientSendDatagram(context, context->message.buffer,
1790  context->message.length);
1791 
1792  //Get current time
1793  time = osGetSystemTime();
1794 
1795  //Save the time at which the message was sent
1796  context->retransmitStartTime = time;
1797  context->keepAliveTimestamp = time;
1798 
1799  //Update MQTT-SN client state
1800  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1801  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGUPD;
1802  }
1803 
1804  //Return status code
1805  return error;
1806 }
1807 
1808 #endif
error_t mqttSnClientProcessWillMsgReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLMSGREQ message.
uint8_t length
Definition: dtls_misc.h:149
error_t mqttSnFormatSearchGw(MqttSnMessage *message, uint8_t radius)
Format SEARCHGW message.
error_t mqttSnClientSendPubRel(MqttSnClientContext *context, uint16_t msgId)
Send PUBREL message.
error_t mqttSnParseRegister(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, const char_t **topicName)
Parse REGISTER message.
error_t mqttSnFormatPublish(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName, const uint8_t *data, size_t dataLen)
Format PUBLISH message.
error_t mqttSnFormatPubRel(MqttSnMessage *message, uint16_t msgId)
Format PUBREL message.
int bool_t
Definition: compiler_port.h:49
@ ERROR_NOT_FOUND
Definition: error.h:145
error_t mqttSnFormatPingResp(MqttSnMessage *message)
Format PINGRESP message.
@ MQTT_SN_MSG_TYPE_PINGRESP
error_t mqttSnFormatPingReq(MqttSnMessage *message, const char_t *clientId)
Format PINGREQ message.
error_t mqttSnParseWillTopicReq(const MqttSnMessage *message)
Parse WILLTOPICREQ message.
error_t mqttSnFormatUnsubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format UNSUBSCRIBE message.
@ MQTT_SN_MSG_TYPE_REGISTER
@ MQTT_SN_SHORT_TOPIC_NAME
Short topic name.
IP network address.
Definition: ip.h:71
@ MQTT_SN_MSG_TYPE_PINGREQ
error_t mqttSnFormatWillMsg(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSG message.
error_t mqttSnFormatConnect(MqttSnMessage *message, MqttSnFlags flags, uint16_t duration, const char_t *clientId)
Format CONNECT message.
error_t mqttSnClientProcessConnAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming CONNACK message.
error_t mqttSnClientSendDisconnect(MqttSnClientContext *context, uint16_t duration)
Send DISCONNECT message.
@ MQTT_SN_MSG_TYPE_CONNECT
error_t mqttSnParseWillMsgResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLMSGRESP message.
error_t mqttSnClientSendRegister(MqttSnClientContext *context, const char_t *topicName)
Send REGISTER message.
#define MqttSnClientContext
#define TRUE
Definition: os_port.h:50
@ MQTT_SN_QOS_LEVEL_1
At least once delivery.
error_t mqttSnClientSendPubAck(MqttSnClientContext *context, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Send PUBACK message.
MqttSnReturnCode
MQTT-SN return codes.
error_t mqttSnClientSendSubscribe(MqttSnClientContext *context, const char_t *topicName, MqttSnQosLevel qos)
Send SUBSCRIBE message.
@ MQTT_SN_PREDEFINED_TOPIC_ID
Predefined topic ID.
error_t mqttSnParsePublish(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, const uint8_t **data, size_t *dataLen)
Parse PUBLISH message.
MqttSnQosLevel
Quality of service level.
error_t mqttSnFormatWillTopic(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPIC message.
@ MQTT_SN_NORMAL_TOPIC_NAME
Normal topic name.
error_t mqttSnParseRegAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse REGACK message.
error_t mqttSnClientProcessMessage(MqttSnClientContext *context, MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
Process incoming MQTT-SN message.
error_t mqttSnClientProcessGwInfo(MqttSnClientContext *context, const MqttSnMessage *message, const IpAddr *ipAddr, uint16_t port)
Process incoming GWINFO message.
error_t mqttSnClientSendSearchGw(MqttSnClientContext *context, uint8_t radius, const IpAddr *destIpAddr, uint16_t destPort)
Send SEARCHGW message.
@ MQTT_SN_MSG_TYPE_GWINFO
error_t mqttSnClientSendUnsubscribe(MqttSnClientContext *context, const char_t *topicName)
Send UNSUBSCRIBE message.
uint16_t msgId
@ MQTT_SN_RETURN_CODE_REJECTED_CONGESTION
@ MQTT_SN_MSG_TYPE_WILLTOPICRESP
uint16_t destPort
Definition: tcp.h:303
uint8_t qos
Definition: mqtt_common.h:179
MQTT-SN message parsing and formatting.
uint16_t topicId
@ MQTT_SN_MSG_TYPE_PUBREL
error_t mqttSnParseWillTopicResp(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse WILLTOPICRESP message.
error_t mqttSnClientSendRegAck(MqttSnClientContext *context, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Send REGACK message.
error_t mqttSnParseDisconnect(const MqttSnMessage *message, uint16_t *duration)
Parse DISCONNECT message.
uint8_t returnCode
error_t mqttSnFormatWillTopicUpd(MqttSnMessage *message, MqttSnFlags flags, const char_t *topicName)
Format WILLTOPICUPD message.
@ MQTT_SN_CLIENT_STATE_SENDING_REQ
uint8_t gwAdd[]
__start_packed struct @232 MqttSnFlags
MQTT-SN flags.
@ MQTT_SN_MSG_TYPE_WILLTOPICREQ
error_t mqttSnClientSendPingReq(MqttSnClientContext *context)
Send PINGREQ message.
@ MQTT_SN_MSG_TYPE_WILLMSGREQ
uint16_t mqttSnClientFindTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a given topic name.
@ MQTT_SN_CLIENT_STATE_SEARCHING
error_t mqttSnFormatPubAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format PUBACK message.
error_t mqttSnFormatDisconnect(MqttSnMessage *message, uint16_t duration)
Format DISCONNECT message.
bool_t mqttSnClientIsDuplicateMessageId(MqttSnClientContext *context, uint16_t msgId)
Check whether the message ID is a duplicate (QoS 2 message processing)
error_t mqttSnClientSendPingResp(MqttSnClientContext *context)
Send PINGRESP message.
error_t mqttSnClientProcessSubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming SUBACK message.
@ MQTT_SN_NORMAL_TOPIC_ID
Normal topic ID.
error_t mqttSnClientAddTopic(MqttSnClientContext *context, const char_t *topicName, uint16_t topicId)
Add a new entry to the topic table.
error_t mqttSnParseWillMsgReq(const MqttSnMessage *message)
Parse WILLMSGREQ message.
error_t mqttSnClientProcessPublish(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBLISH message.
error_t mqttSnFormatPubComp(MqttSnMessage *message, uint16_t msgId)
Format PUBCOMP message.
error_t mqttSnFormatSubscribe(MqttSnMessage *message, MqttSnFlags flags, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format SUBSCRIBE message.
error_t mqttSnParseHeader(MqttSnMessage *message, MqttSnMsgType *type)
Format MQTT-SN message header.
char_t type
error_t mqttSnParseConnAck(const MqttSnMessage *message, MqttSnReturnCode *returnCode)
Parse CONNACK message.
error_t mqttSnParseUnsubAck(const MqttSnMessage *message, uint16_t *msgId)
Parse UNSUBACK message.
error_t
Error codes.
Definition: error.h:42
@ MQTT_SN_MSG_TYPE_PUBREC
error_t mqttSnClientSendPubComp(MqttSnClientContext *context, uint16_t msgId)
Send PUBCOMP message.
error_t mqttSnClientProcessPingReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PINGREQ message.
uint8_t radius
@ MQTT_SN_MSG_TYPE_WILLTOPICUPD
uint8_t retain
Definition: mqtt_common.h:178
error_t mqttSnParseGwInfo(const MqttSnMessage *message, uint8_t *gwId, const uint8_t **gwAdd, size_t *gwAddLen)
Parse GWINFO message.
error_t mqttSnClientSendDatagram(MqttSnClientContext *context, const void *data, size_t length)
Send a datagram.
@ MQTT_SN_MSG_TYPE_SUBSCRIBE
error_t mqttSnClientSendWillMsgUpd(MqttSnClientContext *context)
Send WILLMSGUPD message.
@ MQTT_SN_MSG_TYPE_PUBLISH
@ MQTT_SN_MSG_TYPE_WILLMSGRESP
bool_t mqttSnClientIsShortTopicName(const char_t *topicName)
Check whether a topic name is a short topic name.
error_t mqttSnFormatRegAck(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, MqttSnReturnCode returnCode)
Format REGACK message.
error_t mqttSnClientProcessUnsubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming UNSUBACK message.
@ MQTT_SN_MSG_TYPE_PUBCOMP
error_t mqttSnClientProcessRegister(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming REGISTER message.
@ MQTT_SN_MSG_TYPE_DISCONNECT
error_t mqttSnClientProcessPubAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBACK message.
char_t topicName[]
error_t mqttSnClientProcessPubRel(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBREL message.
MqttSnReturnCode mqttSnDeliverPublishMessage(MqttSnClientContext *context, MqttSnFlags flags, uint16_t topicId, const uint8_t *data, size_t dataLen)
Deliver a PUBLISH message to the application.
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_INVALID_TYPE
Definition: error.h:113
#define TRACE_INFO(...)
Definition: debug.h:94
@ MQTT_SN_CLIENT_STATE_RESP_RECEIVED
@ MQTT_SN_CLIENT_STATE_DISCONNECTING
error_t mqttSnParsePingResp(const MqttSnMessage *message)
Parse PINGRESP message.
error_t mqttSnClientProcessRegAck(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming REGACK message.
error_t mqttSnParseSubAck(const MqttSnMessage *message, MqttSnFlags *flags, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse SUBACK message.
error_t mqttSnClientProcessPubComp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBCOMP message.
Helper functions for MQTT-SN client.
@ MQTT_SN_MSG_TYPE_REGACK
error_t mqttSnFormatPubRec(MqttSnMessage *message, uint16_t msgId)
Format PUBREC message.
uint16_t port
Definition: dns_common.h:223
uint8_t gwId
uint16_t duration
uint8_t flags
Definition: tcp.h:314
#define TRACE_WARNING(...)
Definition: debug.h:84
const char_t * mqttSnGetMessageName(uint16_t msgType)
Get the name of the specified MQTT-SN message.
char char_t
Definition: compiler_port.h:43
MqttSnMsgType
MQTT-SN message types.
error_t mqttSnClientProcessPingResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PINGRESP message.
uint32_t time
Transport protocol abstraction layer.
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:107
error_t mqttSnClientProcessWillTopicReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLTOPICREQ message.
@ MQTT_SN_MSG_TYPE_WILLMSGUPD
error_t mqttSnClientProcessDisconnect(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming DISCONNECT message.
error_t mqttSnDumpMessage(const uint8_t *message, size_t length)
Dump MQTT-SN message for debugging purpose.
Definition: mqtt_sn_debug.c:95
uint16_t mqttSnClientFindPredefTopicName(MqttSnClientContext *context, const char_t *topicName)
Retrieve the topic ID associated with a predefined topic name.
error_t mqttSnParsePubRel(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREL message.
@ MQTT_SN_RETURN_CODE_ACCEPTED
MQTT-SN message.
uint8_t cleanSession
error_t mqttSnClientSendPubRec(MqttSnClientContext *context, uint16_t msgId)
Send PUBREC message.
error_t mqttSnFormatRegister(MqttSnMessage *message, uint16_t msgId, uint16_t topicId, const char_t *topicName)
Format REGISTER message.
error_t mqttSnClientStoreMessageId(MqttSnClientContext *context, uint16_t msgId)
Store message ID (QoS 2 message processing)
uint8_t message[]
Definition: chap.h:152
@ MQTT_SN_MSG_TYPE_UNSUBACK
uint8_t dup
Definition: mqtt_common.h:180
@ MQTT_SN_CLIENT_STATE_ACTIVE
error_t mqttSnClientSendWillMsg(MqttSnClientContext *context)
Send WILLMSG message.
error_t mqttSnClientBroadcastDatagram(MqttSnClientContext *context, const IpAddr *destIpAddr, uint16_t destPort, const void *data, size_t length)
Broadcast a datagram.
error_t mqttSnClientProcessWillTopicResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLTOPICRESP message.
MQTT-SN message formatting and parsing.
MQTT-SN client.
char_t clientId[]
error_t mqttSnClientSendWillTopicUpd(MqttSnClientContext *context)
Send WILLTOPICUPD message.
error_t mqttSnFormatWillMsgUpd(MqttSnMessage *message, const void *data, size_t dataLen)
Format WILLMSGUPD message.
error_t mqttSnParsePubRec(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBREC message.
error_t mqttSnParsePubAck(const MqttSnMessage *message, uint16_t *msgId, uint16_t *topicId, MqttSnReturnCode *returnCode)
Parse PUBACK message.
error_t mqttSnParsePingReq(const MqttSnMessage *message, const char_t **clientId)
Parse PINGREQ message.
#define PRIuSIZE
Definition: compiler_port.h:78
TCP/IP stack core.
uint8_t data[]
Definition: dtls_misc.h:176
@ MQTT_SN_MSG_TYPE_UNSUBSCRIBE
error_t mqttSnClientProcessPubRec(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBREC message.
Data logging functions for debugging purpose (MQTT-SN)
error_t mqttSnParsePubComp(const MqttSnMessage *message, uint16_t *msgId)
Parse PUBCOMP message.
error_t mqttSnClientProcessWillMsgResp(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLMSGRESP message.
@ MQTT_SN_MSG_TYPE_CONNACK
@ MQTT_SN_QOS_LEVEL_2
Exactly once delivery.
error_t mqttSnClientDiscardMessageId(MqttSnClientContext *context, uint16_t msgId)
Discard message ID (QoS 2 message processing)
uint32_t systime_t
Definition: compiler_port.h:46
uint8_t ipAddr[4]
Definition: mib_common.h:187
#define MQTT_SN_INVALID_TOPIC_ID
@ NO_ERROR
Success.
Definition: error.h:44
@ MQTT_SN_MSG_TYPE_PUBACK
Debugging facilities.
@ MQTT_SN_MSG_TYPE_SUBACK
error_t mqttSnClientSendWillTopic(MqttSnClientContext *context)
Send WILLTOPIC message.
error_t mqttSnClientSendConnect(MqttSnClientContext *context, bool_t cleanSession)
Send CONNECT message.
systime_t osGetSystemTime(void)
Retrieve system time.
Ipv4Addr destIpAddr
Definition: ipcp.h:78