Example project to publish messages to a MQTT-SN broker using the u-blox SARA-N200 NB-IoT modem

Dependencies:   MQTTSNPacket X-NUCLEO-SARA-N200

Committer:
KeystoneElectronic
Date:
Wed Aug 22 16:31:30 2018 +0200
Revision:
7:ab32680de141
Parent:
1:70b751b7a189
Use json

Who changed what in which revision?

UserRevisionLine numberNew contents of line
keystone.electronic.solutions@gmail.com 1:70b751b7a189 1 /*******************************************************************************
keystone.electronic.solutions@gmail.com 1:70b751b7a189 2 * Copyright (c) 2014, 2015 IBM Corp.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 3 *
keystone.electronic.solutions@gmail.com 1:70b751b7a189 4 * All rights reserved. This program and the accompanying materials
keystone.electronic.solutions@gmail.com 1:70b751b7a189 5 * are made available under the terms of the Eclipse Public License v1.0
keystone.electronic.solutions@gmail.com 1:70b751b7a189 6 * and Eclipse Distribution License v1.0 which accompany this distribution.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 7 *
keystone.electronic.solutions@gmail.com 1:70b751b7a189 8 * The Eclipse Public License is available at
keystone.electronic.solutions@gmail.com 1:70b751b7a189 9 * http://www.eclipse.org/legal/epl-v10.html
keystone.electronic.solutions@gmail.com 1:70b751b7a189 10 * and the Eclipse Distribution License is available at
keystone.electronic.solutions@gmail.com 1:70b751b7a189 11 * http://www.eclipse.org/org/documents/edl-v10.php.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 12 *
keystone.electronic.solutions@gmail.com 1:70b751b7a189 13 * Contributors:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 14 * Ian Craggs - initial API and implementation and/or initial documentation
keystone.electronic.solutions@gmail.com 1:70b751b7a189 15 *******************************************************************************/
keystone.electronic.solutions@gmail.com 1:70b751b7a189 16
keystone.electronic.solutions@gmail.com 1:70b751b7a189 17 #if !defined(MQTTSNCLIENT_H)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 18 #define MQTTSNCLIENT_H
keystone.electronic.solutions@gmail.com 1:70b751b7a189 19
keystone.electronic.solutions@gmail.com 1:70b751b7a189 20 #include "FP.h"
keystone.electronic.solutions@gmail.com 1:70b751b7a189 21 #include "MQTTSNPacket.h"
keystone.electronic.solutions@gmail.com 1:70b751b7a189 22 #include "stdio.h"
keystone.electronic.solutions@gmail.com 1:70b751b7a189 23
keystone.electronic.solutions@gmail.com 1:70b751b7a189 24
keystone.electronic.solutions@gmail.com 1:70b751b7a189 25 #define INFO_TRACE(_class, _string, ...) printf( "%8s: " _string, _class, ##__VA_ARGS__ )
keystone.electronic.solutions@gmail.com 1:70b751b7a189 26 //#define TRACE(_string, ...) INFO_TRACE( "MQTT-SN", _string, ##__VA_ARGS__)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 27 #define TRACE(_string, ...)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 28
keystone.electronic.solutions@gmail.com 1:70b751b7a189 29 // Data limits
keystone.electronic.solutions@gmail.com 1:70b751b7a189 30 #if !defined(MAX_REGISTRATIONS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 31 #define MAX_REGISTRATIONS 5
keystone.electronic.solutions@gmail.com 1:70b751b7a189 32 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 33 #if !defined(MAX_REGISTRATION_TOPIC_NAME_LENGTH)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 34 #define MAX_REGISTRATION_TOPIC_NAME_LENGTH 20
keystone.electronic.solutions@gmail.com 1:70b751b7a189 35 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 36 #if !defined(MAX_INCOMING_QOS2_MESSAGES)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 37 #define MAX_INCOMING_QOS2_MESSAGES 10
keystone.electronic.solutions@gmail.com 1:70b751b7a189 38 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 39
keystone.electronic.solutions@gmail.com 1:70b751b7a189 40 #if !defined(MQTTSNCLIENT_QOS1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 41 #define MQTTSNCLIENT_QOS1 1
keystone.electronic.solutions@gmail.com 1:70b751b7a189 42 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 43 #if !defined(MQTTSNCLIENT_QOS2)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 44 #define MQTTSNCLIENT_QOS2 0
keystone.electronic.solutions@gmail.com 1:70b751b7a189 45 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 46
keystone.electronic.solutions@gmail.com 1:70b751b7a189 47 namespace MQTTSN
keystone.electronic.solutions@gmail.com 1:70b751b7a189 48 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 49
keystone.electronic.solutions@gmail.com 1:70b751b7a189 50
keystone.electronic.solutions@gmail.com 1:70b751b7a189 51 enum QoS { QOS0, QOS1, QOS2 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 52
keystone.electronic.solutions@gmail.com 1:70b751b7a189 53 // all failure return codes must be negative
keystone.electronic.solutions@gmail.com 1:70b751b7a189 54 enum returnCode { MAX_SUBSCRIPTIONS_EXCEEDED = -3, BUFFER_OVERFLOW = -2, FAILURE = -1, SUCCESS = 0 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 55
keystone.electronic.solutions@gmail.com 1:70b751b7a189 56
keystone.electronic.solutions@gmail.com 1:70b751b7a189 57 struct Message
keystone.electronic.solutions@gmail.com 1:70b751b7a189 58 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 59 enum QoS qos;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 60 bool retained;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 61 bool dup;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 62 unsigned short id;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 63 void *payload;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 64 size_t payloadlen;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 65 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 66
keystone.electronic.solutions@gmail.com 1:70b751b7a189 67
keystone.electronic.solutions@gmail.com 1:70b751b7a189 68 struct MessageData
keystone.electronic.solutions@gmail.com 1:70b751b7a189 69 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 70 MessageData(MQTTSN_topicid &aTopic, struct Message &aMessage) : message(aMessage), topic(aTopic)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 71 { }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 72
keystone.electronic.solutions@gmail.com 1:70b751b7a189 73 struct Message &message;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 74 MQTTSN_topicid &topic;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 75 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 76
keystone.electronic.solutions@gmail.com 1:70b751b7a189 77
keystone.electronic.solutions@gmail.com 1:70b751b7a189 78 class PacketId
keystone.electronic.solutions@gmail.com 1:70b751b7a189 79 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 80 public:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 81 PacketId()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 82 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 83 next = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 84 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 85
keystone.electronic.solutions@gmail.com 1:70b751b7a189 86 int getNext()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 87 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 88 if(next == MAX_PACKET_ID)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 89 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 90 next = 1;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 91 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 92 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 93 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 94 next++;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 95 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 96 return next;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 97 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 98
keystone.electronic.solutions@gmail.com 1:70b751b7a189 99 private:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 100 static const int MAX_PACKET_ID = 65535;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 101 int next;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 102 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 103
keystone.electronic.solutions@gmail.com 1:70b751b7a189 104
keystone.electronic.solutions@gmail.com 1:70b751b7a189 105 /**
keystone.electronic.solutions@gmail.com 1:70b751b7a189 106 * @class MQTTSNClient
keystone.electronic.solutions@gmail.com 1:70b751b7a189 107 * @brief blocking, non-threaded MQTTSN client API
keystone.electronic.solutions@gmail.com 1:70b751b7a189 108 *
keystone.electronic.solutions@gmail.com 1:70b751b7a189 109 * This version of the API blocks on all method calls, until they are complete. This means that only one
keystone.electronic.solutions@gmail.com 1:70b751b7a189 110 * MQTT request can be in process at any one time.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 111 * @param Network a network class which supports send, receive
keystone.electronic.solutions@gmail.com 1:70b751b7a189 112 * @param Timer a timer class with the methods:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 113 */
KeystoneElectronic 7:ab32680de141 114 template<class Network, class Timer, int MAX_PACKET_SIZE = 256, int MAX_MESSAGE_HANDLERS = 5>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 115 class Client
keystone.electronic.solutions@gmail.com 1:70b751b7a189 116 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 117
keystone.electronic.solutions@gmail.com 1:70b751b7a189 118 public:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 119
keystone.electronic.solutions@gmail.com 1:70b751b7a189 120 typedef void (*messageHandler)(MessageData&);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 121
keystone.electronic.solutions@gmail.com 1:70b751b7a189 122 /** Construct the client
keystone.electronic.solutions@gmail.com 1:70b751b7a189 123 * @param network - pointer to an instance of the Network class - must be connected to the endpoint
keystone.electronic.solutions@gmail.com 1:70b751b7a189 124 * before calling MQTT connect
keystone.electronic.solutions@gmail.com 1:70b751b7a189 125 * @param limits an instance of the Limit class - to alter limits as required
keystone.electronic.solutions@gmail.com 1:70b751b7a189 126 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 127 Client(Network& network, unsigned int command_timeout_ms = 30000);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 128
keystone.electronic.solutions@gmail.com 1:70b751b7a189 129 /** Set the default message handling callback - used for any message which does not match a subscription message handler
keystone.electronic.solutions@gmail.com 1:70b751b7a189 130 * @param mh - pointer to the callback function
keystone.electronic.solutions@gmail.com 1:70b751b7a189 131 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 132 void setDefaultMessageHandler(messageHandler mh)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 133 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 134 defaultMessageHandler.attach(mh);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 135 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 136
keystone.electronic.solutions@gmail.com 1:70b751b7a189 137 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
keystone.electronic.solutions@gmail.com 1:70b751b7a189 138 * The nework object must be connected to the network endpoint before calling this
keystone.electronic.solutions@gmail.com 1:70b751b7a189 139 * Default connect options are used
keystone.electronic.solutions@gmail.com 1:70b751b7a189 140 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 141 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 142 int connect();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 143
keystone.electronic.solutions@gmail.com 1:70b751b7a189 144 /** MQTT Connect - send an MQTT connect packet down the network and wait for a Connack
keystone.electronic.solutions@gmail.com 1:70b751b7a189 145 * The nework object must be connected to the network endpoint before calling this
keystone.electronic.solutions@gmail.com 1:70b751b7a189 146 * @param options - connect options
keystone.electronic.solutions@gmail.com 1:70b751b7a189 147 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 148 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 149 int connect(MQTTSNPacket_connectData& options);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 150
keystone.electronic.solutions@gmail.com 1:70b751b7a189 151 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
keystone.electronic.solutions@gmail.com 1:70b751b7a189 152 * @param topic - the topic to publish to
keystone.electronic.solutions@gmail.com 1:70b751b7a189 153 * @param message - the message to send
keystone.electronic.solutions@gmail.com 1:70b751b7a189 154 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 155 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 156 int publish(MQTTSN_topicid& topic, Message& message);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 157
keystone.electronic.solutions@gmail.com 1:70b751b7a189 158 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
keystone.electronic.solutions@gmail.com 1:70b751b7a189 159 * @param topic - the topic to publish to
keystone.electronic.solutions@gmail.com 1:70b751b7a189 160 * @param payload - the data to send
keystone.electronic.solutions@gmail.com 1:70b751b7a189 161 * @param payloadlen - the length of the data
keystone.electronic.solutions@gmail.com 1:70b751b7a189 162 * @param qos - the QoS to send the publish at
keystone.electronic.solutions@gmail.com 1:70b751b7a189 163 * @param retained - whether the message should be retained
keystone.electronic.solutions@gmail.com 1:70b751b7a189 164 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 165 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 166 int publish(MQTTSN_topicid &topic, void* payload, size_t payloadlen, enum QoS qos = QOS0, bool retained = false);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 167
keystone.electronic.solutions@gmail.com 1:70b751b7a189 168 /** MQTT Publish - send an MQTT publish packet and wait for all acks to complete for all QoSs
keystone.electronic.solutions@gmail.com 1:70b751b7a189 169 * @param topic - the topic to publish to
keystone.electronic.solutions@gmail.com 1:70b751b7a189 170 * @param payload - the data to send
keystone.electronic.solutions@gmail.com 1:70b751b7a189 171 * @param payloadlen - the length of the data
keystone.electronic.solutions@gmail.com 1:70b751b7a189 172 * @param id - the packet id used - returned
keystone.electronic.solutions@gmail.com 1:70b751b7a189 173 * @param qos - the QoS to send the publish at
keystone.electronic.solutions@gmail.com 1:70b751b7a189 174 * @param retained - whether the message should be retained
keystone.electronic.solutions@gmail.com 1:70b751b7a189 175 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 176 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 177 int publish(MQTTSN_topicid& topic, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos = QOS1, bool retained = false);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 178
keystone.electronic.solutions@gmail.com 1:70b751b7a189 179 /** MQTT Subscribe - send an MQTT subscribe packet and wait for the suback
keystone.electronic.solutions@gmail.com 1:70b751b7a189 180 * @param topicFilter - a topic pattern which can include wildcards
keystone.electronic.solutions@gmail.com 1:70b751b7a189 181 * @param qos - the MQTT QoS to subscribe at
keystone.electronic.solutions@gmail.com 1:70b751b7a189 182 * @param mh - the callback function to be invoked when a message is received for this subscription
keystone.electronic.solutions@gmail.com 1:70b751b7a189 183 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 184 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 185 int subscribe(MQTTSN_topicid& topicFilter, enum QoS qos, enum QoS &grantedQoS, messageHandler mh);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 186
keystone.electronic.solutions@gmail.com 1:70b751b7a189 187 /** MQTT Unsubscribe - send an MQTT unsubscribe packet and wait for the unsuback
keystone.electronic.solutions@gmail.com 1:70b751b7a189 188 * @param topicFilter - a topic pattern which can include wildcards
keystone.electronic.solutions@gmail.com 1:70b751b7a189 189 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 190 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 191 int unsubscribe(MQTTSN_topicid& topicFilter);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 192
keystone.electronic.solutions@gmail.com 1:70b751b7a189 193 /** MQTT Disconnect - send an MQTT disconnect packet, and clean up any state
keystone.electronic.solutions@gmail.com 1:70b751b7a189 194 * @param duration - used for sleeping clients, 0 means no duration
keystone.electronic.solutions@gmail.com 1:70b751b7a189 195 * @return success code -
keystone.electronic.solutions@gmail.com 1:70b751b7a189 196 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 197 int disconnect(unsigned short duration = 0);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 198
keystone.electronic.solutions@gmail.com 1:70b751b7a189 199 /** A call to this API must be made within the keepAlive interval to keep the MQTT connection alive
keystone.electronic.solutions@gmail.com 1:70b751b7a189 200 * yield can be called if no other MQTT operation is needed. This will also allow messages to be
keystone.electronic.solutions@gmail.com 1:70b751b7a189 201 * received.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 202 * @param timeout_ms the time to wait, in milliseconds
keystone.electronic.solutions@gmail.com 1:70b751b7a189 203 * @return success code - on failure, this means the client has disconnected
keystone.electronic.solutions@gmail.com 1:70b751b7a189 204 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 205 int yield(unsigned long timeout_ms = 1000L);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 206
keystone.electronic.solutions@gmail.com 1:70b751b7a189 207 /** Is the client connected?
keystone.electronic.solutions@gmail.com 1:70b751b7a189 208 * @return flag - is the client connected or not?
keystone.electronic.solutions@gmail.com 1:70b751b7a189 209 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 210 bool isConnected()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 211 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 212 return isconnected;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 213 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 214
keystone.electronic.solutions@gmail.com 1:70b751b7a189 215 protected:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 216
keystone.electronic.solutions@gmail.com 1:70b751b7a189 217 int cycle(Timer& timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 218 int waitfor(int packet_type, Timer& timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 219
keystone.electronic.solutions@gmail.com 1:70b751b7a189 220 private:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 221
keystone.electronic.solutions@gmail.com 1:70b751b7a189 222 int keepalive();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 223 int publish(int len, Timer& timer, enum QoS qos);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 224
keystone.electronic.solutions@gmail.com 1:70b751b7a189 225 int readPacket(Timer& timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 226 int sendPacket(int length, Timer& timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 227 int deliverMessage(MQTTSN_topicid& topic, Message& message);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 228 bool isTopicMatched(char* topicFilter, MQTTSNString& topicName);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 229
keystone.electronic.solutions@gmail.com 1:70b751b7a189 230 Network& ipstack;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 231 unsigned long command_timeout_ms;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 232
keystone.electronic.solutions@gmail.com 1:70b751b7a189 233 unsigned char sendbuf[MAX_PACKET_SIZE];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 234 unsigned char readbuf[MAX_PACKET_SIZE];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 235
keystone.electronic.solutions@gmail.com 1:70b751b7a189 236 Timer last_sent, last_received;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 237 unsigned short duration;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 238 bool ping_outstanding;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 239 bool cleansession;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 240
keystone.electronic.solutions@gmail.com 1:70b751b7a189 241 PacketId packetid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 242
keystone.electronic.solutions@gmail.com 1:70b751b7a189 243 struct MessageHandlers
keystone.electronic.solutions@gmail.com 1:70b751b7a189 244 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 245 MQTTSN_topicid* topicFilter;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 246 FP<void, MessageData&> fp;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 247 } messageHandlers[MAX_MESSAGE_HANDLERS]; // Message handlers are indexed by subscription topic
keystone.electronic.solutions@gmail.com 1:70b751b7a189 248
keystone.electronic.solutions@gmail.com 1:70b751b7a189 249 FP<void, MessageData&> defaultMessageHandler;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 250
keystone.electronic.solutions@gmail.com 1:70b751b7a189 251 bool isconnected;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 252
keystone.electronic.solutions@gmail.com 1:70b751b7a189 253 struct Registrations
keystone.electronic.solutions@gmail.com 1:70b751b7a189 254 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 255 unsigned short id;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 256 char name[MAX_REGISTRATION_TOPIC_NAME_LENGTH];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 257 } registrations[MAX_REGISTRATIONS];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 258
keystone.electronic.solutions@gmail.com 1:70b751b7a189 259 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 260 unsigned char pubbuf[MAX_PACKET_SIZE]; // store the last publish for sending on reconnect
keystone.electronic.solutions@gmail.com 1:70b751b7a189 261 int inflightLen;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 262 unsigned short inflightMsgid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 263 enum QoS inflightQoS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 264 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 265
keystone.electronic.solutions@gmail.com 1:70b751b7a189 266 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 267 bool pubrel;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 268 unsigned short incomingQoS2messages[MAX_INCOMING_QOS2_MESSAGES];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 269 bool isQoS2msgidFree(unsigned short id);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 270 bool useQoS2msgid(unsigned short id);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 271 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 272
keystone.electronic.solutions@gmail.com 1:70b751b7a189 273 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 274
keystone.electronic.solutions@gmail.com 1:70b751b7a189 275 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 276
keystone.electronic.solutions@gmail.com 1:70b751b7a189 277
keystone.electronic.solutions@gmail.com 1:70b751b7a189 278 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 279 MQTTSN::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::Client(Network& network, unsigned int command_timeout_ms) : ipstack(network), packetid()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 280 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 281 inflightLen = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 282 duration = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 283 cleansession = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 284 last_sent = Timer();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 285 last_received = Timer();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 286 ping_outstanding = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 287 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 288 messageHandlers[i].topicFilter = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 289 this->command_timeout_ms = command_timeout_ms;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 290 isconnected = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 291
keystone.electronic.solutions@gmail.com 1:70b751b7a189 292 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 293 inflightMsgid = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 294 inflightQoS = QOS0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 295 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 296
keystone.electronic.solutions@gmail.com 1:70b751b7a189 297
keystone.electronic.solutions@gmail.com 1:70b751b7a189 298 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 299 pubrel = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 300 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 301 incomingQoS2messages[i] = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 302 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 303 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 304
keystone.electronic.solutions@gmail.com 1:70b751b7a189 305 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 306 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 307 bool MQTTSN::Client<Network, Timer, a, b>::isQoS2msgidFree(unsigned short id)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 308 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 309 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 310 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 311 if (incomingQoS2messages[i] == id)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 312 return false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 313 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 314 return true;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 315 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 316
keystone.electronic.solutions@gmail.com 1:70b751b7a189 317
keystone.electronic.solutions@gmail.com 1:70b751b7a189 318 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 319 bool MQTTSN::Client<Network, Timer, a, b>::useQoS2msgid(unsigned short id)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 320 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 321 for (int i = 0; i < MAX_INCOMING_QOS2_MESSAGES; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 322 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 323 if (incomingQoS2messages[i] == 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 324 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 325 incomingQoS2messages[i] = id;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 326 return true;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 327 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 328 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 329 return false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 330 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 331 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 332
keystone.electronic.solutions@gmail.com 1:70b751b7a189 333
keystone.electronic.solutions@gmail.com 1:70b751b7a189 334 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 335 int MQTTSN::Client<Network, Timer, a, b>::sendPacket(int length, Timer& timer)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 336 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 337 int rc = FAILURE,
keystone.electronic.solutions@gmail.com 1:70b751b7a189 338 sent = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 339
keystone.electronic.solutions@gmail.com 1:70b751b7a189 340 do
keystone.electronic.solutions@gmail.com 1:70b751b7a189 341 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 342 sent = ipstack.write(sendbuf, length, timer.left_ms());
keystone.electronic.solutions@gmail.com 1:70b751b7a189 343 TRACE("sendPacket, rc %d from write of %d bytes\n", sent, length);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 344 if (sent < 0) // there was an error writing the data
keystone.electronic.solutions@gmail.com 1:70b751b7a189 345 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 346 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 347 while (sent != length && !timer.expired());
keystone.electronic.solutions@gmail.com 1:70b751b7a189 348
keystone.electronic.solutions@gmail.com 1:70b751b7a189 349 if (sent == length)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 350 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 351 if (this->duration > 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 352 last_sent.countdown(this->duration); // record the fact that we have successfully sent the packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 353 rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 354 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 355 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 356 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 357
keystone.electronic.solutions@gmail.com 1:70b751b7a189 358 #if defined(MQTT_DEBUG)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 359 char printbuf[50];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 360 DEBUG("Rc %d from sending packet %s\n", rc, MQTTPacket_toString(printbuf, sizeof(printbuf), sendbuf, length));
keystone.electronic.solutions@gmail.com 1:70b751b7a189 361 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 362 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 363 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 364
keystone.electronic.solutions@gmail.com 1:70b751b7a189 365
keystone.electronic.solutions@gmail.com 1:70b751b7a189 366 /**
keystone.electronic.solutions@gmail.com 1:70b751b7a189 367 * If any read fails in this method, then we should disconnect from the network, as on reconnect
keystone.electronic.solutions@gmail.com 1:70b751b7a189 368 * the packets can be retried.
keystone.electronic.solutions@gmail.com 1:70b751b7a189 369 * @param timeout the max time to wait for the packet read to complete, in milliseconds
keystone.electronic.solutions@gmail.com 1:70b751b7a189 370 * @return the MQTT packet type, or -1 if none
keystone.electronic.solutions@gmail.com 1:70b751b7a189 371 */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 372 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 373 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::readPacket(Timer& timer)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 374 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 375 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 376 int len = 0; // the length of the whole packet including length field
keystone.electronic.solutions@gmail.com 1:70b751b7a189 377 int lenlen = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 378 int datalen = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 379
keystone.electronic.solutions@gmail.com 1:70b751b7a189 380 #define MQTTSN_MIN_PACKET_LENGTH 3
keystone.electronic.solutions@gmail.com 1:70b751b7a189 381 // 1. read the packet, datagram style
keystone.electronic.solutions@gmail.com 1:70b751b7a189 382 if ((len = ipstack.read(readbuf, MAX_PACKET_SIZE, timer.left_ms())) < MQTTSN_MIN_PACKET_LENGTH)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 383 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 384
keystone.electronic.solutions@gmail.com 1:70b751b7a189 385 // 2. read the length. This is variable in itself
keystone.electronic.solutions@gmail.com 1:70b751b7a189 386 lenlen = MQTTSNPacket_decode(readbuf, len, &datalen);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 387 if (datalen != len)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 388 goto exit; // there was an error
keystone.electronic.solutions@gmail.com 1:70b751b7a189 389
keystone.electronic.solutions@gmail.com 1:70b751b7a189 390 rc = readbuf[lenlen];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 391 if (this->duration > 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 392 last_received.countdown(this->duration); // record the fact that we have successfully received a packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 393 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 394
keystone.electronic.solutions@gmail.com 1:70b751b7a189 395 #if defined(MQTT_DEBUG)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 396 char printbuf[50];
keystone.electronic.solutions@gmail.com 1:70b751b7a189 397 DEBUG("Rc %d from receiving packet %s\n", rc, MQTTPacket_toString(printbuf, sizeof(printbuf), readbuf, len));
keystone.electronic.solutions@gmail.com 1:70b751b7a189 398 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 399 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 400 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 401
keystone.electronic.solutions@gmail.com 1:70b751b7a189 402
keystone.electronic.solutions@gmail.com 1:70b751b7a189 403 // assume topic filter and name is in correct format
keystone.electronic.solutions@gmail.com 1:70b751b7a189 404 // # can only be at end
keystone.electronic.solutions@gmail.com 1:70b751b7a189 405 // + and # can only be next to separator
keystone.electronic.solutions@gmail.com 1:70b751b7a189 406 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 407 bool MQTTSN::Client<Network, Timer, a, b>::isTopicMatched(char* topicFilter, MQTTSNString& topicName)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 408 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 409 char* curf = topicFilter;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 410 char* curn = topicName.lenstring.data;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 411 char* curn_end = curn + topicName.lenstring.len;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 412
keystone.electronic.solutions@gmail.com 1:70b751b7a189 413 while (*curf && curn < curn_end)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 414 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 415 if (*curn == '/' && *curf != '/')
keystone.electronic.solutions@gmail.com 1:70b751b7a189 416 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 417 if (*curf != '+' && *curf != '#' && *curf != *curn)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 418 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 419 if (*curf == '+')
keystone.electronic.solutions@gmail.com 1:70b751b7a189 420 { // skip until we meet the next separator, or end of string
keystone.electronic.solutions@gmail.com 1:70b751b7a189 421 char* nextpos = curn + 1;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 422 while (nextpos < curn_end && *nextpos != '/')
keystone.electronic.solutions@gmail.com 1:70b751b7a189 423 nextpos = ++curn + 1;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 424 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 425 else if (*curf == '#')
keystone.electronic.solutions@gmail.com 1:70b751b7a189 426 curn = curn_end - 1; // skip until end of string
keystone.electronic.solutions@gmail.com 1:70b751b7a189 427 curf++;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 428 curn++;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 429 };
keystone.electronic.solutions@gmail.com 1:70b751b7a189 430
keystone.electronic.solutions@gmail.com 1:70b751b7a189 431 return (curn == curn_end) && (*curf == '\0');
keystone.electronic.solutions@gmail.com 1:70b751b7a189 432 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 433
keystone.electronic.solutions@gmail.com 1:70b751b7a189 434
keystone.electronic.solutions@gmail.com 1:70b751b7a189 435
keystone.electronic.solutions@gmail.com 1:70b751b7a189 436 template<class Network, class Timer, int a, int MAX_MESSAGE_HANDLERS>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 437 int MQTTSN::Client<Network, Timer, a, MAX_MESSAGE_HANDLERS>::deliverMessage(MQTTSN_topicid& topic, Message& message)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 438 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 439 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 440 TRACE("deliverMessage topic id is %d\n", topic.data.id);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 441
keystone.electronic.solutions@gmail.com 1:70b751b7a189 442 // we have to find the right message handler - indexed by topic
keystone.electronic.solutions@gmail.com 1:70b751b7a189 443 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 444 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 445 if (messageHandlers[i].topicFilter != 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 446 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 447 TRACE("messageHandler %d topic id is %d\n", i, messageHandlers[i].topicFilter->data.id);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 448 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 449 if (messageHandlers[i].topicFilter != 0 && (topic.data.id == messageHandlers[i].topicFilter->data.id))
keystone.electronic.solutions@gmail.com 1:70b751b7a189 450 //MQTTSNtopic_equals(&topic, messageHandlers[i].topicFilter) ||
keystone.electronic.solutions@gmail.com 1:70b751b7a189 451 // isTopicMatched(messageHandlers[i].topicFilter, topic)))
keystone.electronic.solutions@gmail.com 1:70b751b7a189 452 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 453 if (messageHandlers[i].fp.attached())
keystone.electronic.solutions@gmail.com 1:70b751b7a189 454 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 455 MessageData md(topic, message);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 456 messageHandlers[i].fp(md);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 457 rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 458 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 459 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 460 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 461
keystone.electronic.solutions@gmail.com 1:70b751b7a189 462 if (rc == FAILURE && defaultMessageHandler.attached())
keystone.electronic.solutions@gmail.com 1:70b751b7a189 463 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 464 MessageData md(topic, message);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 465 defaultMessageHandler(md);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 466 rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 467 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 468
keystone.electronic.solutions@gmail.com 1:70b751b7a189 469 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 470 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 471
keystone.electronic.solutions@gmail.com 1:70b751b7a189 472
keystone.electronic.solutions@gmail.com 1:70b751b7a189 473
keystone.electronic.solutions@gmail.com 1:70b751b7a189 474 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 475 int MQTTSN::Client<Network, Timer, a, b>::yield(unsigned long timeout_ms)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 476 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 477 int rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 478 Timer timer = Timer();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 479
keystone.electronic.solutions@gmail.com 1:70b751b7a189 480 timer.countdown_ms(timeout_ms);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 481 while (!timer.expired())
keystone.electronic.solutions@gmail.com 1:70b751b7a189 482 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 483 if (cycle(timer) == FAILURE)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 484 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 485 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 486 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 487 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 488 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 489
keystone.electronic.solutions@gmail.com 1:70b751b7a189 490 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 491 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 492
keystone.electronic.solutions@gmail.com 1:70b751b7a189 493
keystone.electronic.solutions@gmail.com 1:70b751b7a189 494 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 495 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::cycle(Timer& timer)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 496 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 497 /* get one piece of work off the wire and one pass through */
keystone.electronic.solutions@gmail.com 1:70b751b7a189 498
keystone.electronic.solutions@gmail.com 1:70b751b7a189 499 // read the socket, see what work is due
keystone.electronic.solutions@gmail.com 1:70b751b7a189 500 unsigned short packet_type = readPacket(timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 501
keystone.electronic.solutions@gmail.com 1:70b751b7a189 502 int len = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 503 int rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 504
keystone.electronic.solutions@gmail.com 1:70b751b7a189 505 switch (packet_type)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 506 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 507 case MQTTSN_CONNACK:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 508 case MQTTSN_PUBACK:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 509 case MQTTSN_SUBACK:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 510 case MQTTSN_REGACK:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 511 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 512 case MQTTSN_REGISTER:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 513 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 514 unsigned short topicid, packetid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 515 MQTTSNString topicName;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 516 unsigned char reg_rc = MQTTSN_RC_ACCEPTED;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 517 if (MQTTSNDeserialize_register(&topicid, &packetid, &topicName, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 518 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 519 len = MQTTSNSerialize_regack(sendbuf, MAX_PACKET_SIZE, topicid, packetid, reg_rc);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 520 if (len <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 521 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 522 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 523 rc = sendPacket(len, timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 524 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 525 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 526 case MQTTSN_PUBLISH:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 527 MQTTSN_topicid topicid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 528 Message msg;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 529 if (MQTTSNDeserialize_publish((unsigned char*)&msg.dup, (int*)&msg.qos, (unsigned char*)&msg.retained, &msg.id, &topicid,
keystone.electronic.solutions@gmail.com 1:70b751b7a189 530 (unsigned char**)&msg.payload, (int*)&msg.payloadlen, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 531 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 532 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 533 if (msg.qos != QOS2)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 534 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 535 deliverMessage(topicid, msg);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 536 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 537 else if (isQoS2msgidFree(msg.id))
keystone.electronic.solutions@gmail.com 1:70b751b7a189 538 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 539 if (useQoS2msgid(msg.id))
keystone.electronic.solutions@gmail.com 1:70b751b7a189 540 deliverMessage(topicid, msg);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 541 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 542 WARN("Maximum number of incoming QoS2 messages exceeded");
keystone.electronic.solutions@gmail.com 1:70b751b7a189 543 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 544 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 545 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 546 if (msg.qos != QOS0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 547 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 548 if (msg.qos == QOS1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 549 len = MQTTSNSerialize_puback(sendbuf, MAX_PACKET_SIZE, topicid.data.id, msg.id, 0);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 550 else if (msg.qos == QOS2)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 551 len = MQTTSNSerialize_pubrec(sendbuf, MAX_PACKET_SIZE, msg.id);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 552 if (len <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 553 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 554 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 555 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 556 TRACE("sending puback len %d\n", len);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 557 rc = sendPacket(len, timer);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 558 TRACE("rc %d from sending puback\n", rc);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 559 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 560 if (rc == FAILURE)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 561 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 562 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 563 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 564 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 565 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 566 case MQTTSN_PUBREC:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 567 unsigned short mypacketid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 568 unsigned char type;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 569 if (MQTTSNDeserialize_ack(&type, &mypacketid, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 570 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 571 else if ((len = MQTTSNSerialize_pubrel(sendbuf, MAX_PACKET_SIZE, mypacketid)) <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 572 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 573 else if ((rc = sendPacket(len, timer)) != SUCCESS) // send the PUBREL packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 574 rc = FAILURE; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 575 if (rc == FAILURE)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 576 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 577 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 578 case MQTTSN_PUBCOMP:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 579 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 580 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 581 case MQTTSN_PINGRESP:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 582 ping_outstanding = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 583 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 584 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 585 keepalive();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 586 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 587 if (rc == SUCCESS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 588 rc = packet_type;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 589 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 590 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 591
keystone.electronic.solutions@gmail.com 1:70b751b7a189 592
keystone.electronic.solutions@gmail.com 1:70b751b7a189 593 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 594 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::keepalive()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 595 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 596 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 597
keystone.electronic.solutions@gmail.com 1:70b751b7a189 598 if (duration == 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 599 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 600 rc = SUCCESS;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 601 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 602 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 603
keystone.electronic.solutions@gmail.com 1:70b751b7a189 604 if (last_sent.expired() || last_received.expired())
keystone.electronic.solutions@gmail.com 1:70b751b7a189 605 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 606 if (!ping_outstanding)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 607 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 608 MQTTSNString clientid = MQTTSNString_initializer;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 609 Timer timer = Timer(1000);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 610 int len = MQTTSNSerialize_pingreq(sendbuf, MAX_PACKET_SIZE, clientid);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 611 if (len > 0 && (rc = sendPacket(len, timer)) == SUCCESS) // send the ping packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 612 ping_outstanding = true;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 613 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 614 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 615
keystone.electronic.solutions@gmail.com 1:70b751b7a189 616 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 617 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 618 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 619
keystone.electronic.solutions@gmail.com 1:70b751b7a189 620
keystone.electronic.solutions@gmail.com 1:70b751b7a189 621 // only used in single-threaded mode where one command at a time is in process
keystone.electronic.solutions@gmail.com 1:70b751b7a189 622 template<class Network, class Timer, int a, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 623 int MQTTSN::Client<Network, Timer, a, b>::waitfor(int packet_type, Timer& timer)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 624 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 625 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 626
keystone.electronic.solutions@gmail.com 1:70b751b7a189 627 do
keystone.electronic.solutions@gmail.com 1:70b751b7a189 628 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 629 if (timer.expired())
keystone.electronic.solutions@gmail.com 1:70b751b7a189 630 break; // we timed out
keystone.electronic.solutions@gmail.com 1:70b751b7a189 631 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 632 while ((rc = cycle(timer)) != packet_type);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 633
keystone.electronic.solutions@gmail.com 1:70b751b7a189 634 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 635 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 636
keystone.electronic.solutions@gmail.com 1:70b751b7a189 637
keystone.electronic.solutions@gmail.com 1:70b751b7a189 638 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 639 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::connect(MQTTSNPacket_connectData& options)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 640 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 641 Timer connect_timer = Timer(command_timeout_ms);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 642 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 643 int len = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 644
keystone.electronic.solutions@gmail.com 1:70b751b7a189 645 if (isconnected) // don't send connect packet again if we are already connected
keystone.electronic.solutions@gmail.com 1:70b751b7a189 646 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 647
keystone.electronic.solutions@gmail.com 1:70b751b7a189 648 this->duration = options.duration;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 649 this->cleansession = options.cleansession;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 650 if ((len = MQTTSNSerialize_connect(sendbuf, MAX_PACKET_SIZE, &options)) <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 651 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 652 if ((rc = sendPacket(len, connect_timer)) != SUCCESS) // send the connect packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 653 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 654
keystone.electronic.solutions@gmail.com 1:70b751b7a189 655 if (this->duration > 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 656 last_received.countdown(this->duration);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 657 // this will be a blocking call, wait for the connack
keystone.electronic.solutions@gmail.com 1:70b751b7a189 658 if (waitfor(MQTTSN_CONNACK, connect_timer) == MQTTSN_CONNACK)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 659 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 660 //unsigned char connack_rc = 255;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 661 int connack_rc = 255;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 662 if (MQTTSNDeserialize_connack(&connack_rc, readbuf, MAX_PACKET_SIZE) == 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 663 rc = connack_rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 664 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 665 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 666 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 667 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 668 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 669
keystone.electronic.solutions@gmail.com 1:70b751b7a189 670 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 671 // resend an inflight publish
keystone.electronic.solutions@gmail.com 1:70b751b7a189 672 if (inflightMsgid >0 && inflightQoS == QOS2 && pubrel)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 673 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 674 if ((len = MQTTSNSerialize_pubrel(sendbuf, MAX_PACKET_SIZE, inflightMsgid)) <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 675 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 676 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 677 rc = publish(len, connect_timer, inflightQoS);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 678 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 679 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 680 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 681 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 682 if (inflightMsgid > 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 683 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 684 memcpy(sendbuf, pubbuf, MAX_PACKET_SIZE);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 685 rc = publish(inflightLen, connect_timer, inflightQoS);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 686 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 687 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 688
keystone.electronic.solutions@gmail.com 1:70b751b7a189 689 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 690 if (rc == SUCCESS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 691 isconnected = true;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 692 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 693 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 694
keystone.electronic.solutions@gmail.com 1:70b751b7a189 695
keystone.electronic.solutions@gmail.com 1:70b751b7a189 696 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 697 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::connect()
keystone.electronic.solutions@gmail.com 1:70b751b7a189 698 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 699 MQTTSNPacket_connectData default_options = MQTTSNPacket_connectData_initializer;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 700 return connect(default_options);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 701 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 702
keystone.electronic.solutions@gmail.com 1:70b751b7a189 703
keystone.electronic.solutions@gmail.com 1:70b751b7a189 704 template<class Network, class Timer, int MAX_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 705 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::subscribe(MQTTSN_topicid& topicFilter, enum QoS qos, enum QoS &grantedQoS, messageHandler messageHandler)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 706 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 707 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 708 Timer timer = Timer(command_timeout_ms);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 709 int len = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 710 bool freeHandler = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 711
keystone.electronic.solutions@gmail.com 1:70b751b7a189 712 if (!isconnected)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 713 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 714
keystone.electronic.solutions@gmail.com 1:70b751b7a189 715 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 716 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 717 if (messageHandlers[i].topicFilter == 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 718 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 719 freeHandler = true;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 720 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 721 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 722 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 723 if (!freeHandler)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 724 { // No message handler free
keystone.electronic.solutions@gmail.com 1:70b751b7a189 725 rc = MAX_SUBSCRIPTIONS_EXCEEDED;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 726 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 727 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 728
keystone.electronic.solutions@gmail.com 1:70b751b7a189 729 len = MQTTSNSerialize_subscribe(sendbuf, MAX_PACKET_SIZE, 0, qos, packetid.getNext(), &topicFilter);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 730 if (len <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 731 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 732 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the subscribe packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 733 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 734
keystone.electronic.solutions@gmail.com 1:70b751b7a189 735 if (waitfor(MQTTSN_SUBACK, timer) == MQTTSN_SUBACK) // wait for suback
keystone.electronic.solutions@gmail.com 1:70b751b7a189 736 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 737 unsigned short mypacketid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 738 unsigned char suback_rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 739 if (MQTTSNDeserialize_suback((int*)&grantedQoS, &topicFilter.data.id, &mypacketid, &suback_rc, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 740 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 741 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 742 rc = suback_rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 743 if (suback_rc == MQTTSN_RC_ACCEPTED)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 744 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 745 for (int i = 0; i < MAX_MESSAGE_HANDLERS; ++i)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 746 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 747 if (messageHandlers[i].topicFilter == 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 748 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 749 messageHandlers[i].topicFilter = &topicFilter;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 750 messageHandlers[i].fp.attach(messageHandler);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 751 rc = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 752 break;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 753 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 754 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 755 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 756 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 757 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 758 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 759
keystone.electronic.solutions@gmail.com 1:70b751b7a189 760 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 761 if (rc != SUCCESS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 762 isconnected = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 763 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 764 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 765
keystone.electronic.solutions@gmail.com 1:70b751b7a189 766
keystone.electronic.solutions@gmail.com 1:70b751b7a189 767 template<class Network, class Timer, int MAX_PACKET_SIZE, int MAX_MESSAGE_HANDLERS>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 768 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, MAX_MESSAGE_HANDLERS>::unsubscribe(MQTTSN_topicid& topicFilter)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 769 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 770 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 771 Timer timer = Timer(command_timeout_ms);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 772 int len = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 773
keystone.electronic.solutions@gmail.com 1:70b751b7a189 774 if (!isconnected)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 775 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 776
keystone.electronic.solutions@gmail.com 1:70b751b7a189 777 if ((len = MQTTSNSerialize_unsubscribe(sendbuf, MAX_PACKET_SIZE, packetid.getNext(), &topicFilter)) <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 778 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 779 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the unsubscribe packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 780 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 781
keystone.electronic.solutions@gmail.com 1:70b751b7a189 782 if (waitfor(MQTTSN_UNSUBACK, timer) == MQTTSN_UNSUBACK)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 783 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 784 unsigned short mypacketid; // should be the same as the packetid above
keystone.electronic.solutions@gmail.com 1:70b751b7a189 785 if (MQTTSNDeserialize_unsuback(&mypacketid, readbuf, MAX_PACKET_SIZE) == 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 786 rc = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 787 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 788 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 789 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 790
keystone.electronic.solutions@gmail.com 1:70b751b7a189 791 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 792 if (rc != SUCCESS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 793 isconnected = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 794 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 795 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 796
keystone.electronic.solutions@gmail.com 1:70b751b7a189 797
keystone.electronic.solutions@gmail.com 1:70b751b7a189 798 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 799 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::publish(int len, Timer& timer, enum QoS qos)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 800 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 801 int rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 802
keystone.electronic.solutions@gmail.com 1:70b751b7a189 803 if ((rc = sendPacket(len, timer)) != SUCCESS) // send the publish packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 804 goto exit; // there was a problem
keystone.electronic.solutions@gmail.com 1:70b751b7a189 805
keystone.electronic.solutions@gmail.com 1:70b751b7a189 806 #if MQTTSNCLIENT_QOS1
keystone.electronic.solutions@gmail.com 1:70b751b7a189 807 if (qos == QOS1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 808 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 809 if (waitfor(MQTTSN_PUBACK, timer) == MQTTSN_PUBACK)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 810 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 811 unsigned short mypacketid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 812 unsigned char type;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 813 if (MQTTSNDeserialize_ack(&type, &mypacketid, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 814 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 815 else if (inflightMsgid == mypacketid)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 816 inflightMsgid = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 817 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 818 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 819 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 820 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 821 #elif MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 822 else if (qos == QOS2)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 823 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 824 if (waitfor(PUBCOMP, timer) == PUBCOMP)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 825 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 826 unsigned short mypacketid;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 827 unsigned char type;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 828 if (MQTTDeserialize_ack(&type, &mypacketid, readbuf, MAX_PACKET_SIZE) != 1)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 829 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 830 else if (inflightMsgid == mypacketid)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 831 inflightMsgid = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 832 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 833 else
keystone.electronic.solutions@gmail.com 1:70b751b7a189 834 rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 835 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 836 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 837
keystone.electronic.solutions@gmail.com 1:70b751b7a189 838 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 839 if (rc != SUCCESS)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 840 isconnected = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 841 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 842 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 843
keystone.electronic.solutions@gmail.com 1:70b751b7a189 844
keystone.electronic.solutions@gmail.com 1:70b751b7a189 845
keystone.electronic.solutions@gmail.com 1:70b751b7a189 846 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 847 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::publish(MQTTSN_topicid& topic, void* payload, size_t payloadlen, unsigned short& id, enum QoS qos, bool retained)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 848 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 849 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 850 Timer timer = Timer(command_timeout_ms);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 851 int len = 0;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 852
keystone.electronic.solutions@gmail.com 1:70b751b7a189 853 if (!isconnected)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 854 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 855
keystone.electronic.solutions@gmail.com 1:70b751b7a189 856 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 857 if (qos == QOS1 || qos == QOS2)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 858 id = packetid.getNext();
keystone.electronic.solutions@gmail.com 1:70b751b7a189 859 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 860
keystone.electronic.solutions@gmail.com 1:70b751b7a189 861 len = MQTTSNSerialize_publish(sendbuf, MAX_PACKET_SIZE, 0, qos, retained, id,
keystone.electronic.solutions@gmail.com 1:70b751b7a189 862 topic, (unsigned char*)payload, payloadlen);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 863 if (len <= 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 864 goto exit;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 865
keystone.electronic.solutions@gmail.com 1:70b751b7a189 866 #if MQTTSNCLIENT_QOS1 || MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 867 if (!cleansession)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 868 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 869 memcpy(pubbuf, sendbuf, len);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 870 inflightMsgid = id;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 871 inflightLen = len;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 872 inflightQoS = qos;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 873 #if MQTTSNCLIENT_QOS2
keystone.electronic.solutions@gmail.com 1:70b751b7a189 874 pubrel = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 875 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 876 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 877 #endif
keystone.electronic.solutions@gmail.com 1:70b751b7a189 878
keystone.electronic.solutions@gmail.com 1:70b751b7a189 879 rc = publish(len, timer, qos);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 880 exit:
keystone.electronic.solutions@gmail.com 1:70b751b7a189 881 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 882 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 883
keystone.electronic.solutions@gmail.com 1:70b751b7a189 884
keystone.electronic.solutions@gmail.com 1:70b751b7a189 885 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 886 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::publish(MQTTSN_topicid& topicName, void* payload, size_t payloadlen, enum QoS qos, bool retained)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 887 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 888 unsigned short id = 0; // dummy - not used for anything
keystone.electronic.solutions@gmail.com 1:70b751b7a189 889 return publish(topicName, payload, payloadlen, id, qos, retained);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 890 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 891
keystone.electronic.solutions@gmail.com 1:70b751b7a189 892
keystone.electronic.solutions@gmail.com 1:70b751b7a189 893 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 894 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::publish(MQTTSN_topicid& topicName, Message& message)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 895 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 896 return publish(topicName, message.payload, message.payloadlen, message.qos, message.retained);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 897 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 898
keystone.electronic.solutions@gmail.com 1:70b751b7a189 899
keystone.electronic.solutions@gmail.com 1:70b751b7a189 900 template<class Network, class Timer, int MAX_PACKET_SIZE, int b>
keystone.electronic.solutions@gmail.com 1:70b751b7a189 901 int MQTTSN::Client<Network, Timer, MAX_PACKET_SIZE, b>::disconnect(unsigned short duration)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 902 {
keystone.electronic.solutions@gmail.com 1:70b751b7a189 903 int rc = FAILURE;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 904 Timer timer = Timer(command_timeout_ms); // we might wait for incomplete incoming publishes to complete
keystone.electronic.solutions@gmail.com 1:70b751b7a189 905 int int_duration = (duration == 0) ? -1 : (int)duration;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 906 int len = MQTTSNSerialize_disconnect(sendbuf, MAX_PACKET_SIZE, int_duration);
keystone.electronic.solutions@gmail.com 1:70b751b7a189 907 if (len > 0)
keystone.electronic.solutions@gmail.com 1:70b751b7a189 908 rc = sendPacket(len, timer); // send the disconnect packet
keystone.electronic.solutions@gmail.com 1:70b751b7a189 909
keystone.electronic.solutions@gmail.com 1:70b751b7a189 910 isconnected = false;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 911 return rc;
keystone.electronic.solutions@gmail.com 1:70b751b7a189 912 }
keystone.electronic.solutions@gmail.com 1:70b751b7a189 913
keystone.electronic.solutions@gmail.com 1:70b751b7a189 914
keystone.electronic.solutions@gmail.com 1:70b751b7a189 915 #endif