ESP32 Temperature and Humidity Alerts via OpenClaw
After I built a basement water sensor with an ESP32 and OpenClaw, the next ask was obvious: "What about temperature and humidity?"
Server closet overheating. Wine cellar too dry. Grow tent too moist. Same pattern—cheap hardware, your webhook, your agent, your rules.
Security note: If your OpenClaw instance is accessible from the internet (not just your local network), make sure it's properly secured. 42,665 exposed instances were found in January 2026. Use Clawctl for automatic security hardening.
What You'll Need
| Component | Cost |
|---|---|
| ESP32 dev board | ~$6 |
| DHT22 (temp + humidity) | ~$4 |
| USB power | ~$3 |
| Total | ~$13 |
Same ESP32 stack as the water sensor. Add one wire for the DHT22.
Architecture
DHT22 → ESP32 → HTTP POST → OpenClaw Webhook → Agent (thresholds, schedules) → Slack / SMS / Email
You set the thresholds. You decide when to alert, when to log, and when to correlate (e.g. "high temp + business hours = page on-call").
Wiring
- DHT22 VCC → 3.3V
- DHT22 GND → GND
- DHT22 Data → GPIO 4 (or any digital pin)
- Pull-up: 10kΩ between Data and VCC (many boards have it built-in)
The Code
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <DHT.h>
#define DHTPIN 4
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
const char* ssid = "YOUR_WIFI";
const char* password = "YOUR_PASSWORD";
const char* webhookUrl = "https://your-tenant.clawctl.com/webhook/sensors";
const char* apiKey = "YOUR_API_KEY";
const float TEMP_HIGH = 32.0; // °C – alert above this
const float TEMP_LOW = 5.0; // °C – alert below this
const float HUMIDITY_HIGH = 80.0;
const unsigned long INTERVAL_MS = 60000; // 1 min
unsigned long lastSend = 0;
void setup() {
Serial.begin(115200);
dht.begin();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) delay(500);
}
void loop() {
if (millis() - lastSend < INTERVAL_MS) { delay(100); return; }
lastSend = millis();
float t = dht.readTemperature();
float h = dht.readHumidity();
if (isnan(t) || isnan(h)) { Serial.println("DHT read fail"); return; }
HTTPClient http;
http.begin(webhookUrl);
http.addHeader("Content-Type", "application/json");
http.addHeader("Authorization", String("Bearer ") + apiKey);
StaticJsonDocument<256> doc;
doc["device_id"] = "server-closet-01";
doc["temperature"] = round(t * 10) / 10.0;
doc["humidity"] = round(h * 10) / 10.0;
doc["temp_alert"] = (t > TEMP_HIGH || t < TEMP_LOW);
doc["humidity_alert"] = (h > HUMIDITY_HIGH);
doc["rssi"] = WiFi.RSSI();
String payload;
serializeJson(doc, payload);
int code = http.POST(payload);
http.end();
delay(100);
}
Libraries: DHT sensor library (Adafruit), ArduinoJson, HTTPClient (ESP32).
Agent Side: Thresholds and Actions
on_event: webhook.sensors
triggers:
- condition: "event.temp_alert == true"
actions:
- name: send_slack
params:
channel: "#ops"
text: "Server closet temp {{ event.temperature }}°C (device: {{ event.device_id }})"
- condition: "event.humidity_alert == true"
actions:
- name: send_sms
params:
to: "+1234567890"
message: "High humidity: {{ event.humidity }}% at {{ event.device_id }}"
- condition: "event.temp_alert == false && event.humidity_alert == false"
actions:
- name: log_reading
tool: database
params:
table: env_readings
data: { device: "{{ event.device_id }}", temp: "{{ event.temperature }}", humidity: "{{ event.humidity }}" }
Normal readings → log. Out of range → alert. One agent, many devices. Add more ESP32s with different device_id (e.g. wine-cellar-01, grow-tent-01) and reuse the same webhook.
Why Not Just IFTTT?
You could use a cloud rule engine. But then your thresholds and logic live in their UI, their rate limits, their subscription. With OpenClaw you own the logic, the logs, and the integrations (Slack, Twilio, PagerDuty, internal APIs). Same hardware. Full control.