Compare commits

...

79 Commits

Author SHA1 Message Date
Mathieu Maret dca344d237 Add method to cound number of subscription 2022-09-10 22:44:01 +02:00
Assaf Inbal af01dcb7da Added retain flag for publishing 2022-09-10 22:30:49 +02:00
Brent Rubell 7413e92e77
Merge pull request #213 from adafruit/update-ssl-cert
Update SSL Certificate for ESP8266, add warning
2022-08-15 13:35:40 -04:00
brentru 25662868c5 add cert and warning 2022-08-15 13:18:56 -04:00
Brent Rubell 223d419ebd
Update library.properties 2021-07-12 09:53:23 -04:00
Brent Rubell 37e175dcef
Merge pull request #196 from xdylanm/send_long_packet_fix
Fixed length calculation when payload exceeds 128bytes
2021-07-12 09:53:02 -04:00
Brent Rubell d466773076
Update library.properties 2021-06-22 13:29:31 -04:00
Brent Rubell 3a319ab695
Merge pull request #195 from rgorosito/fix-loss-subscriptions
Fix: Subscriptions can't be read if arrive when waiting for response of ping or publish
2021-06-22 13:29:11 -04:00
xdylanm a2bdbacb17 format 2021-05-30 16:16:14 -07:00
xdylanm b007806ac1 Fixed length calculation when payload exceeds 128bytes 2021-05-30 14:13:57 -07:00
Ricardo Gorosito ab78b291b2 more c formatting fixing 2021-05-25 13:23:51 -03:00
Ricardo Gorosito 986c1b405c fix c formatting 2021-05-25 13:16:43 -03:00
Ricardo Gorosito 4cb40f87d2 stop loosing messages 2021-05-23 15:52:35 -03:00
Brent Rubell e524b5f3ae
Merge pull request #194 from brentru/add-kat-public-funct
Add setKeepAliveInterval() setter
2021-05-18 17:04:56 -04:00
brentru c5cdfc9564 clang format 2021-05-18 16:54:01 -04:00
brentru 86aff92f0b fixup 2021-05-18 16:43:33 -04:00
brentru a1e64c039e settable keepalive interval 2021-05-18 16:41:26 -04:00
Brent Rubell ea2fb46de3
Merge pull request #193 from xdylanm/send_rcv_long_packets
Support publishing and receiving large messages.
2021-05-14 12:01:40 -04:00
xdylanm db003d30d1 Addressing comments from PR #193 with merge from PR#166. Clang-format, version ticked to 2.3.0, replaced duplicate topicOffsetFromLength with packetAdditionalLen. 2021-05-14 08:09:07 -07:00
xdylanm c782cc454f Merge branch 'master' of https://github.com/adafruit/Adafruit_MQTT_Library into send_rcv_long_packets
Pull in changes from flavio-fernandes
2021-05-14 07:47:38 -07:00
Brent Rubell ca12d21eb2
Merge pull request #166 from flavio-fernandes/protect.buffer
Adafruit_MQTT::publishPacket: Protect against memory corruption.
2021-05-14 09:22:29 -04:00
xdylanm 93a35d1a3e fix typo 2021-05-12 21:54:08 -07:00
xdylanm 2ea8a0b3fc Support publishing and receiving large messages. Send multiple 250 byte packets (ref PR#113) for larger messages. Correctly identify topic start position for >127byte messages (ref PR#166). Resolves issue #102 2021-05-12 21:31:22 -07:00
Flaviof ce30d2a146
Merge branch 'master' into protect.buffer 2021-05-12 21:25:20 -04:00
Flavio Fernandes fff701ee62 Bump to 2.2.0 2021-05-12 21:18:33 -04:00
Brent Rubell e8922f60a9
Merge pull request #192 from brentru/add-esp32-esp32s2-example
Add usage example for ESP32 SSL/TLS
2021-05-12 17:36:47 -04:00
brentru 1a3ff727a3 add .skip files for 8266/zero, this is an esp32 example! 2021-05-12 17:33:16 -04:00
brentru 2adac525e1 bump version 2021-05-12 17:30:17 -04:00
brentru 813585f72b add example for esp32s2/esp32 2021-05-12 17:26:26 -04:00
Flavio Fernandes d6f07ed4e4 Adafruit_MQTT::publishPacket: Protect against memory corruption.
Avoid memory corruption from happening when data payload provided
in Adafruit_MQTT::publishPacket is greater than MAXBUFFERSIZE.

In order to do that, a helper function is being added to calculate
how much space is available for the payload after subtracting what
is used as the header.

Pull request https://github.com/adafruit/Adafruit_MQTT_Library/pull/166
Fixes https://github.com/adafruit/Adafruit_MQTT_Library/issues/109
Fixes https://github.com/adafruit/Adafruit_MQTT_Library/issues/122

Signed-off-by: Flavio Fernandes <flavio@flaviof.com>
2021-04-02 12:14:39 -04:00
Brent Rubell f63a37b6fb
Merge pull request #170 from Fapiko/better-ping-handling
Better ping handling
2020-11-06 10:39:12 -05:00
Lucas Jandrew f3f5c18c6d Reformatted with clang-format 2020-11-06 10:20:52 -05:00
Lucas Jandrew c952333c40 Removing commented out debug statements 2020-11-05 13:06:12 -05:00
Lucas Jandrew 7e0a1573ea Merge master to resolve conflicts 2020-11-05 13:04:17 -05:00
Lucas Jandrew 1e72fa7c4a
Bump version number for release 2020-11-05 12:55:09 -05:00
Dylan Herrada c7f716cf5d
Bump to 2.0.0 2020-09-30 15:21:46 -04:00
Brent Rubell 381c3e576c
Merge pull request #171 from frederikheld/fix/typo_in_comment
Fixes typo in comment
2020-09-23 11:49:07 -04:00
Brent Rubell 569c83af8c
Merge pull request #179 from cmumford/fix-protected
Corrected client public/private methods.
2020-09-23 11:48:02 -04:00
Brent Rubell 2f572776c1
Merge pull request #184 from mlwinters/master
Added support for the MKR1010
2020-09-23 11:43:33 -04:00
Morgan f1f515651f
Moved defined(ARDUINO_SAMD_MKR1010) to line 25
Move "defined(ARDUINO_SAMD_MKR1010)" from lilne 24 to line 25
2020-09-23 10:27:06 +01:00
Morgan 4b360f2522
Added support for the MKR1010
Added support for the Arduino MKR1010
2020-09-23 09:51:56 +01:00
Brent Rubell 4a409caf16
Merge branch 'master' into better-ping-handling 2020-08-04 10:38:19 -04:00
Brent Rubell 956242a28b
Bump library.properties version for release 2020-07-07 10:19:42 -04:00
Justin Cooper bf7ce5af91
Latest Adafruit IO SSL Fingerprint 2020-07-06 15:53:19 -05:00
Chris Mumford c5599bfabc Corrected client public/private methods.
Switched the following four methods from public to
protected in Adafruit_MQTT_Client and Adafruit_MQTT_FONA:

1. connectServer
2. disconnectServer
3. readPacket
4. sendPacket

When public (previously) they could be called by users
of this library, which is not the intent of this API.
2020-07-03 10:43:51 -07:00
dherrada 8db0c2787d
Merge pull request #177 from adafruit/actionci
Moved to actions, no doxygen
2020-06-26 10:40:14 -04:00
dherrada 148cfb3591
Moved to actions, no doxygen 2020-06-25 09:56:46 -04:00
Frederik Held ba9a03a41d Fixes typo in comment 2020-02-29 00:21:45 +01:00
Lucas Jandrew 9bf437e61c Fix missing handleSubscriptionPacket from code formatting. 2020-02-24 01:41:00 -05:00
Lucas Jandrew adb717f7dd Removing remainder of whitespace differences 2020-02-24 01:28:48 -05:00
Lucas Jandrew 3ba30fe64b Revert code formatting changes by CLion 2020-02-24 01:22:58 -05:00
Lucas Jandrew 8e8245d734 Removed code from my previous PR 2020-02-24 01:11:43 -05:00
Lucas Jandrew 44199a17ee Fixes issue with client erroneously reading a byte from 0 length packets 2020-02-24 01:10:09 -05:00
Lucas Jandrew 0b8488d9bf Uncommented code to handle subscription packets... 2020-02-23 22:44:35 -05:00
Lucas Jandrew 5ea3e3ba72 Handle publish packets when they're not the expected packet type 2020-02-23 22:42:43 -05:00
Lucas Jandrew 259cba0837 Adds retain support for publishing messages 2020-02-19 19:15:27 -05:00
brentrubell 3693eb8800
Merge pull request #156 from brentru/patch-esp-bsp-2-5-1
Fixing example for ESP8266 (BSP 2.5.1)
2019-05-20 15:01:58 -04:00
brentru 4caf05cf8a bump version for release 2019-05-20 15:01:47 -04:00
brentru d5aa959525 adding ssl fingerprint verification to comply with bearssl in esp8266 bsp 2.5.1 2019-05-20 11:20:45 -04:00
brentrubell bfdece49f7
Merge pull request #155 from brentru/add-airlift-example
Update AirLift Example
2019-05-02 10:16:12 -04:00
brentru 3c71f1c560 remove print for pins 2019-04-19 16:36:14 -04:00
brentru 4a709ffc28 update for a master airlift example 2019-04-19 16:32:14 -04:00
brentrubell 4b328500e2
Merge pull request #153 from brentru/add-pyportal-mqtts
Add PyPortal MQTTS Example
2019-04-18 12:10:02 -04:00
brentru 2b3892a4b6 bump to v1.0.0 2019-04-17 20:37:20 -04:00
brentru 727dc9f986 fix travis 2019-04-16 14:18:06 -04:00
brentru c1e0ecd30e bump to 0.3.0 for release! 2019-04-16 13:51:36 -04:00
brentru 5dd4f68de7 add skip file 2019-04-16 13:45:01 -04:00
brentru 610514e83b add PyPortal MQTTS Example 2019-04-16 13:44:28 -04:00
brentrubell 0687c95333
Merge pull request #152 from brentru/fixup-readme
Update README TravisCI link, add samd51 to compatibility table
2019-04-16 12:07:10 -04:00
brentru 03ac17773f update readme travis and add samd51 to compat table 2019-04-16 11:56:18 -04:00
brentrubell b7838a3278
Merge pull request #148 from ACE1046/master
Message type check in readSubscription (#147)
2019-04-16 11:49:27 -04:00
brentrubell 9eb37efa1c
bumping library for compilation on m4 targets (#151) 2019-04-16 11:48:54 -04:00
Anton ACE 417d342078
Message type check in readSubscription (#147)
Added message type checking in readSubscription
https://github.com/adafruit/Adafruit_MQTT_Library/issues/147
2019-03-14 17:54:06 +03:00
brentrubell 493a1cf590
remove CC3000 from keywords.txt (#145) 2019-02-19 16:56:07 -05:00
brentrubell 12479b2592
fix sha1 fingerprint for io.adafruit.com (#143)
* fix sha1 fingerprint for io.adafruit.com

* bump library version

* add terminating character
2019-02-19 16:36:34 -05:00
brentrubell 07c9ae7153
Bump version for new release. 2018-08-28 10:54:44 -04:00
Limor "Ladyada" Fried 0786de66b6
Merge pull request #130 from brentru/mqtt-subscription-increase
increase mqtt sub. limit for non 32u4/328p devices
2018-08-27 13:17:19 -07:00
brentru 8780dd5491 increase mqtt sub. limit for non 32u4/328p devices 2018-08-27 14:51:29 -04:00
brentrubell 61f75246f4 Library Fixes (#127)
* Removing warnings

* handle reading zero-length packets

* updating travis to exclude archived libraries, addin Arduino WiFi101 lib instead

* adding esp lib to travis

* restrict builds to current hardware platforms

* travis, esp8266: skip esp target for non-esp-based examples

* adding test skips for zero, fixing fingerprint error

bump library version
2018-08-20 09:56:40 -04:00
32 changed files with 968 additions and 435 deletions

26
.github/workflows/githubci.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: Arduino Library CI
on: [pull_request, push, repository_dispatch]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-python@v1
with:
python-version: '3.x'
- uses: actions/checkout@v2
- uses: actions/checkout@v2
with:
repository: adafruit/ci-arduino
path: ci
- name: pre-install
run: bash ci/actions_install.sh
- name: test platforms
run: python3 ci/build_platform.py esp8266 zero
- name: clang
run: python3 ci/run-clang-format.py -e "ci/*" -e "bin/*" -r .

View File

@ -1,12 +0,0 @@
language: c
sudo: false
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
install:
- arduino --install-library "Adafruit SleepyDog Library,Adafruit FONA Library,Adafruit CC3000 Library,Adafruit_WINC1500"
script:
- build_main_platforms
notifications:
email:
on_success: change
on_failure: change

View File

@ -9,8 +9,8 @@
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -21,8 +21,10 @@
// SOFTWARE.
#include "Adafruit_MQTT.h"
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000)
static char *dtostrf (double val, signed char width, unsigned char prec, char *sout) {
#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKR1000) || \
defined(ARDUINO_SAMD_MKR1010) || defined(ARDUINO_ARCH_SAMD)
static char *dtostrf(double val, signed char width, unsigned char prec,
char *sout) {
char fmt[20];
sprintf(fmt, "%%%d.%df", width, prec);
sprintf(sout, fmt, val);
@ -31,23 +33,22 @@ static char *dtostrf (double val, signed char width, unsigned char prec, char *s
#endif
#if defined(ESP8266)
int strncasecmp(const char * str1, const char * str2, int len) {
int d = 0;
while(len--) {
int c1 = tolower(*str1++);
int c2 = tolower(*str2++);
if(((d = c1 - c2) != 0) || (c2 == '\0')) {
return d;
}
int strncasecmp(const char *str1, const char *str2, int len) {
int d = 0;
while (len--) {
int c1 = tolower(*str1++);
int c2 = tolower(*str2++);
if (((d = c1 - c2) != 0) || (c2 == '\0')) {
return d;
}
return 0;
}
return 0;
}
#endif
void printBuffer(uint8_t *buffer, uint16_t len) {
DEBUG_PRINTER.print('\t');
for (uint16_t i=0; i<len; i++) {
for (uint16_t i = 0; i < len; i++) {
if (isprint(buffer[i]))
DEBUG_PRINTER.write(buffer[i]);
else
@ -55,7 +56,7 @@ void printBuffer(uint8_t *buffer, uint16_t len) {
DEBUG_PRINTER.print(F(" [0x"));
if (buffer[i] < 0x10)
DEBUG_PRINTER.print("0");
DEBUG_PRINTER.print(buffer[i],HEX);
DEBUG_PRINTER.print(buffer[i], HEX);
DEBUG_PRINTER.print("], ");
if (i % 8 == 7) {
DEBUG_PRINTER.print("\n\t");
@ -74,7 +75,7 @@ static uint8_t *stringprint(uint8_t *p, char *s) {
}
*/
static uint8_t *stringprint(uint8_t *p, const char *s, uint16_t maxlen=0) {
static uint8_t *stringprint(uint8_t *p, const char *s, uint16_t maxlen = 0) {
// If maxlen is specified (has a non-zero value) then use it as the maximum
// length of the source string to write to the buffer. Otherwise write
// the entire source string.
@ -87,20 +88,34 @@ static uint8_t *stringprint(uint8_t *p, const char *s, uint16_t maxlen=0) {
Serial.write(pgm_read_byte(s+i));
}
*/
p[0] = len >> 8; p++;
p[0] = len & 0xFF; p++;
p[0] = len >> 8;
p++;
p[0] = len & 0xFF;
p++;
strncpy((char *)p, s, len);
return p+len;
return p + len;
}
// packetAdditionalLen is a helper function used to figure out
// how bigger the payload needs to be in order to account for
// its variable length field. As per
// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Table_2.4_Size
// See also readFullPacket
static uint16_t packetAdditionalLen(uint32_t currLen) {
/* Increase length field based on current length */
if (currLen < 128) // 7-bits
return 0;
if (currLen < 16384) // 14-bits
return 1;
if (currLen < 2097152) // 21-bits
return 2;
return 3;
}
// Adafruit_MQTT Definition ////////////////////////////////////////////////////
Adafruit_MQTT::Adafruit_MQTT(const char *server,
uint16_t port,
const char *cid,
const char *user,
const char *pass) {
Adafruit_MQTT::Adafruit_MQTT(const char *server, uint16_t port, const char *cid,
const char *user, const char *pass) {
servername = server;
portnum = port;
clientid = cid;
@ -108,7 +123,7 @@ Adafruit_MQTT::Adafruit_MQTT(const char *server,
password = pass;
// reset subscriptions
for (uint8_t i=0; i<MAXSUBSCRIPTIONS; i++) {
for (uint8_t i = 0; i < MAXSUBSCRIPTIONS; i++) {
subscriptions[i] = 0;
}
@ -117,15 +132,13 @@ Adafruit_MQTT::Adafruit_MQTT(const char *server,
will_qos = 0;
will_retain = 0;
packet_id_counter = 0;
keepAliveInterval = MQTT_CONN_KEEPALIVE;
packet_id_counter = 0;
}
Adafruit_MQTT::Adafruit_MQTT(const char *server,
uint16_t port,
const char *user,
const char *pass) {
Adafruit_MQTT::Adafruit_MQTT(const char *server, uint16_t port,
const char *user, const char *pass) {
servername = server;
portnum = port;
clientid = "";
@ -133,7 +146,7 @@ Adafruit_MQTT::Adafruit_MQTT(const char *server,
password = pass;
// reset subscriptions
for (uint8_t i=0; i<MAXSUBSCRIPTIONS; i++) {
for (uint8_t i = 0; i < MAXSUBSCRIPTIONS; i++) {
subscriptions[i] = 0;
}
@ -142,8 +155,9 @@ Adafruit_MQTT::Adafruit_MQTT(const char *server,
will_qos = 0;
will_retain = 0;
packet_id_counter = 0;
keepAliveInterval = MQTT_CONN_KEEPALIVE;
packet_id_counter = 0;
}
int8_t Adafruit_MQTT::connect() {
@ -158,80 +172,96 @@ int8_t Adafruit_MQTT::connect() {
// Read connect response packet and verify it
len = readFullPacket(buffer, MAXBUFFERSIZE, CONNECT_TIMEOUT_MS);
if (len != 4)
if (len != 4) {
return -1;
if ((buffer[0] != (MQTT_CTRL_CONNECTACK << 4)) || (buffer[1] != 2))
}
if ((buffer[0] != (MQTT_CTRL_CONNECTACK << 4)) || (buffer[1] != 2)) {
return -1;
}
if (buffer[3] != 0)
return buffer[3];
// Setup subscriptions once connected.
for (uint8_t i=0; i<MAXSUBSCRIPTIONS; i++) {
for (uint8_t i = 0; i < MAXSUBSCRIPTIONS; i++) {
// Ignore subscriptions that aren't defined.
if (subscriptions[i] == 0) continue;
if (subscriptions[i] == 0)
continue;
boolean success = false;
for (uint8_t retry=0; (retry<3) && !success; retry++) { // retry until we get a suback
for (uint8_t retry = 0; (retry < 3) && !success;
retry++) { // retry until we get a suback
// Construct and send subscription packet.
uint8_t len = subscribePacket(buffer, subscriptions[i]->topic, subscriptions[i]->qos);
uint8_t len = subscribePacket(buffer, subscriptions[i]->topic,
subscriptions[i]->qos);
if (!sendPacket(buffer, len))
return -1;
return -1;
if(MQTT_PROTOCOL_LEVEL < 3) // older versions didn't suback
break;
if (MQTT_PROTOCOL_LEVEL < 3) // older versions didn't suback
break;
// Check for SUBACK if using MQTT 3.1.1 or higher
// TODO: The Server is permitted to start sending PUBLISH packets matching the
// Subscription before the Server sends the SUBACK Packet. (will really need to use callbacks - ada)
// TODO: The Server is permitted to start sending PUBLISH packets matching
// the Subscription before the Server sends the SUBACK Packet. (will
// really need to use callbacks - ada)
//Serial.println("\t**looking for suback");
if (processPacketsUntil(buffer, MQTT_CTRL_SUBACK, SUBACK_TIMEOUT_MS)) {
success = true;
break;
success = true;
break;
}
//Serial.println("\t**failed, retrying!");
}
if (! success) return -2; // failed to sub for some reason
if (!success)
return -2; // failed to sub for some reason
}
return 0;
}
int8_t Adafruit_MQTT::connect(const char *user, const char *pass)
{
int8_t Adafruit_MQTT::connect(const char *user, const char *pass) {
username = user;
password = pass;
return connect();
}
uint16_t Adafruit_MQTT::processPacketsUntil(uint8_t *buffer, uint8_t waitforpackettype, uint16_t timeout) {
uint16_t Adafruit_MQTT::processPacketsUntil(uint8_t *buffer,
uint8_t waitforpackettype,
uint16_t timeout) {
uint16_t len;
while (len = readFullPacket(buffer, MAXBUFFERSIZE, timeout)) {
//DEBUG_PRINT("Packet read size: "); DEBUG_PRINTLN(len);
// TODO: add subscription reading & call back processing here
while (true) {
len = readFullPacket(buffer, MAXBUFFERSIZE, timeout);
if ((buffer[0] >> 4) == waitforpackettype) {
//DEBUG_PRINTLN(F("Found right packet"));
if (len == 0) {
break;
}
uint8_t packetType = (buffer[0] >> 4);
if (packetType == waitforpackettype) {
return len;
} else {
ERROR_PRINTLN(F("Dropped a packet"));
if (packetType == MQTT_CTRL_PUBLISH) {
handleSubscriptionPacket(len);
} else {
ERROR_PRINTLN(F("Dropped a packet"));
}
}
}
return 0;
}
uint16_t Adafruit_MQTT::readFullPacket(uint8_t *buffer, uint16_t maxsize, uint16_t timeout) {
uint16_t Adafruit_MQTT::readFullPacket(uint8_t *buffer, uint16_t maxsize,
uint16_t timeout) {
// will read a packet and Do The Right Thing with length
uint8_t *pbuff = buffer;
uint8_t rlen;
uint16_t rlen;
// read the packet type:
rlen = readPacket(pbuff, 1, timeout);
if (rlen != 1) return 0;
if (rlen != 1)
return 0;
DEBUG_PRINT(F("Packet Type:\t")); DEBUG_PRINTBUFFER(pbuff, rlen);
DEBUG_PRINT(F("Packet Type:\t"));
DEBUG_PRINTBUFFER(pbuff, rlen);
pbuff++;
uint32_t value = 0;
@ -240,83 +270,100 @@ uint16_t Adafruit_MQTT::readFullPacket(uint8_t *buffer, uint16_t maxsize, uint16
do {
rlen = readPacket(pbuff, 1, timeout);
if (rlen != 1) return 0;
if (rlen != 1)
return 0;
encodedByte = pbuff[0]; // save the last read val
pbuff++; // get ready for reading the next byte
pbuff++; // get ready for reading the next byte
uint32_t intermediate = encodedByte & 0x7F;
intermediate *= multiplier;
value += intermediate;
multiplier *= 128;
if (multiplier > (128UL*128UL*128UL)) {
if (multiplier > (128UL * 128UL * 128UL)) {
DEBUG_PRINT(F("Malformed packet len\n"));
return 0;
}
} while (encodedByte & 0x80);
DEBUG_PRINT(F("Packet Length:\t")); DEBUG_PRINTLN(value);
if (value > (maxsize - (pbuff-buffer) - 1)) {
DEBUG_PRINTLN(F("Packet too big for buffer"));
rlen = readPacket(pbuff, (maxsize - (pbuff-buffer) - 1), timeout);
DEBUG_PRINT(F("Packet Length:\t"));
DEBUG_PRINTLN(value);
// maxsize is limited to 65536 by 16-bit unsigned
if (value > uint32_t(maxsize - (pbuff - buffer) - 1)) {
DEBUG_PRINTLN(F("Packet too big for buffer"));
rlen = readPacket(pbuff, (maxsize - (pbuff - buffer) - 1), timeout);
} else {
rlen = readPacket(pbuff, value, timeout);
}
//DEBUG_PRINT(F("Remaining packet:\t")); DEBUG_PRINTBUFFER(pbuff, rlen);
// DEBUG_PRINT(F("Remaining packet:\t")); DEBUG_PRINTBUFFER(pbuff, rlen);
return ((pbuff - buffer)+rlen);
return ((pbuff - buffer) + rlen);
}
const __FlashStringHelper* Adafruit_MQTT::connectErrorString(int8_t code) {
switch (code) {
case 1: return F("The Server does not support the level of the MQTT protocol requested");
case 2: return F("The Client identifier is correct UTF-8 but not allowed by the Server");
case 3: return F("The MQTT service is unavailable");
case 4: return F("The data in the user name or password is malformed");
case 5: return F("Not authorized to connect");
case 6: return F("Exceeded reconnect rate limit. Please try again later.");
case 7: return F("You have been banned from connecting. Please contact the MQTT server administrator for more details.");
case -1: return F("Connection failed");
case -2: return F("Failed to subscribe");
default: return F("Unknown error");
}
const __FlashStringHelper *Adafruit_MQTT::connectErrorString(int8_t code) {
switch (code) {
case 1:
return F(
"The Server does not support the level of the MQTT protocol requested");
case 2:
return F(
"The Client identifier is correct UTF-8 but not allowed by the Server");
case 3:
return F("The MQTT service is unavailable");
case 4:
return F("The data in the user name or password is malformed");
case 5:
return F("Not authorized to connect");
case 6:
return F("Exceeded reconnect rate limit. Please try again later.");
case 7:
return F("You have been banned from connecting. Please contact the MQTT "
"server administrator for more details.");
case -1:
return F("Connection failed");
case -2:
return F("Failed to subscribe");
default:
return F("Unknown error");
}
}
bool Adafruit_MQTT::disconnect() {
// Construct and send disconnect packet.
uint8_t len = disconnectPacket(buffer);
if (! sendPacket(buffer, len))
if (!sendPacket(buffer, len))
DEBUG_PRINTLN(F("Unable to send disconnect packet"));
return disconnectServer();
}
bool Adafruit_MQTT::publish(const char *topic, const char *data, uint8_t qos) {
return publish(topic, (uint8_t*)(data), strlen(data), qos);
bool Adafruit_MQTT::publish(const char *topic, const char *data, uint8_t qos, uint8_t retain) {
return publish(topic, (uint8_t *)(data), strlen(data), qos, retain);
}
bool Adafruit_MQTT::publish(const char *topic, uint8_t *data, uint16_t bLen, uint8_t qos) {
bool Adafruit_MQTT::publish(const char *topic, uint8_t *data, uint16_t bLen,
uint8_t qos, uint8_t retain) {
// Construct and send publish packet.
uint16_t len = publishPacket(buffer, topic, data, bLen, qos);
uint16_t len =
publishPacket(buffer, topic, data, bLen, qos, (uint16_t)sizeof(buffer), retain);
if (!sendPacket(buffer, len))
return false;
// If QOS level is high enough verify the response packet.
if (qos > 0) {
len = readFullPacket(buffer, MAXBUFFERSIZE, PUBLISH_TIMEOUT_MS);
len = processPacketsUntil(buffer, MQTT_CTRL_PUBACK, PUBLISH_TIMEOUT_MS);
DEBUG_PRINT(F("Publish QOS1+ reply:\t"));
DEBUG_PRINTBUFFER(buffer, len);
if (len != 4)
return false;
if ((buffer[0] >> 4) != MQTT_CTRL_PUBACK)
return false;
uint16_t packnum = buffer[2];
packnum <<= 8;
packnum |= buffer[3];
// we increment the packet_id_counter right after publishing so inc here too to match
// we increment the packet_id_counter right after publishing so inc here too
// to match
packnum++;
if (packnum != packet_id_counter)
return false;
@ -325,7 +372,8 @@ bool Adafruit_MQTT::publish(const char *topic, uint8_t *data, uint16_t bLen, uin
return true;
}
bool Adafruit_MQTT::will(const char *topic, const char *payload, uint8_t qos, uint8_t retain) {
bool Adafruit_MQTT::will(const char *topic, const char *payload, uint8_t qos,
uint8_t retain) {
if (connected()) {
DEBUG_PRINT(F("Will defined after connect"));
@ -338,22 +386,41 @@ bool Adafruit_MQTT::will(const char *topic, const char *payload, uint8_t qos, ui
will_retain = retain;
return true;
}
/***************************************************************************/
/*!
@brief Sets the connect packet's KeepAlive Interval, in seconds. This
function MUST be called prior to connect().
@param keepAlive
Maximum amount of time without communication between the
client and the MQTT broker, in seconds.
@returns True if called prior to connect(), False otherwise.
*/
/***************************************************************************/
bool Adafruit_MQTT::setKeepAliveInterval(uint16_t keepAlive) {
if (connected()) {
DEBUG_PRINT(F("keepAlive defined after connection established."));
return false;
}
keepAliveInterval = keepAlive;
return true;
}
bool Adafruit_MQTT::subscribe(Adafruit_MQTT_Subscribe *sub) {
uint8_t i;
// see if we are already subscribed
for (i=0; i<MAXSUBSCRIPTIONS; i++) {
for (i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i] == sub) {
DEBUG_PRINTLN(F("Already subscribed"));
return true;
}
}
if (i==MAXSUBSCRIPTIONS) { // add to subscriptionlist
for (i=0; i<MAXSUBSCRIPTIONS; i++) {
if (i == MAXSUBSCRIPTIONS) { // add to subscriptionlist
for (i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i] == 0) {
DEBUG_PRINT(F("Added sub ")); DEBUG_PRINTLN(i);
DEBUG_PRINT(F("Added sub "));
DEBUG_PRINTLN(i);
subscriptions[i] = sub;
return true;
}
@ -368,22 +435,23 @@ bool Adafruit_MQTT::unsubscribe(Adafruit_MQTT_Subscribe *sub) {
uint8_t i;
// see if we are already subscribed
for (i=0; i<MAXSUBSCRIPTIONS; i++) {
for (i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i] == sub) {
DEBUG_PRINTLN(F("Found matching subscription and attempting to unsubscribe."));
DEBUG_PRINTLN(
F("Found matching subscription and attempting to unsubscribe."));
// Construct and send unsubscribe packet.
uint8_t len = unsubscribePacket(buffer, subscriptions[i]->topic);
// sending unsubscribe failed
if (! sendPacket(buffer, len))
if (!sendPacket(buffer, len))
return false;
// if QoS for this subscription is 1 or 2, we need
// to wait for the unsuback to confirm unsubscription
if(subscriptions[i]->qos > 0 && MQTT_PROTOCOL_LEVEL > 3) {
if (subscriptions[i]->qos > 0 && MQTT_PROTOCOL_LEVEL > 3) {
// wait for UNSUBACK
len = readFullPacket(buffer, MAXBUFFERSIZE, CONNECT_TIMEOUT_MS);
@ -391,53 +459,43 @@ bool Adafruit_MQTT::unsubscribe(Adafruit_MQTT_Subscribe *sub) {
DEBUG_PRINTBUFFER(buffer, len);
if ((len != 5) || (buffer[0] != (MQTT_CTRL_UNSUBACK << 4))) {
return false; // failure to unsubscribe
return false; // failure to unsubscribe
}
}
subscriptions[i] = 0;
return true;
}
}
// subscription not found, so we are unsubscribed
return true;
}
void Adafruit_MQTT::processPackets(int16_t timeout) {
uint16_t len;
uint32_t elapsed = 0, endtime, starttime = millis();
while (elapsed < (uint32_t)timeout) {
Adafruit_MQTT_Subscribe *sub = readSubscription(timeout - elapsed);
if (sub) {
//Serial.println("**** sub packet received");
if (sub->callback_uint32t != NULL) {
// huh lets do the callback in integer mode
uint32_t data = 0;
data = atoi((char *)sub->lastread);
//Serial.print("*** calling int callback with : "); Serial.println(data);
sub->callback_uint32t(data);
}
else if (sub->callback_double != NULL) {
// huh lets do the callback in doublefloat mode
double data = 0;
data = atof((char *)sub->lastread);
//Serial.print("*** calling double callback with : "); Serial.println(data);
sub->callback_double(data);
}
else if (sub->callback_buffer != NULL) {
// huh lets do the callback in buffer mode
//Serial.print("*** calling buffer callback with : "); Serial.println((char *)sub->lastread);
sub->callback_buffer((char *)sub->lastread, sub->datalen);
}
else if (sub->callback_io != NULL) {
// huh lets do the callback in integer mode
uint32_t data = 0;
data = atoi((char *)sub->lastread);
sub->callback_uint32t(data);
} else if (sub->callback_double != NULL) {
// huh lets do the callback in doublefloat mode
double data = 0;
data = atof((char *)sub->lastread);
sub->callback_double(data);
} else if (sub->callback_buffer != NULL) {
// huh lets do the callback in buffer mode
sub->callback_buffer((char *)sub->lastread, sub->datalen);
} else if (sub->callback_io != NULL) {
// huh lets do the callback in io mode
//Serial.print("*** calling io instance callback with : "); Serial.println((char *)sub->lastread);
((sub->io_mqtt)->*(sub->callback_io))((char *)sub->lastread, sub->datalen);
((sub->io_mqtt)->*(sub->callback_io))((char *)sub->lastread,
sub->datalen);
}
}
@ -449,23 +507,61 @@ void Adafruit_MQTT::processPackets(int16_t timeout) {
elapsed += (endtime - starttime);
}
}
Adafruit_MQTT_Subscribe *Adafruit_MQTT::readSubscription(int16_t timeout) {
// Sync or Async subscriber with message
Adafruit_MQTT_Subscribe *s = 0;
// Check if are unread messages
for (uint8_t i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i] && subscriptions[i]->new_message) {
s = subscriptions[i];
break;
}
}
// not unread message
if (!s) {
// Check if data is available to read.
uint16_t len = readFullPacket(buffer, MAXBUFFERSIZE,
timeout); // return one full packet
s = handleSubscriptionPacket(len);
}
// it there is a message, mark it as not pending
if (s) {
s->new_message = false;
}
return s;
}
Adafruit_MQTT_Subscribe *Adafruit_MQTT::handleSubscriptionPacket(uint16_t len) {
uint16_t i, topiclen, datalen;
// Check if data is available to read.
uint16_t len = readFullPacket(buffer, MAXBUFFERSIZE, timeout); // return one full packet
if (!len)
return NULL; // No data available, just quit.
DEBUG_PRINT("Packet len: "); DEBUG_PRINTLN(len);
if (!len) {
return NULL; // No data available, just quit.
}
DEBUG_PRINT("Packet len: ");
DEBUG_PRINTLN(len);
DEBUG_PRINTBUFFER(buffer, len);
if (len < 3) {
return NULL;
}
if ((buffer[0] & 0xF0) != (MQTT_CTRL_PUBLISH) << 4) {
return NULL;
}
// Parse out length of packet.
topiclen = buffer[3];
DEBUG_PRINT(F("Looking for subscription len ")); DEBUG_PRINTLN(topiclen);
uint16_t const topicoffset = packetAdditionalLen(len);
uint16_t const topicstart = topicoffset + 4;
topiclen = buffer[3 + topicoffset];
DEBUG_PRINT(F("Looking for subscription len "));
DEBUG_PRINTLN(topiclen);
// Find subscription associated with this packet.
for (i=0; i<MAXSUBSCRIPTIONS; i++) {
for (i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i]) {
// Skip this subscription if its name length isn't the same as the
// received topic name.
@ -473,40 +569,52 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::readSubscription(int16_t timeout) {
continue;
// Stop if the subscription topic matches the received topic. Be careful
// to make comparison case insensitive.
if (strncasecmp((char*)buffer+4, subscriptions[i]->topic, topiclen) == 0) {
DEBUG_PRINT(F("Found sub #")); DEBUG_PRINTLN(i);
if (strncasecmp((char *)buffer + topicstart, subscriptions[i]->topic,
topiclen) == 0) {
DEBUG_PRINT(F("Found sub #"));
DEBUG_PRINTLN(i);
if (subscriptions[i]->new_message) {
DEBUG_PRINTLN(F("Lost previous message"));
} else {
subscriptions[i]->new_message = true;
}
break;
}
}
}
if (i==MAXSUBSCRIPTIONS) return NULL; // matching sub not found ???
if (i == MAXSUBSCRIPTIONS)
return NULL; // matching sub not found ???
uint8_t packet_id_len = 0;
uint16_t packetid;
uint16_t packetid = 0;
// Check if it is QoS 1, TODO: we dont support QoS 2
if ((buffer[0] & 0x6) == 0x2) {
packet_id_len = 2;
packetid = buffer[topiclen+4];
packetid = buffer[topiclen + topicstart];
packetid <<= 8;
packetid |= buffer[topiclen+5];
packetid |= buffer[topiclen + topicstart + 1];
}
// zero out the old data
memset(subscriptions[i]->lastread, 0, SUBSCRIPTIONDATALEN);
datalen = len - topiclen - packet_id_len - 4;
datalen = len - topiclen - packet_id_len - topicstart;
if (datalen > SUBSCRIPTIONDATALEN) {
datalen = SUBSCRIPTIONDATALEN-1; // cut it off
datalen = SUBSCRIPTIONDATALEN - 1; // cut it off
}
// extract out just the data, into the subscription object itself
memmove(subscriptions[i]->lastread, buffer+4+topiclen+packet_id_len, datalen);
memmove(subscriptions[i]->lastread,
buffer + topicstart + topiclen + packet_id_len, datalen);
subscriptions[i]->datalen = datalen;
DEBUG_PRINT(F("Data len: ")); DEBUG_PRINTLN(datalen);
DEBUG_PRINT(F("Data: ")); DEBUG_PRINTLN((char *)subscriptions[i]->lastread);
DEBUG_PRINT(F("Data len: "));
DEBUG_PRINTLN(datalen);
DEBUG_PRINT(F("Data: "));
DEBUG_PRINTLN((char *)subscriptions[i]->lastread);
if ((MQTT_PROTOCOL_LEVEL > 3) &&(buffer[0] & 0x6) == 0x2) {
if ((MQTT_PROTOCOL_LEVEL > 3) && (buffer[0] & 0x6) == 0x2) {
uint8_t ackpacket[4];
// Construct and send puback packet.
uint8_t len = pubackPacket(ackpacket, packetid);
if (!sendPacket(ackpacket, len))
@ -520,11 +628,12 @@ Adafruit_MQTT_Subscribe *Adafruit_MQTT::readSubscription(int16_t timeout) {
void Adafruit_MQTT::flushIncoming(uint16_t timeout) {
// flush input!
DEBUG_PRINTLN(F("Flushing input buffer"));
while (readPacket(buffer, MAXBUFFERSIZE, timeout));
while (readPacket(buffer, MAXBUFFERSIZE, timeout))
;
}
bool Adafruit_MQTT::ping(uint8_t num) {
//flushIncoming(100);
// flushIncoming(100);
while (num--) {
// Construct and send ping packet.
@ -554,15 +663,15 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) {
// fixed header, connection messsage no flags
p[0] = (MQTT_CTRL_CONNECT << 4) | 0x0;
p+=2;
p += 2;
// fill in packet[1] last
#if MQTT_PROTOCOL_LEVEL == 3
p = stringprint(p, "MQIsdp");
p = stringprint(p, "MQIsdp");
#elif MQTT_PROTOCOL_LEVEL == 4
p = stringprint(p, "MQTT");
p = stringprint(p, "MQTT");
#else
#error "MQTT level not supported"
#error "MQTT level not supported"
#endif
p[0] = MQTT_PROTOCOL_LEVEL;
@ -576,14 +685,13 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) {
p[0] |= MQTT_CONN_WILLFLAG;
if(will_qos == 1)
if (will_qos == 1)
p[0] |= MQTT_CONN_WILLQOS_1;
else if(will_qos == 2)
else if (will_qos == 2)
p[0] |= MQTT_CONN_WILLQOS_2;
if(will_retain == 1)
if (will_retain == 1)
p[0] |= MQTT_CONN_WILLRETAIN;
}
if (pgm_read_byte(username) != 0)
@ -592,13 +700,13 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) {
p[0] |= MQTT_CONN_PASSWORDFLAG;
p++;
p[0] = MQTT_CONN_KEEPALIVE >> 8;
p[0] = keepAliveInterval >> 8;
p++;
p[0] = MQTT_CONN_KEEPALIVE & 0xFF;
p[0] = keepAliveInterval & 0xFF;
p++;
if(MQTT_PROTOCOL_LEVEL == 3) {
p = stringprint(p, clientid, 23); // Limit client ID to first 23 characters.
if (MQTT_PROTOCOL_LEVEL == 3) {
p = stringprint(p, clientid, 23); // Limit client ID to first 23 characters.
} else {
if (pgm_read_byte(clientid) != 0) {
p = stringprint(p, clientid);
@ -625,29 +733,47 @@ uint8_t Adafruit_MQTT::connectPacket(uint8_t *packet) {
len = p - packet;
packet[1] = len-2; // don't include the 2 bytes of fixed header data
packet[1] = len - 2; // don't include the 2 bytes of fixed header data
DEBUG_PRINTLN(F("MQTT connect packet:"));
DEBUG_PRINTBUFFER(buffer, len);
return len;
}
// as per http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718040
// as per
// http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc398718040
uint16_t Adafruit_MQTT::publishPacket(uint8_t *packet, const char *topic,
uint8_t *data, uint16_t bLen, uint8_t qos) {
uint8_t *data, uint16_t bLen, uint8_t qos,
uint16_t maxPacketLen, uint8_t retain) {
uint8_t *p = packet;
uint16_t len=0;
uint16_t len = 0;
// calc length of non-header data
len += 2; // two bytes to set the topic size
len += 2; // two bytes to set the topic size
len += strlen(topic); // topic length
if(qos > 0) {
if (qos > 0) {
len += 2; // qos packet id
}
len += bLen; // payload length
// Calculate additional bytes for length field (if any)
uint16_t additionalLen = packetAdditionalLen(len + bLen);
// Payload remaining length. When maxPacketLen provided is 0, let's
// assume buffer is big enough. Fingers crossed.
// 2 + additionalLen: header byte + remaining length field (from 1 to 4 bytes)
// len = topic size field + value (string)
// bLen = buffer size
if (!(maxPacketLen == 0 ||
(len + bLen + 2 + additionalLen <= maxPacketLen))) {
// If we make it here, we got a pickle: the payload is not going
// to fit in the packet buffer. Instead of corrupting memory, let's
// do something less damaging by reducing the bLen to what we are
// able to accomodate. Alternatively, consider using a bigger
// maxPacketLen.
bLen = maxPacketLen - (len + 2 + packetAdditionalLen(maxPacketLen));
}
len += bLen; // remaining len excludes header byte & length field
// Now you can start generating the packet!
p[0] = MQTT_CTRL_PUBLISH << 4 | qos << 1;
p[0] = MQTT_CTRL_PUBLISH << 4 | qos << 1 | (retain ? 1 : 0);
p++;
// fill in packet[1] last
@ -655,28 +781,28 @@ uint16_t Adafruit_MQTT::publishPacket(uint8_t *packet, const char *topic,
uint8_t encodedByte = len % 128;
len /= 128;
// if there are more data to encode, set the top bit of this byte
if ( len > 0 ) {
if (len > 0) {
encodedByte |= 0x80;
}
p[0] = encodedByte;
p++;
} while ( len > 0 );
} while (len > 0);
// topic comes before packet identifier
p = stringprint(p, topic);
// add packet identifier. used for checking PUBACK in QOS > 0
if(qos > 0) {
if (qos > 0) {
p[0] = (packet_id_counter >> 8) & 0xFF;
p[1] = packet_id_counter & 0xFF;
p+=2;
p += 2;
// increment the packet id
packet_id_counter++;
}
memmove(p, data, bLen);
p+= bLen;
p += bLen;
len = p - packet;
DEBUG_PRINTLN(F("MQTT publish packet:"));
DEBUG_PRINTBUFFER(buffer, len);
@ -690,12 +816,12 @@ uint8_t Adafruit_MQTT::subscribePacket(uint8_t *packet, const char *topic,
p[0] = MQTT_CTRL_SUBSCRIBE << 4 | MQTT_QOS_1 << 1;
// fill in packet[1] last
p+=2;
p += 2;
// packet identifier. used for checking SUBACK
p[0] = (packet_id_counter >> 8) & 0xFF;
p[1] = packet_id_counter & 0xFF;
p+=2;
p += 2;
// increment the packet id
packet_id_counter++;
@ -706,14 +832,12 @@ uint8_t Adafruit_MQTT::subscribePacket(uint8_t *packet, const char *topic,
p++;
len = p - packet;
packet[1] = len-2; // don't include the 2 bytes of fixed header data
packet[1] = len - 2; // don't include the 2 bytes of fixed header data
DEBUG_PRINTLN(F("MQTT subscription packet:"));
DEBUG_PRINTBUFFER(buffer, len);
return len;
}
uint8_t Adafruit_MQTT::unsubscribePacket(uint8_t *packet, const char *topic) {
uint8_t *p = packet;
@ -721,12 +845,12 @@ uint8_t Adafruit_MQTT::unsubscribePacket(uint8_t *packet, const char *topic) {
p[0] = MQTT_CTRL_UNSUBSCRIBE << 4 | 0x1;
// fill in packet[1] last
p+=2;
p += 2;
// packet identifier. used for checking UNSUBACK
p[0] = (packet_id_counter >> 8) & 0xFF;
p[1] = packet_id_counter & 0xFF;
p+=2;
p += 2;
// increment the packet id
packet_id_counter++;
@ -734,11 +858,10 @@ uint8_t Adafruit_MQTT::unsubscribePacket(uint8_t *packet, const char *topic) {
p = stringprint(p, topic);
len = p - packet;
packet[1] = len-2; // don't include the 2 bytes of fixed header data
packet[1] = len - 2; // don't include the 2 bytes of fixed header data
DEBUG_PRINTLN(F("MQTT unsubscription packet:"));
DEBUG_PRINTBUFFER(buffer, len);
return len;
}
uint8_t Adafruit_MQTT::pingPacket(uint8_t *packet) {
@ -767,43 +890,56 @@ uint8_t Adafruit_MQTT::disconnectPacket(uint8_t *packet) {
return 2;
}
uint Adafruit_MQTT::getSubscriptionCount()
{
uint count = 0;
for (int i = 0; i < MAXSUBSCRIPTIONS; i++) {
if (subscriptions[i])
count++;
}
return count;
}
// Adafruit_MQTT_Publish Definition ////////////////////////////////////////////
Adafruit_MQTT_Publish::Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver,
const char *feed, uint8_t q) {
const char *feed, uint8_t q, uint8_t r) {
mqtt = mqttserver;
topic = feed;
qos = q;
retain = r;
}
bool Adafruit_MQTT_Publish::publish(int32_t i) {
char payload[12];
ltoa(i, payload, 10);
return mqtt->publish(topic, payload, qos);
return mqtt->publish(topic, payload, qos, retain);
}
bool Adafruit_MQTT_Publish::publish(uint32_t i) {
char payload[11];
ultoa(i, payload, 10);
return mqtt->publish(topic, payload, qos);
return mqtt->publish(topic, payload, qos, retain);
}
bool Adafruit_MQTT_Publish::publish(double f, uint8_t precision) {
char payload[41]; // Need to technically hold float max, 39 digits and minus sign.
char payload[41]; // Need to technically hold float max, 39 digits and minus
// sign.
dtostrf(f, 0, precision, payload);
return mqtt->publish(topic, payload, qos);
return mqtt->publish(topic, payload, qos, retain);
}
bool Adafruit_MQTT_Publish::publish(const char *payload) {
return mqtt->publish(topic, payload, qos);
return mqtt->publish(topic, payload, qos, retain);
}
//publish buffer of arbitrary length
// publish buffer of arbitrary length
bool Adafruit_MQTT_Publish::publish(uint8_t *payload, uint16_t bLen) {
return mqtt->publish(topic, payload, bLen, qos);
return mqtt->publish(topic, payload, bLen, qos, retain);
}
// Adafruit_MQTT_Subscribe Definition //////////////////////////////////////////
Adafruit_MQTT_Subscribe::Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver,
@ -817,6 +953,7 @@ Adafruit_MQTT_Subscribe::Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver,
callback_double = 0;
callback_io = 0;
io_mqtt = 0;
new_message = false;
}
void Adafruit_MQTT_Subscribe::setCallback(SubscribeCallbackUInt32Type cb) {
@ -831,9 +968,10 @@ void Adafruit_MQTT_Subscribe::setCallback(SubscribeCallbackBufferType cb) {
callback_buffer = cb;
}
void Adafruit_MQTT_Subscribe::setCallback(AdafruitIO_MQTT *io, SubscribeCallbackIOType cb) {
void Adafruit_MQTT_Subscribe::setCallback(AdafruitIO_MQTT *io,
SubscribeCallbackIOType cb) {
callback_io = cb;
io_mqtt= io;
io_mqtt = io;
}
void Adafruit_MQTT_Subscribe::removeCallback(void) {

View File

@ -9,8 +9,8 @@
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -44,50 +44,62 @@
// Define actual debug output functions when necessary.
#ifdef MQTT_DEBUG
#define DEBUG_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#define DEBUG_PRINTBUFFER(buffer, len) { printBuffer(buffer, len); }
#define DEBUG_PRINT(...) \
{ DEBUG_PRINTER.print(__VA_ARGS__); }
#define DEBUG_PRINTLN(...) \
{ DEBUG_PRINTER.println(__VA_ARGS__); }
#define DEBUG_PRINTBUFFER(buffer, len) \
{ printBuffer(buffer, len); }
#else
#define DEBUG_PRINT(...) {}
#define DEBUG_PRINTLN(...) {}
#define DEBUG_PRINTBUFFER(buffer, len) {}
#define DEBUG_PRINT(...) \
{}
#define DEBUG_PRINTLN(...) \
{}
#define DEBUG_PRINTBUFFER(buffer, len) \
{}
#endif
#ifdef MQTT_ERROR
#define ERROR_PRINT(...) { DEBUG_PRINTER.print(__VA_ARGS__); }
#define ERROR_PRINTLN(...) { DEBUG_PRINTER.println(__VA_ARGS__); }
#define ERROR_PRINTBUFFER(buffer, len) { printBuffer(buffer, len); }
#define ERROR_PRINT(...) \
{ DEBUG_PRINTER.print(__VA_ARGS__); }
#define ERROR_PRINTLN(...) \
{ DEBUG_PRINTER.println(__VA_ARGS__); }
#define ERROR_PRINTBUFFER(buffer, len) \
{ printBuffer(buffer, len); }
#else
#define ERROR_PRINT(...) {}
#define ERROR_PRINTLN(...) {}
#define ERROR_PRINTBUFFER(buffer, len) {}
#define ERROR_PRINT(...) \
{}
#define ERROR_PRINTLN(...) \
{}
#define ERROR_PRINTBUFFER(buffer, len) \
{}
#endif
// Use 3 (MQTT 3.0) or 4 (MQTT 3.1.1)
#define MQTT_PROTOCOL_LEVEL 4
#define MQTT_CTRL_CONNECT 0x1
#define MQTT_CTRL_CONNECTACK 0x2
#define MQTT_CTRL_PUBLISH 0x3
#define MQTT_CTRL_PUBACK 0x4
#define MQTT_CTRL_PUBREC 0x5
#define MQTT_CTRL_PUBREL 0x6
#define MQTT_CTRL_PUBCOMP 0x7
#define MQTT_CTRL_SUBSCRIBE 0x8
#define MQTT_CTRL_SUBACK 0x9
#define MQTT_CTRL_CONNECT 0x1
#define MQTT_CTRL_CONNECTACK 0x2
#define MQTT_CTRL_PUBLISH 0x3
#define MQTT_CTRL_PUBACK 0x4
#define MQTT_CTRL_PUBREC 0x5
#define MQTT_CTRL_PUBREL 0x6
#define MQTT_CTRL_PUBCOMP 0x7
#define MQTT_CTRL_SUBSCRIBE 0x8
#define MQTT_CTRL_SUBACK 0x9
#define MQTT_CTRL_UNSUBSCRIBE 0xA
#define MQTT_CTRL_UNSUBACK 0xB
#define MQTT_CTRL_PINGREQ 0xC
#define MQTT_CTRL_PINGRESP 0xD
#define MQTT_CTRL_DISCONNECT 0xE
#define MQTT_CTRL_UNSUBACK 0xB
#define MQTT_CTRL_PINGREQ 0xC
#define MQTT_CTRL_PINGRESP 0xD
#define MQTT_CTRL_DISCONNECT 0xE
#define MQTT_QOS_1 0x1
#define MQTT_QOS_0 0x0
#define CONNECT_TIMEOUT_MS 6000
#define PUBLISH_TIMEOUT_MS 500
#define PING_TIMEOUT_MS 500
#define SUBACK_TIMEOUT_MS 500
#define PING_TIMEOUT_MS 500
#define SUBACK_TIMEOUT_MS 500
// Adjust as necessary, in seconds. Default to 5 minutes.
#define MQTT_CONN_KEEPALIVE 300
@ -97,51 +109,46 @@
// 23 char client ID.
#define MAXBUFFERSIZE (150)
#define MQTT_CONN_USERNAMEFLAG 0x80
#define MQTT_CONN_PASSWORDFLAG 0x40
#define MQTT_CONN_WILLRETAIN 0x20
#define MQTT_CONN_WILLQOS_1 0x08
#define MQTT_CONN_WILLQOS_2 0x18
#define MQTT_CONN_WILLFLAG 0x04
#define MQTT_CONN_CLEANSESSION 0x02
// how many subscriptions we want to be able to track
#define MAXSUBSCRIPTIONS 5
#define MQTT_CONN_USERNAMEFLAG 0x80
#define MQTT_CONN_PASSWORDFLAG 0x40
#define MQTT_CONN_WILLRETAIN 0x20
#define MQTT_CONN_WILLQOS_1 0x08
#define MQTT_CONN_WILLQOS_2 0x18
#define MQTT_CONN_WILLFLAG 0x04
#define MQTT_CONN_CLEANSESSION 0x02
// how much data we save in a subscription object
// eg max-subscription-payload-size
#if defined (__AVR_ATmega32U4__) || defined(__AVR_ATmega328P__)
#define SUBSCRIPTIONDATALEN 20
// and how many subscriptions we want to be able to track.
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega328P__)
#define MAXSUBSCRIPTIONS 5
#define SUBSCRIPTIONDATALEN 20
#else
#define SUBSCRIPTIONDATALEN 100
#define MAXSUBSCRIPTIONS 15
#define SUBSCRIPTIONDATALEN 100
#endif
class AdafruitIO_MQTT; // forward decl
class AdafruitIO_MQTT; // forward decl
//Function pointer that returns an int
// Function pointer that returns an int
typedef void (*SubscribeCallbackUInt32Type)(uint32_t);
// returns a double
typedef void (*SubscribeCallbackDoubleType)(double);
// returns a chunk of raw data
typedef void (*SubscribeCallbackBufferType)(char *str, uint16_t len);
// returns an io data wrapper instance
typedef void (AdafruitIO_MQTT::*SubscribeCallbackIOType)(char *str, uint16_t len);
typedef void (AdafruitIO_MQTT::*SubscribeCallbackIOType)(char *str,
uint16_t len);
extern void printBuffer(uint8_t *buffer, uint16_t len);
class Adafruit_MQTT_Subscribe; // forward decl
class Adafruit_MQTT_Subscribe; // forward decl
class Adafruit_MQTT {
public:
Adafruit_MQTT(const char *server,
uint16_t port,
const char *cid,
const char *user,
const char *pass);
public:
Adafruit_MQTT(const char *server, uint16_t port, const char *cid,
const char *user, const char *pass);
Adafruit_MQTT(const char *server,
uint16_t port,
const char *user = "",
Adafruit_MQTT(const char *server, uint16_t port, const char *user = "",
const char *pass = "");
virtual ~Adafruit_MQTT() {}
@ -163,23 +170,28 @@ class Adafruit_MQTT {
// connect(). This returns a __FlashStringHelper*, which points to a
// string stored in flash, but can be directly passed to e.g.
// Serial.println without any further processing.
const __FlashStringHelper* connectErrorString(int8_t code);
const __FlashStringHelper *connectErrorString(int8_t code);
// Sends MQTT disconnect packet and calls disconnectServer()
bool disconnect();
// Return true if connected to the MQTT server, otherwise false.
virtual bool connected() = 0; // Subclasses need to fill this in!
virtual bool connected() = 0; // Subclasses need to fill this in!
// Set MQTT last will topic, payload, QOS, and retain. This needs
// to be called before connect() because it is sent as part of the
// connect control packet.
bool will(const char *topic, const char *payload, uint8_t qos = 0, uint8_t retain = 0);
bool will(const char *topic, const char *payload, uint8_t qos = 0,
uint8_t retain = 0);
// Sets the KeepAlive Interval, in seconds.
bool setKeepAliveInterval(uint16_t keepAlive);
// Publish a message to a topic using the specified QoS level. Returns true
// if the message was published, false otherwise.
bool publish(const char *topic, const char *payload, uint8_t qos = 0);
bool publish(const char *topic, uint8_t *payload, uint16_t bLen, uint8_t qos = 0);
bool publish(const char *topic, const char *payload, uint8_t qos = 0, uint8_t retain = 0);
bool publish(const char *topic, uint8_t *payload, uint16_t bLen,
uint8_t qos = 0, uint8_t retain = 0);
// Add a subscription to receive messages for a topic. Returns true if the
// subscription could be added or was already present, false otherwise.
@ -191,37 +203,48 @@ class Adafruit_MQTT {
bool unsubscribe(Adafruit_MQTT_Subscribe *sub);
// Check if any subscriptions have new messages. Will return a reference to
// an Adafruit_MQTT_Subscribe object which has a new message. Should be called
// in the sketch's loop function to ensure new messages are recevied. Note
// that subscribe should be called first for each topic that receives messages!
Adafruit_MQTT_Subscribe *readSubscription(int16_t timeout=0);
// an Adafruit_MQTT_Subscribe object which has a new message. Should be
// called in the sketch's loop function to ensure new messages are recevied.
// Note that subscribe should be called first for each topic that receives
// messages!
Adafruit_MQTT_Subscribe *readSubscription(int16_t timeout = 0);
// Handle any data coming in for subscriptions and fires them off to the
// appropriate callback
Adafruit_MQTT_Subscribe *handleSubscriptionPacket(uint16_t len);
void processPackets(int16_t timeout);
// Ping the server to ensure the connection is still alive.
bool ping(uint8_t n = 1);
protected:
// Count the number of registrered Adafruit_MQTT_Subscribe
uint getSubscriptionCount();
protected:
// Interface that subclasses need to implement:
// Connect to the server and return true if successful, false otherwise.
virtual bool connectServer() = 0;
// Disconnect from the MQTT server. Returns true if disconnected, false otherwise.
virtual bool disconnectServer() = 0; // Subclasses need to fill this in!
// Disconnect from the MQTT server. Returns true if disconnected, false
// otherwise.
virtual bool disconnectServer() = 0; // Subclasses need to fill this in!
// Send data to the server specified by the buffer and length of data.
virtual bool sendPacket(uint8_t *buffer, uint16_t len) = 0;
// Read MQTT packet from the server. Will read up to maxlen bytes and store
// the data in the provided buffer. Waits up to the specified timeout (in
// milliseconds) for data to be available.
virtual uint16_t readPacket(uint8_t *buffer, uint16_t maxlen, int16_t timeout) = 0;
// milliseconds) for data to be available.
virtual uint16_t readPacket(uint8_t *buffer, uint16_t maxlen,
int16_t timeout) = 0;
// Read a full packet, keeping note of the correct length
uint16_t readFullPacket(uint8_t *buffer, uint16_t maxsize, uint16_t timeout);
// Properly process packets until you get to one you want
uint16_t processPacketsUntil(uint8_t *buffer, uint8_t waitforpackettype, uint16_t timeout);
uint16_t processPacketsUntil(uint8_t *buffer, uint8_t waitforpackettype,
uint16_t timeout);
// Shared state that subclasses can use:
const char *servername;
@ -233,46 +256,52 @@ class Adafruit_MQTT {
const char *will_payload;
uint8_t will_qos;
uint8_t will_retain;
uint8_t buffer[MAXBUFFERSIZE]; // one buffer, used for all incoming/outgoing
uint16_t keepAliveInterval; // MQTT KeepAlive time interval, in seconds
uint8_t buffer[MAXBUFFERSIZE]; // one buffer, used for all incoming/outgoing
uint16_t packet_id_counter;
private:
private:
Adafruit_MQTT_Subscribe *subscriptions[MAXSUBSCRIPTIONS];
void flushIncoming(uint16_t timeout);
void flushIncoming(uint16_t timeout);
// Functions to generate MQTT packets.
uint8_t connectPacket(uint8_t *packet);
uint8_t disconnectPacket(uint8_t *packet);
uint16_t publishPacket(uint8_t *packet, const char *topic, uint8_t *payload, uint16_t bLen, uint8_t qos);
uint16_t publishPacket(uint8_t *packet, const char *topic, uint8_t *payload,
uint16_t bLen, uint8_t qos, uint16_t maxPacketLen = 0, uint8_t retain = 0);
uint8_t subscribePacket(uint8_t *packet, const char *topic, uint8_t qos);
uint8_t unsubscribePacket(uint8_t *packet, const char *topic);
uint8_t pingPacket(uint8_t *packet);
uint8_t pubackPacket(uint8_t *packet, uint16_t packetid);
};
class Adafruit_MQTT_Publish {
public:
Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const char *feed, uint8_t qos = 0);
public:
Adafruit_MQTT_Publish(Adafruit_MQTT *mqttserver, const char *feed,
uint8_t qos = 0, uint8_t retain = 0);
bool publish(const char *s);
bool publish(double f, uint8_t precision=2); // Precision controls the minimum number of digits after decimal.
// This might be ignored and a higher precision value sent.
bool publish(
double f,
uint8_t precision =
2); // Precision controls the minimum number of digits after decimal.
// This might be ignored and a higher precision value sent.
bool publish(int32_t i);
bool publish(uint32_t i);
bool publish(uint8_t *b, uint16_t bLen);
private:
Adafruit_MQTT *mqtt;
const char *topic;
uint8_t qos;
uint8_t retain;
};
class Adafruit_MQTT_Subscribe {
public:
Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const char *feedname, uint8_t q=0);
public:
Adafruit_MQTT_Subscribe(Adafruit_MQTT *mqttserver, const char *feedname,
uint8_t q = 0);
void setCallback(SubscribeCallbackUInt32Type callb);
void setCallback(SubscribeCallbackDoubleType callb);
@ -291,13 +320,14 @@ class Adafruit_MQTT_Subscribe {
SubscribeCallbackUInt32Type callback_uint32t;
SubscribeCallbackDoubleType callback_double;
SubscribeCallbackBufferType callback_buffer;
SubscribeCallbackIOType callback_io;
SubscribeCallbackIOType callback_io;
AdafruitIO_MQTT *io_mqtt;
private:
bool new_message;
private:
Adafruit_MQTT *mqtt;
};
#endif

View File

@ -9,8 +9,8 @@
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -21,15 +21,16 @@
// SOFTWARE.
#include "Adafruit_MQTT_Client.h"
bool Adafruit_MQTT_Client::connectServer() {
// Grab server name from flash and copy to buffer for name resolution.
memset(buffer, 0, sizeof(buffer));
strcpy((char *)buffer, servername);
DEBUG_PRINT(F("Connecting to: ")); DEBUG_PRINTLN((char *)buffer);
DEBUG_PRINT(F("Connecting to: "));
DEBUG_PRINTLN((char *)buffer);
// Connect and check for success (0 result).
int r = client->connect((char *)buffer, portnum);
DEBUG_PRINT(F("Connect result: ")); DEBUG_PRINTLN(r);
DEBUG_PRINT(F("Connect result: "));
DEBUG_PRINTLN(r);
return r != 0;
}
@ -49,20 +50,26 @@ bool Adafruit_MQTT_Client::connected() {
uint16_t Adafruit_MQTT_Client::readPacket(uint8_t *buffer, uint16_t maxlen,
int16_t timeout) {
/* Read data until either the connection is closed, or the idle timeout is reached. */
/* Read data until either the connection is closed, or the idle timeout is
* reached. */
uint16_t len = 0;
int16_t t = timeout;
if (maxlen == 0) { // handle zero-length packets
return 0;
}
while (client->connected() && (timeout >= 0)) {
//DEBUG_PRINT('.');
// DEBUG_PRINT('.');
while (client->available()) {
//DEBUG_PRINT('!');
// DEBUG_PRINT('!');
char c = client->read();
timeout = t; // reset the timeout
timeout = t; // reset the timeout
buffer[len] = c;
//DEBUG_PRINTLN((uint8_t)c, HEX);
// DEBUG_PRINTLN((uint8_t)c, HEX);
len++;
if (len == maxlen) { // we read all we want, bail
if (len == maxlen) { // we read all we want, bail
DEBUG_PRINT(F("Read data:\t"));
DEBUG_PRINTBUFFER(buffer, len);
return len;
@ -76,20 +83,22 @@ uint16_t Adafruit_MQTT_Client::readPacket(uint8_t *buffer, uint16_t maxlen,
bool Adafruit_MQTT_Client::sendPacket(uint8_t *buffer, uint16_t len) {
uint16_t ret = 0;
uint16_t offset = 0;
while (len > 0) {
if (client->connected()) {
// send 250 bytes at most at a time, can adjust this later based on Client
uint16_t sendlen = len > 250 ? 250 : len;
//Serial.print("Sending: "); Serial.println(sendlen);
ret = client->write(buffer, sendlen);
DEBUG_PRINT(F("Client sendPacket returned: ")); DEBUG_PRINTLN(ret);
// Serial.print("Sending: "); Serial.println(sendlen);
ret = client->write(buffer + offset, sendlen);
DEBUG_PRINT(F("Client sendPacket returned: "));
DEBUG_PRINTLN(ret);
len -= ret;
offset += ret;
if (ret != sendlen) {
DEBUG_PRINTLN("Failed to send packet.");
return false;
DEBUG_PRINTLN("Failed to send packet.");
return false;
}
} else {
DEBUG_PRINTLN(F("Connection failed!"));

View File

@ -9,8 +9,8 @@
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -22,40 +22,36 @@
#ifndef _ADAFRUIT_MQTT_CLIENT_H_
#define _ADAFRUIT_MQTT_CLIENT_H_
#include "Client.h"
#include "Adafruit_MQTT.h"
#include "Client.h"
// How long to delay waiting for new data to be available in readPacket.
#define MQTT_CLIENT_READINTERVAL_MS 10
// MQTT client implementation for a generic Arduino Client interface. Can work
// with almost all Arduino network hardware like ethernet shield, wifi shield,
// and even other platforms like ESP8266.
class Adafruit_MQTT_Client : public Adafruit_MQTT {
public:
public:
Adafruit_MQTT_Client(Client *client, const char *server, uint16_t port,
const char *cid, const char *user, const char *pass):
Adafruit_MQTT(server, port, cid, user, pass),
client(client)
{}
const char *cid, const char *user, const char *pass)
: Adafruit_MQTT(server, port, cid, user, pass), client(client) {}
Adafruit_MQTT_Client(Client *client, const char *server, uint16_t port,
const char *user="", const char *pass=""):
Adafruit_MQTT(server, port, user, pass),
client(client)
{}
const char *user = "", const char *pass = "")
: Adafruit_MQTT(server, port, user, pass), client(client) {}
bool connectServer();
bool disconnectServer();
bool connected();
uint16_t readPacket(uint8_t *buffer, uint16_t maxlen, int16_t timeout);
bool sendPacket(uint8_t *buffer, uint16_t len);
bool connected() override;
private:
Client* client;
protected:
bool connectServer() override;
bool disconnectServer() override;
uint16_t readPacket(uint8_t *buffer, uint16_t maxlen,
int16_t timeout) override;
bool sendPacket(uint8_t *buffer, uint16_t len) override;
private:
Client *client;
};
#endif

View File

@ -9,8 +9,8 @@
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
@ -22,32 +22,33 @@
#ifndef _ADAFRUIT_MQTT_FONA_H_
#define _ADAFRUIT_MQTT_FONA_H_
#include <Adafruit_FONA.h>
#include "Adafruit_MQTT.h"
#include <Adafruit_FONA.h>
#define MQTT_FONA_INTERAVAILDELAY 100
#define MQTT_FONA_QUERYDELAY 500
// FONA-specific version of the Adafruit_MQTT class.
// Note that this is defined as a header-only class to prevent issues with using
// the library on non-FONA platforms (since Arduino will include all .cpp files
// in the compilation of the library).
class Adafruit_MQTT_FONA : public Adafruit_MQTT {
public:
public:
Adafruit_MQTT_FONA(Adafruit_FONA *f, const char *server, uint16_t port,
const char *cid, const char *user, const char *pass):
Adafruit_MQTT(server, port, cid, user, pass),
fona(f)
{}
const char *cid, const char *user, const char *pass)
: Adafruit_MQTT(server, port, cid, user, pass), fona(f) {}
Adafruit_MQTT_FONA(Adafruit_FONA *f, const char *server, uint16_t port,
const char *user="", const char *pass=""):
Adafruit_MQTT(server, port, user, pass),
fona(f)
{}
const char *user = "", const char *pass = "")
: Adafruit_MQTT(server, port, user, pass), fona(f) {}
bool connectServer() {
bool connected() {
// Return true if connected, false if not connected.
return fona->TCPconnected();
}
protected:
bool connectServer() override {
char server[40];
strncpy(server, servername, 40);
#ifdef ADAFRUIT_SLEEPYDOG_H
@ -59,69 +60,67 @@ class Adafruit_MQTT_FONA : public Adafruit_MQTT {
return fona->TCPconnect(server, portnum);
}
bool disconnectServer() {
return fona->TCPclose();
}
bool disconnectServer() override { return fona->TCPclose(); }
bool connected() {
// Return true if connected, false if not connected.
return fona->TCPconnected();
}
uint16_t readPacket(uint8_t *buffer, uint16_t maxlen, int16_t timeout) {
uint16_t readPacket(uint8_t *buffer, uint16_t maxlen,
int16_t timeout) override {
uint8_t *buffp = buffer;
DEBUG_PRINTLN(F("Reading data.."));
if (!fona->TCPconnected()) return 0;
if (!fona->TCPconnected())
return 0;
/* Read data until either the connection is closed, or the idle timeout is reached. */
/* Read data until either the connection is closed, or the idle timeout is
* reached. */
uint16_t len = 0;
int16_t t = timeout;
uint16_t avail;
while (fona->TCPconnected() && (timeout >= 0)) {
//DEBUG_PRINT('.');
// DEBUG_PRINT('.');
while (avail = fona->TCPavailable()) {
//DEBUG_PRINT('!');
// DEBUG_PRINT('!');
if (len + avail > maxlen) {
avail = maxlen - len;
if (avail == 0) return len;
avail = maxlen - len;
if (avail == 0)
return len;
}
// try to read the data into the end of the pointer
if (! fona->TCPread(buffp, avail)) return len;
if (!fona->TCPread(buffp, avail))
return len;
// read it! advance pointer
buffp += avail;
len += avail;
timeout = t; // reset the timeout
timeout = t; // reset the timeout
//DEBUG_PRINTLN((uint8_t)c, HEX);
// DEBUG_PRINTLN((uint8_t)c, HEX);
if (len == maxlen) { // we read all we want, bail
if (len == maxlen) { // we read all we want, bail
DEBUG_PRINT(F("Read:\t"));
DEBUG_PRINTBUFFER(buffer, len);
return len;
return len;
}
}
#ifdef ADAFRUIT_SLEEPYDOG_H
Watchdog.reset();
#endif
timeout -= MQTT_FONA_INTERAVAILDELAY;
timeout -= MQTT_FONA_QUERYDELAY; // this is how long it takes to query the FONA for avail()
timeout -= MQTT_FONA_QUERYDELAY; // this is how long it takes to query the
// FONA for avail()
delay(MQTT_FONA_INTERAVAILDELAY);
}
return len;
}
bool sendPacket(uint8_t *buffer, uint16_t len) {
bool sendPacket(uint8_t *buffer, uint16_t len) override {
DEBUG_PRINTLN(F("Writing packet"));
if (fona->TCPconnected()) {
boolean ret = fona->TCPsend((char *)buffer, len);
//DEBUG_PRINT(F("sendPacket returned: ")); DEBUG_PRINTLN(ret);
// DEBUG_PRINT(F("sendPacket returned: ")); DEBUG_PRINTLN(ret);
if (!ret) {
DEBUG_PRINTLN("Failed to send packet.");
return false;
@ -133,10 +132,9 @@ class Adafruit_MQTT_FONA : public Adafruit_MQTT {
return true;
}
private:
private:
uint32_t serverip;
Adafruit_FONA *fona;
};
#endif

View File

@ -1,4 +1,4 @@
# Adafruit MQTT Library [![Build Status](https://travis-ci.org/adafruit/Adafruit_MQTT_Library.svg?branch=master)](https://travis-ci.org/adafruit/Adafruit_MQTT_Library)
# Adafruit MQTT Library [![Build Status](https://github.com/adafruit/Adafruit_MQTT_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_MQTT_Library/actions)
Arduino library for MQTT support, including access to Adafruit IO. Works with
the Adafruit FONA, Arduino Yun, ESP8266 Arduino platforms, and anything that supports
@ -36,9 +36,10 @@ ESP8266 | | | X |
Atmega2560 @ 16MHz | | | X |
ATSAM3X8E | | | X |
ATSAM21D | | | X |
ATSAMD51J20 | | | X |
ATtiny85 @ 16MHz | | | X |
ATtiny85 @ 8MHz | | | X |
Intel Curie @ 32MHz | | | X |
Intel Curie @ 32MHz | | | X |
STM32F2 | | | X |
* ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
@ -49,6 +50,7 @@ STM32F2 | | | X |
* ATmega2560 @ 16MHz : Arduino Mega
* ATSAM3X8E : Arduino Due
* ATSAM21D : Arduino Zero, M0 Pro
* ATSAMD51J20: Adafruit PyPortal
* ATtiny85 @ 16MHz : Adafruit Trinket 5V
* ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,183 @@
/****************************************************************
Adafruit MQTT Library, Adafruit IO SSL/TLS Example for AirLift
Must use the latest version of nina-fw from:
https://github.com/adafruit/nina-fw
Works great with Adafruit AirLift ESP32 Co-Processors!
--> https://www.adafruit.com/product/4201
--> https://www.adafruit.com/product/4116
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Brent Rubell for Adafruit Industries.
MIT license, all text above must be included in any redistribution
*******************************************************************/
#include <WiFiNINA.h>
#include <SPI.h>
// For AirLift Breakout/Wing/Shield: Configure the following to match the ESP32 Pins!
#if !defined(SPIWIFI_SS)
// Don't change the names of these #define's! they match the variant ones
#define SPIWIFI SPI
#define SPIWIFI_SS 11 // Chip select pin
#define SPIWIFI_ACK 10 // a.k.a BUSY or READY pin
#define ESP32_RESETN 9 // Reset pin
#define ESP32_GPIO0 -1 // Not connected
#define SET_PINS 1 // Pins were set using this IFNDEF
#endif
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "WLAN_SSID"
#define WLAN_PASS "WIFI_PASSWORD"
int keyIndex = 0; // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883
// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
/************ Global State (you don't need to change this!) ******************/
// WiFiSSLClient for SSL/TLS support
WiFiSSLClient client;
// Setup the MQTT client class by WLAN_PASSing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
/****************************** Feeds ***************************************/
// Setup a feed called 'test' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish test = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/test");
/*************************** Sketch Code ************************************/
void setup()
{
//Initialize serial and wait for port to open:
Serial.begin(115200);
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}
// if the AirLift's pins were defined above...
#ifdef SET_PINS
WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &SPIWIFI);
#endif
// check for the wifi module
while (WiFi.status() == WL_NO_MODULE)
{
Serial.println("Communication with WiFi module failed!");
delay(1000);
}
String fv = WiFi.firmwareVersion();
if (fv < "1.0.0")
{
Serial.println("Please upgrade the firmware");
}
// attempt to connect to Wifi network:
Serial.print("Attempting to connect to SSID: ");
Serial.println(WLAN_SSID);
// Connect to WPA/WPA2 network. Change this line if using open or WEP network:
do
{
status = WiFi.begin(WLAN_SSID, WLAN_PASS);
delay(100); // wait until connected
} while (status != WL_CONNECTED);
Serial.println("Connected to wifi");
printWiFiStatus();
}
uint32_t x = 0;
void loop()
{
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
// Now we can publish stuff!
Serial.print(F("\nSending val "));
Serial.print(x);
Serial.print(F(" to test feed..."));
if (!test.publish(x++))
{
Serial.println(F("Failed"));
}
else
{
Serial.println(F("OK!"));
}
// wait a couple seconds to avoid rate limit
delay(2000);
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect()
{
int8_t ret;
// Stop if already connected.
if (mqtt.connected())
{
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0)
{ // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0)
{
// basically die and wait for WDT to reset me
while (1)
;
}
}
Serial.println("MQTT Connected!");
}
void printWiFiStatus()
{
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());
// print your board's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);
// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,160 @@
/***********************************************************************
Adafruit MQTT Library ESP32 Adafruit IO SSL/TLS example
Use the latest version of the ESP32 Arduino Core:
https://github.com/espressif/arduino-esp32
Works great with Adafruit Huzzah32 Feather and Breakout Board:
https://www.adafruit.com/product/3405
https://www.adafruit.com/products/4172
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Tony DiCola for Adafruit Industries.
Modified by Brent Rubell for Adafruit Industries
MIT license, all text above must be included in any redistribution
**********************************************************************/
#include <WiFi.h>
#include "WiFiClientSecure.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "WLAN_SSID"
#define WLAN_PASS "WIFI_PASSWORD"
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883
// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
/************ Global State (you don't need to change this!) ******************/
// WiFiFlientSecure for SSL/TLS support
WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// io.adafruit.com root CA
const char* adafruitio_root_ca = \
"-----BEGIN CERTIFICATE-----\n" \
"MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh\n" \
"MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" \
"d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD\n" \
"QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT\n" \
"MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n" \
"b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG\n" \
"9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB\n" \
"CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97\n" \
"nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt\n" \
"43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P\n" \
"T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4\n" \
"gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO\n" \
"BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR\n" \
"TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw\n" \
"DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr\n" \
"hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg\n" \
"06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF\n" \
"PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls\n" \
"YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk\n" \
"CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=\n" \
"-----END CERTIFICATE-----\n";
/****************************** Feeds ***************************************/
// Setup a feed called 'test' for publishing.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Publish test = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/test");
/*************************** Sketch Code ************************************/
void setup() {
Serial.begin(115200);
delay(10);
Serial.println(F("Adafruit IO MQTTS (SSL/TLS) Example"));
// Connect to WiFi access point.
Serial.println(); Serial.println();
Serial.print("Connecting to ");
Serial.println(WLAN_SSID);
delay(1000);
WiFi.begin(WLAN_SSID, WLAN_PASS);
delay(2000);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi connected");
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// Set Adafruit IO's root CA
client.setCACert(adafruitio_root_ca);
}
uint32_t x=0;
void loop() {
// Ensure the connection to the MQTT server is alive (this will make the first
// connection and automatically reconnect when disconnected). See the MQTT_connect
// function definition further below.
MQTT_connect();
// Now we can publish stuff!
Serial.print(F("\nSending val "));
Serial.print(x);
Serial.print(F(" to test feed..."));
if (! test.publish(x++)) {
Serial.println(F("Failed"));
} else {
Serial.println(F("OK!"));
}
// wait a couple seconds to avoid rate limit
delay(2000);
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
int8_t ret;
// Stop if already connected.
if (mqtt.connected()) {
return;
}
Serial.print("Connecting to MQTT... ");
uint8_t retries = 3;
while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
Serial.println(mqtt.connectErrorString(ret));
Serial.println("Retrying MQTT connection in 5 seconds...");
mqtt.disconnect();
delay(5000); // wait 5 seconds
retries--;
if (retries == 0) {
// basically die and wait for WDT to reset me
while (1);
}
}
Serial.println("MQTT Connected!");
}

View File

@ -0,0 +1 @@

View File

@ -22,15 +22,18 @@
/************************* WiFi Access Point *********************************/
#define WLAN_SSID "...your SSID..."
#define WLAN_PASS "...your password..."
#define WLAN_SSID "WLAN_SSID"
#define WLAN_PASS "WIFI_PASSWORD"
/************************* Adafruit.io Setup *********************************/
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT 8883 // 8883 for MQTTS
#define AIO_USERNAME "...your AIO username (see https://accounts.adafruit.com)..."
#define AIO_KEY "...your AIO key..."
// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883
// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
#define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
#define AIO_KEY "YOUR_ADAFRUIT_IO_KEY"
/************ Global State (you don't need to change this!) ******************/
@ -40,9 +43,13 @@ WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);
// io.adafruit.com SHA1 fingerprint. Current fingerprint can be verified via:
// echo | openssl s_client -connect io.adafruit.com:443 |& openssl x509 -fingerprint -noout
#define AIO_SSL_FINGERPRINT "77 00 54 2D DA E7 D8 03 27 31 23 99 EB 27 DB CB A5 4C 57 18"
// io.adafruit.com SHA1 fingerprint
/* WARNING - This value was last updated on 08/15/22 and may not be up-to-date!
* If security is a concern for your project, we strongly recommend users impacted by this moving
* to ESP32 which has certificate verification by storing root certs and having a
* chain-of-trust rather than doing individual certificate fingerprints.
*/
static const char *fingerprint PROGMEM = "18 C0 C2 3D BE DD 81 37 73 40 E7 E4 36 61 CB 0A DF 96 AD 25";
/****************************** Feeds ***************************************/
@ -52,11 +59,6 @@ Adafruit_MQTT_Publish test = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/t
/*************************** Sketch Code ************************************/
// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();
void verifyFingerprint();
void setup() {
Serial.begin(115200);
delay(10);
@ -83,8 +85,7 @@ void setup() {
Serial.println("IP address: "); Serial.println(WiFi.localIP());
// check the fingerprint of io.adafruit.com's SSL cert
verifyFingerprint();
client.setFingerprint(fingerprint);
}
uint32_t x=0;
@ -110,28 +111,6 @@ void loop() {
}
void verifyFingerprint() {
const char* host = AIO_SERVER;
Serial.print("Connecting to ");
Serial.println(host);
if (! client.connect(host, AIO_SERVERPORT)) {
Serial.println("Connection failed. Halting execution.");
while(1);
}
if (client.verify(fingerprint, host)) {
Serial.println("Connection secure.");
} else {
Serial.println("Connection insecure! Halting execution.");
while(1);
}
}
// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -35,7 +35,7 @@
// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
// or... use WiFiClientSecure for SSL
//WiFiClientSecure client;
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -1,20 +1,27 @@
#include "Adafruit_FONA.h"
#include <Adafruit_SleepyDog.h>
#include <SoftwareSerial.h>
#include "Adafruit_FONA.h"
#define halt(s) { Serial.println(F( s )); while(1); }
#define halt(s) \
{ \
Serial.println(F(s)); \
while (1) \
; \
}
extern Adafruit_FONA fona;
extern SoftwareSerial fonaSS;
boolean FONAconnect(const __FlashStringHelper *apn, const __FlashStringHelper *username, const __FlashStringHelper *password) {
boolean FONAconnect(const __FlashStringHelper *apn,
const __FlashStringHelper *username,
const __FlashStringHelper *password) {
Watchdog.reset();
Serial.println(F("Initializing FONA....(May take 3 seconds)"));
fonaSS.begin(4800); // if you're using software serial
if (! fona.begin(fonaSS)) { // can also try fona.begin(Serial1)
if (!fona.begin(fonaSS)) { // can also try fona.begin(Serial1)
Serial.println(F("Couldn't find FONA"));
return false;
}
@ -23,25 +30,25 @@ boolean FONAconnect(const __FlashStringHelper *apn, const __FlashStringHelper *u
Watchdog.reset();
Serial.println(F("Checking for network..."));
while (fona.getNetworkStatus() != 1) {
delay(500);
delay(500);
}
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
fona.setGPRSNetworkSettings(apn, username, password);
Serial.println(F("Disabling GPRS"));
fona.enableGPRS(false);
Watchdog.reset();
delay(5000); // wait a few seconds to stabilize connection
delay(5000); // wait a few seconds to stabilize connection
Watchdog.reset();
Serial.println(F("Enabling GPRS"));
if (!fona.enableGPRS(true)) {
Serial.println(F("Failed to turn GPRS on"));
Serial.println(F("Failed to turn GPRS on"));
return false;
}
Watchdog.reset();

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -0,0 +1 @@

View File

@ -1,5 +1,4 @@
Adafruit_MQTT KEYWORD1
Adafruit_MQTT_CC3000 KEYWORD1
Adafruit_MQTT_FONA KEYWORD1
Adafruit_MQTT_Client KEYWORD1
Adafruit_MQTT_Publish KEYWORD1

View File

@ -1,9 +1,10 @@
name=Adafruit MQTT Library
version=0.20.1
version=2.4.3
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=MQTT library that supports the FONA, ESP8266, Yun, and generic Arduino Client hardware.
sentence=MQTT library that supports the FONA, ESP8266, ESP32, Yun, and generic Arduino Client hardware.
paragraph=Simple MQTT library that supports the bare minimum to publish and subscribe to topics.
category=Communication
url=https://github.com/adafruit/Adafruit_MQTT_Library
architectures=*
depends=Adafruit SleepyDog Library, Adafruit FONA Library, WiFi101