Programming

The Benefits of PubSubClient and Points to Be Aware Of

When I send MQTT messages from Arduino device to AWS IoT, because of easy to use I use PubSubClient.

A client library for the Arduino Ethernet Shield that provides support for MQTT. - knolleary/pubsubclient
GitHub - knolleary/pubsubclient: A client library for the Arduino Ethernet Shield that provides support for MQTT. - GitHub

Only following code can load device certificate issued by AWS IoT and send MQTT messages to AWS IoT.

#include <M5StickCPlus.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include <WiFiClientSecure.h>

// WiFi SSID and password
const char *ssid = "xxxxx";
const char *password = "xxxxx";

// AWS IoT endopoint and MQTT topic
const char* aws_endpoint = "xxxxx";
const char* mqtt_topic = "xxxxx";

// Device certificate
const char *cert = R"KEY(
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
)KEY";

const char *private_key = R"KEY(
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
)KEY";

const char *root_ca = R"KEY(
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
)KEY";

WiFiClientSecure net;
PubSubClient client(net);

void connectAWS() {
    M5.Lcd.println("Connecting to AWS");
    while (!client.connected()) {
        if (client.connect("M5StickCPlusClient")) {
            M5.Lcd.println("Connected to AWS");
        } else {
            M5.Lcd.print("Failed, rc=");
            M5.Lcd.print(client.state());
            delay(5000);
        }
    }
}

void callback(char* topic, byte* payload, unsigned int length) {
    M5.Lcd.print("Message arrived [");
    M5.Lcd.print(topic);
    M5.Lcd.print("] ");
    for (unsigned int i = 0; i < length; i++) {
        M5.Lcd.print((char)payload[i]);
    }
    M5.Lcd.println();
}

void setup() {
    M5.begin();
    M5.Lcd.setTextSize(1);
    M5.Lcd.setRotation(3);
    M5.Lcd.println("Connecting to WiFi");

    // WiFi connection
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        M5.Lcd.print(".");
    }
    M5.Lcd.println("\nWiFi connected");

    // Set device certificate
    net.setCACert(root_ca);
    net.setCertificate(cert);
    net.setPrivateKey(private_key);

    client.setServer(aws_endpoint, 8883);
    client.setCallback(callback);

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

void loop() {
    if (!client.connected()) {
        connectAWS();
    }
    client.loop();

    // Sending message
    String message = "Hello from M5StickCPlus";
    client.publish(mqtt_topic, message.c_str());
    delay(10000);
}

However, PubSubClient doesn’t support QoS 1 for publish (only QoS 0). It supports QoS 1 for subscribe though. Looks last commit is 4 years ago, so QoS 1 for publish won’t be supported at least soon.

It can only publish QoS 0 messages. It can subscribe at QoS 0 or QoS 1.

https://github.com/knolleary/pubsubclient/tree/master?tab=readme-ov-file#limitations

On a slightly different topic, the default message size limit is 256 bytes, and when receiving a message that exceeds this limit, no error message is returned. It makes debugging a bit difficult.

The maximum message size, including header, is 256 bytes by default. This is configurable via MQTT_MAX_PACKET_SIZE in PubSubClient.h or can be changed by calling PubSubClient::setBufferSize(size).

https://github.com/knolleary/pubsubclient/tree/master?tab=readme-ov-file#limitations

zuqqhi2

Share
Published by
zuqqhi2
Tags: pubsubclient