【OpenClaw:应用与协同】19、OpenClaw控制移动设备与物联网节点——ADB/MQTT集成实战

OpenClaw设备协同实战:用ADB控制安卓手机、MQTT联动智能家居,打造万物互联的AI智能体

从PC到移动设备,从数字世界到物理世界------让AI真正拥有"触角"

引言:OpenClaw的触角延伸

2026年的今天,AI智能体已经不再满足于"只会在电脑上回答问题"。真正的智能体应该能够:

  • 控制你的手机:远程安装应用、自动截图、读取传感器数据
  • 操控智能家居:通过语音指令开关灯光、调节空调
  • 跨设备协同:PC抓取数据,手机接收通知,IoT传感器触发自动化

OpenClaw通过其强大的节点(Node)机制插件化架构,将触角从单一PC延伸到了安卓手机、iOS设备、树莓派,乃至整个物联网世界。无论是25美元的廉价安卓机,还是鱼塘里的增氧机,都能成为OpenClaw的"手脚"。
客户端
IoT设备节点
移动设备节点
OpenClaw核心
Gateway网关

控制中枢
Android手机

Termux+ADB
iOS设备

Node App
MQTT Broker

消息代理
智能插座/灯光
传感器/增氧机
飞书/钉钉/WhatsApp
Web控制台

本文将深入OpenClaw的设备协同能力,通过两大实战案例------ADB控制安卓手机MQTT控制智能家居,带你构建真正的"万物互联AI智能体"。

一、Android设备控制:ADB集成实战

1.1 ADB与OpenClaw的结合方式

ADB(Android Debug Bridge)是安卓开发的通用调试工具,通过它我们可以实现:

  • 屏幕点击、滑动、输入
  • 应用安装与卸载
  • 截图与录屏
  • 读取传感器数据

OpenClaw通过节点机制将安卓设备纳入控制范围。有两种主流方案:

方案A:Termux方案(推荐,无需Root)

  • 在安卓手机上安装Termux(Linux环境模拟器)
  • 在Termux中运行OpenClaw Node
  • 通过Termux API调用安卓系统能力

方案B:ADB Server方案(适合多设备)

  • PC运行ADB Server
  • 通过USB/WiFi连接多台安卓设备
  • OpenClaw通过ADB命令控制设备

ADB Server方案
PC
ADB Server
Android设备1
Android设备2
Android设备3
Termux方案
Android手机
Termux
OpenClaw Node
Termux API
摄像头/闪光灯/传感器

1.2 环境搭建:在安卓手机上部署OpenClaw Node

参考开发者Ethan的实践,我们可以在25美元的廉价安卓手机上运行OpenClaw:

步骤1:安装Termux

  • 从F-Droid或GitHub下载Termux APK
  • 安装后打开,更新包管理器:
bash 复制代码
pkg update && pkg upgrade

步骤2:安装必要工具

bash 复制代码
pkg install nodejs git termux-api

步骤3:安装OpenClaw

bash 复制代码
npm install -g openclaw

步骤4:启动Node模式

bash 复制代码
# 连接到PC上的Gateway(假设Gateway IP为192.168.1.100)
openclaw node run --host 192.168.1.100 --port 18789 --display-name "Android-Node"

步骤5:在Gateway端授权

bash 复制代码
# 查看待授权的节点
openclaw nodes pending

# 授权节点
openclaw nodes approve <request-id>

1.3 开发ADB控制Skill

创建ADB控制Skill ~/.openclaw/skills/android-control/index.ts

typescript 复制代码
import { exec } from 'child_process';
import { promisify } from 'util';
import fs from 'fs-extra';

const execAsync = promisify(exec);

interface ADBParams {
  deviceId?: string;        // 指定设备ID,默认第一个设备
  action: 'tap' | 'swipe' | 'input' | 'screenshot' | 'install' | 'sensor';
  params: any;
}

export async function handler(params: ADBParams) {
  // 1. 获取设备列表
  const { stdout: devices } = await execAsync('adb devices');
  const deviceList = devices
    .split('\n')
    .filter(line => line.includes('\tdevice'))
    .map(line => line.split('\t')[0]);
  
  if (deviceList.length === 0) {
    return { code: 1, message: '未找到连接的Android设备' };
  }
  
  const deviceId = params.deviceId || deviceList[0];
  const adbBase = `adb -s ${deviceId}`;
  
  // 2. 根据action执行不同命令
  switch (params.action) {
    case 'tap':
      // 点击屏幕坐标
      await execAsync(`${adbBase} shell input tap ${params.params.x} ${params.params.y}`);
      return { code: 0, message: `点击 (${params.params.x}, ${params.params.y}) 成功` };
      
    case 'swipe':
      // 滑动
      await execAsync(`${adbBase} shell input swipe ${params.params.x1} ${params.params.y1} ${params.params.x2} ${params.params.y2} ${params.params.duration || 100}`);
      return { code: 0, message: '滑动成功' };
      
    case 'input':
      // 输入文本
      await execAsync(`${adbBase} shell input text "${params.params.text}"`);
      return { code: 0, message: `输入"${params.params.text}"成功` };
      
    case 'screenshot':
      // 截图
      const timestamp = Date.now();
      const remotePath = `/sdcard/screenshot_${timestamp}.png`;
      const localPath = `/tmp/screenshot_${timestamp}.png`;
      
      await execAsync(`${adbBase} shell screencap -p ${remotePath}`);
      await execAsync(`${adbBase} pull ${remotePath} ${localPath}`);
      await execAsync(`${adbBase} shell rm ${remotePath}`);
      
      // 将图片转为base64返回
      const imageBuffer = await fs.readFile(localPath);
      const base64 = imageBuffer.toString('base64');
      
      return {
        code: 0,
        message: '截图成功',
        data: { image: `data:image/png;base64,${base64}` }
      };
      
    case 'install':
      // 安装应用
      await execAsync(`${adbBase} install ${params.params.apkPath}`);
      return { code: 0, message: `应用安装成功` };
      
    case 'sensor':
      // 读取传感器(需要root或特殊权限)
      const { stdout: sensorData } = await execAsync(`${adbBase} shell dumpsys sensorservice`);
      return { code: 0, data: sensorData };
      
    default:
      return { code: 1, message: `不支持的动作: ${params.action}` };
  }
}

1.4 实战:远程控制手机拍照

通过飞书指令触发手机拍照并返回照片:

yaml 复制代码
# ~/.openclaw/commands/photo.yaml
name: photo
description: 远程控制手机拍照
usage: /photo [camera] [facing]
handler: ./handlers/photo.ts
options:
  - name: facing
    type: string
    enum: [front, back]
    default: back
    description: 摄像头方向
typescript 复制代码
// handlers/photo.ts
export async function handler(params: { facing: 'front' | 'back' }) {
  const deviceId = 'your-android-device-id'; // 可从配置读取
  
  // 调用ADB拍照(需手机安装Open Camera等支持命令行的相机应用)
  const cmd = `adb -s ${deviceId} shell am start -a android.media.action.IMAGE_CAPTURE`;
  await execAsync(cmd);
  
  // 等待拍照完成
  await new Promise(resolve => setTimeout(resolve, 3000));
  
  // 获取最新照片
  const { stdout } = await execAsync(`adb -s ${deviceId} shell ls -t /sdcard/DCIM/Camera/ | head -1`);
  const latestPhoto = stdout.trim();
  
  // 拉取到本地
  const localPath = `/tmp/photo_${Date.now()}.jpg`;
  await execAsync(`adb -s ${deviceId} pull /sdcard/DCIM/Camera/${latestPhoto} ${localPath}`);
  
  // 返回图片
  const imageBuffer = await fs.readFile(localPath);
  const base64 = imageBuffer.toString('base64');
  
  return {
    code: 0,
    message: `📸 拍照成功`,
    data: { image: `data:image/jpeg;base64,${base64}` }
  };
}

测试效果 :在飞书输入/photo back,手机后置摄像头拍照,图片通过飞书返回。

二、IoT设备控制:MQTT集成实战

2.1 MQTT协议与OpenClaw的结合

MQTT是物联网领域的标准消息协议,采用发布/订阅模式。OpenClaw通过MQTT Skill可以控制:

  • 智能灯光、插座
  • 空调、温控器
  • 传感器(温度、湿度、光照)
  • 工业设备(如增氧机)

OpenClaw Gateway
MQTT Skill
MQTT Broker

mosquitto/emqx
智能灯

订阅: home/light/+/set
智能插座

订阅: home/socket/+/set
传感器

发布: home/sensor/temperature
用户指令
返回执行结果

2.2 开发MQTT控制Skill

创建MQTT Skill ~/.openclaw/skills/mqtt-control/index.ts

typescript 复制代码
import mqtt from 'mqtt';

interface MQTTCmdParams {
  broker?: string;          // MQTT broker地址,默认从配置读取
  topic: string;            // 发布主题
  message: string | object; // 消息内容
  qos?: 0 | 1 | 2;          // QoS等级,默认0
  retain?: boolean;         // 是否保留消息,默认false
}

export async function handler(params: MQTTCmdParams) {
  // 从配置读取broker地址
  const brokerUrl = params.broker || process.env.MQTT_BROKER || 'mqtt://localhost:1883';
  
  return new Promise((resolve, reject) => {
    const client = mqtt.connect(brokerUrl);
    
    client.on('connect', () => {
      // 将消息转为字符串
      const messageStr = typeof params.message === 'object' 
        ? JSON.stringify(params.message) 
        : params.message;
      
      client.publish(
        params.topic,
        messageStr,
        {
          qos: params.qos || 0,
          retain: params.retain || false
        },
        (err) => {
          client.end();
          if (err) {
            reject({ code: 1, message: `发布失败: ${err.message}` });
          } else {
            resolve({
              code: 0,
              message: `已发布到 ${params.topic}: ${messageStr}`
            });
          }
        }
      );
    });
    
    client.on('error', (err) => {
      reject({ code: 1, message: `MQTT连接失败: ${err.message}` });
    });
    
    // 设置超时
    setTimeout(() => {
      client.end();
      reject({ code: 1, message: 'MQTT操作超时' });
    }, 5000);
  });
}

2.3 实战:通过飞书控制灯光和空调

创建控制命令 ~/.openclaw/commands/light.yaml

yaml 复制代码
name: light
description: 控制智能灯光
usage: /light [on|off|status]
handler: ./handlers/light.ts
options:
  - name: action
    type: string
    enum: [on, off, status]
    required: true
  - name: room
    type: string
    default: living
    description: 房间名称
typescript 复制代码
// handlers/light.ts
import { mqttSkill } from '../../skills/mqtt-control';

export async function handler(params: { action: string; room: string }) {
  const topic = `home/light/${params.room}/set`;
  const message = params.action === 'status' 
    ? { get: true } 
    : { state: params.action === 'on' ? 'ON' : 'OFF' };
  
  const result = await mqttSkill({
    topic,
    message
  });
  
  return result;
}

空调控制命令类似,增加温度和模式参数:

typescript 复制代码
// handlers/ac.ts
export async function handler(params: { 
  action: 'on' | 'off' | 'set';
  temperature?: number;
  mode?: 'cool' | 'heat' | 'fan';
  room?: string;
}) {
  const topic = `home/ac/${params.room || 'living'}/set`;
  const message = {
    state: params.action === 'set' ? 'ON' : params.action.toUpperCase(),
    temperature: params.temperature,
    mode: params.mode
  };
  
  return await mqttSkill({ topic, message });
}

2.4 实战:鱼塘增氧机自动控制

参考开发者Lupino的实践,我们可以用OpenClaw控制工业设备:

yaml 复制代码
# ~/.openclaw/skills/aerator-control.yaml
name: aerator-control
description: 控制鱼塘增氧机
params:
  action: on/off
  duration: 分钟(可选)
typescript 复制代码
// 增氧机控制逻辑
export async function handler(params: { action: 'on' | 'off'; duration?: number }) {
  // MQTT控制继电器
  const mqttTopic = 'fishpond/aerator/set';
  await mqttSkill({
    topic: mqttTopic,
    message: { state: params.action === 'on' ? 'ON' : 'OFF' }
  });
  
  // 如果指定了时长,设置定时关闭
  if (params.action === 'on' && params.duration) {
    const delay = params.duration * 60 * 1000;
    setTimeout(async () => {
      await mqttSkill({
        topic: mqttTopic,
        message: { state: 'OFF' }
      });
      // 通过飞书通知
      await sendFeishu(`⏰ 增氧机已运行${params.duration}分钟,自动关闭`);
    }, delay);
    
    return {
      code: 0,
      message: `增氧机已开启,将在${params.duration}分钟后自动关闭`
    };
  }
  
  return {
    code: 0,
    message: `增氧机已${params.action === 'on' ? '开启' : '关闭'}`
  };
}

效果:用户通过飞书发送"打开增氧机30分钟",OpenClaw通过MQTT启动继电器,30分钟后自动关闭并通知用户。

三、多设备协同场景

3.1 PC抓取数据,手机接收通知

User 安卓手机节点 Gateway PC节点 User 安卓手机节点 Gateway PC节点 Cron触发:每小时抓取数据 上报抓取结果 分析数据(超过阈值?) 发送push通知 震动+通知栏显示 用户查看

实现

typescript 复制代码
// PC端数据抓取Skill
async function crawlData() {
  const data = await fetch('https://api.example.com/prices');
  if (data.price > 100) {
    // 触发通知
    await openclaw.nodes.invoke({
      node: 'android-phone',
      command: 'notification.send',
      params: {
        title: '价格提醒',
        body: `价格已突破$100: ${data.price}`
      }
    });
  }
}

// 安卓端接收通知(通过Termux API)
// termux-notification -t "价格提醒" -c "价格已突破..."

3.2 IoT传感器触发PC自动化

PC节点 Gateway MQTT Broker 温度传感器 PC节点 Gateway MQTT Broker 温度传感器 发布温度30℃ 转发消息 规则匹配(温度>28℃) 执行降温脚本 启动空调/风扇

实现

typescript 复制代码
// 订阅传感器数据
mqttClient.subscribe('home/sensor/temperature');
mqttClient.on('message', async (topic, message) => {
  const temp = JSON.parse(message.toString()).value;
  
  if (temp > 28) {
    // 触发PC执行降温
    await openclaw.nodes.invoke({
      node: 'pc-node',
      command: 'system.run',
      params: {
        command: '/home/user/scripts/start-fan.sh'
      }
    });
  }
});

3.3 手机集群:分布式感知网络

受开发者Ethan的启发,我们可以用多台廉价安卓手机构建感知集群
Gateway
手机节点1

摄像头监控
手机节点2

环境传感器
手机节点3

备用/负载均衡
运动检测
温度/湿度
触发录像/告警
联动空调/加湿器

每台手机只需25美元,即可获得:

  • 摄像头(视觉感知)
  • 加速度计(震动检测)
  • 麦克风(声音监测)
  • 网络模块(数据传输)

四、安全考虑:设备授权与指令加密

4.1 节点授权机制

OpenClaw要求所有节点必须经过显式授权:

bash 复制代码
# 查看待授权节点
openclaw nodes pending

# 授权节点
openclaw nodes approve <request-id>

# 拒绝节点
openclaw nodes reject <request-id>

# 查看已授权节点
openclaw nodes list

4.2 指令执行权限控制

每个节点可以配置命令执行的白名单:

bash 复制代码
# 为节点添加允许执行的命令
openclaw approvals allowlist add --node "android-phone" "/system/bin/input"
openclaw approvals allowlist add --node "android-phone" "/system/bin/screencap"

# 查看节点权限
openclaw nodes describe --node "android-phone"

权限配置文件 ~/.openclaw/exec-approvals.json

json 复制代码
{
  "nodes": {
    "android-phone": {
      "allowlist": [
        "/system/bin/input",
        "/system/bin/screencap",
        "/data/data/com.termux/files/usr/bin/termux-camera-photo"
      ],
      "denylist": [
        "/system/bin/reboot",
        "/system/bin/rm"
      ]
    }
  }
}

4.3 传输加密

  • Gateway与节点之间使用WebSocket over TLS(wss://)
  • MQTT通信启用TLS,配置用户名/密码认证
  • 敏感数据(如摄像头画面)使用AES-256加密后再传输

4.4 局域网隔离最佳实践

对于家庭物联网场景,推荐网络隔离架构:
家庭局域网
外网
通过VPN/隧道
内网通信
用户手机
OpenClaw Gateway

内网IP
MQTT Broker

内网IP
智能设备

内网IP

  • Gateway不暴露公网端口,通过Tailscale/WireGuard访问
  • MQTT Broker绑定内网IP,拒绝外网连接
  • 智能设备隔离在独立VLAN

五、性能优化:长连接保活与断线重连

5.1 WebSocket长连接保活

节点与Gateway之间通过WebSocket保持长连接,心跳机制:

typescript 复制代码
// 节点端心跳实现
class NodeConnection {
  private ws: WebSocket;
  private heartbeatInterval: NodeJS.Timeout;
  
  connect() {
    this.ws = new WebSocket('ws://gateway:18789');
    
    this.ws.on('open', () => {
      // 每30秒发送一次心跳
      this.heartbeatInterval = setInterval(() => {
        this.ws.send(JSON.stringify({ type: 'heartbeat', timestamp: Date.now() }));
      }, 30000);
    });
    
    this.ws.on('close', () => {
      clearInterval(this.heartbeatInterval);
      // 断线重连,指数退避
      setTimeout(() => this.connect(), 5000);
    });
    
    this.ws.on('message', (data) => {
      const msg = JSON.parse(data.toString());
      if (msg.type === 'heartbeat_ack') {
        // 心跳响应,连接正常
      }
    });
  }
}

5.2 断线重连策略

采用指数退避算法避免网络风暴:

typescript 复制代码
async function connectWithBackoff(attempt = 1) {
  const maxAttempts = 10;
  const baseDelay = 1000; // 1秒
  
  try {
    await connect();
    console.log('连接成功');
  } catch (err) {
    if (attempt >= maxAttempts) {
      console.error('达到最大重试次数');
      return;
    }
    
    const delay = baseDelay * Math.pow(2, attempt - 1) + Math.random() * 1000;
    console.log(`第${attempt}次重试,等待${Math.round(delay)}ms`);
    
    setTimeout(() => connectWithBackoff(attempt + 1), delay);
  }
}

5.3 命令执行超时控制

避免耗时操作阻塞节点:

typescript 复制代码
// 带超时的命令执行
async function executeWithTimeout(cmd: string, timeoutMs = 30000) {
  return Promise.race([
    execAsync(cmd),
    new Promise((_, reject) => 
      setTimeout(() => reject(new Error('执行超时')), timeoutMs)
    )
  ]);
}

六、面试考点:异构设备统一控制的设计模式

Q1:OpenClaw如何实现多种异构设备的统一控制?

核心答案 :通过节点抽象+能力声明模式。
统一调用接口
Gateway
节点抽象层
Android节点

实现camera.*
iOS节点

实现camera./location.
Linux节点

实现system./canvas.
MQTT节点

实现mqtt.publish

每个节点连接Gateway时,会声明自己支持的能力(capabilities):

  • camera.snap:支持拍照
  • screen.record:支持录屏
  • system.run:支持执行命令
  • location.get:支持获取位置

Gateway根据能力声明动态路由指令,上层应用无需关心底层设备差异。

Q2:节点与Gateway的通信协议如何设计?

标准答案:基于WebSocket的JSON-RPC协议。

json 复制代码
// 节点发送能力声明
{
  "type": "node.register",
  "role": "node",
  "capabilities": ["camera.snap", "screen.record", "location.get"],
  "displayName": "Android-Phone-1"
}

// Gateway发送命令调用
{
  "type": "node.invoke",
  "command": "camera.snap",
  "params": { "facing": "back" },
  "id": "req-123"
}

// 节点返回结果
{
  "type": "node.invoke.response",
  "id": "req-123",
  "result": { "image": "base64data..." }
}

Q3:如何处理设备离线状态?

设计要点

  1. 状态维护:Gateway维护节点在线状态表,心跳超时标记离线
  2. 命令队列:可选是否缓存离线命令(通过配置)
  3. 优雅降级:节点离线时,路由到备用节点或返回友好提示
  4. 自动重连:节点端实现断线重连机制

Q4:跨设备任务的分布式一致性如何保证?

解决方案 :采用事务性工作流+补偿机制

typescript 复制代码
async function distributedTask() {
  // 步骤1:在手机A拍照
  const photo = await nodeA.invoke('camera.snap');
  
  try {
    // 步骤2:在PC处理照片
    await nodeB.invoke('image.process', { photo });
    
    // 步骤3:通过MQTT控制设备
    await mqttNode.invoke('mqtt.publish', { topic: 'device/light', message: 'ON' });
  } catch (err) {
    // 失败时执行补偿:关闭灯光,通知用户
    await mqttNode.invoke('mqtt.publish', { topic: 'device/light', message: 'OFF' });
    await notifyUser('任务执行失败,已回滚');
  }
}

Q5:节点权限控制如何实现最小化原则?

最佳实践

  1. 命令级白名单:每个节点只允许执行必要命令
  2. 资源访问限制:摄像头、位置等敏感权限按需申请
  3. 临时授权:高危操作需用户实时确认
  4. 审计日志:所有节点调用记录日志,便于追溯

七、结语:万物互联的AI时代

从25美元的安卓手机,到鱼塘里的增氧机,OpenClaw正在将AI的触角延伸到物理世界的每个角落。通过本文的实战,你已经掌握了:

  • ADB控制安卓设备:远程拍照、安装应用、读取传感器
  • MQTT控制IoT设备:灯光、空调、工业设备
  • 多设备协同:PC+手机+传感器联动
  • 安全加固:节点授权、命令白名单、传输加密
  • 性能优化:长连接保活、断线重连

下一步,你可以尝试:

  • 搭建手机集群,构建分布式感知网络
  • 接入更多传感器(PM2.5、CO2、人体红外)
  • 结合RAG和记忆系统,让AI"记住"设备状态变化

AI智能体的终极形态,不是某个强大的大脑,而是大脑与无数肢体的完美协同。OpenClaw正朝着这个方向大步前进。


本文所有Mermaid图均可直接复制到支持Mermaid的Markdown编辑器中查看。如果你在设备协同开发中遇到问题,欢迎在评论区留言交流。

相关推荐
熊猫钓鱼>_>2 小时前
OpenClaw 多平台接入:让 AI 助理接管你的工作与生活
人工智能·ai·自动化·生活·skills·agent skills·openclaw
Saniffer_SH2 小时前
【高清视频】介绍一个自动化测试辅助小工具 - 上下电测试适用于电脑冷启动的掉电盒
网络·人工智能·驱动开发·嵌入式硬件·测试工具·计算机外设·压力测试
marsh02062 小时前
2 为什么选择OpenClaw?深入分析其技术优势与商业价值
人工智能·ai·数据挖掘·编程·技术
安科瑞-小李2 小时前
分布式光伏与虚拟储能联合优化调度策略研究
大数据·人工智能·充电桩·碳交易·碳管理
德迅云安全-小潘2 小时前
智能风暴:2026年网络安全进入“AI对攻”时代
人工智能·安全·web安全
大傻^2 小时前
【OpenClaw -08】OpenClaw 上下文管理深度实战:从 Context Pruning 到 Token 成本优化
openclaw·llm 上下文管理·token 优化·ai agent 架构
万少2 小时前
为什么你的龙虾 openclaw 搜索网络资讯的技能不好用
人工智能
多恩Stone2 小时前
【SLURM 入门】sbatch 等概念与常用命令
人工智能·python