← 返回首页

1. 项目概述

📌 小布米简介

身高94cm
体重12kg
自由度21个
价格¥9998
公司北京松延动力 (Noetix Robotics)

🎯 可实现场景

  • 远程监控 + AI 对话 - 远程查看家中情况,语音聊天
  • 舵机控制开关 - 物理按压墙壁开关
  • 红外控制家电 - 控制空调、电视、风扇
  • 智能插座控制 - 控制台灯、风扇等

2. 硬件清单

场景配件数量价格难度
场景1 小布米自带(摄像头/麦克风/扬声器) 1 ¥0 简单
场景2 舵机 MG996R 4 ¥60 困难
PCA9685 I2C控制板 1 ¥15
3D打印手指支架 1 ¥30
杜邦线+电源 1 ¥20
场景3 红外发射管 + 38KHz模块 1 ¥20 中等
场景4 WiFi智能插座 若干 ¥30-50/个 简单
总计(全部场景) 约 ¥145-200

3. 场景一:远程监控 + AI 对话

🎯 目标

通过 QQ/微信/Telegram 远程查看小布米摄像头画面,并进行 AI 对话

3.1 部署服务(小布米端)

在有小布米上安装 Python 环境并创建服务:

mkdir -p ~/xiaoao-robot && cd ~/xiaoao-robot pip install flask flask-cors opencv-python numpy pyaudio gTTS

创建主服务文件 ~/xiaoao-robot/main.py

#!/usr/bin/env python3 """小布米机器人控制服务 - 远程监控+AI对话""" from flask import Flask, request, jsonify, send_file from flask_cors import CORS import cv2 import numpy as np import threading import base64 import io from gtts import gTTS import os import time app = Flask(__name__) CORS(app) # 全局变量 camera = None audio_buffer = [] current_frame = None def init_camera(): """初始化摄像头""" global camera camera = cv2.VideoCapture(0) camera.set(3, 640) # 宽度 camera.set(4, 480) # 高度 def generate_frames(): """生成视频流""" global current_frame while True: if camera is not None: success, frame = camera.read() if success: current_frame = frame # 压缩为 JPEG ret, buffer = cv2.imencode('.jpg', frame) if ret: frame_bytes = buffer.tobytes() yield (b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n') time.sleep(0.03) # 约30fps @app.route('/camera/stream') def stream_camera(): """视频流端点""" return Response(generate_frames(), mimetype='multipart/x-mixed-replace; boundary=frame') @app.route('/camera/snapshot') def snapshot(): """拍照端点""" global current_frame if current_frame is not None: _, buffer = cv2.imencode('.jpg', current_frame) return send_file(io.BytesIO(buffer), mimetype='image/jpeg') return jsonify({'error': 'No frame available'}), 400 @app.route('/camera/snapshot/base64') def snapshot_base64(): """返回 Base64 编码的图片(用于发送给 OpenClaw)""" global current_frame if current_frame is not None: _, buffer = cv2.imencode('.jpg', current_frame) img_base64 = base64.b64encode(buffer).decode('utf-8') return jsonify({'image': f'data:image/jpeg;base64,{img_base64}'}) return jsonify({'error': 'No frame available'}), 400 @app.route('/tts/speak', methods=['POST']) def speak(): """文字转语音端点""" data = request.json text = data.get('text', '') lang = data.get('lang', 'zh-CN') if not text: return jsonify({'error': 'No text provided'}), 400 # 生成语音 tts = gTTS(text=text, lang=lang) audio_file = io.BytesIO() tts.write_to_fp(audio_file) audio_file.seek(0) return send_file(audio_file, mimetype='audio/mp3') @app.route('/status') def status(): """服务状态""" return jsonify({ 'status': 'running', 'camera': camera is not None, 'timestamp': time.time() }) if __name__ == '__main__': init_camera() print("🚀 小布米服务启动: http://0.0.0.0:5000") app.run(host='0.0.0.0', port=5000, debug=False)

3.2 后台运行

# 使用 screen 或 nohup 后台运行 cd ~/xiaoao-robot nohup python3 main.py > robot.log 2>&1 & # 或使用 systemd(推荐) sudo tee /etc/systemd/system/xiaoao-robot.service > /dev/null <

3.3 API 端点总结

端点方法说明
/camera/streamGET视频流 (MJPEG)
/camera/snapshotGET拍照 (JPEG)
/camera/snapshot/base64GETBase64 图片 (JSON)
/tts/speakPOST文字转语音
/statusGET服务状态

⚠️ 注意事项

  • 确保小布米和小布米在同一局域网
  • 如需外网访问,需配置端口转发或 VPN
  • 如需 https,使用 nginx 反向代理

4. 场景二:舵机控制开关

🎯 目标

通过 OpenClaw 控制舵机,物理按压墙壁开关

4.1 硬件接线

PCA9685 引脚连接:
├── SCL → 小布米 I2C SCL
├── SDA → 小布米 I2C SDA  
├── VCC → 5V 电源正极
└── GND → GND

舵机连接:
├── 舵机0 → PCA9685 通道0 (客厅灯)
├── 舵机1 → PCA9685 通道1 (卧室灯)
├── 舵机2 → PCA9685 通道2 (厨房灯)
└── 舵机3 → PCA9685 通道3 (卫生间灯)

4.2 安装依赖

sudo apt-get install -y python3-pip i2c-tools pip3 install adafruit-circuitpython-servokit smbus2 # 开启 I2C 接口 sudo raspi-config # 选择 Interface Options → I2C → Enable

4.3 舵机控制服务

#!/usr/bin/env python3 """舵机控制服务 - 控制开关""" from flask import Flask, request, jsonify from adafruit_servokit import ServoKit import time app = Flask(__name__) # 初始化 PCA9685 (16通道) kit = ServoKit(channels=16) # 开关位置映射 SWITCH_MAP = { '客厅灯': {'servo': 0, 'angle_press': 90, 'angle_reset': 0}, '卧室灯': {'servo': 1, 'angle_press': 90, 'angle_reset': 0}, '厨房灯': {'servo': 2, 'angle_press': 90, 'angle_reset': 0}, '卫生间灯': {'servo': 3, 'angle_press': 90, 'angle_reset': 0}, } def press_switch(servo_id, press_angle=90, reset_angle=0, hold_time=0.5): """按压开关""" try: servo = kit.servo[servo_id] # 按下 servo.angle = press_angle time.sleep(hold_time) # 复位 servo.angle = reset_angle return True except Exception as e: print(f"Error: {e}") return False @app.route('/switch/', methods=['POST']) def control_switch(device): """控制开关""" data = request.json or {} action = data.get('action', 'toggle') # toggle, on, off if device not in SWITCH_MAP: return jsonify({'error': f'Unknown device: {device}'}), 404 config = SWITCH_MAP[device] success = press_switch(config['servo'], config['angle_press'], config['angle_reset']) return jsonify({ 'device': device, 'action': action, 'success': success }) @app.route('/switches') def list_switches(): """列出所有开关""" return jsonify({ 'devices': list(SWITCH_MAP.keys()), 'map': SWITCH_MAP }) @app.route('/calibrate', methods=['POST']) def calibrate(): """校准舵机""" data = request.json servo_id = data.get('servo', 0) angle = data.get('angle', 90) kit.servo[servo_id].angle = angle return jsonify({'servo': servo_id, 'angle': angle}) if __name__ == '__main__': print("🎮 舵机服务启动: http://0.0.0.0:5001") app.run(host='0.0.0.0', port=5001, debug=False)

4.4 校准步骤

  1. 运行服务后,通过 API 调整舵机角度
  2. 找到手指对准开关的角度
  3. 更新 SWITCH_MAP 中的 angle_press 值
  4. 测试开关是否正常

⚠️ 难点提醒

  • 3D 打印手指支架需要精确设计
  • 不同开关位置需要单独校准
  • 建议添加限位开关防止舵机过转

5. 场景三:红外控制家电

🎯 目标

通过红外发射控制空调、电视、风扇等红外设备

5.1 硬件

红外发射管VS1838B 或 通用 38KHz 模块
连接GPIO 18 (BCM) 或任意 PWM 引脚

5.2 安装 LIRC

sudo apt-get install -y lirc # 编辑 /boot/config.txt 添加: # dtoverlay=lirc-rpi,gpio_in_pin=18,gpio_out_pin=17 # 编辑 /etc/lirc/lircd.conf.d/ 添加强制码

5.3 红外控制服务

#!/usr/bin/env python3 """红外控制服务""" from flask import Flask, request, jsonify import subprocess import time app = Flask(__name__) # 红外命令映射(需要先用 irw 录制) COMMANDS = { '空调开': 'KEY_POWERON', '空调关': 'KEY_POWEROFF', '空调升温': 'KEY_TEMPUP', '空调降温': 'KEY_TEMPDOWN', '电视开': 'KEY_POWER', '电视音量加': 'KEY_VOLUMEUP', '电视音量减': 'KEY_VOLUMEDOWN', } def send_ir(command): """发送红外命令""" try: subprocess.run(['irsend', 'SEND_ONCE', 'ac_remote', command], check=True, capture_output=True) return True except Exception as e: print(f"IR Error: {e}") return False @app.route('/ir/', methods=['POST']) def ir_control(command): """发送红外命令""" if command not in COMMANDS: return jsonify({'error': 'Unknown command'}), 404 success = send_ir(COMMANDS[command]) return jsonify({'command': command, 'success': success}) @app.route('/ir/list') def list_commands(): """列出可用命令""" return jsonify({'commands': list(COMMANDS.keys())}) if __name__ == '__main__': print("📡 红外服务启动: http://0.0.0.0:5002") app.run(host='0.0.0.0', port=5002, debug=False)

5.4 录制红外码

# 1. 停止 LIRC sudo systemctl stop lircd # 2. 录制遥控器按键 mode2 -d /dev/lirc0 | irrecord -d /dev/lirc0 my_remote.conf # 3. 复制配置 sudo cp my_remote.conf /etc/lirc/lircd.conf.d/ # 4. 重启 LIRC sudo systemctl start lircd # 5. 测试 irsend LIST ac_remote "" irsend SEND_ONCE ac_remote KEY_POWERON

6. 场景四:智能插座控制

🎯 目标

通过 WiFi 智能插座控制普通电器(台灯、风扇等)

6.1 推荐硬件

型号协议价格备注
小米米家插座米家/小米¥50需米家APP
TP-Link KasaKasa¥40支持 API
涂鸦智能插座Tuya¥30需配网
ESP01S 继电器自建¥15需要动手

6.2 涂鸦智能插座方案

#!/usr/bin/env python3 """智能插座控制服务 (Tuya)""" from flask import Flask, request, jsonify import tinytuya app = Flask(__name__) # 插座配置(从 涂鸦APP 获取) DEVICES = { '客厅台灯': {'id': 'bf1234567890abcdef', 'key': '你的设备key', 'ip': '192.168.1.xxx'}, '卧室风扇': {'id': 'bf1234567890abcdef', 'key': '你的设备key', 'ip': '192.168.1.xxx'}, } def get_device(name): """获取设备""" if name not in DEVICES: return None cfg = DEVICES[name] d = tinytuya.OutletDevice(cfg['id'], cfg['ip'], cfg['key']) d.set_version(3.3) return d @app.route('/plug//on', methods=['POST']) def plug_on(name): """打开插座""" d = get_device(name) if d: d.turn_on() return jsonify({'device': name, 'state': 'on'}) return jsonify({'error': 'Device not found'}), 404 @app.route('/plug//off', methods=['POST']) def plug_off(name): """关闭插座""" d = get_device(name) if d: d.turn_off() return jsonify({'device': name, 'state': 'off'}) return jsonify({'error': 'Device not found'}), 404 @app.route('/plug//status', methods=['GET']) def plug_status(name): """查询状态""" d = get_device(name) if d: status = d.status() return jsonify({'device': name, 'status': status}) return jsonify({'error': 'Device not found'}), 404 @app.route('/plugs') def list_plugs(): """列出所有插座""" return jsonify({'devices': list(DEVICES.keys())}) if __name__ == '__main__': print("🔌 智能插座服务: http://0.0.0.0:5003") app.run(host='0.0.0.0', port=5003, debug=False)

💡 小技巧

推荐使用 ESP01S + 继电器 方案,可以自己焊接,成本最低 ¥15

7. OpenClaw 集成

🎯 目标

让 OpenClaw 能够调用小布米的各种能力

7.1 创建 Skill

在 OpenClaw workspace 创建 skill 目录:

mkdir -p ~/.openclaw/skills/xiaoao-robot cd ~/.openclaw/skills/xiaoao-robot # 创建 skill 配置 cat > SKILL.md << 'EOF' # 小布米机器人 Skill ## 能力 - 摄像头监控 - 语音对话 - 控制开关 - 家电控制 ## API 端点 - 摄像头: http://小布米IP:5000/ - 舵机: http://小布米IP:5001/ - 红外: http://小布米IP:5002/ - 插座: http://小布米IP:5003/ EOF # 创建工具脚本 mkdir -p tools cat > tools/camera.py << 'EOF' #!/usr/bin/env python3 import requests import sys ip = sys.argv[1] if len(sys.argv) > 1 else "192.168.1.100" resp = requests.get(f"http://{ip}:5000/camera/snapshot/base64") data = resp.json() print(data.get('image', '')) EOF chmod +x tools/*.py

7.2 配置 OpenClaw

# 在 OpenClaw 控制台或配置文件中添加工具 # openclaw.json 示例配置: { "skills": { "xiaoao-robot": { "enabled": true, "tools": ["camera", "servo", "ir", "plug"] } }, "agents": { "defaults": { "model": "qwen3.5-plus" } } }

7.3 使用示例

用户: "帮我看看家里现在什么样"
OpenClaw → 调用摄像头API → 返回画面 → 发送给用户

用户: "帮我打开客厅灯"
OpenClaw → 调用舵机API → 小布米伸手按开关 → 确认完成

用户: "好热啊,开下空调"
OpenClaw → 调用红外API → 发送空调开启指令

用户: "帮我关掉台灯"
OpenClaw → 调用插座API → 关闭对应插座
            

7.4 完整 Skill 目录结构

~/.openclaw/skills/xiaoao-robot/ ├── SKILL.md # Skill 描述 ├── tools/ │ ├── __init__.py │ ├── camera.py # 摄像头工具 │ ├── servo.py # 舵机工具 │ ├── ir.py # 红外工具 │ └── plug.py # 插座工具 └── config.yaml # 配置文件

8. 常见问题

Q1: 小布米是什么系统?

小布米基于 Android 系统,可以通过 ADB 连接或安装 Termux 来运行 Python 服务。

Q2: 如何连接小布米?

  1. 开启开发者模式:设置 → 关于手机 → 连续点击版本号7次
  2. 开启 USB 调试:开发者选项 → USB 调试
  3. 通过 ADB 连接:adb connect 小布米IP:5555

Q3: 没有智能家居能实现控制吗?

可以!通过方案2(舵机按开关)或方案3(红外控制)可以在不更换现有设备的情况下实现控制。

Q4: 舵机力度不够怎么办?

选择扭矩更大的舵机(如 MG996R 扭矩约 2.5kg/cm),或使用金属齿轮舵机。

Q5: 如何实现外网控制?

方案:1) 配置 VPN 连接家庭网络;2) 使用内网穿透(如 frp、ngrok);3) 部署到有公网IP的服务器。

📐 整体架构图

用户 (QQ/微信/Telegram/Discord)
            │
            ▼
    ┌─────────────────────────┐
    │   OpenClaw Gateway      │
    │   (AI Agent)            │
    └───────────┬─────────────┘
                │
    ┌───────────┴─────────────┐
    │   Skill: xiaoao-robot   │
    │   (工具调用)            │
    └───────────┬─────────────┘
                │
    ┌───────────┴─────────────┐
    │   小布米控制服务       │
    │   (Flask API Server)    │
    └───────────┬─────────────┘
                │
    ┌───────────┼─────────────┐
    │           │             │
    ▼           ▼             ▼
摄像头    舵机控制    红外/插座
            │             │
            ▼             ▼
        手指按开关   设备开关
← 返回上一页