-
Running Code at Intervals Using Adafruit IO
We introduced time utilities to Adafruit IO about a month ago, but we haven’t provided any examples of how to use the feature. To correct this oversight, we added an example to
v0.14.2
of the Adafruit MQTT Arduino Library. This example was a response to a feature request from @phlemoine in the io-issues GitHub repo:I am looking for a way to trigger at a specific time in the day… how can I set up the time the trigger starts ? Same for a 12 hours or even 4 hours …
Here is the relevant code that allows code to be run at 4 hour intervals (midnight, 4am, 8am, etc):
Adafruit_MQTT_Subscribe timefeed = Adafruit_MQTT_Subscribe(&mqtt, "time/seconds"); // set timezone offset from UTC int timeZone = -4; // UTC - 4 eastern daylight time (nyc) int interval = 4; // trigger every X hours int hour = 0; // current hour void timecallback(uint32_t current) { // stash previous hour int previous = hour; // adjust to local time zone current += (timeZone * 60 * 60); // calculate current hour hour = (current / 60 / 60) % 24; // only trigger on interval if((hour != previous) && (hour % interval) == 0) { Serial.println("Run your code here"); } }
The full example can be found in the Adafruit_MQTT Arduino Library on GitHub. You will need to install or update the Adafruit MQTT Library to version
0.14.2
in the Arduino Library Manager, and open theadafruitio_time_esp8266
example to get started.Are these examples helpful? Please visit our IO forum and share your thoughts.
-
Callbacks Added to the Adafruit MQTT Library for Arduino
v0.14.1
of the Adafruit MQTT Library for Arduino introduces subscription callbacks. This change will allow users to organize their code into separate blocks by attaching callbacks to feed and group subscriptions. Here’s a simplified example of what the change looks like:setup() { // add the rest of setup code here // register callback for feed onoffbutton.setCallback(onoffcallback); } 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 in the full example for more info. MQTT_connect(); // wait 10 seconds for subscription messages // since we have no other tasks in this example. mqtt.processPackets(10000); // keep the connection alive mqtt.ping(); } void onoffcallback(char *data, uint16_t len) { Serial.print("Hey we're in a onoff callback, the button value is: "); Serial.println(data); }
In the example above, you can see that we added the call to
mqtt.processPackets(10000);
. This tells the library to wait 10 seconds (10000ms) for incoming packets before moving on to the next task, and it will block all other code execution. If your sketch is only waiting for subscription messages, then 10 seconds might be a good timeout, but if your sketch handles other tasks, you may want to reduce the timeout to 1 second (1000ms).The full example with multiple feed subscriptions can be found in the Adafruit_MQTT Arduino Library on GitHub. You will need to install or update the Adafruit MQTT Library to version
0.14.1
in the Arduino Library Manager, and open themqtt_esp8266_callback
example to get started.Are these examples helpful? Please visit our IO forum and share your thoughts.
-
MQTT Error Reporting
Unlike HTTP, the MQTT protocol does not provide a standard way of reporting errors to connected clients. This poses a problem for Adafruit IO, because there are multiple reasons why sending data to Adafruit IO might fail.
Here are a few common examples:
- Publishing data to an invalid topic
- Publishing data to an unauthorized topic
- Publishing data too fast (rate limit)
- Exceeding the number of feeds for your account (10 currently)
- Sending too large of a payload
Adafruit IO is not a standard MQTT broker. Normally MQTT brokers will rebroadcast published data to any authorized subscribed client as soon as the data is received, so errors are rarely encountered.
The standard MQTT pub/sub workflow looks something like this:
Adafruit IO’s message flow is a bit more complicated, and looks something like this:
In the simplified example above, you can see that there are multiple steps that need to be completed before data is rebroadcasted to subscribed clients. If any of these steps fail, data will not make it back to subscribed clients. The reasons for failure are often unclear to users, so we added two special MQTT topics that will help inform users of any issues related to publishing data.
The first topic you can subscribe to is the error topic for your user. This topic will receive any errors related to data validation and database saves. The topic path looks like this:
{username}/errors
For example, if your username was
ladyada
, you would subscribe to the following topic using your favorite MQTT client:ladyada/errors
The second topic you can subscribe to is the throttle topic for your user. This topic contains any messages related to rate limits on your account. You might see these if you are publishing too fast. The topic path looks like this:
{username}/throttle
Again, if your username was
ladyada
, you would subscribe to the following topic:ladyada/throttle
If you are using the Adafruit MQTT Library, you can define the throttle and error subscriptions at the top of your sketch like this:
/*************************** Error Reporting *********************************/ const char ERRORS[] PROGMEM = AIO_USERNAME "/errors"; Adafruit_MQTT_Subscribe errors = Adafruit_MQTT_Subscribe(&mqtt, ERRORS); const char THROTTLE[] PROGMEM = AIO_USERNAME "/throttle"; Adafruit_MQTT_Subscribe throttle = Adafruit_MQTT_Subscribe(&mqtt, THROTTLE);
Then, subscribe to the topics at the bottom of the
setup
function:void setup() { // ...network connection setup code here // MQTT subscriptions for throttle & error messages mqtt.subscribe(&throttle); mqtt.subscribe(&errors); }
Finally, inside of the main
loop
, print any errors to the serial monitor: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(); // this is our 'wait for incoming subscription packets' busy subloop // try to spend your time here Adafruit_MQTT_Subscribe *subscription; while ((subscription = mqtt.readSubscription(5000))) { if(subscription == &errors) { Serial.print(F("ERROR: ")); Serial.println((char *)errors.lastread); } else if(subscription == &throttle) { Serial.print(F("THROTTLED: ")); Serial.println((char *)throttle.lastread); } } mqtt.ping(); }
You can see the full example for the ESP8266 in the Adafruit_MQTT Arduino Library on GitHub. Install or update the Adafruit MQTT Library to version
0.13.3
in the Arduino Library Manager, and open theadafruitio_errors_esp8266
example to get started.Are these examples helpful? Please visit our IO forum and share your thoughts.
-
IoT Security: Connecting Your ESP8266 to Adafruit IO with SSL/TLS
The ESP8266 based Adafruit HUZZAH breakout and the Adafruit Feather HUZZAH are both popular options to use with Adafruit IO. Because ESP8266 SSL/TLS support is fairly new, most of our Adafruit IO examples use the insecure MQTT port 1883.
Why is this a problem? The MQTT protocol is an insecure protocol on it’s own. All data (including username & password) are sent in the clear, so SSL/TLS is required to protect any sensitive information.
What are SSL & TLS? Transport Layer Security (TLS) and its predecessor, Secure Sockets Layer (SSL), are cryptographic protocols that you use whenever you browse the internet. Have you ever noticed the lock symbol 🔒 in your browser’s URL bar? That lock symbol represents a secure connection between your browser & a web site over SSL/TLS. We use those same protocols to secure traffic between your ESP8266 and Adafruit IO.
We have added an example to the Adafruit_MQTT Arduino Library that you can use to secure communication between your ESP8266 and Adafruit IO. Install or update the Adafruit MQTT Library to version
0.13.2
in the Arduino Library Manager, and open theadafruitio_secure_esp8266
example to get started.The main changes to the standard ESP8266 example are that
WiFiClientSecure
is used in place ofWiFiClient
, and port8883
is used instead of MQTT port1883
. The sketch also checks the fingerprint for theio.adafruit.com
certificate using theverifyFingerprint
function.A simplified summary of the changes can be seen below:
#define AIO_SERVER "io.adafruit.com" #define AIO_SERVERPORT 8883 // 8883 for MQTTS // WiFiFlientSecure for SSL/TLS support WiFiClientSecure client; // io.adafruit.com SHA1 fingerprint const char* fingerprint = "26 96 1C 2A 51 07 FD 15 80 96 93 AE F7 32 CE B9 0D 01 55 C4"; 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); } }
-
From the Forums: Two Buttons & Two LEDs
User
smcculley
posted a useful example in the IO Forum:I have had some requests from people to share my code to talk to Adafruit IO using MQTT and being able to trigger two LED’s.
Note that I am using the latest AdafruitIO MQTT code from GitHub, as it has the latest fixes available: https://github.com/adafruit/Adafruit_MQTT_Library
In Adafruit IO, I created two feeds, called ledone and ledtwo, and added them to a group called leds. I then created a dashboard with two toggle switches, and tied them to the feeds (one to each, obviously) using the default ON and OFF button text.
Check out the post for more details. Thanks for sharing!