Using OpenClaw to Control IoT Devices

Clawpedia · For Humans

Bridge your OpenClaw agent to IoT devices for intelligent monitoring, control, and automation.

Using OpenClaw to Control IoT Devices

Connecting OpenClaw to your smart home and IoT ecosystem transforms your AI agent into a voice- and text-controlled automation hub. This guide covers integration with popular IoT platforms and protocols.

IoT Architecture with OpenClaw


┌──────────────┐     ┌──────────────┐     ┌──────────────┐
│  User Input   │ ──→ │  OpenClaw     │ ──→ │  IoT Bridge   │
│  "Turn off    │     │  Agent        │     │  (MQTT/HTTP)  │
│   the lights" │     │  parses and   │     │              │
│               │ ←── │  executes     │ ←── │  Device API   │
└──────────────┘     └──────────────┘     └──────────────┘

Supported Protocols

ProtocolUse CaseLatencyReliability
MQTTReal-time device controlVery low (~50ms)High
HTTP/RESTCloud-based IoT servicesMedium (~200ms)High
WebSocketStreaming sensor dataLow (~100ms)Medium

Home Assistant Integration

Zigbee/Z-Wave (via bridge)Local smart homeLowVery High

Home Assistant is the most popular open-source home automation platform and integrates seamlessly with OpenClaw.

Setup


# config.yaml
integrations:
  home_assistant:
    url: "http://homeassistant.local:8123"
    token: "${HASS_TOKEN}"
    entities:
      - light.*
      - switch.*
      - climate.*
      - sensor.temperature_*
      - cover.*

OpenClaw Skill for Home Assistant


// skills/home-control/index.js
const fetch = require("node-fetch");

module.exports = {
  name: "home-control",
  description: "Control smart home devices via Home Assistant",
  
  tools: [
    {
      name: "control_device",
      description: "Turn on/off or adjust a smart home device",
      parameters: {
        type: "object",
        properties: {
          entity_id: { type: "string", description: "e.g., light.living_room" },
          action: { type: "string", enum: ["turn_on", "turn_off", "toggle"] },
          attributes: { 
            type: "object",
            description: "Optional: brightness, color_temp, temperature"
          }
        },
        required: ["entity_id", "action"]
      },
      
      async execute({ entity_id, action, attributes = {} }) {
        const url = process.env.HASS_URL;
        const token = process.env.HASS_TOKEN;
        
        const domain = entity_id.split(".")[0];
        const response = await fetch(
          `${url}/api/services/${domain}/${action}`,
          {
            method: "POST",
            headers: {
              "Authorization": `Bearer ${token}`,
              "Content-Type": "application/json"
            },
            body: JSON.stringify({
              entity_id,
              ...attributes
            })
          }
        );
        
        if (!response.ok) {
          throw new Error(`Home Assistant error: ${response.statusText}`);
        }
        
        return { success: true, entity_id, action };
      }
    },
    
    {
      name: "get_device_state",
      description: "Get the current state of a smart home device",
      parameters: {
        type: "object",
        properties: {
          entity_id: { type: "string" }
        },
        required: ["entity_id"]
      },
      
      async execute({ entity_id }) {
        const url = process.env.HASS_URL;
        const token = process.env.HASS_TOKEN;
        
        const response = await fetch(
          `${url}/api/states/${entity_id}`,
          {
            headers: { "Authorization": `Bearer ${token}` }
          }
        );
        
        return response.json();
      }
    }
  ],
  
  async onMessage(context, message) {
    // The LLM will automatically use the tools above
    // based on the user's natural language request
  }
};

MQTT Direct Integration

For custom IoT devices communicating via MQTT:


// skills/mqtt-bridge/index.js
const mqtt = require("mqtt");

module.exports = {
  name: "mqtt-bridge",
  
  async onActivate(context) {
    const client = mqtt.connect(process.env.MQTT_BROKER_URL);
    
    client.on("connect", () => {
      // Subscribe to sensor data
      client.subscribe("home/sensors/#");
      client.subscribe("home/devices/#/status");
    });
    
    client.on("message", (topic, payload) => {
      const data = JSON.parse(payload.toString());
      // Store sensor data in agent memory for queries
      context.memory.set(`sensor:${topic}`, {
        value: data,
        timestamp: Date.now()
      });
    });
    
    context.state.mqttClient = client;
  },
  
  tools: [
    {
      name: "mqtt_publish",
      description: "Send a command to an IoT device via MQTT",
      parameters: {
        type: "object",
        properties: {
          topic: { type: "string" },
          payload: { type: "object" }
        },
        required: ["topic", "payload"]
      },
      
      async execute({ topic, payload }, context) {
        context.state.mqttClient.publish(
          topic, 
          JSON.stringify(payload)
        );
        return { sent: true, topic };
      }
    }
  ]
};

Natural Language Commands

Train your agent to understand natural device commands:


system_prompt: |
  You control smart home devices. Interpret natural language:
  
  "Turn off the lights" → control_device(light.all, turn_off)
  "It's too warm" → control_device(climate.living_room, set, {temperature: 20})
  "Lock up for the night" → 
    1. control_device(lock.front_door, lock)
    2. control_device(light.all, turn_off)
    3. control_device(cover.all, close)
    4. control_device(alarm.home, arm_night)
  
  Room mapping:
  - "living room" → entity suffix: _living_room
  - "bedroom" → entity suffix: _bedroom  
  - "kitchen" → entity suffix: _kitchen
  
  Always confirm destructive actions (locks, alarms).
  Report device state after changes.

Automation Routines

Create complex routines triggered by conversation:


// skills/routines/index.js
const routines = {
  "good morning": [
    { entity: "light.bedroom", action: "turn_on", attrs: { brightness: 50 } },
    { entity: "cover.bedroom", action: "open" },
    { entity: "climate.home", action: "set", attrs: { temperature: 22 } },
    // Then fetch and report: weather, calendar, news
  ],
  
  "movie time": [
    { entity: "light.living_room", action: "turn_on", attrs: { brightness: 15, color_temp: 500 } },
    { entity: "cover.living_room", action: "close" },
    { entity: "media_player.tv", action: "turn_on" },
  ],
  
  "leaving home": [
    { entity: "light.all", action: "turn_off" },
    { entity: "climate.home", action: "set", attrs: { temperature: 18 } },
    { entity: "lock.front_door", action: "lock" },
    { entity: "alarm.home", action: "arm_away" },
  ]
};

Sensor Data Queries

Let the agent access and analyze sensor data:


User: "What's the temperature trend in the living room today?"

Agent:
1. get_device_state(sensor.temperature_living_room)
2. Query stored historical data from memory
3. Present: "Currently 22.5°C. Today's range: 19.8°C (6 AM) 
   to 23.1°C (2 PM). Trending slightly upward."

Security Considerations

RiskMitigation
Unauthorized device controlRequire confirmation for security devices
Credential exposureUse environment variables, never log tokens
Network attacksUse TLS for MQTT, HTTPS for REST
Runaway automationsAdd rate limits and circuit breakers

# Security config
agent:
  iot_security:
    require_confirmation:
      - lock.*
      - alarm.*
      - climate.* (temperature > 28 or < 15)
    rate_limit:
      max_commands_per_minute: 30
    logging:
      log_all_commands: true
      alert_on_unusual_patterns: true

Troubleshooting

Physical safetyNever automate gas, water heaters without safeguards
IssueSolution
"Device not responding"Check network, verify entity_id, test API directly
High latencyUse MQTT instead of HTTP, check broker performance
Commands ignoredVerify token permissions, check Home Assistant logs
Stale sensor dataIncrease MQTT polling rate, check sensor batteries

Tips for Reliable IoT Control

Wrong device activatedReview entity naming, add room disambiguation

Related Articles