The Adafruit WICED Feather API includes an internal MQTT client that allows you perform basic MQTT operations directly with any MQTT broker.
AdafruitMQTT inherits from AdafruitTCP and also has access to all of the functions defined in the parent class.
Note: You are also free to use an external Client based MQTT library (for example Adafruit_MQTT_Library) if you prefer or need something fully under your control. AdafruitMQTT is provided for convenience sake, and to avoid external dependencies, but isn't the only option at your disposal.
Constructors
Some MQTT brokers require a username and password to connect. If necessary, the two values should be provided in the constructor when declaring an instance of AdafruitMQTT.
If no username and password are required, simply use the default empty constructor.
AdafruitMQTT() AdafruitMQTT(const char* username, const char* password)
bool connected ( void ); bool connect ( IPAddress ip, uint16_t port = 1883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT); bool connect ( const char* host, uint16_t port = 1883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT); bool connectSSL ( IPAddress ip, uint16_t port = 8883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT); bool connectSSL ( const char* host, uint16_t port = 8883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT); bool disconnect ( void ); bool publish ( UTF8String topic, UTF8String message, uint8_t qos = MQTT_QOS_AT_MOST_ONCE, bool retained = false ); bool subscribe ( const char* topicFilter, uint8_t qos, messageHandler mh); bool unsubscribe( const char* topicFilter ); void will ( const char* topic, UTF8String message, uint8_t qos = MQTT_QOS_AT_MOST_ONCE, uint8_t retained = 0); void clientID ( const char* client) void setDisconnectCallback ( void (*fp) (void) )
Connection Management
AdafruitMQTT can connect to an MQTT broker using both 'open' (unencrypted) or 'secure' (TLS/SSL encrypted) connections.
bool connected(void)
Indicates if we are currently connected to the MQTT broker or not.
Parameters: None
Returns: 'True' (1) if we are connected to the MQTT broker, otherwise 'false' (0).
bool connect ( IPAddress ip, uint16_t port = 1883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT);
Establishes an open connection with the specified MQTT broker.
Parameters:
- ip: The IP address for the MQTT broker
- port: The port to use (default = 1883)
- cleanSession: Indicates whether the client and broker should remember 'state' across restarts and reconnects (based on the 'Client ID' value set in the constructor):
- If set to false (0) both the client and server will maintain state across restarts of the client, the server and the connection. As state is maintained:
- Message delivery will be reliable meeting the specified QOS even if the client, server or connection are restarted.
- The server will treat a subscription as durable.
- If set to true (1) the client and server will not maintain state across restarts of the client, the server or the connection. This means:
- Message delivery to the specified QOS cannot be maintained if the client, server or connection are restarted
- The server will treat a subscription as non-durable
- keepalive_sec: This value defines the maximum interval (in seconds) between messages being sent or received. Setting a value here ensures that at least one message is sent between the client and the broker within every 'keep alive' period. If no data was sent within 'keepalive_sec' seconds, the Client will send a simple ping to the broker to keep the connection alive. Setting this value to '0' disables the keep alive feature. The default value is 60 seconds.
Returns: 'True' (1) if the connection was successful, otherwise 'false' (0).
bool connect ( const char* host, uint16_t port = 1883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT);
Establishes an open connection with the specified MQTT broker.
Parameters:
- host: The domain name for the MQTT broker
- port: The port to use (default = 1883)
-
cleanSession: Indicates whether the client and broker should remember 'state' across restarts and reconnects (based on the 'Client ID' value set in the constructor):
- If set to false (0) both the client and server will maintain state across restarts of the client, the server and the connection. As state is maintained:
- Message delivery will be reliable meeting the specified QOS even if the client, server or connection are restarted.
- The server will treat a subscription as durable.
- If set to true (1) the client and server will not maintain state across restarts of the client, the server or the connection. This means:
- Message delivery to the specified QOS cannot be maintained if the client, server or connection are restarted
- The server will treat a subscription as non-durable
- keepalive_sec: This value defines the maximum interval (in seconds) between messages being sent or received. Setting a value here ensures that at least one message is sent between the client and the broker within every 'keep alive' period. If no data was sent within 'keepalive_sec' seconds, the Client will send a simple ping to the broker to keep the connection alive. Setting this value to '0' disables the keep alive feature. The default value is 60 seconds.
Returns: 'True' (1) if the connection was successful, otherwise 'false' (0).
bool connectSSL ( IPAddress ip, uint16_t port = 8883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT)
Establishes a secure connection with the specified MQTT broker.
Parameters:
- ip: The IP address of the MQTT broker
- port: The port to use (default = 8883)
-
cleanSession: Indicates whether the client and broker should remember 'state' across restarts and reconnects (based on the 'Client ID' value set in the constructor):
- If set to false (0) both the client and server will maintain state across restarts of the client, the server and the connection. As state is maintained:
- Message delivery will be reliable meeting the specified QOS even if the client, server or connection are restarted.
- The server will treat a subscription as durable.
- If set to true (1) the client and server will not maintain state across restarts of the client, the server or the connection. This means:
- Message delivery to the specified QOS cannot be maintained if the client, server or connection are restarted
- The server will treat a subscription as non-durable
- keepalive_sec: This value defines the maximum interval (in seconds) between messages being sent or received. Setting a value here ensures that at least one message is sent between the client and the broker within every 'keep alive' period. If no data was sent within 'keepalive_sec' seconds, the Client will send a simple ping to the broker to keep the connection alive. Setting this value to '0' disables the keep alive feature. The default value is 60 seconds.
Returns: 'True' (1) if the connection was successful, otherwise 'false' (0).
bool connectSSL ( const char* host, uint16_t port = 8883, bool cleanSession = true, uint16_t keepalive_sec = MQTT_KEEPALIVE_DEFAULT)
Establishes a secure connection with the specified MQTT broker.
Parameters:
- host: The domain name of the MQTT broker
- port: The port to use (default = 8883)
-
cleanSession: Indicates whether the client and broker should remember 'state' across restarts and reconnects (based on the 'Client ID' value set in the constructor):
- If set to false (0) both the client and server will maintain state across restarts of the client, the server and the connection. As state is maintained:
- Message delivery will be reliable meeting the specified QOS even if the client, server or connection are restarted.
- The server will treat a subscription as durable.
- If set to true (1) the client and server will not maintain state across restarts of the client, the server or the connection. This means:
- Message delivery to the specified QOS cannot be maintained if the client, server or connection are restarted
- The server will treat a subscription as non-durable
- keepalive_sec: This value defines the maximum interval (in seconds) between messages being sent or received. Setting a value here ensures that at least one message is sent between the client and the broker within every 'keep alive' period. If no data was sent within 'keepalive_sec' seconds, the Client will send a simple ping to the broker to keep the connection alive. Setting this value to '0' disables the keep alive feature. The default value is 60 seconds.
Returns: 'True' (1) if the connection was successful, otherwise 'false' (0).
bool disconnect (void)
Disconnects from the remote MQTT broker.
Parameters: None
Returns: 'True' (1) if the disconnect was successful, otherwise 'false' (0) if an error occured (check .errno, .errstr, etc.).
bool publish ( UTF8String topic, UTF8String message, uint8_t qos = MQTT_QOS_AT_MOST_ONCE, bool retained = false );
Published the supplied 'message' to the specified 'topic'.
Parameters:
- topic: The topic where the data should be published (ex: "adafruit/data" or "home/rooms/bedroom/temp"). UTF8String is used to make it easier to work with UTF8 data.
- message: The string of data to write to the specified 'topic'. UTF8String is used to make it easier to work with UTF8 data.
- qos: The quality of service level (see the MQTT spec for details). Default = 'At Most Once', meaning the message tries to send once but isn't persisted if the send fails. Possible values are:
- MQTT_QOS_AT_MOST_ONCE
- MQTT_QOS_AT_LEAST_ONCE
- MQTT_QOS_EXACTLY_ONCE
- retained: Whether or not the published message should be 'retained' by the MQTT broker. Sending a message with the retained bool set to 'false' (0) will clear any previously retained message from the broker. The default value is false.
Returns: 'True' (1) if the publish was successful, otherwise 'false' (0) if an error occured (check .errno, .errstr, etc.).
bool subscribe ( const char* topicFilter, uint8_t qos, messageHandler mh);
Subscribes to a specific topic, using a callback mechanism to alert you when new data is available on the specific topicFilter.
Parameters:
- topicFilter: The topic name or topic 'filter' to subscribe to. This can be either a single topic ("home/kitchen/fridge/temp") or make use of a standard MQTT wildcard like "home/+", which will subscribe to changes to any topic above the 'home/' level.
-
qos: A subscribing client can set the maximum quality of service a broker uses to send messages that match the client subscriptions. The QoS of a message forwarded to a subscriber thus might be different to the QoS given to the message by the original publisher. The lower of the two values is used to forward a message. The value of qos can be one of:
- MQTT_QOS_AT_MOST_ONCE
- MQTT_QOS_AT_LEAST_ONCE
- MQTT_QOS_EXACTLY_ONCE
- mh: The MQTT subscribe callback function that will handle callback events (see Subscribe Callback Handler below for details).
Returns: 'True' (1) if the subscribe was successful, otherwise 'false' (0) if an error occured (check .errno, .errstr, etc.).
Subscribe Callback Handler(s)
When you subscribe to a specific topic or topic filter, you also need to pass in a callback function that will be used to handle any subscribe matches or events.
MQTT subscribe callback functions must have the following format:
/**************************************************************************/ /*! @brief MQTT subscribe event callback handler @param topic The topic causing this callback to fire @param message The new value associated with 'topic' @note 'topic' and 'message' are UTF8Strings (byte array), which means they are not null-terminated like C-style strings. You can access its data and len using .data & .len, although there is also a Serial.print override to handle UTF8String data types. */ /**************************************************************************/ void subscribed_callback(UTF8String topic, UTF8String message) { // Print out topic name and message Serial.print("[Subscribed] "); Serial.print(topic); Serial.print(" : ") ; Serial.println(message); // Echo back Serial.print("Echo back to " TOPIC_ECHO " ... "); mqtt.publish(TOPIC_ECHO, message); // Will halt if an error occurs Serial.println("OK"); // Unsubscribe from SUBSCRIBED_TOPIC2 if we received an "stop" message // Won't be able to echo anymore if ( message == "stop" ) { Serial.print("Unsubscribing from " TOPIC_SUBSCRIBE " ... "); mqtt.unsubscribe(TOPIC_SUBSCRIBE); // Will halt if fails Serial.println("OK"); } }
Callback Handler Parameters
- topic: The topic that caused the subscribe callback to fire (UTF8-encoded)
- message: The UTF8 encoded message associated with topic_data
bool unsubscribe( const char* topicFilter );
Unsubscribes from a specific topic or topic filter.
Parameters: The topic or topic filter to unsubscribe from
Returns: 'True' (1) is the unsubscribe was successful, otherwise 'false' (0).
Last Will
MQTT has a concept called a 'Last Will' message. The optional 'Last Will' message can be set using a user-define topic, and this message will be sent if the server/broker is unable to contact the client for a specific amount of time.
This functionality isn't a mandatory part of MQTT, but can be used to detect when nodes are online and offline. When you connect, you can for example set a string like "Online" to a specific topic, and then set a last will message of "Offline" to that same topic. If the node goes offline (battery failure, disconnect, etc.), the broker will use the last will to set the topic to "Offline" once the server/client timeout occurs.
void will ( const char* topic, UTF8String message, uint8_t qos = MQTT_QOS_AT_MOST_ONCE, uint8_t retained = 0);
Sets the last will message.
Parameters:
- topic: The topic where the data should be published (ex: "adafruit/data" or "home/rooms/bedroom/temp").
- message: The string of data to write to the specified 'topic' (UTF8String is used to make it easier to work with UTF8 data).
- qos: The quality of service level (see the MQTT spec for details). Default = 'At Most Once', meaning the message tries to send once but isn't persisted if the send fails. Possible values are:
- MQTT_QOS_AT_MOST_ONCE
- MQTT_QOS_AT_LEAST_ONCE
- MQTT_QOS_EXACTLY_ONCE
- retained: Whether or not the published message should be 'retained' by the MQTT broker. Sending a message with the retained bool set to 'false' (0) will clear any previously retained message from the broker. The default value is false.
Returns: 'True' (1) is the last will message was successfully set, otherwise 'false' (0).
Client ID
The client identifier (Client ID) is an string that identifies each MQTT client connecting to an MQTT broker.
This value should be unique on the broker since the broker uses it for identifying the client and the client's current 'state' of the client (subscriptions, QoS, etc.).
By default, a random 10-23 character string will be generated for the unique Client ID that gets passed to the broker during the connection process. If you wish to maintain a consistent client ID across connections, however, you can override the random client ID by using the .clientID function below:
void clientID(const char* client)
Sets a manual Client ID, overriding the default random value.
Parameters:
- client: A null-terminated string representing the client ID to pass to the MQTT broker.
Returns: Nothing
Disconnect Callback
An optional disconnect callback is available in AdafruitMQTT. This callback handler will fire when you are disconnected from the remote MQTT broker.
To use the callback, add the following function to your sketch (the function name and the contents of the function can change depending on your project requirements):
void disconnect_callback(void) { Serial.println(); Serial.println("-----------------------------"); Serial.println("DISCONNECTED FROM MQTT BROKER"); Serial.println("-----------------------------"); Serial.println(); }
Then pass this function name into the .setDisconnectCallback function BEFORE calling .connect or .connectSSL:
// Set the disconnect callback handler mqtt.setDisconnectCallback(disconnect_callback);
AdafruitMQTT Example
The following example illustrates how to subscribe to topics, set the last will message, publish, and implement one or more subscribe callback handlers:
/********************************************************************* This is an example for our Feather WIFI modules Pick one up today in the adafruit shop! Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! MIT license, check LICENSE for more information All text above, and the splash screen below must be included in any redistribution *********************************************************************/ #include <adafruit_feather.h> #include <adafruit_mqtt.h> #include "certificate_mosquitto.h" /* This sketch demonstrates subscribe/unsubscribe activity with * callbacks. * * It will connect to a public MQTT server (with/without TLS) * and subscribe to TOPIC_SUBSCRIBE (defined below). * * - When a message is received, it will echo back to TOPIC_ECHO * - If the received message is "stop", we will * unsubscribe from TOPIC_SUBSCRIBE and you won't be able to * echo content back to the broker any longer. * * Note: TOPIC_SUBSCRIBE and TOPIC_ECHO must not be the same topic! * Ex. They must not be "adafruit/+" and "adafruit/echo", since this will * cause an infinite loop (received -> echo -> received -> ....) * * For details on the MQTT broker server see http://test.mosquitto.org/ * - Port 1883 : MQTT, unencrypted * - Port 8883 : MQTT, encrypted (TLS) * * Note: may You need an MQTT desktop client such as the lightweight * Java client included in this repo: org.eclipse.paho.mqtt.utility-1.0.0.jar * * For information on configuring your system to work with MQTT see: * - https://learn.adafruit.com/desktop-mqtt-client-for-adafruit-io/installing-software * * To run this demo * 1. Change the WLAN_SSID/WLAN_PASS to match your access point * 2. Decide whether you want to use TLS/SSL or not (USE_TLS) * 3. Change TOPIC*, WILL*, enable CLIENTID if needed * 4. Compile and run * 5. Use an MQTT desktop client to connect to the same MQTT broker and * publish to any topic beginning with "adafruit/feather/" (depending * on TOPIC_SUBSCRIBE). To be able to recieve the echo message, please * also subcribe to "adafruit/feather_echo" (TOPIC_ECHO). */ #define WLAN_SSID "yourSSID" #define WLAN_PASS "yourPass" #define USE_TLS 0 #define BROKER_HOST "test.mosquitto.org" #define BROKER_PORT (USE_TLS ? 8883 : 1883) // Uncomment to set your own ClientID, otherwise a random ClientID is used //#define CLIENTID "Adafruit Feather" #define TOPIC_SUBSCRIBE "adafruit/feather/+" #define TOPIC_ECHO "adafruit/feather_echo" #define WILL_TOPIC "adafruit/feather" #define WILL_MESSAGE "Goodbye!!" AdafruitMQTT mqtt; /**************************************************************************/ /*! @brief Disconnect handler for MQTT broker connection */ /**************************************************************************/ void disconnect_callback(void) { Serial.println(); Serial.println("-----------------------------"); Serial.println("DISCONNECTED FROM MQTT BROKER"); Serial.println("-----------------------------"); Serial.println(); } /**************************************************************************/ /*! @brief The setup function runs once when the board comes out of reset */ /**************************************************************************/ void setup() { Serial.begin(115200); // Wait for the USB serial port to connect. Needed for native USB port only while (!Serial) delay(1); Serial.println("MQTT Subscribe Example\r\n"); // Print all software versions Feather.printVersions(); while ( !connectAP() ) { delay(500); // delay between each attempt } // Connected: Print network info Feather.printNetwork(); // Tell the MQTT client to auto print error codes and halt on errors mqtt.err_actions(true, true); // Set ClientID if defined #ifdef CLIENTID mqtt.clientID(CLIENTID); #endif // Last will must be set before connecting since it is part of the connection data mqtt.will(WILL_TOPIC, WILL_MESSAGE, MQTT_QOS_AT_LEAST_ONCE); // Set the disconnect callback handler mqtt.setDisconnectCallback(disconnect_callback); Serial.printf("Connecting to " BROKER_HOST " port %d ... ", BROKER_PORT); if (USE_TLS) { // Disable default RootCA to save SRAM since we don't need to // access any other site except test.mosquitto.org Feather.useDefaultRootCA(false); // mosquitto CA is pre-generated using pycert.py Feather.addRootCA(rootca_certs, ROOTCA_CERTS_LEN); // Connect with SSL/TLS mqtt.connectSSL(BROKER_HOST, BROKER_PORT); }else { mqtt.connect(BROKER_HOST, BROKER_PORT); } Serial.println("OK"); Serial.print("Subscribing to " TOPIC_SUBSCRIBE " ... "); mqtt.subscribe(TOPIC_SUBSCRIBE, MQTT_QOS_AT_MOST_ONCE, subscribed_callback); // Will halted if an error occurs Serial.println("OK"); } /**************************************************************************/ /*! @brief This loop function runs over and over again */ /**************************************************************************/ void loop() { } /**************************************************************************/ /*! @brief MQTT subscribe event callback handler @param topic The topic causing this callback to fire @param message The new value associated with 'topic' @note 'topic' and 'message' are UTF8Strings (byte array), which means they are not null-terminated like C-style strings. You can access its data and len using .data & .len, although there is also a Serial.print override to handle UTF8String data types. */ /**************************************************************************/ void subscribed_callback(UTF8String topic, UTF8String message) { // Print out topic name and message Serial.print("[Subscribed] "); Serial.print(topic); Serial.print(" : ") ; Serial.println(message); // Echo back Serial.print("Echo back to " TOPIC_ECHO " ... "); mqtt.publish(TOPIC_ECHO, message); // Will halt if an error occurs Serial.println("OK"); // Unsubscribe from SUBSCRIBED_TOPIC2 if we received an "stop" message // Won't be able to echo anymore if ( message == "stop" ) { Serial.print("Unsubscribing from " TOPIC_SUBSCRIBE " ... "); mqtt.unsubscribe(TOPIC_SUBSCRIBE); // Will halt if fails Serial.println("OK"); } } /**************************************************************************/ /*! @brief Connect to defined Access Point */ /**************************************************************************/ bool connectAP(void) { // Attempt to connect to an AP Serial.print("Attempting to connect to: "); Serial.println(WLAN_SSID); if ( Feather.connect(WLAN_SSID, WLAN_PASS) ) { Serial.println("Connected!"); } else { Serial.printf("Failed! %s (%d)", Feather.errstr(), Feather.errno()); Serial.println(); } Serial.println(); return Feather.connected(); }
Page last edited February 16, 2016
Text editor powered by tinymce.