Most IoT tutorials stop at "your sensor is sending data." The hard part (validating it, storing it, and doing something when a reading is abnormal) is left as an exercise for the reader. This guide covers the full path.
What you'll build
- An ESP32 with a DHT22 sensor publishing temperature and humidity to Tendrl
- Validation rules that reject out-of-range readings before they enter your system
- A Strand workflow that sends a Slack message when temperature exceeds 35°C
Prerequisites
- An ESP32 board with MicroPython installed (setup guide)
- A DHT22 sensor wired to GPIO 4
- A free Tendrl account
- A Slack workspace with an incoming webhook URL
Step 1: Create an entity
In the Tendrl dashboard, go to Entities → Add Entity. Name it something like esp32-living-room. Copy the API key it shows you (it's shown once); the next step writes it to the board.
Step 2: Provision the board from the browser
Open the entity's Device tab in Chrome or Edge, plug the ESP32 into USB and click Connect. The browser talks to the board over WebSerial: it detects the chip, MicroPython version and free memory, and offers a Provision form. Paste the entity's API key, enter your Wi-Fi, keep the recommended install tier, click Start provisioning. That writes the SDK and the device config to the board over USB (the key never passes through our servers) and reboots it; it shows up online in Contact a few seconds later. The walkthrough has screenshots.
Prefer a terminal? The same install is one line at the MicroPython REPL, import mip; mip.install("https://app.tendrl.com/api/public/sdk/v1/latest/mpy/package.json"), plus a config.json with your API key and Wi-Fi. The browser just does both for you.
Step 3: Write the sensor script
Upload this as main.py (the Device tab's Files view does it from the same browser page). It reads the DHT22 every 30 seconds and publishes to Tendrl. The SDK handles Wi-Fi connection, TLS, batching, and offline queueing automatically.
import time
from machine import Pin
from dht import DHT22
from tendrl import Client
sensor = DHT22(Pin(4))
client = Client(mode="sync", offline_storage=True)
client.start()
while True:
sensor.measure()
client.publish(
data={
"temperature": sensor.temperature(),
"humidity": sensor.humidity()
},
tags=["sensors", "dht22"]
)
time.sleep(30) Power on the ESP32. Within a few seconds you should see messages arriving in the Tendrl dashboard under your entity.
Step 4: Add validation rules
Go to Services → Create Service. Add two validation rules:
temperature: between-40and85(DHT22 operating range)humidity: between0and100
Attach the service to your entity. Now every incoming message is validated before it's stored. A reading of temperature: 999 from a glitchy sensor gets rejected with a field-level error instead of silently corrupting your data.
Step 5: Build a Slack alert workflow
In Strand, create a new workflow. The flow is three nodes:
- Trigger: set to fire on incoming Contact messages with the
sensorstag - If/Else node with the condition
{{ payload.temperature > 35 }} - Slack connector: on the "true" branch, sends a message to your channel
For the Slack message, use a Jinja2 template:
High temperature alert: {{ payload.temperature }}°C
Humidity: {{ payload.humidity }}%
Entity: {{ meta.entity_name }} That's it. Your ESP32 sends data → Contact validates it → Strand checks the threshold → Slack gets the alert. No broker, no Lambda, no webhook handler.
What's next
- Archive to S3: add an S3 connector node after the if/else to store every reading
- Track device state: use the state table to store the latest firmware version and battery level
- Group devices: use fanouts to manage a fleet of sensors from one place
Tendrl