An API for using MQTT over multiple transports
Fork of MQTT by
MQTTClient.h@25:d13a6c558164, 2014-05-09 (annotated)
- Committer:
- sam_grove
- Date:
- Fri May 09 23:01:35 2014 +0000
- Revision:
- 25:d13a6c558164
- Parent:
- 23:05fc7de97d4a
- Child:
- 28:8b2abe9bd814
- Child:
- 29:833386b16f3e
Simplify example by moving IPStack into this library for each transport. Working on FP usage to not need the FP.cpp inclusion in main
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
icraggs | 6:4d312a49200b | 1 | /******************************************************************************* |
icraggs | 6:4d312a49200b | 2 | * Copyright (c) 2014 IBM Corp. |
sam_grove | 0:fe461e4d7afe | 3 | * |
icraggs | 6:4d312a49200b | 4 | * All rights reserved. This program and the accompanying materials |
icraggs | 6:4d312a49200b | 5 | * are made available under the terms of the Eclipse Public License v1.0 |
icraggs | 6:4d312a49200b | 6 | * and Eclipse Distribution License v1.0 which accompany this distribution. |
sam_grove | 0:fe461e4d7afe | 7 | * |
icraggs | 6:4d312a49200b | 8 | * The Eclipse Public License is available at |
icraggs | 6:4d312a49200b | 9 | * http://www.eclipse.org/legal/epl-v10.html |
icraggs | 6:4d312a49200b | 10 | * and the Eclipse Distribution License is available at |
icraggs | 6:4d312a49200b | 11 | * http://www.eclipse.org/org/documents/edl-v10.php. |
sam_grove | 0:fe461e4d7afe | 12 | * |
icraggs | 6:4d312a49200b | 13 | * Contributors: |
icraggs | 6:4d312a49200b | 14 | * Ian Craggs - initial API and implementation and/or initial documentation |
icraggs | 6:4d312a49200b | 15 | *******************************************************************************/ |
icraggs | 21:e918525e529d | 16 | |
icraggs | 21:e918525e529d | 17 | /* |
icraggs | 21:e918525e529d | 18 | |
icraggs | 21:e918525e529d | 19 | TODO: |
icraggs | 21:e918525e529d | 20 | |
icraggs | 21:e918525e529d | 21 | log messages - use macros |
icraggs | 23:05fc7de97d4a | 22 | |
icraggs | 21:e918525e529d | 23 | define return code constants |
icraggs | 21:e918525e529d | 24 | |
icraggs | 23:05fc7de97d4a | 25 | call connectionLost at appropriate points - in sendPacket and readPacket |
icraggs | 23:05fc7de97d4a | 26 | |
icraggs | 23:05fc7de97d4a | 27 | match wildcard topics |
icraggs | 23:05fc7de97d4a | 28 | |
sam_grove | 25:d13a6c558164 | 29 | updating usage of FP. Try to remove inclusion of FP.cpp in main. sg- |
sam_grove | 25:d13a6c558164 | 30 | |
icraggs | 21:e918525e529d | 31 | */ |
sam_grove | 0:fe461e4d7afe | 32 | |
icraggs | 2:dcfdd2abfe71 | 33 | #if !defined(MQTTCLIENT_H) |
icraggs | 2:dcfdd2abfe71 | 34 | #define MQTTCLIENT_H |
icraggs | 2:dcfdd2abfe71 | 35 | |
icraggs | 2:dcfdd2abfe71 | 36 | #include "FP.h" |
icraggs | 3:dbff6b768d28 | 37 | #include "MQTTPacket.h" |
icraggs | 6:4d312a49200b | 38 | #include "stdio.h" |
icraggs | 2:dcfdd2abfe71 | 39 | |
icraggs | 3:dbff6b768d28 | 40 | namespace MQTT |
icraggs | 3:dbff6b768d28 | 41 | { |
icraggs | 3:dbff6b768d28 | 42 | |
icraggs | 2:dcfdd2abfe71 | 43 | |
icraggs | 2:dcfdd2abfe71 | 44 | enum QoS { QOS0, QOS1, QOS2 }; |
sam_grove | 0:fe461e4d7afe | 45 | |
icraggs | 23:05fc7de97d4a | 46 | enum returnCode { BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 }; |
icraggs | 23:05fc7de97d4a | 47 | |
icraggs | 2:dcfdd2abfe71 | 48 | |
icraggs | 3:dbff6b768d28 | 49 | struct Message |
icraggs | 2:dcfdd2abfe71 | 50 | { |
icraggs | 2:dcfdd2abfe71 | 51 | enum QoS qos; |
icraggs | 2:dcfdd2abfe71 | 52 | bool retained; |
icraggs | 2:dcfdd2abfe71 | 53 | bool dup; |
Ian Craggs |
12:cc7f2d62a393 | 54 | unsigned short id; |
icraggs | 2:dcfdd2abfe71 | 55 | void *payload; |
icraggs | 2:dcfdd2abfe71 | 56 | size_t payloadlen; |
sam_grove | 0:fe461e4d7afe | 57 | }; |
sam_grove | 0:fe461e4d7afe | 58 | |
icraggs | 4:4ef00243708e | 59 | |
icraggs | 20:cad3d54d7ecf | 60 | struct MessageData |
icraggs | 20:cad3d54d7ecf | 61 | { |
icraggs | 20:cad3d54d7ecf | 62 | struct Message message; |
icraggs | 20:cad3d54d7ecf | 63 | char* topicName; |
icraggs | 20:cad3d54d7ecf | 64 | }; |
icraggs | 20:cad3d54d7ecf | 65 | |
icraggs | 20:cad3d54d7ecf | 66 | |
icraggs | 9:01b8cc7d94cc | 67 | class PacketId |
icraggs | 9:01b8cc7d94cc | 68 | { |
icraggs | 9:01b8cc7d94cc | 69 | public: |
icraggs | 23:05fc7de97d4a | 70 | PacketId() |
icraggs | 23:05fc7de97d4a | 71 | { |
icraggs | 23:05fc7de97d4a | 72 | next = 0; |
icraggs | 23:05fc7de97d4a | 73 | } |
icraggs | 9:01b8cc7d94cc | 74 | |
icraggs | 23:05fc7de97d4a | 75 | int getNext() |
icraggs | 23:05fc7de97d4a | 76 | { |
icraggs | 23:05fc7de97d4a | 77 | return next = (next == MAX_PACKET_ID) ? 1 : ++next; |
icraggs | 23:05fc7de97d4a | 78 | } |
Ian Craggs |
12:cc7f2d62a393 | 79 | |
icraggs | 9:01b8cc7d94cc | 80 | private: |
icraggs | 9:01b8cc7d94cc | 81 | static const int MAX_PACKET_ID = 65535; |
icraggs | 9:01b8cc7d94cc | 82 | int next; |
icraggs | 9:01b8cc7d94cc | 83 | }; |
icraggs | 2:dcfdd2abfe71 | 84 | |
icraggs | 16:91c2f9a144d4 | 85 | |
icraggs | 21:e918525e529d | 86 | /** |
icraggs | 21:e918525e529d | 87 | * @class Client |
icraggs | 22:aadb79d29330 | 88 | * @brief blocking, non-threaded MQTT client API |
icraggs | 23:05fc7de97d4a | 89 | * |
icraggs | 23:05fc7de97d4a | 90 | * This version of the API blocks on all method calls, until they are complete. This means that only one |
icraggs | 23:05fc7de97d4a | 91 | * MQTT request can be in process at any one time. |
icraggs | 21:e918525e529d | 92 | * @param Network a network class which supports send, receive |
icraggs | 21:e918525e529d | 93 | * @param Timer a timer class with the methods: |
icraggs | 21:e918525e529d | 94 | */ |
icraggs | 23:05fc7de97d4a | 95 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5> class Client |
icraggs | 2:dcfdd2abfe71 | 96 | { |
icraggs | 2:dcfdd2abfe71 | 97 | |
icraggs | 22:aadb79d29330 | 98 | public: |
icraggs | 15:64a57183aa03 | 99 | |
icraggs | 20:cad3d54d7ecf | 100 | typedef struct |
icraggs | 20:cad3d54d7ecf | 101 | { |
icraggs | 20:cad3d54d7ecf | 102 | Client* client; |
icraggs | 20:cad3d54d7ecf | 103 | Network* network; |
icraggs | 20:cad3d54d7ecf | 104 | } connectionLostInfo; |
icraggs | 20:cad3d54d7ecf | 105 | |
icraggs | 20:cad3d54d7ecf | 106 | typedef int (*connectionLostHandlers)(connectionLostInfo*); |
icraggs | 23:05fc7de97d4a | 107 | typedef void (*messageHandler)(Message*); |
icraggs | 23:05fc7de97d4a | 108 | |
icraggs | 23:05fc7de97d4a | 109 | /** Construct the client |
icraggs | 23:05fc7de97d4a | 110 | * @param network - pointer to an instance of the Network class - must be connected to the endpoint |
icraggs | 23:05fc7de97d4a | 111 | * before calling MQTT connect |
icraggs | 23:05fc7de97d4a | 112 | * @param limits an instance of the Limit class - to alter limits as required |
icraggs | 23:05fc7de97d4a | 113 | */ |
icraggs | 23:05fc7de97d4a | 114 | Client(Network& network, unsigned int command_timeout_ms = 30000); |
icraggs | 20:cad3d54d7ecf | 115 | |
icraggs | 20:cad3d54d7ecf | 116 | /** Set the connection lost callback - called whenever the connection is lost and we should be connected |
icraggs | 20:cad3d54d7ecf | 117 | * @param clh - pointer to the callback function |
icraggs | 20:cad3d54d7ecf | 118 | */ |
icraggs | 20:cad3d54d7ecf | 119 | void setConnectionLostHandler(connectionLostHandlers clh) |
icraggs | 20:cad3d54d7ecf | 120 | { |
icraggs | 20:cad3d54d7ecf | 121 | connectionLostHandler.attach(clh); |
icraggs | 20:cad3d54d7ecf | 122 | } |
icraggs | 20:cad3d54d7ecf | 123 | |
icraggs | 20:cad3d54d7ecf | 124 | /** Set the default message handling callback - used for any message which does not match a subscription message handler |
icraggs | 20:cad3d54d7ecf | 125 | * @param mh - pointer to the callback function |
icraggs | 20:cad3d54d7ecf | 126 | */ |
icraggs | 20:cad3d54d7ecf | 127 | void setDefaultMessageHandler(messageHandler mh) |
icraggs | 20:cad3d54d7ecf | 128 | { |
icraggs | 20:cad3d54d7ecf | 129 | defaultMessageHandler.attach(mh); |
icraggs | 20:cad3d54d7ecf | 130 | } |
icraggs | 2:dcfdd2abfe71 | 131 | |
icraggs | 20:cad3d54d7ecf | 132 | /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack |
icraggs | 20:cad3d54d7ecf | 133 | * The nework object must be connected to the network endpoint before calling this |
icraggs | 20:cad3d54d7ecf | 134 | * @param options - connect options |
icraggs | 20:cad3d54d7ecf | 135 | * @return success code - |
icraggs | 20:cad3d54d7ecf | 136 | */ |
icraggs | 20:cad3d54d7ecf | 137 | int connect(MQTTPacket_connectData* options = 0); |
icraggs | 20:cad3d54d7ecf | 138 | |
icraggs | 20:cad3d54d7ecf | 139 | /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs |
icraggs | 20:cad3d54d7ecf | 140 | * @param topic - the topic to publish to |
icraggs | 20:cad3d54d7ecf | 141 | * @param message - the message to send |
icraggs | 20:cad3d54d7ecf | 142 | * @return success code - |
icraggs | 20:cad3d54d7ecf | 143 | */ |
icraggs | 20:cad3d54d7ecf | 144 | int publish(const char* topicName, Message* message); |
icraggs | 20:cad3d54d7ecf | 145 | |
icraggs | 20:cad3d54d7ecf | 146 | /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback |
icraggs | 20:cad3d54d7ecf | 147 | * @param topicFilter - a topic pattern which can include wildcards |
icraggs | 20:cad3d54d7ecf | 148 | * @param qos - the MQTT QoS to subscribe at |
icraggs | 20:cad3d54d7ecf | 149 | * @param mh - the callback function to be invoked when a message is received for this subscription |
icraggs | 20:cad3d54d7ecf | 150 | * @return success code - |
icraggs | 20:cad3d54d7ecf | 151 | */ |
icraggs | 20:cad3d54d7ecf | 152 | int subscribe(const char* topicFilter, enum QoS qos, messageHandler mh); |
icraggs | 9:01b8cc7d94cc | 153 | |
icraggs | 20:cad3d54d7ecf | 154 | /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback |
icraggs | 20:cad3d54d7ecf | 155 | * @param topicFilter - a topic pattern which can include wildcards |
icraggs | 20:cad3d54d7ecf | 156 | * @return success code - |
icraggs | 20:cad3d54d7ecf | 157 | */ |
icraggs | 20:cad3d54d7ecf | 158 | int unsubscribe(const char* topicFilter); |
icraggs | 20:cad3d54d7ecf | 159 | |
icraggs | 20:cad3d54d7ecf | 160 | /** MQTT Disconnect - send an MQTT disconnect packet |
icraggs | 20:cad3d54d7ecf | 161 | * @return success code - |
icraggs | 20:cad3d54d7ecf | 162 | */ |
icraggs | 20:cad3d54d7ecf | 163 | int disconnect(); |
icraggs | 8:c46930bd6c82 | 164 | |
icraggs | 20:cad3d54d7ecf | 165 | /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive |
icraggs | 20:cad3d54d7ecf | 166 | * yield can be called if no other MQTT operation is needed. This will also allow messages to be |
icraggs | 20:cad3d54d7ecf | 167 | * received. |
icraggs | 23:05fc7de97d4a | 168 | * @param timeout_ms the time to wait, in milliseconds |
icraggs | 20:cad3d54d7ecf | 169 | */ |
icraggs | 23:05fc7de97d4a | 170 | void yield(int timeout_ms = 1000); |
icraggs | 20:cad3d54d7ecf | 171 | |
icraggs | 20:cad3d54d7ecf | 172 | private: |
icraggs | 20:cad3d54d7ecf | 173 | |
icraggs | 20:cad3d54d7ecf | 174 | int cycle(Timer& timer); |
icraggs | 20:cad3d54d7ecf | 175 | int waitfor(int packet_type, Timer& timer); |
icraggs | 20:cad3d54d7ecf | 176 | int keepalive(); |
icraggs | 2:dcfdd2abfe71 | 177 | |
icraggs | 3:dbff6b768d28 | 178 | int decodePacket(int* value, int timeout); |
icraggs | 20:cad3d54d7ecf | 179 | int readPacket(Timer& timer); |
icraggs | 20:cad3d54d7ecf | 180 | int sendPacket(int length, Timer& timer); |
icraggs | 20:cad3d54d7ecf | 181 | int deliverMessage(MQTTString* topic, Message* message); |
icraggs | 3:dbff6b768d28 | 182 | |
icraggs | 23:05fc7de97d4a | 183 | Network& ipstack; |
icraggs | 23:05fc7de97d4a | 184 | unsigned int command_timeout_ms; |
icraggs | 16:91c2f9a144d4 | 185 | |
icraggs | 23:05fc7de97d4a | 186 | char buf[MAX_MQTT_PACKET_SIZE]; |
icraggs | 23:05fc7de97d4a | 187 | char readbuf[MAX_MQTT_PACKET_SIZE]; |
icraggs | 15:64a57183aa03 | 188 | |
icraggs | 20:cad3d54d7ecf | 189 | Timer ping_timer; |
icraggs | 15:64a57183aa03 | 190 | unsigned int keepAliveInterval; |
icraggs | 20:cad3d54d7ecf | 191 | bool ping_outstanding; |
icraggs | 4:4ef00243708e | 192 | |
icraggs | 9:01b8cc7d94cc | 193 | PacketId packetid; |
icraggs | 9:01b8cc7d94cc | 194 | |
sam_grove | 25:d13a6c558164 | 195 | // typedef FP<void, Message*> messageHandlerFP; |
sam_grove | 25:d13a6c558164 | 196 | // FP<void, Message*> messageHandlerFP; |
icraggs | 16:91c2f9a144d4 | 197 | struct MessageHandlers |
icraggs | 15:64a57183aa03 | 198 | { |
icraggs | 20:cad3d54d7ecf | 199 | const char* topic; |
sam_grove | 25:d13a6c558164 | 200 | FP<void, Message*> fp; |
icraggs | 23:05fc7de97d4a | 201 | } messageHandlers[MAX_MESSAGE_HANDLERS]; // Message handlers are indexed by subscription topic |
icraggs | 15:64a57183aa03 | 202 | |
sam_grove | 25:d13a6c558164 | 203 | FP<void, Message*> defaultMessageHandler; |
icraggs | 20:cad3d54d7ecf | 204 | |
sam_grove | 25:d13a6c558164 | 205 | FP<int, connectionLostInfo*> connectionLostHandler; |
sam_grove | 25:d13a6c558164 | 206 | // connectionLostFP connectionLostHandler; |
icraggs | 11:db15da110a37 | 207 | |
sam_grove | 0:fe461e4d7afe | 208 | }; |
sam_grove | 0:fe461e4d7afe | 209 | |
icraggs | 15:64a57183aa03 | 210 | } |
icraggs | 15:64a57183aa03 | 211 | |
icraggs | 15:64a57183aa03 | 212 | |
icraggs | 23:05fc7de97d4a | 213 | template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS> |
icraggs | 23:05fc7de97d4a | 214 | MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms) : ipstack(network), packetid() |
icraggs | 15:64a57183aa03 | 215 | { |
icraggs | 23:05fc7de97d4a | 216 | ping_timer = Timer(); |
icraggs | 23:05fc7de97d4a | 217 | ping_outstanding = 0; |
icraggs | 23:05fc7de97d4a | 218 | for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i) |
icraggs | 20:cad3d54d7ecf | 219 | messageHandlers[i].topic = 0; |
icraggs | 23:05fc7de97d4a | 220 | this->command_timeout_ms = command_timeout_ms; |
icraggs | 11:db15da110a37 | 221 | } |
icraggs | 11:db15da110a37 | 222 | |
icraggs | 11:db15da110a37 | 223 | |
icraggs | 23:05fc7de97d4a | 224 | template<class Network, class Timer, int a, int b> |
icraggs | 23:05fc7de97d4a | 225 | int MQTT::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer) |
icraggs | 8:c46930bd6c82 | 226 | { |
icraggs | 23:05fc7de97d4a | 227 | int rc = FAILURE, |
icraggs | 23:05fc7de97d4a | 228 | sent = 0; |
icraggs | 8:c46930bd6c82 | 229 | |
icraggs | 23:05fc7de97d4a | 230 | while (sent < length && !timer.expired()) |
icraggs | 23:05fc7de97d4a | 231 | { |
icraggs | 23:05fc7de97d4a | 232 | rc = ipstack.write(&buf[sent], length, timer.left_ms()); |
icraggs | 23:05fc7de97d4a | 233 | if (rc == -1) |
icraggs | 23:05fc7de97d4a | 234 | { |
icraggs | 23:05fc7de97d4a | 235 | connectionLostInfo info = {this, &ipstack}; |
icraggs | 23:05fc7de97d4a | 236 | connectionLostHandler(&info); |
icraggs | 23:05fc7de97d4a | 237 | } |
icraggs | 23:05fc7de97d4a | 238 | else |
icraggs | 23:05fc7de97d4a | 239 | sent += rc; |
icraggs | 23:05fc7de97d4a | 240 | } |
icraggs | 20:cad3d54d7ecf | 241 | if (sent == length) |
icraggs | 23:05fc7de97d4a | 242 | { |
icraggs | 20:cad3d54d7ecf | 243 | ping_timer.countdown(this->keepAliveInterval); // record the fact that we have successfully sent the packet |
icraggs | 23:05fc7de97d4a | 244 | rc = SUCCESS; |
icraggs | 23:05fc7de97d4a | 245 | } |
icraggs | 23:05fc7de97d4a | 246 | else |
icraggs | 23:05fc7de97d4a | 247 | rc = FAILURE; |
icraggs | 23:05fc7de97d4a | 248 | return rc; |
icraggs | 8:c46930bd6c82 | 249 | } |
icraggs | 8:c46930bd6c82 | 250 | |
icraggs | 8:c46930bd6c82 | 251 | |
icraggs | 23:05fc7de97d4a | 252 | template<class Network, class Timer, int a, int b> int MQTT::Client<Network, Timer, a, b>::decodePacket(int* value, int timeout) |
icraggs | 8:c46930bd6c82 | 253 | { |
icraggs | 8:c46930bd6c82 | 254 | char c; |
icraggs | 8:c46930bd6c82 | 255 | int multiplier = 1; |
icraggs | 8:c46930bd6c82 | 256 | int len = 0; |
icraggs | 20:cad3d54d7ecf | 257 | const int MAX_NO_OF_REMAINING_LENGTH_BYTES = 4; |
icraggs | 8:c46930bd6c82 | 258 | |
icraggs | 8:c46930bd6c82 | 259 | *value = 0; |
icraggs | 8:c46930bd6c82 | 260 | do |
icraggs | 8:c46930bd6c82 | 261 | { |
icraggs | 8:c46930bd6c82 | 262 | int rc = MQTTPACKET_READ_ERROR; |
icraggs | 8:c46930bd6c82 | 263 | |
icraggs | 8:c46930bd6c82 | 264 | if (++len > MAX_NO_OF_REMAINING_LENGTH_BYTES) |
icraggs | 8:c46930bd6c82 | 265 | { |
icraggs | 8:c46930bd6c82 | 266 | rc = MQTTPACKET_READ_ERROR; /* bad data */ |
icraggs | 8:c46930bd6c82 | 267 | goto exit; |
icraggs | 8:c46930bd6c82 | 268 | } |
icraggs | 23:05fc7de97d4a | 269 | rc = ipstack.read(&c, 1, timeout); |
icraggs | 8:c46930bd6c82 | 270 | if (rc != 1) |
icraggs | 8:c46930bd6c82 | 271 | goto exit; |
icraggs | 8:c46930bd6c82 | 272 | *value += (c & 127) * multiplier; |
icraggs | 8:c46930bd6c82 | 273 | multiplier *= 128; |
icraggs | 8:c46930bd6c82 | 274 | } while ((c & 128) != 0); |
icraggs | 8:c46930bd6c82 | 275 | exit: |
icraggs | 8:c46930bd6c82 | 276 | return len; |
icraggs | 8:c46930bd6c82 | 277 | } |
icraggs | 8:c46930bd6c82 | 278 | |
icraggs | 8:c46930bd6c82 | 279 | |
icraggs | 8:c46930bd6c82 | 280 | /** |
icraggs | 8:c46930bd6c82 | 281 | * If any read fails in this method, then we should disconnect from the network, as on reconnect |
icraggs | 8:c46930bd6c82 | 282 | * the packets can be retried. |
icraggs | 8:c46930bd6c82 | 283 | * @param timeout the max time to wait for the packet read to complete, in milliseconds |
icraggs | 8:c46930bd6c82 | 284 | * @return the MQTT packet type, or -1 if none |
icraggs | 8:c46930bd6c82 | 285 | */ |
icraggs | 23:05fc7de97d4a | 286 | template<class Network, class Timer, int a, int b> |
icraggs | 23:05fc7de97d4a | 287 | int MQTT::Client<Network, Timer, a, b>::readPacket(Timer& timer) |
icraggs | 8:c46930bd6c82 | 288 | { |
icraggs | 8:c46930bd6c82 | 289 | int rc = -1; |
icraggs | 8:c46930bd6c82 | 290 | MQTTHeader header = {0}; |
icraggs | 8:c46930bd6c82 | 291 | int len = 0; |
icraggs | 8:c46930bd6c82 | 292 | int rem_len = 0; |
icraggs | 8:c46930bd6c82 | 293 | |
icraggs | 8:c46930bd6c82 | 294 | /* 1. read the header byte. This has the packet type in it */ |
icraggs | 23:05fc7de97d4a | 295 | if (ipstack.read(readbuf, 1, timer.left_ms()) != 1) |
icraggs | 8:c46930bd6c82 | 296 | goto exit; |
icraggs | 8:c46930bd6c82 | 297 | |
icraggs | 8:c46930bd6c82 | 298 | len = 1; |
icraggs | 8:c46930bd6c82 | 299 | /* 2. read the remaining length. This is variable in itself */ |
icraggs | 20:cad3d54d7ecf | 300 | decodePacket(&rem_len, timer.left_ms()); |
icraggs | 8:c46930bd6c82 | 301 | len += MQTTPacket_encode(readbuf + 1, rem_len); /* put the original remaining length back into the buffer */ |
icraggs | 8:c46930bd6c82 | 302 | |
icraggs | 8:c46930bd6c82 | 303 | /* 3. read the rest of the buffer using a callback to supply the rest of the data */ |
icraggs | 23:05fc7de97d4a | 304 | if (ipstack.read(readbuf + len, rem_len, timer.left_ms()) != rem_len) |
icraggs | 8:c46930bd6c82 | 305 | goto exit; |
icraggs | 8:c46930bd6c82 | 306 | |
icraggs | 8:c46930bd6c82 | 307 | header.byte = readbuf[0]; |
icraggs | 8:c46930bd6c82 | 308 | rc = header.bits.type; |
icraggs | 8:c46930bd6c82 | 309 | exit: |
icraggs | 8:c46930bd6c82 | 310 | return rc; |
icraggs | 3:dbff6b768d28 | 311 | } |
icraggs | 3:dbff6b768d28 | 312 | |
icraggs | 8:c46930bd6c82 | 313 | |
icraggs | 23:05fc7de97d4a | 314 | template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS> |
icraggs | 23:05fc7de97d4a | 315 | int MQTT::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTString* topic, Message* message) |
icraggs | 15:64a57183aa03 | 316 | { |
icraggs | 20:cad3d54d7ecf | 317 | int rc = -1; |
icraggs | 20:cad3d54d7ecf | 318 | |
icraggs | 20:cad3d54d7ecf | 319 | // we have to find the right message handler - indexed by topic |
icraggs | 23:05fc7de97d4a | 320 | for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i) |
icraggs | 20:cad3d54d7ecf | 321 | { |
icraggs | 20:cad3d54d7ecf | 322 | if (messageHandlers[i].topic != 0 && MQTTPacket_equals(topic, (char*)messageHandlers[i].topic)) |
icraggs | 20:cad3d54d7ecf | 323 | { |
icraggs | 20:cad3d54d7ecf | 324 | messageHandlers[i].fp(message); |
icraggs | 20:cad3d54d7ecf | 325 | rc = 0; |
icraggs | 20:cad3d54d7ecf | 326 | break; |
icraggs | 20:cad3d54d7ecf | 327 | } |
icraggs | 20:cad3d54d7ecf | 328 | } |
icraggs | 20:cad3d54d7ecf | 329 | if (rc == -1) |
icraggs | 20:cad3d54d7ecf | 330 | defaultMessageHandler(message); |
icraggs | 20:cad3d54d7ecf | 331 | |
icraggs | 20:cad3d54d7ecf | 332 | return rc; |
icraggs | 15:64a57183aa03 | 333 | } |
icraggs | 15:64a57183aa03 | 334 | |
icraggs | 15:64a57183aa03 | 335 | |
icraggs | 20:cad3d54d7ecf | 336 | |
icraggs | 23:05fc7de97d4a | 337 | template<class Network, class Timer, int a, int b> |
icraggs | 23:05fc7de97d4a | 338 | void MQTT::Client<Network, Timer, a, b>::yield(int timeout_ms) |
icraggs | 20:cad3d54d7ecf | 339 | { |
icraggs | 20:cad3d54d7ecf | 340 | Timer timer = Timer(); |
icraggs | 20:cad3d54d7ecf | 341 | |
icraggs | 23:05fc7de97d4a | 342 | timer.countdown_ms(timeout_ms); |
icraggs | 20:cad3d54d7ecf | 343 | while (!timer.expired()) |
icraggs | 20:cad3d54d7ecf | 344 | cycle(timer); |
icraggs | 20:cad3d54d7ecf | 345 | } |
icraggs | 20:cad3d54d7ecf | 346 | |
icraggs | 20:cad3d54d7ecf | 347 | |
icraggs | 23:05fc7de97d4a | 348 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b> |
icraggs | 23:05fc7de97d4a | 349 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::cycle(Timer& timer) |
icraggs | 8:c46930bd6c82 | 350 | { |
icraggs | 8:c46930bd6c82 | 351 | /* get one piece of work off the wire and one pass through */ |
icraggs | 20:cad3d54d7ecf | 352 | |
Ian Craggs |
12:cc7f2d62a393 | 353 | // read the socket, see what work is due |
icraggs | 20:cad3d54d7ecf | 354 | int packet_type = readPacket(timer); |
icraggs | 15:64a57183aa03 | 355 | |
sam_grove | 25:d13a6c558164 | 356 | int len = 0, rc; |
icraggs | 8:c46930bd6c82 | 357 | switch (packet_type) |
icraggs | 8:c46930bd6c82 | 358 | { |
icraggs | 15:64a57183aa03 | 359 | case CONNACK: |
icraggs | 8:c46930bd6c82 | 360 | case PUBACK: |
icraggs | 8:c46930bd6c82 | 361 | case SUBACK: |
icraggs | 8:c46930bd6c82 | 362 | break; |
icraggs | 15:64a57183aa03 | 363 | case PUBLISH: |
icraggs | 20:cad3d54d7ecf | 364 | MQTTString topicName; |
icraggs | 20:cad3d54d7ecf | 365 | Message msg; |
icraggs | 20:cad3d54d7ecf | 366 | rc = MQTTDeserialize_publish((int*)&msg.dup, (int*)&msg.qos, (int*)&msg.retained, (int*)&msg.id, &topicName, |
icraggs | 23:05fc7de97d4a | 367 | (char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_MQTT_PACKET_SIZE);; |
sam_grove | 25:d13a6c558164 | 368 | rc = rc; // make sure optimizer doesnt omit this |
icraggs | 20:cad3d54d7ecf | 369 | deliverMessage(&topicName, &msg); |
icraggs | 20:cad3d54d7ecf | 370 | if (msg.qos != QOS0) |
icraggs | 20:cad3d54d7ecf | 371 | { |
icraggs | 20:cad3d54d7ecf | 372 | if (msg.qos == QOS1) |
icraggs | 23:05fc7de97d4a | 373 | len = MQTTSerialize_ack(buf, MAX_MQTT_PACKET_SIZE, PUBACK, 0, msg.id); |
icraggs | 20:cad3d54d7ecf | 374 | else if (msg.qos == QOS2) |
icraggs | 23:05fc7de97d4a | 375 | len = MQTTSerialize_ack(buf, MAX_MQTT_PACKET_SIZE, PUBREC, 0, msg.id); |
icraggs | 23:05fc7de97d4a | 376 | if ((rc = sendPacket(len, timer)) != SUCCESS) |
icraggs | 20:cad3d54d7ecf | 377 | goto exit; // there was a problem |
icraggs | 20:cad3d54d7ecf | 378 | } |
Ian Craggs |
12:cc7f2d62a393 | 379 | break; |
icraggs | 15:64a57183aa03 | 380 | case PUBREC: |
icraggs | 20:cad3d54d7ecf | 381 | int type, dup, mypacketid; |
icraggs | 23:05fc7de97d4a | 382 | if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 383 | ; |
icraggs | 23:05fc7de97d4a | 384 | len = MQTTSerialize_ack(buf, MAX_MQTT_PACKET_SIZE, PUBREL, 0, mypacketid); |
icraggs | 23:05fc7de97d4a | 385 | if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet |
icraggs | 20:cad3d54d7ecf | 386 | goto exit; // there was a problem |
Ian Craggs |
12:cc7f2d62a393 | 387 | |
icraggs | 8:c46930bd6c82 | 388 | break; |
icraggs | 8:c46930bd6c82 | 389 | case PUBCOMP: |
icraggs | 8:c46930bd6c82 | 390 | break; |
icraggs | 15:64a57183aa03 | 391 | case PINGRESP: |
icraggs | 20:cad3d54d7ecf | 392 | ping_outstanding = false; |
icraggs | 8:c46930bd6c82 | 393 | break; |
icraggs | 15:64a57183aa03 | 394 | } |
icraggs | 20:cad3d54d7ecf | 395 | keepalive(); |
Ian Craggs |
12:cc7f2d62a393 | 396 | exit: |
icraggs | 8:c46930bd6c82 | 397 | return packet_type; |
icraggs | 15:64a57183aa03 | 398 | } |
icraggs | 15:64a57183aa03 | 399 | |
icraggs | 15:64a57183aa03 | 400 | |
icraggs | 23:05fc7de97d4a | 401 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b> |
icraggs | 23:05fc7de97d4a | 402 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::keepalive() |
icraggs | 15:64a57183aa03 | 403 | { |
icraggs | 20:cad3d54d7ecf | 404 | int rc = 0; |
icraggs | 15:64a57183aa03 | 405 | |
icraggs | 20:cad3d54d7ecf | 406 | if (keepAliveInterval == 0) |
icraggs | 20:cad3d54d7ecf | 407 | goto exit; |
icraggs | 15:64a57183aa03 | 408 | |
icraggs | 20:cad3d54d7ecf | 409 | if (ping_timer.expired()) |
icraggs | 20:cad3d54d7ecf | 410 | { |
icraggs | 20:cad3d54d7ecf | 411 | if (ping_outstanding) |
icraggs | 20:cad3d54d7ecf | 412 | rc = -1; |
icraggs | 20:cad3d54d7ecf | 413 | else |
icraggs | 20:cad3d54d7ecf | 414 | { |
icraggs | 20:cad3d54d7ecf | 415 | Timer timer = Timer(1000); |
icraggs | 23:05fc7de97d4a | 416 | int len = MQTTSerialize_pingreq(buf, MAX_MQTT_PACKET_SIZE); |
icraggs | 20:cad3d54d7ecf | 417 | rc = sendPacket(len, timer); // send the ping packet |
icraggs | 23:05fc7de97d4a | 418 | if (rc != SUCCESS) |
icraggs | 20:cad3d54d7ecf | 419 | rc = -1; // indicate there's a problem |
icraggs | 20:cad3d54d7ecf | 420 | else |
icraggs | 20:cad3d54d7ecf | 421 | ping_outstanding = true; |
icraggs | 20:cad3d54d7ecf | 422 | } |
icraggs | 20:cad3d54d7ecf | 423 | } |
icraggs | 15:64a57183aa03 | 424 | |
icraggs | 15:64a57183aa03 | 425 | exit: |
icraggs | 20:cad3d54d7ecf | 426 | return rc; |
icraggs | 8:c46930bd6c82 | 427 | } |
icraggs | 8:c46930bd6c82 | 428 | |
icraggs | 8:c46930bd6c82 | 429 | |
icraggs | 16:91c2f9a144d4 | 430 | // only used in single-threaded mode where one command at a time is in process |
icraggs | 23:05fc7de97d4a | 431 | template<class Network, class Timer, int a, int b> |
icraggs | 23:05fc7de97d4a | 432 | int MQTT::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer) |
icraggs | 15:64a57183aa03 | 433 | { |
icraggs | 20:cad3d54d7ecf | 434 | int rc = -1; |
icraggs | 20:cad3d54d7ecf | 435 | |
icraggs | 20:cad3d54d7ecf | 436 | do |
icraggs | 16:91c2f9a144d4 | 437 | { |
icraggs | 20:cad3d54d7ecf | 438 | if (timer.expired()) |
icraggs | 20:cad3d54d7ecf | 439 | break; // we timed out |
icraggs | 20:cad3d54d7ecf | 440 | } |
icraggs | 20:cad3d54d7ecf | 441 | while ((rc = cycle(timer)) != packet_type); |
icraggs | 20:cad3d54d7ecf | 442 | |
icraggs | 20:cad3d54d7ecf | 443 | return rc; |
icraggs | 16:91c2f9a144d4 | 444 | } |
icraggs | 16:91c2f9a144d4 | 445 | |
icraggs | 16:91c2f9a144d4 | 446 | |
icraggs | 23:05fc7de97d4a | 447 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b> |
icraggs | 23:05fc7de97d4a | 448 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::connect(MQTTPacket_connectData* options) |
icraggs | 16:91c2f9a144d4 | 449 | { |
icraggs | 23:05fc7de97d4a | 450 | Timer connect_timer = Timer(command_timeout_ms); |
icraggs | 8:c46930bd6c82 | 451 | |
Ian Craggs |
12:cc7f2d62a393 | 452 | MQTTPacket_connectData default_options = MQTTPacket_connectData_initializer; |
icraggs | 8:c46930bd6c82 | 453 | if (options == 0) |
Ian Craggs |
12:cc7f2d62a393 | 454 | options = &default_options; // set default options if none were supplied |
icraggs | 8:c46930bd6c82 | 455 | |
icraggs | 15:64a57183aa03 | 456 | this->keepAliveInterval = options->keepAliveInterval; |
icraggs | 20:cad3d54d7ecf | 457 | ping_timer.countdown(this->keepAliveInterval); |
icraggs | 23:05fc7de97d4a | 458 | int len = MQTTSerialize_connect(buf, MAX_MQTT_PACKET_SIZE, options); |
icraggs | 20:cad3d54d7ecf | 459 | int rc = sendPacket(len, connect_timer); // send the connect packet |
icraggs | 23:05fc7de97d4a | 460 | if (rc != SUCCESS) |
icraggs | 20:cad3d54d7ecf | 461 | goto exit; // there was a problem |
icraggs | 8:c46930bd6c82 | 462 | |
icraggs | 20:cad3d54d7ecf | 463 | // this will be a blocking call, wait for the connack |
icraggs | 20:cad3d54d7ecf | 464 | if (waitfor(CONNACK, connect_timer) == CONNACK) |
icraggs | 15:64a57183aa03 | 465 | { |
icraggs | 20:cad3d54d7ecf | 466 | int connack_rc = -1; |
icraggs | 23:05fc7de97d4a | 467 | if (MQTTDeserialize_connack(&connack_rc, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 468 | rc = connack_rc; |
icraggs | 8:c46930bd6c82 | 469 | } |
icraggs | 15:64a57183aa03 | 470 | |
icraggs | 15:64a57183aa03 | 471 | exit: |
icraggs | 8:c46930bd6c82 | 472 | return rc; |
icraggs | 8:c46930bd6c82 | 473 | } |
icraggs | 8:c46930bd6c82 | 474 | |
icraggs | 8:c46930bd6c82 | 475 | |
icraggs | 23:05fc7de97d4a | 476 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS> |
icraggs | 23:05fc7de97d4a | 477 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(const char* topicFilter, enum QoS qos, messageHandler messageHandler) |
icraggs | 20:cad3d54d7ecf | 478 | { |
icraggs | 20:cad3d54d7ecf | 479 | int len = -1; |
icraggs | 23:05fc7de97d4a | 480 | Timer timer = Timer(command_timeout_ms); |
icraggs | 20:cad3d54d7ecf | 481 | |
icraggs | 8:c46930bd6c82 | 482 | MQTTString topic = {(char*)topicFilter, 0, 0}; |
icraggs | 8:c46930bd6c82 | 483 | |
icraggs | 23:05fc7de97d4a | 484 | int rc = MQTTSerialize_subscribe(buf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic, (int*)&qos); |
icraggs | 20:cad3d54d7ecf | 485 | if (rc <= 0) |
icraggs | 20:cad3d54d7ecf | 486 | goto exit; |
icraggs | 20:cad3d54d7ecf | 487 | len = rc; |
icraggs | 23:05fc7de97d4a | 488 | if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet |
icraggs | 20:cad3d54d7ecf | 489 | goto exit; // there was a problem |
icraggs | 8:c46930bd6c82 | 490 | |
icraggs | 20:cad3d54d7ecf | 491 | if (waitfor(SUBACK, timer) == SUBACK) // wait for suback |
icraggs | 8:c46930bd6c82 | 492 | { |
icraggs | 20:cad3d54d7ecf | 493 | int count = 0, grantedQoS = -1, mypacketid; |
icraggs | 23:05fc7de97d4a | 494 | if (MQTTDeserialize_suback(&mypacketid, 1, &count, &grantedQoS, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 495 | rc = grantedQoS; // 0, 1, 2 or 0x80 |
icraggs | 20:cad3d54d7ecf | 496 | if (rc != 0x80) |
icraggs | 8:c46930bd6c82 | 497 | { |
icraggs | 23:05fc7de97d4a | 498 | for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i) |
icraggs | 16:91c2f9a144d4 | 499 | { |
icraggs | 20:cad3d54d7ecf | 500 | if (messageHandlers[i].topic == 0) |
icraggs | 20:cad3d54d7ecf | 501 | { |
icraggs | 20:cad3d54d7ecf | 502 | messageHandlers[i].topic = topicFilter; |
icraggs | 20:cad3d54d7ecf | 503 | messageHandlers[i].fp.attach(messageHandler); |
icraggs | 20:cad3d54d7ecf | 504 | rc = 0; |
icraggs | 20:cad3d54d7ecf | 505 | break; |
icraggs | 20:cad3d54d7ecf | 506 | } |
icraggs | 16:91c2f9a144d4 | 507 | } |
icraggs | 8:c46930bd6c82 | 508 | } |
icraggs | 8:c46930bd6c82 | 509 | } |
icraggs | 15:64a57183aa03 | 510 | |
icraggs | 15:64a57183aa03 | 511 | exit: |
Ian Craggs |
12:cc7f2d62a393 | 512 | return rc; |
icraggs | 15:64a57183aa03 | 513 | } |
icraggs | 15:64a57183aa03 | 514 | |
icraggs | 15:64a57183aa03 | 515 | |
icraggs | 23:05fc7de97d4a | 516 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int MAX_MESSAGE_HANDLERS> |
icraggs | 23:05fc7de97d4a | 517 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(const char* topicFilter) |
icraggs | 20:cad3d54d7ecf | 518 | { |
icraggs | 20:cad3d54d7ecf | 519 | int len = -1; |
icraggs | 23:05fc7de97d4a | 520 | Timer timer = Timer(command_timeout_ms); |
icraggs | 20:cad3d54d7ecf | 521 | |
Ian Craggs |
12:cc7f2d62a393 | 522 | MQTTString topic = {(char*)topicFilter, 0, 0}; |
icraggs | 8:c46930bd6c82 | 523 | |
icraggs | 23:05fc7de97d4a | 524 | int rc = MQTTSerialize_unsubscribe(buf, MAX_MQTT_PACKET_SIZE, 0, packetid.getNext(), 1, &topic); |
icraggs | 20:cad3d54d7ecf | 525 | if (rc <= 0) |
icraggs | 20:cad3d54d7ecf | 526 | goto exit; |
icraggs | 20:cad3d54d7ecf | 527 | len = rc; |
icraggs | 23:05fc7de97d4a | 528 | if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet |
icraggs | 20:cad3d54d7ecf | 529 | goto exit; // there was a problem |
Ian Craggs |
12:cc7f2d62a393 | 530 | |
icraggs | 20:cad3d54d7ecf | 531 | if (waitfor(UNSUBACK, timer) == UNSUBACK) |
Ian Craggs |
12:cc7f2d62a393 | 532 | { |
icraggs | 20:cad3d54d7ecf | 533 | int mypacketid; // should be the same as the packetid above |
icraggs | 23:05fc7de97d4a | 534 | if (MQTTDeserialize_unsuback(&mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 535 | rc = 0; |
Ian Craggs |
12:cc7f2d62a393 | 536 | } |
icraggs | 15:64a57183aa03 | 537 | |
icraggs | 15:64a57183aa03 | 538 | exit: |
Ian Craggs |
12:cc7f2d62a393 | 539 | return rc; |
icraggs | 15:64a57183aa03 | 540 | } |
icraggs | 15:64a57183aa03 | 541 | |
icraggs | 15:64a57183aa03 | 542 | |
icraggs | 15:64a57183aa03 | 543 | |
icraggs | 23:05fc7de97d4a | 544 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b> |
icraggs | 23:05fc7de97d4a | 545 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::publish(const char* topicName, Message* message) |
icraggs | 20:cad3d54d7ecf | 546 | { |
icraggs | 23:05fc7de97d4a | 547 | Timer timer = Timer(command_timeout_ms); |
icraggs | 20:cad3d54d7ecf | 548 | |
icraggs | 20:cad3d54d7ecf | 549 | MQTTString topicString = {(char*)topicName, 0, 0}; |
icraggs | 15:64a57183aa03 | 550 | |
icraggs | 20:cad3d54d7ecf | 551 | if (message->qos == QOS1 || message->qos == QOS2) |
icraggs | 20:cad3d54d7ecf | 552 | message->id = packetid.getNext(); |
icraggs | 15:64a57183aa03 | 553 | |
icraggs | 23:05fc7de97d4a | 554 | int len = MQTTSerialize_publish(buf, MAX_MQTT_PACKET_SIZE, 0, message->qos, message->retained, message->id, |
icraggs | 20:cad3d54d7ecf | 555 | topicString, (char*)message->payload, message->payloadlen); |
icraggs | 20:cad3d54d7ecf | 556 | int rc = sendPacket(len, timer); // send the subscribe packet |
icraggs | 23:05fc7de97d4a | 557 | if (rc != SUCCESS) |
icraggs | 20:cad3d54d7ecf | 558 | goto exit; // there was a problem |
Ian Craggs |
12:cc7f2d62a393 | 559 | |
icraggs | 20:cad3d54d7ecf | 560 | if (message->qos == QOS1) |
Ian Craggs |
12:cc7f2d62a393 | 561 | { |
icraggs | 20:cad3d54d7ecf | 562 | if (waitfor(PUBACK, timer) == PUBACK) |
icraggs | 20:cad3d54d7ecf | 563 | { |
icraggs | 20:cad3d54d7ecf | 564 | int type, dup, mypacketid; |
icraggs | 23:05fc7de97d4a | 565 | if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 566 | rc = 0; |
icraggs | 20:cad3d54d7ecf | 567 | } |
Ian Craggs |
12:cc7f2d62a393 | 568 | } |
icraggs | 20:cad3d54d7ecf | 569 | else if (message->qos == QOS2) |
Ian Craggs |
12:cc7f2d62a393 | 570 | { |
icraggs | 20:cad3d54d7ecf | 571 | if (waitfor(PUBCOMP, timer) == PUBCOMP) |
icraggs | 20:cad3d54d7ecf | 572 | { |
icraggs | 20:cad3d54d7ecf | 573 | int type, dup, mypacketid; |
icraggs | 23:05fc7de97d4a | 574 | if (MQTTDeserialize_ack(&type, &dup, &mypacketid, readbuf, MAX_MQTT_PACKET_SIZE) == 1) |
icraggs | 20:cad3d54d7ecf | 575 | rc = 0; |
icraggs | 20:cad3d54d7ecf | 576 | } |
Ian Craggs |
12:cc7f2d62a393 | 577 | } |
icraggs | 15:64a57183aa03 | 578 | |
icraggs | 15:64a57183aa03 | 579 | exit: |
icraggs | 8:c46930bd6c82 | 580 | return rc; |
icraggs | 8:c46930bd6c82 | 581 | } |
icraggs | 8:c46930bd6c82 | 582 | |
icraggs | 8:c46930bd6c82 | 583 | |
icraggs | 23:05fc7de97d4a | 584 | template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE, int b> |
icraggs | 23:05fc7de97d4a | 585 | int MQTT::Client<Network, Timer, MAX_MQTT_PACKET_SIZE, b>::disconnect() |
icraggs | 20:cad3d54d7ecf | 586 | { |
icraggs | 23:05fc7de97d4a | 587 | Timer timer = Timer(command_timeout_ms); // we might wait for incomplete incoming publishes to complete |
icraggs | 23:05fc7de97d4a | 588 | int len = MQTTSerialize_disconnect(buf, MAX_MQTT_PACKET_SIZE); |
icraggs | 20:cad3d54d7ecf | 589 | int rc = sendPacket(len, timer); // send the disconnect packet |
icraggs | 20:cad3d54d7ecf | 590 | |
icraggs | 23:05fc7de97d4a | 591 | return rc; |
icraggs | 20:cad3d54d7ecf | 592 | } |
icraggs | 20:cad3d54d7ecf | 593 | |
icraggs | 20:cad3d54d7ecf | 594 | |
icraggs | 20:cad3d54d7ecf | 595 | #endif |