#include <WiFi.h>
#include <HTTPClient.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <DHT.h>
#include <math.h>
// Wi-Fi credentials
const char* ssid = "Wokwi-GUEST";
const char* password = "";
// MQTT settings
const char* mqtt_server = "mqtt.eclipseprojects.io";
const int mqtt_port = 1883;
const char* mqtt_weather_topic = "weather/data";
const char* mqtt_sensor_topic = "sensors/esp32";
// OpenWeatherMap
const char* apiKey = "0897ec6053fd70b586341d0cc5e0d88a";
const char* city = "Cape Town";
const char* countryCode = "ZA";
// DHT and thermistor setup
#define DHTPIN 26
#define DHTTYPE DHT22
#define THERMISTOR_PIN 34
DHT dht(DHTPIN, DHTTYPE);
// Clients
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);
// WiFi connection
void setupWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println(" connected.");
}
// MQTT reconnect
void reconnectMQTT() {
while (!mqttClient.connected()) {
Serial.print("Connecting to MQTT...");
if (mqttClient.connect("ESP32_Combined_Client")) {
Serial.println(" connected.");
} else {
Serial.print(" failed, rc=");
Serial.println(mqttClient.state());
delay(2000);
}
}
}
// Thermistor temperature reading
float readThermistorC() {
int analogValue = analogRead(THERMISTOR_PIN);
float voltage = analogValue * (3.3 / 4095.0);
float resistance = (3.3 * 10000.0 / voltage) - 10000.0;
float steinhart;
steinhart = resistance / 10000.0;
steinhart = log(steinhart);
steinhart /= 3950.0;
steinhart += 1.0 / (25.0 + 273.15);
steinhart = 1.0 / steinhart;
steinhart -= 273.15;
return steinhart;
}
// Fetch and publish weather data
void fetchWeather() {
String cityEncoded = "Cape%20Town";
String apiUrl = "http://api.openweathermap.org/data/2.5/weather?q=" + cityEncoded + "," + countryCode + "&appid=" + apiKey + "&units=metric";
HTTPClient http;
http.begin(apiUrl);
int httpCode = http.GET();
if (httpCode > 0) {
String payload = http.getString();
StaticJsonDocument<1024> doc;
DeserializationError error = deserializeJson(doc, payload);
if (!error) {
StaticJsonDocument<512> outDoc;
outDoc["city"] = city;
outDoc["country"] = countryCode;
outDoc["temp"] = doc["main"]["temp"];
outDoc["humidity"] = doc["main"]["humidity"];
outDoc["description"] = doc["weather"][0]["description"];
outDoc["wind"] = doc["wind"]["speed"];
char buffer[512];
serializeJson(outDoc, buffer);
mqttClient.publish(mqtt_weather_topic, buffer);
Serial.println("Published weather:");
Serial.println(buffer);
} else {
Serial.print("JSON error: ");
Serial.println(error.c_str());
}
} else {
Serial.print("HTTP error: ");
Serial.println(httpCode);
}
http.end();
}
// Read and publish local sensor data
void publishSensorData() {
float dhtTemp = dht.readTemperature();
float dhtHum = dht.readHumidity();
float thermistorTemp = readThermistorC();
if (isnan(dhtTemp) || isnan(dhtHum)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
String payload = "{";
payload += "\"dht22_temp\":" + String(dhtTemp, 1) + ",";
payload += "\"dht22_humidity\":" + String(dhtHum, 1) + ",";
payload += "\"thermistor_temp\":" + String(thermistorTemp, 1);
payload += "}";
mqttClient.publish(mqtt_sensor_topic, payload.c_str());
Serial.println("Published sensor data:");
Serial.println(payload);
}
void setup() {
Serial.begin(115200);
dht.begin();
setupWiFi();
mqttClient.setServer(mqtt_server, mqtt_port);
}
void loop() {
if (!mqttClient.connected()) {
reconnectMQTT();
}
mqttClient.loop();
// Get and send data
fetchWeather();
publishSensorData();
// Wait before next cycle
delay(60000); // Every 60 seconds
}