Currently I am designing system for temperature measuring based on ESP32. I want to use PubSubClient library for maintaining connection with Cayenne cloud. Unfortunately, my attempts to connect with cayenne cloud were unsuccessful. Has anyone succesfully connected to the Cayenne cloud using PubSubClient and could give some advice how to achieve connection? There is no problem with connection to WiFi network. I also attach the code used for connecting to Cayenne.
@adam, @shramik_salgaonkar - thank you for your replies. Unfortunately, I am still not able to connect to Cayenne - according to the PubSubClient API documentation, the client is disconnected(client.state() value is -1). Link to the API documentation is here: Arduino Client for MQTT
What could be the cause of such strange behaviour? For test purposes, I decided to check connectivity to Cayenne by using Cayenne API library. In this case, I was able to connect without problem. I attach the code after modifications, unfortunately there is still no progress, when it comes to communication by using PubSubClient.
// ---------- INLCUDE LIBRARIES ----------
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
// ---------- DEFINE CONSTANT VALUES ----------
#define MQTT_SERVER "mqtt.mydevices.com"
#define MQTT_SERVERPORT 1883
#define MQTT_USERNAME ""
#define MQTT_PASSWORD ""
#define CLIENT_ID ""
// 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 ----------
WiFiClient espClient; // Creates a client instance for the PubSubClient
PubSubClient client(espClient);
// ---------- DEFINE VARIABLES ----------
const char* ssid = ""; // WLAN-SSID (WiFi router)
const char* password = ""; // WLAN Password
// Define a datatype to store the mqtt message, up to 50 bytes.
char msg[50]; // 50 BYTES QUIZAS SEA MUCHO AL GAS, pero bueh
// -------------------- SETUP -------------------
void setup() {
// Initialize serial monitor for debugging purposes.
Serial.begin(9600);
Serial.println("DEBUG: Entering setup ");
// Attempt to connect to WiFi.
WiFi.begin(ssid, password);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(""); // Faltaria agregar que muestre el ip si no es estatico
Serial.println("WiFi connected");
// 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
client.setServer(MQTT_SERVER, MQTT_SERVERPORT);
// 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)
client.setCallback(mqttCallback);
Serial.println("DEBUG: Setup Done! ");
}
long timeStampNow;
long timeStampLastMsg = 0;
// -------------------- LOOOP -------------------
void loop() {
Serial.println("DEBUG: Entering main loop ");
// Check if the esp8266 is connected to the mqtt server.
if (!client.connected()) {
reconnect();
}
// If connected, perform PubSubClient housekeeping function.
client.loop();
// 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.
dealWithTemperatures();
}
delay(10);
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
if (client.connect(CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) {
Serial.println("connected");
// Once connected, resubscribe to the Dashboard on/off button topic.
// client.subscribe(MQTT_TOPIC_BTN_ONOFF);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
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(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
// Show the received message "stream" in the serial monitor.
Serial.print((char)payload[i]);
}
Serial.println();
// 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'.
delay(5000);
}
float x;
// Function that handles temperature adquisition from sensors, and publishing to Cayenne Dashboard.
void dealWithTemperatures() {
// Get the temperature value of sensor with hex address Probe01
x = 22.00;
// 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(x, 2);
// Concatenate the two previous strings into mqtt_message.
String mqtt_message = String(stringOne + stringTwo);
Serial.println(mqtt_message);
// Convert the string into a Char Array
mqtt_message.toCharArray(msg, 20);
Serial.print("Publish message: ");
Serial.println(msg);
// Finally! Publish the temperature to Cayenne Dashboard, Channel 10.
client.publish(MQTT_TOPIC_TPROBE_INT, msg);
}