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:

standard mqtt flow

Adafruit IO’s message flow is a bit more complicated, and looks something like this:

adafruit io mqtt flow

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 the adafruitio_errors_esp8266 example to get started.

Are these examples helpful? Please visit our IO forum and share your thoughts.