Refactor emoji initialization for Electron and Otto boards to use Assets system (#1704)

* otto v1.4.0 MCP

1.使用MCP协议控制机器人
2.gif继承lcdDisplay,避免修改lcdDisplay

* otto v1.4.1 gif as components

gif as components

* electronBot v1.1.0 mcp

1.增加electronBot支持
2.mcp协议
3.gif 作为组件
4.display子类

* 规范代码

1.规范代码
2.修复切换主题死机bug

* fix(ota): 修复 ottoRobot和electronBot OTA 升级崩溃问题 bug

* 1.增加robot舵机初始位置校准
2.fix(mcp_sever) 超出范围异常捕获类型  bug

* refactor: Update Electron and Otto emoji display implementations

- Removed GIF selection from Kconfig for Electron and Otto boards.
- Updated Electron and Otto bot versions to 2.0.4 in their respective config files.
- Refactored emoji display classes to utilize EmojiCollection for managing emojis.
- Enhanced chat label setup and status display functionality in both classes.
- Cleaned up unused code and improved initialization logging for emoji displays.

* Rename OTTO_ICON_FONT.c to otto_icon_font.c

* Rename OTTO_ICON_FONT.c to otto_icon_font.c

* refactor: Update Otto emoji display configurations and functionalities

- Changed chat label text mode to circular scrolling for both Otto and Electron emoji displays.
- Bumped Otto robot version to 2.0.5 in the configuration file.
- Added new actions for Otto robot including Sit, WhirlwindLeg, Fitness, Greeting, Shy, RadioCalisthenics, MagicCircle, and Showcase.
- Enhanced servo sequence handling and added support for executing custom servo sequences.
- Improved logging and error handling for servo sequence execution.

* refactor: Update chat label long mode for Electron and Otto emoji displays

- Changed chat label text mode from wrap to circular scrolling for both Electron and Otto emoji displays.
- Improved consistency in chat label setup across both implementations.

* Update Otto robot README with new actions and parameters

* Update Otto controller parameters for oscillation settings

- Changed default oscillation period from 500ms to 300ms.
- Increased default steps from 5.0 to 8.0.
- Updated default amplitude from 20 degrees to 0 degrees.
- Enhanced documentation with new examples for oscillation modes and sequences.

* Fix default amplitude initialization in Otto controller to use a single zero instead of two digits.

* chore: update txp666/otto-emoji-gif-component version to 1.0.3 in idf_component.yml

* Refactor Otto controller
- Consolidated movement actions into a unified tool for the Otto robot, allowing for a single action command with various parameters.
- Removed individual movement tools (walk, turn, jump, etc.) and replaced them with a more flexible action system.

* Enhance Otto robot functionality by adding WebSocket control server and IP address retrieval feature. Updated config to support WebSocket, and revised README to include new control options and usage examples.

* Add camera support for Otto Robot board

- Introduced configuration option to enable the Otto Robot camera in Kconfig.
- Updated config.h to define camera-related GPIO pins and settings.
- Modified config.json to include camera configuration.
- Enhanced otto_robot.cc to initialize I2C and camera components when the camera is enabled.
- Adjusted power_manager.h to manage battery updates during camera operations.
- Removed unused SetupChatLabel method from OttoEmojiDisplay class.

* Refactor Otto Robot configuration and initialization

- Removed the camera configuration option from Kconfig and related code.
- Introduced a new HardwareConfig struct to encapsulate hardware pin definitions and settings.
- Updated config.h to define camera and non-camera configurations using the new struct.
- Refactored otto_controller.cc and otto_robot.cc to utilize the HardwareConfig struct for initialization.
- Enhanced camera detection and initialization logic based on hardware version.
- Improved audio codec initialization based on configuration settings.

* Refactor emoji initialization for Electron and Otto boards to use Assets system

- Removed direct emoji initialization from `InitializeElectronEmojis` and `InitializeOttoEmojis` methods, delegating the responsibility to the Assets system.
- Updated `CMakeLists.txt` to set `DEFAULT_EMOJI_COLLECTION` to `otto-gif` for both boards.
- Enhanced `build_default_assets.py` to support alias mapping for Otto GIF emojis.
- Updated `idf_component.yml` to bump `otto-emoji-gif-component` version to `^1.0.5` for improved functionality.
This commit is contained in:
小鹏
2026-01-31 18:13:15 +08:00
committed by GitHub
parent aad2f60b87
commit 96f34ec70f
5 changed files with 60 additions and 117 deletions

View File

@ -586,10 +586,12 @@ elseif(CONFIG_BOARD_TYPE_OTTO_ROBOT)
set(BOARD_TYPE "otto-robot") set(BOARD_TYPE "otto-robot")
set(BUILTIN_TEXT_FONT font_puhui_16_4) set(BUILTIN_TEXT_FONT font_puhui_16_4)
set(BUILTIN_ICON_FONT font_awesome_16_4) set(BUILTIN_ICON_FONT font_awesome_16_4)
set(DEFAULT_EMOJI_COLLECTION otto-gif)
elseif(CONFIG_BOARD_TYPE_ELECTRON_BOT) elseif(CONFIG_BOARD_TYPE_ELECTRON_BOT)
set(BOARD_TYPE "electron-bot") set(BOARD_TYPE "electron-bot")
set(BUILTIN_TEXT_FONT font_puhui_20_4) set(BUILTIN_TEXT_FONT font_puhui_20_4)
set(BUILTIN_ICON_FONT font_awesome_20_4) set(BUILTIN_ICON_FONT font_awesome_20_4)
set(DEFAULT_EMOJI_COLLECTION otto-gif)
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM) elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM)
set(BOARD_TYPE "bread-compact-wifi-s3cam") set(BOARD_TYPE "bread-compact-wifi-s3cam")
set(BUILTIN_TEXT_FONT font_puhui_basic_16_4) set(BUILTIN_TEXT_FONT font_puhui_basic_16_4)

View File

@ -3,12 +3,13 @@
#include <esp_log.h> #include <esp_log.h>
#include <cstring> #include <cstring>
#include <vector>
#include "assets.h"
#include "assets/lang_config.h" #include "assets/lang_config.h"
#include "display/lvgl_display/emoji_collection.h" #include "display/lvgl_display/emoji_collection.h"
#include "display/lvgl_display/lvgl_image.h" #include "display/lvgl_display/lvgl_image.h"
#include "display/lvgl_display/lvgl_theme.h" #include "display/lvgl_display/lvgl_theme.h"
#include "otto_emoji_gif.h"
#define TAG "ElectronEmojiDisplay" #define TAG "ElectronEmojiDisplay"
ElectronEmojiDisplay::ElectronEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, ElectronEmojiDisplay::ElectronEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y,
@ -19,64 +20,12 @@ ElectronEmojiDisplay::ElectronEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, e
} }
void ElectronEmojiDisplay::InitializeElectronEmojis() { void ElectronEmojiDisplay::InitializeElectronEmojis() {
ESP_LOGI(TAG, "初始化Electron GIF表情"); ESP_LOGI(TAG, "Electron表情初始化将由Assets系统处理");
// 表情初始化已移至assets系统,通过DEFAULT_EMOJI_COLLECTION=otto-gif配置
auto otto_emoji_collection = std::make_shared<EmojiCollection>(); // assets.cc会从assets分区加载GIF表情并设置到theme
// 中性/平静类表情 -> staticstate
otto_emoji_collection->AddEmoji("staticstate", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("neutral", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("relaxed", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("sleepy", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("idle", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
// 积极/开心类表情 -> happy
otto_emoji_collection->AddEmoji("happy", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("laughing", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("funny", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("loving", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("confident", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("winking", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("cool", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("delicious", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("kissy", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("silly", new LvglRawImage((void*)happy.data, happy.data_size));
// 悲伤类表情 -> sad
otto_emoji_collection->AddEmoji("sad", new LvglRawImage((void*)sad.data, sad.data_size));
otto_emoji_collection->AddEmoji("crying", new LvglRawImage((void*)sad.data, sad.data_size));
// 愤怒类表情 -> anger
otto_emoji_collection->AddEmoji("anger", new LvglRawImage((void*)anger.data, anger.data_size));
otto_emoji_collection->AddEmoji("angry", new LvglRawImage((void*)anger.data, anger.data_size));
// 惊讶类表情 -> scare
otto_emoji_collection->AddEmoji("scare", new LvglRawImage((void*)scare.data, scare.data_size));
otto_emoji_collection->AddEmoji("surprised", new LvglRawImage((void*)scare.data, scare.data_size));
otto_emoji_collection->AddEmoji("shocked", new LvglRawImage((void*)scare.data, scare.data_size));
// 思考/困惑类表情 -> buxue
otto_emoji_collection->AddEmoji("buxue", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("thinking", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("confused", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("embarrassed", new LvglRawImage((void*)buxue.data, buxue.data_size));
// 将表情集合添加到主题中
auto& theme_manager = LvglThemeManager::GetInstance();
auto light_theme = theme_manager.GetTheme("light");
auto dark_theme = theme_manager.GetTheme("dark");
if (light_theme != nullptr) {
light_theme->set_emoji_collection(otto_emoji_collection);
}
if (dark_theme != nullptr) {
dark_theme->set_emoji_collection(otto_emoji_collection);
}
// 设置默认表情为staticstate // 设置默认表情为staticstate
SetEmotion("staticstate"); SetEmotion("staticstate");
ESP_LOGI(TAG, "Electron GIF表情初始化完成");
} }
void ElectronEmojiDisplay::SetupChatLabel() { void ElectronEmojiDisplay::SetupChatLabel() {

View File

@ -3,12 +3,13 @@
#include <esp_log.h> #include <esp_log.h>
#include <cstring> #include <cstring>
#include <vector>
#include "assets.h"
#include "assets/lang_config.h" #include "assets/lang_config.h"
#include "display/lvgl_display/emoji_collection.h" #include "display/lvgl_display/emoji_collection.h"
#include "display/lvgl_display/lvgl_image.h" #include "display/lvgl_display/lvgl_image.h"
#include "display/lvgl_display/lvgl_theme.h" #include "display/lvgl_display/lvgl_theme.h"
#include "otto_emoji_gif.h"
#define TAG "OttoEmojiDisplay" #define TAG "OttoEmojiDisplay"
OttoEmojiDisplay::OttoEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy) OttoEmojiDisplay::OttoEmojiDisplay(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_handle_t panel, int width, int height, int offset_x, int offset_y, bool mirror_x, bool mirror_y, bool swap_xy)
@ -24,64 +25,12 @@ void OttoEmojiDisplay::SetupPreviewImage() {
} }
void OttoEmojiDisplay::InitializeOttoEmojis() { void OttoEmojiDisplay::InitializeOttoEmojis() {
ESP_LOGI(TAG, "初始化Otto GIF表情"); ESP_LOGI(TAG, "Otto表情初始化将由Assets系统处理");
// 表情初始化已移至assets系统,通过DEFAULT_EMOJI_COLLECTION=otto-gif配置
auto otto_emoji_collection = std::make_shared<EmojiCollection>(); // assets.cc会从assets分区加载GIF表情并设置到theme
// 中性/平静类表情 -> staticstate
otto_emoji_collection->AddEmoji("staticstate", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("neutral", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("relaxed", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("sleepy", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
otto_emoji_collection->AddEmoji("idle", new LvglRawImage((void*)staticstate.data, staticstate.data_size));
// 积极/开心类表情 -> happy
otto_emoji_collection->AddEmoji("happy", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("laughing", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("funny", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("loving", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("confident", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("winking", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("cool", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("delicious", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("kissy", new LvglRawImage((void*)happy.data, happy.data_size));
otto_emoji_collection->AddEmoji("silly", new LvglRawImage((void*)happy.data, happy.data_size));
// 悲伤类表情 -> sad
otto_emoji_collection->AddEmoji("sad", new LvglRawImage((void*)sad.data, sad.data_size));
otto_emoji_collection->AddEmoji("crying", new LvglRawImage((void*)sad.data, sad.data_size));
// 愤怒类表情 -> anger
otto_emoji_collection->AddEmoji("anger", new LvglRawImage((void*)anger.data, anger.data_size));
otto_emoji_collection->AddEmoji("angry", new LvglRawImage((void*)anger.data, anger.data_size));
// 惊讶类表情 -> scare
otto_emoji_collection->AddEmoji("scare", new LvglRawImage((void*)scare.data, scare.data_size));
otto_emoji_collection->AddEmoji("surprised", new LvglRawImage((void*)scare.data, scare.data_size));
otto_emoji_collection->AddEmoji("shocked", new LvglRawImage((void*)scare.data, scare.data_size));
// 思考/困惑类表情 -> buxue
otto_emoji_collection->AddEmoji("buxue", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("thinking", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("confused", new LvglRawImage((void*)buxue.data, buxue.data_size));
otto_emoji_collection->AddEmoji("embarrassed", new LvglRawImage((void*)buxue.data, buxue.data_size));
// 将表情集合添加到主题中
auto& theme_manager = LvglThemeManager::GetInstance();
auto light_theme = theme_manager.GetTheme("light");
auto dark_theme = theme_manager.GetTheme("dark");
if (light_theme != nullptr) {
light_theme->set_emoji_collection(otto_emoji_collection);
}
if (dark_theme != nullptr) {
dark_theme->set_emoji_collection(otto_emoji_collection);
}
// 设置默认表情为staticstate // 设置默认表情为staticstate
SetEmotion("staticstate"); SetEmotion("staticstate");
ESP_LOGI(TAG, "Otto GIF表情初始化完成");
} }
LV_FONT_DECLARE(OTTO_ICON_FONT); LV_FONT_DECLARE(OTTO_ICON_FONT);
@ -148,7 +97,7 @@ void OttoEmojiDisplay::SetPreviewImage(std::unique_ptr<LvglImage> image) {
auto img_dsc = preview_image_cached_->image_dsc(); auto img_dsc = preview_image_cached_->image_dsc();
// 设置图片源并显示预览图片 // 设置图片源并显示预览图片
lv_image_set_src(preview_image_, img_dsc); lv_image_set_src(preview_image_, img_dsc);
lv_image_set_rotation(preview_image_, -900); lv_image_set_rotation(preview_image_, 900);
if (img_dsc->header.w > 0 && img_dsc->header.h > 0) { if (img_dsc->header.w > 0 && img_dsc->header.h > 0) {
// zoom factor 1.0 // zoom factor 1.0
lv_image_set_scale(preview_image_, 256 * width_ / img_dsc->header.w); lv_image_set_scale(preview_image_, 256 * width_ / img_dsc->header.w);

View File

@ -59,7 +59,7 @@ dependencies:
espressif/adc_mic: ^0.2.1 espressif/adc_mic: ^0.2.1
espressif/esp_mmap_assets: '>=1.2' espressif/esp_mmap_assets: '>=1.2'
txp666/otto-emoji-gif-component: txp666/otto-emoji-gif-component:
version: ^1.0.3 version: ^1.0.5
rules: rules:
- if: target in [esp32s3] - if: target in [esp32s3]
espressif/adc_battery_estimation: ^0.2.0 espressif/adc_battery_estimation: ^0.2.0

View File

@ -222,6 +222,19 @@ def process_emoji_collection(emoji_collection_dir, assets_dir):
emoji_list = [] emoji_list = []
# Check if this is otto-gif collection
is_otto_gif = 'otto-emoji-gif-component' in emoji_collection_dir or emoji_collection_dir.endswith('otto-gif')
# Otto GIF emoji aliases mapping
otto_gif_aliases = {
"staticstate": ["neutral", "relaxed", "sleepy", "idle"],
"happy": ["laughing", "funny", "loving", "confident", "winking", "cool", "delicious", "kissy", "silly"],
"sad": ["crying"],
"anger": ["angry"],
"scare": ["surprised", "shocked"],
"buxue": ["thinking", "confused", "embarrassed"]
}
# Copy each image from input directory to build/assets directory # Copy each image from input directory to build/assets directory
for root, dirs, files in os.walk(emoji_collection_dir): for root, dirs, files in os.walk(emoji_collection_dir):
for file in files: for file in files:
@ -233,12 +246,20 @@ def process_emoji_collection(emoji_collection_dir, assets_dir):
# Get filename without extension # Get filename without extension
filename_without_ext = os.path.splitext(file)[0] filename_without_ext = os.path.splitext(file)[0]
# Add to emoji list # Add main emoji entry
emoji_list.append({ emoji_list.append({
"name": filename_without_ext, "name": filename_without_ext,
"file": file "file": file
}) })
# Add aliases for otto-gif emojis
if is_otto_gif and filename_without_ext in otto_gif_aliases:
for alias in otto_gif_aliases[filename_without_ext]:
emoji_list.append({
"name": alias,
"file": file
})
return emoji_list return emoji_list
@ -682,14 +703,33 @@ def get_text_font_path(builtin_text_font, xiaozhi_fonts_path):
return None return None
def get_emoji_collection_path(default_emoji_collection, xiaozhi_fonts_path): def get_emoji_collection_path(default_emoji_collection, xiaozhi_fonts_path, project_root=None):
""" """
Get the emoji collection path if needed Get the emoji collection path if needed
Returns the emoji directory path or None if no emoji collection is needed Returns the emoji directory path or None if no emoji collection is needed
Supports:
- PNG emoji collections from xiaozhi-fonts (e.g., emojis_32)
- Otto GIF emoji collection (otto-gif)
""" """
if not default_emoji_collection: if not default_emoji_collection:
return None return None
# Special handling for otto-gif collection
if default_emoji_collection == 'otto-gif':
if project_root:
otto_gif_path = os.path.join(project_root, 'managed_components',
'txp666__otto-emoji-gif-component', 'gifs')
if os.path.exists(otto_gif_path):
return otto_gif_path
else:
print(f"Warning: Otto GIF emoji collection directory not found: {otto_gif_path}")
return None
else:
print("Warning: project_root not provided, cannot locate otto-gif collection")
return None
# Default behavior for PNG emoji collections
emoji_path = os.path.join(xiaozhi_fonts_path, 'png', default_emoji_collection) emoji_path = os.path.join(xiaozhi_fonts_path, 'png', default_emoji_collection)
if os.path.exists(emoji_path): if os.path.exists(emoji_path):
return emoji_path return emoji_path
@ -828,7 +868,10 @@ def main():
text_font_path = get_text_font_path(args.builtin_text_font, args.xiaozhi_fonts_path) text_font_path = get_text_font_path(args.builtin_text_font, args.xiaozhi_fonts_path)
# Get emoji collection path if needed # Get emoji collection path if needed
emoji_collection_path = get_emoji_collection_path(args.emoji_collection, args.xiaozhi_fonts_path) # Calculate project root from script location for otto-gif support
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.dirname(script_dir)
emoji_collection_path = get_emoji_collection_path(args.emoji_collection, args.xiaozhi_fonts_path, project_root)
# Get extra files path if provided # Get extra files path if provided
extra_files_path = args.extra_files extra_files_path = args.extra_files