first commit
This commit is contained in:
841
main/CMakeLists.txt
Normal file
841
main/CMakeLists.txt
Normal file
@ -0,0 +1,841 @@
|
||||
# Define default assets files (Absolute url starting with http or https is supported)
|
||||
set(ASSETS_URL_PREFIX "https://files.xiaozhi.me/assets/default/")
|
||||
|
||||
set(ASSETS_PUHUI_COMMON_14_1 "${ASSETS_URL_PREFIX}none-font_puhui_common_14_1-none.bin")
|
||||
set(ASSETS_XIAOZHI_WAKENET_ONLY "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-none-none.bin")
|
||||
set(ASSETS_XIAOZHI_PUHUI_COMMON_14_1 "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-font_puhui_common_14_1-none.bin")
|
||||
set(ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32 "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-font_puhui_common_16_4-emojis_32.bin")
|
||||
set(ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64 "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-font_puhui_common_16_4-emojis_64.bin")
|
||||
set(ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64 "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-emojis_64.bin")
|
||||
set(ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64 "${ASSETS_URL_PREFIX}wn9_nihaoxiaozhi_tts-font_puhui_common_30_4-emojis_64.bin")
|
||||
set(ASSETS_XIAOZHI_S_WAKENET_ONLY "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-none-none.bin")
|
||||
set(ASSETS_XIAOZHI_S_PUHUI_COMMON_14_1 "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-font_puhui_common_14_1-none.bin")
|
||||
set(ASSETS_XIAOZHI_S_PUHUI_COMMON_16_4_EMOJI_32 "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-font_puhui_common_16_4-emojis_32.bin")
|
||||
set(ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_32 "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-font_puhui_common_20_4-emojis_32.bin")
|
||||
set(ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_64 "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-font_puhui_common_20_4-emojis_64.bin")
|
||||
set(ASSETS_XIAOZHI_S_PUHUI_COMMON_30_4_EMOJI_64 "${ASSETS_URL_PREFIX}wn9s_nihaoxiaozhi-font_puhui_common_30_4-emojis_64.bin")
|
||||
|
||||
# Embedded font files defined in `xiaozhi-fonts` component
|
||||
# Basic fonts include ASCII and about 600 characters used in assets/locales
|
||||
set(FONT_PUHUI_BASIC_14_1 font_puhui_basic_14_1)
|
||||
set(FONT_PUHUI_BASIC_16_4 font_puhui_basic_16_4)
|
||||
set(FONT_PUHUI_BASIC_20_4 font_puhui_basic_20_4)
|
||||
set(FONT_PUHUI_BASIC_30_4 font_puhui_basic_30_4)
|
||||
# Common fonts include about 7000 common characters generated with DeepSeek R1 tokenizer
|
||||
set(FONT_PUHUI_COMMON_14_1 font_puhui_14_1)
|
||||
set(FONT_PUHUI_COMMON_16_4 font_puhui_16_4)
|
||||
set(FONT_PUHUI_COMMON_20_4 font_puhui_20_4)
|
||||
set(FONT_PUHUI_COMMON_30_4 font_puhui_30_4)
|
||||
set(FONT_AWESOME_14_1 font_awesome_14_1)
|
||||
set(FONT_AWESOME_30_1 font_awesome_30_1)
|
||||
set(FONT_AWESOME_16_4 font_awesome_16_4)
|
||||
set(FONT_AWESOME_20_4 font_awesome_20_4)
|
||||
set(FONT_AWESOME_30_4 font_awesome_30_4)
|
||||
|
||||
|
||||
# Define source files
|
||||
set(SOURCES "audio/audio_codec.cc"
|
||||
"audio/audio_service.cc"
|
||||
"audio/codecs/no_audio_codec.cc"
|
||||
"audio/codecs/box_audio_codec.cc"
|
||||
"audio/codecs/es8311_audio_codec.cc"
|
||||
"audio/codecs/es8374_audio_codec.cc"
|
||||
"audio/codecs/es8388_audio_codec.cc"
|
||||
"audio/codecs/es8389_audio_codec.cc"
|
||||
"audio/codecs/dummy_audio_codec.cc"
|
||||
"audio/processors/audio_debugger.cc"
|
||||
"led/single_led.cc"
|
||||
"led/circular_strip.cc"
|
||||
"led/gpio_led.cc"
|
||||
"display/display.cc"
|
||||
"display/lcd_display.cc"
|
||||
"display/oled_display.cc"
|
||||
"display/lvgl_display/lvgl_display.cc"
|
||||
"display/lvgl_display/emoji_collection.cc"
|
||||
"display/lvgl_display/lvgl_theme.cc"
|
||||
"display/lvgl_display/lvgl_font.cc"
|
||||
"display/lvgl_display/lvgl_image.cc"
|
||||
"display/lvgl_display/gif/lvgl_gif.cc"
|
||||
"display/lvgl_display/gif/gifdec.c"
|
||||
"protocols/protocol.cc"
|
||||
"protocols/mqtt_protocol.cc"
|
||||
"protocols/websocket_protocol.cc"
|
||||
"mcp_server.cc"
|
||||
"system_info.cc"
|
||||
"application.cc"
|
||||
"ota.cc"
|
||||
"settings.cc"
|
||||
"device_state_event.cc"
|
||||
"assets.cc"
|
||||
"main.cc"
|
||||
)
|
||||
|
||||
set(INCLUDE_DIRS "." "display" "display/lvgl_display" "audio" "protocols")
|
||||
|
||||
# Add board common files
|
||||
file(GLOB BOARD_COMMON_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/boards/common/*.cc)
|
||||
list(APPEND SOURCES ${BOARD_COMMON_SOURCES})
|
||||
list(APPEND INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/boards/common)
|
||||
|
||||
# Set default LVGL_TEXT_FONT and LVGL_ICON_FONT
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
|
||||
# Add board files according to BOARD_TYPE
|
||||
# Set default assets if the board uses partition table V2
|
||||
if(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI)
|
||||
set(BOARD_TYPE "bread-compact-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ML307)
|
||||
set(BOARD_TYPE "bread-compact-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32)
|
||||
set(BOARD_TYPE "bread-compact-esp32")
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_ESP32_LCD)
|
||||
set(BOARD_TYPE "bread-compact-esp32-lcd")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_DF_K10)
|
||||
set(BOARD_TYPE "df-k10")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_DF_S3_AI_CAM)
|
||||
set(BOARD_TYPE "df-s3-ai-cam")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX_3)
|
||||
set(BOARD_TYPE "esp-box-3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX)
|
||||
set(BOARD_TYPE "esp-box")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_BOX_LITE)
|
||||
set(BOARD_TYPE "esp-box-lite")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_1)
|
||||
set(BOARD_TYPE "kevin-box-1")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_BOX_2)
|
||||
set(BOARD_TYPE "kevin-box-2")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_C3)
|
||||
set(BOARD_TYPE "kevin-c3")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V3_DEV)
|
||||
set(BOARD_TYPE "kevin-sp-v3-dev")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_SP_V4_DEV)
|
||||
set(BOARD_TYPE "kevin-sp-v4-dev")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_KEVIN_YUYING_313LCD)
|
||||
set(BOARD_TYPE "kevin-yuying-313lcd")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_LICHUANG_DEV)
|
||||
set(BOARD_TYPE "lichuang-dev")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_LICHUANG_C3_DEV)
|
||||
set(BOARD_TYPE "lichuang-c3-dev")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P4)
|
||||
set(BOARD_TYPE "magiclick-2p4")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_2P5)
|
||||
set(BOARD_TYPE "magiclick-2p5")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3)
|
||||
set(BOARD_TYPE "magiclick-c3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_MAGICLICK_C3_V2)
|
||||
set(BOARD_TYPE "magiclick-c3-v2")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_S3)
|
||||
set(BOARD_TYPE "m5stack-core-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_M5STACK_CORE_TAB5)
|
||||
set(BOARD_TYPE "m5stack-tab5")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3-echo-base")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3R_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3r-echo-base")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMS3R_CAM_M12_ECHO_BASE)
|
||||
set(BOARD_TYPE "atoms3r-cam-m12-echo-base")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_ATOM_ECHOS3R)
|
||||
set(BOARD_TYPE "atom-echos3r")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_ATOMMATRIX_ECHO_BASE)
|
||||
set(BOARD_TYPE "atommatrix-echo-base")
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3_V3)
|
||||
set(BOARD_TYPE "xmini-c3-v3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3_4G)
|
||||
set(BOARD_TYPE "xmini-c3-4g")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_XMINI_C3)
|
||||
set(BOARD_TYPE "xmini-c3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_KORVO2_V3)
|
||||
set(BOARD_TYPE "esp32s3-korvo2-v3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_SPARKBOT)
|
||||
set(BOARD_TYPE "esp-sparkbot")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_SPOT_S3)
|
||||
set(BOARD_TYPE "esp-spot-s3")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_HI)
|
||||
set(BOARD_TYPE "esp-hi")
|
||||
elseif(CONFIG_BOARD_TYPE_ECHOEAR)
|
||||
set(BOARD_TYPE "echoear")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_AUDIO_BOARD)
|
||||
set(BOARD_TYPE "waveshare-s3-audio-board")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8)
|
||||
set(BOARD_TYPE "esp32-s3-touch-amoled-1.8")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-amoled-2.06")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-amoled-1.75")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85C)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85c")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_85)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.85")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_1_46)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-1.46")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_3_5)
|
||||
set(BOARD_TYPE "esp32-s3-touch-lcd-3.5")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Touch_LCD_3_5B)
|
||||
set(BOARD_TYPE "waveshare-s3-touch-lcd-3.5b")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32C6_LCD_1_69)
|
||||
set(BOARD_TYPE "waveshare-c6-lcd-1.69")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32C6_Touch_AMOLED_1_43)
|
||||
set(BOARD_TYPE "waveshare-c6-touch-amoled-1.43")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_NANO)
|
||||
set(BOARD_TYPE "waveshare-p4-nano")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B)
|
||||
set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-4b")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC)
|
||||
set(BOARD_TYPE "waveshare-p4-wifi6-touch-lcd-xc")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_LCD)
|
||||
set(BOARD_TYPE "bread-compact-wifi-lcd")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_TUDOUZI)
|
||||
set(BOARD_TYPE "tudouzi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CIRCLE_S3)
|
||||
set(BOARD_TYPE "lilygo-t-circle-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1)
|
||||
set(BOARD_TYPE "lilygo-t-cameraplus-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA)
|
||||
set(BOARD_TYPE "lilygo-t-display-s3-pro-mvsrlora")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_MOVECALL_MOJI_ESP32S3)
|
||||
set(BOARD_TYPE "movecall-moji-esp32s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_MOVECALL_CUICAN_ESP32S3)
|
||||
set(BOARD_TYPE "movecall-cuican-esp32s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3)
|
||||
set(BOARD_TYPE "atk-dnesp32s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX0)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box0")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box2-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3_BOX2_4G)
|
||||
set(BOARD_TYPE "atk-dnesp32s3-box2-4g")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_WIFI)
|
||||
set(BOARD_TYPE "atk-dnesp32s3m-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ATK_DNESP32S3M_4G)
|
||||
set(BOARD_TYPE "atk-dnesp32s3m-4g")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_DU_CHATX)
|
||||
set(BOARD_TYPE "du-chatx")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32S3_Taiji_Pi)
|
||||
set(BOARD_TYPE "taiji-pi-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.85tft-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_85TFT_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.85tft-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.96oled-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_0_96OLED_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-0.96oled-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_WIFI)
|
||||
set(BOARD_TYPE "xingzhi-cube-1.54tft-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307)
|
||||
set(BOARD_TYPE "xingzhi-cube-1.54tft-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_SENSECAP_WATCHER)
|
||||
set(BOARD_TYPE "sensecap-watcher")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_DOIT_S3_AIBOX)
|
||||
set(BOARD_TYPE "doit-s3-aibox")
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_WAKENET_ONLY})
|
||||
elseif(CONFIG_BOARD_TYPE_MIXGO_NOVA)
|
||||
set(BOARD_TYPE "mixgo-nova")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_GENJUTECH_S3_1_54TFT)
|
||||
set(BOARD_TYPE "genjutech-s3-1.54tft")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_CGC)
|
||||
set(BOARD_TYPE "esp32-cgc")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_CGC_144)
|
||||
set(BOARD_TYPE "esp32-cgc-144")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_14_1})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_14_1})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board)
|
||||
set(BOARD_TYPE "esp-s3-lcd-ev-board")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP_S3_LCD_EV_Board_2)
|
||||
set(BOARD_TYPE "esp-s3-lcd-ev-board-2")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_30_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_30_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI)
|
||||
set(BOARD_TYPE "zhengchen-1.54tft-wifi")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_MINSI_K08_DUAL)
|
||||
set(BOARD_TYPE "minsi-k08-dual")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307)
|
||||
set(BOARD_TYPE "zhengchen-1.54tft-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_S3_1_54_MUMA)
|
||||
set(BOARD_TYPE "sp-esp32-s3-1.54-muma")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_ESP32_S3_1_28_BOX)
|
||||
set(BOARD_TYPE "sp-esp32-s3-1.28-box")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_OTTO_ROBOT)
|
||||
set(BOARD_TYPE "otto-robot")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
elseif(CONFIG_BOARD_TYPE_ELECTRON_BOT)
|
||||
set(BOARD_TYPE "electron-bot")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_COMMON_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
elseif(CONFIG_BOARD_TYPE_BREAD_COMPACT_WIFI_CAM)
|
||||
set(BOARD_TYPE "bread-compact-wifi-s3cam")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_16_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_16_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_JIUCHUAN)
|
||||
set(BOARD_TYPE "jiuchuan-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_LABPLUS_MPYTHON_V3)
|
||||
set(BOARD_TYPE "labplus-mpython-v3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_LABPLUS_LEDONG_V2)
|
||||
set(BOARD_TYPE "labplus-ledong-v2")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_SURFER_C3_1_14TFT)
|
||||
set(BOARD_TYPE "surfer-c3-1.14tft")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_32})
|
||||
elseif(CONFIG_BOARD_TYPE_YUNLIAO_S3)
|
||||
set(BOARD_TYPE "yunliao-s3")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_shhk_CAM)
|
||||
set(BOARD_TYPE "shhk-cam")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
elseif(CONFIG_BOARD_TYPE_ZHENGCHEN_CAM_ML307)
|
||||
set(BOARD_TYPE "zhengchen-cam-ml307")
|
||||
set(LVGL_TEXT_FONT ${FONT_PUHUI_BASIC_20_4})
|
||||
set(LVGL_ICON_FONT ${FONT_AWESOME_20_4})
|
||||
set(DEFAULT_ASSETS ${ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64})
|
||||
endif()
|
||||
|
||||
file(GLOB BOARD_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.cc
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}/*.c
|
||||
)
|
||||
list(APPEND SOURCES ${BOARD_SOURCES})
|
||||
|
||||
# Select audio processor according to Kconfig
|
||||
if(CONFIG_USE_AUDIO_PROCESSOR)
|
||||
list(APPEND SOURCES "audio/processors/afe_audio_processor.cc")
|
||||
else()
|
||||
list(APPEND SOURCES "audio/processors/no_audio_processor.cc")
|
||||
endif()
|
||||
if(CONFIG_USE_AFE_WAKE_WORD)
|
||||
list(APPEND SOURCES "audio/wake_words/afe_wake_word.cc")
|
||||
elseif(CONFIG_USE_ESP_WAKE_WORD)
|
||||
list(APPEND SOURCES "audio/wake_words/esp_wake_word.cc")
|
||||
elseif(CONFIG_USE_CUSTOM_WAKE_WORD)
|
||||
list(APPEND SOURCES "audio/wake_words/custom_wake_word.cc")
|
||||
endif()
|
||||
|
||||
# Select language directory according to Kconfig
|
||||
if(CONFIG_LANGUAGE_ZH_CN)
|
||||
set(LANG_DIR "zh-CN")
|
||||
elseif(CONFIG_LANGUAGE_ZH_TW)
|
||||
set(LANG_DIR "zh-TW")
|
||||
elseif(CONFIG_LANGUAGE_EN_US)
|
||||
set(LANG_DIR "en-US")
|
||||
elseif(CONFIG_LANGUAGE_JA_JP)
|
||||
set(LANG_DIR "ja-JP")
|
||||
elseif(CONFIG_LANGUAGE_KO_KR)
|
||||
set(LANG_DIR "ko-KR")
|
||||
elseif(CONFIG_LANGUAGE_VI_VN)
|
||||
set(LANG_DIR "vi-VN")
|
||||
elseif(CONFIG_LANGUAGE_TH_TH)
|
||||
set(LANG_DIR "th-TH")
|
||||
elseif(CONFIG_LANGUAGE_DE_DE)
|
||||
set(LANG_DIR "de-DE")
|
||||
elseif(CONFIG_LANGUAGE_FR_FR)
|
||||
set(LANG_DIR "fr-FR")
|
||||
elseif(CONFIG_LANGUAGE_ES_ES)
|
||||
set(LANG_DIR "es-ES")
|
||||
elseif(CONFIG_LANGUAGE_IT_IT)
|
||||
set(LANG_DIR "it-IT")
|
||||
elseif(CONFIG_LANGUAGE_RU_RU)
|
||||
set(LANG_DIR "ru-RU")
|
||||
elseif(CONFIG_LANGUAGE_AR_SA)
|
||||
set(LANG_DIR "ar-SA")
|
||||
elseif(CONFIG_LANGUAGE_HI_IN)
|
||||
set(LANG_DIR "hi-IN")
|
||||
elseif(CONFIG_LANGUAGE_PT_PT)
|
||||
set(LANG_DIR "pt-PT")
|
||||
elseif(CONFIG_LANGUAGE_PL_PL)
|
||||
set(LANG_DIR "pl-PL")
|
||||
elseif(CONFIG_LANGUAGE_CS_CZ)
|
||||
set(LANG_DIR "cs-CZ")
|
||||
elseif(CONFIG_LANGUAGE_FI_FI)
|
||||
set(LANG_DIR "fi-FI")
|
||||
elseif(CONFIG_LANGUAGE_TR_TR)
|
||||
set(LANG_DIR "tr-TR")
|
||||
elseif(CONFIG_LANGUAGE_ID_ID)
|
||||
set(LANG_DIR "id-ID")
|
||||
elseif(CONFIG_LANGUAGE_UK_UA)
|
||||
set(LANG_DIR "uk-UA")
|
||||
elseif(CONFIG_LANGUAGE_RO_RO)
|
||||
set(LANG_DIR "ro-RO")
|
||||
endif()
|
||||
|
||||
# Define generation path
|
||||
set(LANG_JSON "${CMAKE_CURRENT_SOURCE_DIR}/assets/locales/${LANG_DIR}/language.json")
|
||||
set(LANG_HEADER "${CMAKE_CURRENT_SOURCE_DIR}/assets/lang_config.h")
|
||||
file(GLOB LANG_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/locales/${LANG_DIR}/*.ogg)
|
||||
file(GLOB COMMON_SOUNDS ${CMAKE_CURRENT_SOURCE_DIR}/assets/common/*.ogg)
|
||||
|
||||
# If target chip is ESP32, exclude specific files to avoid build errors
|
||||
if(CONFIG_IDF_TARGET_ESP32)
|
||||
list(REMOVE_ITEM SOURCES "audio/codecs/box_audio_codec.cc"
|
||||
"audio/codecs/es8388_audio_codec.cc"
|
||||
"audio/codecs/es8389_audio_codec.cc"
|
||||
"led/gpio_led.cc"
|
||||
)
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS ${SOURCES}
|
||||
EMBED_FILES ${LANG_SOUNDS} ${COMMON_SOUNDS}
|
||||
INCLUDE_DIRS ${INCLUDE_DIRS}
|
||||
WHOLE_ARCHIVE
|
||||
)
|
||||
|
||||
# Use target_compile_definitions to define BOARD_TYPE, BOARD_NAME
|
||||
# If BOARD_NAME is empty, use BOARD_TYPE
|
||||
if(NOT BOARD_NAME)
|
||||
set(BOARD_NAME ${BOARD_TYPE})
|
||||
endif()
|
||||
target_compile_definitions(${COMPONENT_LIB}
|
||||
PRIVATE BOARD_TYPE=\"${BOARD_TYPE}\" BOARD_NAME=\"${BOARD_NAME}\"
|
||||
PRIVATE DEFAULT_ASSETS=\"${DEFAULT_ASSETS}\" LVGL_TEXT_FONT=${LVGL_TEXT_FONT} LVGL_ICON_FONT=${LVGL_ICON_FONT}
|
||||
)
|
||||
|
||||
# Add generation rules
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_HEADER}
|
||||
COMMAND python ${PROJECT_DIR}/scripts/gen_lang.py
|
||||
--language "${LANG_DIR}"
|
||||
--output "${LANG_HEADER}"
|
||||
DEPENDS
|
||||
${LANG_JSON}
|
||||
${PROJECT_DIR}/scripts/gen_lang.py
|
||||
COMMENT "Generating ${LANG_DIR} language config"
|
||||
)
|
||||
|
||||
# Force build generation dependencies
|
||||
add_custom_target(lang_header ALL
|
||||
DEPENDS ${LANG_HEADER}
|
||||
)
|
||||
|
||||
if(CONFIG_BOARD_TYPE_ESP_HI)
|
||||
set(URL "https://github.com/espressif2022/image_player/raw/main/test_apps/test_8bit")
|
||||
set(SPIFFS_DIR "${CMAKE_BINARY_DIR}/emoji")
|
||||
file(MAKE_DIRECTORY ${SPIFFS_DIR})
|
||||
|
||||
# List all files to download
|
||||
set(FILES_TO_DOWNLOAD "")
|
||||
list(APPEND FILES_TO_DOWNLOAD "Anger_enter.aaf" "Anger_loop.aaf" "Anger_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "happy_enter.aaf" "happy_loop.aaf" "happ_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "sad_enter.aaf" "sad_loop.aaf" "sad_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "scorn_enter.aaf" "scorn_loop.aaf" "scorn_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "left_enter.aaf" "left_loop.aaf" "left_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "right_enter.aaf" "right_loop.aaf" "right_return.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "asking.aaf" "blink_once.aaf" "blink_quick.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "connecting.aaf" "panic_enter.aaf" "panic_loop.aaf")
|
||||
list(APPEND FILES_TO_DOWNLOAD "panic_return.aaf" "wake.aaf")
|
||||
|
||||
foreach(FILENAME IN LISTS FILES_TO_DOWNLOAD)
|
||||
set(REMOTE_FILE "${URL}/${FILENAME}")
|
||||
set(LOCAL_FILE "${SPIFFS_DIR}/${FILENAME}")
|
||||
|
||||
# Check if local file exists
|
||||
if(EXISTS ${LOCAL_FILE})
|
||||
message(STATUS "File ${FILENAME} already exists, skipping download")
|
||||
else()
|
||||
message(STATUS "Downloading ${FILENAME}")
|
||||
file(DOWNLOAD ${REMOTE_FILE} ${LOCAL_FILE}
|
||||
STATUS DOWNLOAD_STATUS)
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
if(NOT STATUS_CODE EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download ${FILENAME} from ${URL}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
spiffs_create_partition_assets(
|
||||
assets_A
|
||||
${SPIFFS_DIR}
|
||||
FLASH_IN_PROJECT
|
||||
MMAP_FILE_SUPPORT_FORMAT ".aaf"
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CONFIG_BOARD_TYPE_ECHOEAR)
|
||||
|
||||
idf_build_get_property(build_components BUILD_COMPONENTS)
|
||||
foreach(COMPONENT ${build_components})
|
||||
if(COMPONENT MATCHES "esp_emote_gfx" OR COMPONENT MATCHES "espressif2022__esp_emote_gfx")
|
||||
set(EMOTE_GFX_COMPONENT ${COMPONENT})
|
||||
idf_component_get_property(EMOTE_GFX_COMPONENT_PATH ${EMOTE_GFX_COMPONENT} COMPONENT_DIR)
|
||||
set(SPIFFS_DIR "${EMOTE_GFX_COMPONENT_PATH}/emoji_normal")
|
||||
break()
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
spiffs_create_partition_assets(
|
||||
assets_A
|
||||
${SPIFFS_DIR}
|
||||
FLASH_IN_PROJECT
|
||||
MMAP_FILE_SUPPORT_FORMAT ".aaf, ttf, bin"
|
||||
IMPORT_INC_PATH ${CMAKE_CURRENT_SOURCE_DIR}/boards/${BOARD_TYPE}
|
||||
)
|
||||
endif()
|
||||
|
||||
# Font configuration validation function
|
||||
function(validate_font_config board_name text_font default_assets)
|
||||
if(text_font)
|
||||
# Check if DEFAULT_ASSETS contains font
|
||||
if(default_assets AND default_assets MATCHES "font_")
|
||||
# Rule 1: If DEFAULT_ASSETS uses font, LVGL_TEXT_FONT must be BASIC
|
||||
if(NOT text_font MATCHES "basic")
|
||||
message(FATAL_ERROR "Font config error for ${board_name}: DEFAULT_ASSETS contains COMMON font but LVGL_TEXT_FONT is not BASIC (${text_font})")
|
||||
endif()
|
||||
else()
|
||||
# Rule 2: If no DEFAULT_ASSETS or DEFAULT_ASSETS doesn't contain font_, LVGL_TEXT_FONT must not be BASIC
|
||||
if(text_font MATCHES "basic")
|
||||
message(FATAL_ERROR "Font config error for ${board_name}: No DEFAULT_ASSETS with COMMON font but LVGL_TEXT_FONT is not COMMON (${text_font})")
|
||||
endif()
|
||||
endif()
|
||||
# Pass validation
|
||||
message(STATUS "Font config validation passed for ${board_name}: LVGL_TEXT_FONT=${text_font}, DEFAULT_ASSETS=${default_assets}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# DEFAULT_ASSETS prefix validation function
|
||||
function(validate_default_assets_prefix board_name default_assets)
|
||||
if(default_assets)
|
||||
# Check for ESP32S3/P4 target - DEFAULT_ASSETS cannot start with "wn9s_"
|
||||
if(CONFIG_IDF_TARGET_ESP32S3 OR CONFIG_IDF_TARGET_ESP32P4)
|
||||
if(default_assets MATCHES "^wn9s_")
|
||||
message(FATAL_ERROR "Assets config error for ${board_name}: DEFAULT_ASSETS cannot start with 'wn9s_' for ESP32S3 target (${default_assets})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Check for ESP32C3/C6 target - DEFAULT_ASSETS cannot start with "wn9_"
|
||||
if(CONFIG_IDF_TARGET_ESP32C3 OR CONFIG_IDF_TARGET_ESP32C6)
|
||||
if(default_assets MATCHES "^wn9_")
|
||||
message(FATAL_ERROR "Assets config error for ${board_name}: DEFAULT_ASSETS cannot start with 'wn9_' for ESP32C3/C6 target (${default_assets})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Pass validation
|
||||
message(STATUS "Assets prefix validation passed for ${board_name}: DEFAULT_ASSETS=${default_assets}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Global font configuration validation
|
||||
# This will validate the current board's font configuration
|
||||
if(LVGL_TEXT_FONT)
|
||||
validate_font_config("${BOARD_TYPE}" "${LVGL_TEXT_FONT}" "${DEFAULT_ASSETS}")
|
||||
endif()
|
||||
|
||||
# Global DEFAULT_ASSETS prefix validation
|
||||
# This will validate the current board's DEFAULT_ASSETS prefix configuration
|
||||
if(DEFAULT_ASSETS)
|
||||
validate_default_assets_prefix("${BOARD_TYPE}" "${DEFAULT_ASSETS}")
|
||||
endif()
|
||||
|
||||
# Function to get local assets file path (handles both URL and local file)
|
||||
function(get_assets_local_file assets_source assets_local_file_var)
|
||||
# Check if it's a URL (starts with http:// or https://)
|
||||
if(assets_source MATCHES "^https?://")
|
||||
# It's a URL, download it
|
||||
get_filename_component(ASSETS_FILENAME "${assets_source}" NAME)
|
||||
set(ASSETS_LOCAL_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}")
|
||||
set(ASSETS_TEMP_FILE "${CMAKE_BINARY_DIR}/${ASSETS_FILENAME}.tmp")
|
||||
|
||||
# Check if local file exists
|
||||
if(EXISTS ${ASSETS_LOCAL_FILE})
|
||||
message(STATUS "Assets file ${ASSETS_FILENAME} already exists, skipping download")
|
||||
else()
|
||||
message(STATUS "Downloading ${ASSETS_FILENAME}")
|
||||
|
||||
# Clean up any existing temp file
|
||||
if(EXISTS ${ASSETS_TEMP_FILE})
|
||||
file(REMOVE ${ASSETS_TEMP_FILE})
|
||||
endif()
|
||||
|
||||
# Download to temporary file first
|
||||
file(DOWNLOAD ${assets_source} ${ASSETS_TEMP_FILE}
|
||||
STATUS DOWNLOAD_STATUS)
|
||||
list(GET DOWNLOAD_STATUS 0 STATUS_CODE)
|
||||
if(NOT STATUS_CODE EQUAL 0)
|
||||
# Clean up temp file on failure
|
||||
if(EXISTS ${ASSETS_TEMP_FILE})
|
||||
file(REMOVE ${ASSETS_TEMP_FILE})
|
||||
endif()
|
||||
message(FATAL_ERROR "Failed to download ${ASSETS_FILENAME} from ${assets_source}")
|
||||
endif()
|
||||
|
||||
# Move temp file to final location (atomic operation)
|
||||
file(RENAME ${ASSETS_TEMP_FILE} ${ASSETS_LOCAL_FILE})
|
||||
message(STATUS "Successfully downloaded ${ASSETS_FILENAME}")
|
||||
endif()
|
||||
else()
|
||||
# It's a local file path
|
||||
if(IS_ABSOLUTE "${assets_source}")
|
||||
set(ASSETS_LOCAL_FILE "${assets_source}")
|
||||
else()
|
||||
set(ASSETS_LOCAL_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${assets_source}")
|
||||
endif()
|
||||
|
||||
# Check if local file exists
|
||||
if(NOT EXISTS ${ASSETS_LOCAL_FILE})
|
||||
message(FATAL_ERROR "Assets file not found: ${ASSETS_LOCAL_FILE}")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using assets file: ${ASSETS_LOCAL_FILE}")
|
||||
endif()
|
||||
|
||||
set(${assets_local_file_var} ${ASSETS_LOCAL_FILE} PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Flash assets based on configuration
|
||||
if(CONFIG_FLASH_DEFAULT_ASSETS)
|
||||
# Flash default assets
|
||||
if(DEFAULT_ASSETS)
|
||||
get_assets_local_file("${DEFAULT_ASSETS}" ASSETS_LOCAL_FILE)
|
||||
esptool_py_flash_to_partition(flash "assets" "${ASSETS_LOCAL_FILE}")
|
||||
message(STATUS "Default assets download and flash configured: ${DEFAULT_ASSETS} -> assets partition")
|
||||
else()
|
||||
message(WARNING "FLASH_DEFAULT_ASSETS is enabled but no DEFAULT_ASSETS is defined for board ${BOARD_TYPE}")
|
||||
endif()
|
||||
elseif(CONFIG_FLASH_CUSTOM_ASSETS)
|
||||
# Flash custom assets
|
||||
get_assets_local_file("${CONFIG_CUSTOM_ASSETS_FILE}" ASSETS_LOCAL_FILE)
|
||||
esptool_py_flash_to_partition(flash "assets" "${ASSETS_LOCAL_FILE}")
|
||||
message(STATUS "Custom assets flash configured: ${ASSETS_LOCAL_FILE} -> assets partition")
|
||||
elseif(CONFIG_FLASH_NONE_ASSETS)
|
||||
message(STATUS "Assets flashing disabled (FLASH_NONE_ASSETS)")
|
||||
endif()
|
||||
588
main/Kconfig.projbuild
Normal file
588
main/Kconfig.projbuild
Normal file
@ -0,0 +1,588 @@
|
||||
menu "Xiaozhi Assistant"
|
||||
|
||||
config OTA_URL
|
||||
string "Default OTA URL"
|
||||
default "https://api.tenclass.net/xiaozhi/ota/"
|
||||
help
|
||||
The application will access this URL to check for new firmwares and server address.
|
||||
|
||||
choice
|
||||
prompt "Flash Assets"
|
||||
default FLASH_NONE_ASSETS
|
||||
help
|
||||
Select the assets to flash.
|
||||
|
||||
config FLASH_NONE_ASSETS
|
||||
bool "Do not flash assets"
|
||||
config FLASH_DEFAULT_ASSETS
|
||||
bool "Flash Default Assets"
|
||||
config FLASH_CUSTOM_ASSETS
|
||||
bool "Flash Custom Assets"
|
||||
endchoice
|
||||
|
||||
config CUSTOM_ASSETS_FILE
|
||||
depends on FLASH_CUSTOM_ASSETS
|
||||
string "Custom Assets File"
|
||||
default "assets.bin"
|
||||
help
|
||||
The custom assets file to flash.
|
||||
It can be a local file relative to the project directory or a remote url.
|
||||
|
||||
choice
|
||||
prompt "Default Language"
|
||||
default LANGUAGE_ZH_CN
|
||||
help
|
||||
Select device display language
|
||||
|
||||
config LANGUAGE_ZH_CN
|
||||
bool "Chinese"
|
||||
config LANGUAGE_ZH_TW
|
||||
bool "Chinese Traditional"
|
||||
config LANGUAGE_EN_US
|
||||
bool "English"
|
||||
config LANGUAGE_JA_JP
|
||||
bool "Japanese"
|
||||
config LANGUAGE_KO_KR
|
||||
bool "Korean"
|
||||
config LANGUAGE_VI_VN
|
||||
bool "Vietnamese"
|
||||
config LANGUAGE_TH_TH
|
||||
bool "Thai"
|
||||
config LANGUAGE_DE_DE
|
||||
bool "German"
|
||||
config LANGUAGE_FR_FR
|
||||
bool "French"
|
||||
config LANGUAGE_ES_ES
|
||||
bool "Spanish"
|
||||
config LANGUAGE_IT_IT
|
||||
bool "Italian"
|
||||
config LANGUAGE_RU_RU
|
||||
bool "Russian"
|
||||
config LANGUAGE_AR_SA
|
||||
bool "Arabic"
|
||||
config LANGUAGE_HI_IN
|
||||
bool "Hindi"
|
||||
config LANGUAGE_PT_PT
|
||||
bool "Portuguese"
|
||||
config LANGUAGE_PL_PL
|
||||
bool "Polish"
|
||||
config LANGUAGE_CS_CZ
|
||||
bool "Czech"
|
||||
config LANGUAGE_FI_FI
|
||||
bool "Finnish"
|
||||
config LANGUAGE_TR_TR
|
||||
bool "Turkish"
|
||||
config LANGUAGE_ID_ID
|
||||
bool "Indonesian"
|
||||
config LANGUAGE_UK_UA
|
||||
bool "Ukrainian"
|
||||
config LANGUAGE_RO_RO
|
||||
bool "Romanian"
|
||||
endchoice
|
||||
|
||||
choice BOARD_TYPE
|
||||
prompt "Board Type"
|
||||
default BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
help
|
||||
Board type. 开发板类型
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI
|
||||
bool "面包板新版接线(WiFi)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_LCD
|
||||
bool "面包板新版接线(WiFi)+ LCD"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
bool "面包板新版接线(WiFi)+ LCD + Camera"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ML307
|
||||
bool "面包板新版接线(ML307 AT)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
bool "面包板(WiFi) ESP32 DevKit"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_BREAD_COMPACT_ESP32_LCD
|
||||
bool "面包板(WiFi+ LCD) ESP32 DevKit"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_XMINI_C3_V3
|
||||
bool "虾哥 Mini C3 V3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3_4G
|
||||
bool "虾哥 Mini C3 4G"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_XMINI_C3
|
||||
bool "虾哥 Mini C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_ESP32S3_KORVO2_V3
|
||||
bool "ESP32S3_KORVO2_V3开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPARKBOT
|
||||
bool "ESP-SparkBot开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_SPOT_S3
|
||||
bool "ESP-Spot-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_HI
|
||||
bool "ESP-HI"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_ECHOEAR
|
||||
bool "EchoEar"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX_3
|
||||
bool "ESP BOX 3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX
|
||||
bool "ESP BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_BOX_LITE
|
||||
bool "ESP BOX Lite"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_BOX_1
|
||||
bool "Kevin Box 1"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_BOX_2
|
||||
bool "Kevin Box 2"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_C3
|
||||
bool "Kevin C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_KEVIN_SP_V3_DEV
|
||||
bool "Kevin SP V3开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_KEVIN_SP_V4_DEV
|
||||
bool "Kevin SP V4开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32_CGC
|
||||
bool "ESP32 CGC"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_ESP32_CGC_144
|
||||
bool "ESP32 CGC 144"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_KEVIN_YUYING_313LCD
|
||||
bool "鱼鹰科技3.13LCD开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LICHUANG_DEV
|
||||
bool "立创·实战派ESP32-S3开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LICHUANG_C3_DEV
|
||||
bool "立创·实战派ESP32-C3开发板"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_DF_K10
|
||||
bool "DFRobot 行空板 k10"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DF_S3_AI_CAM
|
||||
bool "DFRobot ESP32-S3 AI智能摄像头模块"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_2P4
|
||||
bool "神奇按钮 Magiclick_2.4"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_2P5
|
||||
bool "神奇按钮 Magiclick_2.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MAGICLICK_C3
|
||||
bool "神奇按钮 Magiclick_C3"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_MAGICLICK_C3_V2
|
||||
bool "神奇按钮 Magiclick_C3_v2"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_M5STACK_CORE_S3
|
||||
bool "M5Stack CoreS3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_M5STACK_CORE_TAB5
|
||||
bool "M5Stack Tab5"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ATOMS3_ECHO_BASE
|
||||
bool "AtomS3 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMS3R_ECHO_BASE
|
||||
bool "AtomS3R + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMS3R_CAM_M12_ECHO_BASE
|
||||
bool "AtomS3R CAM/M12 + Echo Base"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOM_ECHOS3R
|
||||
bool "AtomEchoS3R"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATOMMATRIX_ECHO_BASE
|
||||
bool "AtomMatrix + Echo Base"
|
||||
depends on IDF_TARGET_ESP32
|
||||
config BOARD_TYPE_ESP32S3_AUDIO_BOARD
|
||||
bool "Waveshare ESP32-S3-Audio-Board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_AMOLED_1_8
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-1.8"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-2.06"
|
||||
config BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75
|
||||
bool "Waveshare ESP32-S3-Touch-AMOLED-1.75"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_LCD_1_85C
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.85C"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_LCD_1_85
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.85"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_LCD_1_46
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-1.46"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32C6_LCD_1_69
|
||||
bool "Waveshare ESP32-C6-LCD-1.69"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_ESP32C6_Touch_AMOLED_1_43
|
||||
bool "Waveshare ESP32-C6-Touch-AMOLOED-1.43"
|
||||
depends on IDF_TARGET_ESP32C6
|
||||
config BOARD_TYPE_ESP32S3_Touch_LCD_3_5
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Touch_LCD_3_5B
|
||||
bool "Waveshare ESP32-S3-Touch-LCD-3.5B"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32P4_NANO
|
||||
bool "Waveshare ESP32-P4-NANO"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4B"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C or ESP32-P4-WIFI6-Touch-LCD-4C"
|
||||
depends on IDF_TARGET_ESP32P4
|
||||
config BOARD_TYPE_TUDOUZI
|
||||
bool "土豆子"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CIRCLE_S3
|
||||
bool "LILYGO T-Circle-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_0_V1_1
|
||||
bool "LILYGO T-CameraPlus-S3_V1_0_V1_1"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_CAMERAPLUS_S3_V1_2
|
||||
bool "LILYGO T-CameraPlus-S3_V1_2"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA
|
||||
bool "LILYGO T-Display-S3-Pro-MVSRLora"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LILYGO_T_DISPLAY_S3_PRO_MVSRLORA_NO_BATTERY
|
||||
bool "LILYGO T-Display-S3-Pro-MVSRLora_No_Battery"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MOVECALL_MOJI_ESP32S3
|
||||
bool "Movecall Moji 小智AI衍生版"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MOVECALL_CUICAN_ESP32S3
|
||||
bool "Movecall CuiCan 璀璨·AI吊坠"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3
|
||||
bool "正点原子DNESP32S3开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX
|
||||
bool "正点原子DNESP32S3-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX0
|
||||
bool "正点原子DNESP32S3-BOX0"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX2_WIFI
|
||||
bool "正点原子DNESP32S3-BOX2-WIFI"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3_BOX2_4G
|
||||
bool "正点原子DNESP32S3-BOX2-4G"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3M_WIFI
|
||||
bool "正点原子DNESP32S3M-WIFI"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ATK_DNESP32S3M_4G
|
||||
bool "正点原子DNESP32S3M-4G"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DU_CHATX
|
||||
bool "嘟嘟开发板CHATX(wifi)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32S3_Taiji_Pi
|
||||
bool "太极小派esp32s3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_0_85TFT_WIFI
|
||||
bool "无名科技星智0.85(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_0_85TFT_ML307
|
||||
bool "无名科技星智0.85(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_0_96OLED_WIFI
|
||||
bool "无名科技星智0.96(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_0_96OLED_ML307
|
||||
bool "无名科技星智0.96(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_1_54TFT_WIFI
|
||||
bool "无名科技星智1.54(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_XINGZHI_Cube_1_54TFT_ML307
|
||||
bool "无名科技星智1.54(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SENSECAP_WATCHER
|
||||
bool "SenseCAP Watcher"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_DOIT_S3_AIBOX
|
||||
bool "四博智联AI陪伴盒子"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_MIXGO_NOVA
|
||||
bool "元控·青春"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_GENJUTECH_S3_1_54TFT
|
||||
bool "亘具科技1.54(s3)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_S3_LCD_EV_Board
|
||||
bool "乐鑫ESP S3 LCD EV Board开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP_S3_LCD_EV_Board_2
|
||||
bool "乐鑫ESP S3 LCD EV Board 2开发板"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_shhk_CAM
|
||||
bool "幻鲲科技AI Camera"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_1_54TFT_WIFI
|
||||
bool "征辰科技1.54(WIFI)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_1_54TFT_ML307
|
||||
bool "征辰科技1.54(ML307)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ZHENGCHEN_CAM_ML307
|
||||
bool "征辰科技AI Camera(ML307)"
|
||||
config BOARD_TYPE_MINSI_K08_DUAL
|
||||
bool "敏思科技K08(DUAL)"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32_S3_1_54_MUMA
|
||||
bool "Spotpear ESP32-S3-1.54-MUMA"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_ESP32_S3_1_28_BOX
|
||||
bool "Spotpear ESP32-S3-1.28-BOX"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_OTTO_ROBOT
|
||||
bool "ottoRobot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
select LV_USE_GIF
|
||||
select LV_GIF_CACHE_DECODE_DATA
|
||||
config BOARD_TYPE_ELECTRON_BOT
|
||||
bool "electronBot"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
select LV_USE_GIF
|
||||
select LV_GIF_CACHE_DECODE_DATA
|
||||
config BOARD_TYPE_JIUCHUAN
|
||||
bool "九川智能"
|
||||
config BOARD_TYPE_LABPLUS_MPYTHON_V3
|
||||
bool "labplus mpython_v3 board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_LABPLUS_LEDONG_V2
|
||||
bool "labplus ledong_v2 board"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
config BOARD_TYPE_SURFER_C3_1_14TFT
|
||||
bool "Surfer-C3-1-14TFT"
|
||||
depends on IDF_TARGET_ESP32C3
|
||||
config BOARD_TYPE_YUNLIAO_S3
|
||||
bool "小智云聊-S3"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
endchoice
|
||||
|
||||
choice ESP_S3_LCD_EV_Board_Version_TYPE
|
||||
depends on BOARD_TYPE_ESP_S3_LCD_EV_Board
|
||||
prompt "EV_BOARD Type"
|
||||
default ESP_S3_LCD_EV_Board_1p4
|
||||
help
|
||||
开发板硬件版本型号选择
|
||||
config ESP_S3_LCD_EV_Board_1p4
|
||||
bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.4"
|
||||
config ESP_S3_LCD_EV_Board_1p5
|
||||
bool "乐鑫ESP32_S3_LCD_EV_Board-MB_V1.5"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_OLED_TYPE
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI || BOARD_TYPE_BREAD_COMPACT_ML307 || BOARD_TYPE_BREAD_COMPACT_ESP32
|
||||
prompt "OLED Type"
|
||||
default OLED_SSD1306_128X32
|
||||
help
|
||||
OLED 屏幕类型选择
|
||||
config OLED_SSD1306_128X32
|
||||
bool "SSD1306, 分辨率128*32"
|
||||
config OLED_SSD1306_128X64
|
||||
bool "SSD1306, 分辨率128*64"
|
||||
config OLED_SH1106_128X64
|
||||
bool "SH1106, 分辨率128*64"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_LCD_TYPE
|
||||
depends on BOARD_TYPE_BREAD_COMPACT_WIFI_LCD || BOARD_TYPE_BREAD_COMPACT_ESP32_LCD || BOARD_TYPE_ESP32_CGC || BOARD_TYPE_ESP32P4_NANO || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC || BOARD_TYPE_BREAD_COMPACT_WIFI_CAM
|
||||
prompt "LCD Type"
|
||||
default LCD_ST7789_240X320
|
||||
help
|
||||
屏幕类型选择
|
||||
config LCD_ST7789_240X320
|
||||
bool "ST7789, 分辨率240*320, IPS"
|
||||
config LCD_ST7789_240X320_NO_IPS
|
||||
bool "ST7789, 分辨率240*320, 非IPS"
|
||||
config LCD_ST7789_170X320
|
||||
bool "ST7789, 分辨率170*320"
|
||||
config LCD_ST7789_172X320
|
||||
bool "ST7789, 分辨率172*320"
|
||||
config LCD_ST7789_240X280
|
||||
bool "ST7789, 分辨率240*280"
|
||||
config LCD_ST7789_240X240
|
||||
bool "ST7789, 分辨率240*240"
|
||||
config LCD_ST7789_240X240_7PIN
|
||||
bool "ST7789, 分辨率240*240, 7PIN"
|
||||
config LCD_ST7789_240X135
|
||||
bool "ST7789, 分辨率240*135"
|
||||
config LCD_ST7735_128X160
|
||||
bool "ST7735, 分辨率128*160"
|
||||
config LCD_ST7735_128X128
|
||||
bool "ST7735, 分辨率128*128"
|
||||
config LCD_ST7796_320X480
|
||||
bool "ST7796, 分辨率320*480 IPS"
|
||||
config LCD_ST7796_320X480_NO_IPS
|
||||
bool "ST7796, 分辨率320*480, 非IPS"
|
||||
config LCD_ILI9341_240X320
|
||||
bool "ILI9341, 分辨率240*320"
|
||||
config LCD_ILI9341_240X320_NO_IPS
|
||||
bool "ILI9341, 分辨率240*320, 非IPS"
|
||||
config LCD_GC9A01_240X240
|
||||
bool "GC9A01, 分辨率240*240, 圆屏"
|
||||
config LCD_TYPE_800_1280_10_1_INCH
|
||||
bool "Waveshare 101M-8001280-IPS-CT-K Display"
|
||||
config LCD_TYPE_800_1280_10_1_INCH_A
|
||||
bool "Waveshare 10.1-DSI-TOUCH-A Display"
|
||||
config LCD_TYPE_800_800_3_4_INCH
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-3.4C with 800*800 3.4inch round display"
|
||||
config LCD_TYPE_720_720_4_INCH
|
||||
bool "Waveshare ESP32-P4-WIFI6-Touch-LCD-4C with 720*720 4inch round display"
|
||||
config LCD_CUSTOM
|
||||
bool "自定义屏幕参数"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_KORVO2_V3
|
||||
depends on BOARD_TYPE_ESP32S3_KORVO2_V3
|
||||
prompt "ESP32S3_KORVO2_V3 LCD Type"
|
||||
default ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
help
|
||||
屏幕类型选择
|
||||
config ESP32S3_KORVO2_V3_LCD_ST7789
|
||||
bool "ST7789, 分辨率240*280"
|
||||
config ESP32S3_KORVO2_V3_LCD_ILI9341
|
||||
bool "ILI9341, 分辨率240*320"
|
||||
endchoice
|
||||
|
||||
choice DISPLAY_ESP32S3_AUDIO_BOARD
|
||||
depends on BOARD_TYPE_ESP32S3_AUDIO_BOARD
|
||||
prompt "ESP32S3_AUDIO_BOARD LCD Type"
|
||||
default AUDIO_BOARD_LCD_JD9853
|
||||
help
|
||||
屏幕类型选择
|
||||
config AUDIO_BOARD_LCD_JD9853
|
||||
bool "JD9853, 分辨率320*172"
|
||||
config AUDIO_BOARD_LCD_ST7789
|
||||
bool "ST7789, 分辨率240*320"
|
||||
endchoice
|
||||
|
||||
config USE_WECHAT_MESSAGE_STYLE
|
||||
bool "Enable WeChat Message Style"
|
||||
default n
|
||||
help
|
||||
使用微信聊天界面风格
|
||||
|
||||
config USE_ESP_WAKE_WORD
|
||||
bool "Enable Wake Word Detection (without AFE)"
|
||||
default n
|
||||
depends on IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C5 || IDF_TARGET_ESP32C6 || (IDF_TARGET_ESP32 && SPIRAM)
|
||||
help
|
||||
支持 ESP32 C3、ESP32 C5 与 ESP32 C6,增加ESP32支持(需要开启PSRAM)
|
||||
|
||||
config USE_AFE_WAKE_WORD
|
||||
bool "Enable Wake Word Detection (AFE)"
|
||||
default y
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
需要 ESP32 S3 与 PSRAM 支持
|
||||
|
||||
config USE_CUSTOM_WAKE_WORD
|
||||
bool "Enable Custom Wake Word Detection"
|
||||
default n
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM && (!USE_AFE_WAKE_WORD)
|
||||
help
|
||||
需要 ESP32 S3 与 PSRAM 支持
|
||||
|
||||
config CUSTOM_WAKE_WORD
|
||||
string "Custom Wake Word"
|
||||
default "xiao tu dou"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
自定义唤醒词,中文用拼音表示,每个字之间用空格隔开
|
||||
|
||||
config CUSTOM_WAKE_WORD_DISPLAY
|
||||
string "Custom Wake Word Display"
|
||||
default "小土豆"
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
唤醒后发送给服务器的问候语
|
||||
|
||||
config CUSTOM_WAKE_WORD_THRESHOLD
|
||||
int "Custom Wake Word Threshold (%)"
|
||||
default 20
|
||||
range 1 99
|
||||
depends on USE_CUSTOM_WAKE_WORD
|
||||
help
|
||||
自定义唤醒词阈值,范围1-99,越小越敏感,默认10
|
||||
|
||||
config USE_AUDIO_PROCESSOR
|
||||
bool "Enable Audio Noise Reduction"
|
||||
default y
|
||||
depends on (IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32P4) && SPIRAM
|
||||
help
|
||||
需要 ESP32 S3 与 PSRAM 支持
|
||||
|
||||
config USE_DEVICE_AEC
|
||||
bool "Enable Device-Side AEC"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR && (BOARD_TYPE_ESP_BOX_3 || BOARD_TYPE_ESP_BOX || BOARD_TYPE_ESP_BOX_LITE || BOARD_TYPE_LICHUANG_DEV || BOARD_TYPE_ESP32S3_KORVO2_V3 || BOARD_TYPE_ESP32S3_Touch_AMOLED_1_75 || BOARD_TYPE_ESP32S3_Touch_AMOLED_2_06 || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_4B || BOARD_TYPE_ESP32P4_WIFI6_Touch_LCD_XC || BOARD_TYPE_ESP_S3_LCD_EV_Board_2 || BOARD_TYPE_YUNLIAO_S3 || BOARD_TYPE_ZHENGCHEN_CAM || BOARD_TYPE_ZHENGCHEN_CAM_ML307)
|
||||
help
|
||||
因为性能不够,不建议和微信聊天界面风格同时开启
|
||||
|
||||
config USE_SERVER_AEC
|
||||
bool "Enable Server-Side AEC (Unstable)"
|
||||
default n
|
||||
depends on USE_AUDIO_PROCESSOR
|
||||
help
|
||||
启用服务器端 AEC,需要服务器支持
|
||||
|
||||
config USE_AUDIO_DEBUGGER
|
||||
bool "Enable Audio Debugger"
|
||||
default n
|
||||
help
|
||||
启用音频调试功能,通过UDP发送音频数据
|
||||
|
||||
config USE_ACOUSTIC_WIFI_PROVISIONING
|
||||
bool "Enable Acoustic WiFi Provisioning"
|
||||
default n
|
||||
help
|
||||
启用声波配网功能,使用音频信号传输 WiFi 配置数据
|
||||
|
||||
config AUDIO_DEBUG_UDP_SERVER
|
||||
string "Audio Debug UDP Server Address"
|
||||
default "192.168.2.100:8000"
|
||||
depends on USE_AUDIO_DEBUGGER
|
||||
help
|
||||
UDP服务器地址,格式: IP:PORT,用于接收音频调试数据
|
||||
|
||||
config RECEIVE_CUSTOM_MESSAGE
|
||||
bool "Enable Custom Message Reception"
|
||||
default n
|
||||
help
|
||||
启用接收自定义消息功能,允许设备接收来自服务器的自定义消息(最好通过 MQTT 协议)
|
||||
|
||||
choice I2S_TYPE_TAIJIPI_S3
|
||||
depends on BOARD_TYPE_ESP32S3_Taiji_Pi
|
||||
prompt "taiji-pi-S3 I2S Type"
|
||||
default TAIJIPAI_I2S_TYPE_STD
|
||||
help
|
||||
I2S 类型选择
|
||||
config TAIJIPAI_I2S_TYPE_STD
|
||||
bool "I2S Type STD"
|
||||
config TAIJIPAI_I2S_TYPE_PDM
|
||||
bool "I2S Type PDM"
|
||||
endchoice
|
||||
|
||||
endmenu
|
||||
883
main/application.cc
Normal file
883
main/application.cc
Normal file
@ -0,0 +1,883 @@
|
||||
#include "application.h"
|
||||
#include "board.h"
|
||||
#include "display.h"
|
||||
#include "system_info.h"
|
||||
#include "audio_codec.h"
|
||||
#include "mqtt_protocol.h"
|
||||
#include "websocket_protocol.h"
|
||||
#include "assets/lang_config.h"
|
||||
#include "mcp_server.h"
|
||||
#include "assets.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <esp_log.h>
|
||||
#include <cJSON.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <font_awesome.h>
|
||||
|
||||
#define TAG "Application"
|
||||
|
||||
|
||||
static const char* const STATE_STRINGS[] = {
|
||||
"unknown",
|
||||
"starting",
|
||||
"configuring",
|
||||
"idle",
|
||||
"connecting",
|
||||
"listening",
|
||||
"speaking",
|
||||
"upgrading",
|
||||
"activating",
|
||||
"audio_testing",
|
||||
"fatal_error",
|
||||
"invalid_state"
|
||||
};
|
||||
|
||||
Application::Application() {
|
||||
event_group_ = xEventGroupCreate();
|
||||
|
||||
#if CONFIG_USE_DEVICE_AEC && CONFIG_USE_SERVER_AEC
|
||||
#error "CONFIG_USE_DEVICE_AEC and CONFIG_USE_SERVER_AEC cannot be enabled at the same time"
|
||||
#elif CONFIG_USE_DEVICE_AEC
|
||||
aec_mode_ = kAecOnDeviceSide;
|
||||
#elif CONFIG_USE_SERVER_AEC
|
||||
aec_mode_ = kAecOnServerSide;
|
||||
#else
|
||||
aec_mode_ = kAecOff;
|
||||
#endif
|
||||
|
||||
esp_timer_create_args_t clock_timer_args = {
|
||||
.callback = [](void* arg) {
|
||||
Application* app = (Application*)arg;
|
||||
xEventGroupSetBits(app->event_group_, MAIN_EVENT_CLOCK_TICK);
|
||||
},
|
||||
.arg = this,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "clock_timer",
|
||||
.skip_unhandled_events = true
|
||||
};
|
||||
esp_timer_create(&clock_timer_args, &clock_timer_handle_);
|
||||
}
|
||||
|
||||
Application::~Application() {
|
||||
if (clock_timer_handle_ != nullptr) {
|
||||
esp_timer_stop(clock_timer_handle_);
|
||||
esp_timer_delete(clock_timer_handle_);
|
||||
}
|
||||
vEventGroupDelete(event_group_);
|
||||
}
|
||||
|
||||
void Application::CheckAssetsVersion() {
|
||||
auto& board = Board::GetInstance();
|
||||
auto display = board.GetDisplay();
|
||||
auto assets = board.GetAssets();
|
||||
if (!assets) {
|
||||
ESP_LOGE(TAG, "Assets is not set for board %s", BOARD_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!assets->partition_valid()) {
|
||||
ESP_LOGE(TAG, "Assets partition is not valid for board %s", BOARD_NAME);
|
||||
return;
|
||||
}
|
||||
|
||||
Settings settings("assets", true);
|
||||
// Check if there is a new assets need to be downloaded
|
||||
std::string download_url = settings.GetString("download_url");
|
||||
if (!download_url.empty()) {
|
||||
settings.EraseKey("download_url");
|
||||
}
|
||||
if (download_url.empty() && !assets->checksum_valid()) {
|
||||
download_url = assets->default_assets_url();
|
||||
}
|
||||
|
||||
if (!download_url.empty()) {
|
||||
char message[256];
|
||||
snprintf(message, sizeof(message), Lang::Strings::FOUND_NEW_ASSETS, download_url.c_str());
|
||||
Alert(Lang::Strings::LOADING_ASSETS, message, "cloud_arrow_down", Lang::Sounds::OGG_UPGRADE);
|
||||
|
||||
// Wait for the audio service to be idle for 3 seconds
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
SetDeviceState(kDeviceStateUpgrading);
|
||||
board.SetPowerSaveMode(false);
|
||||
display->SetChatMessage("system", Lang::Strings::PLEASE_WAIT);
|
||||
|
||||
bool success = assets->Download(download_url, [display](int progress, size_t speed) -> void {
|
||||
std::thread([display, progress, speed]() {
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%d%% %uKB/s", progress, speed / 1024);
|
||||
display->SetChatMessage("system", buffer);
|
||||
}).detach();
|
||||
});
|
||||
|
||||
board.SetPowerSaveMode(true);
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
if (!success) {
|
||||
Alert(Lang::Strings::ERROR, Lang::Strings::DOWNLOAD_ASSETS_FAILED, "circle_xmark", Lang::Sounds::OGG_EXCLAMATION);
|
||||
vTaskDelay(pdMS_TO_TICKS(2000));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply assets
|
||||
assets->Apply();
|
||||
display->SetChatMessage("system", "");
|
||||
display->SetEmotion("microchip_ai");
|
||||
}
|
||||
|
||||
void Application::CheckNewVersion(Ota& ota) {
|
||||
const int MAX_RETRY = 10;
|
||||
int retry_count = 0;
|
||||
int retry_delay = 10; // 初始重试延迟为10秒
|
||||
|
||||
auto& board = Board::GetInstance();
|
||||
while (true) {
|
||||
SetDeviceState(kDeviceStateActivating);
|
||||
auto display = board.GetDisplay();
|
||||
display->SetStatus(Lang::Strings::CHECKING_NEW_VERSION);
|
||||
|
||||
if (!ota.CheckVersion()) {
|
||||
retry_count++;
|
||||
if (retry_count >= MAX_RETRY) {
|
||||
ESP_LOGE(TAG, "Too many retries, exit version check");
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[256];
|
||||
snprintf(buffer, sizeof(buffer), Lang::Strings::CHECK_NEW_VERSION_FAILED, retry_delay, ota.GetCheckVersionUrl().c_str());
|
||||
Alert(Lang::Strings::ERROR, buffer, "cloud_slash", Lang::Sounds::OGG_EXCLAMATION);
|
||||
|
||||
ESP_LOGW(TAG, "Check new version failed, retry in %d seconds (%d/%d)", retry_delay, retry_count, MAX_RETRY);
|
||||
for (int i = 0; i < retry_delay; i++) {
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
retry_delay *= 2; // 每次重试后延迟时间翻倍
|
||||
continue;
|
||||
}
|
||||
retry_count = 0;
|
||||
retry_delay = 10; // 重置重试延迟时间
|
||||
|
||||
if (ota.HasNewVersion()) {
|
||||
if (UpgradeFirmware(ota)) {
|
||||
return; // This line will never be reached after reboot
|
||||
}
|
||||
// If upgrade failed, continue to normal operation (don't break, just fall through)
|
||||
}
|
||||
|
||||
// No new version, mark the current version as valid
|
||||
ota.MarkCurrentVersionValid();
|
||||
if (!ota.HasActivationCode() && !ota.HasActivationChallenge()) {
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_CHECK_NEW_VERSION_DONE);
|
||||
// Exit the loop if done checking new version
|
||||
break;
|
||||
}
|
||||
|
||||
display->SetStatus(Lang::Strings::ACTIVATION);
|
||||
// Activation code is shown to the user and waiting for the user to input
|
||||
if (ota.HasActivationCode()) {
|
||||
ShowActivationCode(ota.GetActivationCode(), ota.GetActivationMessage());
|
||||
}
|
||||
|
||||
// This will block the loop until the activation is done or timeout
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
ESP_LOGI(TAG, "Activating... %d/%d", i + 1, 10);
|
||||
esp_err_t err = ota.Activate();
|
||||
if (err == ESP_OK) {
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_CHECK_NEW_VERSION_DONE);
|
||||
break;
|
||||
} else if (err == ESP_ERR_TIMEOUT) {
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
} else {
|
||||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||||
}
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ShowActivationCode(const std::string& code, const std::string& message) {
|
||||
struct digit_sound {
|
||||
char digit;
|
||||
const std::string_view& sound;
|
||||
};
|
||||
static const std::array<digit_sound, 10> digit_sounds{{
|
||||
digit_sound{'0', Lang::Sounds::OGG_0},
|
||||
digit_sound{'1', Lang::Sounds::OGG_1},
|
||||
digit_sound{'2', Lang::Sounds::OGG_2},
|
||||
digit_sound{'3', Lang::Sounds::OGG_3},
|
||||
digit_sound{'4', Lang::Sounds::OGG_4},
|
||||
digit_sound{'5', Lang::Sounds::OGG_5},
|
||||
digit_sound{'6', Lang::Sounds::OGG_6},
|
||||
digit_sound{'7', Lang::Sounds::OGG_7},
|
||||
digit_sound{'8', Lang::Sounds::OGG_8},
|
||||
digit_sound{'9', Lang::Sounds::OGG_9}
|
||||
}};
|
||||
|
||||
// This sentence uses 9KB of SRAM, so we need to wait for it to finish
|
||||
Alert(Lang::Strings::ACTIVATION, message.c_str(), "link", Lang::Sounds::OGG_ACTIVATION);
|
||||
|
||||
for (const auto& digit : code) {
|
||||
auto it = std::find_if(digit_sounds.begin(), digit_sounds.end(),
|
||||
[digit](const digit_sound& ds) { return ds.digit == digit; });
|
||||
if (it != digit_sounds.end()) {
|
||||
audio_service_.PlaySound(it->sound);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Alert(const char* status, const char* message, const char* emotion, const std::string_view& sound) {
|
||||
ESP_LOGW(TAG, "Alert [%s] %s: %s", emotion, status, message);
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
display->SetStatus(status);
|
||||
display->SetEmotion(emotion);
|
||||
display->SetChatMessage("system", message);
|
||||
if (!sound.empty()) {
|
||||
audio_service_.PlaySound(sound);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::DismissAlert() {
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
display->SetStatus(Lang::Strings::STANDBY);
|
||||
display->SetEmotion("neutral");
|
||||
display->SetChatMessage("system", "");
|
||||
}
|
||||
}
|
||||
|
||||
void Application::ToggleChatState() {
|
||||
if (device_state_ == kDeviceStateActivating) {
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
return;
|
||||
} else if (device_state_ == kDeviceStateWifiConfiguring) {
|
||||
audio_service_.EnableAudioTesting(true);
|
||||
SetDeviceState(kDeviceStateAudioTesting);
|
||||
return;
|
||||
} else if (device_state_ == kDeviceStateAudioTesting) {
|
||||
audio_service_.EnableAudioTesting(false);
|
||||
SetDeviceState(kDeviceStateWifiConfiguring);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!protocol_) {
|
||||
ESP_LOGE(TAG, "Protocol not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
Schedule([this]() {
|
||||
if (!protocol_->IsAudioChannelOpened()) {
|
||||
SetDeviceState(kDeviceStateConnecting);
|
||||
if (!protocol_->OpenAudioChannel()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
||||
});
|
||||
} else if (device_state_ == kDeviceStateSpeaking) {
|
||||
Schedule([this]() {
|
||||
AbortSpeaking(kAbortReasonNone);
|
||||
});
|
||||
} else if (device_state_ == kDeviceStateListening) {
|
||||
Schedule([this]() {
|
||||
protocol_->CloseAudioChannel();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Application::StartListening() {
|
||||
if (device_state_ == kDeviceStateActivating) {
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
return;
|
||||
} else if (device_state_ == kDeviceStateWifiConfiguring) {
|
||||
audio_service_.EnableAudioTesting(true);
|
||||
SetDeviceState(kDeviceStateAudioTesting);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!protocol_) {
|
||||
ESP_LOGE(TAG, "Protocol not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
Schedule([this]() {
|
||||
if (!protocol_->IsAudioChannelOpened()) {
|
||||
SetDeviceState(kDeviceStateConnecting);
|
||||
if (!protocol_->OpenAudioChannel()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetListeningMode(kListeningModeManualStop);
|
||||
});
|
||||
} else if (device_state_ == kDeviceStateSpeaking) {
|
||||
Schedule([this]() {
|
||||
AbortSpeaking(kAbortReasonNone);
|
||||
SetListeningMode(kListeningModeManualStop);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Application::StopListening() {
|
||||
if (device_state_ == kDeviceStateAudioTesting) {
|
||||
audio_service_.EnableAudioTesting(false);
|
||||
SetDeviceState(kDeviceStateWifiConfiguring);
|
||||
return;
|
||||
}
|
||||
|
||||
const std::array<int, 3> valid_states = {
|
||||
kDeviceStateListening,
|
||||
kDeviceStateSpeaking,
|
||||
kDeviceStateIdle,
|
||||
};
|
||||
// If not valid, do nothing
|
||||
if (std::find(valid_states.begin(), valid_states.end(), device_state_) == valid_states.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Schedule([this]() {
|
||||
if (device_state_ == kDeviceStateListening) {
|
||||
protocol_->SendStopListening();
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Application::Start() {
|
||||
auto& board = Board::GetInstance();
|
||||
SetDeviceState(kDeviceStateStarting);
|
||||
|
||||
/* Setup the display */
|
||||
auto display = board.GetDisplay();
|
||||
|
||||
/* Setup the audio service */
|
||||
auto codec = board.GetAudioCodec();
|
||||
audio_service_.Initialize(codec);
|
||||
audio_service_.Start();
|
||||
|
||||
AudioServiceCallbacks callbacks;
|
||||
callbacks.on_send_queue_available = [this]() {
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_SEND_AUDIO);
|
||||
};
|
||||
callbacks.on_wake_word_detected = [this](const std::string& wake_word) {
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_WAKE_WORD_DETECTED);
|
||||
};
|
||||
callbacks.on_vad_change = [this](bool speaking) {
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_VAD_CHANGE);
|
||||
};
|
||||
audio_service_.SetCallbacks(callbacks);
|
||||
|
||||
/* Start the clock timer to update the status bar */
|
||||
esp_timer_start_periodic(clock_timer_handle_, 1000000);
|
||||
|
||||
/* Wait for the network to be ready */
|
||||
board.StartNetwork();
|
||||
|
||||
// Update the status bar immediately to show the network state
|
||||
display->UpdateStatusBar(true);
|
||||
|
||||
// Check for new assets version
|
||||
CheckAssetsVersion();
|
||||
|
||||
// Check for new firmware version or get the MQTT broker address
|
||||
Ota ota;
|
||||
CheckNewVersion(ota);
|
||||
|
||||
// Initialize the protocol
|
||||
display->SetStatus(Lang::Strings::LOADING_PROTOCOL);
|
||||
|
||||
// Add MCP common tools before initializing the protocol
|
||||
auto& mcp_server = McpServer::GetInstance();
|
||||
mcp_server.AddCommonTools();
|
||||
mcp_server.AddUserOnlyTools();
|
||||
|
||||
if (ota.HasMqttConfig()) {
|
||||
protocol_ = std::make_unique<MqttProtocol>();
|
||||
} else if (ota.HasWebsocketConfig()) {
|
||||
protocol_ = std::make_unique<WebsocketProtocol>();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No protocol specified in the OTA config, using MQTT");
|
||||
protocol_ = std::make_unique<MqttProtocol>();
|
||||
}
|
||||
|
||||
protocol_->OnConnected([this]() {
|
||||
DismissAlert();
|
||||
});
|
||||
|
||||
protocol_->OnNetworkError([this](const std::string& message) {
|
||||
last_error_message_ = message;
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_ERROR);
|
||||
});
|
||||
protocol_->OnIncomingAudio([this](std::unique_ptr<AudioStreamPacket> packet) {
|
||||
if (device_state_ == kDeviceStateSpeaking) {
|
||||
audio_service_.PushPacketToDecodeQueue(std::move(packet));
|
||||
}
|
||||
});
|
||||
protocol_->OnAudioChannelOpened([this, codec, &board]() {
|
||||
board.SetPowerSaveMode(false);
|
||||
if (protocol_->server_sample_rate() != codec->output_sample_rate()) {
|
||||
ESP_LOGW(TAG, "Server sample rate %d does not match device output sample rate %d, resampling may cause distortion",
|
||||
protocol_->server_sample_rate(), codec->output_sample_rate());
|
||||
}
|
||||
});
|
||||
protocol_->OnAudioChannelClosed([this, &board]() {
|
||||
board.SetPowerSaveMode(true);
|
||||
Schedule([this]() {
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
display->SetChatMessage("system", "");
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
});
|
||||
});
|
||||
protocol_->OnIncomingJson([this, display](const cJSON* root) {
|
||||
// Parse JSON data
|
||||
auto type = cJSON_GetObjectItem(root, "type");
|
||||
if (strcmp(type->valuestring, "tts") == 0) {
|
||||
auto state = cJSON_GetObjectItem(root, "state");
|
||||
if (strcmp(state->valuestring, "start") == 0) {
|
||||
Schedule([this]() {
|
||||
aborted_ = false;
|
||||
if (device_state_ == kDeviceStateIdle || device_state_ == kDeviceStateListening) {
|
||||
SetDeviceState(kDeviceStateSpeaking);
|
||||
}
|
||||
});
|
||||
} else if (strcmp(state->valuestring, "stop") == 0) {
|
||||
Schedule([this]() {
|
||||
if (device_state_ == kDeviceStateSpeaking) {
|
||||
if (listening_mode_ == kListeningModeManualStop) {
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
} else {
|
||||
SetDeviceState(kDeviceStateListening);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (strcmp(state->valuestring, "sentence_start") == 0) {
|
||||
auto text = cJSON_GetObjectItem(root, "text");
|
||||
if (cJSON_IsString(text)) {
|
||||
ESP_LOGI(TAG, "<< %s", text->valuestring);
|
||||
Schedule([this, display, message = std::string(text->valuestring)]() {
|
||||
display->SetChatMessage("assistant", message.c_str());
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (strcmp(type->valuestring, "stt") == 0) {
|
||||
auto text = cJSON_GetObjectItem(root, "text");
|
||||
if (cJSON_IsString(text)) {
|
||||
ESP_LOGI(TAG, ">> %s", text->valuestring);
|
||||
Schedule([this, display, message = std::string(text->valuestring)]() {
|
||||
display->SetChatMessage("user", message.c_str());
|
||||
});
|
||||
}
|
||||
} else if (strcmp(type->valuestring, "llm") == 0) {
|
||||
auto emotion = cJSON_GetObjectItem(root, "emotion");
|
||||
if (cJSON_IsString(emotion)) {
|
||||
Schedule([this, display, emotion_str = std::string(emotion->valuestring)]() {
|
||||
display->SetEmotion(emotion_str.c_str());
|
||||
});
|
||||
}
|
||||
} else if (strcmp(type->valuestring, "mcp") == 0) {
|
||||
auto payload = cJSON_GetObjectItem(root, "payload");
|
||||
if (cJSON_IsObject(payload)) {
|
||||
McpServer::GetInstance().ParseMessage(payload);
|
||||
}
|
||||
} else if (strcmp(type->valuestring, "system") == 0) {
|
||||
auto command = cJSON_GetObjectItem(root, "command");
|
||||
if (cJSON_IsString(command)) {
|
||||
ESP_LOGI(TAG, "System command: %s", command->valuestring);
|
||||
if (strcmp(command->valuestring, "reboot") == 0) {
|
||||
// Do a reboot if user requests a OTA update
|
||||
Schedule([this]() {
|
||||
Reboot();
|
||||
});
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown system command: %s", command->valuestring);
|
||||
}
|
||||
}
|
||||
} else if (strcmp(type->valuestring, "alert") == 0) {
|
||||
auto status = cJSON_GetObjectItem(root, "status");
|
||||
auto message = cJSON_GetObjectItem(root, "message");
|
||||
auto emotion = cJSON_GetObjectItem(root, "emotion");
|
||||
if (cJSON_IsString(status) && cJSON_IsString(message) && cJSON_IsString(emotion)) {
|
||||
Alert(status->valuestring, message->valuestring, emotion->valuestring, Lang::Sounds::OGG_VIBRATION);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Alert command requires status, message and emotion");
|
||||
}
|
||||
#if CONFIG_RECEIVE_CUSTOM_MESSAGE
|
||||
} else if (strcmp(type->valuestring, "custom") == 0) {
|
||||
auto payload = cJSON_GetObjectItem(root, "payload");
|
||||
ESP_LOGI(TAG, "Received custom message: %s", cJSON_PrintUnformatted(root));
|
||||
if (cJSON_IsObject(payload)) {
|
||||
Schedule([this, display, payload_str = std::string(cJSON_PrintUnformatted(payload))]() {
|
||||
display->SetChatMessage("system", payload_str.c_str());
|
||||
});
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Invalid custom message format: missing payload");
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown message type: %s", type->valuestring);
|
||||
}
|
||||
});
|
||||
bool protocol_started = protocol_->Start();
|
||||
|
||||
SystemInfo::PrintHeapStats();
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
|
||||
has_server_time_ = ota.HasServerTime();
|
||||
if (protocol_started) {
|
||||
std::string message = std::string(Lang::Strings::VERSION) + ota.GetCurrentVersion();
|
||||
display->ShowNotification(message.c_str());
|
||||
display->SetChatMessage("system", "");
|
||||
// Play the success sound to indicate the device is ready
|
||||
audio_service_.PlaySound(Lang::Sounds::OGG_SUCCESS);
|
||||
}
|
||||
|
||||
// Start the main event loop task with priority 3
|
||||
xTaskCreate([](void* arg) {
|
||||
((Application*)arg)->MainEventLoop();
|
||||
vTaskDelete(NULL);
|
||||
}, "main_event_loop", 2048 * 4, this, 3, &main_event_loop_task_handle_);
|
||||
}
|
||||
|
||||
// Add a async task to MainLoop
|
||||
void Application::Schedule(std::function<void()> callback) {
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
main_tasks_.push_back(std::move(callback));
|
||||
}
|
||||
xEventGroupSetBits(event_group_, MAIN_EVENT_SCHEDULE);
|
||||
}
|
||||
|
||||
// The Main Event Loop controls the chat state and websocket connection
|
||||
// If other tasks need to access the websocket or chat state,
|
||||
// they should use Schedule to call this function
|
||||
void Application::MainEventLoop() {
|
||||
while (true) {
|
||||
auto bits = xEventGroupWaitBits(event_group_, MAIN_EVENT_SCHEDULE |
|
||||
MAIN_EVENT_SEND_AUDIO |
|
||||
MAIN_EVENT_WAKE_WORD_DETECTED |
|
||||
MAIN_EVENT_VAD_CHANGE |
|
||||
MAIN_EVENT_CLOCK_TICK |
|
||||
MAIN_EVENT_ERROR, pdTRUE, pdFALSE, portMAX_DELAY);
|
||||
|
||||
if (bits & MAIN_EVENT_ERROR) {
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
Alert(Lang::Strings::ERROR, last_error_message_.c_str(), "circle_xmark", Lang::Sounds::OGG_EXCLAMATION);
|
||||
}
|
||||
|
||||
if (bits & MAIN_EVENT_SEND_AUDIO) {
|
||||
while (auto packet = audio_service_.PopPacketFromSendQueue()) {
|
||||
if (protocol_ && !protocol_->SendAudio(std::move(packet))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & MAIN_EVENT_WAKE_WORD_DETECTED) {
|
||||
OnWakeWordDetected();
|
||||
}
|
||||
|
||||
if (bits & MAIN_EVENT_VAD_CHANGE) {
|
||||
if (device_state_ == kDeviceStateListening) {
|
||||
auto led = Board::GetInstance().GetLed();
|
||||
led->OnStateChanged();
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & MAIN_EVENT_SCHEDULE) {
|
||||
std::unique_lock<std::mutex> lock(mutex_);
|
||||
auto tasks = std::move(main_tasks_);
|
||||
lock.unlock();
|
||||
for (auto& task : tasks) {
|
||||
task();
|
||||
}
|
||||
}
|
||||
|
||||
if (bits & MAIN_EVENT_CLOCK_TICK) {
|
||||
clock_ticks_++;
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
display->UpdateStatusBar();
|
||||
|
||||
// Print the debug info every 10 seconds
|
||||
if (clock_ticks_ % 10 == 0) {
|
||||
// SystemInfo::PrintTaskCpuUsage(pdMS_TO_TICKS(1000));
|
||||
// SystemInfo::PrintTaskList();
|
||||
SystemInfo::PrintHeapStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Application::OnWakeWordDetected() {
|
||||
if (!protocol_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
audio_service_.EncodeWakeWord();
|
||||
|
||||
if (!protocol_->IsAudioChannelOpened()) {
|
||||
SetDeviceState(kDeviceStateConnecting);
|
||||
if (!protocol_->OpenAudioChannel()) {
|
||||
audio_service_.EnableWakeWordDetection(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
auto wake_word = audio_service_.GetLastWakeWord();
|
||||
ESP_LOGI(TAG, "Wake word detected: %s", wake_word.c_str());
|
||||
#if CONFIG_USE_AFE_WAKE_WORD || CONFIG_USE_CUSTOM_WAKE_WORD
|
||||
// Encode and send the wake word data to the server
|
||||
while (auto packet = audio_service_.PopWakeWordPacket()) {
|
||||
protocol_->SendAudio(std::move(packet));
|
||||
}
|
||||
// Set the chat state to wake word detected
|
||||
protocol_->SendWakeWordDetected(wake_word);
|
||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
||||
#else
|
||||
SetListeningMode(aec_mode_ == kAecOff ? kListeningModeAutoStop : kListeningModeRealtime);
|
||||
// Play the pop up sound to indicate the wake word is detected
|
||||
audio_service_.PlaySound(Lang::Sounds::OGG_POPUP);
|
||||
#endif
|
||||
} else if (device_state_ == kDeviceStateSpeaking) {
|
||||
AbortSpeaking(kAbortReasonWakeWordDetected);
|
||||
} else if (device_state_ == kDeviceStateActivating) {
|
||||
SetDeviceState(kDeviceStateIdle);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::AbortSpeaking(AbortReason reason) {
|
||||
ESP_LOGI(TAG, "Abort speaking");
|
||||
aborted_ = true;
|
||||
if (protocol_) {
|
||||
protocol_->SendAbortSpeaking(reason);
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SetListeningMode(ListeningMode mode) {
|
||||
listening_mode_ = mode;
|
||||
SetDeviceState(kDeviceStateListening);
|
||||
}
|
||||
|
||||
void Application::SetDeviceState(DeviceState state) {
|
||||
if (device_state_ == state) {
|
||||
return;
|
||||
}
|
||||
|
||||
clock_ticks_ = 0;
|
||||
auto previous_state = device_state_;
|
||||
device_state_ = state;
|
||||
ESP_LOGI(TAG, "STATE: %s", STATE_STRINGS[device_state_]);
|
||||
|
||||
// Send the state change event
|
||||
DeviceStateEventManager::GetInstance().PostStateChangeEvent(previous_state, state);
|
||||
|
||||
auto& board = Board::GetInstance();
|
||||
auto display = board.GetDisplay();
|
||||
auto led = board.GetLed();
|
||||
led->OnStateChanged();
|
||||
switch (state) {
|
||||
case kDeviceStateUnknown:
|
||||
case kDeviceStateIdle:
|
||||
display->SetStatus(Lang::Strings::STANDBY);
|
||||
display->SetEmotion("neutral");
|
||||
audio_service_.EnableVoiceProcessing(false);
|
||||
audio_service_.EnableWakeWordDetection(true);
|
||||
break;
|
||||
case kDeviceStateConnecting:
|
||||
display->SetStatus(Lang::Strings::CONNECTING);
|
||||
display->SetEmotion("neutral");
|
||||
display->SetChatMessage("system", "");
|
||||
break;
|
||||
case kDeviceStateListening:
|
||||
display->SetStatus(Lang::Strings::LISTENING);
|
||||
display->SetEmotion("neutral");
|
||||
|
||||
// Make sure the audio processor is running
|
||||
if (!audio_service_.IsAudioProcessorRunning()) {
|
||||
// Send the start listening command
|
||||
protocol_->SendStartListening(listening_mode_);
|
||||
audio_service_.EnableVoiceProcessing(true);
|
||||
audio_service_.EnableWakeWordDetection(false);
|
||||
}
|
||||
break;
|
||||
case kDeviceStateSpeaking:
|
||||
display->SetStatus(Lang::Strings::SPEAKING);
|
||||
|
||||
if (listening_mode_ != kListeningModeRealtime) {
|
||||
audio_service_.EnableVoiceProcessing(false);
|
||||
// Only AFE wake word can be detected in speaking mode
|
||||
#if CONFIG_USE_AFE_WAKE_WORD
|
||||
audio_service_.EnableWakeWordDetection(true);
|
||||
#else
|
||||
audio_service_.EnableWakeWordDetection(false);
|
||||
#endif
|
||||
}
|
||||
audio_service_.ResetDecoder();
|
||||
break;
|
||||
default:
|
||||
// Do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::Reboot() {
|
||||
ESP_LOGI(TAG, "Rebooting...");
|
||||
// Disconnect the audio channel
|
||||
if (protocol_ && protocol_->IsAudioChannelOpened()) {
|
||||
protocol_->CloseAudioChannel();
|
||||
}
|
||||
protocol_.reset();
|
||||
audio_service_.Stop();
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
bool Application::UpgradeFirmware(Ota& ota, const std::string& url) {
|
||||
auto& board = Board::GetInstance();
|
||||
auto display = board.GetDisplay();
|
||||
|
||||
// Use provided URL or get from OTA object
|
||||
std::string upgrade_url = url.empty() ? ota.GetFirmwareUrl() : url;
|
||||
std::string version_info = url.empty() ? ota.GetFirmwareVersion() : "(Manual upgrade)";
|
||||
|
||||
// Close audio channel if it's open
|
||||
if (protocol_ && protocol_->IsAudioChannelOpened()) {
|
||||
ESP_LOGI(TAG, "Closing audio channel before firmware upgrade");
|
||||
protocol_->CloseAudioChannel();
|
||||
}
|
||||
ESP_LOGI(TAG, "Starting firmware upgrade from URL: %s", upgrade_url.c_str());
|
||||
|
||||
Alert(Lang::Strings::OTA_UPGRADE, Lang::Strings::UPGRADING, "download", Lang::Sounds::OGG_UPGRADE);
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
|
||||
SetDeviceState(kDeviceStateUpgrading);
|
||||
|
||||
std::string message = std::string(Lang::Strings::NEW_VERSION) + version_info;
|
||||
display->SetChatMessage("system", message.c_str());
|
||||
|
||||
board.SetPowerSaveMode(false);
|
||||
audio_service_.Stop();
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
|
||||
bool upgrade_success = ota.StartUpgradeFromUrl(upgrade_url, [display](int progress, size_t speed) {
|
||||
std::thread([display, progress, speed]() {
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%d%% %uKB/s", progress, speed / 1024);
|
||||
display->SetChatMessage("system", buffer);
|
||||
}).detach();
|
||||
});
|
||||
|
||||
if (!upgrade_success) {
|
||||
// Upgrade failed, restart audio service and continue running
|
||||
ESP_LOGE(TAG, "Firmware upgrade failed, restarting audio service and continuing operation...");
|
||||
audio_service_.Start(); // Restart audio service
|
||||
board.SetPowerSaveMode(true); // Restore power save mode
|
||||
Alert(Lang::Strings::ERROR, Lang::Strings::UPGRADE_FAILED, "circle_xmark", Lang::Sounds::OGG_EXCLAMATION);
|
||||
vTaskDelay(pdMS_TO_TICKS(3000));
|
||||
return false;
|
||||
} else {
|
||||
// Upgrade success, reboot immediately
|
||||
ESP_LOGI(TAG, "Firmware upgrade successful, rebooting...");
|
||||
display->SetChatMessage("system", "Upgrade successful, rebooting...");
|
||||
vTaskDelay(pdMS_TO_TICKS(1000)); // Brief pause to show message
|
||||
Reboot();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void Application::WakeWordInvoke(const std::string& wake_word) {
|
||||
if (device_state_ == kDeviceStateIdle) {
|
||||
ToggleChatState();
|
||||
Schedule([this, wake_word]() {
|
||||
if (protocol_) {
|
||||
protocol_->SendWakeWordDetected(wake_word);
|
||||
}
|
||||
});
|
||||
} else if (device_state_ == kDeviceStateSpeaking) {
|
||||
Schedule([this]() {
|
||||
AbortSpeaking(kAbortReasonNone);
|
||||
});
|
||||
} else if (device_state_ == kDeviceStateListening) {
|
||||
Schedule([this]() {
|
||||
if (protocol_) {
|
||||
protocol_->CloseAudioChannel();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool Application::CanEnterSleepMode() {
|
||||
if (device_state_ != kDeviceStateIdle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (protocol_ && protocol_->IsAudioChannelOpened()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!audio_service_.IsIdle()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now it is safe to enter sleep mode
|
||||
return true;
|
||||
}
|
||||
|
||||
void Application::SendMcpMessage(const std::string& payload) {
|
||||
if (protocol_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure you are using main thread to send MCP message
|
||||
if (xTaskGetCurrentTaskHandle() == main_event_loop_task_handle_) {
|
||||
ESP_LOGI(TAG, "Send MCP message in main thread");
|
||||
protocol_->SendMcpMessage(payload);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Send MCP message in sub thread");
|
||||
Schedule([this, payload = std::move(payload)]() {
|
||||
protocol_->SendMcpMessage(payload);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Application::SetAecMode(AecMode mode) {
|
||||
aec_mode_ = mode;
|
||||
Schedule([this]() {
|
||||
auto& board = Board::GetInstance();
|
||||
auto display = board.GetDisplay();
|
||||
switch (aec_mode_) {
|
||||
case kAecOff:
|
||||
audio_service_.EnableDeviceAec(false);
|
||||
display->ShowNotification(Lang::Strings::RTC_MODE_OFF);
|
||||
break;
|
||||
case kAecOnServerSide:
|
||||
audio_service_.EnableDeviceAec(false);
|
||||
display->ShowNotification(Lang::Strings::RTC_MODE_ON);
|
||||
break;
|
||||
case kAecOnDeviceSide:
|
||||
audio_service_.EnableDeviceAec(true);
|
||||
display->ShowNotification(Lang::Strings::RTC_MODE_ON);
|
||||
break;
|
||||
}
|
||||
|
||||
// If the AEC mode is changed, close the audio channel
|
||||
if (protocol_ && protocol_->IsAudioChannelOpened()) {
|
||||
protocol_->CloseAudioChannel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Application::PlaySound(const std::string_view& sound) {
|
||||
audio_service_.PlaySound(sound);
|
||||
}
|
||||
110
main/application.h
Normal file
110
main/application.h
Normal file
@ -0,0 +1,110 @@
|
||||
#ifndef _APPLICATION_H_
|
||||
#define _APPLICATION_H_
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/event_groups.h>
|
||||
#include <freertos/task.h>
|
||||
#include <esp_timer.h>
|
||||
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
|
||||
#include "protocol.h"
|
||||
#include "ota.h"
|
||||
#include "audio_service.h"
|
||||
#include "device_state_event.h"
|
||||
|
||||
|
||||
#define MAIN_EVENT_SCHEDULE (1 << 0)
|
||||
#define MAIN_EVENT_SEND_AUDIO (1 << 1)
|
||||
#define MAIN_EVENT_WAKE_WORD_DETECTED (1 << 2)
|
||||
#define MAIN_EVENT_VAD_CHANGE (1 << 3)
|
||||
#define MAIN_EVENT_ERROR (1 << 4)
|
||||
#define MAIN_EVENT_CHECK_NEW_VERSION_DONE (1 << 5)
|
||||
#define MAIN_EVENT_CLOCK_TICK (1 << 6)
|
||||
|
||||
|
||||
enum AecMode {
|
||||
kAecOff,
|
||||
kAecOnDeviceSide,
|
||||
kAecOnServerSide,
|
||||
};
|
||||
|
||||
class Application {
|
||||
public:
|
||||
static Application& GetInstance() {
|
||||
static Application instance;
|
||||
return instance;
|
||||
}
|
||||
// 删除拷贝构造函数和赋值运算符
|
||||
Application(const Application&) = delete;
|
||||
Application& operator=(const Application&) = delete;
|
||||
|
||||
void Start();
|
||||
void MainEventLoop();
|
||||
DeviceState GetDeviceState() const { return device_state_; }
|
||||
bool IsVoiceDetected() const { return audio_service_.IsVoiceDetected(); }
|
||||
void Schedule(std::function<void()> callback);
|
||||
void SetDeviceState(DeviceState state);
|
||||
void Alert(const char* status, const char* message, const char* emotion = "", const std::string_view& sound = "");
|
||||
void DismissAlert();
|
||||
void AbortSpeaking(AbortReason reason);
|
||||
void ToggleChatState();
|
||||
void StartListening();
|
||||
void StopListening();
|
||||
void Reboot();
|
||||
void WakeWordInvoke(const std::string& wake_word);
|
||||
bool UpgradeFirmware(Ota& ota, const std::string& url = "");
|
||||
bool CanEnterSleepMode();
|
||||
void SendMcpMessage(const std::string& payload);
|
||||
void SetAecMode(AecMode mode);
|
||||
AecMode GetAecMode() const { return aec_mode_; }
|
||||
void PlaySound(const std::string_view& sound);
|
||||
AudioService& GetAudioService() { return audio_service_; }
|
||||
|
||||
private:
|
||||
Application();
|
||||
~Application();
|
||||
|
||||
std::mutex mutex_;
|
||||
std::deque<std::function<void()>> main_tasks_;
|
||||
std::unique_ptr<Protocol> protocol_;
|
||||
EventGroupHandle_t event_group_ = nullptr;
|
||||
esp_timer_handle_t clock_timer_handle_ = nullptr;
|
||||
volatile DeviceState device_state_ = kDeviceStateUnknown;
|
||||
ListeningMode listening_mode_ = kListeningModeAutoStop;
|
||||
AecMode aec_mode_ = kAecOff;
|
||||
std::string last_error_message_;
|
||||
AudioService audio_service_;
|
||||
|
||||
bool has_server_time_ = false;
|
||||
bool aborted_ = false;
|
||||
int clock_ticks_ = 0;
|
||||
TaskHandle_t check_new_version_task_handle_ = nullptr;
|
||||
TaskHandle_t main_event_loop_task_handle_ = nullptr;
|
||||
|
||||
void OnWakeWordDetected();
|
||||
void CheckNewVersion(Ota& ota);
|
||||
void CheckAssetsVersion();
|
||||
void ShowActivationCode(const std::string& code, const std::string& message);
|
||||
void SetListeningMode(ListeningMode mode);
|
||||
};
|
||||
|
||||
|
||||
class TaskPriorityReset {
|
||||
public:
|
||||
TaskPriorityReset(BaseType_t priority) {
|
||||
original_priority_ = uxTaskPriorityGet(NULL);
|
||||
vTaskPrioritySet(NULL, priority);
|
||||
}
|
||||
~TaskPriorityReset() {
|
||||
vTaskPrioritySet(NULL, original_priority_);
|
||||
}
|
||||
|
||||
private:
|
||||
BaseType_t original_priority_;
|
||||
};
|
||||
|
||||
#endif // _APPLICATION_H_
|
||||
406
main/assets.cc
Normal file
406
main/assets.cc
Normal file
@ -0,0 +1,406 @@
|
||||
#include "assets.h"
|
||||
#include "board.h"
|
||||
#include "display.h"
|
||||
#include "application.h"
|
||||
#include "lvgl_theme.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <spi_flash_mmap.h>
|
||||
#include <esp_timer.h>
|
||||
#include <cbin_font.h>
|
||||
|
||||
|
||||
#define TAG "Assets"
|
||||
|
||||
struct mmap_assets_table {
|
||||
char asset_name[32]; /*!< Name of the asset */
|
||||
uint32_t asset_size; /*!< Size of the asset */
|
||||
uint32_t asset_offset; /*!< Offset of the asset */
|
||||
uint16_t asset_width; /*!< Width of the asset */
|
||||
uint16_t asset_height; /*!< Height of the asset */
|
||||
};
|
||||
|
||||
|
||||
Assets::Assets(std::string default_assets_url) {
|
||||
if (default_assets_url.find("http") == 0) {
|
||||
default_assets_url_ = default_assets_url;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "The default assets url is not a http url: %s", default_assets_url.c_str());
|
||||
}
|
||||
|
||||
// Initialize the partition
|
||||
InitializePartition();
|
||||
}
|
||||
|
||||
Assets::~Assets() {
|
||||
if (mmap_handle_ != 0) {
|
||||
esp_partition_munmap(mmap_handle_);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Assets::CalculateChecksum(const char* data, uint32_t length) {
|
||||
uint32_t checksum = 0;
|
||||
for (uint32_t i = 0; i < length; i++) {
|
||||
checksum += data[i];
|
||||
}
|
||||
return checksum & 0xFFFF;
|
||||
}
|
||||
|
||||
bool Assets::InitializePartition() {
|
||||
partition_valid_ = false;
|
||||
checksum_valid_ = false;
|
||||
assets_.clear();
|
||||
|
||||
partition_ = esp_partition_find_first(ESP_PARTITION_TYPE_ANY, ESP_PARTITION_SUBTYPE_ANY, "assets");
|
||||
if (partition_ == nullptr) {
|
||||
ESP_LOGI(TAG, "No assets partition found");
|
||||
return false;
|
||||
}
|
||||
|
||||
int free_pages = spi_flash_mmap_get_free_pages(SPI_FLASH_MMAP_DATA);
|
||||
uint32_t storage_size = free_pages * 64 * 1024;
|
||||
ESP_LOGI(TAG, "The storage free size is %ld KB", storage_size / 1024);
|
||||
ESP_LOGI(TAG, "The partition size is %ld KB", partition_->size / 1024);
|
||||
if (storage_size < partition_->size) {
|
||||
ESP_LOGE(TAG, "The free size %ld KB is less than assets partition required %ld KB", storage_size / 1024, partition_->size / 1024);
|
||||
return false;
|
||||
}
|
||||
|
||||
esp_err_t err = esp_partition_mmap(partition_, 0, partition_->size, ESP_PARTITION_MMAP_DATA, (const void**)&mmap_root_, &mmap_handle_);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to mmap assets partition: %s", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
partition_valid_ = true;
|
||||
|
||||
uint32_t stored_files = *(uint32_t*)(mmap_root_ + 0);
|
||||
uint32_t stored_chksum = *(uint32_t*)(mmap_root_ + 4);
|
||||
uint32_t stored_len = *(uint32_t*)(mmap_root_ + 8);
|
||||
|
||||
if (stored_len > partition_->size - 12) {
|
||||
ESP_LOGD(TAG, "The stored_len (0x%lx) is greater than the partition size (0x%lx) - 12", stored_len, partition_->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto start_time = esp_timer_get_time();
|
||||
uint32_t calculated_checksum = CalculateChecksum(mmap_root_ + 12, stored_len);
|
||||
auto end_time = esp_timer_get_time();
|
||||
ESP_LOGI(TAG, "The checksum calculation time is %d ms", int((end_time - start_time) / 1000));
|
||||
|
||||
if (calculated_checksum != stored_chksum) {
|
||||
ESP_LOGE(TAG, "The calculated checksum (0x%lx) does not match the stored checksum (0x%lx)", calculated_checksum, stored_chksum);
|
||||
return false;
|
||||
}
|
||||
|
||||
checksum_valid_ = true;
|
||||
|
||||
for (uint32_t i = 0; i < stored_files; i++) {
|
||||
auto item = (const mmap_assets_table*)(mmap_root_ + 12 + i * sizeof(mmap_assets_table));
|
||||
auto asset = Asset{
|
||||
.size = static_cast<size_t>(item->asset_size),
|
||||
.offset = static_cast<size_t>(12 + sizeof(mmap_assets_table) * stored_files + item->asset_offset)
|
||||
};
|
||||
assets_[item->asset_name] = asset;
|
||||
}
|
||||
return checksum_valid_;
|
||||
}
|
||||
|
||||
bool Assets::Apply() {
|
||||
void* ptr = nullptr;
|
||||
size_t size = 0;
|
||||
if (!GetAssetData("index.json", ptr, size)) {
|
||||
ESP_LOGE(TAG, "The index.json file is not found");
|
||||
return false;
|
||||
}
|
||||
cJSON* root = cJSON_ParseWithLength(static_cast<char*>(ptr), size);
|
||||
if (root == nullptr) {
|
||||
ESP_LOGE(TAG, "The index.json file is not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* version = cJSON_GetObjectItem(root, "version");
|
||||
if (cJSON_IsNumber(version)) {
|
||||
if (version->valuedouble > 1) {
|
||||
ESP_LOGE(TAG, "The assets version %d is not supported, please upgrade the firmware", version->valueint);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* srmodels = cJSON_GetObjectItem(root, "srmodels");
|
||||
if (cJSON_IsString(srmodels)) {
|
||||
std::string srmodels_file = srmodels->valuestring;
|
||||
if (GetAssetData(srmodels_file, ptr, size)) {
|
||||
if (models_list_ != nullptr) {
|
||||
esp_srmodel_deinit(models_list_);
|
||||
models_list_ = nullptr;
|
||||
}
|
||||
models_list_ = srmodel_load(static_cast<uint8_t*>(ptr));
|
||||
if (models_list_ != nullptr) {
|
||||
auto& app = Application::GetInstance();
|
||||
app.GetAudioService().SetModelsList(models_list_);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Failed to load srmodels.bin");
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "The srmodels file %s is not found", srmodels_file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef HAVE_LVGL
|
||||
auto& theme_manager = LvglThemeManager::GetInstance();
|
||||
auto light_theme = theme_manager.GetTheme("light");
|
||||
auto dark_theme = theme_manager.GetTheme("dark");
|
||||
|
||||
cJSON* font = cJSON_GetObjectItem(root, "text_font");
|
||||
if (cJSON_IsString(font)) {
|
||||
std::string fonts_text_file = font->valuestring;
|
||||
if (GetAssetData(fonts_text_file, ptr, size)) {
|
||||
auto text_font = std::make_shared<LvglCBinFont>(ptr);
|
||||
if (text_font->font() == nullptr) {
|
||||
ESP_LOGE(TAG, "Failed to load fonts.bin");
|
||||
return false;
|
||||
}
|
||||
if (light_theme != nullptr) {
|
||||
light_theme->set_text_font(text_font);
|
||||
}
|
||||
if (dark_theme != nullptr) {
|
||||
dark_theme->set_text_font(text_font);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "The font file %s is not found", fonts_text_file.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* emoji_collection = cJSON_GetObjectItem(root, "emoji_collection");
|
||||
if (cJSON_IsArray(emoji_collection)) {
|
||||
auto custom_emoji_collection = std::make_shared<EmojiCollection>();
|
||||
int emoji_count = cJSON_GetArraySize(emoji_collection);
|
||||
for (int i = 0; i < emoji_count; i++) {
|
||||
cJSON* emoji = cJSON_GetArrayItem(emoji_collection, i);
|
||||
if (cJSON_IsObject(emoji)) {
|
||||
cJSON* name = cJSON_GetObjectItem(emoji, "name");
|
||||
cJSON* file = cJSON_GetObjectItem(emoji, "file");
|
||||
if (cJSON_IsString(name) && cJSON_IsString(file)) {
|
||||
if (!GetAssetData(file->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "Emoji %s image file %s is not found", name->valuestring, file->valuestring);
|
||||
continue;
|
||||
}
|
||||
custom_emoji_collection->AddEmoji(name->valuestring, new LvglRawImage(ptr, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (light_theme != nullptr) {
|
||||
light_theme->set_emoji_collection(custom_emoji_collection);
|
||||
}
|
||||
if (dark_theme != nullptr) {
|
||||
dark_theme->set_emoji_collection(custom_emoji_collection);
|
||||
}
|
||||
}
|
||||
|
||||
cJSON* skin = cJSON_GetObjectItem(root, "skin");
|
||||
if (cJSON_IsObject(skin)) {
|
||||
cJSON* light_skin = cJSON_GetObjectItem(skin, "light");
|
||||
if (cJSON_IsObject(light_skin) && light_theme != nullptr) {
|
||||
cJSON* text_color = cJSON_GetObjectItem(light_skin, "text_color");
|
||||
cJSON* background_color = cJSON_GetObjectItem(light_skin, "background_color");
|
||||
cJSON* background_image = cJSON_GetObjectItem(light_skin, "background_image");
|
||||
if (cJSON_IsString(text_color)) {
|
||||
light_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_color)) {
|
||||
light_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
light_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_image)) {
|
||||
if (!GetAssetData(background_image->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring);
|
||||
return false;
|
||||
}
|
||||
auto background_image = std::make_shared<LvglCBinImage>(ptr);
|
||||
light_theme->set_background_image(background_image);
|
||||
}
|
||||
}
|
||||
cJSON* dark_skin = cJSON_GetObjectItem(skin, "dark");
|
||||
if (cJSON_IsObject(dark_skin) && dark_theme != nullptr) {
|
||||
cJSON* text_color = cJSON_GetObjectItem(dark_skin, "text_color");
|
||||
cJSON* background_color = cJSON_GetObjectItem(dark_skin, "background_color");
|
||||
cJSON* background_image = cJSON_GetObjectItem(dark_skin, "background_image");
|
||||
if (cJSON_IsString(text_color)) {
|
||||
dark_theme->set_text_color(LvglTheme::ParseColor(text_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_color)) {
|
||||
dark_theme->set_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
dark_theme->set_chat_background_color(LvglTheme::ParseColor(background_color->valuestring));
|
||||
}
|
||||
if (cJSON_IsString(background_image)) {
|
||||
if (!GetAssetData(background_image->valuestring, ptr, size)) {
|
||||
ESP_LOGE(TAG, "The background image file %s is not found", background_image->valuestring);
|
||||
return false;
|
||||
}
|
||||
auto background_image = std::make_shared<LvglCBinImage>(ptr);
|
||||
dark_theme->set_background_image(background_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
auto display = Board::GetInstance().GetDisplay();
|
||||
ESP_LOGI(TAG, "Refreshing display theme...");
|
||||
|
||||
auto current_theme = display->GetTheme();
|
||||
if (current_theme != nullptr) {
|
||||
display->SetTheme(current_theme);
|
||||
}
|
||||
cJSON_Delete(root);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Assets::Download(std::string url, std::function<void(int progress, size_t speed)> progress_callback) {
|
||||
ESP_LOGI(TAG, "Downloading new version of assets from %s", url.c_str());
|
||||
|
||||
// 取消当前资源分区的内存映射
|
||||
if (mmap_handle_ != 0) {
|
||||
esp_partition_munmap(mmap_handle_);
|
||||
mmap_handle_ = 0;
|
||||
mmap_root_ = nullptr;
|
||||
}
|
||||
checksum_valid_ = false;
|
||||
assets_.clear();
|
||||
|
||||
// 下载新的资源文件
|
||||
auto network = Board::GetInstance().GetNetwork();
|
||||
auto http = network->CreateHttp(0);
|
||||
|
||||
if (!http->Open("GET", url)) {
|
||||
ESP_LOGE(TAG, "Failed to open HTTP connection");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (http->GetStatusCode() != 200) {
|
||||
ESP_LOGE(TAG, "Failed to get assets, status code: %d", http->GetStatusCode());
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t content_length = http->GetBodyLength();
|
||||
if (content_length == 0) {
|
||||
ESP_LOGE(TAG, "Failed to get content length");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (content_length > partition_->size) {
|
||||
ESP_LOGE(TAG, "Assets file size (%u) is larger than partition size (%lu)", content_length, partition_->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 定义扇区大小为4KB(ESP32的标准扇区大小)
|
||||
const size_t SECTOR_SIZE = esp_partition_get_main_flash_sector_size();
|
||||
|
||||
// 计算需要擦除的扇区数量
|
||||
size_t sectors_to_erase = (content_length + SECTOR_SIZE - 1) / SECTOR_SIZE; // 向上取整
|
||||
size_t total_erase_size = sectors_to_erase * SECTOR_SIZE;
|
||||
|
||||
ESP_LOGI(TAG, "Sector size: %u, content length: %u, sectors to erase: %u, total erase size: %u",
|
||||
SECTOR_SIZE, content_length, sectors_to_erase, total_erase_size);
|
||||
|
||||
// 写入新的资源文件到分区,一边erase一边写入
|
||||
char buffer[512];
|
||||
size_t total_written = 0;
|
||||
size_t recent_written = 0;
|
||||
size_t current_sector = 0;
|
||||
auto last_calc_time = esp_timer_get_time();
|
||||
|
||||
while (true) {
|
||||
int ret = http->Read(buffer, sizeof(buffer));
|
||||
if (ret < 0) {
|
||||
ESP_LOGE(TAG, "Failed to read HTTP data: %s", esp_err_to_name(ret));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
|
||||
// 检查是否需要擦除新的扇区
|
||||
size_t write_end_offset = total_written + ret;
|
||||
size_t needed_sectors = (write_end_offset + SECTOR_SIZE - 1) / SECTOR_SIZE;
|
||||
|
||||
// 擦除需要的新扇区
|
||||
while (current_sector < needed_sectors) {
|
||||
size_t sector_start = current_sector * SECTOR_SIZE;
|
||||
size_t sector_end = (current_sector + 1) * SECTOR_SIZE;
|
||||
|
||||
// 确保擦除范围不超过分区大小
|
||||
if (sector_end > partition_->size) {
|
||||
ESP_LOGE(TAG, "Sector end (%u) exceeds partition size (%lu)", sector_end, partition_->size);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Erasing sector %u (offset: %u, size: %u)", current_sector, sector_start, SECTOR_SIZE);
|
||||
esp_err_t err = esp_partition_erase_range(partition_, sector_start, SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to erase sector %u at offset %u: %s", current_sector, sector_start, esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
current_sector++;
|
||||
}
|
||||
|
||||
// 写入数据到分区
|
||||
esp_err_t err = esp_partition_write(partition_, total_written, buffer, ret);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to write to assets partition at offset %u: %s", total_written, esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
total_written += ret;
|
||||
recent_written += ret;
|
||||
|
||||
// 计算进度和速度
|
||||
if (esp_timer_get_time() - last_calc_time >= 1000000 || total_written == content_length || ret == 0) {
|
||||
size_t progress = total_written * 100 / content_length;
|
||||
size_t speed = recent_written; // 每秒的字节数
|
||||
ESP_LOGI(TAG, "Progress: %u%% (%u/%u), Speed: %u B/s, Sectors erased: %u",
|
||||
progress, total_written, content_length, speed, current_sector);
|
||||
if (progress_callback) {
|
||||
progress_callback(progress, speed);
|
||||
}
|
||||
last_calc_time = esp_timer_get_time();
|
||||
recent_written = 0; // 重置最近写入的字节数
|
||||
}
|
||||
}
|
||||
|
||||
http->Close();
|
||||
|
||||
if (total_written != content_length) {
|
||||
ESP_LOGE(TAG, "Downloaded size (%u) does not match expected size (%u)", total_written, content_length);
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Assets download completed, total written: %u bytes, total sectors erased: %u",
|
||||
total_written, current_sector);
|
||||
|
||||
// 重新初始化资源分区
|
||||
if (!InitializePartition()) {
|
||||
ESP_LOGE(TAG, "Failed to re-initialize assets partition");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Assets::GetAssetData(const std::string& name, void*& ptr, size_t& size) {
|
||||
auto asset = assets_.find(name);
|
||||
if (asset == assets_.end()) {
|
||||
return false;
|
||||
}
|
||||
auto data = (const char*)(mmap_root_ + asset->second.offset);
|
||||
if (data[0] != 'Z' || data[1] != 'Z') {
|
||||
ESP_LOGE(TAG, "The asset %s is not valid with magic %02x%02x", name.c_str(), data[0], data[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
ptr = static_cast<void*>(const_cast<char*>(data + 2));
|
||||
size = asset->second.size;
|
||||
return true;
|
||||
}
|
||||
65
main/assets.h
Normal file
65
main/assets.h
Normal file
@ -0,0 +1,65 @@
|
||||
#ifndef ASSETS_H
|
||||
#define ASSETS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
|
||||
#include <cJSON.h>
|
||||
#include <esp_partition.h>
|
||||
#include <model_path.h>
|
||||
|
||||
|
||||
// All combinations of wakenet_model, text_font, emoji_collection can be found from the following url:
|
||||
// https://github.com/78/xiaozhi-fonts/releases/tag/assets
|
||||
|
||||
#define ASSETS_PUHUI_COMMON_14_1 "none-font_puhui_common_14_1-none.bin"
|
||||
#define ASSETS_XIAOZHI_WAKENET "wn9_nihaoxiaozhi_tts-none-none.bin"
|
||||
#define ASSETS_XIAOZHI_WAKENET_SMALL "wn9s_nihaoxiaozhi-none-none.bin"
|
||||
#define ASSETS_XIAOZHI_PUHUI_COMMON_14_1 "wn9_nihaoxiaozhi_tts-font_puhui_common_14_1-none.bin"
|
||||
#define ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_32 "wn9_nihaoxiaozhi_tts-font_puhui_common_16_4-emojis_32.bin"
|
||||
#define ASSETS_XIAOZHI_PUHUI_COMMON_16_4_EMOJI_64 "wn9_nihaoxiaozhi_tts-font_puhui_common_16_4-emojis_64.bin"
|
||||
#define ASSETS_XIAOZHI_PUHUI_COMMON_20_4_EMOJI_64 "wn9_nihaoxiaozhi_tts-font_puhui_common_20_4-emojis_64.bin"
|
||||
#define ASSETS_XIAOZHI_PUHUI_COMMON_30_4_EMOJI_64 "wn9_nihaoxiaozhi_tts-font_puhui_common_30_4-emojis_64.bin"
|
||||
#define ASSETS_XIAOZHI_S_PUHUI_COMMON_14_1 "wn9s_nihaoxiaozhi-font_puhui_common_14_1-none.bin"
|
||||
#define ASSETS_XIAOZHI_S_PUHUI_COMMON_16_4_EMOJI_32 "wn9s_nihaoxiaozhi-font_puhui_common_16_4-emojis_32.bin"
|
||||
#define ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_32 "wn9s_nihaoxiaozhi-font_puhui_common_20_4-emojis_32.bin"
|
||||
#define ASSETS_XIAOZHI_S_PUHUI_COMMON_20_4_EMOJI_64 "wn9s_nihaoxiaozhi-font_puhui_common_20_4-emojis_64.bin"
|
||||
#define ASSETS_XIAOZHI_S_PUHUI_COMMON_30_4_EMOJI_64 "wn9s_nihaoxiaozhi-font_puhui_common_30_4-emojis_64.bin"
|
||||
|
||||
struct Asset {
|
||||
size_t size;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
class Assets {
|
||||
public:
|
||||
Assets(std::string default_assets_url);
|
||||
~Assets();
|
||||
|
||||
bool Download(std::string url, std::function<void(int progress, size_t speed)> progress_callback);
|
||||
bool Apply();
|
||||
|
||||
inline bool partition_valid() const { return partition_valid_; }
|
||||
inline bool checksum_valid() const { return checksum_valid_; }
|
||||
inline std::string default_assets_url() const { return default_assets_url_; }
|
||||
|
||||
private:
|
||||
Assets(const Assets&) = delete;
|
||||
Assets& operator=(const Assets&) = delete;
|
||||
|
||||
bool InitializePartition();
|
||||
uint32_t CalculateChecksum(const char* data, uint32_t length);
|
||||
bool GetAssetData(const std::string& name, void*& ptr, size_t& size);
|
||||
|
||||
const esp_partition_t* partition_ = nullptr;
|
||||
esp_partition_mmap_handle_t mmap_handle_ = 0;
|
||||
const char* mmap_root_ = nullptr;
|
||||
bool partition_valid_ = false;
|
||||
bool checksum_valid_ = false;
|
||||
std::string default_assets_url_;
|
||||
srmodel_list_t* models_list_ = nullptr;
|
||||
std::map<std::string, Asset> assets_;
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
main/assets/common/exclamation.ogg
Normal file
BIN
main/assets/common/exclamation.ogg
Normal file
Binary file not shown.
BIN
main/assets/common/low_battery.ogg
Normal file
BIN
main/assets/common/low_battery.ogg
Normal file
Binary file not shown.
BIN
main/assets/common/popup.ogg
Normal file
BIN
main/assets/common/popup.ogg
Normal file
Binary file not shown.
BIN
main/assets/common/success.ogg
Normal file
BIN
main/assets/common/success.ogg
Normal file
Binary file not shown.
BIN
main/assets/common/vibration.ogg
Normal file
BIN
main/assets/common/vibration.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/0.ogg
Normal file
BIN
main/assets/locales/ar-SA/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/1.ogg
Normal file
BIN
main/assets/locales/ar-SA/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/2.ogg
Normal file
BIN
main/assets/locales/ar-SA/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/3.ogg
Normal file
BIN
main/assets/locales/ar-SA/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/4.ogg
Normal file
BIN
main/assets/locales/ar-SA/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/5.ogg
Normal file
BIN
main/assets/locales/ar-SA/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/6.ogg
Normal file
BIN
main/assets/locales/ar-SA/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/7.ogg
Normal file
BIN
main/assets/locales/ar-SA/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/8.ogg
Normal file
BIN
main/assets/locales/ar-SA/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/9.ogg
Normal file
BIN
main/assets/locales/ar-SA/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/activation.ogg
Normal file
BIN
main/assets/locales/ar-SA/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/err_pin.ogg
Normal file
BIN
main/assets/locales/ar-SA/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/err_reg.ogg
Normal file
BIN
main/assets/locales/ar-SA/err_reg.ogg
Normal file
Binary file not shown.
55
main/assets/locales/ar-SA/language.json
Normal file
55
main/assets/locales/ar-SA/language.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "ar-SA"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "تحذير",
|
||||
"INFO": "معلومات",
|
||||
"ERROR": "خطأ",
|
||||
"VERSION": "الإصدار ",
|
||||
"LOADING_PROTOCOL": "الاتصال بالخادم...",
|
||||
"INITIALIZING": "التهيئة...",
|
||||
"PIN_ERROR": "يرجى إدخال بطاقة SIM",
|
||||
"REG_ERROR": "لا يمكن الوصول إلى الشبكة، يرجى التحقق من حالة بطاقة البيانات",
|
||||
"DETECTING_MODULE": "اكتشاف الوحدة...",
|
||||
"REGISTERING_NETWORK": "انتظار الشبكة...",
|
||||
"CHECKING_NEW_VERSION": "فحص الإصدار الجديد...",
|
||||
"CHECK_NEW_VERSION_FAILED": "فشل فحص الإصدار الجديد، سيتم المحاولة خلال %d ثانية: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "التبديل إلى Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "التبديل إلى 4G...",
|
||||
"STANDBY": "في الانتظار",
|
||||
"CONNECT_TO": "الاتصال بـ ",
|
||||
"CONNECTING": "جاري الاتصال...",
|
||||
"CONNECTED_TO": "متصل بـ ",
|
||||
"LISTENING": "الاستماع...",
|
||||
"SPEAKING": "التحدث...",
|
||||
"SERVER_NOT_FOUND": "البحث عن خدمة متاحة",
|
||||
"SERVER_NOT_CONNECTED": "لا يمكن الاتصال بالخدمة، يرجى المحاولة لاحقاً",
|
||||
"SERVER_TIMEOUT": "انتهت مهلة الاستجابة",
|
||||
"SERVER_ERROR": "فشل الإرسال، يرجى التحقق من الشبكة",
|
||||
"CONNECT_TO_HOTSPOT": "اتصل الهاتف بنقطة الاتصال ",
|
||||
"ACCESS_VIA_BROWSER": "،الوصول عبر المتصفح ",
|
||||
"WIFI_CONFIG_MODE": "وضع تكوين الشبكة",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "الدخول في وضع تكوين الشبكة...",
|
||||
"SCANNING_WIFI": "فحص Wi-Fi...",
|
||||
"NEW_VERSION": "إصدار جديد ",
|
||||
"OTA_UPGRADE": "تحديث OTA",
|
||||
"UPGRADING": "تحديث النظام...",
|
||||
"UPGRADE_FAILED": "فشل التحديث",
|
||||
"ACTIVATION": "تفعيل الجهاز",
|
||||
"BATTERY_LOW": "البطارية منخفضة",
|
||||
"BATTERY_CHARGING": "جاري الشحن",
|
||||
"BATTERY_FULL": "البطارية ممتلئة",
|
||||
"BATTERY_NEED_CHARGE": "البطارية منخفضة، يرجى الشحن",
|
||||
"VOLUME": "الصوت ",
|
||||
"MUTED": "صامت",
|
||||
"MAX_VOLUME": "أقصى صوت",
|
||||
"RTC_MODE_OFF": "AEC مُوقف",
|
||||
"RTC_MODE_ON": "AEC مُشغل",
|
||||
"DOWNLOAD_ASSETS_FAILED": "فشل في تنزيل الموارد",
|
||||
"LOADING_ASSETS": "جاري تحميل الموارد...",
|
||||
"PLEASE_WAIT": "يرجى الانتظار...",
|
||||
"FOUND_NEW_ASSETS": "تم العثور على موارد جديدة: %s",
|
||||
"HELLO_MY_FRIEND": "مرحباً، صديقي!"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/ar-SA/upgrade.ogg
Normal file
BIN
main/assets/locales/ar-SA/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/welcome.ogg
Normal file
BIN
main/assets/locales/ar-SA/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/ar-SA/wificonfig.ogg
Normal file
BIN
main/assets/locales/ar-SA/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/0.ogg
Normal file
BIN
main/assets/locales/cs-CZ/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/1.ogg
Normal file
BIN
main/assets/locales/cs-CZ/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/2.ogg
Normal file
BIN
main/assets/locales/cs-CZ/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/3.ogg
Normal file
BIN
main/assets/locales/cs-CZ/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/4.ogg
Normal file
BIN
main/assets/locales/cs-CZ/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/5.ogg
Normal file
BIN
main/assets/locales/cs-CZ/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/6.ogg
Normal file
BIN
main/assets/locales/cs-CZ/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/7.ogg
Normal file
BIN
main/assets/locales/cs-CZ/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/8.ogg
Normal file
BIN
main/assets/locales/cs-CZ/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/9.ogg
Normal file
BIN
main/assets/locales/cs-CZ/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/activation.ogg
Normal file
BIN
main/assets/locales/cs-CZ/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/err_pin.ogg
Normal file
BIN
main/assets/locales/cs-CZ/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/err_reg.ogg
Normal file
BIN
main/assets/locales/cs-CZ/err_reg.ogg
Normal file
Binary file not shown.
55
main/assets/locales/cs-CZ/language.json
Normal file
55
main/assets/locales/cs-CZ/language.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "cs-CZ"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Varování",
|
||||
"INFO": "Informace",
|
||||
"ERROR": "Chyba",
|
||||
"VERSION": "Verze ",
|
||||
"LOADING_PROTOCOL": "Připojování k serveru...",
|
||||
"INITIALIZING": "Inicializace...",
|
||||
"PIN_ERROR": "Prosím vložte SIM kartu",
|
||||
"REG_ERROR": "Nelze se připojit k síti, zkontrolujte stav datové karty",
|
||||
"DETECTING_MODULE": "Detekce modulu...",
|
||||
"REGISTERING_NETWORK": "Čekání na síť...",
|
||||
"CHECKING_NEW_VERSION": "Kontrola nové verze...",
|
||||
"CHECK_NEW_VERSION_FAILED": "Kontrola nové verze selhala, opakování za %d sekund: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Přepínání na Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "Přepínání na 4G...",
|
||||
"STANDBY": "Pohotovost",
|
||||
"CONNECT_TO": "Připojit k ",
|
||||
"CONNECTING": "Připojování...",
|
||||
"CONNECTED_TO": "Připojeno k ",
|
||||
"LISTENING": "Naslouchání...",
|
||||
"SPEAKING": "Mluvení...",
|
||||
"SERVER_NOT_FOUND": "Hledání dostupné služby",
|
||||
"SERVER_NOT_CONNECTED": "Nelze se připojit ke službě, zkuste to později",
|
||||
"SERVER_TIMEOUT": "Čas odpovědi vypršel",
|
||||
"SERVER_ERROR": "Odeslání selhalo, zkontrolujte síť",
|
||||
"CONNECT_TO_HOTSPOT": "Připojte telefon k hotspotu ",
|
||||
"ACCESS_VIA_BROWSER": ",přístup přes prohlížeč ",
|
||||
"WIFI_CONFIG_MODE": "Režim konfigurace sítě",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Vstup do režimu konfigurace sítě...",
|
||||
"SCANNING_WIFI": "Skenování Wi-Fi...",
|
||||
"NEW_VERSION": "Nová verze ",
|
||||
"OTA_UPGRADE": "OTA upgrade",
|
||||
"UPGRADING": "Aktualizace systému...",
|
||||
"UPGRADE_FAILED": "Upgrade selhal",
|
||||
"ACTIVATION": "Aktivace zařízení",
|
||||
"BATTERY_LOW": "Slabá baterie",
|
||||
"BATTERY_CHARGING": "Nabíjení",
|
||||
"BATTERY_FULL": "Baterie plná",
|
||||
"BATTERY_NEED_CHARGE": "Slabá baterie, prosím nabijte",
|
||||
"VOLUME": "Hlasitost ",
|
||||
"MUTED": "Ztlumeno",
|
||||
"MAX_VOLUME": "Maximální hlasitost",
|
||||
"RTC_MODE_OFF": "AEC vypnuto",
|
||||
"RTC_MODE_ON": "AEC zapnuto",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Nepodařilo se stáhnout prostředky",
|
||||
"LOADING_ASSETS": "Načítání prostředků...",
|
||||
"PLEASE_WAIT": "Prosím čekejte...",
|
||||
"FOUND_NEW_ASSETS": "Nalezeny nové prostředky: %s",
|
||||
"HELLO_MY_FRIEND": "Ahoj, můj příteli!"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/cs-CZ/upgrade.ogg
Normal file
BIN
main/assets/locales/cs-CZ/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/welcome.ogg
Normal file
BIN
main/assets/locales/cs-CZ/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/cs-CZ/wificonfig.ogg
Normal file
BIN
main/assets/locales/cs-CZ/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/0.ogg
Normal file
BIN
main/assets/locales/de-DE/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/1.ogg
Normal file
BIN
main/assets/locales/de-DE/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/2.ogg
Normal file
BIN
main/assets/locales/de-DE/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/3.ogg
Normal file
BIN
main/assets/locales/de-DE/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/4.ogg
Normal file
BIN
main/assets/locales/de-DE/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/5.ogg
Normal file
BIN
main/assets/locales/de-DE/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/6.ogg
Normal file
BIN
main/assets/locales/de-DE/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/7.ogg
Normal file
BIN
main/assets/locales/de-DE/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/8.ogg
Normal file
BIN
main/assets/locales/de-DE/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/9.ogg
Normal file
BIN
main/assets/locales/de-DE/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/activation.ogg
Normal file
BIN
main/assets/locales/de-DE/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/err_pin.ogg
Normal file
BIN
main/assets/locales/de-DE/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/err_reg.ogg
Normal file
BIN
main/assets/locales/de-DE/err_reg.ogg
Normal file
Binary file not shown.
55
main/assets/locales/de-DE/language.json
Normal file
55
main/assets/locales/de-DE/language.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "de-DE"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Warnung",
|
||||
"INFO": "Information",
|
||||
"ERROR": "Fehler",
|
||||
"VERSION": "Version ",
|
||||
"LOADING_PROTOCOL": "Verbindung zum Server...",
|
||||
"INITIALIZING": "Initialisierung...",
|
||||
"PIN_ERROR": "Bitte SIM-Karte einlegen",
|
||||
"REG_ERROR": "Netzwerkverbindung fehlgeschlagen, bitte Datenkartenstatus prüfen",
|
||||
"DETECTING_MODULE": "Modul erkennen...",
|
||||
"REGISTERING_NETWORK": "Auf Netzwerk warten...",
|
||||
"CHECKING_NEW_VERSION": "Neue Version prüfen...",
|
||||
"CHECK_NEW_VERSION_FAILED": "Neue Version prüfen fehlgeschlagen, Wiederholung in %d Sekunden: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Zu Wi-Fi wechseln...",
|
||||
"SWITCH_TO_4G_NETWORK": "Zu 4G wechseln...",
|
||||
"STANDBY": "Bereitschaft",
|
||||
"CONNECT_TO": "Verbinden zu ",
|
||||
"CONNECTING": "Verbindung wird hergestellt...",
|
||||
"CONNECTED_TO": "Verbunden mit ",
|
||||
"LISTENING": "Zuhören...",
|
||||
"SPEAKING": "Sprechen...",
|
||||
"SERVER_NOT_FOUND": "Verfügbaren Service suchen",
|
||||
"SERVER_NOT_CONNECTED": "Service-Verbindung fehlgeschlagen, bitte später versuchen",
|
||||
"SERVER_TIMEOUT": "Antwort-Timeout",
|
||||
"SERVER_ERROR": "Senden fehlgeschlagen, bitte Netzwerk prüfen",
|
||||
"CONNECT_TO_HOTSPOT": "Handy mit Hotspot verbinden ",
|
||||
"ACCESS_VIA_BROWSER": ",Browser öffnen ",
|
||||
"WIFI_CONFIG_MODE": "Netzwerkkonfigurationsmodus",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Netzwerkkonfigurationsmodus eingeben...",
|
||||
"SCANNING_WIFI": "Wi-Fi scannen...",
|
||||
"NEW_VERSION": "Neue Version ",
|
||||
"OTA_UPGRADE": "OTA-Upgrade",
|
||||
"UPGRADING": "System wird aktualisiert...",
|
||||
"UPGRADE_FAILED": "Upgrade fehlgeschlagen",
|
||||
"ACTIVATION": "Gerät aktivieren",
|
||||
"BATTERY_LOW": "Niedriger Batteriestand",
|
||||
"BATTERY_CHARGING": "Wird geladen",
|
||||
"BATTERY_FULL": "Batterie voll",
|
||||
"BATTERY_NEED_CHARGE": "Niedriger Batteriestand, bitte aufladen",
|
||||
"VOLUME": "Lautstärke ",
|
||||
"MUTED": "Stummgeschaltet",
|
||||
"MAX_VOLUME": "Maximale Lautstärke",
|
||||
"RTC_MODE_OFF": "AEC aus",
|
||||
"RTC_MODE_ON": "AEC ein",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Fehler beim Herunterladen der Ressourcen",
|
||||
"LOADING_ASSETS": "Ressourcen werden geladen...",
|
||||
"PLEASE_WAIT": "Bitte warten...",
|
||||
"FOUND_NEW_ASSETS": "Neue Ressourcen gefunden: %s",
|
||||
"HELLO_MY_FRIEND": "Hallo, mein Freund!"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/de-DE/upgrade.ogg
Normal file
BIN
main/assets/locales/de-DE/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/welcome.ogg
Normal file
BIN
main/assets/locales/de-DE/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/de-DE/wificonfig.ogg
Normal file
BIN
main/assets/locales/de-DE/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/0.ogg
Normal file
BIN
main/assets/locales/en-US/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/1.ogg
Normal file
BIN
main/assets/locales/en-US/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/2.ogg
Normal file
BIN
main/assets/locales/en-US/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/3.ogg
Normal file
BIN
main/assets/locales/en-US/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/4.ogg
Normal file
BIN
main/assets/locales/en-US/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/5.ogg
Normal file
BIN
main/assets/locales/en-US/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/6.ogg
Normal file
BIN
main/assets/locales/en-US/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/7.ogg
Normal file
BIN
main/assets/locales/en-US/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/8.ogg
Normal file
BIN
main/assets/locales/en-US/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/9.ogg
Normal file
BIN
main/assets/locales/en-US/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/activation.ogg
Normal file
BIN
main/assets/locales/en-US/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/err_pin.ogg
Normal file
BIN
main/assets/locales/en-US/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/err_reg.ogg
Normal file
BIN
main/assets/locales/en-US/err_reg.ogg
Normal file
Binary file not shown.
56
main/assets/locales/en-US/language.json
Normal file
56
main/assets/locales/en-US/language.json
Normal file
@ -0,0 +1,56 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "en-US"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Warning",
|
||||
"INFO": "Information",
|
||||
"ERROR": "Error",
|
||||
"VERSION": "Ver ",
|
||||
"LOADING_PROTOCOL": "Logging in...",
|
||||
"INITIALIZING": "Initializing...",
|
||||
"PIN_ERROR": "Please insert SIM card",
|
||||
"REG_ERROR": "Unable to access network, please check SIM card status",
|
||||
"DETECTING_MODULE": "Detecting module...",
|
||||
"REGISTERING_NETWORK": "Waiting for network...",
|
||||
"CHECKING_NEW_VERSION": "Checking for new version...",
|
||||
"CHECK_NEW_VERSION_FAILED": "Check for new version failed, will retry in %d seconds: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Switching to Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "Switching to 4G...",
|
||||
"STANDBY": "Standby",
|
||||
"CONNECT_TO": "Connect to ",
|
||||
"CONNECTING": "Connecting...",
|
||||
"CONNECTION_SUCCESSFUL": "Connection Successful",
|
||||
"CONNECTED_TO": "Connected to ",
|
||||
"LISTENING": "Listening...",
|
||||
"SPEAKING": "Speaking...",
|
||||
"SERVER_NOT_FOUND": "Looking for available service",
|
||||
"SERVER_NOT_CONNECTED": "Unable to connect to service, please try again later",
|
||||
"SERVER_TIMEOUT": "Waiting for response timeout",
|
||||
"SERVER_ERROR": "Sending failed, please check the network",
|
||||
"CONNECT_TO_HOTSPOT": "Hotspot: ",
|
||||
"ACCESS_VIA_BROWSER": " Config URL: ",
|
||||
"WIFI_CONFIG_MODE": "Wi-Fi Configuration Mode",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Entering Wi-Fi configuration mode...",
|
||||
"SCANNING_WIFI": "Scanning Wi-Fi...",
|
||||
"NEW_VERSION": "New version ",
|
||||
"OTA_UPGRADE": "OTA Upgrade",
|
||||
"UPGRADING": "System is upgrading...",
|
||||
"UPGRADE_FAILED": "Upgrade failed",
|
||||
"ACTIVATION": "Activation",
|
||||
"BATTERY_LOW": "Low battery",
|
||||
"BATTERY_CHARGING": "Charging",
|
||||
"BATTERY_FULL": "Battery full",
|
||||
"BATTERY_NEED_CHARGE": "Low battery, please charge",
|
||||
"VOLUME": "Volume ",
|
||||
"MUTED": "Muted",
|
||||
"MAX_VOLUME": "Max volume",
|
||||
"RTC_MODE_OFF": "AEC Off",
|
||||
"RTC_MODE_ON": "AEC On",
|
||||
"PLEASE_WAIT": "Please wait...",
|
||||
"FOUND_NEW_ASSETS": "Found new assets: %s",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Failed to download assets",
|
||||
"LOADING_ASSETS": "Loading assets...",
|
||||
"HELLO_MY_FRIEND": "Hello, my friend!"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/en-US/upgrade.ogg
Normal file
BIN
main/assets/locales/en-US/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/welcome.ogg
Normal file
BIN
main/assets/locales/en-US/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/en-US/wificonfig.ogg
Normal file
BIN
main/assets/locales/en-US/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/0.ogg
Normal file
BIN
main/assets/locales/es-ES/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/1.ogg
Normal file
BIN
main/assets/locales/es-ES/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/2.ogg
Normal file
BIN
main/assets/locales/es-ES/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/3.ogg
Normal file
BIN
main/assets/locales/es-ES/3.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/4.ogg
Normal file
BIN
main/assets/locales/es-ES/4.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/5.ogg
Normal file
BIN
main/assets/locales/es-ES/5.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/6.ogg
Normal file
BIN
main/assets/locales/es-ES/6.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/7.ogg
Normal file
BIN
main/assets/locales/es-ES/7.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/8.ogg
Normal file
BIN
main/assets/locales/es-ES/8.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/9.ogg
Normal file
BIN
main/assets/locales/es-ES/9.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/activation.ogg
Normal file
BIN
main/assets/locales/es-ES/activation.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/err_pin.ogg
Normal file
BIN
main/assets/locales/es-ES/err_pin.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/err_reg.ogg
Normal file
BIN
main/assets/locales/es-ES/err_reg.ogg
Normal file
Binary file not shown.
55
main/assets/locales/es-ES/language.json
Normal file
55
main/assets/locales/es-ES/language.json
Normal file
@ -0,0 +1,55 @@
|
||||
{
|
||||
"language": {
|
||||
"type": "es-ES"
|
||||
},
|
||||
"strings": {
|
||||
"WARNING": "Advertencia",
|
||||
"INFO": "Información",
|
||||
"ERROR": "Error",
|
||||
"VERSION": "Versión ",
|
||||
"LOADING_PROTOCOL": "Conectando al servidor...",
|
||||
"INITIALIZING": "Inicializando...",
|
||||
"PIN_ERROR": "Por favor inserte la tarjeta SIM",
|
||||
"REG_ERROR": "No se puede acceder a la red, verifique el estado de la tarjeta de datos",
|
||||
"DETECTING_MODULE": "Detectando módulo...",
|
||||
"REGISTERING_NETWORK": "Esperando red...",
|
||||
"CHECKING_NEW_VERSION": "Verificando nueva versión...",
|
||||
"CHECK_NEW_VERSION_FAILED": "Error al verificar nueva versión, reintentando en %d segundos: %s",
|
||||
"SWITCH_TO_WIFI_NETWORK": "Cambiando a Wi-Fi...",
|
||||
"SWITCH_TO_4G_NETWORK": "Cambiando a 4G...",
|
||||
"STANDBY": "En espera",
|
||||
"CONNECT_TO": "Conectar a ",
|
||||
"CONNECTING": "Conectando...",
|
||||
"CONNECTED_TO": "Conectado a ",
|
||||
"LISTENING": "Escuchando...",
|
||||
"SPEAKING": "Hablando...",
|
||||
"SERVER_NOT_FOUND": "Buscando servicio disponible",
|
||||
"SERVER_NOT_CONNECTED": "No se puede conectar al servicio, inténtelo más tarde",
|
||||
"SERVER_TIMEOUT": "Tiempo de espera agotado",
|
||||
"SERVER_ERROR": "Error de envío, verifique la red",
|
||||
"CONNECT_TO_HOTSPOT": "Conectar teléfono al punto de acceso ",
|
||||
"ACCESS_VIA_BROWSER": ",acceder mediante navegador ",
|
||||
"WIFI_CONFIG_MODE": "Modo configuración de red",
|
||||
"ENTERING_WIFI_CONFIG_MODE": "Entrando en modo configuración de red...",
|
||||
"SCANNING_WIFI": "Escaneando Wi-Fi...",
|
||||
"NEW_VERSION": "Nueva versión ",
|
||||
"OTA_UPGRADE": "Actualización OTA",
|
||||
"UPGRADING": "Actualizando sistema...",
|
||||
"UPGRADE_FAILED": "Actualización fallida",
|
||||
"ACTIVATION": "Activación del dispositivo",
|
||||
"BATTERY_LOW": "Batería baja",
|
||||
"BATTERY_CHARGING": "Cargando",
|
||||
"BATTERY_FULL": "Batería llena",
|
||||
"BATTERY_NEED_CHARGE": "Batería baja, por favor cargar",
|
||||
"VOLUME": "Volumen ",
|
||||
"MUTED": "Silenciado",
|
||||
"MAX_VOLUME": "Volumen máximo",
|
||||
"RTC_MODE_OFF": "AEC desactivado",
|
||||
"RTC_MODE_ON": "AEC activado",
|
||||
"DOWNLOAD_ASSETS_FAILED": "Error al descargar recursos",
|
||||
"LOADING_ASSETS": "Cargando recursos...",
|
||||
"PLEASE_WAIT": "Por favor espere...",
|
||||
"FOUND_NEW_ASSETS": "Encontrados nuevos recursos: %s",
|
||||
"HELLO_MY_FRIEND": "¡Hola, mi amigo!"
|
||||
}
|
||||
}
|
||||
BIN
main/assets/locales/es-ES/upgrade.ogg
Normal file
BIN
main/assets/locales/es-ES/upgrade.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/welcome.ogg
Normal file
BIN
main/assets/locales/es-ES/welcome.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/es-ES/wificonfig.ogg
Normal file
BIN
main/assets/locales/es-ES/wificonfig.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fi-FI/0.ogg
Normal file
BIN
main/assets/locales/fi-FI/0.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fi-FI/1.ogg
Normal file
BIN
main/assets/locales/fi-FI/1.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fi-FI/2.ogg
Normal file
BIN
main/assets/locales/fi-FI/2.ogg
Normal file
Binary file not shown.
BIN
main/assets/locales/fi-FI/3.ogg
Normal file
BIN
main/assets/locales/fi-FI/3.ogg
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user