#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <MQTT.h>
#include <HTTPClient.h>
#include <DHT.h>
WiFiClient net;
MQTTClient mqtt;
unsigned long lastMillis = 0;
// LED pin mapping
const int LED1_PIN = 14;
const int LED2_PIN = 12;
const int LED3_PIN = 13;
// DHT22 sensor settings
#define DHTPIN 27
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
// Device identification
const char* deviceName = "Wokwi-ESP32";
// Google Apps Script URL - REPLACE WITH YOUR URL
const char* googleSheetsScriptUrl = "https://script.google.com/macros/s/AKfycbyWdegZWrTjn_Z-MgafLmLo9GICarMfLopLNvrJA2m3dziOOnAOUxukgXNpiHkJX0Gw/exec";
// Sensor reading intervals
unsigned long lastSensorRead = 0;
const unsigned long sensorReadInterval = 5000; // Read sensor every 5 seconds
unsigned long lastGoogleSheetsLog = 0;
const unsigned long googleSheetsLogInterval = 600000; // Log to sheets every 60 seconds
// Store latest sensor readings
float currentTemperature = 0;
float currentHumidity = 0;
// Flag for first reading
bool firstReadingComplete = false;
void connectWiFi() {
Serial.print("Connecting to Wi-Fi ");
WiFi.begin("Wokwi-GUEST", "", 6);
while (WiFi.status() != WL_CONNECTED) {
delay(250);
Serial.print(".");
}
Serial.println(" connected!");
}
void connectMQTT() {
Serial.print("Connecting to MQTT broker ");
while (!mqtt.connect("moltbot-wokwi-esp32", "ariffin", "password")) {
Serial.print(".");
delay(250);
}
Serial.println(" connected!");
Serial.println();
// Subscribe to the control topic
mqtt.subscribe("moltbot-wokwi-esp32/control");
}
void messageReceived(String &topic, String &payload) {
Serial.println("incoming: " + topic + " - " + payload);
if (topic == "moltbot-wokwi-esp32/control") {
// Parse payload format: "gpio,state"
int commaIndex = payload.indexOf(',');
if (commaIndex > 0) {
int gpio = payload.substring(0, commaIndex).toInt();
int state = payload.substring(commaIndex + 1).toInt();
Serial.print("GPIO: ");
Serial.print(gpio);
Serial.print(" State: ");
Serial.println(state);
// Control the LED based on GPIO pin
digitalWrite(gpio, state);
} else {
Serial.println("Invalid payload format. Expected: gpio,state");
}
}
}
void sendToGoogleSheets(float temperature, float humidity) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
// Use WiFiClientSecure for HTTPS
WiFiClientSecure client;
client.setInsecure(); // Skip certificate validation for simplicity
http.begin(client, googleSheetsScriptUrl);
http.addHeader("Content-Type", "application/json");
// Create JSON payload with device name
String jsonPayload = "{\"device\":\"" + String(deviceName) +
"\",\"temperature\":" + String(temperature, 2) +
",\"humidity\":" + String(humidity, 2) + "}";
Serial.println("==== Log to Google Sheets ====");
Serial.println(jsonPayload);
int httpResponseCode = http.POST(jsonPayload);
if (httpResponseCode > 0) {
String response = http.getString();
Serial.print("✓ HTTP Response code: ");
Serial.println(httpResponseCode);
// Only print response if it's a success (200-299)
if (httpResponseCode >= 200 && httpResponseCode < 300) {
Serial.print("Response: ");
Serial.println(response);
} else {
Serial.println("Note: Redirect or error response (see code above)");
}
} else {
Serial.print("✗ Error sending data: ");
Serial.println(httpResponseCode);
}
http.end();
} else {
Serial.println("✗ WiFi disconnected, cannot send data");
}
}
void readSensor() {
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// Check if readings are valid
if (isnan(humidity) || isnan(temperature)) {
Serial.println("✗ Failed to read from DHT sensor!");
return;
}
// Update current readings
currentTemperature = temperature;
currentHumidity = humidity;
Serial.println("======== DHT22 Reading =======");
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" °C");
Serial.print("Humidity: ");
Serial.print(humidity);
Serial.println(" %");
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.println("Hello, Moltbot ESP32!");
Serial.print("Device Name: ");
Serial.println(deviceName);
// Initialize LED pins
pinMode(LED1_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
pinMode(LED3_PIN, OUTPUT);
// Turn off all LEDs initially
digitalWrite(LED1_PIN, LOW);
digitalWrite(LED2_PIN, LOW);
digitalWrite(LED3_PIN, LOW);
// Initialize DHT22 sensor
dht.begin();
Serial.println("DHT22 sensor initialized");
// Connect to Wokwi's Wi-Fi
connectWiFi();
mqtt.begin("mqtt.ariffin.cc", net);
mqtt.onMessage(messageReceived);
// Connect to MQTT Broker
connectMQTT();
Serial.println("======== ESP32 Ready =========");
Serial.println("- LED control via MQTT");
Serial.println("- DHT22 sensor logging to Google Sheets");
Serial.println("- Reading sensor every 5 seconds");
Serial.println("- Logging to sheets every 60 seconds");
Serial.println();
// Wait 2 seconds for sensor to stabilize, then take first reading
delay(2000);
readSensor();
// Send first reading immediately
if (!isnan(currentTemperature) && !isnan(currentHumidity)) {
sendToGoogleSheets(currentTemperature, currentHumidity);
firstReadingComplete = true;
lastGoogleSheetsLog = millis(); // Reset sheet log timer
}
}
void loop() {
delay(10); // this speeds up the simulation
mqtt.loop();
delay(10); // <- fixes some issues with WiFi stability
// Maintain WiFi connection
if (WiFi.status() != WL_CONNECTED) {
connectWiFi();
}
// Maintain MQTT connection
if (!mqtt.connected()) {
connectMQTT();
}
unsigned long currentMillis = millis();
// Read sensor every 5 seconds
if (currentMillis - lastSensorRead >= sensorReadInterval) {
lastSensorRead = currentMillis;
readSensor();
}
// Log to Google Sheets every 60 seconds (after first reading)
if (firstReadingComplete && (currentMillis - lastGoogleSheetsLog >= googleSheetsLogInterval)) {
lastGoogleSheetsLog = currentMillis;
// Only send if we have valid readings
if (!isnan(currentTemperature) && !isnan(currentHumidity)) {
sendToGoogleSheets(currentTemperature, currentHumidity);
}
}
}