第 37 章

边缘计算实战:树莓派 24/7 Always-On Agent Node 完整搭建

第37章:边缘计算实战:树莓派 24/7 Always-On Agent Node 完整搭建

概述

树莓派是 OpenClaw Headless Node 的最佳载体之一。它体积小、功耗低、可以全天候运行,价格亲民,且具备丰富的 GPIO 接口用于传感器接入。本章将从硬件选型开始,一步步带你将一块树莓派配置为一个生产级的 Always-On Agent Node:始终连接到你的 Gateway,随时响应 Agent 的远程命令,并能自主采集摄像头和传感器数据。


37.1 硬件选型

推荐配置

型号 RAM 推荐程度 适用场景
Raspberry Pi 5 (4GB) 4 GB 首选 高频命令执行、多传感器
Raspberry Pi 5 (8GB) 8 GB 旗舰 本地轻量推理 + Node 双用途
Raspberry Pi 4B (4GB) 4 GB 推荐 标准 Node 场景
Raspberry Pi 4B (2GB) 2 GB 可用 低负载纯命令执行
Raspberry Pi Zero 2W 512 MB 不推荐 RAM 太小,Node.js 22 吃力

推荐选择 Raspberry Pi 4B 4GB 或 Raspberry Pi 5 4GB。 Pi 5 的性能提升约 2-3 倍,USB 3.0 带宽对接摄像头更充裕。

必要配件

- MicroSD 卡:32GB+,Class 10 / A1 评级(推荐 Samsung EVO 系列)
- 电源:官方 USB-C 电源适配器(Pi 4B: 15W / Pi 5: 27W)
- 散热:主动散热风扇或铝制散热壳(7/24运行必备)
- 网络:有线以太网优先(稳定性 > 无线)
- 可选:USB 摄像头(Logitech C920 / Pi Camera Module 3)

存储建议

对于生产用途,强烈建议使用 SSD 替代 MicroSD 卡(通过 USB 3.0 转接):

# Pi 5 也支持 NVMe HAT(M.2 SSD 直连)
# SSD 相比 MicroSD 寿命提升约 10 倍,读写速度提升约 5 倍

37.2 系统配置

操作系统选择

系统 优点 适用场景
Ubuntu Server 24.04 LTS (ARM64) 软件包最新、与主流文档一致 推荐,生产首选
Raspberry Pi OS Lite (64-bit) 官方优化、硬件兼容性最好 需要 GPIO/Camera 模块时
Debian 12 Bookworm (ARM64) 最稳定 极低维护需求场景

本章以 Ubuntu Server 24.04 LTS ARM64 为例。

烧录系统

# 使用 Raspberry Pi Imager(推荐)
# 或使用 dd 命令(Linux/macOS):
sudo dd if=ubuntu-24.04-preinstalled-server-arm64+raspi.img.xz \
  of=/dev/sdX bs=4M status=progress conv=fsync

在 Raspberry Pi Imager 中,烧录前配置:

初次启动配置

# SSH 连接
ssh [email protected]

# 更新系统
sudo apt update && sudo apt upgrade -y

# 设置时区
sudo timedatectl set-timezone Asia/Shanghai

# 配置 hostname
sudo hostnamectl set-hostname openclaw-node-01

# 启用并配置防火墙(允许 SSH)
sudo ufw allow OpenSSH
sudo ufw enable

# 禁用不必要的服务(降低功耗)
sudo systemctl disable bluetooth
sudo systemctl disable cups
sudo systemctl stop bluetooth cups

内存优化配置

编辑 /boot/firmware/config.txt(Ubuntu)或 /boot/config.txt(Pi OS):

# 减少 GPU 内存分配(无图形界面时)
gpu_mem=16

# 启用 USB 引导(如果使用 SSD)
# program_usb_boot_mode=1

37.3 Node.js 22 LTS 安装

OpenClaw Node 需要 Node.js 22 LTS(当前 LTS 版本)。

方法一:使用 NodeSource 官方源(推荐)

# 安装 NodeSource 脚本
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -

# 安装 Node.js
sudo apt install -y nodejs

# 验证安装
node --version   # v22.x.x
npm --version    # 10.x.x

方法二:使用 nvm(适合开发机)

# 安装 nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.0/install.sh | bash

# 重新加载 shell
source ~/.bashrc

# 安装 Node.js 22
nvm install 22
nvm use 22
nvm alias default 22

验证环境

node --version
# v22.14.0

npm --version
# 10.9.2

# 验证 ARM64 架构
node -e "console.log(process.arch)"
# arm64

37.4 安装 OpenClaw Node

# 全局安装 OpenClaw CLI(包含 node 子命令)
sudo npm install -g @openclaw/cli

# 验证安装
openclaw --version
# openclaw 4.2.1

# 初始化 Node 配置
openclaw node init

openclaw node init 会引导你完成:

  1. 输入 Gateway 地址(例如:192.168.1.100mygateway.ts.net
  2. 设置节点显示名称(例如:Pi Node - Living Room
  3. 选择要声明的 Capability(Headless 模式默认 system.run
  4. 生成并保存节点 ID

配置文件默认保存在 ~/.openclaw/node.json

{
  "nodeId": "node-a1b2c3d4",
  "displayName": "Pi Node - Living Room",
  "gateway": {
    "host": "192.168.1.100",
    "port": 18789,
    "tls": false
  },
  "capabilities": ["system.run", "system.which"],
  "reconnect": {
    "enabled": true,
    "initialDelay": 5,
    "maxDelay": 300,
    "multiplier": 2
  }
}

37.5 远程连接命令

基本连接命令

# 前台运行(测试用)
openclaw node run \
  --host 192.168.1.100 \
  --port 18789 \
  --display-name "Pi Node - Living Room"

# 使用配置文件运行(推荐)
openclaw node run --config ~/.openclaw/node.json

# 连接到 Tailscale 地址的 Gateway
openclaw node run \
  --host mygateway.ts.net \
  --port 18789 \
  --display-name "Raspberry Pi 4B" \
  --tls

# 指定额外 Capability
openclaw node run \
  --host 192.168.1.100 \
  --port 18789 \
  --display-name "Pi Camera Node" \
  --capabilities system.run,system.which

连接验证

成功连接后,Gateway 侧输出:

[Gateway] Node connected: Pi Node - Living Room (node-a1b2c3d4)
[Gateway] Capabilities registered: system.run, system.which
[Gateway] Node status: pending (awaiting approval)

在 Gateway 主机上审批:

openclaw devices list
# ID          DISPLAY NAME           PLATFORM   STATUS
# req-x1y2    Pi Node - Living Room  headless   pending

openclaw devices approve req-x1y2
# ✓ Device approved: Pi Node - Living Room

37.6 架构图:Gateway 在云端,树莓派在本地

┌─────────────────────────────────────────────────────┐
│                      云端 (AWS)                       │
│                                                     │
│  ┌─────────────┐    ┌─────────────────────────────┐ │
│  │   OpenClaw  │    │        Gateway              │ │
│  │   Agent     │◄──►│   (推理 + 路由 + WebSocket) │ │
│  │  (LLM调用)  │    │   port: 18789               │ │
│  └─────────────┘    └──────────┬──────────────────┘ │
│                                │ WebSocket (TLS)     │
└────────────────────────────────┼────────────────────┘
                                 │
                    Internet / Tailscale VPN
                                 │
┌────────────────────────────────┼────────────────────┐
│                      本地网络                         │
│                                │                    │
│  ┌─────────────────────────────▼──────────────────┐ │
│  │              树莓派 4B / 5                       │ │
│  │                                                 │ │
│  │   openclaw node run (role: "node")              │ │
│  │                                                 │ │
│  │   Capabilities:                                 │ │
│  │   ✓ system.run  ← Shell 命令执行                │ │
│  │   ✓ system.which                                │ │
│  │                                                 │ │
│  │   可选扩展:                                      │ │
│  │   ✓ USB 摄像头 → camera.snap                   │ │
│  │   ✓ 温湿度传感器 (DHT22) → sensor.read         │ │
│  │   ✓ GPIO 控制 → gpio.write                     │ │
│  └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘

工作流程:
用户 → Control UI → Gateway → Agent 推理 →
Tool Call(system.run) → 路由至树莓派 →
本地执行命令 → 返回结果 → Agent → 用户

37.7 systemd 开机自启服务配置

创建专用用户(安全最佳实践)

# 创建无 shell 的系统用户
sudo useradd --system --no-create-home --shell /usr/sbin/nologin openclaw-node

# 创建配置目录
sudo mkdir -p /etc/openclaw /var/log/openclaw
sudo chown openclaw-node:openclaw-node /var/log/openclaw

# 复制配置文件
sudo cp ~/.openclaw/node.json /etc/openclaw/node.json
sudo chown openclaw-node:openclaw-node /etc/openclaw/node.json
sudo chmod 640 /etc/openclaw/node.json

systemd 服务单元文件

创建 /etc/systemd/system/openclaw-node.service

[Unit]
Description=OpenClaw Agent Node
Documentation=https://docs.openclaw.ai/nodes
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=300
StartLimitBurst=5

[Service]
Type=simple
User=openclaw-node
Group=openclaw-node

# 可执行文件路径(使用 which openclaw 确认)
ExecStart=/usr/bin/openclaw node run --config /etc/openclaw/node.json

# 工作目录
WorkingDirectory=/var/lib/openclaw

# 环境变量(不要在此处放置密钥,使用 EnvironmentFile)
Environment=NODE_ENV=production
Environment=LOG_LEVEL=info
EnvironmentFile=-/etc/openclaw/node.env

# 重启策略
Restart=on-failure
RestartSec=10s

# 日志输出
StandardOutput=append:/var/log/openclaw/node.log
StandardError=append:/var/log/openclaw/node-error.log

# 安全加固
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/var/lib/openclaw /var/log/openclaw /etc/openclaw
AmbientCapabilities=

# 资源限制
LimitNOFILE=65536
MemoryMax=512M

[Install]
WantedBy=multi-user.target

环境变量文件

创建 /etc/openclaw/node.env(600 权限):

# Node 特定环境变量(如有需要)
OPENCLAW_NODE_LOG_LEVEL=info
OPENCLAW_NODE_RECONNECT_ENABLED=true
sudo chown root:openclaw-node /etc/openclaw/node.env
sudo chmod 640 /etc/openclaw/node.env

创建工作目录

sudo mkdir -p /var/lib/openclaw
sudo chown openclaw-node:openclaw-node /var/lib/openclaw

启用并启动服务

# 重新加载 systemd 配置
sudo systemctl daemon-reload

# 启用开机自启
sudo systemctl enable openclaw-node

# 立即启动服务
sudo systemctl start openclaw-node

# 检查服务状态
sudo systemctl status openclaw-node

验证服务运行

# 查看实时日志
sudo journalctl -u openclaw-node -f

# 查看日志文件
sudo tail -f /var/log/openclaw/node.log

# 典型的正常启动日志:
# [2026-04-26 09:00:00] OpenClaw Node v4.2.1 starting...
# [2026-04-26 09:00:01] Connecting to Gateway: 192.168.1.100:18789
# [2026-04-26 09:00:02] WebSocket connected
# [2026-04-26 09:00:02] Capabilities declared: system.run, system.which
# [2026-04-26 09:00:03] Node status: online (node-a1b2c3d4)

37.8 摄像头接入与自动上报

硬件准备

USB 摄像头(推荐 Logitech C920):

# 检查摄像头识别
lsusb | grep -i logitech
# Bus 002 Device 003: ID 046d:082d Logitech, Inc. HD Pro Webcam C920

ls /dev/video*
# /dev/video0  /dev/video1

# 安装 ffmpeg
sudo apt install -y ffmpeg v4l-utils

# 测试拍照
ffmpeg -f v4l2 -i /dev/video0 -frames:v 1 /tmp/test.jpg

Raspberry Pi Camera Module 3(CSI 接口):

# Ubuntu 上启用 CSI 摄像头
echo "dtoverlay=imx708" | sudo tee -a /boot/firmware/config.txt

# Pi OS 上使用 libcamera
sudo apt install -y libcamera-apps
libcamera-jpeg -o /tmp/test.jpg --width 1920 --height 1080

为 Node 添加 camera.snap 能力

修改 /etc/openclaw/node.json

{
  "nodeId": "node-a1b2c3d4",
  "displayName": "Pi Camera Node",
  "gateway": {
    "host": "192.168.1.100",
    "port": 18789
  },
  "capabilities": ["system.run", "system.which", "camera.snap"],
  "camera": {
    "device": "/dev/video0",
    "snapCommand": "ffmpeg -f v4l2 -i /dev/video0 -frames:v 1 {output} -y",
    "outputDir": "/tmp/openclaw-camera"
  }
}

定时自动拍照上报

使用 Cron 任务(通过 Control UI 创建):

# 每30分钟拍一张照片
*/30 * * * * node_invoke camera.snap --node node-a1b2c3d4 --upload-to memory

或者通过 system.run 触发自定义脚本:

# /usr/local/bin/camera-snap.sh
#!/bin/bash
OUTPUT="/tmp/openclaw-camera/snap-$(date +%Y%m%d-%H%M%S).jpg"
mkdir -p /tmp/openclaw-camera
ffmpeg -f v4l2 -i /dev/video0 -frames:v 1 "$OUTPUT" -y -loglevel quiet
echo "$OUTPUT"

37.9 传感器数据采集方案(GPIO/I2C)

DHT22 温湿度传感器

# 安装 Python GPIO 库
sudo apt install -y python3-pip
pip3 install adafruit-circuitpython-dht

# 读取脚本:/usr/local/bin/read-dht22.py
#!/usr/bin/env python3
import adafruit_dht
import board
import json
import sys

dht = adafruit_dht.DHT22(board.D4)  # GPIO4

try:
    temperature = dht.temperature
    humidity = dht.humidity
    result = {
        "temperature_c": round(temperature, 1),
        "temperature_f": round(temperature * 9/5 + 32, 1),
        "humidity_percent": round(humidity, 1),
        "timestamp": __import__('time').time()
    }
    print(json.dumps(result))
except Exception as e:
    print(json.dumps({"error": str(e)}), file=sys.stderr)
    sys.exit(1)

Agent 通过 system.run 调用:

python3 /usr/local/bin/read-dht22.py
# {"temperature_c": 24.5, "temperature_f": 76.1, "humidity_percent": 58.3, "timestamp": 1745625600}

BMP280 气压传感器(I2C)

# 启用 I2C
sudo raspi-config nonint do_i2c 0
# 或编辑 /boot/firmware/config.txt 添加: dtparam=i2c_arm=on

# 检查 I2C 设备
i2cdetect -y 1
# 77: BMP280 默认地址

pip3 install adafruit-circuitpython-bmp280
#!/usr/bin/env python3
import adafruit_bmp280
import board
import busio
import json

i2c = busio.I2C(board.SCL, board.SDA)
bmp280 = adafruit_bmp280.Adafruit_BMP280_I2C(i2c)
bmp280.sea_level_pressure = 1013.25

print(json.dumps({
    "pressure_hpa": round(bmp280.pressure, 2),
    "altitude_m": round(bmp280.altitude, 1),
    "temperature_c": round(bmp280.temperature, 1)
}))

37.10 低功耗优化

CPU 降频配置

# 查看当前频率
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq

# 设置保守调频策略(适合持续轻负载)
echo "conservative" | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor

# 永久设置(编辑 /boot/firmware/config.txt)
# arm_freq=1500  # Pi 4B 默认 1800,降至 1500 节省约 15% 功耗
# over_voltage=0

禁用不必要的硬件

# 禁用 Wi-Fi(有线网络时)
sudo rfkill block wifi

# 禁用蓝牙
sudo rfkill block bluetooth

# 关闭 HDMI 输出(无显示器时节省约 25mA)
# 添加到 /etc/rc.local:
# /usr/bin/tvservice -o

# 禁用 USB 电源(若无 USB 设备,Pi 4B)
# echo '1-1' | sudo tee /sys/bus/usb/drivers/usb/unbind

典型功耗参考(Pi 4B)

配置 典型功耗
满负载(1.8GHz + USB 设备) ~6.4W
空闲(Wi-Fi 禁用,无 USB) ~2.7W
优化后(降频 + HDMI 关闭) ~2.1W
深度睡眠(不适合 Always-On) ~1.4W

37.11 常见问题排查

问题1:Node 频繁断线重连

# 检查网络稳定性
ping -c 100 192.168.1.100 | tail -5
# 若丢包率 > 1%,优先排查网络硬件

# 检查 Gateway 是否过载
openclaw gateway status

# 增大重连退避时间(避免风暴)
# 编辑 node.json:
# "reconnect": { "initialDelay": 10, "maxDelay": 600, "multiplier": 3 }

问题2:system.run 执行失败

# 检查可执行文件路径
which python3 ffmpeg bash

# openclaw-node 用户权限测试
sudo -u openclaw-node /usr/bin/python3 -c "print('ok')"

# 若需要访问 /dev/video0,添加用户到 video 组
sudo usermod -aG video openclaw-node
sudo systemctl restart openclaw-node

问题3:内存不足(OOM)

# 检查内存使用
free -h
sudo journalctl -k | grep -i "oom\|killed"

# 为 Node 进程添加内存限制保护
# 已在 systemd 文件中配置 MemoryMax=512M

# 若系统整体内存不足,增加 swap
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

问题4:Node 未在 Gateway 出现

# 确认防火墙允许出站 18789
sudo ufw status

# 测试 TCP 连通性
nc -zv 192.168.1.100 18789

# 检查 Node 日志
sudo journalctl -u openclaw-node --since "5 minutes ago"

# 常见原因:Gateway 地址错误、TLS 配置不匹配

问题5:摄像头权限拒绝

# 检查 /dev/video0 权限
ls -la /dev/video0
# crw-rw----+ 1 root video 81, 0 Apr 26 09:00 /dev/video0

# 确认用户已加入 video 组(需重启服务生效)
sudo usermod -aG video openclaw-node
sudo systemctl restart openclaw-node
groups openclaw-node
# openclaw-node : openclaw-node video

37.12 更新与维护

更新 OpenClaw Node

# 检查当前版本
openclaw --version

# 更新到最新稳定版
sudo npm update -g @openclaw/cli

# 更新后重启服务
sudo systemctl restart openclaw-node

日志轮转配置

创建 /etc/logrotate.d/openclaw-node

/var/log/openclaw/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    postrotate
        systemctl kill --signal=USR1 openclaw-node.service 2>/dev/null || true
    endscript
}

37.13 小结

通过本章的配置,你的树莓派现在是一个:

结合第36章介绍的能力矩阵,你已经完全掌握了将物理设备接入 OpenClaw Agent 的完整技术路径。下一章将聚焦 Control UI 的深度使用。


下一章:第38章 — Control UI 深度:配置编辑、实时日志、审批管理与 Dream Diary

本章评分
4.7  / 5  (3 评分)

💬 留言讨论