AdafruitMQTT includes an OPTIONAL helper class called AdafruitMQTTTopic that can be used to publish data to a single topic on an MQTT broker.
This helper class inherits from Print, which allows you to write data to MQTT topics similarly to how you would write data to the 'Serial Monitor', using .print statements.
AdafruitMQTTTopic(AdafruitMQTT& mqtt, const char* topic, uint8_t qos = MQTT_QOS_AT_MOST_ONCE, bool retain = false)
Parameters:
- mqtt: A reference to the AdafruitMQTT instance associated with this helper (since the connection to the MQTT broker is defined and managed there).
- topic: A null-terminated string containing the topic to publish to
- qos: An optional quality of server (QoS) level to use when publishing. If left empty, this argument will default to 'At Most Once', meaning it will try to publish the data but if the operation fails it won't persist the attempt and retry again later.
- retain: Sets the 'retain' bit to indicate if any messages published to the MQTT broker should be retained on the broker for the next client(s) that access that topic.
The following example shows how to properly declare an instance of the AdafruitMQTTTopic class (note that the default QoS and retain values are used):
#define CLIENTID "Adafruit Feather" #define TOPIC "adafruit/feather" AdafruitMQTT mqtt (CLIENTID); AdafruitMQTTTopic publisher (mqtt, TOPIC);
Functions
In addition to the functions defined in the Print base class (see the Print.h source as well), the following functions are defined as part of AdafruitMQTTTopic:
void retain(bool on)
void retain (bool on)
Enables or disabled the 'retain' feature when publishing messages. This indicates whether the published message should be maintained on the broker when a message is written to the topic.
Parameters:
- on: Whether or not the published message should be 'retained' by the MQTT broker. Sending a message with the this set to 'false' (0) will clear any previously retained message from the broker.
Returns: Nothing
Subscribe Callbacks
You can also subscribe or unsubcribe to publications on the topic using the following functions:
bool subscribe (messageHandler_t mh); bool unsubscribe (void); bool subscribed (void);
bool subscribe (messageHandler_t mh)
This function will subscribe to the topic and any changes will be sent to the specified callback handler.
Parameters:
- mh: The callback handler where the subscription event should be redirected to.
Returns: 'True' (1) is the subscribe was successful, otherwise 'false' (0).
Subscription callback handlers 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.printf("["); Serial.print(topic); Serial.printf("]"); Serial.print(" : message = ") ; Serial.println(message); // Unsubscribe if message = "stop" if ( message == "stop" ) { Serial.print("Unsubscribing ... "); mqttTopic.unsubscribe(); // Will halt if fails Serial.println("OK"); } }
bool unsubscribe (void)
Unsubscribes to the topic if you previously called .subscribe.
Parameters: None
Returns: 'True' (1) if the operation succeeded, otherwise 'false' (0).
bool subscribed (void)
Indicates whether you are currently susbcripted to this topic or not.
Parameters: None
Returns: 'True' (1) if you are subscribed, otherwise 'false' (0).
Publishing Data via 'Print'
One important thing to keep in mind with AdafruitMQTTTopic is that every .print* function corresponds to an MQTT publication request.
The following code will result in three different MQTT publications:
int number_of_days = 7; char* place = "somewhere"; pub.print(number_of_days); pub.print(" days since something happened "); pub.print(place);
You can work around this '1 print = 1 publication' restriction by using the printf function, as shown in the example below:
int number_of_days = 7; char* place = "somewhere"; pub.printf("%d days since something happened %s", number_of_days, place);
For a full list of printf modifiers (the special '%' character sequences that get replaced with variables after the main string) see printf here.
The most common modifiers are described below though (all preceded by '%' so '%d' for a signed decimal value, etc.) :
- d or i: Signed decimal value ('int', 'int16_t', etc.)
- u: unsigned decimal value ('uint32_t', etc.)
- x: lower-case hexadecimal integer (ex. 'a12b' for 0xA12B)
- X: upper-case hexadecimal integer (ex. 'A12B' for 0xA12B)
- f: floating point value ('float', etc.)
- s: null-terminated string of characters (ex. "sample")
- c: A single characters (ex. 'a')
Example
The following sketch shows how you might use AdafruitMQTTTopic in the real world. The latest source can be found in the MQTT/MqttTopicClass folder in 'examples'.
/********************************************************************* 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 connects to a public MQTT server (with/without TLS) * and publishes a message to a topic every 5 seconds. * * For server details 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 or * - A full desktop client like MQTT.fx https://learn.adafruit.com/desktop-mqtt-client-for-adafruit-io/installing-software * * To run this demo * 1. Change WLAN_SSID/WLAN_PASS * 2. Decide whether you want to use TLS/SSL or not (USE_TLS) * 3. Change CLIENTID, TOPIC, PUBLISH_MESSAGE, WILL_MESSAGE if you want * 4. Compile and run * 5. Use your MQTT desktop client to connect to the same sever and subscribe * to the defined topic to monitor the published message(s). */ #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 "adafruit/feather" #define WILL_MESSAGE "Goodbye!!" AdafruitMQTT mqtt; AdafruitMQTTTopic mqttTopic(&mqtt, TOPIC, MQTT_QOS_EXACTLY_ONCE); char old_value = '0'; char value = '0'; /**************************************************************************/ /*! @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 Publish using Publisher 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(TOPIC, WILL_MESSAGE, MQTT_QOS_AT_LEAST_ONCE); // Connect to broker 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"); // Subscribe with callback mqttTopic.subscribe(subscribed_callback); Serial.println("Please use desktop client to subcribe to \'" TOPIC "\' to monitor"); // Inital publish Serial.printf("Publishing \'%d\' ... ", value); mqttTopic.print( value ); // use .write to send in binary format Serial.println("OK"); } /**************************************************************************/ /*! @brief This loop function runs over and over again */ /**************************************************************************/ void loop() { // value changed due to subscribed callback if (old_value != value) { // check if still subscribed if ( mqttTopic.subscribed() ) { old_value = value; Serial.println(); Serial.printf("Publishing \'%c\' ... \r\n", value); mqttTopic.print( value ); // use .write to send in binary 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) { // Copy received data to 'value' memcpy(&value, message.data, 1); // Print out topic name and message Serial.printf("["); Serial.print(topic); Serial.printf("]"); Serial.print(" : value = ") ; Serial.println(value); // Increase value by 1 value++; // wrap around if (value > '9') value = '0'; // Unsubscribe if we received an "stop" message // Won't be able to echo anymore if ( message == "stop" ) { Serial.print("Unsubscribing ... "); mqttTopic.unsubscribe(); // 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 March 01, 2016
Text editor powered by tinymce.