Skip to content

Instantly share code, notes, and snippets.

@mjvo
Last active August 10, 2020 12:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mjvo/4913d11adcc08d7188819c79e2186b99 to your computer and use it in GitHub Desktop.
Save mjvo/4913d11adcc08d7188819c79e2186b99 to your computer and use it in GitHub Desktop.
Quickstart code for Arduino MQTT communication
#define SECRET_SSID "DukeOpen" // your network SSID (name)
#define SECRET_PASS "" // your network password; leave empty for open networks
/*
####################################################################################
MQTT PubSub implementation for Feather M0
For information on configuration:
http://mjvo.github.io/tutorials/circuits/mqtt/
External libraries required (available through Arduino Library Manager):
- WiFi101: https://www.arduino.cc/en/Reference/WiFi101
- PubSub Client by Nick O'Leary: https://pubsubclient.knolleary.net/
- arduino-timer by Michael Contreras: https://github.com/contrem/arduino-timer
####################################################################################s
*/
// Arduino library dependencies
// modify only if your application requires additional libraries
#include <SPI.h>
#include <WiFi101.h>
#include <PubSubClient.h>
#include <timer.h>
///////enter your wifi access credentials in the tab: arduino_secrets.h
#include "arduino_secrets.h"
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
int status = WL_IDLE_STATUS; // variable to hold WiFi radio's status
// MQTT CONFIGURATION SETTINGS
#define MQTT_BROKER "mqtt.ip.or.url" // specify MQTT broker address (IP or URL)
#define MQTT_PORT 8883 // use 8883 for TLS/SSL MQTT; use 1883 for non-secure
////// if using TLS/SSL for MQTT, use this line
WiFiSSLClient WiFiclient; // instantiate a secure WiFi client
///// if not, comment out line 32 and *un*comment line 35 below
// WiFiClient WiFiclient; // instantiate a non-SSL WiFi client
PubSubClient client(WiFiclient); // use WiFi for MQTT communication
// each MQTT client should have a unique ID
String device_id = "FeatherM0-"; // this will be used with Mac address for uniqueness
// variables for non-blocking MQTT reconnection
long lastReconnectAttempt = 0;
long now;
// ****
// PIN DECLARATIONS
//
// Pin declarations for Feather hardware control
// Modify as necessary for your hardware setup.
// Don't forget pinMode in the setup() function!
// ****
// examples:
// const int ledPin = 13; // onboard LED
// const int sensorPin = A1; // analog input, such as potentiometer
// ****************
// SUBSCRIPTIONS SETUP
// modify Part A and Part B if your application
// requires that you subscribe to an MQTT topic
//
// If you do NOT need to subscribe to and parse an
// MQTT topic, comment out all client.subscribe() functions
// in Part A. Part B can be left alone.
// ****************
// ********
// Part A
// doSubscriptions() is a function for subscribing to MQTT topics
// Subscriptions happen after successful connection to MQTT broker
// ********
void doSubscriptions() {
// Specify topic subscriptions line by line below, such as
// client.subscribe("/some/topic");
// client.subscribe("/another/topic");
}
// ****
// parseMQTT is a "callback" function for processing incoming MQTT messages
// based on the subscribed topics set in doSubscriptions above
//
// Individual topics can be handled differently
//
// ****
void parseMQTT(char* topic, byte* payload, unsigned int length) {
payload[length] = '\0'; // important - do not delete
// print to serial every message, regardless of topic
// (optional)
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
Serial.print((char*)payload);
Serial.println();
// ********
// PART B
// Handle parsing of specific topics below, using the "string
// compare" function to differentiate among topics
//
/* syntax:
if (strcmp(topic, "/some/topic/") == 0){
//Do something with its payload
}
*/
// ********
/////// TOPIC SPECIFIC PARSING GOES HERE
}
// END SUBSCRIPTIONS SETUP
// ****************
// MQTT PUBLISHING SETUP
//
// If your application requires that you publish to an MQTT
// topic at regular intervals, modify Part 1 and Part 2 below
//
// If you instead wish to publish only when a particular hardware
// event happens (e.g. on button press), or when a particular threshold is
// reached, this can be accomplished in your loop() function with if/else
// statements (e.g. if (temp > 105) { client.publish("temp overload" } ).
//
// ****************
auto doPub = timer_create_default(); // create a timer with default settings
// ****
// Part 1
// Below you can specify how often you wish to publish
// to a given MQTT topic (e.g. every 100 ms, every 10 secs,
// every 24 hours, etc).
//
// Multiple publish events can happen at a given interval.
//
// Comment out ALL doPub.every() functions if you do NOT
// wish to publish to any MQTT topics
//
// ****
void setPubIntervals() {
// syntax: doPub.every(milliseconds, callbackFunction);
//doPub.every(100, someFunc); // call the someFunc() function every 100 ms
}
// ****
//
// Part 2:
// Here you specify what happens for each callback function
// added to the timer in Part 1 above.
//
// Minimum Syntax:
/*
bool someFunc(void *) {
client.publish("/some/topic", "value_as_string", false); // true:false --> retained
return true; // repeat --> true
}
*/
//
// ****
///////// doPub callback functions go here
void setup() {
// ****
// Any pinMode declarations should be set here
// ****
//pinMode(ledPin, OUTPUT);
//pinMode(sensorPin, INPUT);
// default Arduino ADC resolution is 10-bit
// but we can set it to the Feather M0 native resolution of 12-bit
analogReadResolution(12);
//////////////////////////////////////////////////////////////
// No need to modify below, unless specifying publish //
// events in the loop() function //
//////////////////////////////////////////////////////////////
//Initialize serial and wait for port to open:
Serial.begin(9600);
// Feather M0-specific WiFi pins
WiFi.setPins(8, 7, 4, 2);
// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi chip not present or accessible");
// don't continue:
while (true);
}
// attempt to connect to WiFi network:
while ( status != WL_CONNECTED) {
Serial.print("Attempting to connect to SSID: ");
Serial.println(ssid);
// Connect to WiFi:
if (sizeof(pass) <= 1) {
status = WiFi.begin(ssid);
}
else {
status = WiFi.begin(ssid, pass);
}
// wait 5 seconds for connection:
delay(5000);
}
// you're connected now, so print out a success message:
Serial.println("You're connected to the network");
// print your Feather's IP address and MQTT info:
IPAddress ip = WiFi.localIP();
Serial.print("Device IP Address: ");
Serial.println(ip);
// get your MAC address:
byte mac[6];
WiFi.macAddress(mac);
String mac_address;
for (int i = 5; i >= 0; i--) {
if (mac[i] < 16) mac_address += "0";
mac_address += String(mac[i], HEX);
if (i > 0) mac_address += ":";
}
// append to device_id
device_id += mac_address;
Serial.print("Attempting to connect to MQTT Broker: ");
Serial.print(MQTT_BROKER);
Serial.print(":");
Serial.println(MQTT_PORT);
lastReconnectAttempt = 0;
// initiate first connection to MQTT broker
client.setServer(MQTT_BROKER, MQTT_PORT);
// specify a function to call upon receipt of a msg
// on a subscribed channel; in this case parseMQTT()
client.setCallback(parseMQTT);
setPubIntervals(); // initalize any publish intervals
}
void loop()
{
// get the current time
now = millis();
// if MQTT connection lost
if (!client.connected()) {
// only attempt to reconnect every 5 secs
if (now - lastReconnectAttempt > 5000) { // 5 secs since last reconnect attempt?
lastReconnectAttempt = now;
// Attempt to reconnect
if (reconnect()) {
lastReconnectAttempt = 0;
}
}
} else {
// MQTT client connected
client.loop();
}
doPub.tick(); // tick the doPub timer
}
boolean reconnect() {
if (client.connect(device_id.c_str())) {
Serial.print(device_id);
Serial.println(" connected to MQTT broker");
doSubscriptions(); // (re)subscribe to desired topics
return client.connected();
}
Serial.print("MQTT connection failed, rc=");
Serial.println(client.state());
Serial.println("Trying again ...");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment