- Multi-Hardware Support: Single codebase for:
- Heltec WiFi Kit 32 V3 (with OLED display)
- ESP32-C3 SuperMini (ultra-compact, headless)
- Generic ESP32 DevKits (standard boards)
- Multi-Sensor Support:
- Dual Dashboard Architecture:
- On-Device Dashboard: Real-time web interface served directly from the ESP32 (accessible via local IP)
- Central Server Dashboard: Historical data visualization with interactive charts (Flask + Chart.js)
- Multi-Device Management: Each sensor reports with unique MAC address identifier; central dashboard allows filtering by device
- WiFi Manager: Zero-config setup via captive portal (
Climate-Setup) β no hardcoded credentials4 - OTA Updates: Wirelessly update firmware over the network
- NTP Time Sync: Automatic time synchronization via local or public NTP servers
- Offline Capable: Continues measuring and displaying data without internet connection
- Asynchronous Architecture: Non-blocking web server ensures responsive dashboards even during measurements56
Features: OLED Display (128x64), BME680 environmental sensor Use Case: Standalone room monitor with live display
| BME680 Pin | Heltec V3 Pin | Notes |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SDA | GPIO 41 | I2C Bus 1 (avoids OLED conflict) |
| SCL | GPIO 42 | I2C Bus 1 |
Config Setup:
#define USE_DISPLAY
#define USE_BME680Features: Ultra-compact (22.5Γ18mm), low power, RISC-V architecture789 Use Case: Space-constrained installations, battery-powered projects
| AM2301A Pin | ESP32-C3 Pin | Notes |
|---|---|---|
| VCC (Red) | 3V3 or 5V | Power supply (3.3-6V supported) 2 |
| GND (Black) | GND | Ground |
| DATA (Yellow) | GPIO 8 | Digital single-wire protocol 10 |
Important: The AM2301A module typically includes an internal pull-up resistor. If using the bare sensor, add a 4.7kΞ© - 10kΞ© resistor between DATA and VCC.10
Config Setup:
#define SENSOR_TYPE_DHT
#define DHT_PIN 8
#define DHT_TYPE DHT21Features: Standard development board, headless operation Use Case: Cost-effective multi-room monitoring
| BME680 Pin | ESP32 Pin | Notes |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SDA | GPIO 21 | I2C Bus 0 (standard) |
| SCL | GPIO 22 | I2C Bus 0 |
Config Setup:
// Leave USE_DISPLAY commented out
#define USE_BME680Install the following libraries via Tools β Manage Libraries:
| Library | Author | Purpose |
|---|---|---|
Adafruit BME680 Library |
Adafruit | BME680 sensor driver |
Adafruit Unified Sensor |
Adafruit | Dependency for BME680 |
DHT sensor library |
Adafruit | AM2301A/DHT21 driver 2 |
Adafruit SSD1306 |
Adafruit | OLED display driver (Heltec only) |
Adafruit GFX Library |
Adafruit | Graphics library (Heltec only) |
WiFiManager |
tzapu | Captive portal for WiFi config |
ESPAsyncWebServer |
me-no-dev | Asynchronous web server 54 |
AsyncTCP |
me-no-dev | Async TCP library for ESP32 5 |
Note: When installing DHT sensor library, select "Install All" when prompted for dependencies.
The firmware automatically adapts based on config.h definitions:
// For Heltec V3 with display + BME680:
#define USE_DISPLAY
#define USE_BME680
// For ESP32-C3 SuperMini with DHT:
#define SENSOR_TYPE_DHT
#define DHT_PIN 8
#define DHT_TYPE DHT21
// For generic ESP32 with BME680 (no display):
#define USE_BME680const char* SERVER_URL = "http://192.168.1.50:5000/post-data";
const char* API_KEY = "MeinGeheimesIoTKennwort123"; // Must match server configconst unsigned long UPDATE_INTERVAL = 30000; // Measure every 30 seconds
const unsigned long SEND_INTERVAL = 60000; // Upload every 60 seconds- Flash Firmware:
- Connect ESP32 via USB
- Select correct board in Arduino IDE:
- Heltec:
Heltec WiFi Kit 32 V3 - C3:
ESP32C3 Dev Module - Generic:
ESP32 Dev Module
- Heltec:
- Upload sketch
- WiFi Configuration:
- On first boot, device creates AP:
Climate-Setup(Password:password) - Connect with smartphone/laptop
- Captive portal opens automatically (or navigate to
192.168.4.1) - Enter your WiFi credentials
- Device reboots and connects
- On first boot, device creates AP:
- Access On-Device Dashboard:
- Check Serial Monitor for assigned IP (e.g.,
192.168.1.45) - Open browser:
http://192.168.1.45 - View live sensor data with auto-refresh
- Check Serial Monitor for assigned IP (e.g.,
- Subsequent Updates (OTA):
- In Arduino IDE:
Tools β Port β Network Port β [Your Device] - Upload wirelessly using password from
config.h
- In Arduino IDE:
- Clone repository:
git clone <your-repo-url>
cd <repo-folder>- Install dependencies:
pip install flask- Configure
config.py:
API_KEY = "MeinGeheimesIoTKennwort123" # Must match ESP32
DB_NAME = "klima.db"
HOST = "0.0.0.0" # Listen on all interfaces
PORT = 5000
TIME_FORMAT_12H = False # Set True for US time formatpython3 server.py- Central Dashboard:
http://localhost:5000 - Device Selector: Dropdown menu to filter by sensor MAC address
- Time Ranges: 1 Hour / 24 Hours / 7 Days / 30 Days
- API Endpoints:
GET /api/history?range=day&device_id=XX:XX:XX:XX:XX:XX- Filtered historical dataGET /api/devices- List of all registered sensorsPOST /post-data- Data ingestion endpoint (used by ESP32)
- Device Identification: Each ESP32 reports its MAC address as
device_idin every upload - Database Structure:
measurementstable includesdevice_idcolumn for filtering - Dashboard Filtering: Dropdown menu shows all active sensors; select one to view its data
- Automatic Discovery: New devices appear in the dropdown as soon as they upload their first measurement
CREATE TABLE measurements (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
device_id TEXT, -- MAC address (e.g., "AA:BB:CC:DD:EE:FF")
temperature REAL,
humidity REAL,
pressure REAL, -- 0 for DHT sensors
gas_resistance REAL -- 0 for DHT sensors
);View last 5 entries (with device IDs):
python3 -c "import sqlite3, config; c = sqlite3.connect(config.DB_NAME); cursor = c.cursor(); cursor.execute('SELECT timestamp, device_id, temperature, humidity FROM measurements ORDER BY id DESC LIMIT 5'); print(*cursor.fetchall(), sep='\n')"List all registered devices:
python3 -c "import sqlite3, config; c = sqlite3.connect(config.DB_NAME); cursor = c.cursor(); cursor.execute('SELECT DISTINCT device_id FROM measurements'); print(*cursor.fetchall(), sep='\n')"Reset database (clears all data):
python3 -c "import sqlite3, config; c = sqlite3.connect(config.DB_NAME); c.execute('DROP TABLE IF EXISTS measurements'); c.commit(); print('Database reset complete.')"Export to CSV:
sqlite3 -header -csv klima.db "SELECT * FROM measurements" > export.csv- Live sensor values with color-coded cards
- Air quality status indicator (for BME680)
- Device MAC address display
- WiFi signal strength (RSSI)
- Auto-refresh every 2 seconds
- Dark theme optimized for OLED displays
- Interactive Chart.js time-series graphs
- Temperature, humidity, pressure, air quality trends
- Multi-device selector dropdown
- Responsive design for mobile/desktop
- Configurable time ranges with data aggregation for long periods
- 12h/24h time format support
- API Key: Change default
API_KEYin bothconfig.handconfig.pybefore deployment - OTA Password: Update
OTA_PASSinconfig.hto prevent unauthorized firmware updates - Network Exposure: Server binds to
0.0.0.0by default β restrict via firewall if needed
"DHT.h: No such file or directory"
β Install DHT sensor library by Adafruit via Library Manager
ESP32-C3 not showing display output β Correct behavior β C3 variant has no display. Access dashboard via IP address
BME680 shows 0 values on C3 β Correct behavior β C3 uses DHT sensor. Pressure/Gas fields are dummy values
Server returns 403 "Invalid API Key"
β Ensure API_KEY matches exactly in config.h and config.py
OTA not found in Arduino IDE β Wait 30 seconds after boot, refresh network ports list
Open Source. Free to use, modify, and distribute.
Built with the following third-party libraries:
- Adafruit Sensor Libraries β BME680, DHT, SSD1306, GFX (MIT License)
- WiFiManager by tzapu (MIT License)
- ESPAsyncWebServer by me-no-dev (LGPL 2.1)
- AsyncTCP by me-no-dev (LGPL 2.1)
- Flask β Python web framework (BSD-3-Clause)
- Chart.js β JavaScript charting library (MIT License)
Footnotes
-
https://github.com/sidharthmohannair/Tutorial-ESP32-C3-Super-Mini β©
-
https://www.hellasdigital.gr/electronics/sensors/temperature-sensors/dht21-am2301a-digital-temperature-humidity-sensor-module-with-sht11-sht15-for-arduino/?sl=en β© β©2 β©3 β©4
-
https://hobbycomponents.com/sensors/840-dht21-am2301-temperature-humidity-sensor β© β©2
-
https://github.com/arjenhiemstra/ESPAsyncWebServer β© β©2 β©3
-
https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/library.json β©
-
https://mischianti.org/esp32-c3-super-mini-high-resolution-pinout-datasheet-and-specs/ β© β©2
-
https://www.studiopieters.nl/esp32-c3-super-mini-pinout/ β© β©2
-
https://www.espboards.dev/esp32/esp32-c3-super-mini/ β© β©2
-
https://randomnerdtutorials.com/getting-started-esp32-c3-super-mini/ β©
-
https://forum.arduino.cc/t/esp32-c3-supermini-pinout/1189850 β©
-
https://www.sudo.is/docs/esphome/boards/esp32c3supermini/ β©
-
https://docs.cirkitdesigner.com/component/eafd4036-104c-43c2-b73d-1a42eae22d03/esp32-c3-supermini β©
-
https://www.roboter-bausatz.de/p/am2301-dht21-digitaler-temperatursensor β©