⏳ This skill is pending AI review.

Scores will appear once the review pipeline completes.

version unknown

openclaw-xiaomi-home

canmaxfire@canmaxfire⭐ 1 stars· last commit 6mo ago· 0 open issues

Your OpenClaw can now control your smart home. It connects to your Xiaomi/Mijia devices through Home Assistant and lets you control lights, AC, locks, sensors and more with plain text or voice commands. Ask things like "turn on the living room light", "set AC to 26 degrees", "is the front door locked?", or "what's the bedroom temperature?" and your AI assistant handles it instantly. Triggers: "turn on the light", "set AC temperature", "is the door locked?", "check the temperature", "lock the doo

Choose how to use this skill

You do not need every option. Choose the path your AI client supports. The stable page stays the same; versioned files are immutable.

1. Native installer

This listing has no registered native installer command. Use the complete package or source fallback below, depending on what your client supports.

Do not guess an installer command or replace an existing version without reviewing the diff.

2. Complete package recommended

Download the ZIP when available. It includes SKILL.md plus the references, security notes and version metadata.

No complete ProSkills package is published for this listing yet.

3. Prompt-only

Copy the prompt above when the agent can read the stable page or when you want to adopt the workflow without installing a skill.

Need only the instruction file?

Download SKILL.md only if your client requires a single file. The complete ZIP is safer for a full installation because it preserves the references and release context.

No path installs or executes anything by itself. Your agent still needs access to the project files. Before updating, compare the installed version and review the diff.

β€”/10

// RATINGS

⭐GitHub Stars
⭐ 1 on GitHubGitHub β†—

New / niche

🟒ProSkills Score
β€”
πŸ“

Not yet listed on ClawHub or SkillsMP

// README

openclaw-xiaomi-home

Version ClawHub

Your OpenClaw can now control your smart home. Connect to Xiaomi/Mijia devices through Home Assistant and control everything with plain text or voice.

The Problem It Solves

Smart home devices are scattered across apps:

  • Open Mi Home app β†’ find device β†’ tap button

This skill fixes that. Just tell your AI what you want:

"Turn on the living room light"
"Set bedroom AC to 26 degrees"
"Is the front door locked?"

Done.

What You Can Control

CategoryExamples
πŸ’‘ LightsOn/off, brightness
❄️ Air ConditioningTemperature, mode, fan speed
πŸ” Door LocksLock/unlock from anywhere
🌑️ SensorsTemperature, humidity, motion
πŸ’¨ Fans & HumidifiersOn/off, speed
πŸͺŸ Blinds & CurtainsOpen/close
πŸ€– Robot VacuumsStart, stop, return to base
πŸ”Š XiaoAI SpeakersVoice announcements (TTS)

Works with 1837+ Xiaomi/Mijia devices.

How It Works

You β†’ "Turn on the light"
  ↓
OpenClaw AI
  ↓
Home Assistant (local)
  ↓
Xiaomi Device

All stays on your local network β€” no cloud, no subscription.

Installation

# ClawHub
clawhub install openclaw-xiaomi-home

# Manual
git clone https://github.com/canmaxice-maker/openclaw-xiaomi-home.git
mv openclaw-xiaomi-home ~/.openclaw/skills/

Setup (One Time)

1. Start Home Assistant

cd ~/.openclaw/skills/openclaw-xiaomi-home
docker compose up -d

Open http://localhost:8123 and create your account.

2. Add Xiaomi Devices

  1. Settings β†’ Devices & Services β†’ Add Integration
  2. Search Xiaomi Home β†’ login with Xiaomi account
  3. Wait for devices to import

3. Create Access Token

  1. HA profile β†’ Long-Lived Access Tokens β†’ Create Token
  2. Copy and save it

4. Install Control Server

cd ~/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server
npm install && cp .env.example .env
# Edit .env with your HA_URL and HA_TOKEN

5. Start

launchctl load ~/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server/ai.openclaw.ha-mcp.plist

6. Test

node src/call-tool.mjs ping_ha
node src/call-tool.mjs list_all_devices '{"domain":"light"}'

Usage

Just talk to your AI assistant:

"Turn on the living room light"
"Set bedroom AC to 26 degrees"
"Is the front door locked?"
"What's the temperature?"
"Lock all doors"
"Turn off all lights"
"Open the blinds"
"Start the vacuum"

XiaoAI TTS Voice Announcement

Use XiaoAI speakers as a voice announcement system β€” your AI can "speak" reminders and alerts through the speaker.

⚠️ Note: Entity IDs are device-specific. You must find your own XiaoAI speaker's notify entity in Home Assistant (see Finding Your Entity IDs below).

Python script: ~/.openclaw/workspace/scripts/xiaoai_announce.py

# Find your notify entity ID first (see below), then:
python3 ~/.openclaw/workspace/scripts/xiaoai_announce.py "06:30 θ―₯θ΅·εΊŠδΊ†" "notify.YOUR_ENTITY_ID"

MCP tool: xiaoai_announce(message, entity_id?)

Use cases: Health reminders, smart home alerts, agent notifications.

Finding Your Entity IDs

XiaoAI speaker entity IDs are unique to your account. To find them:

  1. Open Home Assistant β†’ Developer Tools β†’ States
  2. Filter by notify and look for entities containing xiaoai, play_text, or speaker
  3. Copy the entity ID (format: notify.xiaomi_cn_XXXXXXXXXX_xxxx)

Security & Privacy

Required Credentials

CredentialPurposeStorage
HA_TOKENHome Assistant Long-Lived Access Token.env file (gitignored)

Security Model

ConcernMitigation
Unauthenticated accessMCP server requires Authorization: Bearer <HA_TOKEN> on every request
Cross-origin abuseCORS restricted to http://localhost only
LAN accessServer binds to localhost, not all interfaces
Token exfiltrationHA_TOKEN is only sent to localhost:8123 β€” never to external services
Credential leakage.env is in .gitignore β€” never committed to git

What This Skill Does NOT Do

  • ❌ Does NOT transmit your HA token to any external service
  • ❌ Does NOT accept requests from non-localhost origins
  • ❌ Does NOT collect, log, or transmit usage data
  • ❌ Does NOT use any LLM or AI processing
  • ❌ Does NOT expose unauthenticated endpoints

Troubleshooting

HA won't start

docker logs homeassistant

Devices not showing

  • Use China mainland Xiaomi server in Mi Home
  • Restart the homeassistant container

Token not working

  • Re-create the Long-Lived Access Token in HA
  • Update HA_TOKEN in .env

Credits

Changelog

VersionDateChanges
v1.2.02026-04-24Added XiaoAI TTS voice announcement via xiaoai_announce tool
v1.1.02026-04-21Plain language rewrite β€” user benefit focus
v1.0.02026-04-21Initial release

License

MIT

// HOW IT'S BUILT

// FILES

21 files shipped with this skill. Inline text is the catalog copy. The upstream link is the source repository.

  • SKILL.md3.2 KB9f9dd4b1040fupstream β†—
    ---
    name: openclaw-xiaomi-home
    description: Your OpenClaw can now control your smart home. It connects to your Xiaomi/Mijia devices through Home Assistant and lets you control lights, AC, locks, sensors and more with plain text or voice commands. Ask things like "turn on the living room light", "set AC to 26 degrees", "is the front door locked?", or "what's the bedroom temperature?" and your AI assistant handles it instantly. Triggers: "turn on the light", "set AC temperature", "is the door locked?", "check the temperature", "lock the door", "turn everything off".
    
    NOTE: Requires Home Assistant (Docker, localhost:8123) and Xiaomi devices paired with Mi Home.
    
    Required credentials:
    - `HA_TOKEN`: Long-Lived Access Token from Home Assistant, stored in `.env` (gitignored). Used as Bearer token to authenticate MCP server requests. Never sent to any external service.
    
    Security:
    - MCP server only accepts requests from localhost
    - All MCP calls require "Authorization: Bearer <HA_TOKEN>" header
    - HA_TOKEN is never transmitted to any service other than your local Home Assistant
    - No data collection or exfiltration β€” purely local device control
    ---
    
    # Xiaomi Home Control
    
    **Your OpenClaw can now control your smart home.** Connect to Xiaomi/Mijia devices through Home Assistant and control everything with plain text or voice.
    
    ## What It Does
    
    Just tell your AI what you want:
    
    ```
    "Turn on the living room light"
    "Set bedroom AC to 26 degrees"
    "Is the front door locked?"
    "What's the temperature?"
    "Lock all doors"
    "Turn off all lights"
    ```
    
    Done. No apps. No switching. No pointing and clicking.
    
    ## What You Can Control
    
    | Category | Examples |
    |----------|---------|
    | πŸ’‘ Lights | Turn on/off, adjust brightness |
    | ❄️ Air Conditioning | Set temperature, mode, fan speed |
    | πŸ” Door Locks | Lock/unlock from anywhere |
    | 🌑️ Sensors | Temperature, humidity, motion |
    | πŸ’¨ Fans & Humidifiers | On/off, speed control |
    | πŸͺŸ Blinds & Curtains | Open/close |
    | πŸ€– Robot Vacuums | Start, stop, return to charger |
    
    Works with **1837+ Xiaomi/Mijia devices** via the official Xiaomi Home integration.
    
    ## Setup (One Time)
    
    ```bash
    # 1. Start Home Assistant
    docker compose up -d
    
    # 2. Connect your Xiaomi devices
    # (open localhost:8123 β†’ add Xiaomi Home integration)
    
    # 3. Install the control server
    cd scripts/ha-mcp-server && npm install
    
    # 4. Done
    ```
    
    Full guide in README.md.
    
    ## How It Works
    
    ```
    You β†’ "Turn on the light"
      ↓
    OpenClaw AI
      ↓
    Home Assistant (your local server)
      ↓
    Xiaomi Device
    ```
    
    All on **your local network** β€” no cloud, no subscription.
    
    ## Why It's Better
    
    | Before | After |
    |--------|-------|
    | Open app β†’ find device β†’ tap | Just say what you want |
    | One device at a time | Control everything at once |
    | Can't do it remotely | Through AI assistant from anywhere |
    | Remember which app for which device | Describe it in plain English |
    
    ## Privacy
    
    - Everything stays on your home network
    - No cloud dependency after setup
    - No data collection or tracking
    - Runs on your own hardware
    
    ## Example Commands
    
    ```
    "Turn on the living room light"
    "Dim the bedroom to 30%"
    "Set AC to cool mode at 24 degrees"
    "Is the door locked?"
    "Lock the front door"
    "What's the living room temperature?"
    "Turn off all lights"
    "Open the blinds"
    "Start the vacuum"
    ```
    
  • README.md5.6 KBfc336c6ac863upstream β†—
    # openclaw-xiaomi-home
    
    [![Version](https://img.shields.io/badge/version-v1.2.0-blue.svg)](https://github.com/canmaxfire/openclaw-xiaomi-home)
    [![ClawHub](https://img.shields.io/badge/ClawHub-openclaw--xiaomi--home-green.svg)](https://clawhub.com/openclaw-xiaomi-home)
    
    **Your OpenClaw can now control your smart home.** Connect to Xiaomi/Mijia devices through Home Assistant and control everything with plain text or voice.
    
    ## The Problem It Solves
    
    Smart home devices are scattered across apps:
    - Open Mi Home app β†’ find device β†’ tap button
    
    **This skill fixes that.** Just tell your AI what you want:
    
    ```
    "Turn on the living room light"
    "Set bedroom AC to 26 degrees"
    "Is the front door locked?"
    ```
    
    Done.
    
    ## What You Can Control
    
    | Category | Examples |
    |----------|----------|
    | πŸ’‘ Lights | On/off, brightness |
    | ❄️ Air Conditioning | Temperature, mode, fan speed |
    | πŸ” Door Locks | Lock/unlock from anywhere |
    | 🌑️ Sensors | Temperature, humidity, motion |
    | πŸ’¨ Fans & Humidifiers | On/off, speed |
    | πŸͺŸ Blinds & Curtains | Open/close |
    | πŸ€– Robot Vacuums | Start, stop, return to base |
    | πŸ”Š **XiaoAI Speakers** | **Voice announcements (TTS)** |
    
    Works with **1837+ Xiaomi/Mijia devices**.
    
    ## How It Works
    
    ```
    You β†’ "Turn on the light"
      ↓
    OpenClaw AI
      ↓
    Home Assistant (local)
      ↓
    Xiaomi Device
    ```
    
    All stays **on your local network** β€” no cloud, no subscription.
    
    ## Installation
    
    ```bash
    # ClawHub
    clawhub install openclaw-xiaomi-home
    
    # Manual
    git clone https://github.com/canmaxice-maker/openclaw-xiaomi-home.git
    mv openclaw-xiaomi-home ~/.openclaw/skills/
    ```
    
    ## Setup (One Time)
    
    ### 1. Start Home Assistant
    
    ```bash
    cd ~/.openclaw/skills/openclaw-xiaomi-home
    docker compose up -d
    ```
    
    Open http://localhost:8123 and create your account.
    
    ### 2. Add Xiaomi Devices
    
    1. **Settings β†’ Devices & Services β†’ Add Integration**
    2. Search **Xiaomi Home** β†’ login with Xiaomi account
    3. Wait for devices to import
    
    ### 3. Create Access Token
    
    1. HA profile β†’ **Long-Lived Access Tokens** β†’ Create Token
    2. Copy and save it
    
    ### 4. Install Control Server
    
    ```bash
    cd ~/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server
    npm install && cp .env.example .env
    # Edit .env with your HA_URL and HA_TOKEN
    ```
    
    ### 5. Start
    
    ```bash
    launchctl load ~/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server/ai.openclaw.ha-mcp.plist
    ```
    
    ### 6. Test
    
    ```bash
    node src/call-tool.mjs ping_ha
    node src/call-tool.mjs list_all_devices '{"domain":"light"}'
    ```
    
    ## Usage
    
    Just talk to your AI assistant:
    
    ```
    "Turn on the living room light"
    "Set bedroom AC to 26 degrees"
    "Is the front door locked?"
    "What's the temperature?"
    "Lock all doors"
    "Turn off all lights"
    "Open the blinds"
    "Start the vacuum"
    ```
    
    ## XiaoAI TTS Voice Announcement
    
    Use XiaoAI speakers as a voice announcement system β€” your AI can "speak" reminders and alerts through the speaker.
    
    **⚠️ Note:** Entity IDs are device-specific. You must find your own XiaoAI speaker's `notify` entity in Home Assistant (see [Finding Your Entity IDs](#finding-your-entity-ids) below).
    
    **Python script:** `~/.openclaw/workspace/scripts/xiaoai_announce.py`
    
    ```bash
    # Find your notify entity ID first (see below), then:
    python3 ~/.openclaw/workspace/scripts/xiaoai_announce.py "06:30 θ―₯θ΅·εΊŠδΊ†" "notify.YOUR_ENTITY_ID"
    ```
    
    **MCP tool:** `xiaoai_announce(message, entity_id?)`
    
    **Use cases:** Health reminders, smart home alerts, agent notifications.
    
    ### Finding Your Entity IDs
    
    XiaoAI speaker entity IDs are unique to your account. To find them:
    
    1. Open Home Assistant β†’ **Developer Tools β†’ States**
    2. Filter by `notify` and look for entities containing `xiaoai`, `play_text`, or `speaker`
    3. Copy the entity ID (format: `notify.xiaomi_cn_XXXXXXXXXX_xxxx`)
    
    ---
    
    ## Security & Privacy
    
    ### Required Credentials
    
    | Credential | Purpose | Storage |
    |------------|---------|---------|
    | `HA_TOKEN` | Home Assistant Long-Lived Access Token | `.env` file (gitignored) |
    
    ### Security Model
    
    | Concern | Mitigation |
    |---------|------------|
    | Unauthenticated access | MCP server requires `Authorization: Bearer <HA_TOKEN>` on every request |
    | Cross-origin abuse | CORS restricted to `http://localhost` only |
    | LAN access | Server binds to localhost, not all interfaces |
    | Token exfiltration | HA_TOKEN is only sent to `localhost:8123` β€” never to external services |
    | Credential leakage | `.env` is in `.gitignore` β€” never committed to git |
    
    ### What This Skill Does NOT Do
    
    - ❌ Does NOT transmit your HA token to any external service
    - ❌ Does NOT accept requests from non-localhost origins
    - ❌ Does NOT collect, log, or transmit usage data
    - ❌ Does NOT use any LLM or AI processing
    - ❌ Does NOT expose unauthenticated endpoints
    
    ## Troubleshooting
    
    ### HA won't start
    ```bash
    docker logs homeassistant
    ```
    
    ### Devices not showing
    - Use **China mainland** Xiaomi server in Mi Home
    - Restart the homeassistant container
    
    ### Token not working
    - Re-create the Long-Lived Access Token in HA
    - Update `HA_TOKEN` in `.env`
    
    ## Credits
    
    - [Home Assistant](https://www.home-assistant.io/)
    - [ha_xiaomi_home](https://github.com/nickoowen/ha-xiaomi-home)
    - [OpenClaw](https://openclaw.ai/)
    
    ## Changelog
    
    | Version | Date | Changes |
    |---------|------|---------|
    | [v1.2.0](https://github.com/canmaxice-maker/openclaw-xiaomi-home/releases/tag/v1.2.0) | 2026-04-24 | Added XiaoAI TTS voice announcement via `xiaoai_announce` tool |
    | [v1.1.0](https://github.com/canmaxice-maker/openclaw-xiaomi-home/releases/tag/v1.1.0) | 2026-04-21 | Plain language rewrite β€” user benefit focus |
    | [v1.0.0](https://github.com/canmaxice-maker/openclaw-xiaomi-home/releases/tag/v1.0.0) | 2026-04-21 | Initial release |
    
    ## License
    
    MIT
    
  • scripts/ha-mcp-server/.env.example137 B77c671b22c29upstream β†—
    # Home Assistant Configuration
    HA_URL=http://localhost:8123
    HA_TOKEN=your_long_lived_access_token_here
    
    # Server Configuration
    PORT=3002
    
  • scripts/ha-mcp-server/ai.openclaw.ha-mcp.plist986 B67ac4f04ecd8upstream β†—
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>ai.openclaw.ha-mcp</string>
        <key>ProgramArguments</key>
        <array>
            <string>/opt/homebrew/bin/node</string>
            <string>/Users/nanali/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server/src/http-server.mjs</string>
        </array>
        <key>EnvironmentVariables</key>
        <dict>
            <key>HOME</key>
            <string>/Users/nanali</string>
        </dict>
        <key>WorkingDirectory</key>
        <string>/Users/nanali/.openclaw/skills/openclaw-xiaomi-home/scripts/ha-mcp-server</string>
        <key>StandardOutPath</key>
        <string>/Users/nanali/.openclaw/logs/ha-mcp.log</string>
        <key>StandardErrorPath</key>
        <string>/Users/nanali/.openclaw/logs/ha-mcp.err.log</string>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
    </dict>
    </plist>
    
  • scripts/ha-mcp-server/package-lock.json57 KB1c2827c3c162upstream β†—

    Contents are not inlined in the catalog. Open the upstream file.

  • scripts/ha-mcp-server/package.json550 B38e5be15861cupstream β†—
    {
      "name": "ha-mcp-server",
      "version": "1.0.0",
      "description": "MCP server for Home Assistant - controls Xiaomi devices via natural language",
      "type": "module",
      "main": "src/http-server.mjs",
      "scripts": {
        "start": "node src/http-server.mjs",
        "start:stdio": "node src/index.mjs",
        "test": "node src/call-tool.mjs ping_ha"
      },
      "keywords": [
        "home-assistant",
        "xiaomi",
        "mcp",
        "smart-home",
        "openclaw"
      ],
      "author": "Nana / OpenClaw",
      "license": "MIT",
      "dependencies": {
        "dotenv": "^16.4.5"
      }
    }
    
  • scripts/ha-mcp-server/src/call-tool.mjs2.0 KB41c41bdbf16fupstream β†—
    /**
     * HA MCP Client - Call tools via HTTP JSON-RPC
     * Usage: node call-tool.mjs <tool_name> [args_json]
     */
    
    import http from "http";
    import { readFileSync } from "fs";
    import path from "path";
    import { fileURLToPath } from "url";
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    const envPath = path.resolve(__dirname, "../.env");
    const env = {};
    try {
      const lines = readFileSync(envPath, "utf8").split("\n");
      for (const line of lines) {
        const [key, ...vals] = line.split("=");
        if (key && vals.length) env[key.trim()] = vals.join("=").trim();
      }
    } catch (e) { /* no .env */ }
    
    const HOST = process.env.HA_MCP_HOST || "localhost";
    const PORT = process.env.HA_MCP_PORT || "3002";
    const HA_TOKEN = env.HA_TOKEN || "";
    
    function rpc(method, params = {}) {
      return new Promise((resolve, reject) => {
        const body = JSON.stringify({ jsonrpc: "2.0", id: 1, method, params });
        const headers = {
          "Content-Type": "application/json",
          "Content-Length": Buffer.byteLength(body),
          "Authorization": `Bearer ${HA_TOKEN}`,
        };
        const options = { hostname: HOST, port: PORT, path: "/", method: "POST", headers };
        const req = http.request(options, res => {
          let data = "";
          res.on("data", chunk => data += chunk);
          res.on("end", () => {
            try {
              const json = JSON.parse(data);
              if (json.error) reject(new Error(json.error.message));
              else resolve(json.result);
            } catch (e) { reject(e); }
          });
        });
        req.on("error", reject);
        req.write(body);
        req.end();
      });
    }
    
    const tool = process.argv[2];
    const args = process.argv[3] ? JSON.parse(process.argv[3]) : {};
    
    if (!tool) {
      console.error("Usage: node call-tool.mjs <tool_name> [args_json]");
      process.exit(1);
    }
    
    rpc("tools/call", { name: tool, arguments: args })
      .then(result => {
        const text = result.content?.[0]?.text || JSON.stringify(result);
        console.log(text);
      })
      .catch(err => {
        console.error("Error:", err.message);
        process.exit(1);
      });
    
  • scripts/ha-mcp-server/src/http-server.mjs12 KBcaaa58b5c872upstream β†—
    /**
     * Home Assistant MCP Server - Simple HTTP JSON-RPC
     * Compatible with any MCP client via HTTP POST
     */
    
    import http from "http";
    import { readFileSync } from "fs";
    import path from "path";
    import { fileURLToPath } from "url";
    
    const __dirname = path.dirname(fileURLToPath(import.meta.url));
    const envPath = path.resolve(__dirname, "../.env");
    const env = {};
    try {
      const lines = readFileSync(envPath, "utf8").split("\n");
      for (const line of lines) {
        const [key, ...vals] = line.split("=");
        if (key && vals.length) env[key.trim()] = vals.join("=").trim();
      }
    } catch (e) { /* no .env */ }
    
    const HA_URL = env.HA_URL || "http://localhost:8123";
    const HA_TOKEN = env.HA_TOKEN || "";
    const PORT = parseInt(env.PORT || "3002", 10);
    const ALLOWED_ORIGIN = "http://localhost"; // Only allow localhost for CORS
    
    // Simple bearer token auth: must send "Authorization: Bearer <HA_TOKEN>" header
    function checkAuth(req) {
      const auth = req.headers["authorization"] || req.headers["Authorization"];
      if (!auth || !auth.startsWith("Bearer ")) return false;
      const token = auth.slice("Bearer ".length);
      return token === HA_TOKEN;
    }
    
    // ============================================================================
    // HA API
    // ============================================================================
    
    async function haFetch(endpoint, options = {}) {
      const url = `${HA_URL}/api${endpoint}`;
      const response = await fetch(url, {
        ...options,
        headers: {
          "Authorization": `Bearer ${HA_TOKEN}`,
          "Content-Type": "application/json",
          ...options.headers,
        },
      });
      if (!response.ok) throw new Error(`HA API error: ${response.status}`);
      return response.json();
    }
    
    const getEntity = (id) => haFetch(`/states/${id}`);
    const callService = (d, s, data) => haFetch(`/services/${d}/${s}`, { method: "POST", body: JSON.stringify(data) });
    const getAllEntities = () => haFetch("/states");
    
    // ============================================================================
    // Tool Implementations
    // ============================================================================
    
    const tools = {
      // Lights
      light_turn_on: async ({ entity_id, brightness }) => {
        const data = { entity_id };
        if (brightness !== undefined) data.brightness = brightness;
        await callService("light", "turn_on", data);
        return textResult(`Light ${entity_id} turned on${brightness ? ` (brightness: ${brightness})` : ""}`);
      },
      light_turn_off: async ({ entity_id }) => {
        await callService("light", "turn_off", { entity_id });
        return textResult(`Light ${entity_id} turned off`);
      },
      get_light_state: async ({ entity_id }) => {
        const e = await getEntity(entity_id);
        return textResult(`${e.entity_id}: ${e.state} (brightness: ${e.attributes.brightness ?? "N/A"})`);
      },
    
      // Climate / AC
      climate_set_temperature: async ({ entity_id, temperature }) => {
        await callService("climate", "set_temperature", { entity_id, temperature });
        return textResult(`${entity_id} set to ${temperature}Β°C`);
      },
      climate_set_mode: async ({ entity_id, mode }) => {
        await callService("climate", "set_hvac_mode", { entity_id, hvac_mode: mode });
        return textResult(`${entity_id} mode set to ${mode}`);
      },
      get_climate_state: async ({ entity_id }) => {
        const e = await getEntity(entity_id);
        const a = e.attributes;
        return textResult(`${e.entity_id}: ${e.state}, temp: ${a.current_temperature}Β°C, target: ${a.temperature}Β°C`);
      },
    
      // Fans
      fan_turn_on: async ({ entity_id }) => {
        await callService("fan", "turn_on", { entity_id });
        return textResult(`${entity_id} turned on`);
      },
      fan_turn_off: async ({ entity_id }) => {
        await callService("fan", "turn_off", { entity_id });
        return textResult(`${entity_id} turned off`);
      },
      fan_set_speed: async ({ entity_id, speed }) => {
        await callService("fan", "set_percentage", { entity_id, percentage: speed });
        return textResult(`${entity_id} speed set to ${speed}%`);
      },
      get_fan_state: async ({ entity_id }) => {
        const e = await getEntity(entity_id);
        return textResult(`${e.entity_id}: ${e.state} (speed: ${e.attributes.percentage ?? "N/A"}%)`);
      },
    
      // Switches
      switch_turn_on: async ({ entity_id }) => { await callService("switch", "turn_on", { entity_id }); return textResult(`${entity_id} turned on`); },
      switch_turn_off: async ({ entity_id }) => { await callService("switch", "turn_off", { entity_id }); return textResult(`${entity_id} turned off`); },
      get_switch_state: async ({ entity_id }) => { const e = await getEntity(entity_id); return textResult(`${e.entity_id}: ${e.state}`); },
    
      // Locks
      lock_lock: async ({ entity_id }) => { await callService("lock", "lock", { entity_id }); return textResult(`${entity_id} locked`); },
      lock_unlock: async ({ entity_id }) => { await callService("lock", "unlock", { entity_id }); return textResult(`${entity_id} unlocked`); },
      get_lock_state: async ({ entity_id }) => { const e = await getEntity(entity_id); return textResult(`${e.entity_id}: ${e.state}`); },
    
      // Sensors
      get_sensor_reading: async ({ entity_id }) => { const e = await getEntity(entity_id); return textResult(`${e.entity_id}: ${e.state} ${e.attributes.unit_of_measurement ?? ""}`); },
      list_sensors: async () => {
        const entities = await getAllEntities();
        const sensors = entities.filter(e => e.entity_id.startsWith("sensor.") || e.entity_id.startsWith("binary_sensor."));
        const list = sensors.slice(0, 30).map(e => `  - ${e.entity_id}: ${e.state} ${e.attributes.unit_of_measurement ?? ""}`).join("\n");
        return textResult(`Sensors (${sensors.length} total):\n${list}`);
      },
    
      // Humidifier
      humidifier_turn_on: async ({ entity_id }) => { await callService("humidifier", "turn_on", { entity_id }); return textResult(`${entity_id} turned on`); },
      humidifier_turn_off: async ({ entity_id }) => { await callService("humidifier", "turn_off", { entity_id }); return textResult(`${entity_id} turned off`); },
      get_humidifier_state: async ({ entity_id }) => { const e = await getEntity(entity_id); return textResult(`${e.entity_id}: ${e.state}, humidity: ${e.attributes.current_humidity ?? "N/A"}%`); },
    
      // Cover / Blinds
      cover_open: async ({ entity_id }) => { await callService("cover", "open_cover", { entity_id }); return textResult(`${entity_id} opened`); },
      cover_close: async ({ entity_id }) => { await callService("cover", "close_cover", { entity_id }); return textResult(`${entity_id} closed`); },
      get_cover_state: async ({ entity_id }) => { const e = await getEntity(entity_id); return textResult(`${e.entity_id}: ${e.state}`); },
    
      // Vacuum
      vacuum_start: async ({ entity_id }) => { await callService("vacuum", "start", { entity_id }); return textResult(`${entity_id} started`); },
      vacuum_stop: async ({ entity_id }) => { await callService("vacuum", "stop", { entity_id }); return textResult(`${entity_id} stopped`); },
      vacuum_return_to_base: async ({ entity_id }) => { await callService("vacuum", "return_to_base", { entity_id }); return textResult(`${entity_id} returning to base`); },
    
      // Devices
      list_all_devices: async (args = {}) => {
        const entities = await getAllEntities();
        const filtered = args.domain ? entities.filter(e => e.entity_id.startsWith(args.domain + ".")) : entities;
        const list = filtered.slice(0, 50).map(e => `  - ${e.entity_id}: ${e.state}`).join("\n");
        return textResult(`${filtered.length} entities (showing 50):\n${list}`);
      },
      get_device_state: async ({ entity_id }) => {
        const e = await getEntity(entity_id);
        return textResult(`${e.entity_id}\nState: ${e.state}\nAttributes: ${JSON.stringify(e.attributes, null, 2)}`);
      },
    
      // Scene
      trigger_scene: async ({ entity_id }) => { await callService("scene", "turn_on", { entity_id }); return textResult(`Scene ${entity_id} triggered`); },
    
      // XiaoAI TTS Announce
      xiaoai_announce: async ({ message, entity_id }) => {
        const target = entity_id || "notify.xiaomi_cn_501481700_l16a_play_text_a_7_3";
        await haFetch("/services/notify/send_message", {
          method: "POST",
          body: JSON.stringify({ message, entity_id: target }),
        });
        return textResult(`XiaoAI announced: ${message}`);
      },
    
      // HA status
      ping_ha: async () => { await haFetch("/config"); return textResult("Home Assistant is reachable and running"); },
      get_ha_config: async () => { const c = await haFetch("/config"); return textResult(`Home Assistant version: ${c.version}`); },
    };
    
    function textResult(text) {
      return { content: [{ type: "text", text }] };
    }
    
    // ============================================================================
    // HTTP Server
    // ============================================================================
    
    const server = http.createServer(async (req, res) => {
      if (req.method === "OPTIONS") {
        res.writeHead(200, { "Access-Control-Allow-Origin": ALLOWED_ORIGIN, "Access-Control-Allow-Methods": "POST, GET, OPTIONS", "Access-Control-Allow-Headers": "Content-Type, Authorization" });
        res.end();
        return;
      }
      // Reject requests from non-localhost origins
      const origin = req.headers["origin"] || req.headers["Origin"];
      if (origin && !origin.startsWith(ALLOWED_ORIGIN)) {
        res.writeHead(403, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ error: "Forbidden: cross-origin request denied" }));
        return;
      }
      // Require authentication for all tool calls
      if (req.method === "POST" && !checkAuth(req)) {
        res.writeHead(401, { "Content-Type": "application/json", "WWW-Authenticate": "Bearer" });
        res.end(JSON.stringify({ error: "Unauthorized: valid Bearer token required" }));
        return;
      }
      if (req.method === "GET" && req.url === "/health") {
        res.writeHead(200, { "Content-Type": "application/json" });
        res.end(JSON.stringify({ status: "ok" }));
        return;
      }
      if (req.method !== "POST") { res.writeHead(404); res.end(); return; }
    
      let body = "";
      req.on("data", chunk => body += chunk);
      req.on("end", async () => {
        try {
          const json = JSON.parse(body);
          const jsonrpc = json.jsonrpc || "2.0";
          const method = json.method;
          const params = json.params || {};
          const responseId = json.id;
    
          if (method === "tools/list") {
            const toolList = Object.keys(tools).map(name => ({ name, description: "", inputSchema: { type: "object" } }));
            res.writeHead(200, { "Content-Type": "application/json" });
            res.end(JSON.stringify({ jsonrpc, id: responseId, result: { tools: toolList } }));
            return;
          }
          if (method === "tools/call") {
            const toolName = params.name;
            const args = params.arguments || {};
            if (!tools[toolName]) {
              res.writeHead(200, { "Content-Type": "application/json" });
              res.end(JSON.stringify({ jsonrpc, id: responseId, error: { code: -32601, message: `Tool ${toolName} not found` } }));
              return;
            }
            try {
              const result = await tools[toolName](args);
              res.writeHead(200, { "Content-Type": "application/json" });
              res.end(JSON.stringify({ jsonrpc, id: responseId, result }));
            } catch (err) {
              res.writeHead(200, { "Content-Type": "application/json" });
              res.end(JSON.stringify({ jsonrpc, id: responseId, error: { code: -32603, message: err.message } }));
            }
            return;
          }
          res.writeHead(200, { "Content-Type": "application/json" });
          res.end(JSON.stringify({ jsonrpc, id: responseId, error: { code: -32601, message: "Method not found" } }));
        } catch (e) {
          res.writeHead(200, { "Content-Type": "application/json" });
          res.end(JSON.stringify({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } }));
        }
      });
    });
    
    server.listen(PORT, () => {
      console.error(`HA MCP Server running on http://localhost:${PORT}`);
    });
    
  • scripts/ha-mcp-server/tsconfig.json336 B2b380862c53cupstream β†—
    {
      "compilerOptions": {
        "target": "ES2022",
        "module": "NodeNext",
        "moduleResolution": "NodeNext",
        "outDir": "./dist",
        "rootDir": "./src",
        "strict": true,
        "esModuleInterop": true,
        "skipLibCheck": true,
        "resolveJsonModule": true
      },
      "include": ["src/**/*"],
      "exclude": ["node_modules", "dist"]
    }
    
  • scripts/setup.sh3.1 KB7c350679d661upstream β†—
    #!/bin/bash
    # Setup script for openclaw-xiaomi-home skill
    # This script helps users install Home Assistant and configure the MCP server
    
    set -e
    
    SKILL_DIR="$(cd "$(dirname "$0")/.." && pwd)"
    SCRIPT_DIR="$SKILL_DIR/scripts/ha-mcp-server"
    PLIST_SRC="$SCRIPT_DIR/ai.openclaw.ha-mcp.plist"
    
    echo "=========================================="
    echo "Xiaomi Home Skill Setup"
    echo "=========================================="
    
    # Check Docker
    if ! command -v docker &> /dev/null; then
        echo "Error: Docker is not installed."
        echo "Please install Docker Desktop from: https://docs.docker.com/desktop/setup/install/mac-install/"
        exit 1
    fi
    
    if ! docker info &> /dev/null; then
        echo "Error: Docker is not running."
        echo "Please start Docker Desktop."
        exit 1
    fi
    echo "βœ“ Docker is installed and running"
    
    # Start Home Assistant
    echo ""
    echo "Starting Home Assistant..."
    cd "$SKILL_DIR"
    docker compose up -d 2>/dev/null || docker run -d \
      --name homeassistant \
      --privileged \
      -p 8123:8123 \
      -v ~/homeassistant/config:/config \
      -v /etc/localtime:/etc/localtime:ro \
      -e TZ=Asia/Shanghai \
      --dns=8.8.8.8 \
      --dns=223.5.5.5 \
      --restart=unless-stopped \
      ghcr.io/home-assistant/home-assistant:stable
    
    echo "βœ“ Home Assistant started"
    echo "  Access at: http://localhost:8123"
    echo ""
    echo "  First-time setup:"
    echo "  1. Open http://localhost:8123 and create your account"
    echo "  2. Add 'external_url: http://localhost:8123' to ~/homeassistant/config/configuration.yaml"
    echo "  3. Go to Settings β†’ Devices & Services β†’ Add Integration"
    echo "  4. Search 'Xiaomi Home' and login with your Xiaomi account"
    echo "  5. Profile β†’ Security β†’ Create Long-Lived Access Token"
    echo ""
    
    # Setup HA token
    if [ ! -f "$SCRIPT_DIR/.env" ]; then
        echo "=========================================="
        echo "MCP Server Configuration"
        echo "=========================================="
        echo "Enter your Home Assistant Long-Lived Access Token:"
        read -r HA_TOKEN
        echo "HA_URL=http://localhost:8123" > "$SCRIPT_DIR/.env"
        echo "HA_TOKEN=$HA_TOKEN" >> "$SCRIPT_DIR/.env"
        echo "PORT=3002" >> "$SCRIPT_DIR/.env"
        echo "βœ“ Created .env file"
    else
        echo "βœ“ .env file already exists"
    fi
    
    # Install MCP Server dependencies
    echo ""
    echo "Installing MCP Server..."
    cd "$SCRIPT_DIR"
    npm install --silent 2>/dev/null
    
    # Setup LaunchAgent
    echo ""
    echo "Installing HA MCP Server as LaunchAgent..."
    mkdir -p "$HOME/Library/LaunchAgents"
    mkdir -p "$(dirname "$PLIST_SRC")"
    
    # Create user-specific plist
    PLIST_DST="$HOME/Library/LaunchAgents/ai.openclaw.ha-mcp.plist"
    sed "s|/Users/nanali|$HOME|g" "$PLIST_SRC" > "$PLIST_DST"
    launchctl load "$PLIST_DST" 2>/dev/null || true
    echo "βœ“ HA MCP Server installed as LaunchAgent"
    
    echo ""
    echo "=========================================="
    echo "Setup Complete!"
    echo "=========================================="
    echo ""
    echo "HA MCP Server: http://localhost:3002"
    echo "Home Assistant: http://localhost:8123"
    echo ""
    echo "Test the MCP server:"
    echo "  node $SCRIPT_DIR/src/call-tool.mjs ping_ha"
    echo ""
    echo "For OpenClaw integration, add this skill to your OpenClaw"
    echo "and the MCP server will automatically handle device control."
    
  • references/api-notes.md2.0 KBade0f653cd84upstream β†—
    # Home Assistant API Notes
    
    ## Authentication
    
    All API requests require a Long-Lived Access Token in the Authorization header:
    
    ```
    Authorization: Bearer YOUR_TOKEN_HERE
    ```
    
    ## Base URL
    
    ```
    http://localhost:8123/api
    ```
    
    ## Key Endpoints
    
    ### States
    
    ```bash
    # Get all states
    GET /api/states
    
    # Get single entity state
    GET /api/states/{entity_id}
    
    # Example
    curl -H "Authorization: Bearer $HA_TOKEN" \
         http://localhost:8123/api/states/light.living_room
    ```
    
    ### Services
    
    ```bash
    # Call a service
    POST /api/services/{domain}/{service}
    
    # Light examples
    POST /api/services/light/turn_on
    {"entity_id": "light.living_room", "brightness": 255}
    
    POST /api/services/light/turn_off
    {"entity_id": "light.living_room"}
    
    # Climate examples
    POST /api/services/climate/set_temperature
    {"entity_id": "climate.living_room_ac", "temperature": 26}
    
    POST /api/services/climate/set_hvac_mode
    {"entity_id": "climate.living_room_ac", "hvac_mode": "cool"}
    
    # Lock examples
    POST /api/services/lock/lock
    {"entity_id": "lock.front_door"}
    
    POST /api/services/lock/unlock
    {"entity_id": "lock.front_door"}
    ```
    
    ### Config
    
    ```bash
    GET /api/config
    ```
    
    ### Events
    
    ```bash
    # Listen to events (Server-Sent Events)
    GET /api/events
    ```
    
    ## Entity ID Format
    
    ```
    {domain}.{device_name}_{identifier}
    ```
    
    Examples:
    - `light.living_room_ceiling`
    - `climate.bedroom_ac`
    - `sensor.kitchen_temperature`
    - `binary_sensor.front_door`
    - `lock.front_door`
    - `switch.tv_plug`
    
    ## Common Domains
    
    | Domain | Type |
    |--------|------|
    | `light` | Lights |
    | `switch` | Plugs, Switches |
    | `climate` | AC, Heaters |
    | `sensor` | Sensors (readings) |
    | `binary_sensor` | Binary sensors (on/off) |
    | `lock` | Smart locks |
    | `cover` | Curtains, Blinds |
    | `fan` | Fans |
    | `scene` | Scenes |
    | `automation` | Automations |
    
    ## Error Responses
    
    ```json
    {
      "code": "not_found",
      "message": "Entity not found"
    }
    ```
    
    ## Rate Limits
    
    - No strict rate limit for local API
    - Recommended: max 10 calls/second
    - Cloud API (Xiaomi) may have stricter limits
    
  • references/automations.md3.4 KBd5188bcb0a34upstream β†—
    # Automation Templates
    
    ## Home Assistant Automation Examples
    
    These automations can be configured in Home Assistant's UI or via YAML.
    
    ### Temperature-Based Climate Control
    
    ```yaml
    automation:
      - alias: "Auto AC when hot"
        trigger:
          - platform: numeric_state
            entity_id: sensor.living_room_temperature
            above: 28
        condition:
          - condition: time
            after: "08:00:00"
            before: "22:00:00"
        action:
          - service: climate.set_temperature
            target:
              entity_id: climate.living_room_ac
            data:
              temperature: 26
          - service: notify.openclaw
            data:
              message: "🌑️ Living room temp above 28°C, AC turned on to 26°C"
    ```
    
    ### Motion-Activated Light
    
    ```yaml
    automation:
      - alias: "Hallway light on motion"
        trigger:
          - platform: state
            entity_id: binary_sensor.hallway_motion
            to: "on"
        condition:
          - condition: sun
            after: sunset
            before: sunrise
        action:
          - service: light.turn_on
            target:
              entity_id: light.hallway
            data:
              brightness: 128
    ```
    
    ### Door Lock Reminder
    
    ```yaml
    automation:
      - alias: "Front door auto-lock"
        trigger:
          - platform: state
            entity_id: binary_sensor.front_door
            to: "closed"
            for:
              minutes: 2
        condition:
          - condition: state
            entity_id: lock.front_door
            state: "unlocked"
        action:
          - service: lock.lock
            target:
              entity_id: lock.front_door
    ```
    
    ### Goodnight Routine
    
    ```yaml
    automation:
      - alias: "Goodnight scene"
        trigger:
          - platform: time
            at: "22:30:00"
        action:
          - service: light.turn_off
            target:
              entity_id: group.all_lights
          - service: climate.set_temperature
            target:
              entity_id: climate.bedroom_ac
            data:
              temperature: 25
          - service: lock.lock
            target:
              entity_id: lock.front_door
    ```
    
    ### Leave Home
    
    ```yaml
    automation:
      - alias: "Turn off when leaving"
        trigger:
          - platform: state
            entity_id: binary_sensor.front_door
            to: "closed"
            for:
              minutes: 5
        condition:
          - condition: state
            entity_id: person.jun
            state: "not_home"
        action:
          - service: switch.turn_off
            target:
              entity_id: group.all_switches
          - service: notify.openclaw
            data:
              message: "πŸ”’ Home secured. All devices off."
    ```
    
    ## OpenClaw Webhook Integration
    
    To receive alerts in OpenClaw, set up a webhook in Home Assistant.
    
    ### Configuration
    
    Add to `configuration.yaml`:
    
    ```yaml
    rest_command:
      notify_openclaw:
        url: "http://localhost:8123/api/webhook/openclaw_notify"
        method: POST
        content_type: "application/json"
        payload: '{"message": "{{ message }}"}'
    ```
    
    ### Enable Webhook in UI
    
    Settings β†’ Devices & Services β†’ Helpers β†’ Add Helper β†’ Webhook
    
    ### Notify OpenClaw from Automation
    
    ```yaml
    action:
      - service: rest_command.notify_openclaw
        data:
          message: "⚠️ Smoke detected in living room!"
    ```
    
    ## Natural Language Commands from OpenClaw
    
    OpenClaw can execute these automations via the MCP tools:
    
    ```
    User: "Turn on the fan when temperature exceeds 30Β°C"
    β†’ OpenClaw: Creates automation in HA or triggers manual command
    
    User: "Lock all doors at 10 PM"  
    β†’ OpenClaw: Creates time-based automation
    
    User: "Turn off everything when I leave"
    β†’ OpenClaw: Creates device-based automation
    ```
    
  • references/device-support.md2.9 KB9401dd5eb9daupstream β†—
    # Device Support Reference
    
    ## Supported Devices
    
    ### Lighting βœ…
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Ceiling Lights | Mi LED Ceiling Light, Philips Ceiling Light | Full on/off/brightness/color control |
    | Table Lamps | Mi Bedside Lamp, Mi Desk Lamp | Full control |
    | Floor Lamps | Mi Floor Lamp | Full control |
    | Bulbs | Mi LED Bulb, Philips Hue (via ecosystem) | Full on/off/brightness |
    
    ### Climate βœ…
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Air Conditioners | Mi Air Conditioner, various IR-based ACs | Temperature, mode, fan speed |
    | Heaters | Mi Smart Heater, Mi Oil Heater | Temperature control |
    | Fans | Mi Smart Fan, Mi Standing Fan | On/off, speed |
    
    ### Sensors βœ…
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Temperature/Humidity | Mi Temperature and Humidity Sensor | Readings |
    | Door/Window | Mi Door/Window Sensor | Open/close status |
    | Motion | Mi Motion Sensor | Detected/idle |
    | Water Leak | Mi Water Leak Sensor | Detected/safe |
    
    ### Smart Locks βœ…
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Door Locks | Xiaomi Smart Door Lock, Aqara Smart Lock | Lock/unlock, auto-lock settings |
    
    ### Plugs & Switches βœ…
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Smart Plugs | Mi Smart Plug, Aqara Plug | On/off, power monitoring |
    | Wall Switches | Mi Wall Switch, Aqara Wall Switch | On/off |
    
    ### Appliances ⚠️
    | Category | Examples | Notes |
    |----------|----------|-------|
    | Refrigerators | Mi Refrigerator | Basic on/off, temperature |
    | Washers | Mi Washing Machine | Start/stop, basic modes |
    | Projectors | Mi Laser Projector | On/off, input selection |
    
    ## NOT Supported ❌
    
    - **Bluetooth devices** (direct BLE connection)
    - **Infrared (IR) devices** (TVs, AC remotes via IR blaster)
    - **Virtual devices** (scenes, automations created in Mi Home)
    - **Wearable devices** (Mi Band, etc.)
    - **Air Purifiers** (some models may work)
    - **Robot Vacuums** (different integration path)
    
    ## Local vs Cloud Control
    
    ### With Central Hub Gateway βœ…
    - Commands go through the local hub
    - Faster response (< 1 second)
    - Works without internet
    - Requires: Hub firmware 3.3.0_0023+
    
    ### Without Central Hub
    - Commands go through Xiaomi Cloud
    - Slower response (1-3 seconds)
    - Requires internet connection
    - May have latency during cloud outages
    
    ### LAN Control (Partial Alternative)
    Enable in Xiaomi Home integration settings:
    Settings β†’ Devices & Services β†’ Xiaomi Home β†’ Configure β†’ LAN Control
    
    ⚠️ Note: LAN control only works for IP devices (WiFi), not BLE Mesh/ZigBee devices.
    
    ## Entity Naming Convention
    
    In Home Assistant, Xiaomi devices appear as:
    - `light.xiaomi_xxx` - Lights
    - `climate.xiaomi_xxx` - AC/Heaters
    - `sensor.xiaomi_temperature` - Sensors
    - `binary_sensor.xiaomi_door` - Door/Window sensors
    - `lock.xiaomi_lock` - Smart locks
    - `switch.xiaomi_plug` - Plugs/Switches
    
  • references/installation.md2.3 KBa78382a729b1upstream β†—
    # Detailed Installation Guide
    
    ## Prerequisites
    
    - Docker Desktop 4.x+
    - Xiaomi account with Mi Home app and linked devices
    - (Optional) Xiaomi Central Hub Gateway for local control
    
    ## Step 1: Install Docker Desktop
    
    Download from: https://docs.docker.com/desktop/setup/install/mac-install/
    
    After installation, ensure Docker is running (whale icon in menu bar).
    
    ## Step 2: Clone and Setup the Skill
    
    ```bash
    git clone https://github.com/YOUR_USERNAME/openclaw-xiaomi-home.git
    cd openclaw-xiaomi-home
    ```
    
    ## Step 3: Configure mcporter
    
    Add the MCP server to your mcporter config:
    
    ```bash
    mcporter config add ha-mcp \
      --stdio "cd /path/to/openclaw-xiaomi-home/scripts/ha-mcp-server && npm start"
    ```
    
    Or add it manually to `~/.openclaw/config/mcporter.json`:
    
    ```json
    {
      "servers": {
        "ha-mcp": {
          "command": "node",
          "args": ["/path/to/openclaw-xiaomi-home/scripts/ha-mcp-server/dist/index.js"],
          "env": {
            "HA_URL": "http://localhost:8123",
            "HA_TOKEN": "your_long_lived_token"
          }
        }
      }
    }
    ```
    
    ## Step 4: Get Home Assistant Token
    
    1. Open Home Assistant: http://localhost:8123
    2. Create account / Login
    3. Profile (your username) β†’ Security
    4. Create Long-Lived Access Token
    5. Copy the token
    
    ## Step 5: Update .env
    
    Edit `scripts/ha-mcp-server/.env`:
    
    ```
    HA_URL=http://localhost:8123
    HA_TOKEN=your_copied_token_here
    PORT=3002
    ```
    
    ## Step 6: Install ha_xiaomi_home Integration
    
    1. Home Assistant β†’ Settings β†’ Devices & Services
    2. Add Integration β†’ Search "Xiaomi Home"
    3. Click "Xiaomi Home" β†’ Continue
    4. Login with Xiaomi account
    5. Select your home and devices to import
    
    ## Step 7: Test
    
    After HA restarts and devices are imported, test:
    
    ```bash
    mcporter call ha-mcp.list_all_devices
    mcporter call ha-mcp.ping_ha
    ```
    
    ## Troubleshooting
    
    ### HA Container Won't Start
    
    Check logs:
    ```bash
    docker logs homeassistant
    ```
    
    ### Can't Login to Xiaomi
    
    The Xiaomi Cloud API may be blocked in your region. Use a VPN or enable LAN control in the integration settings.
    
    ### Devices Not Showing
    
    - Ensure devices are added to Mi Home app first
    - Check if device type is supported (no BLE/IR devices)
    - Try re-authorizing the Xiaomi account in integration settings
    
    ## Updating
    
    ```bash
    cd openclaw-xiaomi-home
    git pull
    cd scripts/ha-mcp-server
    npm install && npm run build
    docker compose restart homeassistant
    ```
    
  • .github/ISSUE_TEMPLATE/bug_report.md628 B003460b4115fupstream β†—
    ---
    name: "\U0001F41B Bug Report"
    about: Report something that isn't working correctly
    title: "[Bug] "
    labels: bug
    assignees: ''
    ---
    
    ## πŸ› Description
    [Describe the bug clearly and concisely]
    
    ## πŸ”„ Steps to Reproduce
    1. 
    2. 
    3. 
    
    ## βœ… Expected Behavior
    [What should happen]
    
    ## ❌ Actual Behavior
    [What actually happens]
    
    ## πŸ“‹ Environment
    - **Home Assistant version**: 
    - **openclaw-xiaomi-home version**: 
    - **Device type**: 
    - **macOS / Linux version**: 
    
    ## πŸ“Έ Screenshots / Logs
    [If applicable, add screenshots or relevant log output]
    
    ## πŸ” Additional Context
    [Add any other context about the problem here]
    
  • .github/ISSUE_TEMPLATE/config.yml405 B6732e04732f6upstream β†—
    blank_issues_enabled: false
    contact_links:
      - name: "\U0001F4AC General Question / Usage Help"
        url: https://github.com/canmaxfire/openclaw-xiaomi-home/discussions"
        about: Please ask and answer general questions here.
      - name: "\U0001F310 Installation Help"
        url: https://github.com/canmaxfire/openclaw-xiaomi-home#quick-start"
        about: Check the README for installation instructions first.
    
  • .github/ISSUE_TEMPLATE/feature_request.md737 B72711c6456d8upstream β†—
    ---
    name: "\U0001F31F Feature Request"
    about: Suggest a new feature or improvement
    title: "[Feature] "
    labels: enhancement
    assignees: ''
    ---
    
    ## ✨ Problem / Use Case
    [Describe the problem you want to solve, or the use case this feature would enable]
    
    ## πŸ’‘ Proposed Solution
    [Describe what you'd like to happen]
    
    ## πŸ”„ Current Workaround
    [If applicable, describe any workaround you're currently using]
    
    ## πŸ“‹ Alternative Solutions
    [Describe any alternative solutions or features you've considered]
    
    ## πŸ”§ Device / Integration
    [Is this related to a specific device type or Home Assistant integration?]
    - Device type: 
    - Home Assistant version: 
    
    ## πŸ“Έ Mockup / Examples
    [If applicable, add screenshots, diagrams, or examples]
    
  • .github/PULL_REQUEST_TEMPLATE.md789 Bb05275f73e2fupstream β†—
    ## πŸ“¦ Pull Request
    
    ### Description
    [Describe what changes this PR makes and why]
    
    ### Related Issue
    [Link to the issue this PR addresses, e.g. "Fixes #12"]
    
    ### Type of Change
    - [ ] Bug fix
    - [ ] New feature
    - [ ] Documentation update
    - [ ] Code refactoring
    - [ ] Other: 
    
    ### Testing
    [Describe what testing you've done]
    - [ ] Tested locally with Home Assistant
    - [ ] Tested with specific device(s): 
    - [ ] No testing done (please explain why)
    
    ### Checklist
    - [ ] My code follows the style guidelines of this project
    - [ ] I have performed a self-review of my own code
    - [ ] I have commented my code, particularly in hard-to-understand areas
    - [ ] I have made corresponding changes to the documentation
    - [ ] My changes generate no new warnings
    
    ### Screenshots / Logs
    [If applicable]
    
  • .gitignore41 B4274b5191944upstream β†—
    node_modules/
    dist/
    .env
    *.log
    .DS_Store
    
  • docker-compose.yml463 B545018b39c2bupstream β†—
    # Home Assistant + Xiaomi Home Integration
    # Usage: docker compose up -d
    
    services:
      homeassistant:
        container_name: homeassistant
        image: ghcr.io/home-assistant/home-assistant:stable
        privileged: true
        network_mode: host
        volumes:
          - ./config:/config
          - /etc/localtime:/etc/localtime:ro
        environment:
          - TZ=Asia/Shanghai
        restart: unless-stopped
        # For Apple Silicon Macs, you may need to add:
        # platform: linux/arm64
    
  • LICENSE1.0 KB1809662b5abbupstream β†—
    MIT License
    
    Copyright (c) 2026 Nana / OpenClaw
    
    Permission is hereby granted, free of charge, to any person obtaining a copy
    of this software and associated documentation files (the "Software"), to deal
    in the Software without restriction, including without limitation the rights
    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    copies of the Software, and to permit persons to whom the Software is
    furnished to do so, subject to the following conditions:
    
    The above copyright notice and this permission notice shall be included in all
    copies or substantial portions of the Software.
    
    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    SOFTWARE.
    

Plain-text copy, no login: /skill-bundles/canmaxfire-openclaw-xiaomi-home.md

// REPO STATS

1 stars
0 open issues
Last commit: 6mo ago