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 formatting and parsing
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.4
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)
351  {
353  }
354  else
355  {
357  }
358 
359  //The client sends a REGACK message to acknowledge the receipt and
360  //processing of a REGISTER message
361  error = mqttSnClientSendRegAck(context, msgId, topicId, returnCode);
362  }
363 
364  //Return status code
365  return error;
366 }
367 
368 
369 /**
370  * @brief Process incoming REGACK message
371  * @param[in] context Pointer to the MQTT-SN client context
372  * @param[in] message Pointer to the received MQTT-SN message
373  * @return Error code
374  **/
375 
377  const MqttSnMessage *message)
378 {
379  error_t error;
380  uint16_t msgId;
381  uint16_t topicId;
383 
384  //Parse REGACK message
386 
387  //Valid message received?
388  if(!error)
389  {
390  //Check current state
391  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
392  context->msgType == MQTT_SN_MSG_TYPE_REGISTER &&
393  context->msgId == msgId)
394  {
395  //Notify the application that a REGACK message has been received
396  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
397  context->msgType = MQTT_SN_MSG_TYPE_REGACK;
398  context->topicId = topicId;
399  context->returnCode = returnCode;
400 
401  //The MQTT-SN gateway is alive
402  context->keepAliveCounter = 0;
403  }
404  }
405 
406  //Return status code
407  return error;
408 }
409 
410 
411 /**
412  * @brief Process incoming PUBLISH message
413  * @param[in] context Pointer to the MQTT-SN client context
414  * @param[in] message Pointer to the received MQTT-SN message
415  * @return Error code
416  **/
417 
419  const MqttSnMessage *message)
420 {
421  error_t error;
422  bool_t duplicate;
423  uint16_t msgId;
424  uint16_t topicId;
425  const uint8_t *data;
426  size_t dataLen;
429 
430  //Parse PUBLISH message
432  &data, &dataLen);
433 
434  //Valid message received?
435  if(!error)
436  {
437  //Check QoS level
438  if(flags.qos == MQTT_SN_QOS_LEVEL_1)
439  {
440  //Deliver the message to the application
442  data, dataLen);
443 
444  //A PUBACK packet is the response to a PUBLISH packet with QoS level 1
445  error = mqttSnClientSendPubAck(context, msgId, topicId, returnCode);
446  }
447  else if(flags.qos == MQTT_SN_QOS_LEVEL_2)
448  {
449  //Check whether the ownership of the QoS 2 message has already been
450  //transferred to the client
451  duplicate = mqttSnClientIsDuplicateMessageId(context, msgId);
452 
453  //Duplicate message?
454  if(duplicate)
455  {
456  //In QoS 2, the receiver must not cause duplicate messages to be
457  //delivered to any onward recipients
458  error = mqttSnClientSendPubRec(context, msgId);
459  }
460  else
461  {
462  //Accept the ownership of the QoS 2 message
463  error = mqttSnClientStoreMessageId(context, msgId);
464 
465  //Check status code
466  if(!error)
467  {
468  //Initiate onward delivery of the application message
470  data, dataLen);
471  }
472  else
473  {
474  //The message identifier cannot be saved
476  }
477 
478  //Check whether the PUBLISH message has been accepted
480  {
481  //A PUBREC packet is the response to a PUBLISH packet with QoS 2.
482  //It is the second packet of the QoS 2 protocol exchange
483  error = mqttSnClientSendPubRec(context, msgId);
484  }
485  else
486  {
487  //Discard message identifier
489 
490  //Reject the PUBLISH message
491  error = mqttSnClientSendPubAck(context, msgId, topicId,
492  returnCode);
493  }
494  }
495  }
496  else
497  {
498  //Deliver the message to the application
500  data, dataLen);
501 
502  //In QoS 0, the receiver always accepts the message
503  error = NO_ERROR;
504  }
505  }
506 
507  //Return status code
508  return error;
509 }
510 
511 
512 /**
513  * @brief Process incoming PUBACK message
514  * @param[in] context Pointer to the MQTT-SN client context
515  * @param[in] message Pointer to the received MQTT-SN message
516  * @return Error code
517  **/
518 
520  const MqttSnMessage *message)
521 {
522  error_t error;
523  uint16_t msgId;
524  uint16_t topicId;
526 
527  //Parse PUBACK message
529 
530  //Valid message received?
531  if(!error)
532  {
533  //Check current state
534  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
535  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
536  context->msgId == msgId)
537  {
538  //Notify the application that a PUBACK message has been received
539  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
540  context->msgType = MQTT_SN_MSG_TYPE_PUBACK;
541  context->returnCode = returnCode;
542 
543  //The MQTT-SN gateway is alive
544  context->keepAliveCounter = 0;
545  }
546  }
547 
548  //Return status code
549  return error;
550 }
551 
552 
553 /**
554  * @brief Process incoming PUBREC message
555  * @param[in] context Pointer to the MQTT-SN client context
556  * @param[in] message Pointer to the received MQTT-SN message
557  * @return Error code
558  **/
559 
561  const MqttSnMessage *message)
562 {
563  error_t error;
564  uint16_t msgId;
565 
566  //Parse PUBREC message
567  error = mqttSnParsePubRec(message, &msgId);
568 
569  //Valid message received?
570  if(!error)
571  {
572  //Check current state
573  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
574  context->msgType == MQTT_SN_MSG_TYPE_PUBLISH &&
575  context->msgId == msgId)
576  {
577  //Notify the application that a PUBREC message has been received
578  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
579  context->msgType = MQTT_SN_MSG_TYPE_PUBREC;
580 
581  //The MQTT-SN gateway is alive
582  context->keepAliveCounter = 0;
583  }
584  }
585 
586  //Return status code
587  return error;
588 }
589 
590 
591 /**
592  * @brief Process incoming PUBREL message
593  * @param[in] context Pointer to the MQTT-SN client context
594  * @param[in] message Pointer to the received MQTT-SN message
595  * @return Error code
596  **/
597 
599  const MqttSnMessage *message)
600 {
601  error_t error;
602  uint16_t msgId;
603 
604  //Parse PUBREL message
605  error = mqttSnParsePubRel(message, &msgId);
606 
607  //Valid message received?
608  if(!error)
609  {
610  //Discard message identifier
612 
613  //A PUBCOMP message is the response to a PUBREL packet. It is the fourth
614  //and final message of the QoS 2 protocol exchange
615  error = mqttSnClientSendPubComp(context, msgId);
616  }
617 
618  //Return status code
619  return error;
620 }
621 
622 
623 /**
624  * @brief Process incoming PUBCOMP message
625  * @param[in] context Pointer to the MQTT-SN client context
626  * @param[in] message Pointer to the received MQTT-SN message
627  * @return Error code
628  **/
629 
631  const MqttSnMessage *message)
632 {
633  error_t error;
634  uint16_t msgId;
635 
636  //Parse PUBCOMP message
637  error = mqttSnParsePubComp(message, &msgId);
638 
639  //Valid message received?
640  if(!error)
641  {
642  //Check current state
643  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
644  context->msgType == MQTT_SN_MSG_TYPE_PUBREL &&
645  context->msgId == msgId)
646  {
647  //Notify the application that a PUBCOMP message has been received
648  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
649  context->msgType = MQTT_SN_MSG_TYPE_PUBCOMP;
650 
651  //The MQTT-SN gateway is alive
652  context->keepAliveCounter = 0;
653  }
654  }
655 
656  //Return status code
657  return error;
658 }
659 
660 
661 /**
662  * @brief Process incoming SUBACK message
663  * @param[in] context Pointer to the MQTT-SN client context
664  * @param[in] message Pointer to the received MQTT-SN message
665  * @return Error code
666  **/
667 
669  const MqttSnMessage *message)
670 {
671  error_t error;
672  uint16_t msgId;
673  uint16_t topicId;
676 
677  //Parse SUBACK message
679 
680  //Valid message received?
681  if(!error)
682  {
683  //Check current state
684  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
685  context->msgType == MQTT_SN_MSG_TYPE_SUBSCRIBE &&
686  context->msgId == msgId)
687  {
688  //Notify the application that a SUBACK message has been received
689  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
690  context->msgType = MQTT_SN_MSG_TYPE_SUBACK;
691  context->topicId = topicId;
692  context->returnCode = returnCode;
693 
694  //The MQTT-SN gateway is alive
695  context->keepAliveCounter = 0;
696  }
697  }
698 
699  //Return status code
700  return error;
701 }
702 
703 
704 /**
705  * @brief Process incoming UNSUBACK message
706  * @param[in] context Pointer to the MQTT-SN client context
707  * @param[in] message Pointer to the received MQTT-SN message
708  * @return Error code
709  **/
710 
712  const MqttSnMessage *message)
713 {
714  error_t error;
715  uint16_t msgId;
716 
717  //Parse UNSUBACK message
718  error = mqttSnParseUnsubAck(message, &msgId);
719 
720  //Valid message received?
721  if(!error)
722  {
723  //Check current state
724  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
725  context->msgType == MQTT_SN_MSG_TYPE_UNSUBSCRIBE &&
726  context->msgId == msgId)
727  {
728  //Notify the application that a UNSUBACK message has been received
729  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
730  context->msgType = MQTT_SN_MSG_TYPE_UNSUBACK;
731 
732  //The MQTT-SN gateway is alive
733  context->keepAliveCounter = 0;
734  }
735  }
736 
737  //Return status code
738  return error;
739 }
740 
741 
742 /**
743  * @brief Process incoming PINGREQ message
744  * @param[in] context Pointer to the MQTT-SN client context
745  * @param[in] message Pointer to the received MQTT-SN message
746  * @return Error code
747  **/
748 
750  const MqttSnMessage *message)
751 {
752  error_t error;
753  const char_t *clientId;
754 
755  //Parse PINGREQ message
757 
758  //Valid message received?
759  if(!error)
760  {
761  //A client shall answer with a PINGRESP message when it receives a
762  //PINGREQ message from the GW to which it is connected
763  error = mqttSnClientSendPingResp(context);
764  }
765 
766  //Return status code
767  return error;
768 }
769 
770 
771 /**
772  * @brief Process incoming PINGRESP message
773  * @param[in] context Pointer to the MQTT-SN client context
774  * @param[in] message Pointer to the received MQTT-SN message
775  * @return Error code
776  **/
777 
779  const MqttSnMessage *message)
780 {
781  error_t error;
782 
783  //Parse PINGRESP message
784  error = mqttSnParsePingResp(message);
785 
786  //Valid message received?
787  if(!error)
788  {
789  //Check current state
790  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
791  context->msgType == MQTT_SN_MSG_TYPE_PINGREQ)
792  {
793  //Notify the application that a PINGRESP message has been received
794  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
795  context->msgType = MQTT_SN_MSG_TYPE_PINGRESP;
796  }
797 
798  //The MQTT-SN gateway is alive
799  context->keepAliveCounter = 0;
800  }
801 
802  //Return status code
803  return error;
804 }
805 
806 
807 /**
808  * @brief Process incoming DISCONNECT message
809  * @param[in] context Pointer to the MQTT-SN client context
810  * @param[in] message Pointer to the received MQTT-SN message
811  * @return Error code
812  **/
813 
815  const MqttSnMessage *message)
816 {
817  error_t error;
818  uint16_t duration;
819 
820  //Parse DISCONNECT message
822 
823  //Valid message received?
824  if(!error)
825  {
826  //The gateway indicates that it wants to close the connection
827  context->state = MQTT_SN_CLIENT_STATE_DISCONNECTING;
828  }
829 
830  //Return status code
831  return error;
832 }
833 
834 
835 /**
836  * @brief Process incoming WILLTOPICRESP message
837  * @param[in] context Pointer to the MQTT-SN client context
838  * @param[in] message Pointer to the received MQTT-SN message
839  * @return Error code
840  **/
841 
843  const MqttSnMessage *message)
844 {
845  error_t error;
847 
848  //Parse WILLTOPICRESP message
850 
851  //Valid message received?
852  if(!error)
853  {
854  //Check current state
855  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
856  context->msgType == MQTT_SN_MSG_TYPE_WILLTOPICUPD)
857  {
858  //Notify the application that a WILLTOPICRESP message has been received
859  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
860  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICRESP;
861  context->returnCode = returnCode;
862 
863  //The MQTT-SN gateway is alive
864  context->keepAliveCounter = 0;
865  }
866  }
867 
868  //Return status code
869  return error;
870 }
871 
872 
873 /**
874  * @brief Process incoming WILLMSGRESP message
875  * @param[in] context Pointer to the MQTT-SN client context
876  * @param[in] message Pointer to the received MQTT-SN message
877  * @return Error code
878  **/
879 
881  const MqttSnMessage *message)
882 {
883  error_t error;
885 
886  //Parse WILLMSGRESP message
888 
889  //Valid message received?
890  if(!error)
891  {
892  //Check current state
893  if(context->state == MQTT_SN_CLIENT_STATE_SENDING_REQ &&
894  context->msgType == MQTT_SN_MSG_TYPE_WILLMSGUPD)
895  {
896  //Notify the application that a WILLMSGRESP message has been received
897  context->state = MQTT_SN_CLIENT_STATE_RESP_RECEIVED;
898  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGRESP;
899  context->returnCode = returnCode;
900 
901  //The MQTT-SN gateway is alive
902  context->keepAliveCounter = 0;
903  }
904  }
905 
906  //Return status code
907  return error;
908 }
909 
910 
911 /**
912  * @brief Send SEARCHGW message
913  * @param[in] context Pointer to the MQTT-SN client context
914  * @param[in] radius Broadcast radius of SEARCHGW message
915  * @param[in] destIpAddr Destination IP address
916  * @param[in] destPort Destination port number
917  * @return Error code
918  **/
919 
921  const IpAddr *destIpAddr, uint16_t destPort)
922 {
923  error_t error;
924 
925  //Format SEARCHGW message
926  error = mqttSnFormatSearchGw(&context->message, radius);
927 
928  //Check status code
929  if(!error)
930  {
931  //Debug message
932  TRACE_INFO("Sending SEARCHGW message (%" PRIuSIZE " bytes)...\r\n",
933  context->message.length);
934 
935  //Dump the contents of the message for debugging purpose
936  mqttSnDumpMessage(context->message.buffer, context->message.length);
937 
938  //Send MQTT-SN message
940  context->message.buffer, context->message.length);
941 
942  //Save the time at which the message was sent
943  context->retransmitStartTime = osGetSystemTime();
944  }
945 
946  //Return status code
947  return error;
948 }
949 
950 
951 /**
952  * @brief Send CONNECT message
953  * @param[in] context Pointer to the MQTT-SN client context
954  * @param[in] cleanSession If this flag is set, then the client and server
955  * must discard any previous session and start a new one
956  * @return Error code
957  **/
958 
960  bool_t cleanSession)
961 {
962  error_t error;
963  systime_t time;
965 
966  //The flags contains a number of parameters specifying the behavior of
967  //the MQTT-SN connection
968  flags.all = 0;
969 
970  //If CleanSession is set to 1, the client and server must discard any
971  //previous session and start a new one
972  if(cleanSession)
973  flags.cleanSession = TRUE;
974 
975  //If the client supplies a zero-byte Client Identifier, the client must
976  //also set CleanSession to 1
977  if(context->clientId[0] == '\0')
978  flags.cleanSession = TRUE;
979 
980  //Check whether a valid Will message has been specified
981  if(context->willMessage.topic[0] != '\0')
982  flags.will = TRUE;
983 
984  //Format CONNECT message
985  error = mqttSnFormatConnect(&context->message, flags,
986  context->keepAlive / 1000, context->clientId);
987 
988  //Check status code
989  if(!error)
990  {
991  //Debug message
992  TRACE_INFO("Sending CONNECT message (%" PRIuSIZE " bytes)...\r\n",
993  context->message.length);
994 
995  //Dump the contents of the message for debugging purpose
996  mqttSnDumpMessage(context->message.buffer, context->message.length);
997 
998  //Send MQTT-SN message
999  error = mqttSnClientSendDatagram(context, context->message.buffer,
1000  context->message.length);
1001 
1002  //Get current time
1003  time = osGetSystemTime();
1004 
1005  //Save the time at which the message was sent
1006  context->retransmitStartTime = time;
1007  context->keepAliveTimestamp = time;
1008 
1009  //Update MQTT-SN client state
1010  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1011  context->msgType = MQTT_SN_MSG_TYPE_CONNECT;
1012  }
1013 
1014  //Return status code
1015  return error;
1016 }
1017 
1018 
1019 /**
1020  * @brief Send WILLTOPIC message
1021  * @param[in] context Pointer to the MQTT-SN client context
1022  * @return Error code
1023  **/
1024 
1026 {
1027  error_t error;
1028 
1029  //Format WILLTOPIC message
1030  error = mqttSnFormatWillTopic(&context->message,
1031  context->willMessage.flags, context->willMessage.topic);
1032 
1033  //Check status code
1034  if(!error)
1035  {
1036  //Debug message
1037  TRACE_INFO("Sending WILLTOPIC message (%" PRIuSIZE " bytes)...\r\n",
1038  context->message.length);
1039 
1040  //Dump the contents of the message for debugging purpose
1041  mqttSnDumpMessage(context->message.buffer, context->message.length);
1042 
1043  //Send MQTT-SN message
1044  error = mqttSnClientSendDatagram(context, context->message.buffer,
1045  context->message.length);
1046  }
1047 
1048  //Return status code
1049  return error;
1050 }
1051 
1052 
1053 /**
1054  * @brief Send WILLMSG message
1055  * @param[in] context Pointer to the MQTT-SN client context
1056  * @return Error code
1057  **/
1058 
1060 {
1061  error_t error;
1062 
1063  //Format WILLMSG message
1064  error = mqttSnFormatWillMsg(&context->message,
1065  context->willMessage.payload, context->willMessage.length);
1066 
1067  //Check status code
1068  if(!error)
1069  {
1070  //Debug message
1071  TRACE_INFO("Sending WILLMSG message (%" PRIuSIZE " bytes)...\r\n",
1072  context->message.length);
1073 
1074  //Dump the contents of the message for debugging purpose
1075  mqttSnDumpMessage(context->message.buffer, context->message.length);
1076 
1077  //Send MQTT-SN message
1078  error = mqttSnClientSendDatagram(context, context->message.buffer,
1079  context->message.length);
1080  }
1081 
1082  //Return status code
1083  return error;
1084 }
1085 
1086 
1087 /**
1088  * @brief Send REGISTER message
1089  * @param[in] context Pointer to the MQTT-SN client context
1090  * @param[in] topicName Topic name
1091  * @return Error code
1092  **/
1093 
1095  const char_t *topicName)
1096 {
1097  error_t error;
1098  systime_t time;
1099 
1100  //Format REGISTER message
1101  error = mqttSnFormatRegister(&context->message, context->msgId, 0,
1102  topicName);
1103 
1104  //Check status code
1105  if(!error)
1106  {
1107  //Debug message
1108  TRACE_INFO("Sending REGISTER message (%" PRIuSIZE " bytes)...\r\n",
1109  context->message.length);
1110 
1111  //Dump the contents of the message for debugging purpose
1112  mqttSnDumpMessage(context->message.buffer, context->message.length);
1113 
1114  //Send MQTT-SN message
1115  error = mqttSnClientSendDatagram(context, context->message.buffer,
1116  context->message.length);
1117 
1118  //Get current time
1119  time = osGetSystemTime();
1120 
1121  //Save the time at which the message was sent
1122  context->retransmitStartTime = time;
1123  context->keepAliveTimestamp = time;
1124 
1125  //Update MQTT-SN client state
1126  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1127  context->msgType = MQTT_SN_MSG_TYPE_REGISTER;
1128  }
1129 
1130  //Return status code
1131  return error;
1132 }
1133 
1134 
1135 /**
1136  * @brief Send REGACK message
1137  * @param[in] context Pointer to the MQTT-SN client context
1138  * @param[in] msgId Message identifier
1139  * @param[in] topicId Topic identifier
1140  * @param[in] returnCode Return code
1141  * @return Error code
1142  **/
1143 
1146 {
1147  error_t error;
1148 
1149  //Format REGACK message
1150  error = mqttSnFormatRegAck(&context->message, msgId, topicId, returnCode);
1151 
1152  //Check status code
1153  if(!error)
1154  {
1155  //Debug message
1156  TRACE_INFO("Sending REGACK message (%" PRIuSIZE " bytes)...\r\n",
1157  context->message.length);
1158 
1159  //Dump the contents of the message for debugging purpose
1160  mqttSnDumpMessage(context->message.buffer, context->message.length);
1161 
1162  //Send MQTT-SN message
1163  error = mqttSnClientSendDatagram(context, context->message.buffer,
1164  context->message.length);
1165  }
1166 
1167  //Return status code
1168  return error;
1169 }
1170 
1171 
1172 /**
1173  * @brief Send PUBLISH message
1174  * @param[in] context Pointer to the MQTT-SN client context
1175  * @param[in] msgId Message identifier
1176  * @param[in] topicName Short topic name
1177  * @param[in] data Message payload
1178  * @param[in] length Length of the message payload
1179  * @param[in] qos QoS level to be used when publishing the message
1180  * @param[in] retain This flag specifies if the message is to be retained
1181  * @param[in] dup This flag specifies if the message is sent for the first
1182  * time or if the message is retransmitted
1183  * @return Error code
1184  **/
1185 
1187  uint16_t msgId, const char_t *topicName, const uint8_t *data,
1188  size_t length, MqttSnQosLevel qos, bool_t retain, bool_t dup)
1189 {
1190  error_t error;
1191  systime_t time;
1192  uint16_t topicId;
1194 
1195  //Initialize status code
1196  error = NO_ERROR;
1197 
1198  //Reset unused flags
1199  flags.all = 0;
1200  //Set QoS level
1201  flags.qos = qos;
1202  //Set RETAIN flag
1203  flags.retain = retain;
1204  //set DUP flag
1205  flags.dup = dup;
1206 
1207  //Short topic name?
1209  {
1210  //The PUBLISH message contains a short topic name
1211  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1212  //The value of the topic ID is not relevant
1213  topicId = 0;
1214  }
1215  else
1216  {
1217  //Check whether a predefined topic ID has been registered
1219 
1220  //Predefined topic ID found?
1222  {
1223  //The PUBLISH message contains a predefined topic ID
1224  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1225  }
1226  else
1227  {
1228  //Check whether the topic name has been registered
1230 
1231  //Topic ID found?
1233  {
1234  //The PUBLISH message contains a normal topic ID
1235  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_ID;
1236  }
1237  else
1238  {
1239  //The topic name has not been registered
1240  error = ERROR_NOT_FOUND;
1241  }
1242  }
1243  }
1244 
1245  //Check status code
1246  if(!error)
1247  {
1248  //Format PUBLISH message
1249  error = mqttSnFormatPublish(&context->message, flags, msgId,
1251  }
1252 
1253  //Check status code
1254  if(!error)
1255  {
1256  //Debug message
1257  TRACE_INFO("Sending PUBLISH message (%" PRIuSIZE " bytes)...\r\n",
1258  context->message.length);
1259 
1260  //Dump the contents of the message for debugging purpose
1261  mqttSnDumpMessage(context->message.buffer, context->message.length);
1262 
1263  //Send MQTT-SN message
1264  error = mqttSnClientSendDatagram(context, context->message.buffer,
1265  context->message.length);
1266 
1267  //Get current time
1268  time = osGetSystemTime();
1269 
1270  //Check QoS level
1272  {
1273  //Save the time at which the message was sent
1274  context->retransmitStartTime = time;
1275  context->keepAliveTimestamp = time;
1276 
1277  //Update MQTT-SN client state
1278  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1279  context->msgType = MQTT_SN_MSG_TYPE_PUBLISH;
1280  }
1281  else
1282  {
1283  //In the QoS 0, no response is sent by the receiver and no retry
1284  //is performed by the sender
1285  context->state = MQTT_SN_CLIENT_STATE_ACTIVE;
1286  }
1287  }
1288 
1289  //Return status code
1290  return error;
1291 }
1292 
1293 
1294 /**
1295  * @brief Send PUBACK message
1296  * @param[in] context Pointer to the MQTT-SN client context
1297  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1298  * @param[in] topicId Topic identifier
1299  * @param[in] returnCode Return code
1300  * @return Error code
1301  **/
1302 
1305 {
1306  error_t error;
1307 
1308  //Format PUBACK message
1309  error = mqttSnFormatPubAck(&context->message, msgId, topicId, returnCode);
1310 
1311  //Check status code
1312  if(!error)
1313  {
1314  //Debug message
1315  TRACE_INFO("Sending PUBACK message (%" PRIuSIZE " bytes)...\r\n",
1316  context->message.length);
1317 
1318  //Dump the contents of the message for debugging purpose
1319  mqttSnDumpMessage(context->message.buffer, context->message.length);
1320 
1321  //Send MQTT-SN message
1322  error = mqttSnClientSendDatagram(context, context->message.buffer,
1323  context->message.length);
1324  }
1325 
1326  //Return status code
1327  return error;
1328 }
1329 
1330 
1331 /**
1332  * @brief Send PUBREC message
1333  * @param[in] context Pointer to the MQTT-SN client context
1334  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1335  * @return Error code
1336  **/
1337 
1339 {
1340  error_t error;
1341 
1342  //Format PUBREC message
1343  error = mqttSnFormatPubRec(&context->message, msgId);
1344 
1345  //Check status code
1346  if(!error)
1347  {
1348  //Debug message
1349  TRACE_INFO("Sending PUBREC message (%" PRIuSIZE " bytes)...\r\n",
1350  context->message.length);
1351 
1352  //Dump the contents of the message for debugging purpose
1353  mqttSnDumpMessage(context->message.buffer, context->message.length);
1354 
1355  //Send MQTT-SN message
1356  error = mqttSnClientSendDatagram(context, context->message.buffer,
1357  context->message.length);
1358  }
1359 
1360  //Return status code
1361  return error;
1362 }
1363 
1364 
1365 /**
1366  * @brief Send PUBREL message
1367  * @param[in] context Pointer to the MQTT-SN client context
1368  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1369  * @return Error code
1370  **/
1371 
1373 {
1374  error_t error;
1375  systime_t time;
1376 
1377  //Format PUBREL message
1378  error = mqttSnFormatPubRel(&context->message, msgId);
1379 
1380  //Check status code
1381  if(!error)
1382  {
1383  //Debug message
1384  TRACE_INFO("Sending PUBREL message (%" PRIuSIZE " bytes)...\r\n",
1385  context->message.length);
1386 
1387  //Dump the contents of the message for debugging purpose
1388  mqttSnDumpMessage(context->message.buffer, context->message.length);
1389 
1390  //Send MQTT-SN message
1391  error = mqttSnClientSendDatagram(context, context->message.buffer,
1392  context->message.length);
1393 
1394  //Get current time
1395  time = osGetSystemTime();
1396 
1397  //Save the time at which the message was sent
1398  context->retransmitStartTime = time;
1399  context->keepAliveTimestamp = time;
1400 
1401  //Update MQTT-SN client state
1402  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1403  context->msgType = MQTT_SN_MSG_TYPE_PUBREL;
1404  }
1405 
1406  //Return status code
1407  return error;
1408 }
1409 
1410 
1411 /**
1412  * @brief Send PUBCOMP message
1413  * @param[in] context Pointer to the MQTT-SN client context
1414  * @param[in] msgId Message identifier of the corresponding PUBLISH message
1415  * @return Error code
1416  **/
1417 
1419 {
1420  error_t error;
1421 
1422  //Format PUBCOMP message
1423  error = mqttSnFormatPubComp(&context->message, msgId);
1424 
1425  //Check status code
1426  if(!error)
1427  {
1428  //Debug message
1429  TRACE_INFO("Sending PUBCOMP message (%" PRIuSIZE " bytes)...\r\n",
1430  context->message.length);
1431 
1432  //Dump the contents of the message for debugging purpose
1433  mqttSnDumpMessage(context->message.buffer, context->message.length);
1434 
1435  //Send MQTT-SN message
1436  error = mqttSnClientSendDatagram(context, context->message.buffer,
1437  context->message.length);
1438  }
1439 
1440  //Return status code
1441  return error;
1442 }
1443 
1444 
1445 /**
1446  * @brief Send SUBSCRIBE message
1447  * @param[in] context Pointer to the MQTT-SN client context
1448  * @param[in] topicName Topic filter
1449  * @param[in] qos Maximum QoS level at which the server can send application
1450  * messages to the client
1451  * @return Error code
1452  **/
1453 
1456 {
1457  error_t error;
1458  systime_t time;
1459  uint16_t topicId;
1461 
1462  //Initialize status code
1463  error = NO_ERROR;
1464 
1465  //Reset unused flags
1466  flags.all = 0;
1467  //Set QoS level
1468  flags.qos = qos;
1469 
1470  //Check whether a predefined topic ID has been registered
1472 
1473  //Predefined topic ID found?
1475  {
1476  //The SUBSCRIBE message contains a predefined topic ID
1477  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1478  }
1479  else
1480  {
1481  //Short topic name?
1483  {
1484  //The SUBSCRIBE message contains a short topic name
1485  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1486  }
1487  else
1488  {
1489  //The SUBSCRIBE message contains a normal topic name
1490  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1491  }
1492 
1493  //Format SUBSCRIBE message
1494  error = mqttSnFormatSubscribe(&context->message, flags,
1495  context->msgId, topicId, topicName);
1496  }
1497 
1498  //Check status code
1499  if(!error)
1500  {
1501  //Debug message
1502  TRACE_INFO("Sending SUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1503  context->message.length);
1504 
1505  //Dump the contents of the message for debugging purpose
1506  mqttSnDumpMessage(context->message.buffer, context->message.length);
1507 
1508  //Send MQTT-SN message
1509  error = mqttSnClientSendDatagram(context, context->message.buffer,
1510  context->message.length);
1511 
1512  //Get current time
1513  time = osGetSystemTime();
1514 
1515  //Save the time at which the message was sent
1516  context->retransmitStartTime = time;
1517  context->keepAliveTimestamp = time;
1518 
1519  //Update MQTT-SN client state
1520  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1521  context->msgType = MQTT_SN_MSG_TYPE_SUBSCRIBE;
1522  }
1523 
1524  //Return status code
1525  return error;
1526 }
1527 
1528 
1529 /**
1530  * @brief Send UNSUBSCRIBE message
1531  * @param[in] context Pointer to the MQTT-SN client context
1532  * @param[in] topicName Topic filter
1533  * @return Error code
1534  **/
1535 
1537  const char_t *topicName)
1538 {
1539  error_t error;
1540  systime_t time;
1541  uint16_t topicId;
1543 
1544  //Initialize status code
1545  error = NO_ERROR;
1546 
1547  //Reset unused flags
1548  flags.all = 0;
1549 
1550  //Check whether a predefined topic ID has been registered
1552 
1553  //Predefined topic ID found?
1555  {
1556  //The UNSUBSCRIBE message contains a predefined topic ID
1557  flags.topicIdType = MQTT_SN_PREDEFINED_TOPIC_ID;
1558  }
1559  else
1560  {
1561  //Short topic name?
1562  if(osStrlen(topicName) == 2 && osStrchr(topicName, '#') == NULL &&
1563  osStrchr(topicName, '+') == NULL)
1564  {
1565  //The UNSUBSCRIBE message contains a short topic name
1566  flags.topicIdType = MQTT_SN_SHORT_TOPIC_NAME;
1567  }
1568  else
1569  {
1570  //The UNSUBSCRIBE message contains a normal topic name
1571  flags.topicIdType = MQTT_SN_NORMAL_TOPIC_NAME;
1572  }
1573 
1574  //Format UNSUBSCRIBE message
1575  error = mqttSnFormatUnsubscribe(&context->message, flags,
1576  context->msgId, topicId, topicName);
1577  }
1578 
1579  //Check status code
1580  if(!error)
1581  {
1582  //Debug message
1583  TRACE_INFO("Sending UNSUBSCRIBE message (%" PRIuSIZE " bytes)...\r\n",
1584  context->message.length);
1585 
1586  //Dump the contents of the message for debugging purpose
1587  mqttSnDumpMessage(context->message.buffer, context->message.length);
1588 
1589  //Send MQTT-SN message
1590  error = mqttSnClientSendDatagram(context, context->message.buffer,
1591  context->message.length);
1592 
1593  //Get current time
1594  time = osGetSystemTime();
1595 
1596  //Save the time at which the message was sent
1597  context->retransmitStartTime = time;
1598  context->keepAliveTimestamp = time;
1599 
1600  //Update MQTT-SN client state
1601  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1602  context->msgType = MQTT_SN_MSG_TYPE_UNSUBSCRIBE;
1603  }
1604 
1605  //Return status code
1606  return error;
1607 }
1608 
1609 
1610 /**
1611  * @brief Send PINGREQ message
1612  * @param[in] context Pointer to the MQTT-SN client context
1613  * @return Error code
1614  **/
1615 
1617 {
1618  error_t error;
1619 
1620  //Format PINGREQ message
1621  error = mqttSnFormatPingReq(&context->message, context->clientId);
1622 
1623  //Check status code
1624  if(!error)
1625  {
1626  //Debug message
1627  TRACE_INFO("Sending PINGREQ message (%" PRIuSIZE " bytes)...\r\n",
1628  context->message.length);
1629 
1630  //Dump the contents of the message for debugging purpose
1631  mqttSnDumpMessage(context->message.buffer, context->message.length);
1632 
1633  //Send MQTT-SN message
1634  error = mqttSnClientSendDatagram(context, context->message.buffer,
1635  context->message.length);
1636 
1637  //Save the time at which the message was sent
1638  context->keepAliveTimestamp = osGetSystemTime();
1639  }
1640 
1641  //Return status code
1642  return error;
1643 }
1644 
1645 
1646 /**
1647  * @brief Send PINGRESP message
1648  * @param[in] context Pointer to the MQTT-SN client context
1649  * @return Error code
1650  **/
1651 
1653 {
1654  error_t error;
1655 
1656  //Format PINGRESP message
1657  error = mqttSnFormatPingResp(&context->message);
1658 
1659  //Check status code
1660  if(!error)
1661  {
1662  //Debug message
1663  TRACE_INFO("Sending PINGRESP message (%" PRIuSIZE " bytes)...\r\n",
1664  context->message.length);
1665 
1666  //Dump the contents of the message for debugging purpose
1667  mqttSnDumpMessage(context->message.buffer, context->message.length);
1668 
1669  //Send MQTT-SN message
1670  error = mqttSnClientSendDatagram(context, context->message.buffer,
1671  context->message.length);
1672  }
1673 
1674  //Return status code
1675  return error;
1676 }
1677 
1678 
1679 /**
1680  * @brief Send DISCONNECT message
1681  * @param[in] context Pointer to the MQTT-SN client context
1682  * @param[in] duration Value of the sleep timer
1683  * @return Error code
1684  **/
1685 
1687  uint16_t duration)
1688 {
1689  error_t error;
1690 
1691  //Format DISCONNECT message
1692  error = mqttSnFormatDisconnect(&context->message, duration);
1693 
1694  //Check status code
1695  if(!error)
1696  {
1697  //Debug message
1698  TRACE_INFO("Sending DISCONNECT message (%" PRIuSIZE " bytes)...\r\n",
1699  context->message.length);
1700 
1701  //Dump the contents of the message for debugging purpose
1702  mqttSnDumpMessage(context->message.buffer, context->message.length);
1703 
1704  //Send MQTT-SN message
1705  error = mqttSnClientSendDatagram(context, context->message.buffer,
1706  context->message.length);
1707 
1708  //Save the time at which the message was sent
1709  context->retransmitStartTime = osGetSystemTime();
1710 
1711  //Update MQTT-SN client state
1712  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1713  context->msgType = MQTT_SN_MSG_TYPE_DISCONNECT;
1714  }
1715 
1716  //Return status code
1717  return error;
1718 }
1719 
1720 
1721 /**
1722  * @brief Send WILLTOPICUPD message
1723  * @param[in] context Pointer to the MQTT-SN client context
1724  * @return Error code
1725  **/
1726 
1728 {
1729  error_t error;
1730  systime_t time;
1731 
1732  //Format WILLTOPICUPD message
1733  error = mqttSnFormatWillTopicUpd(&context->message,
1734  context->willMessage.flags, context->willMessage.topic);
1735 
1736  //Check status code
1737  if(!error)
1738  {
1739  //Debug message
1740  TRACE_INFO("Sending WILLTOPICUPD message (%" PRIuSIZE " bytes)...\r\n",
1741  context->message.length);
1742 
1743  //Dump the contents of the message for debugging purpose
1744  mqttSnDumpMessage(context->message.buffer, context->message.length);
1745 
1746  //Send MQTT-SN message
1747  error = mqttSnClientSendDatagram(context, context->message.buffer,
1748  context->message.length);
1749 
1750  //Get current time
1751  time = osGetSystemTime();
1752 
1753  //Save the time at which the message was sent
1754  context->retransmitStartTime = time;
1755  context->keepAliveTimestamp = time;
1756 
1757  //Update MQTT-SN client state
1758  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1759  context->msgType = MQTT_SN_MSG_TYPE_WILLTOPICUPD;
1760  }
1761 
1762  //Return status code
1763  return error;
1764 }
1765 
1766 
1767 /**
1768  * @brief Send WILLMSGUPD message
1769  * @param[in] context Pointer to the MQTT-SN client context
1770  * @return Error code
1771  **/
1772 
1774 {
1775  error_t error;
1776  systime_t time;
1777 
1778  //Format WILLMSGUPD message
1779  error = mqttSnFormatWillMsgUpd(&context->message,
1780  context->willMessage.payload, context->willMessage.length);
1781 
1782  //Check status code
1783  if(!error)
1784  {
1785  //Debug message
1786  TRACE_INFO("Sending WILLMSGUPD message (%" PRIuSIZE " bytes)...\r\n",
1787  context->message.length);
1788 
1789  //Dump the contents of the message for debugging purpose
1790  mqttSnDumpMessage(context->message.buffer, context->message.length);
1791 
1792  //Send MQTT-SN message
1793  error = mqttSnClientSendDatagram(context, context->message.buffer,
1794  context->message.length);
1795 
1796  //Get current time
1797  time = osGetSystemTime();
1798 
1799  //Save the time at which the message was sent
1800  context->retransmitStartTime = time;
1801  context->keepAliveTimestamp = time;
1802 
1803  //Update MQTT-SN client state
1804  context->state = MQTT_SN_CLIENT_STATE_SENDING_REQ;
1805  context->msgType = MQTT_SN_MSG_TYPE_WILLMSGUPD;
1806  }
1807 
1808  //Return status code
1809  return error;
1810 }
1811 
1812 #endif
error_t mqttSnClientProcessWillMsgReq(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming WILLMSGREQ message.
#define osStrchr(s, c)
Definition: os_port.h:195
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:53
@ ERROR_NOT_FOUND
Definition: error.h:147
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:90
@ 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.
uint8_t message[]
Definition: chap.h:154
error_t mqttSnClientSendRegister(MqttSnClientContext *context, const char_t *topicName)
Send REGISTER message.
#define MqttSnClientContext
#define TRUE
Definition: os_port.h:50
uint8_t data[]
Definition: ethernet.h:222
@ 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.
uint8_t type
Definition: coap_common.h:176
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:340
uint8_t qos
Definition: mqtt_common.h:181
#define osStrlen(s)
Definition: os_port.h:165
MQTT-SN message formatting and parsing.
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[]
@ 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.
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:43
@ 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.
@ MQTT_SN_MSG_TYPE_WILLTOPICUPD
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.
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:115
#define TRACE_INFO(...)
Definition: debug.h:95
uint8_t length
Definition: tcp.h:368
@ MQTT_SN_CLIENT_STATE_RESP_RECEIVED
@ MQTT_SN_CLIENT_STATE_DISCONNECTING
error_t mqttSnParsePingResp(const MqttSnMessage *message)
Parse PINGRESP message.
uint32_t dataLen
Definition: sftp_common.h:229
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.
uint32_t systime_t
System time.
uint16_t port
Definition: dns_common.h:267
uint16_t duration
uint8_t flags
Definition: tcp.h:351
#define TRACE_WARNING(...)
Definition: debug.h:85
const char_t * mqttSnGetMessageName(uint16_t msgType)
Get the name of the specified MQTT-SN message.
char char_t
Definition: compiler_port.h:48
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:108
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.
char_t topicName[]
@ MQTT_SN_RETURN_CODE_ACCEPTED
MQTT-SN message.
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)
@ MQTT_SN_MSG_TYPE_UNSUBACK
uint8_t dup
Definition: mqtt_common.h:182
@ 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.
Ipv4Addr ipAddr
Definition: ipcp.h:105
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
TCP/IP stack core.
@ MQTT_SN_MSG_TYPE_UNSUBSCRIBE
error_t mqttSnClientProcessPubRec(MqttSnClientContext *context, const MqttSnMessage *message)
Process incoming PUBREC message.
MqttSnFlags
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)
#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:80