Tools
My Peripheral
openclaw my-peripheral-plugin
Install
npm install
```
Configuration Example
{
"plugins": {
"entries": {
"my-peripheral-plugin": {
"enabled": true,
"config": {
"gatewayEndpoint": "http://127.0.0.1:8080",
"defaultDeviceId": "ws63-demo-01"
}
}
}
}
}
README
# my-peripheral-plugin
**通用 IoT 外设网关插件** — 零代码接入任意设备
Go | TypeScript | JSON 描述符驱动
[快速开始](#快速开始) | [使用方式](#使用方式) | [添加新设备](#添加新设备) | [API 参考](#gateway-api) | [示例](#示例)
---
## 插件概览
| 基础工具 | 动态工具 | 协议 | 设备描述符 |
|:---:|:---:|:---:|:---:|
| **9** | **自动生成** | **3** | **JSON** |
| 始终可用 | 按设备命令注册 | UPM / REST / MIXED | 新设备零代码接入 |
## 这是什么
my-peripheral-plugin 是一个运行在 OpenClaw 平台上的通用外设网关插件。通过中间层 Go Gateway 与实际硬件通信,支持任意 IoT 设备接入。
核心特性:
- **零代码接入** — 新设备只需写一个 JSON 描述符,无需改任何代码
- **动态命令发现** — Gateway 注册了什么命令,Plugin 自动生成对应工具
- **多协议支持** — UPM 二进制协议、REST HTTP、混合模式
- **风险分级** — 高危命令自动标记,执行前需用户确认
架构:
```
Agent 对话
└─ Plugin(TypeScript,进程内)
└─ Go Gateway(REST API,独立进程)
└─ 设备(HI3863 / ESP32 / STM32 / ...)
```
## 项目结构
```
my_peripheral_plugin/
├── openclaw.plugin.json # 插件清单(平台识别入口,文件名不可改)
├── package.json # npm 依赖
├── index.ts # 插件主入口
├── SKILL.md # Agent 技能描述
├── src/
│ ├── gateway-client.ts # Gateway HTTP 客户端
│ ├── base-tools.ts # 9 个基础工具
│ ├── tool-discovery.ts # 动态命令发现与工具注册
│ └── types/
│ └── openclaw-plugin-sdk.d.ts # 平台 SDK 类型声明(最小化)
├── gateway/ # Go Gateway 后端
│ ├── cmd/ # 程序入口
│ ├── internal/ # 业务逻辑(命令路由、设备管理、REST API)
│ ├── configs/devices/ # 设备描述符(新设备加在这里)
│ │ ├── index.json # 描述符索引
│ │ └── profiles/ # 设备配置文件
│ │ ├── hi3863.json # HI3863 WiFi/BLE/SLE 模组
│ │ └── generic-upm.json # 通用 UPM 示例
│ ├── Dockerfile # 容器构建
│ └── deployments/ # docker-compose
└── examples/ # 新设备接入示例
├── esp32-sensor.json # REST 协议 - 温湿度传感器
└── stm32-motor-upm.json # UPM 协议 - 电机控制器
```
---
## 快速开始
### 前置条件
| 依赖 | 版本 | 用途 |
|------|------|------|
| Go | 1.23+ | 编译 Gateway |
| OpenClaw | 最新版 | 宿主平台 |
**1. 启动 Go Gateway:**
```bash
cd gateway
go build -o gateway ./cmd/my_peripheral_plugin
./gateway
# 输出: my_peripheral_plugin starting at 127.0.0.1:8080
```
**2. 将插件放入扩展目录:**
```bash
# 项目级(推荐,仅当前项目生效)
cp -r my-peripheral-plugin <项目>/.openclaw/extensions/my-peripheral-plugin
# 或用户级(全局生效)
cp -r my-peripheral-plugin ~/.openclaw/extensions/my-peripheral-plugin
# 安装依赖(仅首次)
cd <目标路径>/my-peripheral-plugin
npm install
```
安装包极小:仅 2 个依赖(@sinclair/typebox + typescript),约 26MB。
平台 SDK 由 OpenClaw 运行时通过 jiti 别名注入,不需要本地安装。
**3. 在配置文件中启用:**
配置文件路径为 `~/.openclaw/openclaw.json`(Windows 为 `%USERPROFILE%\.openclaw\openclaw.json`),
在 `plugins.entries` 中添加:
```json
{
"plugins": {
"entries": {
"my-peripheral-plugin": {
"enabled": true,
"config": {
"gatewayEndpoint": "http://127.0.0.1:8080",
"defaultDeviceId": "ws63-demo-01"
}
}
}
}
}
```
### Docker 环境部署
> 以下内容适用于 OpenClaw 以 Docker Compose 方式运行的场景。
> 如果 OpenClaw 运行在宿主机上,请使用上方标准流程。
#### 前置条件
| 依赖 | 版本 | 用途 |
|------|------|------|
| Docker | 20+ | 容器化运行 |
| OpenClaw | 最新版 | Docker 镜像已构建 |
#### 1. 在 OpenClaw 的 `docker-compose.yml` 中添加 `peripheral-gateway` 服务
```yaml
services:
peripheral-gateway:
build:
context: ./extensions/my-peripheral-plugin/gateway
dockerfile: Dockerfile
environment:
MY_PERIPHERAL_PLUGIN_BIND_ADDR: "0.0.0.0:8080"
MY_PERIPHERAL_PLUGIN_DESCRIPTOR_INDEX: "configs/devices/index.json"
MY_PERIPHERAL_PLUGIN_CACHE_TTL: "30s"
MY_PERIPHERAL_PLUGIN_AUDIT_STORE: "memory"
MY_PERIPHERAL_PLUGIN_IDEMPOTENCY_TTL: "24h"
ports:
- "127.0.0.1:8080:8080"
restart: unless-stopped
openclaw-gateway:
# ... 已有配置 ...
depends_on:
- peripheral-gateway
volumes:
# 挂载插件目录到容器内
- ./extensions/my-peripheral-plugin:/app/extensions/my-peripheral-plugin
```
#### 2. 在 OpenClaw 配置文件中启用插件(Docker 内网地址)
```json
{
"plugins": {
"entries": {
"my-peripheral-plugin": {
"enabled": true,
"config": {
"gatewayEndpoint": "http://peripheral-gateway:8080",
"defaultDeviceId": "ws63-demo-01"
}
}
}
}
}
```
注意 `gatewayEndpoint` 使用 Docker 内网地址 `http://peripheral-gateway:8080`,
同一 compose 网络中服务名即主机名,无需暴露端口到宿主机。
#### 3. 构建并启动
```bash
cd <openclaw项目根目录>
# 首次构建 Gateway 镜像
docker compose build peripheral-gateway
# 启动全部服务
docker compose up -d
```
#### 4. 验证
```bash
# 检查容器状态
docker compose ps
# peripheral-gateway-1 running 0.0.0.0:8080->8080/tcp
# openclaw-gateway-1 running 0.0.0.0:18789->18789/tcp
# 检查 Gateway 健康
curl http://127.0.0.1:8080/healthz
# {"status":"ok","service":"my_peripheral_plugin"}
# 查看 OpenClaw 日志确认插件加载
docker compose logs openclaw-gateway | grep peripheral
```
成功加载时日志输出:
```
my-peripheral-plugin 已加载,endpoint=http://peripheral-gateway:8080
动态命令发现完成,注册 13 个工具
设备轮询启动,间隔 30000ms
```
#### 重启与更新
```bash
# 重启全部服务(配置变更后)
docker compose up -d --force-recreate
# 仅重建 Gateway(Go 代码或描述符变更后)
docker compose build peripheral-gateway && docker compose up -d
# 查看实时日志
docker compose logs -f openclaw-gateway peripheral-gateway
```
### 插件加载机制
```
OpenClaw 启动
→ 扫描 extensions/ 目录
→ 发现 my-peripheral-plugin/openclaw.plugin.json
→ 读取插件 ID 和 configSchema
→ jiti 加载 index.ts(运行时编译,无需预构建)
→ 调用 register(api)
→ 注册 9 个基础工具(立即可用)
→ 启动命令发现服务(连接 Gateway,异步注册 cmd_* 动态工具)
→ 启动设备轮询服务
→ 注册 /peripheral/health HTTP 路由
```
**插件发现位置(按优先级):**
| 优先级 | 路径 | 来源 |
|:---:|------|------|
| 1 | 配置文件中 `plugins.load.paths` 指定的路径 | 配置级 |
| 2 | `<工作目录>/.openclaw/extensions/` | 项目级 |
| 3 | `~/.openclaw/extensions/` | 用户级 |
| 4 | OpenClaw 仓库内 `extensions/`(Docker 内 `/app/extensions/`) | 内置级 |
内置插件默认禁用,需要在配置中显式 `"enabled": true`。
项目级和用户级插件默认启用,无需额外配置。
**插件配置项:**
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| `gatewayEndpoint` | `http://127.0.0.1:8080` | Gateway REST API 地址(Docker 中用服务名) |
| `gatewayToken` | 空 | API 认证令牌(可选) |
| `defaultDeviceId` | 空 | 默认设备,省略时每次调用需指定 |
| `pollIntervalMs` | `30000` | 设备轮询间隔(ms),0 为禁用 |
插件加载后,Agent 对话中自动获得所有注册的工具,无需手动触发。
用户在对话中描述需求(如"扫描 WiFi"),Agent 自动选择对应工具执行。
---
## 使用方式
### 基础工具(9 个,始终可用)
| 工具 | 用途 |
|------|------|
| `list_devices` | 查询所有设备,支持按在线状态和能力过滤 |
| `query_device_status` | 查询设备综合状态(WiFi/BLE/SLE/外设) |
| `query_device_resources` | 查询 CPU、内存、网络等资源 |
| `probe_device` | 检测设备是否在线 |
| `list_commands` | 查看所有可用命令及参数定义 |
| `execute_device_command` | 通用命令执行入口(兜底) |
| `query_audit_logs` | 查询操作审计日志 |
| `query_alerts` | 查询系统告警 |
| `gateway_status` | 查看 Gateway 运行时状态 |
### 动态工具(自动生成,cmd_ 前缀)
根据 Gateway 中注册的设备命令自动生成,不同设备产生不同工具集。
例如内置设备生成:
```
cmd_wifi_scan cmd_query_device_status
...
```
使用 `list_commands` 查看当前完整列表。
### 对话示例
用户在 OpenClaw Chat 中输入自然语言指令,Agent 自动调用对应工具执行:
**WiFi 扫描 — 调用 `cmd_wifi_scan` 获取周围热点列表:**

**扫描结果整理 — Agent 将原始数据解析为可读表格(SSID、RSSI、信道、加密方式):**

更多对话场景:
```
用户:查看设备当前状态
Agent:[调用 query_device_status] WiFi 已连接,信号 -45dBm,内存 78%...
```
---
## 添加新设备
新设备接入只需 2 个文件操作,不需要写任何代码。
### Step 1 - 编写设备描述符
在 `gateway/configs/devices/profiles/` 下新建 JSON 文件:
```json
{
"version": "1.0",
"name": "my-new-device",
"devices": [
{
"id": "new-device-01",
"autoload": true,
"endpoint": "http://192.168.1.100",
"vendor": "vendor-name",
"model": "MODEL-X",
"profile": "device-v1",
"protocol": "rest",
"capabilities": ["wifi", "sensor"]
}
],
"commands": [
{
"name": "read_sensor",
"category": "query",
"protocol": "REST",
"rest_path": "/api/sensor/read",
"priority": "low",
"risk_level": "safe",
"permission": "read",
"idempotent": true,
"supported_profiles": ["device-v1"]
}
]
}
```
### Step 2 - 注册到索引
编辑 `gateway/configs/devices/index.json`:
```diff
"includes": [
"profiles/hi3863.json",
"profiles/generic-upm.json",
+ "profiles/my-new-device.json"
]
```
重启 Gateway,新工具 `cmd_read_sensor` 立即可用。
### 命令字段参考
| 字段 | 必填 | 取值 | 说明 |
|------|:---:|------|------|
| `name` | 是 | 字符串 | 命令名,生成 `cmd_<name>` 工具 |
| `category` | 是 | `query` `control` `config` `admin` | 命令分类 |
| `protocol` | 是 | `UPM` `REST` `MIXED` | 通信协议 |
| `upm_opcode` | UPM 时 | `"0x04"` | UPM 操作码 |
| `rest_path` | REST 时 | `"/api/..."` | HTTP 接口路径 |
| `priority` | 是 | `low` `normal` `high` | 执行优先级 |
| `risk_level` | 是 | `safe` `sensitive` `dangerous` `critical` | 风险等级 |
| `permission` | 是 | `read` `control` `config` `admin` | 权限要求 |
| `idempotent` | 是 | `true` / `false` | 是否幂等 |
| `require_confirm` | | `true` | 高危命令需用户确认 |
| `param_schema` | | 对象 | 参数定义(见下表) |
| `supported_profiles` | 是 | 字符串数组 | 适用的设备规格 |
### param_schema 参数类型
| type | 对应 | 示例 |
|------|------|------|
| `string` | 字符串 | SSID、设备 ID |
| `number` | 浮点数 | 温度阈值 |
| `integer` | 整数 | 寄存器地址、RPM |
| `boolean` | 布尔 | 开关标志 |
| `object` | 键值对 | 扩展参数 |
---
## Gateway API
| 端点 | 方法 | 说明 |
|------|:---:|------|
| `/healthz` | GET | 健康检查 |
| `/api/v1/devices` | GET | 设备列表(支持 `?online=true&capability=wifi`) |
| `/api/v1/devices/:id/status` | GET | 设备状态(支持 `?refresh=true`) |
| `/api/v1/devices/:id/resources` | GET | 设备资源 |
| `/api/v1/devices/:id/probe` | GET | 设备在线探测 |
| `/api/v1/commands` | GET | 命令发现(列出所有已注册命令及参数定义) |
| `/api/v1/commands/:name` | POST | 执行命令 |
| `/api/v1/audit/logs` | GET | 审计日志(支持 `?device_id=&command=&limit=`) |
| `/api/v1/alerts/logs` | GET | 告警日志(支持 `?severity=&state=&limit=`) |
| `/api/v1/runtime/descriptor` | GET | 描述符运行时状态 |
---
## 示例
`examples/` 目录包含可直接使用的设备描述符模板:
| 文件 | 协议 | 设备类型 | 命令数 |
|------|:---:|----------|:---:|
| `esp32-sensor.json` | REST | ESP32 温湿度传感器 | 4 |
| `stm32-motor-upm.json` | UPM | STM32 电机控制器 | 7 |
使用方式:
```bash
# 复制示例到描述符目录
cp examples/esp32-sensor.json gateway/configs/devices/profiles/
# 在 index.json 的 includes 中加入
# "profiles/esp32-sensor.json"
# 重启 Gateway 即可
```
---
## 常见问题
**Q: Plugin 加载后没有动态工具?**
检查 Gateway 是否正常运行:`curl http://127.0.0.1:8080/healthz`
**Q: 命令执行超时?**
Gateway 默认超时 8 秒。检查设备 endpoint 是否可达:`curl <设备地址>`
**Q: 如何
... (truncated)
tools
Comments
Sign in to leave a comment