Just two more topics to make you an expert!
Quality of Service
MQTT has some basic Quality of Service 'QoS' capability built in. Basically, say you were using MQTT over a radio, and your toaster is sending radio signals to some base station...there's a chance those messages won't arrive. Heck, even with WiFi or Ethernet, there's a chance your message doesnt actually get to the MQTT broker.
Sending messages without knowing for sure they were received is called "QoS 0" (zero).
You may also want QoS 1, which lets you know the message was received. Basically, after each publication, the subscriber says "OK". In MQTT-speak this is called the "PUBACK" (Publication Acknowledgement)
Turning it on is easy, in the Adafruit_MQTT_Publish creation, put MQTT_QOS_1 and that feed will be QoS 1. By default, feeds are created with MQTT_QOS_0 and you don't need to specify QoS0
Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, PHOTOCELL_FEED, MQTT_QOS_1);
Whenever you call photocell.publish() it will return false if the publication was not PUBACK'd
There's also QoS 2, which not only guarantees your message was received but that it was only received once. This is a bit more complex because you need to start tracking packet IDs so we'll leave that for a later time.
Last Will & Testament
OK this is a bit morbid but, you know already that when people pass away they may have a "final wish" for how their money or posessions are distributed. That final wish is called their Will. Likewise MQTT connections also have the ability to have a Will.
The Will is essentially "If the MQTT feed is disconnected, the broker shall create one last publication on my behalf". This is very handy when you want to notify that the MQTT client is offline.
Here's an example, we omitted the first half of the sketch where the WiFi settings and Adafruit config is done.
/****************************** Feeds ***************************************/ // Setup a feed called 'photocell' for publishing. // Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname> const char PHOTOCELL_FEED[] PROGMEM = AIO_USERNAME "/feeds/photocell"; Adafruit_MQTT_Publish photocell = Adafruit_MQTT_Publish(&mqtt, PHOTOCELL_FEED, MQTT_QOS_1); // Define a will const char WILL_FEED[] PROGMEM = AIO_USERNAME "/feeds/onoff"; Adafruit_MQTT_Publish lastwill = Adafruit_MQTT_Publish(&mqtt, WILL_FEED, MQTT_QOS_1); /*************************** 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 setup() { Serial.begin(115200); delay(10); Serial.println(F("Adafruit MQTT with Will demo")); // Connect to WiFi access point. Serial.println(); Serial.println(); Serial.print("Connecting to "); Serial.println(WLAN_SSID); WiFi.begin(WLAN_SSID, WLAN_PASS); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); // Setup MQTT will to set on/off to "OFF" when we disconnect mqtt.will(WILL_FEED, "OFF"); } 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(); lastwill.publish("ON"); // make sure we publish ON first thing after connecting // Now we can publish stuff! Serial.print(F("\nSending photocell val ")); Serial.print(x); Serial.print("..."); if (! photocell.publish(x++)) { Serial.println(F("Failed")); } else { Serial.println(F("OK!")); } delay(5000); } // 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!"); }
We create a Will feed (we'll recycle the ONOFF button feed
// Define a will const char WILL_FEED[] PROGMEM = AIO_USERNAME "/feeds/onoff"; Adafruit_MQTT_Publish lastwill = Adafruit_MQTT_Publish(&mqtt, WILL_FEED, MQTT_QOS_1);
and in the setup, configure the Will and the message you want reported
// Setup MQTT will to set on/off to "OFF" when we disconnect mqtt.will(WILL_FEED, "OFF");
Then in every loop, right after we check connection, write ON to the feed
lastwill.publish("ON"); // make sure we publish ON first thing after connecting
Then, you can test this out and unplug the client board from power. After MQTT_CONN_KEEPALIVE seconds, the onoff slider button will automatically slide to OFF
Don't forget to adjust
// Adjust as necessary, in seconds. Default to 5 minutes. #define MQTT_CONN_KEEPALIVE 300
If you want a different timeout!
Page last edited January 10, 2016
Text editor powered by tinymce.