When I send MQTT messages from Arduino device to AWS IoT, because of easy to use I use PubSubClient.
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
inPubSubClient.h
or can be changed by callingPubSubClient::setBufferSize(size)
.https://github.com/knolleary/pubsubclient/tree/master?tab=readme-ov-file#limitations