IoT Weather Station with Cloud Integration using esp 32

ESP32 IoT Weather Station with Cloud Integration | MakeMindz
☁️ Wokwi ESP32
☁️ ESP32 IoT Project · Advanced Level

IoT Weather Station
with Cloud Integration

A professional-grade weather station running on ESP32 — 6 sensors, OLED local display, live web dashboard with auto-refresh, and automatic ThingSpeak cloud logging. Simulated 100% in Wokwi.

🎓 Advanced ⏱️ ~60 min 📡 ESP32 🌡️ DHT22 + BMP280 ☁️ ThingSpeak Cloud 🌐 Web Dashboard

🖥️ Platform: Wokwi — Free ESP32 Simulation, No Installation

Paste diagram.json + code, press Play — full Wi-Fi web dashboard runs in your browser instantly.

🔗 wokwi.com →
00

Project Overview

What You'll Build
ESP32 IoT Weather Station with cloud integration showing OLED display, sensors, and web dashboard in Wokwi simulation
ESP32 IoT Weather Station — 6 sensors + OLED display + web dashboard + ThingSpeak cloud logging

This project simulates a professional IoT weather monitoring system — the kind used in smart cities and agricultural monitoring. The ESP32 reads 6 sensors simultaneously, displays data locally on an OLED, serves a beautiful web dashboard over Wi-Fi, and uploads data to the ThingSpeak cloud every 20 seconds.

ThingSpeak CloudAuto-upload every 20s with 6 data fields
Web DashboardBeautiful gradient UI with 5-second auto-refresh
Data HistoryTracks last 50 readings in memory
Auto Weather DetectionDetermines Sunny/Rainy/Cloudy/Hot/Cold automatically
RESTful JSON APIEndpoints: /data, /history, /api/weather
OLED Local DisplayReal-time readings on 128×64 SSD1306 screen
Responsive DesignWeb dashboard works on mobile and desktop
Non-Blocking Loopmillis() timing — sensor read every 2s, cloud every 20s

Auto Weather Condition Detection

☀️Sunny
Light >80%
🌧️Rainy
Rain >60%
🌦️Drizzle
Rain >30%
☁️Cloudy
Light <20%
💧Humid
Hum >80%
🔥Hot
Temp >30°C
❄️Cold
Temp <15°C
🌤️Clear
Default
01

6 Sensors & Components

Step 1

All components are virtual in Wokwi — no hardware shopping needed. Here's what each sensor measures:

🌡️

DHT22

Temperature & Humidity sensor (−40° to 80°C)

Pin D15
🎚️

BMP280

Pressure (hPa) & Altitude (metres) via I²C

I²C 0x76
☀️

Light Sensor

Brightness level 0–100% (potentiometer in Wokwi)

Pin D34
🌧️

Rain Sensor

Precipitation % detection (potentiometer in Wokwi)

Pin D35
📟

OLED SSD1306

128×64 local display — all readings at once

I²C 0x3C
💡

Status LED

Blue LED blinks on every sensor read cycle

Pin D2
02

Circuit Wiring Reference

Step 2

If you paste diagram.json (Step 3), wiring is automatic. This table is for manual reference.

ComponentPinESP32Wire
DHT22VCC3.3VRed
DHT22GNDGNDBlack
DHT22SDA (Data)D15Green
BMP280VCC3.3VRed
BMP280SDAD21Blue
BMP280SCLD22Yellow
OLED SSD1306SDAD21Blue (shared I²C)
OLED SSD1306SCLD22Yellow (shared I²C)
Light Sensor (Pot)SIGD34Orange
Rain Sensor (Pot)SIGD35Purple
Blue LED → 220ΩAnode (+)D2Blue
💡

BMP280 and OLED share the same I²C bus (SDA: D21, SCL: D22). BMP280 uses address 0x76, OLED uses 0x3C — no conflict since they have different addresses.

03

Wokwi Setup — Quick Start

Step 3 · 3 Minutes
💡

Wokwi is free — no account needed to start. Go to wokwi.com, create a new ESP32 project, then paste the files below.

1

🌐 Create New ESP32 Project

  • Go to wokwi.com in any modern browser
  • Click "New Project" → select "ESP32" (not Arduino UNO)
  • You'll see a blank canvas with the ESP32 DevKit placed
💡

Create a free Wokwi account to save your project and share the simulation link with your teacher or classmates!

2

📋 Paste diagram.json — Auto-Wires All Components

  • Click the "diagram.json" tab next to sketch.ino
  • Select all existing text and delete it completely
  • Paste the complete JSON below and press Ctrl+S
  • All 8 components appear fully wired ✅
⚠️

Copy the ENTIRE JSON — starts with { ends with }. Any missing bracket causes a parse error.

diagram.json — paste into Wokwi
{
  "version": 1,
  "author": "ESP32 IoT Weather Station",
  "editor": "wokwi",
  "parts": [
    { "type": "wokwi-esp32-devkit-v1", "id": "esp",  "top": 0,      "left": 0,     "attrs": {} },
    { "type": "wokwi-dht22",         "id": "dht1", "top": -86.4, "left": 143.4, "attrs": { "temperature": "24", "humidity": "60" } },
    { "type": "wokwi-bmp280",        "id": "bmp1", "top": -105.6,"left": 249.6, "attrs": { "i2cAddress": "0x76" } },
    { "type": "wokwi-ssd1306",       "id": "oled1","top": 144,   "left": 288,   "attrs": { "i2cAddress": "0x3C" } },
    { "type": "wokwi-potentiometer", "id": "ldr1", "top": -19.2, "left": 364.8, "rotate": 180, "attrs": { "label": "Light Sensor" } },
    { "type": "wokwi-potentiometer", "id": "rain1","top": 96,    "left": 364.8, "rotate": 180, "attrs": { "label": "Rain Sensor"  } },
    { "type": "wokwi-led",          "id": "led1", "top": -124.8,"left": 470.4, "attrs": { "color": "blue", "lightColor": "blue" } },
    { "type": "wokwi-resistor",    "id": "r1",   "top": -67.2, "left": 470.4, "rotate": 90,  "attrs": { "value": "220" } }
  ],
  "connections": [
    [ "esp:TX0",   "$serialMonitor:RX", "", [] ],
    [ "esp:RX0",   "$serialMonitor:TX", "", [] ],
    [ "dht1:VCC", "esp:3V3",    "red",    ["v0"] ],
    [ "dht1:GND", "esp:GND.1", "black",  ["v0"] ],
    [ "dht1:SDA", "esp:D15",   "green",  ["v0"] ],
    [ "bmp1:VCC", "esp:3V3",    "red",    ["v0"] ],
    [ "bmp1:GND", "esp:GND.1", "black",  ["v0"] ],
    [ "bmp1:SDA", "esp:D21",   "blue",   ["v0"] ],
    [ "bmp1:SCL", "esp:D22",   "yellow", ["v0"] ],
    [ "oled1:VCC","esp:3V3",    "red",    ["h0"] ],
    [ "oled1:GND","esp:GND.2", "black",  ["h0"] ],
    [ "oled1:SDA","esp:D21",   "blue",   ["h0"] ],
    [ "oled1:SCL","esp:D22",   "yellow", ["h0"] ],
    [ "ldr1:GND", "esp:GND.1", "black",  ["v0"] ],
    [ "ldr1:VCC", "esp:3V3",    "red",    ["v0"] ],
    [ "ldr1:SIG", "esp:D34",   "orange", ["v0"] ],
    [ "rain1:GND","esp:GND.2", "black",  ["v0"] ],
    [ "rain1:VCC","esp:3V3",    "red",    ["v0"] ],
    [ "rain1:SIG","esp:D35",   "purple", ["v0"] ],
    [ "led1:A",   "esp:D2",    "blue",   ["v0"] ],
    [ "led1:C",   "r1:1",      "blue",   ["v0"] ],
    [ "r1:2",     "esp:GND.1", "black",  ["v0"] ]
  ],
  "dependencies": {}
}
3

📚 Add Libraries File

Create a file called libraries.txt in Wokwi (click the "+" icon next to file tabs) and paste these lines:

libraries.txt
DHT sensor library
Adafruit BMP280 Library
Adafruit SSD1306
Adafruit GFX Library
💡

Wokwi auto-downloads all libraries when you start the simulation. WiFi, WebServer, and HTTPClient are built into the ESP32 core — no need to list them.

4

▶ Paste Code & Press Play

  • Click sketch.ino, delete default code, paste the complete code from Section 04
  • Press the green ▶ Play button
  • Watch the Serial Monitor — it will print the ESP32's local IP address
  • Click the IP address link in Wokwi's Serial Monitor to open the live web dashboard!
⚠️

The WiFi SSID in the code is "Wokwi-GUEST" (no password) — this is Wokwi's built-in simulated Wi-Fi network. Don't change it for the simulation.

Free Simulation

Open ESP32 Simulation on Wokwi

Create a new ESP32 project and paste the files above, or explore existing ESP32 projects in the Wokwi gallery.

Open Wokwi — ESP32
04

Complete Arduino Code — Explained

Step 4

Paste this into sketch.ino in Wokwi. The code is organized into logical sections with explanations.

① Includes, Pins, WiFi & ThingSpeak Config

weather_station.ino — Part 1/4
/*
 * ESP32 IoT Weather Station with Cloud Integration
 * MakeMindz.com | Wokwi ESP32 Simulation
 * Sensors: DHT22, BMP280, Light (LDR), Rain
 * Outputs: OLED display, Web Dashboard, ThingSpeak Cloud
 */

#include <WiFi.h>
#include <WebServer.h>
#include <HTTPClient.h>
#include <DHT.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_BMP280.h>

// ── WiFi (Wokwi-GUEST = Wokwi's built-in simulated network) ──
const char* ssid     = "Wokwi-GUEST";
const char* password = "";

// ── ThingSpeak Cloud ──────────────────────────────────────────
const char* thingSpeakServer = "api.thingspeak.com";
String thingSpeakAPIKey = "YOUR_API_KEY_HERE";   // ← Replace with yours
const long thingSpeakChannel = 123456;             // ← Replace with your channel ID

// ── Pin Definitions ───────────────────────────────────────────
#define DHT_PIN   15
#define LDR_PIN   34    // Analog — light sensor
#define RAIN_PIN  35    // Analog — rain sensor
#define LED_PIN   2     // Built-in LED (blue)
#define DHT_TYPE  DHT22

// ── Library Objects ───────────────────────────────────────────
DHT dht(DHT_PIN, DHT_TYPE);
Adafruit_BMP280 bmp;
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
WebServer server(80);

// ── Weather Data Structure ────────────────────────────────────
struct WeatherData {
  float  temperature, humidity, pressure, altitude;
  int    lightLevel, rainLevel;
  String weatherCondition;
  unsigned long timestamp;
} currentWeather;

// ── Timing (non-blocking with millis()) ───────────────────────
unsigned long lastSensorRead   = 0;
unsigned long lastCloudUpload  = 0;
const long    sensorInterval   = 2000;   // Read every 2s
const long    cloudInterval    = 20000;  // Upload every 20s

// ── History (last 50 readings) ────────────────────────────────
const int maxPoints = 50;
float tempHistory[50], humidHistory[50];
int   dataIndex = 0;
bool  cloudConnected = false;
int   uploadCount    = 0;

② setup() — Boot, WiFi & Sensor Init

weather_station.ino — Part 2/4
void setup() {
  Serial.begin(115200);
  pinMode(LED_PIN, OUTPUT);

  // DHT22
  dht.begin();

  // BMP280 — I2C address 0x76
  if (!bmp.begin(0x76)) {
    Serial.println("BMP280 not found!");
  } else {
    bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,
                   Adafruit_BMP280::SAMPLING_X2,
                   Adafruit_BMP280::SAMPLING_X16,
                   Adafruit_BMP280::FILTER_X16,
                   Adafruit_BMP280::STANDBY_MS_500);
  }

  // OLED — I2C address 0x3C
  if (display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    display.clearDisplay();
    display.setTextSize(1); display.setTextColor(SSD1306_WHITE);
    display.setCursor(0, 0);
    display.println("Weather Station");
    display.println("Initializing...");
    display.display(); delay(2000);
  }

  connectWiFi();    // Connects to Wokwi-GUEST

  // Register web server routes
  server.on("/",            handleRoot);
  server.on("/data",        handleData);
  server.on("/history",     handleHistory);
  server.on("/api/weather", handleAPIWeather);
  server.begin();

  readSensors();
  updateDisplay();
  Serial.println("=== Weather Station Ready ===");
}

void connectWiFi() {
  WiFi.begin(ssid, password);
  display.clearDisplay(); display.setCursor(0,0);
  display.println("Connecting WiFi..."); display.display();
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500); Serial.print("."); attempts++;
  }
  if (WiFi.status() == WL_CONNECTED) {
    Serial.println("\nConnected! IP: " + WiFi.localIP().toString());
    display.clearDisplay(); display.setCursor(0,0);
    display.println("WiFi Connected!");
    display.print("IP: "); display.println(WiFi.localIP());
    display.display(); delay(2000);
  }
}

③ loop(), Sensor Reading & Cloud Upload

weather_station.ino — Part 3/4
void loop() {
  server.handleClient();
  unsigned long now = millis();

  // Read all sensors every 2 seconds
  if (now - lastSensorRead >= sensorInterval) {
    lastSensorRead = now;
    readSensors();
    updateDisplay();
    blinkLED();
  }

  // Upload to ThingSpeak every 20 seconds
  if (now - lastCloudUpload >= cloudInterval) {
    lastCloudUpload = now;
    uploadToCloud();
  }
}

void readSensors() {
  currentWeather.temperature = dht.readTemperature();
  currentWeather.humidity    = dht.readHumidity();
  currentWeather.pressure    = bmp.readPressure() / 100.0F;  // Pa → hPa
  currentWeather.altitude    = bmp.readAltitude(1013.25);

  int ldrRaw  = analogRead(LDR_PIN);
  int rainRaw = analogRead(RAIN_PIN);
  currentWeather.lightLevel = map(ldrRaw,  0, 4095, 0,   100);
  currentWeather.rainLevel  = map(rainRaw, 0, 4095, 100, 0);  // Inverted
  currentWeather.timestamp  = millis();
  currentWeather.weatherCondition = determineCondition();

  if (isnan(currentWeather.temperature) || isnan(currentWeather.humidity)) {
    currentWeather.temperature = currentWeather.humidity = 0;
  }
  tempHistory[dataIndex]  = currentWeather.temperature;
  humidHistory[dataIndex] = currentWeather.humidity;
  dataIndex = (dataIndex + 1) % maxPoints;
}

String determineCondition() {
  if      (currentWeather.rainLevel  > 60) return "Rainy";
  else if (currentWeather.rainLevel  > 30) return "Drizzle";
  else if (currentWeather.humidity   > 80) return "Humid";
  else if (currentWeather.lightLevel < 20) return "Cloudy";
  else if (currentWeather.lightLevel > 80) return "Sunny";
  else if (currentWeather.temperature > 30) return "Hot";
  else if (currentWeather.temperature < 15) return "Cold";
  else                                        return "Clear";
}

void uploadToCloud() {
  if (WiFi.status() != WL_CONNECTED) { cloudConnected = false; return; }
  HTTPClient http;
  String url = "http://" + String(thingSpeakServer) + "/update?api_key=" + thingSpeakAPIKey;
  url += "&field1=" + String(currentWeather.temperature);
  url += "&field2=" + String(currentWeather.humidity);
  url += "&field3=" + String(currentWeather.pressure);
  url += "&field4=" + String(currentWeather.lightLevel);
  url += "&field5=" + String(currentWeather.rainLevel);
  url += "&field6=" + String(currentWeather.altitude);
  http.begin(url);
  int code = http.GET();
  if (code == 200) { cloudConnected = true; uploadCount++; Serial.println("✓ Cloud upload OK"); }
  http.end();
}

void updateDisplay() {
  display.clearDisplay();
  display.setTextSize(1); display.setCursor(0, 0);
  display.println("WEATHER STATION");
  display.drawLine(0, 9, 128, 9, SSD1306_WHITE);
  display.setCursor(0, 12); display.print("Temp: "); display.print(currentWeather.temperature, 1); display.println(" C");
  display.setCursor(0, 22); display.print("Hum:  "); display.print(currentWeather.humidity, 1); display.println(" %");
  display.setCursor(0, 32); display.print("Press:"); display.print(currentWeather.pressure, 0); display.println("hPa");
  display.setCursor(0, 42); display.print("Light:"); display.print(currentWeather.lightLevel); display.println("%");
  display.setCursor(0, 52); display.print("Status:"); display.println(currentWeather.weatherCondition);
  display.display();
}

void blinkLED() { digitalWrite(LED_PIN, HIGH); delay(50); digitalWrite(LED_PIN, LOW); }

④ Web Server Handlers — Dashboard & JSON API

weather_station.ino — Part 4/4
// ── Main Dashboard (/) — gradient card UI, auto-refresh 5s ──
void handleRoot() {
  String html = "<!DOCTYPE html><html><head>"
    "<meta name='viewport' content='width=device-width,initial-scale=1'>"
    "<meta http-equiv='refresh' content='5'>"   // Auto-refresh every 5s
    "<style>body{font-family:Arial;background:linear-gradient(135deg,#667eea,#764ba2);"
    "margin:0;padding:20px;color:#fff}.container{max-width:900px;margin:0 auto}"
    "h1{text-align:center;font-size:2.2em;margin-bottom:8px}"
    ".grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:16px;margin:20px 0}"
    ".card{background:rgba(255,255,255,.15);backdrop-filter:blur(10px);padding:20px;"
    "border-radius:14px;border:1px solid rgba(255,255,255,.2)}"
    ".value{font-size:2.4em;font-weight:700;margin:8px 0}"
    ".icon{font-size:2em}.status{text-align:center;margin-top:16px;"
    "background:rgba(255,255,255,.15);padding:14px;border-radius:10px}"
    "@media(max-width:600px){.grid{grid-template-columns:1fr}}</style></head><body>";

  html += "<div class='container'><h1>🌤️ IoT Weather Station</h1>";
  html += "<p style='text-align:center;opacity:.8'>Auto-refreshes every 5 seconds</p>";
  html += "<div class='card' style='text-align:center;font-size:1.5em;margin-bottom:16px'>"
        + getWeatherIcon() + " <strong>" + currentWeather.weatherCondition + "</strong></div>";
  html += "<div class='grid'>";

  // 6 sensor cards
  String sensors[6][3] = {
    {"🌡️","Temperature",  String(currentWeather.temperature,1)+" °C"},
    {"💧","Humidity",     String(currentWeather.humidity,1)+" %"},
    {"🎚️","Pressure",     String(currentWeather.pressure,0)+" hPa"},
    {"⛰️","Altitude",     String(currentWeather.altitude,0)+" m"},
    {"☀️","Light Level",  String(currentWeather.lightLevel)+" %"},
    {"🌧️","Rain Level",   String(currentWeather.rainLevel)+" %"}
  };
  for (int i=0; i<6; i++) {
    html += "<div class='card'><div class='icon'>"+sensors[i][0]+"</div>"
          + "<h3 style='opacity:.8'>"+sensors[i][1]+"</h3>"
          + "<div class='value'>"+sensors[i][2]+"</div></div>";
  }
  html += "</div><div class='status'>";
  html += cloudConnected ? "<span style='color:#4ade80'>☁️ Cloud Connected</span>"
                         : "<span style='color:#f87171'>☁️ Cloud Offline</span>";
  html += " · WiFi: " + WiFi.localIP().toString()
       + " · Uploads: " + String(uploadCount)
       + " · Uptime: " + String(millis()/1000) + "s</div></div></body></html>";
  server.send(200, "text/html", html);
}

String getWeatherIcon() {
  if (currentWeather.weatherCondition == "Rainy")   return "🌧️";
  if (currentWeather.weatherCondition == "Drizzle") return "🌦️";
  if (currentWeather.weatherCondition == "Sunny")   return "☀️";
  if (currentWeather.weatherCondition == "Cloudy")  return "☁️";
  if (currentWeather.weatherCondition == "Hot")     return "🔥";
  if (currentWeather.weatherCondition == "Cold")    return "❄️";
  return "🌤️";
}

// ── JSON API endpoints ──────────────────────────────────────
void handleData() {
  String json = "{";
  json += "\"temperature\":" + String(currentWeather.temperature,2) + ",";
  json += "\"humidity\":"    + String(currentWeather.humidity,2)    + ",";
  json += "\"pressure\":"    + String(currentWeather.pressure,2)    + ",";
  json += "\"altitude\":"    + String(currentWeather.altitude,2)    + ",";
  json += "\"light\":"       + String(currentWeather.lightLevel)     + ",";
  json += "\"rain\":"        + String(currentWeather.rainLevel)      + ",";
  json += "\"condition\":\"" + currentWeather.weatherCondition       + "\",";
  json += "\"cloudConnected\":" + String(cloudConnected ? "true" : "false") + "}";
  server.send(200, "application/json", json);
}

void handleHistory() {
  String json = "{\"temperature\":[";
  for (int i=0; i<maxPoints; i++) { json += String(tempHistory[i],1); if(i<maxPoints-1) json+=","; }
  json += "],\"humidity\":[";
  for (int i=0; i<maxPoints; i++) { json += String(humidHistory[i],1); if(i<maxPoints-1) json+=","; }
  json += "]}";
  server.send(200, "application/json", json);
}

void handleAPIWeather() { handleData(); }
05

ThingSpeak Cloud Setup

Optional but Powerful
☁️

ThingSpeak is a free IoT platform by MathWorks. It lets you collect, visualize, and analyze sensor data from anywhere in the world using MATLAB-powered charts.

ESP32 IoT Weather Station web dashboard showing temperature, humidity, pressure, altitude, light and rain cards
Web dashboard — auto-refreshes every 5 seconds with live data from all 6 sensors
  1. 1
    Create ThingSpeak account — go to thingspeak.com → click "Get Started For Free" → verify email
  2. 2
    Create a new Channel — Channels → My Channels → New Channel. Name it "ESP32 Weather Station"
  3. 3
    Enable 6 fields: Field 1: Temperature · Field 2: Humidity · Field 3: Pressure · Field 4: Light Level · Field 5: Rain Level · Field 6: Altitude → Click "Save Channel"
  4. 4
    Get your Write API Key — click the "API Keys" tab on your channel page. Copy the Write API Key (looks like: XXXXXXXXXXXXXXXX)
  5. 5
    Update the code — replace the two lines in Part 1 of the code:
Update in weather_station.ino
// Replace these two lines with your real ThingSpeak credentials:
String thingSpeakAPIKey  = "XXXXXXXXXXXXXXXX";  // ← Your Write API Key
const long thingSpeakChannel = 123456;          // ← Your Channel ID number
  1. 6
    Restart the simulation — open Serial Monitor. After Wi-Fi connects, look for: ✓ Cloud upload OK appearing every 20 seconds
  2. 7
    View your charts — go to ThingSpeak → Channels → My Channels → ESP32 Weather Station → you'll see live data charts for all 6 fields!
💡

ThingSpeak free plan allows 3 million messages per year (≈8,200/day). Uploading every 20 seconds = 4,320 messages/day — well within the free limit!

ThingSpeak cloud dashboard showing ESP32 weather station data charts
ThingSpeak cloud dashboard — auto-generated charts for each sensor field
06

Interactive Testing Guide

The Fun Part!

Press Play & Watch Serial Monitor

After pressing ▶ in Wokwi, the Serial Monitor will show boot messages, then print the local IP address once Wi-Fi connects. Click that IP address to open the live web dashboard!

⚠️

Compile error? Check that your libraries.txt has all 4 library names exactly as shown in Step 3. Wokwi is case-sensitive.

🌡️

Adjust DHT22 Temperature & Humidity

  • Click the DHT22 sensor in Wokwi — a popup shows sliders
  • Set temp to 35°C → condition changes to "Hot" on OLED and dashboard
  • Set temp to 10°C → condition changes to "Cold" + ❄️ icon
  • Set humidity to 85% → condition becomes "Humid"
☀️

Rotate Light & Rain Sensor Knobs

  • Rotate Light Sensor knob fully clockwise → "Sunny" ☀️
  • Rotate Light Sensor knob fully counter-clockwise → "Cloudy" ☁️
  • Rotate Rain Sensor knob to max → "Rainy" 🌧️ + watch rain % climb
  • Rotate partially → "Drizzle" 🌦️ at medium rain level
🌐

Explore the JSON API

The ESP32 serves 3 API endpoints you can call from the browser:

  • /data — current sensor readings as JSON
  • /history — last 50 temperature + humidity readings
  • /api/weather — same as /data (RESTful alias)
💡

Access these by appending to the IP address: e.g. 192.168.1.x/data. Use these endpoints to integrate with mobile apps or data dashboards!

07

More ESP32 & IoT Projects

MakeMindz Collection
🧠 MakeMindz

ESP32 IoT Weather Station with Cloud Integration · Wokwi Simulation

Simulate free at wokwi.com · All projects at makemindz.com

Comments

try for free