MimiClaw 配置飞书机器人和添加硬件控制技能

本文本介绍配置飞书机器人为MimiClaw的一个输入/输出端,和添加一个控制WS2812与LED的控制技能。

MimiClaw 可通过飞书机器人接收指令、反馈结果。

一、创建飞书机器人

在飞书开放平台创建企业自建应用并完成配置,步骤如下:

(1)创建企业自建应用
访问 飞书开放平台 https://open.feishu.cn/,使用飞书账号登录(个人账号即可,无需企业认证)。
点击页面右上角“创建企业自建应用”,填写应用名称(如“MimiClaw 控制”),点击“创建”。

进入应用管理页面后,在左侧菜单「凭证与基础信息」中,复制「App ID」和「App Secret」,妥善保存(后续配置 MimiClaw 需用到)。

MimiClaw 配置飞书机器人和添加硬件控制技能


(2)添加机器人能力并配置权限
在应用管理左侧菜单,点击「添加应用能力」,在弹出的列表中找到「机器人」,点击「配置」,启用机器人能力。
启用后,进入「权限管理」页面,搜索并添加以下 4 个核心权限(缺一不可):
im:message:允许机器人发送消息
im:message.p2p_msg:readonly:允许机器人接收私聊消息
im:message:send_as_bot:允许机器人以自身身份回复消息
contact:user.base:readonly:允许机器人读取用户基础信息

MimiClaw 配置飞书机器人和添加硬件控制技能


(3)配置事件订阅(长连接模式)
为让嵌入式设备(ESP32-S3)能稳定接收飞书消息,采用长连接(WebSocket)模式订阅事件,无需公网 IP,配置步骤如下:
在应用管理左侧菜单,点击「事件与回调」。
订阅方式选择「使用长连接接收事件」,点击「保存」(无需填写回调地址)。
点击「添加事件」,在搜索框中输入「im.message.receive_v1」,勾选该事件(接收消息事件),点击「确认添加」,完成事件订阅。
MimiClaw 配置飞书机器人和添加硬件控制技能
长连接模式通过 WebSocket 全双工通道接收飞书回调,延迟低、稳定性高,非常适合嵌入式设备的网络场景。

(4)发布应用并添加机器人
在应用管理左侧菜单,点击「版本管理与发布」,点击「创建版本」,填写版本号(如 1.0.0),简要填写更新说明(如“初始版本,支持 RGB 彩灯控制”),提交审核。
个人账号创建的应用无需人工审核,提交后立即发布成功。


  (5)MimiClaw源码修改

修改mimi_secrets.h内的以下行,粘贴上一步的APP ID和AAPP SECRET

/* Feishu Bot */
#define MIMI_SECRET_FEISHU_APP_ID   ""
#define MIMI_SECRET_FEISHU_APP_SECRET   ""

编译并烧录固件。

在飞书APP内用创建的机器人进行对话吧。

MimiClaw 配置飞书机器人和添加硬件控制技能


二、添加硬件控制技能

编写可由MimiClaw调用的硬件控制技能,需要3步:
1. 编写硬件控制工具代码
2. 向MimiClaw注册工具
3. 编写给大模型看的skill文档

这样当我们向MimiClaw发出硬件控制的对话时,由大模型分析后转为调用工具代码,从而完成硬件控制操作。

下面以开关LED和WS2812为例来说明

(1)编写工具代码
在tools目录内新建tool_led.h和tool_led.c文件,

在main/tools/tool_led.c内, 添加以下代码:

#include "led_strip.h"  // 引入 led_strip components

#define WS2812_GPIO 48        // 板载 WS2812 连接的 GPIO 引脚
static led_strip_handle_t s_led_strip = NULL;  // LED 驱动句柄

static const char *TAG = "tool_led";

//============== WS2812 ==================/
// WS2812 初始化函数
esp_err_t ws2812_init(void)
{
    if (s_led_strip != NULL) return ESP_OK;  // 避免重复初始化

    // LED 灯带配置
    led_strip_config_t strip_cfg = {
        .strip_gpio_num = WS2812_GPIO,    // 连接的 GPIO 引脚
        .max_leds = 1,                    // 灯珠数量(板载为 1 个)
        .led_model = LED_MODEL_WS2812,    // 灯珠型号为 WS2812
        .color_component_format = LED_STRIP_COLOR_COMPONENT_FMT_GRB,  
    };

    // RMT 外设配置(驱动 WS2812 需用到 RMT 外设)
    led_strip_rmt_config_t rmt_cfg = {
        .clk_src = RMT_CLK_SRC_DEFAULT, 
        .resolution_hz = 10 * 1000 * 1000, 
        .mem_block_symbols = 0, 
        .flags.with_dma = false,          // 无需 DMA(单灯珠无需高速传输)
    };

    // 创建 RMT 驱动的 LED 设备
    led_strip_new_rmt_device(&strip_cfg, &rmt_cfg, &s_led_strip);
    led_strip_clear(s_led_strip);  // 初始化后熄灭彩灯
    return ESP_OK;
}

// WS2812 设置函数(r: 红色, g: 绿色, b: 蓝色,取值 0-255)
esp_err_t ws2812_set(uint8_t r, uint8_t g, uint8_t b)
{
    ws2812_init();  // 确保驱动已初始化
    led_strip_set_pixel(s_led_strip, 0, r, g, b);  // 设置第 0 个灯珠颜色
    led_strip_refresh(s_led_strip);  // 刷新显示,使颜色生效
    ESP_LOGI(TAG, "ws2812 set r:%d g:%d b:%d", r, g, b);
    return ESP_OK;
}

// ws2812 on工具函数
esp_err_t tool_ws2812_on_execute(const char *in_json, char *out, size_t len) {
    cJSON *root = cJSON_Parse(in_json);
    if (!root) {
        snprintf(out, len, "Error: invalid input");
        return ESP_ERR_INVALID_ARG;
    }

    cJSON *red_obj = cJSON_GetObjectItem(root, "red");
    uint8_t red = (red_obj && cJSON_IsNumber(red_obj)) ? (uint8_t)red_obj->valueint : 0;
    cJSON *green_obj = cJSON_GetObjectItem(root, "green");
    uint8_t green = (red_obj && cJSON_IsNumber(green_obj)) ? (uint8_t)green_obj->valueint : 0;
    cJSON *blue_obj = cJSON_GetObjectItem(root, "blue");
    uint8_t blue = (red_obj && cJSON_IsNumber(blue_obj)) ? (uint8_t)blue_obj->valueint : 0;

    ws2812_set(red, green, blue);
    snprintf(out, len, "WS2812 ON");  // 执行结果
    return ESP_OK;
}

// ws2812 off 工具函数
esp_err_t tool_ws2812_off_execute(const char *in, char *out, size_t len) {
    ws2812_set(0, 0, 0);  // 红色:R=255, G=0, B=0
    snprintf(out, len, "WS2812 OFF");  // 执行结果
    return ESP_OK;
}

//=================== Led Tool =============================
// Led on工具函数
esp_err_t tool_led_on_execute(const char *in_json, char *out, size_t len) {
    cJSON *root = cJSON_Parse(in_json);
    if (!root) {
        snprintf(out, len, "Error: invalid input");
        return ESP_ERR_INVALID_ARG;
    }

    cJSON *pin_obj = cJSON_GetObjectItem(root, "pin");
    uint8_t pin = (pin_obj && cJSON_IsNumber(pin_obj)) ? (uint8_t)pin_obj->valueint : 0;
    cJSON *value_obj = cJSON_GetObjectItem(root, "value");
    uint8_t value = (pin_obj && cJSON_IsNumber(value_obj)) ? (uint8_t)value_obj->valueint : 0;

    if (gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT) != ESP_OK ||
        gpio_set_level(pin, value) != ESP_OK) {

        snprintf(out, len, "Error: failed to turn on %d", pin);
        cJSON_Delete(root);
        return ESP_FAIL;
    }

    snprintf(out, len, "LED ON");  // 执行结果
    return ESP_OK;
}

// Led off 工具函数
esp_err_t tool_led_off_execute(const char *in_json, char *out, size_t len) {
    cJSON *root = cJSON_Parse(in_json);
    if (!root) {
        snprintf(out, len, "Error: invalid input");
        return ESP_ERR_INVALID_ARG;
    }

    cJSON *pin_obj = cJSON_GetObjectItem(root, "pin");
    uint8_t pin = (pin_obj && cJSON_IsNumber(pin_obj)) ? (uint8_t)pin_obj->valueint : 0;

    if (gpio_set_direction(pin, GPIO_MODE_INPUT_OUTPUT) != ESP_OK ||
        gpio_set_level(pin, 0) != ESP_OK) {

        snprintf(out, len, "Error: failed to turn on %d", pin);
        cJSON_Delete(root);
        return ESP_FAIL;
    }
    
    snprintf(out, len, "LED OFF");  // 执行结果
    return ESP_OK;
}
tool_ws2812_on和tool_ws2812_off为操作WS2812 LED的代码,这里使用led_strip组件,需用idf.py add component 添加到项目
tool_led_on和tool_led_off_execute为操作普通LED的代码


 (2) 注册工具

在main/toos/tool_registry.c 文件的tool_registry_init函数中,添加以上四个工具的注册代码,如下:

    // Register led_on
    mimi_tool_t led_on = {
        .name = "led_on",
        .description = "Turn on the LED immediately. Use when user says 'led on pin val'.",
        .input_schema_json = 
            "{\"type\":\"object\","
            "\"properties\":{"
                "\"pin\":{\"type\":\"integer\",\"description\":\"Pin(0-48)\"},"
                "\"value\":{\"type\":\"integer\",\"description\":\"Value(0-255)\"}"
            "},"
            "\"required\":[\"pin\",\"value\"]}",
        .execute = tool_led_on_execute,  // 绑定执行函数
    };
    register_tool(&led_on);

    // Register led_off
    mimi_tool_t led_off = {
        .name = "led_off",
        .description = "Turn off the LED immediately. Use when user says 'led off pin'.",
        .input_schema_json = 
            "{\"type\":\"object\","
            "\"properties\":{"
                "\"pin\":{\"type\":\"integer\",\"description\":\"Pin(0-48)\"}"
            "},"
            "\"required\":[\"pin\"]}",
        .execute = tool_led_off_execute,  // 绑定执行函数
    };
    register_tool(&led_off);

    // Register ws2812_on
    mimi_tool_t ws2812_on = {
        .name = "ws2812_on",
        .description = "Turn on the WS2812 immediately. Use when user says 'ws2812 on x,x,x'.",
        .input_schema_json = 
            "{\"type\":\"object\","
            "\"properties\":{"
                "\"red\":{\"type\":\"integer\",\"description\":\"Red Value(0-255)\"},"
                "\"green\":{\"type\":\"integer\",\"description\":\"Green Value(0-255)\"},"
                "\"blue\":{\"type\":\"integer\",\"description\":\"Blue Value(0-255)\"}"
            "},"
            "\"required\":[\"red\",\"green\",\"blue\"]}",
        .execute = tool_ws2812_on_execute,  // 绑定执行函数
    };
    register_tool(&ws2812_on);

    // Register ws2812_off
    mimi_tool_t ws2812_off = {
        .name = "ws2812_off",
        .description = "Turn off the WS2812 immediately. Use when user says 'ws2812 off'.",
        .input_schema_json = "{\"type\":\"object\",\"properties\":{},\"required\":[]}",
        .execute = tool_ws2812_off_execute,
    };
    register_tool(&ws2812_off);
为规定格式生成工具代码描述,然后向MimiClaw注册。

 (3) 编写技能描述

这是最重要的一步,决定了AI是否能理解我们的对话描述并转为工具技能调用。
在spiffs_data/skills/目录下新建一个led-control.md文件,输入以下内容:

# WS2812 Control
Control ws2812 led.

## When to use
When the user asks to turn ws2812 on/off.

## How to use
1. To **ws2812 on**: use ws2812_on with red,green,blue (0-255)
2. To **ws2812 off**: use ws2812_off

## Example
User: "led on 4 255"
→ led_on { "pin": 4, "value": 255 }

User: "led off 4"
→ led_off { "pin": 4 }

User: "ws2812 on 255 128 0"
→ ws2812_on {"red": 255, "green": 128, "blue": 0}

User: "ws2812 off"
→ ws2812_off
这个文档就是写给AI的工具使用手册,告诉AI在什么时候调用工具,如何去调用,并给出示例。

编译并烧录固件。

MimiClaw 配置飞书机器人和添加硬件控制技能

通过MimiClaw+大模型,我们让ESP32具备了自主思考的能力,而通过技能,我们可以让设备具备行动的能力。

- 本文由用户 老张 发布,文中观点仅代表作者本人,不代表本站立场。
- 如需转载,请联系作者;如有侵权,请联系本站处理。

04-10   阅读(63)   评论(0)
 标签: 人工智能 ESP32 AI助手 Mimiclaw

涨知识
PWM

PWM,英文名Pulse Width Modulation,是脉冲宽度调制缩写,它是通过调节占空比的变化来调节信号、能量等的变化。

评论:
相关文章
MimiClaw应用与开发教程1:部署和测试

MimiClaw‌ 是一款基于 ‌ESP32-S3‌ 芯片的超轻量级AI助手,适合嵌入式AI与物联网开发者快速部署本地化AI代理。本系列教程基于MimiClaw的Arduino移植版本进行讲解,小节主要讲解部署和测试。


ESP32扫描wifi 热点列表

就像我们用手机打开WiFi功能后可以浏览附近的可用WiFi。要将手机连接到热点,通常需要打开Wi-Fi设置应用程序,列出可用的网络,然后选择所需的热点。然后输入密码(或不输入密码),可以使用ESP32进行相同的操作。


OpenClaw最强科普,看完就真会玩龙虾了

近日,中国台湾大学电机工程学系副教授李宏毅在社交平台上传了一节公开课,以OpenClaw为例,介绍了AI Agent的运作原理。这堂课把最近火爆全网的OpenClaw从头到脚拆了一遍,讲清楚了这只“龙虾”到底是怎么工作的。


ESP32-S3 部署 MimicLaw 完整教程:从零到成功调用 DeepSeek

一块 30 块钱的开发板 + 一个大模型 API,就能做出可以听懂人话的智能硬件。 本文记录完整安装过程和踩坑经验,确保你跟着做就能跑通。


MimiClaw 架构全解析,把 “智能龙虾” 跑在 ESP32 上

本文将从手绘架构图入手,逐层拆解 MimiClaw 的分层设计、核心模块、数据流转与底层实现,带你解剖这只“智能虾”的技术骨架,看懂在 C 语言加持下,AI 智能体如何以可穿戴设备的形态,在你身边稳稳运行、离线服务、主动响应。


如何用 platform.local.txt 深度定制 ESP32 编译流程?

本文介绍如何在不脱离 ArduinoIDE 可视化开发的前提下,通过一个名为 platform.local.txt 的小文件,实现对 ESP32 编译流程的精准控制。


优化Arduino-ESP32程序体积

本文将系统分析程序体积增长的五大根源,并提供经过验证的优化方案,帮助减小固件大小。


开发ESP32大模型AI语音助手-从软件到硬件

本文所DIY的语音助手设备端使用的是MicroPython、服务端是Python,对于很多开发者来说MicroPython入门没难度。


【ESP32 C++教程】Unit10-2:音频录制

本小节使用音频开发框架实现一个音频录制到文件的示例。


ESP32 I2S 接口深度解析:从时序、格式到 ESP-IDF 驱动实战

I2S协议通过BCLK、LRCLK和DATA三线精准传输音频数据,但时序边沿、帧格式、时钟源等细节常引发噪声或断连。本文详解ESP32的I2S实现,从协议原理到ESP-IDF v5.x代码配置,助你避开常见陷阱,确保音频稳定传输。