Last active
August 10, 2020 12:51
-
-
Save mjvo/4913d11adcc08d7188819c79e2186b99 to your computer and use it in GitHub Desktop.
Quickstart code for Arduino MQTT communication
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define SECRET_SSID "DukeOpen" // your network SSID (name) | |
#define SECRET_PASS "" // your network password; leave empty for open networks |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
#################################################################################### | |
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