Provides Javascript wrappers for MQTT.

Dependencies:   mbed-http DEVI2C_JS MQTTPacket FP

Committer:
kajasu
Date:
Mon Feb 03 09:36:20 2020 +0000
Revision:
1:a8ffffd1beab
Parent:
0:f4dbe435e64c
TT

Who changed what in which revision?

UserRevisionLine numberNew contents of line
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1 /*******************************************************************************
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 2 * Copyright (c) 2014, 2017 IBM Corp.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 3 *
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 4 * All rights reserved. This program and the accompanying materials
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 5 * are made available under the terms of the Eclipse Public License v1.0
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 7 *
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 8 * The Eclipse Public License is available at
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 9 * http://www.eclipse.org/legal/epl-v10.html
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 10 * and the Eclipse Distribution License is available at
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 11 * http://www.eclipse.org/org/documents/edl-v10.php.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 12 *
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 13 * Contributors:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 14 * Ian Craggs - initial API and implementation and/or initial documentation
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 15 * Ian Craggs - fix for bug 458512 - QoS 2 messages
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 16 * Ian Craggs - fix for bug 460389 - send loop uses wrong length
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 17 * Ian Craggs - fix for bug 464169 - clearing subscriptions
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 18 * Ian Craggs - fix for bug 464551 - enums and ints can be different size
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 19 * Mark Sonnentag - fix for bug 475204 - inefficient instantiation of Timer
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 20 * Ian Craggs - fix for bug 475749 - packetid modified twice
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 21 * Ian Craggs - add ability to set message handler separately #6
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 22 *******************************************************************************/
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 23
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 24 #if !defined(MQTTCLIENT_H)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 25 #define MQTTCLIENT_H
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 26
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 27 #include "FP.h"
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 28 #include "MQTTPacket.h"
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 29 #include <stdio.h>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 30 #include "MQTTLogging.h"
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 31
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 32 #if !defined(MQTTCLIENT_QOS1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 33 #define MQTTCLIENT_QOS1 1
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 34 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 35 #if !defined(MQTTCLIENT_QOS2)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 36 #define MQTTCLIENT_QOS2 0
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 37 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 38
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 39 namespace MQTT
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 40 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 41
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 42
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 43 enum QoS { QOS0, QOS1, QOS2 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 44
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 45 // all failure return codes must be negative
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 46 enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 47
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 48
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 49 struct Message
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 50 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 51 enum QoS qos;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 52 bool retained;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 53 bool dup;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 54 unsigned short id;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 55 void *payload;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 56 size_t payloadlen;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 57 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 58
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 59
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 60 struct MessageData
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 61 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 62 MessageData(MQTTString &aTopicName, struct Message &aMessage) : message(aMessage), topicName(aTopicName)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 63 { }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 64
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 65 struct Message &message;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 66 MQTTString &topicName;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 67 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 68
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 69
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 70 struct connackData
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 71 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 72 int rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 73 bool sessionPresent;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 74 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 75
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 76
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 77 struct subackData
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 78 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 79 int grantedQoS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 80 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 81
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 82
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 83 class PacketId
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 84 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 85 public:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 86 PacketId()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 87 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 88 next = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 89 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 90
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 91 int getNext()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 92 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 93 return next = (next == MAX_PACKET_ID) ? 1 : next + 1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 94 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 95
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 96 private:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 97 static const int MAX_PACKET_ID = 65535;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 98 int next;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 99 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 100
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 101
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 102 /**
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 103 * @class Client
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 104 * @brief blocking, non-threaded MQTT client API
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 105 *
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 106 * This version of the API blocks on all method calls, until they are complete. This means that only one
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 107 * MQTT request can be in process at any one time.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 108 * @param Network a network class which supports send, receive
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 109 * @param Timer a timer class with the methods:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 110 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 111 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 112 class Client
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 113 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 114
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 115 public:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 116
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 117 typedef void (*messageHandler)(MessageData&);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 118
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 119 /** Construct the client
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 120 * @param network - pointer to an instance of the Network class - must be connected to the endpoint
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 121 * before calling MQTT connect
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 122 * @param limits an instance of the Limit class - to alter limits as required
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 123 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 124 Client(Network& network, unsigned int command_timeout_ms = 30000);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 125
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 126 /** Set the default message handling callback - used for any message which does not match a subscription message handler
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 127 * @param mh - pointer to the callback function. Set to 0 to remove.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 128 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 129 void setDefaultMessageHandler(messageHandler mh)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 130 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 131 if (mh != 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 132 defaultMessageHandler.attach(mh);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 133 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 134 defaultMessageHandler.detach();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 135 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 136
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 137 /** Set a message handling callback. This can be used outside of the the subscribe method.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 138 * @param topicFilter - a topic pattern which can include wildcards
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 139 * @param mh - pointer to the callback function. If 0, removes the callback if any
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 140 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 141 int setMessageHandler(const char* topicFilter, messageHandler mh);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 142
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 143 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 144 * The nework object must be connected to the network endpoint before calling this
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 145 * Default connect options are used
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 146 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 147 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 148 int connect();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 149
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 150 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 151 * The nework object must be connected to the network endpoint before calling this
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 152 * @param options - connect options
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 153 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 154 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 155 int connect(MQTTPacket_connectData& options);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 156
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 157 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 158 * The nework object must be connected to the network endpoint before calling this
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 159 * @param options - connect options
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 160 * @param connackData - connack data to be returned
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 161 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 162 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 163 int connect(MQTTPacket_connectData& options, connackData& data);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 164
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 165 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 166 * @param topic - the topic to publish to
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 167 * @param message - the message to send
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 168 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 169 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 170 int publish(const char* topicName, Message& message);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 171
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 172 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 173 * @param topic - the topic to publish to
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 174 * @param payload - the data to send
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 175 * @param payloadlen - the length of the data
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 176 * @param qos - the QoS to send the publish at
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 177 * @param retained - whether the message should be retained
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 178 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 179 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 180 int publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos = QOS0, bool retained = false);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 181
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 182 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 183 * @param topic - the topic to publish to
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 184 * @param payload - the data to send
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 185 * @param payloadlen - the length of the data
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 186 * @param id - the packet id used - returned
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 187 * @param qos - the QoS to send the publish at
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 188 * @param retained - whether the message should be retained
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 189 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 190 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 191 int publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos = QOS1, bool retained = false);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 192
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 193 /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 194 * @param topicFilter - a topic pattern which can include wildcards
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 195 * @param qos - the MQTT QoS to subscribe at
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 196 * @param mh - the callback function to be invoked when a message is received for this subscription
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 197 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 198 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 199 int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 200
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 201 /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 202 * @param topicFilter - a topic pattern which can include wildcards
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 203 * @param qos - the MQTT QoS to subscribe at©
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 204 * @param mh - the callback function to be invoked when a message is received for this subscription
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 205 * @param
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 206 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 207 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 208 int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh, subackData &data);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 209
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 210 /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 211 * @param topicFilter - a topic pattern which can include wildcards
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 212 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 213 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 214 int unsubscribe(const char* topicFilter);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 215
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 216 /** MQTT Disconnect - send an MQTT disconnect packet, and clean up any state
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 217 * @return success code -
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 218 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 219 int disconnect();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 220
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 221 /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 222 * yield can be called if no other MQTT operation is needed. This will also allow messages to be
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 223 * received.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 224 * @param timeout_ms the time to wait, in milliseconds
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 225 * @return success code - on failure, this means the client has disconnected
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 226 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 227 int yield(unsigned long timeout_ms = 1000L);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 228
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 229 /** Is the client connected?
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 230 * @return flag - is the client connected or not?
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 231 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 232 bool isConnected()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 233 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 234 return isconnected;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 235 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 236
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 237 private:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 238
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 239 void closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 240 void cleanSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 241 int cycle(Timer& timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 242 int waitfor(int packet_type, Timer& timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 243 int keepalive();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 244 int publish(int len, Timer& timer, enum QoS qos);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 245
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 246 int decodePacket(int* value, int timeout);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 247 int readPacket(Timer& timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 248 int sendPacket(int length, Timer& timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 249 int deliverMessage(MQTTString& topicName, Message& message);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 250 bool isTopicMatched(char* topicFilter, MQTTString& topicName);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 251
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 252 Network& ipstack;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 253 unsigned long command_timeout_ms;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 254
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 255 unsigned char sendbuf[MAX_MQTT_PACKET_SIZE];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 256 unsigned char readbuf[MAX_MQTT_PACKET_SIZE];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 257
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 258 Timer last_sent, last_received;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 259 unsigned int keepAliveInterval;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 260 bool ping_outstanding;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 261 bool cleansession;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 262
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 263 PacketId packetid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 264
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 265 struct MessageHandlers
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 266 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 267 const char* topicFilter;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 268 FP<void, MessageData&> fp;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 269 } messageHandlers[MAX_MESSAGE_HANDLERS]; // Message handlers are indexed by subscription topic
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 270
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 271 FP<void, MessageData&> defaultMessageHandler;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 272
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 273 bool isconnected;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 274
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 275 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 276 unsigned char pubbuf[MAX_MQTT_PACKET_SIZE]; // store the last publish for sending on reconnect
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 277 int inflightLen;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 278 unsigned short inflightMsgid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 279 enum QoS inflightQoS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 280 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 281
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 282 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 283 bool pubrel;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 284 #if !defined(MAX_INCOMING_QOS2_MESSAGES)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 285 #define MAX_INCOMING_QOS2_MESSAGES 10
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 286 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 287 unsigned short incomingQoS2messages[MAX_INCOMING_QOS2_MESSAGES];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 288 bool isQoS2msgidFree(unsigned short id);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 289 bool useQoS2msgid(unsigned short id);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 290 void freeQoS2msgid(unsigned short id);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 291 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 292
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 293 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 294
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 295 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 296
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 297
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 298 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 299 void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::cleanSession()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 300 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 301 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 302 messageHandlers[i].topicFilter = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 303
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 304 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 305 inflightMsgid = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 306 inflightQoS = QOS0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 307 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 308
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 309 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 310 pubrel = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 311 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 312 incomingQoS2messages[i] = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 313 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 314 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 315
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 316
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 317 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 318 void MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::closeSession()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 319 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 320 ping_outstanding = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 321 isconnected = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 322 if (cleansession)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 323 cleanSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 324 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 325
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 326
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 327 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 328 MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms) : ipstack(network), packetid()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 329 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 330 this->command_timeout_ms = command_timeout_ms;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 331 cleansession = true;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 332 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 333 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 334
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 335
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 336 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 337 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 338 bool MQTT::Client<Network, Timer, a, b>::isQoS2msgidFree(unsigned short id)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 339 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 340 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 341 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 342 if (incomingQoS2messages[i] == id)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 343 return false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 344 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 345 return true;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 346 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 347
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 348
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 349 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 350 bool MQTT::Client<Network, Timer, a, b>::useQoS2msgid(unsigned short id)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 351 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 352 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 353 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 354 if (incomingQoS2messages[i] == 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 355 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 356 incomingQoS2messages[i] = id;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 357 return true;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 358 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 359 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 360 return false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 361 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 362
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 363
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 364 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 365 void MQTT::Client<Network, Timer, a, b>::freeQoS2msgid(unsigned short id)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 366 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 367 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 368 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 369 if (incomingQoS2messages[i] == id)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 370 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 371 incomingQoS2messages[i] = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 372 return;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 373 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 374 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 375 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 376 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 377
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 378
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 379 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 380 int MQTT::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 381 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 382 int rc = FAILURE,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 383 sent = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 384
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 385 while (sent < length)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 386 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 387 rc = ipstack.write(&sendbuf[sent], length - sent, timer.left_ms());
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 388 if (rc < 0) // there was an error writing the data
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 389 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 390 sent += rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 391 if (timer.expired()) // only check expiry after at least one attempt to write
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 392 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 393 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 394 if (sent == length)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 395 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 396 if (this->keepAliveInterval > 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 397 last_sent.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 398 rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 399 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 400 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 401 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 402
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 403 #if defined(MQTT_DEBUG)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 404 char printbuf[150];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 405 DEBUG("Rc %d from sending packet %s\r\n", rc,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 406 MQTTFormat_toServerString(printbuf, sizeof(printbuf), sendbuf, length));
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 407 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 408 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 409 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 410
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 411
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 412 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 413 int MQTT::Client<Network, Timer, a, b>::decodePacket(int* value, int timeout)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 414 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 415 unsigned char c;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 416 int multiplier = 1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 417 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 418 const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 419
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 420 *value = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 421 do
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 422 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 423 int rc = MQTTPACKET_READ_ERROR;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 424
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 425 if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 426 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 427 rc = MQTTPACKET_READ_ERROR; /* bad data */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 428 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 429 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 430 rc = ipstack.read(&c, 1, timeout);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 431 if (rc != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 432 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 433 *value += (c & 127) * multiplier;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 434 multiplier *= 128;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 435 } while ((c & 128) != 0);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 436 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 437 return len;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 438 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 439
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 440
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 441 /**
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 442 * If any read fails in this method, then we should disconnect from the network, as on reconnect
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 443 * the packets can be retried.
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 444 * @param timeout the max time to wait for the packet read to complete, in milliseconds
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 445 * @return the MQTT packet type, 0 if none, -1 if error
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 446 */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 447 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 448 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::readPacket(Timer& timer)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 449 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 450 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 451 MQTTHeader header = {0};
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 452 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 453 int rem_len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 454
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 455 /* 1. read the header byte. This has the packet type in it */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 456 rc = ipstack.read(readbuf, 1, timer.left_ms());
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 457 if (rc != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 458 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 459
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 460 len = 1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 461 /* 2. read the remaining length. This is variable in itself */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 462 decodePacket(&rem_len, timer.left_ms());
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 463 len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length into the buffer */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 464
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 465 if (rem_len > (MAX_MQTT_PACKET_SIZE - len))
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 466 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 467 rc = BUFFER_OVERFLOW;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 468 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 469 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 470
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 471 /* 3. read the rest of the buffer using a callback to supply the rest of the data */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 472 if (rem_len > 0 && (ipstack.read(readbuf + len, rem_len, timer.left_ms()) != rem_len))
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 473 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 474
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 475 header.byte = readbuf[0];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 476 rc = header.bits.type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 477 if (this->keepAliveInterval > 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 478 last_received.countdown(this->keepAliveInterval); // record the fact that we have successfully received a packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 479 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 480
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 481 #if defined(MQTT_DEBUG)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 482 if (rc >= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 483 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 484 char printbuf[50];
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 485 DEBUG("Rc %d receiving packet %s\r\n", rc,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 486 MQTTFormat_toClientString(printbuf, sizeof(printbuf), readbuf, len));
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 487 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 488 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 489 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 490 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 491
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 492
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 493 // assume topic filter and name is in correct format
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 494 // # can only be at end
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 495 // + and # can only be next to separator
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 496 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 497 bool MQTT::Client<Network, Timer, a, b>::isTopicMatched(char* topicFilter, MQTTString& topicName)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 498 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 499 char* curf = topicFilter;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 500 char* curn = topicName.lenstring.data;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 501 char* curn_end = curn + topicName.lenstring.len;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 502
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 503 while (*curf && curn < curn_end)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 504 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 505 if (*curn == '/' && *curf != '/')
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 506 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 507 if (*curf != '+' && *curf != '#' && *curf != *curn)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 508 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 509 if (*curf == '+')
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 510 { // skip until we meet the next separator, or end of string
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 511 char* nextpos = curn + 1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 512 while (nextpos < curn_end && *nextpos != '/')
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 513 nextpos = ++curn + 1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 514 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 515 else if (*curf == '#')
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 516 curn = curn_end - 1; // skip until end of string
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 517 curf++;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 518 curn++;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 519 };
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 520
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 521 return (curn == curn_end) && (*curf == '\0');
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 522 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 523
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 524
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 525
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 526 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 527 int MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTString& topicName, Message& message)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 528 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 529 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 530
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 531 // we have to find the right message handler - indexed by topic
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 532 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 533 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 534 if (messageHandlers[i].topicFilter != 0 && (MQTTPacket_equals(&topicName, (char*)messageHandlers[i].topicFilter) ||
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 535 isTopicMatched((char*)messageHandlers[i].topicFilter, topicName)))
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 536 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 537 if (messageHandlers[i].fp.attached())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 538 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 539 MessageData md(topicName, message);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 540 messageHandlers[i].fp(md);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 541 rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 542 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 543 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 544 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 545
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 546 if (rc == FAILURE && defaultMessageHandler.attached())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 547 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 548 MessageData md(topicName, message);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 549 defaultMessageHandler(md);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 550 rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 551 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 552
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 553 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 554 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 555
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 556
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 557
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 558 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 559 int MQTT::Client<Network, Timer, a, b>::yield(unsigned long timeout_ms)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 560 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 561 int rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 562 Timer timer;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 563
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 564 timer.countdown_ms(timeout_ms);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 565 while (!timer.expired())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 566 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 567 if (cycle(timer) < 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 568 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 569 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 570 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 571 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 572 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 573
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 574 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 575 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 576
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 577
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 578 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 579 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle(Timer& timer)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 580 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 581 // get one piece of work off the wire and one pass through
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 582 int len = 0,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 583 rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 584
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 585 int packet_type = readPacket(timer); // read the socket, see what work is due
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 586
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 587 switch (packet_type)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 588 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 589 default:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 590 // no more data to read, unrecoverable. Or read packet fails due to unexpected network error
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 591 rc = packet_type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 592 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 593 case NSAPI_ERROR_WOULD_BLOCK:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 594 case NSAPI_ERROR_OK: // timed out reading packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 595 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 596 case CONNACK:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 597 case PUBACK:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 598 case SUBACK:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 599 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 600 case PUBLISH:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 601 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 602 MQTTString topicName = MQTTString_initializer;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 603 Message msg;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 604 int intQoS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 605 msg.payloadlen = 0; /* this is a size_t, but deserialize publish sets this as int */
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 606 if (MQTTDeserialize_publish((unsigned char*)&msg.dup, &intQoS, (unsigned char*)&msg.retained, (unsigned short*)&msg.id, &topicName,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 607 (unsigned char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 608 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 609 msg.qos = (enum QoS)intQoS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 610 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 611 if (msg.qos != QOS2)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 612 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 613 deliverMessage(topicName, msg);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 614 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 615 else if (isQoS2msgidFree(msg.id))
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 616 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 617 if (useQoS2msgid(msg.id))
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 618 deliverMessage(topicName, msg);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 619 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 620 WARN("Maximum number of incoming QoS2 messages exceeded");
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 621 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 622 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 623 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 624 if (msg.qos != QOS0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 625 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 626 if (msg.qos == QOS1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 627 len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBACK, 0, msg.id);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 628 else if (msg.qos == QOS2)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 629 len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREC, 0, msg.id);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 630 if (len <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 631 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 632 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 633 rc = sendPacket(len, timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 634 if (rc == FAILURE)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 635 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 636 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 637 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 638 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 639 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 640 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 641 case PUBREC:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 642 case PUBREL:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 643 unsigned short mypacketid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 644 unsigned char dup, type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 645 if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 646 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 647 else if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 648 (packet_type == PUBREC) ? PUBREL : PUBCOMP, 0, mypacketid)) <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 649 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 650 else if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 651 rc = FAILURE; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 652 if (rc == FAILURE)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 653 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 654 if (packet_type == PUBREL)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 655 freeQoS2msgid(mypacketid);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 656 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 657
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 658 case PUBCOMP:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 659 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 660 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 661 case PINGRESP:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 662 ping_outstanding = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 663 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 664 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 665
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 666 if (keepalive() != SUCCESS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 667 //check only keepalive FAILURE status so that previous FAILURE status can be considered as FAULT
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 668 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 669
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 670 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 671 if (rc == SUCCESS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 672 rc = packet_type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 673 else if (isconnected)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 674 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 675 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 676 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 677
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 678
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 679 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 680 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::keepalive()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 681 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 682 int rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 683 static Timer ping_sent;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 684
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 685 if (keepAliveInterval == 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 686 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 687
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 688 if (ping_outstanding)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 689 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 690 if (ping_sent.expired())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 691 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 692 rc = FAILURE; // session failure
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 693 #if defined(MQTT_DEBUG)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 694 DEBUG("PINGRESP not received in keepalive interval\r\n");
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 695 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 696 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 697 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 698 else if (last_sent.expired() || last_received.expired())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 699 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 700 Timer timer(1000);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 701 int len = MQTTSerialize_pingreq(sendbuf, MAX_MQTT_PACKET_SIZE);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 702 if (len > 0 && (rc = sendPacket(len, timer)) == SUCCESS) // send the ping packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 703 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 704 ping_outstanding = true;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 705 ping_sent.countdown(this->keepAliveInterval);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 706 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 707 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 708 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 709 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 710 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 711
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 712
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 713 // only used in single-threaded mode where one command at a time is in process
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 714 template<class Network, class Timer, int a, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 715 int MQTT::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 716 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 717 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 718
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 719 do
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 720 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 721 if (timer.expired())
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 722 break; // we timed out
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 723 rc = cycle(timer);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 724 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 725 while (rc != packet_type && rc >= 0);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 726
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 727 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 728 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 729
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 730
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 731 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 732 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options, connackData& data)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 733 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 734 Timer connect_timer(command_timeout_ms);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 735 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 736 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 737
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 738 if (isconnected) // don't send connect packet again if we are already connected
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 739 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 740
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 741 this->keepAliveInterval = options.keepAliveInterval;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 742 this->cleansession = options.cleansession;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 743 if ((len = MQTTSerialize_connect(sendbuf, MAX_MQTT_PACKET_SIZE, &options)) <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 744 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 745 if ((rc = sendPacket(len, connect_timer)) != SUCCESS) // send the connect packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 746 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 747
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 748 if (this->keepAliveInterval > 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 749 last_received.countdown(this->keepAliveInterval);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 750 // this will be a blocking call, wait for the connack
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 751 if (waitfor(CONNACK, connect_timer) == CONNACK)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 752 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 753 data.rc = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 754 data.sessionPresent = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 755 if (MQTTDeserialize_connack((unsigned char*)&data.sessionPresent,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 756 (unsigned char*)&data.rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 757 rc = data.rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 758 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 759 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 760 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 761 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 762 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 763
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 764 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 765 // resend any inflight publish
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 766 if (inflightMsgid > 0 && inflightQoS == QOS2 && pubrel)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 767 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 768 if ((len = MQTTSerialize_ack(sendbuf, MAX_MQTT_PACKET_SIZE, PUBREL, 0, inflightMsgid)) <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 769 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 770 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 771 rc = publish(len, connect_timer, inflightQoS);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 772 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 773 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 774 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 775 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 776 if (inflightMsgid > 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 777 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 778 memcpy(sendbuf, pubbuf, MAX_MQTT_PACKET_SIZE);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 779 rc = publish(inflightLen, connect_timer, inflightQoS);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 780 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 781 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 782
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 783 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 784 if (rc == SUCCESS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 785 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 786 isconnected = true;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 787 ping_outstanding = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 788 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 789 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 790 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 791
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 792
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 793 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 794 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData& options)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 795 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 796 connackData data;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 797 return connect(options, data);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 798 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 799
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 800
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 801 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 802 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 803 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 804 MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 805 return connect(default_options);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 806 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 807
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 808
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 809 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 810 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::setMessageHandler(const char* topicFilter, messageHandler messageHandler)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 811 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 812 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 813 int i = -1;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 814
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 815 // first check for an existing matching slot
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 816 for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 817 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 818 if (messageHandlers[i].topicFilter != 0 && strcmp(messageHandlers[i].topicFilter, topicFilter) == 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 819 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 820 if (messageHandler == 0) // remove existing
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 821 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 822 messageHandlers[i].topicFilter = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 823 messageHandlers[i].fp.detach();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 824 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 825 rc = SUCCESS; // return i when adding new subscription
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 826 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 827 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 828 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 829 // if no existing, look for empty slot (unless we are removing)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 830 if (messageHandler != 0) {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 831 if (rc == FAILURE)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 832 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 833 for (i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 834 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 835 if (messageHandlers[i].topicFilter == 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 836 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 837 rc = SUCCESS;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 838 break;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 839 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 840 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 841 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 842 if (i < MAX_MESSAGE_HANDLERS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 843 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 844 messageHandlers[i].topicFilter = topicFilter;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 845 messageHandlers[i].fp.attach(messageHandler);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 846 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 847 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 848 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 849 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 850
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 851
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 852 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 853 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 854 enum QoS qos, messageHandler messageHandler, subackData& data)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 855 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 856 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 857 Timer timer(command_timeout_ms);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 858 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 859 MQTTString topic = {(char*)topicFilter, {0, 0}};
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 860
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 861 if (!isconnected)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 862 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 863
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 864 len = MQTTSerialize_subscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 865 if (len <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 866 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 867 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 868 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 869
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 870 if (waitfor(SUBACK, timer) == SUBACK) // wait for suback
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 871 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 872 int count = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 873 unsigned short mypacketid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 874 data.grantedQoS = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 875 if (MQTTDeserialize_suback(&mypacketid, 1, &count, &data.grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 876 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 877 if (data.grantedQoS != 0x80)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 878 rc = setMessageHandler(topicFilter, messageHandler);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 879 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 880 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 881 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 882 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 883
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 884 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 885 if (rc == FAILURE)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 886 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 887 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 888 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 889
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 890
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 891 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 892 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter, enum QoS qos, messageHandler messageHandler)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 893 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 894 subackData data;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 895 return subscribe(topicFilter, qos, messageHandler, data);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 896 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 897
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 898
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 899 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 900 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(const char* topicFilter)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 901 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 902 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 903 Timer timer(command_timeout_ms);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 904 MQTTString topic = {(char*)topicFilter, {0, 0}};
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 905 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 906
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 907 if (!isconnected)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 908 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 909
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 910 if ((len = MQTTSerialize_unsubscribe(sendbuf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic)) <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 911 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 912 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the unsubscribe packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 913 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 914
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 915 if (waitfor(UNSUBACK, timer) == UNSUBACK)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 916 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 917 unsigned short mypacketid; // should be the same as the packetid above
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 918 if (MQTTDeserialize_unsuback(&mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 919 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 920 // remove the subscription message handler associated with this topic, if there is one
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 921 setMessageHandler(topicFilter, 0);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 922 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 923 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 924 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 925 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 926
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 927 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 928 if (rc != SUCCESS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 929 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 930 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 931 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 932
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 933
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 934 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 935 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(int len, Timer& timer, enum QoS qos)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 936 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 937 int rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 938
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 939 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the publish packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 940 goto exit; // there was a problem
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 941
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 942 #if MQTTCLIENT_QOS1
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 943 if (qos == QOS1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 944 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 945 if (waitfor(PUBACK, timer) == PUBACK)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 946 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 947 unsigned short mypacketid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 948 unsigned char dup, type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 949 if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 950 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 951 else if (inflightMsgid == mypacketid)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 952 inflightMsgid = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 953 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 954 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 955 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 956 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 957 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 958 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 959 else if (qos == QOS2)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 960 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 961 if (waitfor(PUBCOMP, timer) == PUBCOMP)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 962 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 963 unsigned short mypacketid;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 964 unsigned char dup, type;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 965 if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) != 1)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 966 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 967 else if (inflightMsgid == mypacketid)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 968 inflightMsgid = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 969 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 970 else
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 971 rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 972 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 973 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 974
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 975 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 976 if (rc != SUCCESS)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 977 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 978 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 979 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 980
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 981
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 982
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 983 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 984 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos, bool retained)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 985 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 986 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 987 Timer timer(command_timeout_ms);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 988 MQTTString topicString = MQTTString_initializer;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 989 int len = 0;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 990
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 991 if (!isconnected)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 992 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 993
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 994 topicString.cstring = (char*)topicName;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 995
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 996 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 997 if (qos == QOS1 || qos == QOS2)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 998 id = packetid.getNext();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 999 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1000
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1001 len = MQTTSerialize_publish(sendbuf, MAX_MQTT_PACKET_SIZE, 0, qos, retained, id,
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1002 topicString, (unsigned char*)payload, payloadlen);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1003 if (len <= 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1004 goto exit;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1005
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1006 #if MQTTCLIENT_QOS1 || MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1007 if (!cleansession)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1008 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1009 memcpy(pubbuf, sendbuf, len);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1010 inflightMsgid = id;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1011 inflightLen = len;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1012 inflightQoS = qos;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1013 #if MQTTCLIENT_QOS2
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1014 pubrel = false;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1015 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1016 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1017 #endif
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1018
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1019 rc = publish(len, timer, qos);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1020 exit:
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1021 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1022 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1023
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1024
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1025 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1026 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, void* payload, size_t payloadlen, enum QoS qos, bool retained)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1027 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1028 unsigned short id = 0; // dummy - not used for anything
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1029 return publish(topicName, payload, payloadlen, id, qos, retained);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1030 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1031
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1032
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1033 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1034 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, Message& message)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1035 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1036 return publish(topicName, message.payload, message.payloadlen, message.qos, message.retained);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1037 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1038
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1039
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1040 template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b>
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1041 int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::disconnect()
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1042 {
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1043 int rc = FAILURE;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1044 Timer timer(command_timeout_ms); // we might wait for incomplete incoming publishes to complete
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1045 int len = MQTTSerialize_disconnect(sendbuf, MAX_MQTT_PACKET_SIZE);
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1046 if (len > 0)
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1047 rc = sendPacket(len, timer); // send the disconnect packet
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1048 closeSession();
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1049 return rc;
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1050 }
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1051
akhtar.syedzeeshan@gmail.com 0:f4dbe435e64c 1052 #endif