The full architecture. Two loops. Twenty tools. Rules that run locally, forever.
Everything runs inside a single loop() on a single core.
Runs every iteration. Reads sensors, checks conditions, fires actions. No network calls, no LLM, no latency. Edge-triggered: fires once per condition transition, then auto-resets. Persisted to flash - survives reboots.
Activates only when a message arrives - via Telegram, serial, or NATS. Calls the LLM through OpenRouter, Ollama, llama.cpp, or any OpenAI-compatible endpoint. HTTP mode for local LLMs saves ~40% RAM. Up to 5 tool-call iterations. Creates rules, registers devices, reads sensors, configures the system.
The LLM is the compiler. The ESP32 is the runtime.
What happens when you say "When chip temp goes above 45, set LED orange."
"When chip temp goes above 45, set LED orange"
LLM processes the intent, decides to call rule_create
Calls rule_create("hot_alert", "chip_temp", "gt", 45, "led_set", "255,140,0")
Written to /rules.json on flash (~80 bytes). Survives power loss.
Every iteration: reads chip_temp, checks if > 45, fires led_set on transition.
Fires once when condition becomes true. Auto-resets when condition clears. No repeated triggers.
On next power-on: loads from flash, resumes evaluation immediately. No re-setup needed.
Seven conditions. Six action types. Persistent, edge-triggered automation.
Greater than threshold. Fires when sensor value exceeds the set point.
Less than threshold. Fires when sensor value drops below the set point.
Equal to threshold. Fires on exact match (integer comparison).
Not equal. Fires when sensor value differs from the set point.
Any change. Fires when the sensor value changes from its previous reading.
Periodic. Fires every interval_seconds (default: evaluation interval). Use for heartbeats, scheduled reports, and watchdogs. Tool output shows last=Xs for verification.
Chain-triggered. Skipped during normal evaluation. Only fires when another rule's chain targets it. Created automatically by chain_create.
Set a registered actuator's value - digital, relay, or PWM output by name.
Set the onboard RGB LED to any color. Takes R,G,B values.
Write HIGH or LOW to a GPIO pin directly.
Publish a message to a NATS subject. Enables rule-triggered device-to-device messaging.
Send a Telegram alert. Configurable cooldown (default 60s) prevents message flooding.
Send text over serial_text UART. Supports {value} and {device_name} interpolation.
chain_create generates multiple linked rules under the hood. The first rule evaluates normally against the sensor condition. Each subsequent step becomes a separate rule with condition: chained - these skip normal evaluation and only fire when the previous step queues them.
Delays don't block the loop. A pending chain queue (8 entries max) tracks scheduled steps with their target timestamps. Each rulesEvaluate() iteration checks the queue and fires any steps whose delay has elapsed.
rule_createThe triggering sensor's reading at fire time.
Any named sensor's live reading (e.g., {chip_temp}).
Extract the msg field from a JSON NATS payload by device name.
"Temp is {chip_temp}°C" → "Temp is 36.2°C"Named sensors and actuators. Register once, reference by name everywhere.
Digital input pin. Returns HIGH (1) or LOW (0).
Analog input via ADC. Returns raw value (0-4095).
10K NTC thermistor. Automatic temperature conversion.
Light-dependent resistor. Returns light level reading.
Chip's internal temperature sensor. No external hardware needed.
NATS-subscribed sensor. Receives values published to a configured NATS subject. No GPIO pin. Bridges external systems into the rule engine.
Text lines from UART1 serial port. Connects Arduinos, GPS modules, CO2 sensors. Stores last line as value + message. One device max.
Current hour (0-23). NTP-synced, POSIX timezone + DST.
Current minute (0-59). Updates every rule evaluation cycle.
Combined time as hour*100+minute (e.g., 1830 = 6:30 PM). Use with eq for scheduled rules.
Digital output pin. Set HIGH or LOW.
Relay control. On/off switching for higher-power loads.
PWM output. Variable duty cycle for dimmers, motors, servos.
chip_temp and three clock sensors (clock_hour, clock_minute, clock_hhmm) are pre-registered on first boot. Persisted to /devices.json. NATS sensors (nats_value) register on demand - subscribe to any subject, feed external data into rules.
The complete tool reference, grouped by category.
Control the onboard RGB LED. Set any color with R, G, B values (0-255). Visual feedback for every action.
Drive output pins HIGH or LOW. Control relays, motors, actuators, or any digital output connected to a GPIO pin.
Read digital and analog values from any GPIO pin. Supports ADC readings for sensors, voltage dividers, and switches.
Read the ESP32 internal temperature sensor directly. Returns degrees Celsius. No external hardware required.
Register a named sensor or actuator. Specify name, type (digital_in, analog_in, ntc_10k, etc.), and GPIO pin. Persisted to flash.
List all registered devices with their names, types, pins, and current values. Shows both sensors and actuators.
Remove a registered device by name. Cleans up the registry entry and updates the persisted file.
Read a sensor by its registered name. Automatically handles type-specific conversions (NTC to Celsius, raw ADC, etc.).
Set a named actuator's output value. Supports digital on/off, relay switching, and PWM duty cycle control.
Create a persistent automation rule. Specify name, sensor, condition, threshold, and action. Immediately active and persisted to flash.
List all rules with conditions, actions, enabled state, last trigger time, and current evaluation status.
Delete a rule by name. Removes from active evaluation and from the persisted rules file. Takes effect immediately.
Enable or disable a rule without deleting it. Disabled rules are preserved but skip evaluation.
Create a multi-step automation chain in one call. Up to 5 steps with delays. Actions: telegram, led_set, gpio_write, nats_publish, actuator, serial_send.
Query system information: free heap, uptime, WiFi RSSI, chip temperature, flash usage, and firmware version.
Read any file from the LittleFS flash filesystem. Access configs, rules, device registry, logs, or custom data files.
Write data to the flash filesystem. Create or update config files, persist sensor readings, store notes or custom data.
Publish messages to NATS subjects. Enables device-to-device communication, event broadcasting, and IoT mesh coordination.
Send text over the serial_text UART connection. Appends newline automatically. Supports {value} and {device_name} interpolation.
Send a natural language message to another WireClaw device by name. NATS-based request/reply with 30-second timeout.
No external hardware needed. chip_temp sensor + onboard RGB LED = full demo.
What happens when you power on.