Here you can find information about the MQTT protocol and how it works.
You need the Arduino IDE installed. And the PubSubClient library.
If you don't know how to install libraries on the Arduino IDE here is a guide.
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "mdefAP";
const char* password = "mdefPassword";
WiFiClient wifiClient;
const char* mqttBroker = "192.168.5.1";
const char* mqttClientName = "teamX";
const String mqttUser = ""; // MQTT User Authentification
const String mqttPass = ""; // MQTT Password Authentification
const char* topicToSub = "teamx/in";
const char* topicToPub = "teamx/out";
PubSubClient mqttClient(wifiClient);
const int buttPin = 6;
bool buttState;
void mqttConnect() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect(mqttClientName, mqttUser, mqttPass)) {
Serial.println("connected");
mqttClient.publish("hello", mqttClientName);
// Topic(s) subscription
mqttClient.subscribe(topicToSub);
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
void callback(char* topic, byte* message, unsigned int length) {
String receivedMsg;
for (int i = 0; i < length; i++) {
receivedMsg += (char)message[i];
}
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
Serial.println(receivedMsg);
if (String(topic) == topicToSub) {
// Add here the code to act on input --------------
// Arduino String obejct reference :
// https://www.arduino.cc/reference/en/language/variables/data-types/stringobject/
if (receivedMsg == ("1")) {
Serial.println("on");
digitalWrite(LED_BUILTIN, HIGH);
} else if (receivedMsg == "0") {
Serial.println("off");
digitalWrite(LED_BUILTIN, LOW);
}
//-------------------------------------------------
}
}
void setup() {
Serial.begin(115200);
// Connect to wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// MQTT setup
mqttClient.setServer(mqttBroker, 1883);
mqttClient.setCallback(callback);
// Led setup
pinMode(LED_BUILTIN, OUTPUT);
}
unsigned long lastMsg = 0;
char msg[50];
void loop() {
// Check the current button state
bool currentState = digitalRead(buttPin);
// Check if we are still connected to the MQTT broker
if (!mqttClient.connected()) {
mqttConnect();
}
// Let PubSubClient library do his magic
mqttClient.loop();
// Add your publish code here --------------------
// OPTION 1 -- Publish based on events
if (currentState != buttState) {
buttState = currentState;
snprintf (msg, 50, "%i", buttState);
mqttClient.publish(topicToPub, msg);
}
// OPTION 2 -- Publish based on Timer
// Only publish every 5 seconds
unsigned long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
snprintf (msg, 50, "%ld - hello again!", now);
Serial.print("Publish message: ");
Serial.println(msg);
mqttClient.publish(topicToPub, msg);
}
//-----------------------------------------------
}
#include <WiFi.h>
#include <PubSubClient.h>
Change the WiFi ssid and password to fit your's.
const char* ssid = "mdefAP";
const char* password = "mdefPassword";
WiFiClient wifiClient;
Set the IP address or name of your MQTT broker or the server name, the name that will identify your device and the names of a topic(s) to subscribe and/or publish, and the authentification (mqttUser
and mqttPass
)
const char* mqttBroker = "192.168.5.1";
const char* mqttUser = ""; // MQTT User Authentification
const char* mqttPass = ""; // MQTT Password Authentification
const char* mqttClientName = "teamX";
const char* topicToSub = "teamx/in";
const char* topicToPub = "teamx/out";
PubSubClient mqttClient(wifiClient);
Adding variables for topic names is optional but in this way if you need to change them you can do it in one point instead of tracking all the places where they are used.
This function is called on the main loop, it checks if the connection with the MQTT broker is alive and reconnects if necessary.
Here we subscribe to the topics we want to receive.
void mqttConnect() {
while (!mqttClient.connected()) {
Serial.print("Attempting MQTT connection...");
if (mqttClient.connect(mqttClientName, mqttUser, mqttPass)) {
Serial.println("connected");
mqttClient.publish("hello", mqttClientName);
// Topic(s) subscription
mqttClient.subscribe(topicToSub);
} else {
Serial.print("failed, rc=");
Serial.print(mqttClient.state());
Serial.println(" try again in 5 seconds");
delay(5000);
}
}
}
This function is executed every time a message is received. In this example if we receive the words on or off in a specific topic we change the led state.
void callback(char* topic, byte* message, unsigned int length) {
String receivedMsg;
for (int i = 0; i < length; i++) {
receivedMsg += (char)message[i];
}
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
Serial.println(receivedMsg);
if (String(topic) == topicToSub) {
if (receivedMsg == ("1")) {
Serial.println("on");
digitalWrite(LED_BUILTIN, HIGH);
} else if (receivedMsg == "0") {
Serial.println("off");
digitalWrite(LED_BUILTIN, LOW);
}
} // Here you can check for other subscribed topics
}
Subscribing to a new topic is done in three points of the code:
mqttConnect()
function add a line subscribing to the new topic: mqttClient.subscribe(newName)
callback()
function check if the new topic is receiving something, evaluate the message and take some actions!Start Serial communication, WiFi, MQTT and the pin to control internal led.
void setup() {
Serial.begin(115200);
// Connect to wifi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
// MQTT setup
mqttClient.setServer(mqttBroker, 1883);
mqttClient.setCallback(callback);
// Led setup
pinMode(LED_BUILTIN, OUTPUT);
}
In the main loop we check if the MQTT connection is still alive and call the mqttConnect()
function if needed.
We need to call the mqttClient.loop()
function every cycle so the PubSubClient library has time to do his inner works.
// Declare needed variables
unsigned long lastMsg = 0;
char msg[50];
void loop() {
// Check the current button state
bool currentState = digitalRead(buttPin);
// Check if we are still connected to the MQTT broker
if (!mqttClient.connected()) {
mqttConnect();
}
// Let PubSubClient library do his magic
mqttClient.loop();
// Publish based on events
if (currentState != buttState) {
buttState = currentState;
snprintf (msg, 50, "%i", buttState);
mqttClient.publish(topicToPub, msg);
}
}
Now make sure your broker is running and it is on the right address and power your feather!
Publishing a MQTT message can be done just adding a call to the publish(topic, message)
function of the MQTT client.
Check the output of the Feather Serial port
To interact with MQTT from your computer you can use
mosquitto software.
Log in your Raspberry Pi MQTT broker.
/var/log/mosquitto/mosquitto.log
)sudo systemctl stop mosquitto
and run it manually (just type mosquitto
and hit enter) to see the the console output.Printing debug messages to the Serial port can make your code big and more complicated, but when something doesn't work you will be gratefull of those lines!