256dpi / arduino-mqtt

MQTT library for Arduino
MIT License
1.01k stars 230 forks source link
arduino iot mqtt

arduino-mqtt

Test GitHub release

This library bundles the lwmqtt MQTT 3.1.1 client and adds a thin wrapper to get an Arduino like API.

Download the latest version from the release section. Or even better use the built-in Library Manager in the Arduino IDE and search for "lwmqtt".

The library is also available on PlatformIO. You can install it by running: pio lib install "256dpi/MQTT".

Compatibility

The following examples show how you can use the library with various Arduino compatible hardware:

Other shields and boards should also work if they provide a Client based network implementation.

Check out the Wiki to find more examples.

Notes

Example

The following example uses an Arduino MKR1000 to connect to the public shiftr.io instance. You can check on your device after a successful connection here: https://www.shiftr.io/try.

#include <SPI.h>
#include <WiFi101.h>
#include <MQTT.h>

const char ssid[] = "ssid";
const char pass[] = "pass";

WiFiClient net;
MQTTClient client;

unsigned long lastMillis = 0;

void connect() {
  Serial.print("checking wifi...");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(1000);
  }

  Serial.print("\nconnecting...");
  while (!client.connect("arduino", "public", "public")) {
    Serial.print(".");
    delay(1000);
  }

  Serial.println("\nconnected!");

  client.subscribe("/hello");
  // client.unsubscribe("/hello");
}

void messageReceived(String &topic, String &payload) {
  Serial.println("incoming: " + topic + " - " + payload);

  // Note: Do not use the client in the callback to publish, subscribe or
  // unsubscribe as it may cause deadlocks when other things arrive while
  // sending and receiving acknowledgments. Instead, change a global variable,
  // or push to a queue and handle it in the loop after calling `client.loop()`.
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, pass);

  // Note: Local domain names (e.g. "Computer.local" on OSX) are not supported
  // by Arduino. You need to set the IP address directly.
  client.begin("public.cloud.shiftr.io", net);
  client.onMessage(messageReceived);

  connect();
}

void loop() {
  client.loop();

  if (!client.connected()) {
    connect();
  }

  // publish a message roughly every second.
  if (millis() - lastMillis > 1000) {
    lastMillis = millis();
    client.publish("/hello", "world");
  }
}

API

Create the object with:

MQTTClient()
MQTTClient(int bufSize)
MQTTClient(int readBufSize, int writeBufSize)

Initialize the object using the hostname of the broker, the brokers port (default: 1883) and the underlying Client class for network transport:

void begin(Client &client);
void begin(const char hostname[], Client &client);
void begin(const char hostname[], int port, Client &client);
void begin(IPAddress address, Client &client);
void begin(IPAddress address, int port, Client &client);

The hostname and port can also be changed after calling begin():

void setHost(const char hostname[]);
void setHost(const char hostname[], int port);
void setHost(IPAddress address);
void setHost(IPAddress address, int port);

Set a will message (last testament) that gets registered on the broker after connecting. setWill() has to be called before calling connect():

void setWill(const char topic[]);
void setWill(const char topic[], const char payload[]);
void setWill(const char topic[], const char payload[], bool retained, int qos);
void clearWill();

Register a callback to receive messages:

void onMessage(MQTTClientCallbackSimple);
// Callback signature: void messageReceived(String &topic, String &payload) {}

void onMessage(MQTTClientCallbackSimpleFunction cb);
// Callback signature: std::function<void(String &topic, String &payload)>

void onMessageAdvanced(MQTTClientCallbackAdvanced);
// Callback signature: void messageReceived(MQTTClient *client, char topic[], char bytes[], int length) {}

void onMessageAdvanced(MQTTClientCallbackAdvancedFunction cb);
// Callback signature: std::function<void(MQTTClient *client, char topic[], char bytes[], int length)>

Set more advanced options:

void setKeepAlive(int keepAlive);
void setCleanSession(bool cleanSession);
void setTimeout(int timeout);
void setOptions(int keepAlive, bool cleanSession, int timeout);

Set a custom clock source "custom millis" callback to enable deep sleep applications:

void setClockSource(MQTTClientClockSource);
// Callback signature: uint32_t clockSource() {}

Connect to broker using the supplied client ID and an optional username and password:

bool connect(const char clientID[], bool skip = false);
bool connect(const char clientID[], const char username[], bool skip = false);
bool connect(const char clientID[], const char username[], const char password[], bool skip = false);

Publish a message to the broker with an optional payload, which can be a string or binary:

bool publish(const String &topic);
bool publish(const char topic[]);
bool publish(const String &topic, const String &payload);
bool publish(const String &topic, const String &payload, bool retained, int qos);
bool publish(const char topic[], const String &payload);
bool publish(const char topic[], const String &payload, bool retained, int qos);
bool publish(const char topic[], const char payload[]);
bool publish(const char topic[], const char payload[], bool retained, int qos);
bool publish(const char topic[], const char payload[], int length);
bool publish(const char topic[], const char payload[], int length, bool retained, int qos);

Obtain the last used packet ID and prepare the publication of a duplicate message using the specified packet ID:

uint16_t lastPacketID();
void prepareDuplicate(uint16_t packetID);

Subscribe to a topic:

bool subscribe(const String &topic);
bool subscribe(const String &topic, int qos); 
bool subscribe(const char topic[]);
bool subscribe(const char topic[], int qos);

Unsubscribe from a topic:

bool unsubscribe(const String &topic);
bool unsubscribe(const char topic[]);

Sends and receives packets:

bool loop();

Check if the client is currently connected:

bool connected();

Check whether a session was present at the time of the last connect:

bool sessionPresent();

Configure dropping of overflowing messages (exceeding read buffer) and checking the count of dropped messages:

void dropOverflow(bool enabled);
uint32_t droppedMessages();

Access low-level information for debugging:

lwmqtt_err_t lastError();
lwmqtt_return_code_t returnCode();

Disconnect from the broker:

bool disconnect();

Release Management