Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
276 lines (182 sloc) 8.75 KB
MQTT Raw Data to Cayenne Dashboard,
using the great Nick O'Leary's PubSubClient
(Arduino Client for MQTT,
What does it do?
This sketch will attempt to connect to Cayenne MQTT server via Wifi,
subscribe to a "dashboard button" topic, to turn on/off the esp8266 built in led.
Also it will publish temperature readings from a Dallas DS18b20 digital temperature sensor.
In a near future, the esp8266 (NodeMCU v2) should act as a smart thermostat, controlling my central heater/boiler.
It should be possible to remotely check ambient temperature and boiler status using
Cayenne Dashboard and turn the heater on/off (in case I left home in a hurry!, etc.)
Inspired in several tutorials and sketches mashed up, mainly..
Andreas Spiess
Terry King
Markus Ulsass
Marc / spacefolder
// ---------- INLCUDE LIBRARIES ----------
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <OneWire.h> //
#include <DallasTemperature.h>
// ---------- DEFINE CONSTANT VALUES ----------
#define PIN_ONE_WIRE_BUS 2 // GPIO02, D4 on esp8266. Sensor's data input pin.
#define MQTT_SERVER ""
#define MQTT_SERVERPORT 1883
#define MQTT_USERNAME "fxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxe"
#define MQTT_PASSWORD "fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxd"
#define CLIENT_ID "7xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx0"
// Define "topic" linked to the Cayenne Dashboard ON/OFF button (boiler) (Cayenne Channel 5)
#define MQTT_TOPIC_BTN_ONOFF "v1/" MQTT_USERNAME "/things/" CLIENT_ID "/cmd/5"
// Define "topic" linked to the Cayenne Dashboard Temperature Gauge (Cayenne Channel 10)
#define MQTT_TOPIC_TPROBE_INT "v1/" MQTT_USERNAME "/things/" CLIENT_ID "/data/10"
// ---------- INITIALIZE INSTANCES ----------
OneWire oneWire(PIN_ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
WiFiClient espClient; // Creates a client instance for the PubSubClient
PubSubClient client(espClient);
// ---------- DEFINE VARIABLES ----------
const char* ssid = "xxxxxxxxxxx"; // WLAN-SSID (WiFi router)
const char* password = "xxxxxxxxx"; // WLAN Password
// Probe01 is the Hex Adress of the Dallas Temperature sensor. In the future, more than one
// sensor will be used, readings are done using the hardware address of each one.
DeviceAddress Probe01 = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Probe #001
// Temperature readings will be once every 2 seconds. Define variables to use with "millis" function.
long timeStampNow;
long timeStampLastMsg = 0;
// Define a datatype to store the mqtt message, up to 50 bytes.
char msg[50]; // 50 BYTES QUIZAS SEA MUCHO AL GAS, pero bueh
// This variable will store the temperature readings from the Dallas probe.
float tempDallasProbe1;
// -------------------- SETUP -------------------
void setup() {
// Initialize serial monitor for debugging purposes.
Serial.println("DEBUG: Entering setup ");
// Attempt to connect to WiFi.
WiFi.begin(ssid, password);
Serial.print("Connecting to ");
while (WiFi.status() != WL_CONNECTED) {
Serial.println(""); // Faltaria agregar que muestre el ip si no es estatico
Serial.println("WiFi connected");
// Initialize Dallas temperature library/
Serial.print("Initializing Temperature Control Library Version ");
// set the DS18b20's resolution to 10 bit (0.25 C degress)
sensors.setResolution(Probe01, 10);
// Check if temperature sensors are present.
Serial.print("DEBUG: Number of devices found on the OneWire bus = ");
// Initialize Pins
pinMode(BUILTIN_LED, OUTPUT); // esp8266's built in led.
digitalWrite(BUILTIN_LED, !LOW); // This pin handles inverse logic, it's state is reversed.
// Initialize MQTT PubSub Library
// Function called in case of an incomming mqtt message from Cayenne Dashboard
// (In this case is the dashboard button to turn on/off the heater)
Serial.println("DEBUG: Setup Done! ");
// -------------------- LOOOP -------------------
void loop() {
Serial.println("DEBUG: Entering main loop ");
// Check if the esp8266 is connected to the mqtt server.
if (!client.connected()) {
// If connected, perform PubSubClient housekeeping function.
// Publish temperature readings every 2 seconds (2000ms)
timeStampNow = millis();
if (timeStampNow - timeStampLastMsg > 2000) { // Publish interval in milliseconds
// Reset the counter
timeStampLastMsg = timeStampNow;
// Jump to the actual function to read and publish temperatures.
Serial.println("DEBUG: Reached MAIN LOOP END --> Looping ");
// ------------------------------ OTHER FUNCTIONS
// Function that attempts to reconnect to the mqtt server.
void reconnect() {
// If esp8266 is disconnected from the mqtt server, try to reconnect.
// (*** I still need to think what wil happen to the boiler if connection is lost ***)
while (!client.connected()) {
Serial.print("DEBUG: Attempting MQTT connection...");
// Attempt to connect
// Once connected, resubscribe to the Dashboard on/off button topic.
} else {
Serial.print("failed, rc=");
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
Serial.println("DEBUG: Quiting reconnect loop ");
// Function to intercept MQTT messages
void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print("] ");
for (int i = 0; i < length; i++) {
// Show the received message "stream" in the serial monitor.
// The actual Cayenne mqtt message payload (Actuator Command) consists of:
// a Sequence Identifier followed by the actual Value (0 = Off, 1 = On)
// For example: "2otoExGxnMJz0Jn,0". We need the Value that is in "position" number 16.
if ((char)payload[16] == '0') {
// We received a 0, so turn built in led off.
digitalWrite(BUILTIN_LED, !LOW);
// Publish confirmation that the led was actually turned off, so it is reflected in the dashboard.
client.publish("v1/" MQTT_USERNAME "/things/" CLIENT_ID "/data/5", "0");
if ((char)payload[16] == '1') {
// We received a 1, so turn built in led on.
digitalWrite(BUILTIN_LED, !HIGH);
// Publish confirmation that the led was actually turned off, so it is reflected in the dashboard.
client.publish("v1/" MQTT_USERNAME "/things/" CLIENT_ID "/data/5", "1");
// Delay for debugging purposes. If a message arrives from Cayenne, the terminal feed pauses 5'.
// Function that handles temperature adquisition from sensors, and publishing to Cayenne Dashboard.
void dealWithTemperatures() {
Serial.print(" Requesting temperatures...");
sensors.requestTemperatures(); // Send the command to get temperatures of all devices on the bus.
// Get the temperature value of sensor with hex address Probe01
tempDallasProbe1 = sensors.getTempC(Probe01);
// Construct the mqtt message following Cayenne's rules, according to the Docs..
// Send Sensor data -> Topic: v1/username/things/clientID/data/channel
// (*** Still need to optimize the use of strings in this part!!! ***)
String stringOne = "temp,c=";
//using a float rounded to 2 decimal places.
String stringTwo = String(tempDallasProbe1, 2);
// Concatenate the two previous strings into mqtt_message.
String mqtt_message = String(stringOne + stringTwo);
// Convert the string into a Char Array
mqtt_message.toCharArray(msg, 20);
Serial.print("Publish message: ");
// Finally! Publish the temperature to Cayenne Dashboard, Channel 10.
client.publish(MQTT_TOPIC_TPROBE_INT, msg);
You can’t perform that action at this time.