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:如何处理设备离线状态?
设计要点:
- 状态维护:Gateway维护节点在线状态表,心跳超时标记离线
- 命令队列:可选是否缓存离线命令(通过配置)
- 优雅降级:节点离线时,路由到备用节点或返回友好提示
- 自动重连:节点端实现断线重连机制
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:节点权限控制如何实现最小化原则?
最佳实践:
- 命令级白名单:每个节点只允许执行必要命令
- 资源访问限制:摄像头、位置等敏感权限按需申请
- 临时授权:高危操作需用户实时确认
- 审计日志:所有节点调用记录日志,便于追溯
七、结语:万物互联的AI时代
从25美元的安卓手机,到鱼塘里的增氧机,OpenClaw正在将AI的触角延伸到物理世界的每个角落。通过本文的实战,你已经掌握了:
- ✅ ADB控制安卓设备:远程拍照、安装应用、读取传感器
- ✅ MQTT控制IoT设备:灯光、空调、工业设备
- ✅ 多设备协同:PC+手机+传感器联动
- ✅ 安全加固:节点授权、命令白名单、传输加密
- ✅ 性能优化:长连接保活、断线重连
下一步,你可以尝试:
- 搭建手机集群,构建分布式感知网络
- 接入更多传感器(PM2.5、CO2、人体红外)
- 结合RAG和记忆系统,让AI"记住"设备状态变化
AI智能体的终极形态,不是某个强大的大脑,而是大脑与无数肢体的完美协同。OpenClaw正朝着这个方向大步前进。
本文所有Mermaid图均可直接复制到支持Mermaid的Markdown编辑器中查看。如果你在设备协同开发中遇到问题,欢迎在评论区留言交流。