[144] | 1 | // The MIT License (MIT)
|
---|
| 2 | //
|
---|
| 3 | // Copyright (c) 2015 Adafruit Industries
|
---|
| 4 | //
|
---|
| 5 | // Permission is hereby granted, free of charge, to any person obtaining a copy
|
---|
| 6 | // of this software and associated documentation files (the "Software"), to deal
|
---|
| 7 | // in the Software without restriction, including without limitation the rights
|
---|
| 8 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 9 | // copies of the Software, and to permit persons to whom the Software is
|
---|
| 10 | // furnished to do so, subject to the following conditions:
|
---|
| 11 | //
|
---|
| 12 | // The above copyright notice and this permission notice shall be included in all
|
---|
| 13 | // copies or substantial portions of the Software.
|
---|
| 14 | //
|
---|
| 15 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
---|
| 16 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
| 17 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
---|
| 18 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
---|
| 19 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
---|
| 20 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
---|
| 21 | // SOFTWARE.
|
---|
| 22 | #ifndef _ADAFRUIT_MQTT_H_
|
---|
| 23 | #define _ADAFRUIT_MQTT_H_
|
---|
| 24 |
|
---|
| 25 | #if ARDUINO >= 100
|
---|
| 26 | #include "Arduino.h"
|
---|
| 27 | #else
|
---|
| 28 | #include "WProgram.h"
|
---|
| 29 | #endif
|
---|
| 30 |
|
---|
| 31 | // Uncomment/comment to turn on/off debug output messages.
|
---|
| 32 | //#define MQTT_DEBUG
|
---|
| 33 |
|
---|
| 34 | // Set where debug messages will be printed.
|
---|
| 35 | #define DEBUG_PRINTER Serial
|
---|
| 36 |
|
---|
| 37 | // Define actual debug output functions when necessary.
|
---|
| 38 | #ifdef MQTT_DEBUG
|
---|
| 39 | #define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
|
---|
| 40 | #define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
|
---|
| 41 | #define DEBUG_PRINTBUFFER(buffer, len) { printBuffer(buffer, len); }
|
---|
| 42 | #else
|
---|
| 43 | #define DEBUG_PRINT(...) {}
|
---|
| 44 | #define DEBUG_PRINTLN(...) {}
|
---|
| 45 | #define DEBUG_PRINTBUFFER(buffer, len) {}
|
---|
| 46 | #endif
|
---|
| 47 |
|
---|
| 48 | #define MQTT_PROTOCOL_LEVEL 4
|
---|
| 49 |
|
---|
| 50 | #define MQTT_CTRL_CONNECT 0x01
|
---|
| 51 | #define MQTT_CTRL_CONNECTACK 0x02
|
---|
| 52 | #define MQTT_CTRL_PUBLISH 0x03
|
---|
| 53 | #define MQTT_CTRL_SUBSCRIBE 0x08
|
---|
| 54 | #define MQTT_CTRL_SUBACK 0x09
|
---|
| 55 | #define MQTT_CTRL_PINGREQ 0x0C
|
---|
| 56 | #define MQTT_CTRL_PINGRESP 0x0D
|
---|
| 57 |
|
---|
| 58 | #define MQTT_QOS_1 0x1
|
---|
| 59 | #define MQTT_QOS_0 0x0
|
---|
| 60 |
|
---|
| 61 | #define CONNECT_TIMEOUT_MS 3000
|
---|
| 62 | #define PUBLISH_TIMEOUT_MS 500
|
---|
| 63 | #define PING_TIMEOUT_MS 500
|
---|
| 64 |
|
---|
| 65 | // Adjust as necessary, in seconds. Default to 5 minutes.
|
---|
| 66 | #define MQTT_CONN_KEEPALIVE 30
|
---|
| 67 |
|
---|
| 68 | // Largest full packet we're able to send.
|
---|
| 69 | // Need to be able to store at least ~90 chars for a connect packet with full
|
---|
| 70 | // 23 char client ID.
|
---|
| 71 | #define MAXBUFFERSIZE (125)
|
---|
| 72 |
|
---|
| 73 | #define MQTT_CONN_USERNAMEFLAG 0x80
|
---|
| 74 | #define MQTT_CONN_PASSWORDFLAG 0x40
|
---|
| 75 | #define MQTT_CONN_WILLRETAIN 0x20
|
---|
| 76 | #define MQTT_CONN_WILLQOS 0x08
|
---|
| 77 | #define MQTT_CONN_WILLFLAG 0x04
|
---|
| 78 | #define MQTT_CONN_CLEANSESSION 0x02
|
---|
| 79 |
|
---|
| 80 | // how many subscriptions we want to be able to
|
---|
| 81 | // track
|
---|
| 82 | #define MAXSUBSCRIPTIONS 5
|
---|
| 83 |
|
---|
| 84 | // how much data we save in a subscription object
|
---|
| 85 | // eg max-subscription-payload-size
|
---|
| 86 | #define SUBSCRIPTIONDATALEN 1024
|
---|
| 87 |
|
---|
| 88 |
|
---|
| 89 | extern void printBuffer(uint8_t *buffer, uint8_t len);
|
---|
| 90 |
|
---|
| 91 | class Adafruit_MQTT_Subscribe; // forward decl
|
---|
| 92 |
|
---|
| 93 | class Adafruit_MQTT {
|
---|
| 94 | public:
|
---|
| 95 | Adafruit_MQTT(const char *server, uint16_t port, const char *cid,
|
---|
| 96 | const char *user, const char *pass);
|
---|
| 97 | Adafruit_MQTT(const __FlashStringHelper *server, uint16_t port, const __FlashStringHelper *cid,
|
---|
| 98 | const __FlashStringHelper *user, const __FlashStringHelper *pass);
|
---|
| 99 | virtual ~Adafruit_MQTT() {}
|
---|
| 100 |
|
---|
| 101 | // Connect to the MQTT server. Returns 0 on success, otherwise an error code
|
---|
| 102 | // that indicates something went wrong:
|
---|
| 103 | // -1 = Error connecting to server
|
---|
| 104 | // 1 = Wrong protocol
|
---|
| 105 | // 2 = ID rejected
|
---|
| 106 | // 3 = Server unavailable
|
---|
| 107 | // 4 = Bad username or password
|
---|
| 108 | // 5 = Not authenticated
|
---|
| 109 | // 6 = Failed to subscribe
|
---|
| 110 | // Use connectErrorString() to get a printable string version of the
|
---|
| 111 | // error.
|
---|
| 112 | int8_t connect();
|
---|
| 113 |
|
---|
| 114 | // Return a printable string version of the error code returned by
|
---|
| 115 | // connect(). This returns a __FlashStringHelper*, which points to a
|
---|
| 116 | // string stored in flash, but can be directly passed to e.g.
|
---|
| 117 | // Serial.println without any further processing.
|
---|
| 118 | const __FlashStringHelper* connectErrorString(int8_t code);
|
---|
| 119 |
|
---|
| 120 | // Disconnect from the MQTT server. Returns true if disconnected, false
|
---|
| 121 | // otherwise.
|
---|
| 122 | virtual bool disconnect() = 0; // Subclasses need to fill this in!
|
---|
| 123 |
|
---|
| 124 | // Return true if connected to the MQTT server, otherwise false.
|
---|
| 125 | virtual bool connected() = 0; // Subclasses need to fill this in!
|
---|
| 126 |
|
---|
| 127 | // Publish a message to a topic using the specified QoS level. Returns true
|
---|
| 128 | // if the message was published, false otherwise.
|
---|
| 129 | // The topic must be stored in PROGMEM. It can either be a
|
---|
| 130 | // char*, or a __FlashStringHelper* (the result of the F() macro).
|
---|
| 131 | bool publish(const char *topic, const char *payload, uint8_t qos = 0);
|
---|
| 132 | bool publish(const __FlashStringHelper *topic, const char *payload, uint8_t qos = 0) {
|
---|
| 133 | return publish((const char *)topic, payload, qos);
|
---|
| 134 | }
|
---|
| 135 |
|
---|
| 136 | // Add a subscription to receive messages for a topic. Returns true if the
|
---|
| 137 | // subscription could be added or was already present, false otherwise.
|
---|
| 138 | // Must be called before connect(), subscribing after the connection
|
---|
| 139 | // is made is not currently supported.
|
---|
| 140 | bool subscribe(Adafruit_MQTT_Subscribe *sub);
|
---|
| 141 |
|
---|
| 142 | // Check if any subscriptions have new messages. Will return a reference to
|
---|
| 143 | // an Adafruit_MQTT_Subscribe object which has a new message. Should be called
|
---|
| 144 | // in the sketch's loop function to ensure new messages are recevied. Note
|
---|
| 145 | // that subscribe should be called first for each topic that receives messages!
|
---|
| 146 | Adafruit_MQTT_Subscribe *readSubscription(int16_t timeout=0);
|
---|
| 147 |
|
---|
| 148 | // Ping the server to ensure the connection is still alive. Returns true if
|
---|
| 149 | // successful, otherwise false.
|
---|
| 150 | bool ping(uint8_t t);
|
---|
| 151 |
|
---|
| 152 | protected:
|
---|
| 153 | // Interface that subclasses need to implement:
|
---|
| 154 |
|
---|
| 155 | // Connect to the server and return true if successful, false otherwise.
|
---|
| 156 | virtual bool connectServer() = 0;
|
---|
| 157 |
|
---|
| 158 | // Send data to the server specified by the buffer and length of data.
|
---|
| 159 | virtual bool sendPacket(uint8_t *buffer, uint8_t len) = 0;
|
---|
| 160 |
|
---|
| 161 | // Read MQTT packet from the server. Will read up to maxlen bytes and store
|
---|
| 162 | // the data in the provided buffer. Waits up to the specified timeout (in
|
---|
| 163 | // milliseconds) for data to be available. If checkForValidPubPacket is true
|
---|
| 164 | // then the received data is verified to make sure it's a complete packet.
|
---|
| 165 | virtual uint16_t readPacket(uint8_t *buffer, uint8_t maxlen, int16_t timeout,
|
---|
| 166 | bool checkForValidPubPacket = false) = 0;
|
---|
| 167 |
|
---|
| 168 | // Shared state that subclasses can use:
|
---|
| 169 | const char *servername;
|
---|
| 170 | int16_t portnum;
|
---|
| 171 | const char *clientid;
|
---|
| 172 | const char *username;
|
---|
| 173 | const char *password;
|
---|
| 174 | uint8_t buffer[MAXBUFFERSIZE]; // one buffer, used for all incoming/outgoing
|
---|
| 175 |
|
---|
| 176 | private:
|
---|
| 177 | Adafruit_MQTT_Subscribe *subscriptions[MAXSUBSCRIPTIONS];
|
---|
| 178 |
|
---|
| 179 | // Functions to generate MQTT packets.
|
---|
| 180 | uint8_t connectPacket(uint8_t *packet);
|
---|
| 181 | uint8_t publishPacket(uint8_t *packet, const char *topic, const char *payload, uint8_t qos);
|
---|
| 182 | uint8_t subscribePacket(uint8_t *packet, const char *topic, uint8_t qos);
|
---|
| 183 | uint8_t pingPacket(uint8_t *packet);
|
---|
| 184 | };
|
---|
| 185 |
|
---|
| 186 |
|
---|
| 187 | class Adafruit_MQTT_Publish {
|
---|
| 188 | public:
|
---|
| 189 | Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const char *feed, uint8_t qos = 0);
|
---|
| 190 | Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const __FlashStringHelper *feed, uint8_t qos = 0);
|
---|
| 191 |
|
---|
| 192 | bool publish(const char *s);
|
---|
| 193 | bool publish(double f, uint8_t precision=2); // Precision controls the minimum number of digits after decimal.
|
---|
| 194 | // This might be ignored and a higher precision value sent.
|
---|
| 195 | bool publish(int32_t i);
|
---|
| 196 | bool publish(uint32_t i);
|
---|
| 197 |
|
---|
| 198 | private:
|
---|
| 199 | Adafruit_MQTT *mqtt;
|
---|
| 200 | const char *topic;
|
---|
| 201 | uint8_t qos;
|
---|
| 202 | };
|
---|
| 203 |
|
---|
| 204 | class Adafruit_MQTT_Subscribe {
|
---|
| 205 | public:
|
---|
| 206 | Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const char *feedname, uint8_t q=0);
|
---|
| 207 | Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const __FlashStringHelper *feedname, uint8_t q=0);
|
---|
| 208 |
|
---|
| 209 | bool setCallback(void (*callback)(char *));
|
---|
| 210 |
|
---|
| 211 | const char *topic;
|
---|
| 212 | uint8_t qos;
|
---|
| 213 |
|
---|
| 214 | uint8_t lastread[SUBSCRIPTIONDATALEN];
|
---|
| 215 | // Number valid bytes in lastread. Limited to SUBSCRIPTIONDATALEN-1 to
|
---|
| 216 | // ensure nul terminating lastread.
|
---|
| 217 | uint8_t datalen;
|
---|
| 218 | private:
|
---|
| 219 | Adafruit_MQTT *mqtt;
|
---|
| 220 | };
|
---|
| 221 |
|
---|
| 222 |
|
---|
| 223 | #endif
|
---|