/*
This project in based on exo2 thinkspeak example.
Find the original here,
https://wokwi.com/projects/381738103490740225
This example is about home automation. We have a room with a light and a fan.
2 LEDS depicting two outputs.
Light - Red LED
Fan - Green LED
Our DHT22 is there to take temperature and humidity reading of the room. Our user
may connect to thingspeak cloud and view the data directly.
Our user may send https commands to http or mqtt server directly to switch on/off
the light or fan.
We have used a virtuino IOT platform as front end and used mqtt to connect and manage all
device data.
*/
#include <WiFi.h>
#include <PubSubClient.h>
#include "DHTesp.h"
#include "ThingSpeak.h"
const int DHT_PIN = 18;
WiFiClient espClient;
PubSubClient client(espClient);
char ssid[] = "Wokwi-GUEST"; // Change this to your network SSID
char pass[] = ""; // Change this your network password
// MQTT broker settings and topics
const char* mqtt_server = "mqtt3.thingspeak.com";
// Published settings
const char* publishTopic = "channels/2557311/publish"; // Sensor data channel
// Subscribed settings Virtuino command 1
const char* subscribeTopicFor_Command_1 = "channels/2560873/subscribe/fields/field1"; //Output channel field 1
const char* subscribeTopicFor_Command_2 = "channels/2560873/subscribe/fields/field2"; //Output channel field 2
const char* mqtt_client_id = "ExYuJS8gGR4aFSU5LgcKAR8"; // MQTT client ID
const char* mqtt_username = "ExYuJS8gGR4aFSU5LgcKAR8"; // MQTT username
const char* mqtt_password = "blGuja6bjxnj22eo2bxFmY1j"; // MQTT password
const unsigned long postingInterval = 10L * 1000L;
const int Light_PIN = 32; // light connected here. +ve logic RED color LED
const int Fan_PIN = 33; // fan connected here. +ve logic GREEN color LED
DHTesp dhtSensor; // DHT
unsigned long lastUploadedTime = 0;
void setup_wifi() {
delay(10);
Serial.print("\nConnecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, pass);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
randomSeed(micros());
Serial.println("\nWiFi connected\nIP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
if (client.connect(mqtt_client_id,mqtt_username,mqtt_password)) {
Serial.println("connected");
client.subscribe(subscribeTopicFor_Command_1);
client.subscribe(subscribeTopicFor_Command_2);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying
delay(5000);
}
}
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
}
void setup() {
Serial.begin(9600);
while (!Serial)
delay(1);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
dhtSensor.setup(DHT_PIN, DHTesp::DHT22); // Initialize the DHT22 sensor
pinMode(Light_PIN, OUTPUT);
pinMode(Fan_PIN, OUTPUT);
delay(2000); // Add a delay after sensor initialization
}
void loop() {
if (!client.connected())
reconnect();
client.loop();
if (millis() - lastUploadedTime > postingInterval) {
float temperature = dhtSensor.getTemperature();
float humidity = dhtSensor.getHumidity();
if (!isnan(temperature) && !isnan(humidity)) {
publishMessage(publishTopic, temperature, humidity, true);
} else {
Serial.println("Invalid sensor readings. Skipping MQTT publish.");
}
lastUploadedTime = millis();
}
}
String toLowerCaseString(String str) {
String result = str;
result.toLowerCase();
return result;
}
//callback structure
void callback(char* topic, byte* payload, unsigned int length) {
Serial.println("Message arrived [" + String(topic) + "]");
String incomingMessage = "";
for (int i = 0; i < length; i++)
incomingMessage += (char)payload[i];
Serial.println("Payload: " + incomingMessage);
// Convert both topic and comparison string to lowercase for case-insensitive comparison
String lowerTopic = toLowerCaseString(String(topic));
String lowerField1 = toLowerCaseString("field1");
String lowerField2 = toLowerCaseString("field2");
if (lowerTopic.endsWith(lowerField1) || lowerTopic.endsWith(lowerField2)) {
// Process temperature (field1) or humidity (field2)
float value = incomingMessage.toFloat();
if (lowerTopic.endsWith(lowerField1)) {
digitalWrite(Light_PIN, value > 0 ? HIGH:LOW);
Serial.println("Light is turned " + String(value > 0 ? "On":"Off"));
// Add your logic for handling temperature (field1) here
} else if (lowerTopic.endsWith(lowerField2)) {
digitalWrite(Fan_PIN, value > 0 ? HIGH:LOW);
Serial.println("Fan is turned " + String(value > 0 ? "On":"Off"));
// Add your logic for handling humidity (field2) here
}
} else {
Serial.println("Unknown topic. Payload not processed.");
}
}
void publishMessage(const char* topic, float temperature, float humidity, boolean retained) {
String payload = "field1=" + String(temperature, 2) + "&field2=" + String(humidity, 2) + "&status=MQTTPUBLISH";
if (client.publish(topic, payload.c_str(), retained)) {
Serial.println("Message published [" + String(topic) + "]: " + payload);
} else {
Serial.println("Failed to publish message.");
}
}