下载的开源源代码压缩包,名称为“mimiclaw-main”,总大小为466K。
解压缩后打开,找到了纯C语言的 MimiClaw 主程序 mimi.c,其大小只有6K,好奇数了一下,总共169行。
MimiClaw 主程序 mimi.c 源代码如下
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_system.h"
#include "esp_heap_caps.h"
#include "esp_spiffs.h"
#include "nvs_flash.h"
#include "mimi_config.h"
#include "bus/message_bus.h"
#include "wifi/wifi_manager.h"
#include "telegram/telegram_bot.h"
#include "llm/llm_proxy.h"
#include "agent/agent_loop.h"
#include "memory/memory_store.h"
#include "memory/session_mgr.h"
#include "gateway/ws_server.h"
#include "cli/serial_cli.h"
#include "proxy/http_proxy.h"
#include "tools/tool_registry.h"
#include "display/display.h"
#include "buttons/button_driver.h"
#include "ui/config_screen.h"
#include "imu/imu_manager.h"
#include "rgb/rgb.h"
#include "skills/skill_loader.h"
static const char *TAG = "mimi";
static esp_err_t init_nvs(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_LOGW(TAG, "NVS partition truncated, erasing...");
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
return ret;
}
static esp_err_t init_spiffs(void)
{
esp_vfs_spiffs_conf_t conf = {
.base_path = MIMI_SPIFFS_BASE,
.partition_label = NULL,
.max_files = 10,
.format_if_mount_failed = true,
};
esp_err_t ret = esp_vfs_spiffs_register(&conf);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPIFFS mount failed: %s", esp_err_to_name(ret));
return ret;
}
size_t total = 0, used = 0;
esp_spiffs_info(NULL, &total, &used);
ESP_LOGI(TAG, "SPIFFS: total=%d, used=%d", (int)total, (int)used);
return ESP_OK;
}
/* Outbound dispatch task: reads from outbound queue and routes to channels */
static void outbound_dispatch_task(void *arg)
{
ESP_LOGI(TAG, "Outbound dispatch started");
while (1) {
mimi_msg_t msg;
if (message_bus_pop_outbound(&msg, UINT32_MAX) != ESP_OK) continue;
ESP_LOGI(TAG, "Dispatching response to %s:%s", msg.channel, msg.chat_id);
if (strcmp(msg.channel, MIMI_CHAN_TELEGRAM) == 0) {
telegram_send_message(msg.chat_id, msg.content);
} else if (strcmp(msg.channel, MIMI_CHAN_WEBSOCKET) == 0) {
ws_server_send(msg.chat_id, msg.content);
} else if (strcmp(msg.channel, MIMI_CHAN_SYSTEM) == 0) {
ESP_LOGI(TAG, "System message [%s]: %.128s", msg.chat_id, msg.content);
} else {
ESP_LOGW(TAG, "Unknown channel: %s", msg.channel);
}
free(msg.content);
}
}
void app_main(void)
{
/* Silence noisy components */
esp_log_level_set("esp-x509-crt-bundle", ESP_LOG_WARN);
ESP_LOGI(TAG, "========================================");
ESP_LOGI(TAG, " MimiClaw - ESP32-S3 AI Agent");
ESP_LOGI(TAG, "========================================");
/* Print memory info */
ESP_LOGI(TAG, "Internal free: %d bytes",
(int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
ESP_LOGI(TAG, "PSRAM free: %d bytes",
(int)heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
/* Display + input */
ESP_ERROR_CHECK(display_init());
display_show_banner();
ESP_ERROR_CHECK(rgb_init());
rgb_set(255, 0, 0);
button_Init();
config_screen_init();
imu_manager_init();
imu_manager_set_shake_callback(config_screen_toggle);
/* Phase 1: Core infrastructure */
ESP_ERROR_CHECK(init_nvs());
ESP_ERROR_CHECK(esp_event_loop_create_default());
ESP_ERROR_CHECK(init_spiffs());
/* Initialize subsystems */
ESP_ERROR_CHECK(message_bus_init());
ESP_ERROR_CHECK(memory_store_init());
ESP_ERROR_CHECK(skill_loader_init());
ESP_ERROR_CHECK(session_mgr_init());
ESP_ERROR_CHECK(wifi_manager_init());
ESP_ERROR_CHECK(http_proxy_init());
ESP_ERROR_CHECK(telegram_bot_init());
ESP_ERROR_CHECK(llm_proxy_init());
ESP_ERROR_CHECK(tool_registry_init());
ESP_ERROR_CHECK(cron_service_init());
ESP_ERROR_CHECK(heartbeat_init());
ESP_ERROR_CHECK(agent_loop_init());
/* Start Serial CLI first (works without WiFi) */
ESP_ERROR_CHECK(serial_cli_init());
/* Start WiFi */
esp_err_t wifi_err = wifi_manager_start();
if (wifi_err == ESP_OK) {
ESP_LOGI(TAG, "Scanning nearby APs on boot...");
wifi_manager_scan_and_print();
ESP_LOGI(TAG, "Waiting for WiFi connection...");
if (wifi_manager_wait_connected(30000) == ESP_OK) {
ESP_LOGI(TAG, "WiFi connected: %s", wifi_manager_get_ip());
/* Start network-dependent services */
ESP_ERROR_CHECK(telegram_bot_start());
ESP_ERROR_CHECK(agent_loop_start());
cron_service_start();
heartbeat_start();
ESP_ERROR_CHECK(ws_server_start());
/* Outbound dispatch task */
xTaskCreatePinnedToCore(
outbound_dispatch_task, "outbound",
MIMI_OUTBOUND_STACK, NULL,
MIMI_OUTBOUND_PRIO, NULL, MIMI_OUTBOUND_CORE);
ESP_LOGI(TAG, "All services started!");
} else {
ESP_LOGW(TAG, "WiFi connection timeout. Check MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
}
} else {
ESP_LOGW(TAG, "No WiFi credentials. Set MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
}
ESP_LOGI(TAG, "MimiClaw ready. Type 'help' for CLI commands.");
} 复制代码
中文注释后有300行
// ==============================================
// 头文件包含区:引入系统库 + 项目功能模块
// ==============================================
// 标准输入输出库(打印、文件操作等)
#include <stdio.h>
// 字符串处理库(字符串比较、复制、拼接等)
#include <string.h>
// FreeRTOS 实时操作系统核心头文件
#include "freertos/FreeRTOS.h"
// FreeRTOS 任务管理头文件(创建任务、延时等)
#include "freertos/task.h"
// ESP32 日志打印库(输出调试信息)
#include "esp_log.h"
// ESP32 事件循环库(处理系统/外设事件)
#include "esp_event.h"
// ESP32 系统功能库(重启、错误码等)
#include "esp_system.h"
// ESP32 内存管理库(获取剩余内存、PSRAM 状态)
#include "esp_heap_caps.h"
// ESP32 SPIFFS 文件系统库(存储配置、文件)
#include "esp_spiffs.h"
// ESP32 NVS 非易失性存储库(保存WiFi密码、配置)
#include "nvs_flash.h"
// 项目全局配置文件(宏定义、参数配置)
#include "mimi_config.h"
// 消息总线模块(设备内部消息传递、分发)
#include "bus/message_bus.h"
// WiFi 管理模块(连接、扫描、获取IP)
#include "wifi/wifi_manager.h"
// Telegram 机器人模块(收发消息)
#include "telegram/telegram_bot.h"
// 大模型代理模块(对接AI大模型)
#include "llm/llm_proxy.h"
// AI 智能体循环模块(核心AI逻辑运行)
#include "agent/agent_loop.h"
// 记忆存储模块(保存对话历史)
#include "memory/memory_store.h"
// 会话管理模块(管理多用户对话)
#include "memory/session_mgr.h"
// WebSocket 服务端模块(网页/客户端通信)
#include "gateway/ws_server.h"
// 串口命令行模块(串口输入指令控制设备)
#include "cli/serial_cli.h"
// HTTP 代理模块(网络请求代理)
#include "proxy/http_proxy.h"
// 工具注册模块(注册AI可调用的工具)
#include "tools/tool_registry.h"
// 屏幕显示模块(驱动OLED/LCD)
#include "display/display.h"
// 按键驱动模块(检测物理按键)
#include "buttons/button_driver.h"
// 配置界面模块(屏幕上的配置菜单)
#include "ui/config_screen.h"
// 陀螺仪传感器模块(检测姿态、摇晃)
#include "imu/imu_manager.h"
// RGB 彩灯驱动模块
#include "rgb/rgb.h"
// 技能加载模块(加载AI技能、功能)
#include "skills/skill_loader.h"
// ==============================================
// 全局变量定义
// ==============================================
// 日志标签,用于区分打印来源
static const char *TAG = "mimi";
// ==============================================
// 模块1:NVS 非易失性存储初始化
// 功能:初始化Flash存储,保存WiFi密码、配置等断电不丢失的数据
// ==============================================
static esp_err_t init_nvs(void)
{
// 初始化NVS闪存
esp_err_t ret = nvs_flash_init();
// 判断:如果NVS空间不足/版本不兼容
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
// 打印警告日志
ESP_LOGW(TAG, "NVS partition truncated, erasing...");
// 擦除NVS分区(修复异常)
ESP_ERROR_CHECK(nvs_flash_erase());
// 重新初始化NVS
ret = nvs_flash_init();
}
// 返回初始化结果
return ret;
}
// ==============================================
// 模块2:SPIFFS 文件系统初始化
// 功能:挂载Flash文件系统,用于存放配置文件、技能文件等
// ==============================================
static esp_err_t init_spiffs(void)
{
// 定义SPIFFS配置结构体
esp_vfs_spiffs_conf_t conf = {
.base_path = MIMI_SPIFFS_BASE, // 挂载根路径
.partition_label = NULL, // 使用默认分区
.max_files = 10, // 最大同时打开文件数
.format_if_mount_failed = true, // 挂载失败自动格式化
};
// 注册并挂载SPIFFS文件系统
esp_err_t ret = esp_vfs_spiffs_register(&conf);
// 挂载失败:打印错误并返回
if (ret != ESP_OK) {
ESP_LOGE(TAG, "SPIFFS mount failed: %s", esp_err_to_name(ret));
return ret;
}
// 定义变量存储总容量、已用容量
size_t total = 0, used = 0;
// 获取SPIFFS容量信息
esp_spiffs_info(NULL, &total, &used);
// 打印文件系统容量
ESP_LOGI(TAG, "SPIFFS: total=%d, used=%d", (int)total, (int)used);
// 初始化成功
return ESP_OK;
}
// ==============================================
// 模块3:消息出站调度任务
// 功能:从消息队列取出消息,分发给对应通道(Telegram/websocket/系统)
// ==============================================
/* Outbound dispatch task: reads from outbound queue and routes to channels */
static void outbound_dispatch_task(void *arg)
{
// 打印任务启动日志
ESP_LOGI(TAG, "Outbound dispatch started");
// 死循环:持续处理出站消息
while (1) {
// 定义消息结构体变量
mimi_msg_t msg;
// 从消息总线取出消息(永久等待)
if (message_bus_pop_outbound(&msg, UINT32_MAX) != ESP_OK) continue;
// 打印消息分发信息
ESP_LOGI(TAG, "Dispatching response to %s:%s", msg.channel, msg.chat_id);
// 判断消息通道:Telegram机器人
if (strcmp(msg.channel, MIMI_CHAN_TELEGRAM) == 0) {
// 发送消息到Telegram
telegram_send_message(msg.chat_id, msg.content);
}
// 判断消息通道:WebSocket客户端
else if (strcmp(msg.channel, MIMI_CHAN_WEBSOCKET) == 0) {
// 发送消息到WebSocket
ws_server_send(msg.chat_id, msg.content);
}
// 判断消息通道:系统内部消息
else if (strcmp(msg.channel, MIMI_CHAN_SYSTEM) == 0) {
// 打印系统消息
ESP_LOGI(TAG, "System message [%s]: %.128s", msg.chat_id, msg.content);
}
// 未知通道
else {
ESP_LOGW(TAG, "Unknown channel: %s", msg.channel);
}
// 释放消息内容内存(防止内存泄漏)
free(msg.content);
}
}
// ==============================================
// 主函数:程序入口(ESP32 开机后自动运行)
// 功能:按顺序初始化所有硬件、系统、功能模块,启动服务
// ==============================================
void app_main(void)
{
// ==============================================
// 初始化前置:日志级别配置
// 降低证书组件日志级别,减少冗余打印
// ==============================================
esp_log_level_set("esp-x509-crt-bundle", ESP_LOG_WARN);
// 打印项目启动标题
ESP_LOGI(TAG, "========================================");
ESP_LOGI(TAG, " MimiClaw - ESP32-S3 AI Agent");
ESP_LOGI(TAG, "========================================");
// ==============================================
// 系统信息打印:内存状态
// ==============================================
// 打印内部RAM剩余空间
ESP_LOGI(TAG, "Internal free: %d bytes",
(int)heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
// 打印外部PSRAM剩余空间
ESP_LOGI(TAG, "PSRAM free: %d bytes",
(int)heap_caps_get_free_size(MALLOC_CAP_SPIRAM));
// ==============================================
// 硬件初始化:显示、输入、传感器
// ==============================================
// 初始化屏幕(断言检查:失败则重启)
ESP_ERROR_CHECK(display_init());
// 屏幕显示开机横幅
display_show_banner();
// 初始化RGB彩灯
ESP_ERROR_CHECK(rgb_init());
// 设置RGB为红色(开机提示)
rgb_set(255, 0, 0);
// 初始化按键驱动
button_Init();
// 初始化配置界面
config_screen_init();
// 初始化陀螺仪传感器
imu_manager_init();
// 设置陀螺仪摇晃回调:摇晃切换配置界面
imu_manager_set_shake_callback(config_screen_toggle);
// ==============================================
// 核心系统初始化:NVS + 事件循环 + SPIFFS
// ==============================================
/* Phase 1: Core infrastructure */
// 初始化NVS存储
ESP_ERROR_CHECK(init_nvs());
// 创建默认事件循环
ESP_ERROR_CHECK(esp_event_loop_create_default());
// 初始化SPIFFS文件系统
ESP_ERROR_CHECK(init_spiffs());
// ==============================================
// 功能子系统初始化
// ==============================================
/* Initialize subsystems */
ESP_ERROR_CHECK(message_bus_init()); // 消息总线
ESP_ERROR_CHECK(memory_store_init()); // 记忆存储
ESP_ERROR_CHECK(skill_loader_init()); // 技能加载
ESP_ERROR_CHECK(session_mgr_init()); // 会话管理
ESP_ERROR_CHECK(wifi_manager_init()); // WiFi管理
ESP_ERROR_CHECK(http_proxy_init()); // HTTP代理
ESP_ERROR_CHECK(telegram_bot_init()); // Telegram机器人
ESP_ERROR_CHECK(llm_proxy_init()); // 大模型代理
ESP_ERROR_CHECK(tool_registry_init()); // 工具注册
ESP_ERROR_CHECK(cron_service_init()); // 定时任务服务
ESP_ERROR_CHECK(heartbeat_init()); // 心跳服务
ESP_ERROR_CHECK(agent_loop_init()); // AI智能体循环
// ==============================================
// 启动串口命令行(无需WiFi即可使用)
// ==============================================
/* Start Serial CLI first (works without WiFi) */
ESP_ERROR_CHECK(serial_cli_init());
// ==============================================
// WiFi 连接 + 网络服务启动
// ==============================================
/* Start WiFi */
// 启动WiFi管理
esp_err_t wifi_err = wifi_manager_start();
// WiFi启动成功
if (wifi_err == ESP_OK) {
ESP_LOGI(TAG, "Scanning nearby APs on boot...");
// 扫描并打印附近WiFi
wifi_manager_scan_and_print();
ESP_LOGI(TAG, "Waiting for WiFi connection...");
// 等待WiFi连接(超时30秒)
if (wifi_manager_wait_connected(30000) == ESP_OK) {
// 打印WiFi连接成功 + IP地址
ESP_LOGI(TAG, "WiFi connected: %s", wifi_manager_get_ip());
// ==============================================
// WiFi连接成功后:启动网络依赖服务
// ==============================================
/* Start network-dependent services */
ESP_ERROR_CHECK(telegram_bot_start()); // 启动Telegram机器人
ESP_ERROR_CHECK(agent_loop_start()); // 启动AI智能体
cron_service_start(); // 启动定时任务
heartbeat_start(); // 启动心跳
ESP_ERROR_CHECK(ws_server_start()); // 启动WebSocket服务
// ==============================================
// 创建消息分发任务(核心消息调度)
// ==============================================
/* Outbound dispatch task */
xTaskCreatePinnedToCore(
outbound_dispatch_task, "outbound", // 任务函数 + 名称
MIMI_OUTBOUND_STACK, NULL, // 栈大小 + 传入参数
MIMI_OUTBOUND_PRIO, NULL, // 优先级 + 任务句柄
MIMI_OUTBOUND_CORE); // 绑定CPU核心
// 所有服务启动完成
ESP_LOGI(TAG, "All services started!");
} else {
// WiFi连接超时提示
ESP_LOGW(TAG, "WiFi connection timeout. Check MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
}
} else {
// 无WiFi凭据提示
ESP_LOGW(TAG, "No WiFi credentials. Set MIMI_SECRET_WIFI_SSID in mimi_secrets.h");
}
// 系统就绪提示
ESP_LOGI(TAG, "MimiClaw ready. Type 'help' for CLI commands.");
} 复制代码